Skip to content

External agent composer: structured prompts, @ files, and queue - #54

Merged
soorya-u merged 9 commits into
mainfrom
feat/external-agent-composer
Jul 15, 2026
Merged

soorya-u merged 9 commits into
mainfrom
feat/external-agent-composer

Conversation

@soorya-u

@soorya-u soorya-u commented Jul 15, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Structured prompt blocks (text/file/url) end-to-end: schemas, ACP mapping, and user-message chips
  • Worker searchEntries via FileFinder fuzzy/path search for remote @ mentions (search-after-type, path-prefix with /)
  • Lexical composer (t3code-style) with inline chips, slash/file autocomplete, stop vs queue actions, and prompt queue drain

Test plan

  • Type @ → “Type to search”; @web/ lists files under that folder
  • Select a mention from what does @… → text then chip, caret after chip; Backspace removes chip
  • Paste URL → URL chip; send message shows chips (not markdown) in user bubble
  • While turn runs: empty = Stop; with text = queue icon; queued items show “Queued messages” and drain after turn
  • Context usage ring and / autocomplete still work

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added a rich prompt editor supporting text, file attachments, URLs, mentions, and slash-command autocomplete.
    • Added queued messages for active conversations, with controls to remove queued items.
    • Added agent mode selection, available command suggestions, and context-usage indicators.
    • Added workspace file browsing and search for project attachments.
    • Structured prompt content now preserves resource previews in sent messages.
  • Tests

    • Expanded coverage for structured prompts, attachments, queues, filesystem search, and composer modes.

soorya-u and others added 6 commits July 15, 2026 16:15
Support multimodal composer prompts as typed prompt blocks, rename dir listings to fs, and expose fuzzy searchEntries for remote @-file pickers.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace dir listing helpers with FileFinder-backed list/searchEntries, map prompt blocks into ACP content, and persist user_message blocks through turns.

Co-authored-by: Cursor <cursoragent@cursor.com>
Queue messages while a turn is active with stable drain, rename listDir to listEntries, and add debounced searchEntries for composer @ mentions.

Co-authored-by: Cursor <cursoragent@cursor.com>
Use a t3code-style Lexical editor for inline file/URL chips, slash/file autocomplete, stop/queue primary actions, context usage, and structured user bubbles.

Co-authored-by: Cursor <cursoragent@cursor.com>
Mark implemented external-agent-composer tasks and sync composer-ui delta requirements.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
cyrus Ready Ready Preview, Comment Jul 15, 2026 11:25am

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@soorya-u, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 71300d03-0e87-42f8-8cee-c009d386c9a5

📥 Commits

Reviewing files that changed from the base of the PR and between 8301cab and d9adbc4.

📒 Files selected for processing (28)
  • .dotagents/INSTRUCTIONS.md
  • apps/cli/src/core/agents/prompt.ts
  • apps/cli/src/core/agents/runtime.ts
  • apps/cli/src/handlers/controller/fs.ts
  • apps/cli/src/utils/fs.test.ts
  • apps/cli/src/utils/fs.ts
  • apps/web/src/components/chat/composer/compact-composer-controls.tsx
  • apps/web/src/components/chat/composer/composer-mode.test.ts
  • apps/web/src/components/chat/composer/composer-mode.ts
  • apps/web/src/components/chat/composer/composer-prompt-editor.tsx
  • apps/web/src/components/chat/composer/footer-controls.tsx
  • apps/web/src/components/chat/composer/index.tsx
  • apps/web/src/components/chat/composer/primary-action.tsx
  • apps/web/src/components/chat/messages/user-message.tsx
  • openspec/changes/archive/2026-07-15-external-agent-composer/.openspec.yaml
  • openspec/changes/archive/2026-07-15-external-agent-composer/design.md
  • openspec/changes/archive/2026-07-15-external-agent-composer/proposal.md
  • openspec/changes/archive/2026-07-15-external-agent-composer/specs/external-agent-composer/spec.md
  • openspec/changes/archive/2026-07-15-external-agent-composer/specs/wire-schemas/spec.md
  • openspec/changes/archive/2026-07-15-external-agent-composer/tasks.md
  • openspec/specs/composer-ui/spec.md
  • openspec/specs/external-agent-composer/spec.md
  • openspec/specs/wire-schemas/spec.md
  • shared/hooks/src/connection/use-agent-catalog.ts
  • shared/hooks/src/connection/use-controller-threads.ts
  • shared/hooks/src/stores/prompt-queue.test.ts
  • shared/hooks/src/stores/prompt-queue.ts
  • shared/schemas/src/rtc/catalog.ts
📝 Walkthrough

Walkthrough

Changes

The PR adds structured prompt blocks, ACP resource mapping, agent command and context metadata, queued prompts, a Lexical composer with attachments and autocomplete, mode and usage controls, filesystem search RPCs, and corresponding schemas, hooks, tests, and UI wiring.

