Skip to content

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
DimmKirr merged 1 commit into
mainfrom
feature/wip
May 5, 2026

Conversation

@DimmKirr

@DimmKirr DimmKirr commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Changes

  • 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

…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
@DimmKirr
DimmKirr merged commit 1b1851d into main May 5, 2026
1 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant