Skip to content

feat(opencode): add OpenCode v2 actor integration - #5740

Draft
NathanFlurry wants to merge 1 commit into
pi-headlessfrom
opencode-headless
Draft

NathanFlurry wants to merge 1 commit into
pi-headlessfrom
opencode-headless

Conversation

@NathanFlurry

Copy link
Copy Markdown
Member
  • Embed OpenCode v2 in Rivet Actors with SQLite sessions, durable events, and interrupted-generation recovery.
  • Expose native actions and Pi-style helpers with optional shared sandbox adapters and custom actions and plugins.
  • Add integration documentation, release checks, and SQLite, Docker, and generation-recovery tests.
  • Stack on the Pi integration for the shared sandbox adapter.

@railway-app

railway-app Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

🚅 Deployed to the actors-pr-5740 environment in rivet-frontend

Service Status Web Updated
frontend-cloud 😴 Sleeping (View Logs) Web Sep 16, 2026 at 8:33 am UTC
frontend-inspector 😴 Sleeping (View Logs) Web Sep 16, 2026 at 8:32 am UTC
kitchen-sink 😴 Sleeping (View Logs) Web Sep 16, 2026 at 8:32 am UTC
ladle ✅ Success (View Logs) Web Sep 16, 2026 at 8:24 am UTC
mcp-hub ✅ Success (View Logs) Web Sep 16, 2026 at 8:22 am UTC
website ❌ Build Failed (View Logs) Web Sep 16, 2026 at 8:21 am UTC

@claude

claude Bot commented Sep 16, 2026

Copy link
Copy Markdown
Contributor

Review: OpenCode v2 actor integration

Went through integrations/opencode/src/*, the test suite, and the docs page. Overall this is a well-built integration: no vi.mock, real SQLite (node:sqlite) and real Docker/subprocess tests, careful SessionRestart deferral to sequence recovery after the event subscription is wired up, and cleanup paths (dispose) that always run through finally. Nice work.

Findings

1. Docs page inlines TypeScript instead of using <CodeSnippet> (docs/content/integrations/opencode.mdx)

docs/CLAUDE.md is explicit: "Never inline a fenced TypeScript block. Real examples live in examples/ and are embedded with <CodeSnippet>, so they are type-checked and cannot rot. A snippet that fails to compile fails the website build."

opencode.mdx has four inline ```ts blocks (lines ~21, ~49, ~67, ~109) instead of <CodeSnippet file="examples/docs/integrations-opencode/..." />. This is the only integration doc in this batch with no justification for it — compare with:

  • pi.mdx (the integration this PR stacks on and mirrors) uses <CodeSnippet file="examples/docs/integrations-pi/..."> throughout, and examples/docs/integrations-pi/ exists.
  • flue.mdx / vercel-eve.mdx also inline TS, but each carries an explicit comment justifying the exception ("intentionally hardcodes... importing snippets across repositories would add an agentOS dependency"). opencode.mdx has no such comment, and no cross-repo constraint applies here since integrations/opencode lives in this repo.

There's no examples/docs/integrations-opencode/ directory in this PR. Worth adding one and switching to <CodeSnippet> so these examples are type-checked against the actual @rivet-dev/opencode package, same as pi.mdx.

Minor / non-blocking observations

  • integrations/opencode/src/sandbox.ts: sandboxEnvironment's shell-mode spawn only quotes command.args, not command.command itself, when building the -c script ([command.command, ...command.args.map(quote)].join(" ")). That matches how it's exercised in docker.test.ts (a single pre-built shell string with empty args), but if a caller ever passes both a command.command containing shell metacharacters and non-empty args expecting positional interpolation, only the args get escaped. Given the trust model in CLAUDE.md (a Rivet Actor's sandbox is trusted, application-local, not an adversarial boundary) this is likely fine as-is, just flagging the asymmetry in case it's surprising later.
  • integrations/opencode/package.json pins @opencode/* to an exact 0.0.0-dev-19487 prerelease tag. That's presumably intentional given the <Info> callout ("pinned preview of OpenCode v2"), just noting it so the pin gets revisited once OpenCode v2 has a stable release line.

Testing

Test coverage looks strong: SQLite migration/commit/rollback (sqlite.test.ts), sandbox process lifecycle including truncated-output and cancellation (sandbox.test.ts), a real Docker-backed sandbox test gated behind OPENCODE_DOCKER_TESTS=1 (docker.test.ts) that also verifies host env vars are stripped from sandboxed spawns, and a generation/recovery test that simulates host eviction mid-generation and asserts durable resume (generation.test.ts). All consistent with the "no module mocking, real infra" testing policy.

🤖 Generated with Claude Code

This branch had an error being deployed

1 failed deployment
rivet-frontend / actors-pr-5740 — 53bb3a67 Deployed Sep 16, 2026 by railway-app[bot]
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