Structured prompt and runtime

Layer / File(s) Summary
Prompt contract and persistence
shared/schemas/..., shared/utils/...
Chat messages use typed text/resource blocks that remain available through validation, events, cache updates, views, and folded messages.
Agent prompt mapping and metadata
apps/cli/src/core/agents/...
Runtime sessions track commands and usage and route text or structured prompts through ACP-compatible APIs.
Turn and thread wiring
apps/cli/src/utils/..., apps/cli/src/core/threads/..., apps/cli/src/handlers/controller/chat.ts
Turn orchestration and coordinator flows accept structured messages while formatting text for legacy content fields.

Agent catalog and composer

Layer / File(s) Summary
Catalog metadata and prompt queue
shared/hooks/src/stores/..., shared/schemas/src/rtc/catalog.ts
Per-thread state tracks capabilities, commands, modes, context usage, and queued prompts.
Catalog connections and queued sending
shared/hooks/src/connection/...
Catalog queries synchronize modes and usage, while active-thread messages queue and drain sequentially.
Lexical composer and resource editing
apps/web/src/components/chat/composer/composer-*.tsx, apps/web/package.json
The composer serializes text and inline resource nodes and adds attachment, mention, slash-command, and queue interactions.
Composer controls and presentation
apps/web/src/components/chat/composer/..., apps/web/src/components/chat/messages/...
Mode, context usage, busy-state, and structured user-message rendering are integrated into the chat UI.

Filesystem catalog APIs

Layer / File(s) Summary
Filesystem scanning utilities
apps/cli/src/utils/fs.ts, apps/cli/src/utils/fs.test.ts
Filesystem listing and search support depth limits, gitignore-aware scanning, query normalization, result truncation, timeouts, and cleanup.
Filesystem contracts and hooks
shared/schemas/src/rtc/fs.ts, shared/connections/..., shared/hooks/src/connection/..., apps/cli/src/handlers/controller/...
Directory and search entry RPCs replace the previous directory-only endpoint and are consumed by project browsing.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.28% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the PR’s main scope: external agent composer work covering structured prompts, file mentions, and queueing.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/external-agent-composer

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai 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.

Actionable comments posted: 16

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/web/src/components/chat/composer/primary-action.tsx (1)

30-57: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the stop action available when a queued draft exists.

While busy, entering any content replaces “Stop generation” with “Add to queue.” Users must erase their draft before they can stop the active turn. Render separate queue and stop controls when both actions are available.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/chat/composer/primary-action.tsx` around lines 30 -
57, Update the busy branch in the primary action component so a draft that can
be queued does not replace the stop control. When busy and canSend is true,
render both the Add to queue submit button and the Stop generation button using
onStop; preserve the existing single stop-control behavior when no draft is
available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/cli/src/core/agents/prompt.ts`:
- Around line 32-39: Update resolveResourceUri to use Node’s pathToFileURL for
resolved local paths instead of checking whether the path starts with "/".
Preserve passthrough behavior for HTTP and existing file:// URIs, and return the
pathToFileURL result so Windows drive-letter paths become valid, forward-slash
file URIs for mapPromptBlockToAcp.

In `@apps/cli/src/core/agents/runtime.ts`:
- Around line 49-50: Update recoverSessions() to keep session metadata
synchronized: call attachSessionMetadata() after each successful session
recovery and detachSessionMetadata() whenever recovery removes a session,
including failed recovery and unsupported loadSession cases. Add regression
coverage for successful recovery, failed recovery, and unsupported loadSession,
while preserving existing recovery behavior.
- Line 338: In both branches of closeSession(), move
detachSessionMetadata(threadId) to after the awaited session.close() call
completes successfully. Preserve the existing session cleanup behavior, but
ensure rejected closes leave the session’s metadata listener and cached
commands/usage intact.

In `@apps/cli/src/handlers/controller/fs.ts`:
- Around line 14-17: Update the error handling around listDir, listFiles, and
searchFiles so only missing-path filesystem errors map to ORPCError code
NOT_FOUND. Preserve the existing error message conversion, but classify readdir
failures, scan timeouts, and FileFinder errors with the project’s
internal/transient ORPC code instead of treating every failure as not found.

In `@apps/cli/src/utils/fs.ts`:
- Around line 98-102: Update the normalization in the search-query flow to
remove only mention and explicit path prefixes, without stripping leading dots
from dotfiles or path components such as .github/workflows and @.env. Adjust
SEARCH_QUERY_PREFIX_PATTERN or its application accordingly, while preserving the
existing trim and empty-query handling.

In `@apps/web/src/components/chat/composer/composer-mode.test.ts`:
- Around line 3-14: Replace the locally defined shouldShowModeSelector helper in
the composer mode selector tests with the production implementation, importing
the actual helper or rendering the production control. Keep the existing empty
and non-empty mode assertions, ensuring they exercise the composer’s real
mode-selector behavior.

