Skip to content

⛔ DO NOT MERGE — feat: wire OpenCode into spawn dialogs and empty-state UI (headless routing)#140

Draft
khaliqgant wants to merge 8 commits into
mainfrom
claude/opencode-harness-support
Draft

⛔ DO NOT MERGE — feat: wire OpenCode into spawn dialogs and empty-state UI (headless routing)#140
khaliqgant wants to merge 8 commits into
mainfrom
claude/opencode-harness-support

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

@khaliqgant khaliqgant commented Jun 7, 2026

What this PR does

OpenCode was already registered across pear's harness surfaces (proactive agents, burn stamping, cloud agent picker, toolbar, AgentIcons) but was missing from the interactive spawn surfaces users touch directly.

Changes (diff vs PR #139 base):

  • SpawnAgentCli type: 'claude' | 'codex''claude' | 'codex' | 'opencode'
  • SpawnAgentDialog: adds OpenCode card to the spawn grid
  • TerminalPane empty state: adds OpenCode quick-spawn button
  • broker.ts: adds 'opencode' to the headless agent list so it routes through spawnCli({ transport: 'headless' }) rather than spawnPty()

This PR is rebased on #139 — all headless infrastructure (runtime tracking, attachTerminal guard, composite key fix, SpawnCliInput import) lives in #139, not duplicated here.

Critical gap — structured output rendering is NOT in this PR

Same gap as #139: the output pipeline (worker_streambroker:pty-chunk → xterm) is unchanged. For OpenCode headless agents, raw event JSON from OpenCode's app-server will hit xterm verbatim. This is not the intended end state.

How OpenCode's structured output works

OpenCode runs opencode serve --port <n> and exposes an SSE endpoint at /event. Events of interest:

  • message.delta — streamed text output
  • file.changed — file edit notifications
  • permission.requested — approval prompts

V1 plan: parse these SSE events from worker_stream chunks, extract message.delta text, emit formatted text to xterm.
V2 plan: no xterm; render message.delta as message bubbles, file.changed as diff cards, permission.requested as native approval dialogs.

Merge order

  1. Merge ⛔ DO NOT MERGE — feat: upgrade @agent-relay to 8.3.0, wire headless spawn routing and runtime tracking #139 first (relay 8.3.0 + headless infrastructure) — but wait for relay 8.3.0 npm install first
  2. Merge this PR (⛔ DO NOT MERGE — feat: wire OpenCode into spawn dialogs and empty-state UI (headless routing) #140) after ⛔ DO NOT MERGE — feat: upgrade @agent-relay to 8.3.0, wire headless spawn routing and runtime tracking #139

Conflicts to expect at merge

SpawnAgentDialog, TerminalPane, and SpawnAgentCli are also touched by PR #138 (Grok). Conflicts are trivial — result should be all four harnesses in each location.

Deferred

  • V1 structured rendering: parse OpenCode SSE events → formatted xterm text
  • V2 native Pear UI: message bubbles, diff cards, approval dialogs as React components
  • Native approval cards: intercept permission.requested and render as Pear dialog cards

Generated by Claude Code

Bumps all @agent-relay/* packages to ^8.3.0 which ships Codex
app-server adapter, headless agent runtime, and SpawnCliInput.

Pear now tracks each agent's runtime (pty | headless) from the
agent_spawned event and skips PTY snapshot/resize in attachTerminal
for headless agents. The terminal pane shows a placeholder for
headless agents instead of an xterm instance.

Also improves the xterm.js config: lineHeight 1.2, letterSpacing 0.5,
bar cursor, 10k scrollback, alt fast-scroll, macOptionIsMeta, and
replaces instant display:none tab switching with a 150ms opacity fade.

Deferred (noted for follow-up):
- Structured output rendering for Claude (--output-format stream-json)
- Structured output rendering for Codex (app-server events)
- Native approval-prompt UI cards (vs y/n in terminal)
- Bundled monospace font (Geist Mono / Berkeley Mono)

https://claude.ai/code/session_01KXU1uAUwx3L82TMLnAmU4z
@gemini-code-assist
Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Jun 7, 2026

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 7, 2026

Warning

Review limit reached

@khaliqgant, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 2 minutes and 13 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe9f25b3-edc1-4538-917e-ccceffd4f87b

📥 Commits

Reviewing files that changed from the base of the PR and between 6e66172 and a3c8a42.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • electron-builder.mcp-resources.yml
  • package.json
  • src/main/broker.test.ts
  • src/main/broker.ts
  • src/renderer/src/components/sidebar/SpawnAgentDialog.tsx
  • src/renderer/src/components/terminal/TerminalPane.tsx
  • src/renderer/src/hooks/use-terminal.ts
  • src/renderer/src/lib/spawn-agent.ts
  • src/renderer/src/stores/agent-store.ts
  • src/shared/types/ipc.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/opencode-harness-support

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

Re-trigger cubic

@agent-relay-code
Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

Reviewed PR #140 against .workforce/pr.diff, changed files, current checkout, and PR comments.

No code changes were needed. The opencode CLI addition is already supported by the broker/main-side paths and shared harness types, and the renderer build accepts the new icon/import/union usage.

Validation run:

  • npm ci
  • npm run build passed
  • npm test passed: 88 tests
  • npm run verify:mcp-resources-drift passed
  • PR bot comments checked: no actionable findings; quota-limit comments only, plus cubic reported no issues

Notes:

  • npx tsc --project tsconfig.web.json --noEmit fails on existing unrelated renderer errors outside this PR surface.
  • src/main/ipc-handlers.test.ts could not be run standalone because it imports vitest, which is not a declared dependency in this checkout.

I’m not printing READY because I cannot verify remote CI completion/mergeability from this sandbox.

agent-relay-code Bot and others added 2 commits June 7, 2026 06:26
…red-output CLIs

Claude uses --output-format stream-json and Codex has its own app-server; neither
needs an interactive PTY. spawnAgentOnce now routes these two CLIs through
spawnCli({ transport: 'headless' }) (relay 8.3.0) while shells and unknown
executables continue to use spawnPty.

The resolved runtime is set on agentRuntimes immediately after spawn so
attachTerminal skips PTY-only operations (resize, snapshot) without a race
against the async agent_spawned event.

worker_stream chunks still flow through broker:pty-chunk → xterm, so the
headless placeholder that hid the terminal entirely is removed — V1 rendering
is unaffected.

https://claude.ai/code/session_01KXU1uAUwx3L82TMLnAmU4z
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Jun 7, 2026

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/main/broker.ts
agent-relay-code Bot added a commit that referenced this pull request Jun 7, 2026
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Jun 7, 2026

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

Copy link
Copy Markdown

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread src/main/broker.ts Outdated
Three bugs caught in review:

1. SpawnCliInput was missing from the @agent-relay/harness-driver import block,
   causing a TypeScript compile error wherever it was referenced.

2. The immediate agentRuntimes.set() after spawnCli used a bare agent name,
   while every other read/write in the map (agent_spawned event, syncAgents,
   attachTerminal) used the composite "sessionKey:name" key from
   getAgentRuntimeKey(). The cache miss meant the early-set optimization —
   intended to prevent a race between spawnAgent returning and attachTerminal
   reading before agent_spawned fires — was always a no-op.

3. The broker test mock's listAgents/getStatus always returned runtime:'pty'
   for every agent, including those spawned via spawnCli. This would overwrite
   the correct headless runtime in agentRuntimes on the next listAgents poll.
   The mock now tracks runtimes per agent in a local Map, consistent with how
   spawnPty/spawnCli register them.

https://claude.ai/code/session_01KXU1uAUwx3L82TMLnAmU4z
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Jun 7, 2026

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

claude and others added 3 commits June 7, 2026 07:08
OpenCode was already registered as a harness in proactive agents,
burn stamping, the cloud agent picker, and the toolbar — but was
missing from the interactive spawn surfaces.

Adds OpenCode to SpawnAgentCli type, SpawnAgentDialog AGENT_OPTIONS
(3-col grid), and TerminalPane empty-state quick-spawn buttons.

OpenCode runs headless via the app-server (relay 8.3.0), so spawning
it will use the headless runtime path rather than a PTY terminal.
Native structured output rendering is tracked separately.

https://claude.ai/code/session_01KXU1uAUwx3L82TMLnAmU4z
OpenCode exposes an HTTP app-server (opencode serve); relay connects to it
instead of spawning an interactive PTY. spawnAgentOnce routes cli=opencode
through spawnCli({ transport: 'headless' }) (relay 8.3.0 API).

Adds the agentRuntimes map and attachTerminal headless guard so PTY-only
operations (resize, snapshot) are skipped for OpenCode agents. worker_stream
chunks still flow through broker:pty-chunk → xterm for V1 terminal rendering.

https://claude.ai/code/session_01KXU1uAUwx3L82TMLnAmU4z
@khaliqgant khaliqgant force-pushed the claude/opencode-harness-support branch from 6e59aa7 to a3c8a42 Compare June 7, 2026 07:11
@codeant-ai
Copy link
Copy Markdown

codeant-ai Bot commented Jun 7, 2026

Your free trial PR review limit of 300 PRs has been reached. Please upgrade your plan to continue using CodeAnt AI.

@khaliqgant khaliqgant changed the title feat: wire OpenCode into spawn dialogs and empty-state UI ⛔ DO NOT MERGE — feat: wire OpenCode into spawn dialogs and empty-state UI (headless routing) Jun 7, 2026
@khaliqgant khaliqgant marked this pull request as draft June 7, 2026 07:30
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.

2 participants