[Fix] kimi-code provider: register approval handler so hosted sessions can exit plan mode - #2360
[Fix] kimi-code provider: register approval handler so hosted sessions can exit plan mode#2360L42y wants to merge 1 commit into
Conversation
…an exit plan mode Hosted sessions run headless with permission "yolo" and no interactive approval surface. The SDK's ExitPlanMode review policy escalates plan exits to an approval request in every mode except "auto", and the headless RPC cancels handler-less requests, so a session that entered plan mode deadlocked: every ExitPlanMode was auto-dismissed and plan mode kept denying all writes. Register an approval handler on session create and resume that approves plan exits (restoring the yolo posture) and cancels everything else, matching the previous handler-less behavior.
baixiaohang
left a comment
There was a problem hiding this comment.
Recommendation: approve
- Rationale: The change closes the hosted Kimi plan-mode deadlock at the provider boundary while preserving fail-closed behavior for every non-plan approval request.
Risk level: A
- Path baseline: includes
packages/client/**-> A - Semantic lift: none
PR summary
- Author / repo: L42y / first-tree-ai/first-tree
- Problem: A hosted Kimi agent that enters plan mode cannot obtain interactive approval, so every exit attempt is cancelled and all subsequent writes remain blocked.
- Approach: Register one hosted-session approval handler before the first prompt on both create and resume. It approves plan-exit requests and cancels all other requests with explicit hosted-session feedback.
- Impacted modules:
packages/client/src/providers/kimi-code/
Review findings
✅ 1. The pinned SDK confirms that valid ExitPlanMode calls require approval outside auto mode and that a missing handler returns cancelled; the fix addresses that exact boundary.
✅ 2. Registration covers both session creation and restoration before provider input, and the SDK clears the handler when the session closes.
✅ 3. Non-plan approvals remain fail closed, so the change does not broaden the hosted runtime's general approval surface.
Action taken
- Approved the unchanged head
f213bc5e8ed0485a6d2edf7ae5cd29f4888fc489after explicit maintainer authorization.
yuezengwu
left a comment
There was a problem hiding this comment.
Reviewed exact head f213bc5e8ed0485a6d2edf7ae5cd29f4888fc489.
The provider registers the hosted approval handler before the first prompt on both create and resume. The pinned SDK evidence confirms that non-auto plan exits are otherwise routed through approval and that missing handlers return cancelled; SDK session close also clears the handler. Non-plan approval requests remain fail closed.
Independent validation in a clean detached worktree:
pnpm --filter @first-tree/client exec vitest run src/providers/kimi-code/__tests__/handler.test.ts— 38 passedpnpm --filter @first-tree/client typecheck— passedpnpm exec biome check packages/client/src/providers/kimi-code/index.ts packages/client/src/providers/kimi-code/__tests__/handler.test.ts— passedgit diff --check— passed
Symptom
A hosted kimi-code agent session deadlocked in plan mode: the agent called
ExitPlanMode9 times and every call was dismissed with the synthetic result "Plan approval dismissed. Plan mode remains active." Plan mode then kept denying all writes (CronCreate,Edit, and every other write tool), so the hosted agent could make no progress at all.Root cause
packages/client/src/providers/kimi-code/index.ts) runs headless sessions withpermission: "yolo"and never registers an approval handler.@botiverse/kimi-code-sdk,ExitPlanModeReviewAskPermissionPolicyescalatesExitPlanModeto an approval request in every permission mode except"auto"— including"yolo".requestApprovalreturns{decision: "cancelled", feedback: "No approval handler registered."}when no handler is registered.Fix
Register a module-level approval handler on every kimi-code session, on both the create and resume paths:
toolName === "ExitPlanMode"ordisplay.kind === "plan_review"), return{ decision: "approved" }— restoring the intended yolo posture for hosted sessions.{ decision: "cancelled", feedback: "No interactive approval surface in hosted sessions." }— matching the previous handler-less behavior for everything else.First Tree code only; the SDK and
patches/are untouched.Test coverage
packages/client/src/providers/kimi-code/__tests__/handler.test.ts:FakeSessiongains asetApprovalHandlerspy.startandresume, the handler is registered; invoking it with anExitPlanMode/plan_reviewrequest returns{ decision: "approved" }; invoking it with a non-plan request (Bash) returnscancelledwith the hosted-session feedback.Verification
pnpm --filter @first-tree/client exec vitest run src/providers/kimi-code/__tests__/handler.test.ts— all tests pass (including the new one).pnpm --filter @first-tree/client typecheck— clean.biome checkon the two touched files — clean.