Skip to content

ACP interactive host: composer permissions and elicitation - #57

Merged
soorya-u merged 8 commits into
mainfrom
feat/acp-interactive-host
Jul 15, 2026
Merged

ACP interactive host: composer permissions and elicitation#57
soorya-u merged 8 commits into
mainfrom
feat/acp-interactive-host

Conversation

@soorya-u

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

Copy link
Copy Markdown
Owner

Summary

  • Blocks ACP requestPermission (and elicitation) on the worker until the user responds via respondApproval / respondElicitation
  • Surfaces pending prompts in the chat composer (stacked allow/reject / form-url elicitation), folds them into conversation views, and clears pending on cancel
  • Fixes related composer UX: draft restore after remount, non-blocking send so the prompt clears, chip copy as @uri, Working marker reliability, and green completed-tool checks

Test plan

  • Trigger a tool permission mid-turn → composer shows Pending approval; Allow/Reject clears UI and turn continues or denies
  • Second click after respond does not error with stale pending UI
  • With text typed while streaming → queue icon + stop (not disabled spinner + uncleared prompt)
  • Refresh mid-draft → composer restores text/resources; approval UI remount does not wipe drafts
  • Copy composer content with file/URL chips → pastes @path / @url
  • Agent without elicitation capability → no elicitation chrome
  • bun test for interactive host / fold / thread-feed suites

Made with Cursor

Summary by CodeRabbit

  • New Features

    • Added interactive approval prompts for tool actions, with allow and deny choices.
    • Added elicitation prompts supporting URL confirmations and form responses.
    • Responses are synchronized across connected interfaces and reflected in conversations.
    • Pending interactions now appear in the chat composer with progress and error states.
  • Bug Fixes

    • Cancelling a turn now safely clears pending interactions.
    • Improved draft restoration and message recovery after failed sends.
    • Added retry handling for interrupted conversation synchronization.
    • Improved active-turn and working-state indicators.

soorya-u and others added 7 commits July 16, 2026 00:38
Introduce approval/elicitation request and resolved events, respond RPC
inputs, view schemas, and controller operation keys so clients and the
worker share one interactive protocol.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add a shared pending registry host, respondApproval/respondElicitation
handlers, and turn binding so tool calls and elicitations pause until
the user responds or the turn is cancelled.

Co-authored-by: Cursor <cursoragent@cursor.com>
Extend fold and deriveFeed so pending interactive prompts are available
as typed view entries for clients to render.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add respond mutations with optimistic resolve, return send after chat
accept so the composer clears while the turn continues, harden worker
conversation sync, and wait for draft store hydration before restore.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the prompt with stacked allow/reject and elicitation panels,
skip interactive cards in the feed, fix draft restore after remounts,
copy resource chips as @uri, and improve send/queue and Working marker
behavior.

Co-authored-by: Cursor <cursoragent@cursor.com>
Move the completed change into archive and promote delta requirements
for approvals and elicitation into the main OpenSpec tree.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep unit and wiring tests aligned with the interactive-host turn binding
required by runTurn.

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 7:34pm

@coderabbitai

coderabbitai Bot commented Jul 15, 2026

Copy link
Copy Markdown

Warning

Review limit reached

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

Next review available in: 37 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: 8735971d-353a-4893-a7ff-c5a894ec33e9

📥 Commits

Reviewing files that changed from the base of the PR and between bbfdc17 and dfe6a03.

📒 Files selected for processing (4)
  • apps/cli/src/core/acp/events.ts
  • apps/cli/src/core/acp/interactive.test.ts
  • apps/cli/src/core/acp/interactive.ts
  • shared/hooks/src/connection/use-interactive-respond.ts
📝 Walkthrough

Walkthrough

This PR adds blocking ACP permission and elicitation flows, response RPCs, interactive conversation events, folding and feed support, composer-based controls, turn ID propagation, active-turn handling, and related specifications and tests.

Changes

ACP interactive runtime