In `@apps/web/src/components/chat/composer/composer-prompt-editor.tsx`:
- Around line 134-139: Update CommandKeyPlugin and handleCommandKeyDown to
dispatch and process the existing "Escape" ComposerCommandKey. Ensure Escape
reaches autocomplete consumers through the same command-key API and closes the
relevant autocomplete state, while preserving existing behavior for the other
keys.
- Around line 64-95: Update the serialization traversal around flushText and
visit so paragraph boundaries produce newline separators and whitespace adjacent
to resource chips is preserved. Remove the unconditional trimming that strips
meaningful spaces, while still excluding COMPOSER_CHIP_PLACEHOLDER and avoiding
unintended empty text blocks.

In `@apps/web/src/components/chat/composer/index.tsx`:
- Line 69: Update the composer’s onSend contract and invocation to return and
await a promise, then clear the editor only after the send succeeds. In the send
handler around onSend and the sending state, use try/finally so sending is
always reset even when busy does not transition, while preserving the existing
busy-state behavior.
- Around line 147-151: Update insertFileMention to derive the resource name
without accepting an empty final path segment: when the path ends with "/", use
the preceding non-empty segment or the full path as the fallback. Pass this
non-blank name to replaceAtTokenWithResource while preserving the existing
behavior for file paths.

In `@apps/web/src/components/chat/messages/user-message.tsx`:
- Around line 47-69: Update the text branch in the blocks.map rendering flow to
pass each non-empty block.text through the existing markdown renderer,
preserving markdown formatting such as bold; keep resource blocks rendered with
UserMessageResourceChip and retain the current trimming and empty-text behavior.

In `@openspec/specs/composer-ui/spec.md`:
- Around line 67-79: Update the composer capability logic in the composer
component to use the cached bindAgent capabilities for the current thread.
Derive attachment visibility from embedded-context support, including both file
and URL attachment controls, instead of relying only on threadCwd or always
enabling URL pasting; preserve supported-agent behavior and the existing
slash-command handling.

In `@shared/hooks/src/connection/use-agent-catalog.ts`:
- Around line 144-159: Update the agent-switch mutation around onMutate and
onSuccess to snapshot and clear all agent-scoped catalog state, including
models, modes, efforts, personas, capabilities, commands, and usage. Extend the
existing rollback returned by onMutate and restore every snapshot in onError,
while preserving the onSuccess population of the new agent’s catalog and usage
data.

In `@shared/hooks/src/connection/use-controller-threads.ts`:
- Around line 175-188: Update the prompt-draining loop around sendMessageNow so
a queued prompt remains available until sending succeeds. Preserve FIFO ordering
by peeking before dequeueing and removing only after a successful send, or by
restoring the failed prompt at the front; ensure failures, including
stop-related failures, do not lose user content.
- Around line 203-210: Update sendMessage and the active-turn tracking around
activeTurnByThreadRef so queue decisions reflect turns already running from
remounts or other clients, not only turns created by sendMessageNow. Synchronize
the map from conversation/session events, or enforce the same serialization
server-side, while preserving enqueue behavior for active threads and preventing
concurrent turns.

In `@shared/schemas/src/rtc/catalog.ts`:
- Around line 26-29: Update ContextUsageSchema to validate that both optional
used and limit values are non-negative, while preserving their optional nature
and numeric validation. This ensures ComposerContextUsage receives only valid
values for ratio and progress rendering.

---

Outside diff comments:
In `@apps/web/src/components/chat/composer/primary-action.tsx`:
- Around line 30-57: Update the busy branch in the primary action component so a
draft that can be queued does not replace the stop control. When busy and
canSend is true, render both the Add to queue submit button and the Stop
generation button using onStop; preserve the existing single stop-control
behavior when no draft is available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eee8c6e2-8a09-4494-9bbe-8a7b00af18c7

📥 Commits

Reviewing files that changed from the base of the PR and between 85466a0 and 8301cab.

