Skip to content

fix: await event loop in non-interactive opencode run#29132

Open
hardes11 wants to merge 1 commit into
anomalyco:devfrom
hardes11:fix/run-format-json-missing-events
Open

fix: await event loop in non-interactive opencode run#29132
hardes11 wants to merge 1 commit into
anomalyco:devfrom
hardes11:fix/run-format-json-missing-events

Conversation

@hardes11
Copy link
Copy Markdown

@hardes11 hardes11 commented May 24, 2026

Issue for this PR

Closes #26855 (originally reported as #29131, which was a duplicate)

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Fixes opencode run --format json exiting before the event stream completes. In non-interactive mode, loop() was called fire-and-forget (.catch(), not awaited). When prompt() returns the HTTP ack, execute() returns, the Effect framework disposes the in-process server, and the SSE stream dies before the model finishes generating.

Only step_start was emitted. text and step_finish were lost.

The change stores the loop promise and awaits it after the prompt/command call, keeping the process alive until the session reaches idle.

How did you verify your code works?

  • Build: bun run build --single --skip-embed-web-ui → smoke test passed
  • Before fix: opencode run "what is 2+2?" --format json emits only step_start
  • After fix: emits step_start, text (with "4"), step_finish
  • Also verified with opencode run "search arxiv for..." --format json — tool_use events now appear
  • Full typecheck passed (bun turbo typecheck, 15/15 packages)

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

In non-interactive mode, the event processing loop was started with
fire-and-forget (Promise.catch but not awaited). When the prompt()
call returned its HTTP acknowledgment, execute() returned immediately,
and the Effect framework's cleanup disposed the in-process server,
killing the SSE stream before the model finished generating.

Only the step_start event was emitted (it arrives before prompt()
returns). All text, tool_use, and step_finish events were lost because
the stream was torn down mid-generation.

Fix: store the loop promise and await it after the prompt/command call
completes. This keeps the process alive until the session reaches idle
and all events have been processed.

Tested: `opencode run 'what is 2+2?' --format json` now correctly
emits step_start + text + step_finish events (previously only step_start).
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.

run --format json can exit before emitting final step_finish event

1 participant