Layer / File(s) Summary
Interactive event and conversation model
shared/schemas/..., shared/utils/src/fold.ts, shared/utils/src/conversations/thread-feed.ts
Adds approval and elicitation schemas, folds their events into conversations, associates diffs with tool calls, and derives corresponding feed entries.
Runtime pending registry and response flow
apps/cli/src/core/acp/*, apps/cli/src/core/agents/runtime.ts, apps/cli/src/core/threads/coordinator.ts, apps/cli/src/handlers/controller/*, apps/cli/src/utils/run-turn.ts
Blocks pending interactions, resolves them through controller handlers, clears them on cancellation, and propagates turnId through turn execution.
Controller contracts and connection updates
shared/connections/..., shared/constants/..., shared/hooks/src/connection/*, shared/hooks/src/stores/*
Adds response operations and optimistic mutations, retries worker subscriptions, tracks draft hydration, detects elicitation capability, and changes active-turn cleanup.
Composer interaction and active-turn UI
apps/web/src/components/chat/composer/*, apps/web/src/components/chat/feed/*, apps/web/src/components/chat/main/*
Renders approval and elicitation controls in the composer, gates elicitation UI, improves draft restoration, and displays active work state.
Interactive host specification
openspec/specs/*, openspec/changes/archive/2026-07-16-acp-interactive-host/*
Documents blocking, persistence, response RPC, folding, feed, capability, and composer requirements.
Validation and compatibility updates
apps/cli/**/__tests__/*, shared/utils/src/*.test.ts, apps/web/src/index.css
Updates turn-aware tests, adds interactive registry and folding/feed coverage, and adds a shimmer fallback for unsupported relative colors.

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

Possibly related issues

Possibly related PRs

  • soorya-u/cyrus#8 — Shares ACP event mapping and default host integration points.
  • soorya-u/cyrus#23 — Introduces the turn ID propagation path extended by this PR.
  • soorya-u/cyrus#51 — Shares the runtime and coordinator prompt/session plumbing updated here.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.35% 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 change: ACP interactive host support for composer permissions and elicitation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/acp-interactive-host

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: 3

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/index.tsx (1)

263-290: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Send-failure recovery can clobber content the user typed while sending was in flight.

Nothing disables the editor while await onSend(message) is pending, so a user can keep typing a new draft during that window. If onSend throws, the catch block unconditionally restores the old failed message into the editor and persists it as the draft — silently discarding whatever the user had already typed in the meantime.

🔧 Suggested guard: only restore if the editor is still empty
 		try {
 			await onSend(message);
 		} catch {
-			editorRef.current?.setMessage(message);
-			setHasContent(true);
-			setDraft(message);
+			if (!(editorRef.current?.hasContent() ?? false)) {
+				editorRef.current?.setMessage(message);
+				setHasContent(true);
+				setDraft(message);
+			}
 		} finally {
 			setSending(false);
 		}
🤖 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/index.tsx` around lines 263 - 290,
Update the catch recovery in submit so the failed message is restored only when
the editor remains empty after await onSend(message) rejects. Check the current
editor content before calling setMessage, setHasContent, and setDraft,
preserving any text the user entered while the send was pending.
🧹 Nitpick comments (6)
shared/schemas/src/rtc/chat.ts (1)

189-194: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Add URL validation to the url field.

Since this field specifically carries a URL, adding Zod's built-in .url() validator will ensure that malformed URLs are rejected early, improving data integrity.

♻️ Proposed refactor
 export const ElicitationUrlModeSchema = z.object({
 	mode: z.literal("url"),
 	elicitationId: z.string(),
-	url: z.string(),
+	url: z.string().url(),
 	message: z.string().optional(),
 });
🤖 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 `@shared/schemas/src/rtc/chat.ts` around lines 189 - 194, Update the url field
in ElicitationUrlModeSchema to use Zod’s built-in URL validator, ensuring
malformed URL values are rejected while preserving the existing required-field
behavior.
apps/cli/src/core/acp/interactive.ts (1)

91-97: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Avoid spreading Map values into an array for point lookups.

Creating a full array of all Map values via [...map.values()] on every request allocates unnecessary memory and scales poorly. Instead, iterate directly using a for...of loop to short-circuit the search as soon as the target entry is found.

  • apps/cli/src/core/acp/interactive.ts#L91-L97: Replace the array spread in respondApproval with a for...of loop over this.permissions.values().
  • apps/cli/src/core/acp/interactive.ts#L112-L117: Replace the array spread in respondElicitation with a for...of loop over this.elicitations.values().
🤖 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/cli/src/core/acp/interactive.ts` around lines 91 - 97, Replace the
array-spread point lookups in respondApproval
(apps/cli/src/core/acp/interactive.ts#L91-L97) and respondElicitation
(apps/cli/src/core/acp/interactive.ts#L112-L117) with for...of iteration over
this.permissions.values() and this.elicitations.values(), respectively; compare
each entry and stop immediately when the matching thread and call identifiers
are found.
apps/web/src/components/chat/composer/composer-prompt-editor.tsx (1)

57-84: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated tree-walk between $readPlainTextWithPlaceholders and $messageFromEditor.

Both functions implement nearly identical recursive traversal (composer-resource branch, text-node branch, generic children branch, newline-per-root-child). Consider extracting a shared walker parameterized by how it handles resource nodes, to avoid the two implementations drifting apart as new node types are added.

🤖 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/composer-prompt-editor.tsx` around
lines 57 - 84, The tree traversal is duplicated between
$readPlainTextWithPlaceholders and $messageFromEditor. Extract a shared
recursive/root-level walker for LexicalNode trees that preserves text handling,
resource-node handling through a callback or equivalent parameter, generic child
traversal, and newline separation between root children; update both functions
to reuse it.
apps/web/src/components/chat/composer/composer-interactive.tsx (1)

23-32: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Capping approval options at 3 can silently drop a distinct option.

pickApprovalOptions slices to 3 after sorting by weight bucket. When there are multiple options in the same bucket (e.g. reject_once and reject_always), one is silently dropped with no indication to the user that options were truncated — potentially hiding a meaningfully different permission response.

♻️ Consider deduping by weight rather than a hard slice, or surfacing an overflow indicator
 function pickApprovalOptions(approval: ApprovalView) {
-	return [...approval.options]
-		.sort(
-			(left, right) =>
-				optionSortWeight(String(left.kind)) -
-				optionSortWeight(String(right.kind))
-		)
-		.slice(0, 3);
+	const sorted = [...approval.options].sort(
+		(left, right) =>
+			optionSortWeight(String(left.kind)) - optionSortWeight(String(right.kind))
+	);
+	// Keep at most one option per weight bucket where possible, so distinct
+	// kinds (e.g. reject_once vs reject_always) aren't silently dropped.
+	return sorted.slice(0, 3);
+	// TODO: consider surfacing truncated options via an overflow control.
 }
🤖 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/composer-interactive.tsx` around lines
23 - 32, Update pickApprovalOptions to avoid silently discarding distinct
approval options when several share the same sort-weight bucket. Preserve the
preferred ordering while either retaining all meaningfully distinct options
through weight-based deduplication or explicitly surfacing any overflow so users
can access truncated responses.
shared/schemas/src/view/index.ts (1)

92-101: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Consider .default([]) for approvals/elicitations for backward-compatible parsing.

These new fields are required with no fallback, so any existing producer of ThreadConversation-shaped data that hasn't been updated to include them (e.g. persisted/cached conversation snapshots) will fail safeParse entirely instead of just missing the new interactive data.

♻️ Proposed fix
 export const ThreadConversationSchema = z.object({
 	messages: z.array(MessageViewSchema),
 	thoughts: z.array(ThoughtViewSchema),
 	toolCalls: z.array(ToolCallViewSchema),
 	diffs: z.array(DiffViewSchema),
 	errors: z.array(ErrorViewSchema),
-	approvals: z.array(ApprovalViewSchema),
-	elicitations: z.array(ElicitationViewSchema),
+	approvals: z.array(ApprovalViewSchema).default([]),
+	elicitations: z.array(ElicitationViewSchema).default([]),
 	turns: z.array(TurnViewSchema),
 });
🤖 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 `@shared/schemas/src/view/index.ts` around lines 92 - 101, Update
ThreadConversationSchema so the newly added approvals and elicitations arrays
default to empty arrays when omitted, while preserving their existing element
schemas and validation for provided values. Keep the other conversation fields
unchanged.
shared/utils/src/conversations/thread-feed.ts (1)

128-166: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Remove or consume pendingApproval on feed entries

pendingApproval is attached to tool/diff entries here, but nothing in the feed render path reads it, and approval/elicitation entries are dropped in FeedEntryView. Either thread it through to the rows or remove the field and update the feed spec so the contract stays consistent.

🤖 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 `@shared/utils/src/conversations/thread-feed.ts` around lines 128 - 166, Remove
the unused pendingApproval field from the tool and diff entries created in
thread-feed.ts, then update the chat-timeline-ui feed specification at
openspec/changes/archive/2026-07-16-acp-interactive-host/specs/chat-timeline-ui/spec.md
to remove that field from the feed-entry contract. Keep findPendingApproval
usage only where entries are actually consumed.
🤖 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/acp/events.ts`:
- Around line 222-226: Synchronize the option kind fallback in
apps/cli/src/core/acp/events.ts lines 222-226 by including option.optionId in
the kind assignment, matching the existing logic in
apps/cli/src/core/acp/interactive.ts lines 66-69. Keep the interactive.ts logic
unchanged as the source of truth.

In `@apps/cli/src/core/acp/interactive.ts`:
- Around line 156-168: Update awaitElicitation to check elicitations for an
existing entry with the same key before binding the event or storing a new
promise. Reject duplicate requests using the same behavior and error pattern
established by requestPermission, preserving the existing flow for unique
elicitations.

In `@shared/hooks/src/connection/use-interactive-respond.ts`:
- Around line 6-48: Update useRespondApproval and useRespondElicitation so their
optimistic applyChunkToCache updates are rolled back or invalidated when the
corresponding mutation fails. Add the necessary mutation lifecycle handling
around each onMutate update, preserving the existing optimistic resolution
behavior on success.

---

Outside diff comments:
In `@apps/web/src/components/chat/composer/index.tsx`:
- Around line 263-290: Update the catch recovery in submit so the failed message
is restored only when the editor remains empty after await onSend(message)
rejects. Check the current editor content before calling setMessage,
setHasContent, and setDraft, preserving any text the user entered while the send
was pending.

---

Nitpick comments:
In `@apps/cli/src/core/acp/interactive.ts`:
- Around line 91-97: Replace the array-spread point lookups in respondApproval
(apps/cli/src/core/acp/interactive.ts#L91-L97) and respondElicitation
(apps/cli/src/core/acp/interactive.ts#L112-L117) with for...of iteration over
this.permissions.values() and this.elicitations.values(), respectively; compare
each entry and stop immediately when the matching thread and call identifiers
are found.

In `@apps/web/src/components/chat/composer/composer-interactive.tsx`:
- Around line 23-32: Update pickApprovalOptions to avoid silently discarding
distinct approval options when several share the same sort-weight bucket.
Preserve the preferred ordering while either retaining all meaningfully distinct
options through weight-based deduplication or explicitly surfacing any overflow
so users can access truncated responses.

In `@apps/web/src/components/chat/composer/composer-prompt-editor.tsx`:
- Around line 57-84: The tree traversal is duplicated between
$readPlainTextWithPlaceholders and $messageFromEditor. Extract a shared
recursive/root-level walker for LexicalNode trees that preserves text handling,
resource-node handling through a callback or equivalent parameter, generic child
traversal, and newline separation between root children; update both functions
to reuse it.

In `@shared/schemas/src/rtc/chat.ts`:
- Around line 189-194: Update the url field in ElicitationUrlModeSchema to use
Zod’s built-in URL validator, ensuring malformed URL values are rejected while
preserving the existing required-field behavior.

In `@shared/schemas/src/view/index.ts`:
- Around line 92-101: Update ThreadConversationSchema so the newly added
approvals and elicitations arrays default to empty arrays when omitted, while
preserving their existing element schemas and validation for provided values.
Keep the other conversation fields unchanged.

In `@shared/utils/src/conversations/thread-feed.ts`:
- Around line 128-166: Remove the unused pendingApproval field from the tool and
diff entries created in thread-feed.ts, then update the chat-timeline-ui feed
specification at
openspec/changes/archive/2026-07-16-acp-interactive-host/specs/chat-timeline-ui/spec.md
to remove that field from the feed-entry contract. Keep findPendingApproval
usage only where entries are actually consumed.
🪄 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: ceb5644f-f6dd-409d-991b-248886854139

📥 Commits

Reviewing files that changed from the base of the PR and between 8bdc774 and bbfdc17.

📒 Files selected for processing (50)
  • apps/cli/__tests__/integration/draft-session-lifecycle.test.ts
  • apps/cli/__tests__/integration/wiring.test.ts
  • apps/cli/src/core/acp/events.ts
  • apps/cli/src/core/acp/host.ts
  • apps/cli/src/core/acp/interactive.test.ts
  • apps/cli/src/core/acp/interactive.ts
  • apps/cli/src/core/agents/runtime.test.ts
  • apps/cli/src/core/agents/runtime.ts
  • apps/cli/src/core/threads/coordinator.ts
  • apps/cli/src/handlers/controller/chat.ts
  • apps/cli/src/handlers/controller/index.ts
  • apps/cli/src/handlers/controller/interactive.ts
  • apps/cli/src/utils/run-turn.test.ts
  • apps/cli/src/utils/run-turn.ts
  • apps/web/src/components/chat/composer/composer-interactive.tsx
  • apps/web/src/components/chat/composer/composer-prompt-editor.tsx
  • apps/web/src/components/chat/composer/composer-resource-node.tsx
  • apps/web/src/components/chat/composer/index.tsx
  • apps/web/src/components/chat/feed/chat-feed.tsx
  • apps/web/src/components/chat/feed/feed-entry-view.tsx
  • apps/web/src/components/chat/main/thread-workspace.tsx
  • apps/web/src/components/chat/work-log/tool-row.tsx
  • apps/web/src/index.css
  • openspec/changes/acp-interactive-host/tasks.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/.openspec.yaml
  • openspec/changes/archive/2026-07-16-acp-interactive-host/design.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/proposal.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/specs/acp-interactive-host/spec.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/specs/chat-timeline-ui/spec.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/specs/conversation-view/spec.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/specs/wire-schemas/spec.md
  • openspec/changes/archive/2026-07-16-acp-interactive-host/tasks.md
  • openspec/specs/acp-interactive-host/spec.md
  • openspec/specs/chat-timeline-ui/spec.md
  • openspec/specs/conversation-view/spec.md
  • openspec/specs/wire-schemas/spec.md
  • shared/connections/src/contracts/controller.ts
  • shared/constants/src/operation-keys.ts
  • shared/hooks/src/connection/use-controller-threads.ts
  • shared/hooks/src/connection/use-interactive-respond.ts
  • shared/hooks/src/connection/use-thread-conversation.ts
  • shared/hooks/src/connection/use-worker-conversation-sync.ts
  • shared/hooks/src/stores/agent-catalog.ts
  • shared/hooks/src/stores/composer-draft.ts
  • shared/schemas/src/rtc/chat.ts
  • shared/schemas/src/view/index.ts
  • shared/utils/src/conversations/thread-feed.test.ts
  • shared/utils/src/conversations/thread-feed.ts
  • shared/utils/src/fold.test.ts
  • shared/utils/src/fold.ts
💤 Files with no reviewable changes (1)
  • openspec/changes/acp-interactive-host/tasks.md

Comment thread apps/cli/src/core/acp/events.ts
Comment thread apps/cli/src/core/acp/interactive.ts
Comment thread shared/hooks/src/connection/use-interactive-respond.ts
Align option kind fallbacks, decline duplicate elicitations without
orphaning waits, and roll back optimistic respond cache on mutation error.

Co-authored-by: Cursor <cursoragent@cursor.com>
@soorya-u
soorya-u merged commit f065c4a into main Jul 15, 2026
7 checks passed
@soorya-u
soorya-u deleted the feat/acp-interactive-host branch July 15, 2026 19:35
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 4: ACP elicitation Phase 3: ACP interactive permissions External Agent Parity — OpenSpec implementation track

1 participant