Repository navigation
feat(web): subagent threads rest on a collapsed composer bar - #318
Conversation
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ae197fb752
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const showSubagentComposerBar = | ||
| isServerThread && | ||
| activeThread?.lineage.relationshipToParent === "subagent" && | ||
| expandedSubagentComposerKey !== routeThreadKey && |
There was a problem hiding this comment.
Reset the expanded composer after leaving the thread
When ChatViewContent remains mounted while navigating between IDs on the parameterized thread route, clicking Message stores the child’s routeThreadKey, but leaving only changes the current key and never clears the stored one. Opening the parent and then returning to that same child therefore renders the full ChatComposer again instead of restoring the collapsed bar promised for a new visit. Reset this expansion when the active thread changes, or provide an explicit way to collapse it.
AGENTS.md reference: AGENTS.md:L77-L77
Useful? React with 👍 / 👎.
| effortLabel={subagentBarModel?.effortLabel ?? null} | ||
| status={subagentBarStatus} | ||
| onMessage={ | ||
| composerControlsLocked |
There was a problem hiding this comment.
Keep Message hidden until the subagent origin resolves
On older remote servers, the parent shell omits subagentComposerStates, so the fallback parent-detail subscription is asynchronous and matchedParentSubagent is temporarily null. During that window composerControlsLocked is false and this exposes Message even for a provider-native child; if clicked, the stored expansion continues to suppress the bar after the fallback identifies the child as provider-native, leaving the full composer available for the visit. Treat an unresolved origin as loading or force the bar closed when the origin resolves to provider_native.
AGENTS.md reference: AGENTS.md:L78-L78
Useful? React with 👍 / 👎.
| onExpandImage={onExpandTimelineImage} | ||
| onOpenIssueContext={openIssueContext} | ||
| /> | ||
| {showSubagentComposerBar ? ( |
There was a problem hiding this comment.
Handle snapshot delivery while the composer is collapsed
On desktop, SnapShotCoordinator still accepts the current server thread as a capture target, writes the image into that thread’s composer draft, and dispatches the composer-focus event. This branch has unmounted ChatComposer, however, so the focus ref is null and the newly attached capture has no visible destination; an app-owned child hides it until the user independently clicks Message, while a provider-native child has no way to reveal or send it at all. Expand an eligible composer for external draft deliveries, or reject/redirect captures when messaging is unavailable.
AGENTS.md reference: AGENTS.md:L73-L74
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: af39bbdff3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const workspaceFileDropHandlers = makeWorkspaceFileDropHandlers({ | ||
| setDragActive: setIsWorkspaceFileDragActive, | ||
| addFiles: (files) => composerRef.current?.addDroppedFiles(files), | ||
| addFiles: (files) => resolveComposerHandle(composerRef)?.addDroppedFiles(files), |
There was a problem hiding this comment.
Disable file drops when messaging is unavailable
When the current child is provider-native or its ownership is still loading, the composer has neither a mounted handle nor a reveal callback, so this drop callback silently discards the files. The surrounding unconditional drag handlers still advertise a copy operation and display “Drop files to attach,” making a successful-looking drop do nothing; gate the drop affordance on messaging availability or explicitly reject/redirect the drop.
AGENTS.md reference: AGENTS.md:L73-L73
Useful? React with 👍 / 👎.
| const subagents = parentRef | ||
| ? (readThreadShell(parentRef)?.subagentComposerStates ?? | ||
| readThreadProjection(parentRef)?.projection.subagents) | ||
| : undefined; | ||
| const origin = subagents?.find((child) => child.childThreadId === target.threadId)?.origin; | ||
| return origin === "app_owned"; |
There was a problem hiding this comment.
Defer snapshot routing until child ownership resolves
On an older remote server that omits subagentComposerStates, opening an app-owned child starts an asynchronous parent-detail subscription, so readThreadProjection(parentRef) can still be null when the snapshot is routed. The newly added origin === "app_owned" check is fresh evidence: it treats that unresolved state as definitively unmessageable, causing resolveExistingSnapShotTarget to reject the current child and resolveTarget to create a new conversation if the user chooses Chat before the fallback arrives. Preserve an unresolved state and wait or retry instead of redirecting a valid app-owned child.
AGENTS.md reference: AGENTS.md:L15-L17
Useful? React with 👍 / 👎.
Subagent threads replace the composer with a one-line bar showing the model, effort, live status, and an Open parent button. App-owned subagents expand the full composer from the bar; provider-native ones run on their own. Pending approvals and questions always show the composer. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Reset expansion when leaving a subagent, wait for ownership before enabling messages, and reveal eligible composers for explicit actions. Keep desktop captures deliverable and preserve dark surfaces and dialog focus. Co-Authored-By: GPT-6.1-Sol (Codex) <noreply@openai.com>
af39bbd to
d8b3650
Compare
There was a problem hiding this comment.
Your trial has ended. Reactivate Greptile to resume code reviews.
There was a problem hiding this comment.
💡 Codex Review
pathway/apps/web/src/components/ChatView.tsx
Line 4077 in d8b3650
When an app-owned subagent is left on this collapsed bar, some non-composer entry points still read composerRef.current directly rather than calling resolveComposerHandle. In particular, submitting an element annotation from the embedded preview reaches onSend via onSendAnnotation, but onSend sees a null handle and returns without sending; the thread panel's push-recovery action similarly reports that the provider is unavailable. Reveal the messageable composer before these actions read their send context.
AGENTS.md reference: AGENTS.md:L71-L73
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Opening a subagent's thread showed the full composer, even for provider-native subagents that can't take messages. There was no quick way to see which model the subagent runs on, how long it has been working, or to get back to the parent thread.
Subagent threads now replace the composer with a one-line bar, based on t3code's
ProviderSubagentBar. It shows the provider icon, the model, the effort label, and the status ("Working 12s", "Completed in 8m 1s"), with an Open parent button.The status comes from the child thread's latest run. Provider-native children have no runs, so for them it falls back to the child's runless root turn. The timer updates the label directly once a second, so the chat view doesn't re-render while it ticks. The branch/context strip is hidden while the bar shows.
docs/user/subagents.mddescribes the new bar.Surfaces: web and desktop. iOS is native SwiftUI and is not covered here; it could be a follow-up.
Verification:
vp test run src/components/chat/SubagentComposerBar.logic.test.tspasses (8 tests), plus targeted lint and a webtsgo --noEmit. Before/after screenshots are still to come, because I haven't run it in a live client yet.Audit follow-up (GPT-6.1-Sol, af39bbd):
Implemented with Claude Opus 5.5 in Claude Code.
🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.