| refactor: rename Polit/PolitDeck to Pilot/PilotDeck across entire codebase
Automated global rename covering all case variants:
- PolitDeck → PilotDeck, politdeck → pilotdeck, POLITDECK → PILOTDECK
- Polit → Pilot, polit → pilot, POLIT → PILOT, politDeck → pilotDeck
Includes:
- 648 content replacements across 200+ source files
- 24 file renames + 3 directory renames (src/polit→pilot, tests/polit→pilot, docs/polit-config→pilot-config)
- package.json name, bin, env vars updated
- package-lock.json regenerated
- "Politely" in server-manager.ts preserved via placeholder mechanism
- All 587 unit tests pass, tsc --noEmit clean
- E2E tests verified against real OpenRouter API (model, tool-use, context, lifecycle hooks)
Co-authored-by: Cursor <cursoragent@cursor.com>
| 24 天前 |
| refactor: rename Polit/PolitDeck to Pilot/PilotDeck across entire codebase
Automated global rename covering all case variants:
- PolitDeck → PilotDeck, politdeck → pilotdeck, POLITDECK → PILOTDECK
- Polit → Pilot, polit → pilot, POLIT → PILOT, politDeck → pilotDeck
Includes:
- 648 content replacements across 200+ source files
- 24 file renames + 3 directory renames (src/polit→pilot, tests/polit→pilot, docs/polit-config→pilot-config)
- package.json name, bin, env vars updated
- package-lock.json regenerated
- "Politely" in server-manager.ts preserved via placeholder mechanism
- All 587 unit tests pass, tsc --noEmit clean
- E2E tests verified against real OpenRouter API (model, tool-use, context, lifecycle hooks)
Co-authored-by: Cursor <cursoragent@cursor.com>
| 24 天前 |
| feat(gateway): wire interactive Web UI permission flow end-to-end
The PolitDeck gateway used to expose a GatewayPermissionBus with
getPermissionBus() / consume() / rejectSession(), but nobody ever
called bus.register(...) — agent runtime PermissionRequest events
were never bridged to the Web UI's banner, and permissionDecide()
always returned { delivered: false }. The UI's "Allow + remember"
button only wrote allowedTools to localStorage; that value
only took effect on the *next* turn (via syncPermissionRules at
runChatViaGateway entry), so within the current turn the agent
saw stale rules and the prompt looped forever. On top of that,
PermissionRuntime.decide consulted tool.checkPermissions()
*before* user-configured allow rules, so tools that hardcode ask
(web_fetch, web_search) overrode an explicit grant.
This patch closes the loop:
* src/gateway/permission/createGatewayPermissionHook.ts (new)
Callback hook handler that emits a permission_request GatewayEvent
into the active submitTurn stream, registers a pending entry with
the bus, and awaits the user's decision. On allow + remember it
mutates the live session permissionRules.allow array (shared by
reference with the agent's PermissionContext) so subsequent calls
to the same tool inside the same turn bypass the ask path.
If the session has no active turn sink the hook denies immediately
— better a clean denial than a silent hang.
* src/gateway/client/InProcessGateway.ts
Deduplicate the two competing emitForSession() definitions and
keep the boolean-returning version. The hook now uses the return
value to detect "nobody listening" and deny.
* src/extension/hooks/execution/HookRuntime.ts
Expose getCallbackExecutor() so external code can register
callback hooks (specifically the permission gateway hook) before
the runtime dispatches events.
* src/cli/createLocalGateway.ts
In createSession, inject a per-session callback hook on the
PermissionRequest event pointing at the gateway permission
callback, and register the handler with that session's
CallbackHookExecutor — wiring the gateway-side bus, the live
permissionRules array, and the emit sink together so each session
gets its own properly-scoped permission round-trip.
* src/permission/decision/PermissionRuntime.ts
Reorder decide() so user-configured allow rules are consulted
*before* tool.checkPermissions(). This lets an explicit
"Allow + remember" grant defeat tools that hardcode ask. Deny rules
still beat allow rules (checked first), so a user can't be tricked
into granting a tool that's explicitly denied at config / session
scope.
* ui/src/components/chat/hooks/useChatComposerState.ts
* ui/src/components/chat/utils/chatPermissions.ts
Drop the provider !== 'claude' gate from handleGrantToolPermission
and getPilotDeckPermissionSuggestion. After the PolitDeck-only
migration every provider routes through the same gateway
PermissionContext, so the "Permission added" UI is useful for
DeepSeek / OpenAI / Anthropic / etc., not just Claude.
End-to-end result: agent triggers ask → Web UI shows banner →
user clicks Allow + remember → hook resolves with allow → live
permissionRules.allow is mutated → next decide() walks the allow
branch immediately, with no per-turn ceremony. Same-tool follow-up
calls in the same turn no longer re-prompt; new turns keep working
because syncPermissionRules continues to mirror localStorage on
entry.
Co-authored-by: Cursor <cursoragent@cursor.com>
| 21 天前 |
| feat(hooks): add PreModelRequest lifecycle hook for model provider/model observability
Wire dispatchLifecycle before yield model_request_started so plugins
can observe the runtime provider and model on every model call.
Co-authored-by: Cursor <cursoragent@cursor.com>
| 20 天前 |