Repository navigation
cell serve gains OpenAI Responses API + SSE streaming, configurable system prompts across flags/env/toml, and per-stack user-image tagging that ends per-session image sprawl - #36
Merged
Conversation
…ystem prompts across flags/env/toml, and per-stack user-image tagging that ends per-session image sprawl - feat(serve): add `POST /v1/responses` (OpenAI Responses API) — n8n "Message a Model", OpenAI Agents SDK and other newer clients can now target cell serve directly - feat(serve): stream `/v1/chat/completions` and `/v1/responses` over SSE for the claude agent — incremental token deltas, 15s `:keepalive` heartbeats so long agentic turns survive proxy idle timeouts; opencode falls back to buffered - feat(serve): add `--system-prompt` / `--system-prompt-file` flags, `DEVCELL_SYSTEM_PROMPT` / `DEVCELL_SYSTEM_PROMPT_FILE` env vars, and `[llm].system_prompt_file` TOML key — operators can pin a baseline prompt that composes with per-request `instructions`/`system` instead of overriding it - feat(serve): expose `GET /v1/models`, `GET /healthz`, `GET /api/openapi.json`, `GET /swagger/` UI — clients can discover available models and the API is browsable - feat(serve): honor OpenAI `reasoning_effort` / `reasoning.effort` (`low|medium|high`) → `claude --effort` per request; non-spec values silently dropped - feat(serve): parse claude `--output-format=json` envelope into per-response token + cost telemetry (input/output/cache tokens, total_cost_usd) and surface it in OpenAI `usage` shape - feat(serve): opt-in `DEVCELL_LOG_PROMPTS=1` logs full prompt + reply at INFO; off by default since prompts often carry secrets / PII - feat(serve): reuse a fixed `DEVCELL_API_KEY` when set instead of always generating, and stop printing the key on startup unless it was generated — deployments no longer leak the key into stderr/logs - feat(serve): claude is now invoked with `--dangerously-skip-permissions` so tool calls don't block on a TTY-less permission gate; the bearer API key is the auth boundary - feat(runner): default user-image tag is now `devcell-user:<stack>[-<modules>-<sha8>]` instead of `devcell-user:<session>` — one image per stack/module-set instead of one per tmux session, eliminating ~13 GB-per-session image sprawl - feat(cfg): add `[cell].per_session_image` toml key + `DEVCELL_PER_SESSION_IMAGE` env to opt back into the legacy per-session tagging - feat(runner): `DEVCELL_DOCKER_BUILD_ARGS="KEY=VAL ..."` injects `--build-arg` pairs into image builds — lets users override Dockerfile ARGs without forking - fix(op): `ResolveItems` now collects per-item errors and continues instead of aborting on the first failure — a single missing/locked 1Password item no longer blocks the whole agent launch - fix(config): clamp generated VNC/RDP ports above 65535 back into the valid TCP range — projects with high port prefixes no longer fail to bind - fix(logger): server mode renders plain ASCII logs with timestamps and no ANSI colors — log aggregators (CloudWatch, journald) no longer see escape codes - feat(nixhome/mcp): add `enabled` attribute on MCP server entries — variants can be registered in nix without being staged into Claude/OpenCode/Codex configs (used by new `notion-oauth` opt-in) - feat(nixhome/infra): add `notion-api` local stdio MCP (npx-wrapped @notionhq/notion-mcp-server) using `NOTION_API_KEY` — non-interactive, works for headless agents; `notion-oauth` remote variant kept as opt-in - feat(nixhome/project-management): add `n8n` MCP server (czlonkowski/n8n-mcp) for workflow-automation control via `N8N_API_URL` / `N8N_API_KEY` - feat(nixhome/security): add ghidra, radare2, rizin, binwalk, yara, upx, pev, detect-it-easy, capstone, ropper, foremost, sleuthkit — full PE/ELF/Mach-O reverse-engineering and forensics toolkit available in the security stack - feat(nixhome/base): add 7zz, p7zip, tinyxxd, hexedit — broader archive and hex-editing coverage in every stack - feat(nixhome/go): add go-swag — `swag init` available for generating OpenAPI specs - chore(build): pin `docker buildx bake` output to gzip and disable provenance/sbom attestations — older Docker daemons and registries that choke on zstd or OCI provenance can now pull images - chore(build): regenerate Swagger docs in goreleaser `before:hooks`, `task cell:build`, and the Dockerfile builder stage so `/swagger/` is always in sync with annotations - refactor(runner): split `BuildSystemPrompt` into `ContainerContext` (auto-generated mounts/paths/constraints) + `ResolveSystemPrompt` (7-tier source chain) + `AssembleSystemPrompt` (concatenator) — both `cell claude` and `cell serve` now share the same prompt-resolution logic - refactor(serve): `Executor.Run` now takes an `ExecOpts` struct instead of positional args — no user-facing impact - refactor(serve): trim trailing newlines from agent stdout before placing into `output_text` / `message.content` — clients no longer see a stray `\n` at the end of every reply - chore(deps): add swaggo/swag + http-swagger, promote charmbracelet/bubbles+bubbletea to direct deps, drop go-md2man/blackfriday indirects — no user-facing impact - test(serve): add full coverage for responses, sse_chat, sse_responses, claude_json, claude_stream, exec, exec_stream, plus expanded handler/server/openai compat tests - test(runner): expanded systemprompt tests covering all seven resolution tiers, mutual-exclusion errors, and file-relative path handling - test(cfg): add tests for `per_session_image` resolution and TOML round-trip
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
POST /v1/responses(OpenAI Responses API) — n8n "Message a Model", OpenAI Agents SDK and other newer clients can now target cell serve directly/v1/chat/completionsand/v1/responsesover SSE for the claude agent — incremental token deltas, 15s:keepaliveheartbeats so long agentic turns survive proxy idle timeouts; opencode falls back to buffered--system-prompt/--system-prompt-fileflags,DEVCELL_SYSTEM_PROMPT/DEVCELL_SYSTEM_PROMPT_FILEenv vars, and[llm].system_prompt_fileTOML key — operators can pin a baseline prompt that composes with per-requestinstructions/systeminstead of overriding itGET /v1/models,GET /healthz,GET /api/openapi.json,GET /swagger/UI — clients can discover available models and the API is browsablereasoning_effort/reasoning.effort(low|medium|high) →claude --effortper request; non-spec values silently dropped--output-format=jsonenvelope into per-response token + cost telemetry (input/output/cache tokens, total_cost_usd) and surface it in OpenAIusageshapeDEVCELL_LOG_PROMPTS=1logs full prompt + reply at INFO; off by default since prompts often carry secrets / PIIDEVCELL_API_KEYwhen set instead of always generating, and stop printing the key on startup unless it was generated — deployments no longer leak the key into stderr/logs--dangerously-skip-permissionsso tool calls don't block on a TTY-less permission gate; the bearer API key is the auth boundarydevcell-user:<stack>[-<modules>-<sha8>]instead ofdevcell-user:<session>— one image per stack/module-set instead of one per tmux session, eliminating ~13 GB-per-session image sprawl[cell].per_session_imagetoml key +DEVCELL_PER_SESSION_IMAGEenv to opt back into the legacy per-session taggingDEVCELL_DOCKER_BUILD_ARGS="KEY=VAL ..."injects--build-argpairs into image builds — lets users override Dockerfile ARGs without forkingResolveItemsnow collects per-item errors and continues instead of aborting on the first failure — a single missing/locked 1Password item no longer blocks the whole agent launchenabledattribute on MCP server entries — variants can be registered in nix without being staged into Claude/OpenCode/Codex configs (used by newnotion-oauthopt-in)notion-apilocal stdio MCP (npx-wrapped @notionhq/notion-mcp-server) usingNOTION_API_KEY— non-interactive, works for headless agents;notion-oauthremote variant kept as opt-inn8nMCP server (czlonkowski/n8n-mcp) for workflow-automation control viaN8N_API_URL/N8N_API_KEYswag initavailable for generating OpenAPI specsdocker buildx bakeoutput to gzip and disable provenance/sbom attestations — older Docker daemons and registries that choke on zstd or OCI provenance can now pull imagesbefore:hooks,task cell:build, and the Dockerfile builder stage so/swagger/is always in sync with annotationsBuildSystemPromptintoContainerContext(auto-generated mounts/paths/constraints) +ResolveSystemPrompt(7-tier source chain) +AssembleSystemPrompt(concatenator) — bothcell claudeandcell servenow share the same prompt-resolution logicExecutor.Runnow takes anExecOptsstruct instead of positional args — no user-facing impactoutput_text/message.content— clients no longer see a stray\nat the end of every replyper_session_imageresolution and TOML round-trip