fix(cursor): CreatePlan Yes accepts and continues task (nested outcome + plan→execute) (#1097)

* fix(cursor): nest ACP extension outcome so plan approvals aren't cancelled

Cursor's ACP blocking extension methods (cursor/ask_question,
cursor/create_plan) expect the JSON-RPC result to nest the outcome under
an `outcome` key, e.g. `{ outcome: { outcome: "accepted" } }`. The
adapter returned it flat (`{ outcome: "accepted" }`), so Cursor read
`response.outcome.outcome` as undefined and fell back to a cancellation
— an approved plan was relayed to the agent as `User cancelled`, making
plan mode unusable over HAPI for Cursor sessions.

Wrap every ask_question / create_plan response in the nested envelope
and add regression tests asserting the exact wire shape for the
affirmative approval -> CreatePlan path (plus approved_for_session,
reject, and abort).

Fixes #79

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

* fix(cursor): continue task after CreatePlan Yes (plan→execute)

Nested ACP accept alone is not a complete fix: Yes unblocked create_plan
but the prompt turn still ended with the plan "done" and no execution.
Mirror Claude ExitPlanMode: on accept, leave plan/ask for an executable
mode and queue a continue prompt so the original user task keeps going.

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

* fix(cursor): sync runCursor enqueue mode after CreatePlan accept

Codex Major on #1097: setPermissionMode alone left runCursor's
currentPermissionMode stale, so the next user message could re-enter
plan/ask after Yes. Notify onPermissionModeChanged from CursorSession
so the enqueue source of truth stays aligned with the session.

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

---------

Co-authored-by: Debian <heavygee@oos-linux.in.lockhouse>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
HeavyGee
2026-07-27 12:57:31 +08:00
committed by GitHub
co-authored by Cursor Debian
parent 311e0cef55
commit e4cc3916c8
10 changed files with 245 additions and 27 deletions
+4 -1
View File
@@ -31,6 +31,8 @@ interface LoopOptions {
model?: string;
sessionMetadata?: Metadata | null;
onSessionReady?: (session: CursorSession) => void;
/** Keep runCursor's enqueue mode in sync when the session leaves plan/ask. */
onPermissionModeChanged?: (mode: PermissionMode) => void;
}
export async function loop(opts: LoopOptions): Promise<void> {
@@ -52,7 +54,8 @@ export async function loop(opts: LoopOptions): Promise<void> {
cursorWorktree: opts.cursorWorktree,
cursorAddDirs: opts.cursorAddDirs,
model: opts.model,
permissionMode: opts.permissionMode ?? 'default'
permissionMode: opts.permissionMode ?? 'default',
onPermissionModeChanged: opts.onPermissionModeChanged
});
await runLocalRemoteSession({