⛔ Files ignored due to path filters (1)
  • bun.lock is excluded by !**/*.lock
📒 Files selected for processing (63)
  • apps/cli/__tests__/integration/draft-session-lifecycle.test.ts
  • apps/cli/__tests__/integration/wiring.test.ts
  • apps/cli/package.json
  • apps/cli/src/commands/service/start.ts
  • apps/cli/src/core/agents/prompt.test.ts
  • apps/cli/src/core/agents/prompt.ts
  • apps/cli/src/core/agents/runtime.test.ts
  • apps/cli/src/core/agents/runtime.ts
  • apps/cli/src/core/registry/binary.ts
  • apps/cli/src/core/threads/coordinator.ts
  • apps/cli/src/handlers/controller/catalog/context.ts
  • apps/cli/src/handlers/controller/chat.ts
  • apps/cli/src/handlers/controller/dir.ts
  • apps/cli/src/handlers/controller/fs.ts
  • apps/cli/src/handlers/controller/index.ts
  • apps/cli/src/store/agents.ts
  • apps/cli/src/store/config.ts
  • apps/cli/src/store/database.ts
  • apps/cli/src/store/registry.ts
  • apps/cli/src/utils/dir.ts
  • apps/cli/src/utils/fs.test.ts
  • apps/cli/src/utils/fs.ts
  • apps/cli/src/utils/process.ts
  • apps/cli/src/utils/run-turn.test.ts
  • apps/cli/src/utils/run-turn.ts
  • apps/web/package.json
  • apps/web/src/components/chat/composer/compact-composer-controls.tsx
  • apps/web/src/components/chat/composer/composer-attachments.tsx
  • apps/web/src/components/chat/composer/composer-context-usage.tsx
  • apps/web/src/components/chat/composer/composer-mode.test.ts
  • apps/web/src/components/chat/composer/composer-prompt-editor.tsx
  • apps/web/src/components/chat/composer/composer-queue.tsx
  • apps/web/src/components/chat/composer/composer-resource-node.tsx
  • apps/web/src/components/chat/composer/footer-controls.tsx
  • apps/web/src/components/chat/composer/index.tsx
  • apps/web/src/components/chat/composer/primary-action.tsx
  • apps/web/src/components/chat/composer/slash-command-autocomplete.tsx
  • apps/web/src/components/chat/main/thread-workspace.tsx
  • apps/web/src/components/chat/messages/user-message.tsx
  • apps/web/src/hooks/projects/use-add-project-browse.ts
  • openspec/changes/external-agent-composer/tasks.md
  • openspec/specs/composer-ui/spec.md
  • shared/connections/src/contracts/controller.ts
  • shared/constants/src/operation-keys.test.ts
  • shared/constants/src/operation-keys.ts
  • shared/hooks/src/connection/use-agent-catalog.ts
  • shared/hooks/src/connection/use-controller-threads.ts
  • shared/hooks/src/connection/use-list-dir.ts
  • shared/hooks/src/connection/use-list-entries.ts
  • shared/hooks/src/connection/use-search-entries.ts
  • shared/hooks/src/connection/use-worker-conversation-sync.ts
  • shared/hooks/src/stores/agent-catalog.ts
  • shared/hooks/src/stores/prompt-queue.test.ts
  • shared/hooks/src/stores/prompt-queue.ts
  • shared/schemas/src/rtc/catalog.ts
  • shared/schemas/src/rtc/chat.test.ts
  • shared/schemas/src/rtc/chat.ts
  • shared/schemas/src/rtc/dir.ts
  • shared/schemas/src/rtc/fs.ts
  • shared/schemas/src/view/index.ts
  • shared/utils/src/conversations/cache.ts
  • shared/utils/src/fold.ts
  • tests/e2e/manual/verify-draft-session.ts
💤 Files with no reviewable changes (4)
  • shared/schemas/src/rtc/dir.ts
  • apps/cli/src/utils/dir.ts
  • shared/hooks/src/connection/use-list-dir.ts
  • apps/cli/src/handlers/controller/dir.ts

Comment thread apps/cli/src/core/agents/prompt.ts
Comment thread apps/cli/src/core/agents/runtime.ts
Comment thread apps/cli/src/core/agents/runtime.ts Outdated
Comment thread apps/cli/src/handlers/controller/fs.ts Outdated
Comment thread apps/cli/src/utils/fs.ts
Comment thread openspec/specs/composer-ui/spec.md
Comment thread shared/hooks/src/connection/use-agent-catalog.ts
Comment thread shared/hooks/src/connection/use-controller-threads.ts
Comment thread shared/hooks/src/connection/use-controller-threads.ts
Comment thread shared/schemas/src/rtc/catalog.ts
Document no-backward-compat and prefer better-result error-as-values guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
Harden FS/prompt URI handling, session metadata recovery, queue drain safety, and capability-aware composer controls.

Co-authored-by: Cursor <cursoragent@cursor.com>
@soorya-u soorya-u linked an issue Jul 15, 2026 that may be closed by this pull request
Move the completed change into archive and fold its delta requirements into main openspec specs.

Co-authored-by: Cursor <cursoragent@cursor.com>
@soorya-u
soorya-u merged commit 8436cdd into main Jul 15, 2026
7 checks passed
@soorya-u
soorya-u deleted the feat/external-agent-composer branch July 15, 2026 11:26

This branch was successfully deployed

1 active deployment
Preview — d9adbc4a Deployed Jul 15, 2026 by vercel[bot]
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.

Phase 2a: External agent composer

1 participant