Skip to content

feat(web): subagent threads rest on a collapsed composer bar - #318

Merged
coreybain merged 2 commits into
mainfrom
add-subagent-compose-bar
Oct 8, 2026
Merged

coreybain merged 2 commits into
mainfrom
add-subagent-compose-bar

Conversation

@coreybain

@coreybain coreybain commented Oct 8, 2026 •

Copy link
Copy Markdown
Collaborator

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.

  • App-owned (delegated) subagents: a Message button opens the full composer and focuses it, so you can talk to the subagent or change its model. It stays open until you leave the thread.
  • Provider-native subagents: the bar says "Runs on its own" and can't open the composer.
  • Pending approvals and questions: these always show the full composer so you can answer.

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.md describes 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.ts passes (8 tests), plus targeted lint and a web tsgo --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):

  • Leaving the thread now always collapses the composer, including when the environment changes.
  • The Message button waits until the subagent's kind is known. While it loads, the bar says "Loading subagent".
  • Actions that need the composer open it first. This covers type-to-focus, the model picker shortcut, Compact, file drops, the file browser's "Add to chat", attaching an edited image, and terminal context. Each of these now opens the collapsed composer of a Pathway-started subagent before using it, instead of silently doing nothing.
  • Desktop snapshots open the composer they land in. A capture aimed at a provider-run subagent goes to a new conversation instead.
  • Closing the command palette returns focus to where it was when there is no composer.
  • The bar picks up the composer's default dark-theme surface.

Implemented with Claude Opus 5.5 in Claude Code.

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-08T10:57:39.256067Z d8b3650 New commits
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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".

Comment thread apps/web/src/components/ChatView.tsx Outdated
const showSubagentComposerBar =
isServerThread &&
activeThread?.lineage.relationshipToParent === "subagent" &&
expandedSubagentComposerKey !== routeThreadKey &&

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment thread apps/web/src/components/ChatView.tsx Outdated
effortLabel={subagentBarModel?.effortLabel ?? null}
status={subagentBarStatus}
onMessage={
composerControlsLocked

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 ? (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Comment on lines +61 to +66
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";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

Corey Baines and others added 2 commits October 8, 2026 21:50
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>
@coreybain
coreybain force-pushed the add-subagent-compose-bar branch from af39bbd to d8b3650 Compare October 8, 2026 10:51

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Your trial has ended. Reactivate Greptile to resume code reviews.

@coreybain
coreybain merged commit 97c60d5 into main Oct 8, 2026
2 checks passed
@coreybain
coreybain deleted the add-subagent-compose-bar branch October 8, 2026 10:52

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

!(currentSubagentComposerVisit.expanded && subagentMessagingAvailable === true) &&

P2 Badge Reveal the composer for external send actions

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".

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.

1 participant