feat(cli): inherit local TUI permission mode on local→remote switch

Add permission mode tracking across the local→remote switch so mode changes
made inside the interactive Claude TUI (shift+tab) are inherited when
launching remote. Previously, a mode picked in local TUI was invisible to
remote sessions.

Implementation:
- generateHookSettings: add trackPermissionMode option to register UserPromptSubmit
  and PreToolUse hooks (their payloads carry permission_mode; SessionStart's does
  not). Export buildHookSettings for testing and make matcher optional.
- New hookPermissionMode.ts: normalizer for hook permission_mode → HAPI mode
  ('manual' → 'default'; unknown modes like 'dontAsk' → null/ignored).
- runClaude.ts: generate a second, local-TUI-only hook settings file with
  trackPermissionMode enabled (remote SDK process keeps the SessionStart-only
  file — these hooks block Claude per prompt/tool, and remote state is owned
  by hub/RPC). Hook callback inherits mode when session.mode === 'local': updates
  currentPermissionMode, syncs session, pushes keepalive, emits permission-mode-
  changed event.
- session.ts, loop.ts, claudeLocalLauncher.ts: plumb localHookSettingsPath
  (defaults to hookSettingsPath when not provided).
This commit is contained in:
weishu
2026-08-01 23:40:46 +08:00
parent 9727f7e4a0
commit 3e61d276bd
9 changed files with 138 additions and 15 deletions
+4
View File
@@ -18,6 +18,8 @@ export class Session extends AgentSessionBase<EnhancedMode> {
readonly mcpServers: Record<string, any>;
readonly allowedTools?: string[];
readonly hookSettingsPath: string;
/** Settings for the interactive TUI: also forwards permission-mode-carrying hooks. */
readonly localHookSettingsPath: string;
readonly startedBy: 'runner' | 'terminal';
readonly startingMode: 'local' | 'remote';
localLaunchFailure: LocalLaunchFailure | null = null;
@@ -38,6 +40,7 @@ export class Session extends AgentSessionBase<EnhancedMode> {
startedBy: 'runner' | 'terminal';
startingMode: 'local' | 'remote';
hookSettingsPath: string;
localHookSettingsPath?: string;
permissionMode?: PermissionMode;
model?: SessionModel;
effort?: SessionEffort;
@@ -67,6 +70,7 @@ export class Session extends AgentSessionBase<EnhancedMode> {
this.mcpServers = opts.mcpServers;
this.allowedTools = opts.allowedTools;
this.hookSettingsPath = opts.hookSettingsPath;
this.localHookSettingsPath = opts.localHookSettingsPath ?? opts.hookSettingsPath;
this.startedBy = opts.startedBy;
this.startingMode = opts.startingMode;
this.permissionMode = opts.permissionMode;