Repository navigation
External agent composer: structured prompts, @ files, and queue - #54
Conversation
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>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 21 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the 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 configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (28)
📝 WalkthroughWalkthroughChangesThe 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
Agent catalog and composer
Filesystem catalog APIs
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related issues
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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 winKeep 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
⛔ Files ignored due to path filters (1)
bun.lockis excluded by!**/*.lock
📒 Files selected for processing (63)
apps/cli/__tests__/integration/draft-session-lifecycle.test.tsapps/cli/__tests__/integration/wiring.test.tsapps/cli/package.jsonapps/cli/src/commands/service/start.tsapps/cli/src/core/agents/prompt.test.tsapps/cli/src/core/agents/prompt.tsapps/cli/src/core/agents/runtime.test.tsapps/cli/src/core/agents/runtime.tsapps/cli/src/core/registry/binary.tsapps/cli/src/core/threads/coordinator.tsapps/cli/src/handlers/controller/catalog/context.tsapps/cli/src/handlers/controller/chat.tsapps/cli/src/handlers/controller/dir.tsapps/cli/src/handlers/controller/fs.tsapps/cli/src/handlers/controller/index.tsapps/cli/src/store/agents.tsapps/cli/src/store/config.tsapps/cli/src/store/database.tsapps/cli/src/store/registry.tsapps/cli/src/utils/dir.tsapps/cli/src/utils/fs.test.tsapps/cli/src/utils/fs.tsapps/cli/src/utils/process.tsapps/cli/src/utils/run-turn.test.tsapps/cli/src/utils/run-turn.tsapps/web/package.jsonapps/web/src/components/chat/composer/compact-composer-controls.tsxapps/web/src/components/chat/composer/composer-attachments.tsxapps/web/src/components/chat/composer/composer-context-usage.tsxapps/web/src/components/chat/composer/composer-mode.test.tsapps/web/src/components/chat/composer/composer-prompt-editor.tsxapps/web/src/components/chat/composer/composer-queue.tsxapps/web/src/components/chat/composer/composer-resource-node.tsxapps/web/src/components/chat/composer/footer-controls.tsxapps/web/src/components/chat/composer/index.tsxapps/web/src/components/chat/composer/primary-action.tsxapps/web/src/components/chat/composer/slash-command-autocomplete.tsxapps/web/src/components/chat/main/thread-workspace.tsxapps/web/src/components/chat/messages/user-message.tsxapps/web/src/hooks/projects/use-add-project-browse.tsopenspec/changes/external-agent-composer/tasks.mdopenspec/specs/composer-ui/spec.mdshared/connections/src/contracts/controller.tsshared/constants/src/operation-keys.test.tsshared/constants/src/operation-keys.tsshared/hooks/src/connection/use-agent-catalog.tsshared/hooks/src/connection/use-controller-threads.tsshared/hooks/src/connection/use-list-dir.tsshared/hooks/src/connection/use-list-entries.tsshared/hooks/src/connection/use-search-entries.tsshared/hooks/src/connection/use-worker-conversation-sync.tsshared/hooks/src/stores/agent-catalog.tsshared/hooks/src/stores/prompt-queue.test.tsshared/hooks/src/stores/prompt-queue.tsshared/schemas/src/rtc/catalog.tsshared/schemas/src/rtc/chat.test.tsshared/schemas/src/rtc/chat.tsshared/schemas/src/rtc/dir.tsshared/schemas/src/rtc/fs.tsshared/schemas/src/view/index.tsshared/utils/src/conversations/cache.tsshared/utils/src/fold.tstests/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
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>
Move the completed change into archive and fold its delta requirements into main openspec specs. Co-authored-by: Cursor <cursoragent@cursor.com>
Summary
searchEntriesvia FileFinder fuzzy/path search for remote@mentions (search-after-type, path-prefix with/)Test plan
@→ “Type to search”;@web/lists files under that folderwhat does @…→ text then chip, caret after chip; Backspace removes chip/autocomplete still workMade with Cursor
Summary by CodeRabbit
New Features
Tests