Skip to content

fix(server): stop OpenCode child sessions and route their approvals - #210

Merged
leoisadev1 merged 3 commits into
mainfrom
fix/opencode-child-sessions
Sep 13, 2026
Merged

leoisadev1 merged 3 commits into
mainfrom
fix/opencode-child-sessions

Conversation

@leoisadev1

Copy link
Copy Markdown
Member

Problem

OpenCode runs each subagent in a separate child session. Akeru only aborted the parent session and dropped events whose sessionID was not the parent. Child model requests could keep running after Stop, and child permission or question prompts never appeared on the parent thread.

Adaptation

This ports child-session ownership and descendant abort from upstream T3 Code onto the live legacy OpenCode adapter. It does not change OpenCode Go's Mastra controller, Codex, or Kimi.

  • Record descendant sessions from session.created / session.updated parent links.
  • Route child permission and question events onto the parent thread after ancestry is verified, including a bounded retry when the relation is not yet known.
  • Interrupt and session teardown walk session.children and abort every descendant, with SDK list/abort concurrency capped at 8.
  • Unrelated OpenCode sessions are not touched. A failed child abort fails the interrupt.

Akeru subscription env, MCP headers/credentials, lazy attachments, and raw event retention are unchanged.

Upstream

Adapted from pingdotgg/t3code#8480 (child request routing and ancestry) and pingdotgg/t3code#9005 (descendant abort).

Scope

  • apps/server/src/provider/Layers/OpenCodeAdapter.ts
  • focused adapter tests
  • docs/internals/providers.md

Not in this PR: CLI probe bounding (pingdotgg#8750, pingdotgg#10427, see #205), full-access auto-reply (pingdotgg#9282), approval retry / stuck running (pingdotgg#9653), revert boundaries (pingdotgg#9924), part-index memory, or SDK skill loading (pingdotgg#9585).

Verification

  • vp test run apps/server/src/provider/Layers/OpenCodeAdapter.test.ts — 38 tests passed, including child permission routing, unrelated-session isolation, ancestry recovery, nested descendant abort, and child-abort failure.
  • Targeted lint passed. Server typecheck reports no new errors in the changed files.

No live OpenCode CLI or browser pass: this is adapter protocol behavior covered by the recorded mock. End-to-end bot/group cancellation remains blocked until an OpenCode runtime and credentials are available in the isolated environment.

Limitations

Prompt send serialization, idle reconciliation, and failed-reply retry from later upstream follow-ups are still separate work. Windows was not exercised; child abort uses the same SDK client as the parent session.

Made with Grok 4.6 High in Grok Build via Orca.

OpenCode runs each subagent in a child session. The adapter only aborted
the parent and dropped events from other session IDs, so child model
requests and approval prompts could continue after Stop.

Track descendant sessions, route child permission and question events
onto the parent thread after ancestry is verified, and walk the child
tree on interrupt and teardown. Unrelated sessions are left alone.
OpenCode Go stays on Mastra.

Adapted from pingdotgg#8480 and pingdotgg#9005.

Made with Grok 4.6 High in Grok Build via Orca.
@vercel

vercel Bot commented Sep 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
akeru-bot-landing Building Building Preview Sep 10, 2026 5:33pm UTC

Request Review

@github-actions github-actions Bot added type:provider Agent provider contribution. vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XL labels Sep 10, 2026
@greptile-apps

greptile-apps Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

Greptile Summary

This update ensures child OpenCode approval and question events are routed to their owning parent session, including terminal events received while ancestry is still being resolved.

Confidence Score: 5/5

Safe to merge.

The previous approval-routing issue is resolved. greptile-apps[bot] resolved it without explanation; the current code retains a terminal event received during ancestry resolution and emits it after the child session is confirmed as related.

Reviews (3): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

A child permission reply that arrived while ancestry was still unknown
was dropped because the request already had a retry. After ancestry
resolved, only request.opened was forwarded, so the approval stayed
open. Remember the terminal event on the pending retry and emit it
after the opened event.

Made with Grok 4.6 High in Grok Build via Orca.
…ssions

# Conflicts:
#	docs/internals/providers.md
@leoisadev1
leoisadev1 merged commit ce8b50a into main Sep 13, 2026
11 checks passed
@leoisadev1
leoisadev1 deleted the fix/opencode-child-sessions branch September 13, 2026 20:01
@leoisadev1

Copy link
Copy Markdown
Member Author

This is Leo's agent. The independent lifecycle-race regression still fails on refreshed head e6a7437. The 39 committed OpenCodeAdapter tests pass, but the additional deterministic test against the unchanged shipped adapter ends with request.opened instead of request.resolved.

Sequence: hold the child session.get ancestry lookup after permission.asked; deliver session.created identifying the child ancestry; deliver permission.replied; release the pending lookup after observing request.resolved. The pending ask retry subsequently emits request.opened, reopening the settled permission. This differs from the committed case where ancestry remains unknown until the lookup returns.

Re-run: vp test run apps/server/src/provider/Layers/OpenCodeAdapter.test.ts -t 'keeps child permission settled when lifecycle establishes ancestry during lookup' --maxWorkers=2. One supplemental test failed in 11ms within a 17ms suite. This test uses the actual adapter with the existing SDK mock plus a promise barrier in the mock event stream; no production implementation edits and no sleeps/polling. It remains scratch-only evidence, not committed regression coverage.

Please retain the repair hold: reconcile in-flight ancestry retries with lifecycle-established ownership and already-settled requests, add a committed deterministic regression for this interleaving, and rerun review. Existing Orca access remains unavailable to this supervisor, so this comment is not a worker-delivery or repair-execution receipt.

@github-actions github-actions Bot mentioned this pull request Sep 13, 2026
leoisadev1 added a commit that referenced this pull request Sep 13, 2026
* fix(server): stop OpenCode child sessions and route their approvals

OpenCode runs each subagent in a child session. The adapter only aborted
the parent and dropped events from other session IDs, so child model
requests and approval prompts could continue after Stop.

Track descendant sessions, route child permission and question events
onto the parent thread after ancestry is verified, and walk the child
tree on interrupt and teardown. Unrelated sessions are left alone.
OpenCode Go stays on Mastra.

Adapted from pingdotgg#8480 and pingdotgg#9005.

Made with Grok 4.6 High in Grok Build via Orca.

* fix(server): keep child OpenCode replies during ancestry retry

A child permission reply that arrived while ancestry was still unknown
was dropped because the request already had a retry. After ancestry
resolved, only request.opened was forwarded, so the approval stayed
open. Remember the terminal event on the pending retry and emit it
after the opened event.

Made with Grok 4.6 High in Grok Build via Orca.

* fix(server): auto-reply full-access OpenCode permission asks

Full-access threads still surfaced OpenCode permission dialogs for
doom-loop and subagent asks that never consult the session ruleset.
Reply once off the event pump, without a persistent always grant, and
fall back to the dialog if that reply fails.

Depends on child-session routing in #210.

Adapted from pingdotgg#9282.

Made with Grok 4.6 High in Grok Build via Orca.

* fix(server): abort timed-out OpenCode approvals

* test(server): drain full-access approval events

* test(server): bound OpenCode reply barrier

* test(server): type reply timeout failure

This branch was successfully deployed

1 active deployment
Preview — e6a7437e Deployed Sep 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL type:provider Agent provider contribution. vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant