feat(app): add subagents tab to the session side panel - #39382
Open
sdpfigueiredo wants to merge 20 commits into
Open
feat(app): add subagents tab to the session side panel#39382sdpfigueiredo wants to merge 20 commits into
sdpfigueiredo wants to merge 20 commits into
Conversation
sdpfigueiredo
force-pushed
the
sub-agents-tab
branch
from
July 28, 2026 22:22
a9a4ac4 to
d20e071
Compare
This was referenced Jul 28, 2026
Adds a session side-panel tab listing the active session's subagents, each showing task name, live status, cost, and token usage. - Children are derived reactively from the live sync store plus a one-shot backfill for subagents created before the store's fetch window, deduped by id with the live entry winning. - Per-row status and token totals are reactive accessors, so the tab reflects live updates without remounting. - Terminal status (completed/cancelled/error) is read from the parent session's task tool parts, mirroring the CLI footer's reader, with zero per-child network requests. - Cost and token formatting is shared with the session context tab via an extracted formatter module. - i18n keys are complete and consistent across all 18 locales.
- taskStatus() now also treats a completed task part whose output begins with "Aborted" or "Task aborted" as cancelled, fixing a live QA finding where a subagent cancelled through a task-tool implementation that swallows aborts still rendered as Completed. - Removed dead useSDK import/variable in the subagents tab. - Removed dead useSync import/variable and fixed a floating promise in the session side panel. - Removed two redundant `as Session[]` assertions on empty-array literals in the subagents context, proven redundant by typecheck. - Fixed a TypeScript narrowing gap on session.cost inside a Show block, mirroring the existing session.model narrowing pattern.
- session.cost's Show block now gates on a plain boolean (session.cost != null) and coalesces with ?? 0 at the call site, instead of passing the raw number into Show's when - Solid gates on plain JS truthiness, so a cost of exactly 0 was being hidden by the previous fix instead of rendering $0.00. - Added a DOM-level test asserting cost=0 renders correctly. - Awaited a mock.module call in the pure-function test file that was still bare, matching the pattern used everywhere else in this branch's test files.
sdpfigueiredo
force-pushed
the
sub-agents-tab
branch
from
July 30, 2026 20:15
12b7160 to
ca9bec6
Compare
# Conflicts: # packages/app/src/i18n/bs.ts # packages/app/src/i18n/da.ts # packages/app/src/i18n/de.ts # packages/app/src/i18n/es.ts # packages/app/src/i18n/fr.ts # packages/app/src/i18n/ja.ts # packages/app/src/i18n/ko.ts # packages/app/src/i18n/no.ts # packages/app/src/i18n/pl.ts # packages/app/src/i18n/ru.ts # packages/app/src/i18n/th.ts # packages/app/src/i18n/tr.ts # packages/app/src/i18n/uk.ts # packages/app/src/i18n/zh.ts # packages/app/src/i18n/zht.ts
sdpfigueiredo
force-pushed
the
sub-agents-tab
branch
from
August 5, 2026 08:33
d3b9200 to
e46735b
Compare
# Conflicts: # packages/app/src/pages/session/timeline/message-timeline.tsx
|
Many thanks to @sdpfigueiredo for implementing this! I see this PR addresses the issue I described in #37267, and the implementation looks good to me. From a functional perspective, I have no objections to this implementation. If it gets merged and released, I will test it out as soon as possible and provide feedback. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Issue for this PR
Closes #37267
Type of change
What does this PR do?
Adds a "Subagents" tab to the session side panel, so subagent activity can be
followed without it being buried by the main agent's log stream, the problem
described in #37267.
The tab lists each subagent spawned by the current session with its task name,
status, cost, token usage and model. Clicking a row opens that subagent's session,
which is the drill-down to its full output.
Status comes from two places. Running/retrying is read from
session_statusin thesync store. Terminal states (completed / cancelled / failed) come from the parent
session's
tasktool parts, the same source the CLI footer already uses inpackages/opencode/src/cli/cmd/run/subagent-data.ts. The parent session is the oneyou have open, so its parts are already in the store and nothing extra is fetched.
The child list is derived from the live sync store filtered by
parentID, plus aone-shot backfill query for subagents created before the store's paginated window.
No polling and no per-subagent requests.
One part of the issue is not covered: there's no brief output summary on each row.
Rows show status and usage, and you click through for the output. Happy to add a
summary line if that's wanted.
How did you verify your code works?
bun run test:unitandbun run test:solidinpackages/app(741 tests).The one worth looking at is
packages/app/test/session-agents-tab.test.tsx: itmutates only
session_statusfor one child and asserts the row's text changes whilethe DOM node stays identical. It fails if the row values stop being reactive, which
is the mistake that makes this kind of list silently go stale.
Manually: started the backend and the web app, spawned several subagents in one
session, cancelled some mid-run and let others finish. The tab was opened once and
never reopened, new subagents appeared on their own and statuses changed in place.
Screenshots / recordings
Checklist