Skip to content

feat(agents): add opencode support - #315

Draft
defangdevs wants to merge 2 commits into
masterfrom
feat/80-opencode-support
Draft

feat(agents): add opencode support#315
defangdevs wants to merge 2 commits into
masterfrom
feat/80-opencode-support

Conversation

@defangdevs

Copy link
Copy Markdown
Owner

Summary

Adds opencode (pkgs.opencode, MIT — no unfree allowance needed) as a
third supported agent CLI alongside claude and codex. Closes #80.

  • supportedAgents, agentPackage, option docs/enums: opencode joins the
    claude/codex set everywhere it's data-driven (installAgents, the
    settings page's session UI, agent-box-session, AWS Agent parameter).
  • Resume identity (the interesting part, since opencode has no
    --session-id to mint up front, same problem codex has): stamp
    [agent-box session <bid>] into the kickoff prompt, then find it again
    on respawn. Codex greps its per-session rollout files for the marker;
    opencode keeps every session (across every session name and working
    directory) in ONE shared SQLite database, so the lookup goes through
    opencode's own db query subcommand instead — no new sqlite dependency.
    Verified live against opencode 1.18.18, fully offline with no provider
    configured: the TUI writes the kickoff prompt into that database as soon
    as it starts, well before it would ever reach a model — which is also
    what makes tests/sessions.nix's new subtest able to exercise this
    against the real binary instead of a stub.
  • remoteControl is deliberately ignored for opencode (MVP, matches the
    plan from Add opencode support #80's feasibility comment): no vendor pairing app exists yet,
    so an opencode session is reachable only through the browser terminal or
    a local tmux attach. opencode serve/web behind the box's own Caddy
    front end could stand in for it later — a separate product decision.
  • Settings-page transcript download is scoped out, filed separately as
    settings page: opencode transcript download #314: transcript_of assumes one file per session (claude's .jsonl,
    codex's per-rollout file), and opencode's shared-database store doesn't
    fit that shape without an on-demand export step. settings-daemon.py's
    comments point at settings page: opencode transcript download #314 instead of promising it here.

Test plan

  • python3 bin/assemble-module.pymodules/agent-box.nix regenerated
  • nix build .#checks.aarch64-linux.{module-generated-up-to-date,module-single-file,assemble-module-escaping,golden-snapshot,multi-user,download-route,webhook-route} — all green
  • nix run .#update-golden — reviewed the diff (opencode joining AGENT_BOX_AGENT_BINS/PATH, the two source comments it touches) and committed it
  • nix eval .#checks.x86_64-linux.*.drvPath for every x86-only VM test (this box is aarch64, can't build/run them) — all evaluate cleanly, no Nix errors
  • ~/bin/check-testscript.sh tests/sessions.nix (the driver's own ty/ruff gates) — clean
  • cfn-lint aws/template.yaml — clean, same as master
  • shellcheck modules/src/supervisor.sh — no new warnings from the added function/case branch
  • New tests/sessions.nix subtests added: opencode binary installed, agent-box-session add --agent opencode, AGENTS.md seeding, and the kickoff-prompt-marker / resume-by-session-id round trip against the real opencode binary (not evaluatable on this aarch64 box beyond eval-check — needs a maintainer's x86 CI run)

🤖 Generated with Claude Code

https://claude.ai/code/session_01AMbiL3ux2XbUTrGQqP15U1

Adds opencode (pkgs.opencode, MIT — no unfree allowance needed) as a third
supported agent CLI alongside claude and codex.

Resume identity works like codex's: since opencode has no --session-id
equivalent, the kickoff prompt is stamped with a "[agent-box session <bid>]"
marker and a respawn looks it up again. Unlike codex's per-session rollout
files, every opencode session lives in one shared SQLite database, so the
lookup goes through opencode's own `db` query subcommand instead of a grep
(verified live against opencode 1.18.18, fully offline, no provider
configured — the TUI writes the kickoff prompt into that database before it
would ever reach a model).

remoteControl is deliberately ignored for opencode (MVP): it has no vendor
pairing app, so sessions are reachable only through the browser terminal or
a local tmux attach.

Settings-page transcript download is scoped out and filed separately as
#314: opencode's shared-database session store doesn't fit the
one-file-per-session model every other transcript_of branch assumes.

tests/sessions.nix exercises the new agent against the real opencode
binary (no stub) — AGENTS.md seeding, session add/rm, and the kickoff/
resume marker round-trip. tests/golden updated via `nix run .#update-golden`
for the new agent showing up in AGENT_BOX_AGENT_BINS/PATH and the two
source-file comments it touches.

Closes #80.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMbiL3ux2XbUTrGQqP15U1
CI (run 32513310738) showed the resume path working correctly — it found
the stamped session and passed --session ses_... — but the test's own
assertion was too broad: it checked "agent-box session" not in the resumed
command, and the default resume steer prompt's own wording ("...restarted
(agent-box session <bid>)...") legitimately contains that bare phrase
without brackets. Only the bracketed "[agent-box session <bid>]" MARKER
should be absent on a successful resume; check for that specifically.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AMbiL3ux2XbUTrGQqP15U1
@defangdevs

Copy link
Copy Markdown
Owner Author

Heads-up from #317, which just merged: master's modules/agent-box.nix, tests/golden/, .github/workflows/ci.yml and flake.nix all moved, so this branch will want a rebase plus nix run .#assemble and nix run .#update-golden. The sources will not conflict; the generated files will.

Relevant to opencode specifically: the settings page now has guided sign-in cards driven by a table in the settings daemon (CONNECT_DEFS), and the module hands it AGENT_BOX_CONNECT_BINS built by mapping over installAgents — so an opencode box will pass opencode=<binary> and the daemon will ignore it (no CONNECT_DEFS row, so no card, no error). Giving opencode a card is one table row plus a status parser: it needs the sign-in command, the host(s) its URL lives on, whether it prints a code in the pane or takes one back, and a command that reports whether it is signed in. tests/connect.nix stubs the CLIs, so a new row costs a stub, not a network.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Backlog

Development

Successfully merging this pull request may close these issues.

Add opencode support

2 participants