handsoff 0.1.1 → 0.1.2-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +63 -34
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/process.js +1032 -136
- package/dist/gateway/process.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/attach.ts","../../src/shared/settings-merge.ts","../../src/shared/credentials.ts","../../src/config.ts","../../src/i18n/index.ts","../../src/i18n/locales/en.ts","../../src/cli/init.ts","../../src/cli/wizard/engine.ts","../../src/cli/wizard/state.ts","../../src/cli/wizard/applicator.ts","../../src/cli/wizard/detectors/claude.ts","../../src/cli/wizard/detectors/codex.ts","../../src/cli/wizard/prompts.ts","../../src/cli/wizard/steps/cli.ts","../../src/cli/wizard/detectors/channel.ts","../../src/cli/wizard/steps/channel-menu.ts","../../src/cli/wizard/steps/channel-config.ts","../../src/cli/wizard/steps/channel-notify.ts","../../src/cli/wizard/steps/agent-select.ts","../../src/shared/channelInstance.ts","../../src/cli/wizard/steps/channel-select.ts","../../src/cli/wizard/steps/binding-confirm.ts","../../src/cli/wizard/steps/pair-continue.ts","../../src/cli/daemon.ts","../../src/shared/pidfile.ts","../../src/cli/wizard/steps/final.ts","../../src/cli/logs.ts","../../src/cli/status.ts","../../src/cli/stop.ts","../../src/cli/gateway.ts","../../src/cli/debug/index.ts","../../src/cli/agent/claude.ts","../../src/cli/agent/codex.ts","../../src/shared/logger.ts","../../src/cli/agent/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { attachCommand } from './attach.js';\nimport { initCommand } from './init.js';\nimport { logsCommand } from './logs.js';\nimport { statusCommand } from './status.js';\nimport { stopCommand } from './stop.js';\nimport { gatewayCommand } from './gateway.js';\nimport { debugCommand } from './debug/index.js';\nimport { registerAgentCommands } from './agent/index.js';\n\nconst program = new Command();\n\nprogram\n .name('handsoff')\n .description('Leave your desk, not your code. Remote control for AI coding assistants via messaging platforms')\n .version('0.1.0');\n\nprogram.addCommand(attachCommand);\nprogram.addCommand(debugCommand);\nprogram.addCommand(initCommand);\nprogram.addCommand(logsCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(stopCommand);\nprogram.addCommand(gatewayCommand);\n\n// Register agent shortcut commands (e.g., handsoff claude)\nregisterAgentCommands(program);\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport { mergeHooks } from '../shared/settings-merge.js';\nimport { getHookToken } from '../shared/credentials.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { loadConfig } from '../config.js';\nimport { t } from '../i18n/index.js';\n\n// TODO: These will be migrated to adapters/agent/claude.ts\ntype HookEntry = {\n matcher: string;\n hooks: Array<{ type: string; url: string }>;\n};\n\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nfunction backupSettings(settingsPath: string): void {\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(settingsPath)) {\n writeFileSync(backupPath, readFileSync(settingsPath, 'utf-8'));\n }\n}\n\nfunction writeSettings(settingsPath: string, settings: Record<string, unknown>): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n}\n\nfunction getGatewayBaseUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n\nasync function checkGatewayHealth(port: number): Promise<boolean> {\n try {\n const response = await fetch(`${getGatewayBaseUrl(port)}/health`, {\n method: 'GET',\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nfunction generateHooksConfig(token: string, port: number): Record<string, HookEntry[]> {\n const baseUrl = `${getGatewayBaseUrl(port)}/hook/${token}`;\n\n // Create hook entries with empty matcher (matches all)\n const createHookEntry = (event: string): HookEntry => ({\n matcher: '',\n hooks: [{ type: 'http', url: `${baseUrl}/${event}` }],\n });\n\n return {\n Stop: [createHookEntry('Stop')],\n SessionStart: [createHookEntry('SessionStart')],\n SessionEnd: [createHookEntry('SessionEnd')],\n UserPromptSubmit: [createHookEntry('UserPromptSubmit')],\n PermissionRequest: [createHookEntry('PermissionRequest')],\n };\n}\n\nexport const attachCommand = new Command('attach')\n .description('Attach an agent to the Gateway')\n .argument('<agent-type>', 'Agent type (e.g., claude)')\n .action(async (agentType: string) => {\n // Load config first to get the correct port\n const config = loadConfig();\n const gatewayPort = config.general.hook_server_port;\n\n // Step 1: Check Gateway is running\n console.log(t('cli.attach.checking'));\n const isHealthy = await checkGatewayHealth(gatewayPort);\n\n if (!isHealthy) {\n console.error(t('cli.attach.notRunning'));\n process.exit(1);\n }\n\n console.log(t('cli.attach.running'));\n\n // Step 2: Load hook token from credentials\n const hookToken = getHookToken();\n if (!hookToken) {\n console.error(t('cli.attach.tokenNotFound'));\n process.exit(1);\n }\n\n const token = hookToken.substring(0, 8) + '...';\n console.log(t('cli.attach.usingToken', { token }));\n\n // Step 3: Backup existing settings\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n\n if (!existsSync(backupPath)) {\n backupSettings(settingsPath);\n console.log(t('cli.attach.settingsBacked', { path: backupPath }));\n }\n\n // Step 4: Merge hooks into settings.json\n console.log(t('cli.attach.configuringHooks'));\n\n // Read current settings\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n }\n\n // Generate hooks config with the persistent token and port\n const hooksConfig = generateHooksConfig(hookToken, gatewayPort);\n\n // Merge hooks (preserving existing non-handsoff hooks)\n const mergedSettings = mergeHooks(currentSettings, hooksConfig);\n writeSettings(settingsPath, mergedSettings);\n\n // Step 5: Display success message\n console.log('');\n console.log(t('cli.attach.attached', { agent: agentType }));\n console.log('');\n console.log(t('cli.attach.connected'));\n console.log(t('cli.attach.start'));\n console.log('');\n console.log(t('cli.attach.forwarding'));\n console.log(t('cli.attach.tipStatus'));\n console.log(t('cli.attach.tipDetach'));\n });\n","// Inner hook configuration (the actual HTTP hook)\nexport interface HookConfig {\n type: string;\n url: string;\n}\n\n// Outer hook entry with matcher (Claude Code's format)\nexport interface HookEntry {\n matcher: string;\n hooks: HookConfig[];\n}\n\nexport interface ClaudeSettings {\n hooks?: Record<string, HookEntry[]>;\n [key: string]: unknown;\n}\n\n// Check if a hook config is from handsoff (by URL pattern)\nexport function isHandsoffHook(hook: HookConfig): boolean {\n return hook.type === 'http' && hook.url.includes('/hook/');\n}\n\n// Check if a hook entry contains handsoff hooks\nexport function isHandsoffEntry(entry: HookEntry): boolean {\n return entry.hooks.some(hook => isHandsoffHook(hook));\n}\n\nexport function extractTokenFromUrl(url: string): string | null {\n const match = url.match(/\\/hook\\/([^/]+)/);\n return match?.[1] || null;\n}\n\nexport function removeHandsoffHooks(settings: ClaudeSettings): ClaudeSettings {\n if (!settings.hooks) return settings;\n\n const cleanedHooks: Record<string, HookEntry[]> = {};\n\n for (const [eventName, entries] of Object.entries(settings.hooks)) {\n // Filter out entries that contain handsoff hooks\n const cleanedEntries = entries.filter(entry => !isHandsoffEntry(entry));\n if (cleanedEntries.length > 0) {\n cleanedHooks[eventName] = cleanedEntries;\n }\n }\n\n return { ...settings, hooks: cleanedHooks };\n}\n\nexport function mergeHooks(\n existing: ClaudeSettings,\n newHooks: Record<string, HookEntry[]>\n): ClaudeSettings {\n // Remove all existing handsoff hooks\n const cleaned = removeHandsoffHooks(existing);\n\n const mergedHooks: Record<string, HookEntry[]> = {};\n\n // Get all event names from both existing (cleaned) and new hooks\n const allEvents = new Set([\n ...Object.keys(cleaned.hooks || {}),\n ...Object.keys(newHooks)\n ]);\n\n for (const eventName of allEvents) {\n const existingEntries = cleaned.hooks?.[eventName] || [];\n const newEntries = newHooks[eventName] || [];\n\n // Filter out any new entries that already exist with same URL\n const existingUrls = new Set(\n existingEntries.flatMap(e => e.hooks.map(h => h.url))\n );\n const uniqueNewEntries = newEntries.filter(\n entry => !entry.hooks.some(h => existingUrls.has(h.url))\n );\n\n const merged = [...uniqueNewEntries, ...existingEntries];\n\n // Only include event if it has hooks\n if (merged.length > 0) {\n mergedHooks[eventName] = merged;\n }\n }\n\n return { ...cleaned, hooks: mergedHooks };\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\n\nexport interface Credentials {\n version: string;\n hookToken: string;\n createdAt: string;\n}\n\nconst CREDENTIALS_VERSION = '1';\nconst DEFAULT_TOKEN_LENGTH = 8;\n\nfunction getCredentialsPath(): string {\n return join(homedir(), '.handsoff', 'credentials.json');\n}\n\nfunction generateToken(): string {\n return randomBytes(DEFAULT_TOKEN_LENGTH).toString('hex');\n}\n\nexport function loadCredentials(): Credentials | null {\n const path = getCredentialsPath();\n\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n console.error(`Failed to load credentials from ${path}:`, error);\n return null;\n }\n}\n\nexport function saveCredentials(credentials: Credentials): void {\n const path = getCredentialsPath();\n // Ensure directory exists before writing\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(credentials, null, 2), { mode: 0o600 });\n}\n\nexport function getOrCreateHookToken(): string {\n const existing = loadCredentials();\n\n if (existing?.hookToken) {\n return existing.hookToken;\n }\n\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n\nexport function getHookToken(): string | null {\n return loadCredentials()?.hookToken ?? null;\n}\n\nexport function resetCredentials(): string {\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport dotenv from 'dotenv';\n// Note: Notification types removed - using EventBus architecture now\n\n// Load .env file if exists\ndotenv.config();\n\nexport interface GeneralConfig {\n default_agent: string;\n log_level: string;\n hook_server_port: number;\n}\n\nexport interface TelegramConfig {\n enabled: boolean;\n bot_token: string;\n allowed_users: string[];\n notify_types?: string[];\n}\n\nexport interface FeishuConfig {\n enabled: boolean;\n app_id: string;\n app_secret: string;\n allowed_users?: string[];\n notify_types?: string[];\n}\n\nexport interface ClaudeAgentConfig {\n adapter: string;\n binary: string;\n work_dir: string;\n model: string;\n permission_mode: string;\n}\n\nexport interface AgentPermissionConfig {\n lowRiskTools: string[];\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n sandbox_mode: string;\n}\n\nexport interface LoggerConfig {\n enabled: boolean;\n notify_types?: string[];\n}\n\nexport interface PermissionConfig {\n timeout_ms: number;\n default_on_timeout: 'allow' | 'deny';\n}\n\nexport interface ChannelConfig {\n logger?: LoggerConfig;\n telegram?: TelegramConfig;\n feishu?: FeishuConfig;\n permission?: PermissionConfig;\n}\n\nexport interface AppChannelConfig {\n enabled: boolean;\n channel_id: string;\n auth_token: string;\n heartbeat_interval_ms?: number;\n notify_types?: string[];\n}\n\nexport interface ChannelsConfig {\n app?: AppChannelConfig;\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig & { permission?: AgentPermissionConfig };\n codex?: CodexAgentConfig;\n}\n\nexport interface BindingsConfig {\n claude?: string; // \"channelType:channelInstanceId\" e.g. \"telegram:abc123\"\n codex?: string;\n}\n\nexport interface Config {\n general: GeneralConfig;\n channel: ChannelConfig;\n channels?: ChannelsConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n default_agent: 'claude',\n log_level: 'info',\n hook_server_port: 9876,\n },\n channel: {\n logger: {\n enabled: true,\n },\n telegram: {\n enabled: true,\n bot_token: '',\n allowed_users: [],\n },\n feishu: {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [],\n notify_types: [],\n },\n permission: {\n timeout_ms: 300000, // 5 minutes\n default_on_timeout: 'deny',\n },\n },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n permission: {\n lowRiskTools: ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'],\n },\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n sandbox_mode: '',\n },\n },\n channels: {},\n bindings: {},\n};\n\nfunction getConfigPath(): string {\n return join(homedir(), '.handsoff', 'config.toml');\n}\n\nfunction mergeWithDefaults(raw: any): Config {\n return {\n general: {\n ...DEFAULT_CONFIG.general,\n ...(raw.general || {}),\n hook_server_port: parseInt(\n process.env.HANDSOFF_HOOK_SERVER_PORT ||\n String(raw.general?.hook_server_port || DEFAULT_CONFIG.general.hook_server_port),\n 10\n ),\n },\n channel: {\n logger: {\n ...DEFAULT_CONFIG.channel.logger,\n ...(raw.channel?.logger || {}),\n notify_types: raw.channel?.logger?.notify_types,\n },\n telegram: {\n ...DEFAULT_CONFIG.channel.telegram,\n ...(raw.channel?.telegram || {}),\n allowed_users: (raw.channel?.telegram?.allowed_users || []).map(String),\n bot_token:\n process.env.HANDSOFF_TELEGRAM_BOT_TOKEN ||\n raw.channel?.telegram?.bot_token ||\n '',\n notify_types: raw.channel?.telegram?.notify_types,\n },\n feishu: {\n ...DEFAULT_CONFIG.channel.feishu,\n ...(raw.channel?.feishu || {}),\n allowed_users: raw.channel?.feishu?.allowed_users || [],\n app_id:\n process.env.HANDSOFF_FEISHU_APP_ID || raw.channel?.feishu?.app_id || '',\n app_secret:\n process.env.HANDSOFF_FEISHU_APP_SECRET ||\n raw.channel?.feishu?.app_secret ||\n '',\n notify_types: raw.channel?.feishu?.notify_types,\n },\n permission: {\n ...DEFAULT_CONFIG.channel.permission,\n ...(raw.channel?.permission || {}),\n // Support env var override\n timeout_ms: parseInt(\n process.env.HANDSOFF_PERMISSION_TIMEOUT_MS ||\n String(\n raw.channel?.permission?.timeout_ms ||\n DEFAULT_CONFIG.channel.permission!.timeout_ms\n ),\n 10\n ),\n default_on_timeout:\n (process.env.HANDSOFF_PERMISSION_DEFAULT as 'allow' | 'deny') ||\n raw.channel?.permission?.default_on_timeout ||\n DEFAULT_CONFIG.channel.permission!.default_on_timeout,\n },\n },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n permission: {\n ...DEFAULT_CONFIG.agent.claude!.permission,\n ...(raw.agent?.claude?.permission || {}),\n },\n },\n codex: {\n ...DEFAULT_CONFIG.agent.codex!,\n ...(raw.agent?.codex || {}),\n command: raw.agent?.codex?.command\n ? raw.agent.codex.command\n : DEFAULT_CONFIG.agent.codex!.command,\n work_dir: raw.agent?.codex?.work_dir || DEFAULT_CONFIG.agent.codex!.work_dir,\n model: raw.agent?.codex?.model || DEFAULT_CONFIG.agent.codex!.model,\n approval_policy: raw.agent?.codex?.approval_policy || DEFAULT_CONFIG.agent.codex!.approval_policy,\n sandbox_mode: raw.agent?.codex?.sandbox_mode || DEFAULT_CONFIG.agent.codex!.sandbox_mode,\n },\n },\n channels: {\n ...DEFAULT_CONFIG.channels,\n ...(raw.channels || {}),\n app: raw.channels?.app\n ? {\n enabled: raw.channels.app.enabled === true,\n channel_id: String(raw.channels.app.channel_id || ''),\n auth_token: String(raw.channels.app.auth_token || ''),\n heartbeat_interval_ms: raw.channels.app.heartbeat_interval_ms\n ? parseInt(String(raw.channels.app.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channels.app.notify_types)\n ? raw.channels.app.notify_types.map(String)\n : undefined,\n }\n : DEFAULT_CONFIG.channels?.app,\n },\n bindings: {\n ...DEFAULT_CONFIG.bindings,\n ...(raw.bindings || {}),\n },\n };\n}\n\nexport function loadConfig(): Config {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return DEFAULT_CONFIG;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const raw = TOML.parse(content) as any;\n return mergeWithDefaults(raw);\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return DEFAULT_CONFIG;\n }\n}\n","// src/i18n/index.ts\nimport './types.js';\nimport i18next from 'i18next';\nimport en from './locales/en.js';\n\nconst lng = process.env.HANDSOFF_LANG ?? 'en';\n\ni18next.init({\n initImmediate: false,\n lng,\n fallbackLng: 'en',\n resources: { en: { translation: en } },\n interpolation: { escapeValue: false },\n});\n\nexport const t = i18next.t.bind(i18next);\n","// src/i18n/locales/en.ts\nexport default {\n wizard: {\n section: {\n cli: '[ CLI Configuration ]',\n channel: '[ Channel Configuration ]',\n complete: '[ Setup Complete ]',\n },\n cli: {\n runAgain: 'Run init again when Claude Code is installed.',\n detected: 'Claude Code detected.',\n hooksInstalled: 'Hooks already installed.',\n hooksNotInstalled: 'Hooks not installed.',\n hooksTokenMismatch: 'Hooks have outdated token - reconfiguration required.',\n actionQuestion: 'Select action:',\n injectAction: 'Inject hooks configuration',\n updateAction: 'Update hooks configuration',\n backAction: 'Back',\n hookCheckbox: 'Select hooks:',\n noHooksSelected: 'No hooks selected, skipping injection.',\n injecting: 'Injecting hooks...',\n injected: 'Hooks injected',\n failed: 'Failed: {{error}}',\n },\n channel: {\n configuring: 'Configuring {{channel}}',\n telegram: {\n botToken: 'Telegram bot token:',\n allowedUsers: 'Allowed Telegram user IDs (comma-separated):',\n testing: 'Testing Telegram connection...',\n connected: 'Connected to Telegram',\n sendingTest: 'Sending test message...',\n testSent: 'Test message sent',\n testContent: 'Handsoff test message',\n testWarning: 'Could not send test message (user may not have messaged bot yet)',\n apiError: 'API error: {{status}}',\n connFailed: 'Connection failed: {{error}}',\n },\n feishu: {\n appId: 'Feishu App ID:',\n appSecret: 'Feishu App Secret:',\n allowedUsers: 'Allowed User IDs (comma-separated, e.g., ou_xxx,oc_xxx):',\n required: 'app_id and app_secret are required. Skipping.',\n },\n },\n codex: {\n enable: 'Enable Codex agent integration?',\n command: 'Codex app-server command:',\n workDir: 'Default Codex working directory (optional):',\n model: 'Default Codex model (optional):',\n approvalPolicy: 'Default Codex approval policy (optional):',\n detected: 'Codex CLI detected.',\n notDetected: 'Codex CLI not found in PATH.',\n enabled: 'Codex integration enabled.',\n disabled: 'Codex integration disabled.',\n },\n notify: {\n title: 'Notification types for {{channel}}',\n checkbox: 'Notification types:',\n saved: 'Notification types saved for {{channel}}',\n },\n menu: {\n select: 'Select:',\n next: '--- Next ---',\n testFailed: 'Test failed. Action:',\n retry: 'Retry',\n reenter: 'Re-enter',\n backToMenu: 'Back to menu',\n restartQuestion: 'Restart Gateway now?',\n },\n final: {\n noItems: 'No items configured.',\n itemOk: '{{item}}: OK',\n running: 'Gateway is running',\n runningChanges: 'Gateway is running with pending changes',\n configModified: 'Configuration was modified. Restart required to apply changes.',\n runningReady: 'Gateway is already running and ready.',\n notRunning: 'Gateway is not running',\n configModifiedStart: 'Configuration was modified. Starting Gateway with new configuration.',\n restarting: 'Restarting...',\n restarted: 'Gateway restarted with new configuration',\n starting: 'Starting...',\n started: 'Gateway started',\n startFailed: 'Failed: {{error}}',\n restartTip: 'Run `handsoff gateway start` to restart.',\n startTip: 'Run `handsoff gateway start` to start.',\n done: 'Done.',\n },\n },\n\n gateway: {\n stopping: 'Stopping daemon...',\n startedOnPort: 'Gateway started on port {{port}}',\n stopped: 'Daemon stopped',\n notRunning: 'Daemon is not running',\n restartedOnPort: 'Gateway restarted on port {{port}}',\n startFailed: 'Failed to start Gateway',\n stopFailed: 'Failed to stop Gateway',\n restartFailed: 'Failed to restart Gateway',\n error: ' Error: {{error}}',\n checkLogs: 'Check logs at: {{path}}',\n status: {\n title: 'Gateway Status:',\n running: 'Running: {{value}}',\n sessions: 'Sessions: {{count}}',\n clients: 'Connected clients: {{count}}',\n activeSessions: 'Active sessions:',\n notResponding: 'Gateway is not responding',\n notRunning: 'Gateway is not running',\n },\n },\n\n daemon: {\n alreadyRunning: 'Daemon is already running',\n startedOnPort: 'Daemon started on port {{port}}',\n startFailed: 'Daemon failed to start. Check logs for details.',\n checkLogs: 'Check logs at: {{path}}',\n portInUse: 'Warning: Port {{port}} still in use after {{ms}}ms',\n startError: 'Failed to start daemon: {{error}}',\n lackingToken: 'Daemon is running but PID file lacks token, restarting...',\n scriptNotFound: 'Daemon script not found: {{path}}',\n },\n\n status: {\n title: '=== Handsoff Status ===',\n daemon: {\n running: 'Daemon: ✓ Running',\n notRunning: 'Daemon: ✗ Not running',\n },\n port: 'Port: {{port}}',\n logLevel: 'Log Level: {{level}}',\n channels: 'Channels:',\n telegram: {\n enabled: 'Telegram: ✓ Enabled',\n disabled: 'Telegram: ✗ Disabled',\n },\n feishu: {\n enabled: 'Feishu: ✓ Enabled',\n disabled: 'Feishu: ✗ Disabled',\n },\n settingsBackup: 'Settings: ✓ Backup exists',\n settingsNoBackup: 'Settings: ✗ No backup',\n paths: 'Paths:',\n pathConfig: 'Config: {{path}}',\n pathLogs: 'Logs: {{path}}',\n pathBackup: 'Backup: {{path}}',\n },\n\n cli: {\n init: {\n configExists: 'Configuration exists. Continue?',\n cancelled: 'Cancelled.',\n },\n stop: {\n notRunning: 'Handsoff daemon is not running',\n stopping: 'Stopping handsoff daemon...',\n stopped: 'Daemon stopped successfully',\n failed: 'Failed to stop daemon cleanly',\n },\n attach: {\n checking: 'Checking Gateway status...',\n running: 'Gateway is running',\n notRunning: 'Gateway is not running. Start it with: handsoff gateway start',\n tokenNotFound: 'Hook token not found. Please run \"handsoff init\" first.',\n attached: 'Successfully attached {{agent}} to Gateway',\n start: 'Start \"claude\" to begin a session.',\n usingToken: 'Using hook token: {{token}}',\n settingsBacked: 'Claude settings backed up to: {{path}}',\n configuringHooks: 'Configuring hooks in Claude settings...',\n connected: 'Your Claude Code is now connected to handsoff Gateway.',\n forwarding: 'Events will be forwarded to connected clients.',\n tipStatus: 'Use \"handsoff gateway status\" to check status',\n tipDetach: 'Use \"handsoff detach\" to remove hooks and restore settings',\n },\n agent: {\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n tokenNotFound: 'Failed to get token from daemon',\n hooksConfigured: 'Claude hooks configured',\n startingIn: 'Starting Claude Code in {{dir}}...',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n configuring: 'Configuring Claude Code...',\n settingsBacked: 'Claude settings backed up',\n exited: '\\nClaude Code exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n tipStop: 'Use \"handsoff stop\" to stop the daemon and restore settings',\n detaching: '\\nDetaching from Claude...',\n },\n codex: {\n notInstalled: 'Codex CLI is not installed',\n installMethods: 'Please install Codex CLI using one of these methods:',\n option1npm: 'Option 1 - npm (recommended): npm install -g @openai/codex',\n option2brew: 'Option 2 - Homebrew (macOS): brew install --cask codex',\n alternative: 'Alternatively, use Claude Code: handsoff claude',\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n notEnabled: 'Codex adapter is not enabled in handsoff config.',\n enableHint: 'Enable it with \"handsoff init\" or by setting agent.codex.enabled = true in ~/.handsoff/config.toml, then restart the daemon.',\n startingIn: 'Starting Codex CLI {{version}} in {{dir}}',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n exited: '\\nCodex CLI exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n detaching: '\\nDetaching from Codex...',\n },\n debug: {\n starting: 'Starting hook debug server on port {{port}}',\n capturing: 'This will capture all incoming webhook requests...',\n pressCtrlC: 'Press Ctrl+C to stop.',\n stopping: '\\nStopping debug server...',\n },\n },\n\n notifications: {\n permission: {\n title: '🔐 Permission Request',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n args: 'Args: {{args}}',\n requestId: 'Request ID: {{requestId}}',\n allow: '✅ Allow',\n deny: '❌ Deny',\n },\n finished: {\n titleTelegram: '✅ Task Completed',\n titleLogger: '🏁 Task Completed',\n session: 'Session: {{sessionId}}',\n message: 'Message: {{message}}',\n eventType: 'Type: {{eventType}}',\n },\n sessionStart: {\n title: '🟢 Session Started',\n session: 'Session: {{sessionId}}',\n },\n error: {\n title: '❌ Error',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n message: 'Message: {{message}}',\n },\n unauthorized: 'You are not authorized to use this bot.',\n received: 'Message received.',\n processingError: 'Error processing message.',\n },\n};\n","import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { confirm } from '@inquirer/prompts';\nimport { WizardEngine } from './wizard/engine.js';\nimport { t } from '../i18n/index.js';\nimport { getOrCreateHookToken, resetCredentials } from '../shared/credentials.js';\n\nexport const initCommand = new Command('init')\n .description('Initialize handsoff configuration')\n .option('-f, --force', 'Force reinitialize (regenerate token)')\n .action(async (options) => {\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n\n if (existsSync(configPath) && !options.force) {\n const overwrite = await confirm({\n message: t('cli.init.configExists'),\n default: false,\n });\n if (!overwrite) {\n console.log(t('cli.init.cancelled'));\n return;\n }\n }\n\n // Ensure hook token is created early, even if user skips CLI configuration\n // When --force is used, regenerate the token\n if (options.force) {\n resetCredentials();\n } else {\n getOrCreateHookToken();\n }\n\n const wizard = new WizardEngine();\n await wizard.run();\n });\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { createInitialState, type WizardState, type WizardStep } from './state.js';\nimport { ConfigApplicator } from './applicator.js';\nimport { stepCli } from './steps/cli.js';\nimport { stepCliMenu } from './steps/channel-menu.js';\nimport { stepChannelConfig } from './steps/channel-config.js';\nimport { stepChannelNotify } from './steps/channel-notify.js';\nimport { stepAgentSelect } from './steps/agent-select.js';\nimport { stepChannelSelect } from './steps/channel-select.js';\nimport { stepBindingConfirm } from './steps/binding-confirm.js';\nimport { stepPairContinue } from './steps/pair-continue.js';\nimport { stepFinal } from './steps/final.js';\nimport { detectClaude } from './detectors/claude.js';\nimport { detectCodex } from './detectors/codex.js';\nimport { detectChannel } from './detectors/channel.js';\nimport { loadConfig } from '../../config.js';\n\nexport class WizardEngine {\n private state: WizardState;\n private applicator: ConfigApplicator;\n\n constructor() {\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n const hasExistingConfig = existsSync(configPath);\n this.state = createInitialState(hasExistingConfig);\n this.applicator = new ConfigApplicator();\n }\n\n async run(): Promise<void> {\n await this.detectAllStatus();\n\n while (this.state.current !== 'done' && this.state.current !== 'quit') {\n if (this.state.current === 'final' && this.hasChanges()) {\n this.applicator.apply(this.state.pendingChanges, this.state.bindings);\n }\n\n const result = await this.runStep(this.state.current);\n\n if (result.action === 'next') {\n this.state.previous = this.state.current;\n this.state.current = result.next! as WizardStep;\n } else if (result.action === 'back') {\n this.state.current = this.state.previous || 'agent-select';\n } else if (result.action === 'quit') {\n this.state.current = 'quit';\n }\n }\n }\n\n private async detectAllStatus(): Promise<void> {\n const config = loadConfig();\n const claude = detectClaude();\n this.state.claudeDetection = claude;\n this.state.itemStatus.set('claude', claude.hooked ? 'configured' : 'unconfigured');\n\n const codex = detectCodex();\n this.state.codexDetection = codex;\n this.state.itemStatus.set(\n 'codex',\n config.agent.codex?.enabled ? 'configured' : (codex.installed ? 'detected' : 'not-found')\n );\n\n const channelNames = ['logger', 'telegram', 'feishu'] as const;\n for (const name of channelNames) {\n const detection = await detectChannel(name);\n if (detection.configured) {\n this.state.itemStatus.set(name, 'configured');\n } else if (detection.error) {\n this.state.itemStatus.set(name, 'error');\n }\n }\n }\n\n private async runStep(step: WizardStep) {\n switch (step) {\n case 'agent-select':\n return await stepAgentSelect(this.state);\n case 'channel-select':\n return await stepChannelSelect(this.state);\n case 'binding-confirm':\n return await stepBindingConfirm(this.state);\n case 'pair-continue':\n return await stepPairContinue(this.state);\n case 'cli':\n return await stepCli(this.state);\n case 'cli-menu':\n return await stepCliMenu(this.state);\n case 'channel-config':\n return await stepChannelConfig(this.state);\n case 'channel-notify':\n return await stepChannelNotify(this.state);\n case 'final':\n return await stepFinal(this.state);\n default:\n return { action: 'next', next: 'done' as const };\n }\n }\n\n private hasChanges(): boolean {\n return this.state.sessionConfigured.size > 0 ||\n Object.keys(this.state.pendingChanges).length > 0 ||\n Object.keys(this.state.bindings).length > 0;\n }\n}\n","import type { ClaudeDetection } from './detectors/claude.js';\nimport type { CodexDetection } from './detectors/codex.js';\n\nexport type WizardStep = 'cli' | 'cli-menu' | 'agent-select' | 'channel-select' | 'binding-confirm' | 'pair-continue' | 'channel-config' | 'channel-notify' | 'final' | 'done' | 'quit';\n\nexport type ItemStatus = 'configured' | 'unconfigured' | 'error' | 'detected' | 'not-found';\n\nexport interface WizardState {\n current: WizardStep;\n previous?: WizardStep;\n hasExistingConfig: boolean;\n claudeDetection?: ClaudeDetection;\n codexDetection?: CodexDetection;\n pendingChanges: {\n agent?: {\n claude?: Record<string, unknown>;\n codex?: Record<string, unknown>;\n };\n channel?: Record<string, Record<string, unknown>>;\n };\n bindings: Record<string, string>;\n itemStatus: Map<string, ItemStatus>;\n sessionConfigured: Set<string>;\n validationResults: Map<string, { ok: boolean; message?: string }>;\n currentAgentName?: string;\n currentChannelName?: string;\n currentCliName?: string;\n}\n\nexport function createInitialState(hasExistingConfig: boolean): WizardState {\n return {\n current: 'agent-select',\n hasExistingConfig,\n pendingChanges: {},\n bindings: {},\n itemStatus: new Map(),\n sessionConfigured: new Set(),\n validationResults: new Map(),\n };\n}\n","import { writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport { loadConfig } from '../../config.js';\nimport type { WizardState } from './state.js';\n\nexport class ConfigApplicator {\n apply(pending: WizardState['pendingChanges'], bindings?: Record<string, string>): void {\n const current = loadConfig();\n\n const merged = {\n ...current,\n general: { ...current.general },\n channel: {\n ...current.channel,\n logger: pending.channel?.logger\n ? { ...(current.channel?.logger ?? {}), ...pending.channel.logger }\n : current.channel?.logger,\n telegram: pending.channel?.telegram\n ? { ...(current.channel?.telegram ?? {}), ...pending.channel.telegram }\n : current.channel?.telegram,\n feishu: pending.channel?.feishu\n ? { ...(current.channel?.feishu ?? {}), ...pending.channel.feishu }\n : current.channel?.feishu,\n permission: pending.channel?.permission\n ? { ...(current.channel?.permission ?? {}), ...pending.channel.permission }\n : current.channel?.permission,\n },\n agent: {\n ...current.agent,\n ...(pending.agent?.claude ? {\n claude: { ...(current.agent?.claude ?? {}), ...pending.agent.claude },\n } : {}),\n ...(pending.agent?.codex ? {\n codex: { ...(current.agent?.codex ?? {}), ...pending.agent.codex },\n } : {}),\n },\n };\n\n let finalConfig = merged;\n if (bindings && Object.keys(bindings).length > 0) {\n finalConfig = {\n ...merged,\n bindings: {\n ...(merged.bindings || {}),\n ...bindings,\n },\n };\n }\n\n const configDir = join(homedir(), '.handsoff');\n mkdirSync(configDir, { recursive: true });\n const configPath = join(configDir, 'config.toml');\n const content = TOML.stringify(finalConfig as unknown as Parameters<typeof TOML.stringify>[0]);\n writeFileSync(configPath, content);\n }\n}\n","import { execSync } from 'child_process';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { getHookToken } from '../../../shared/credentials.js';\n\nexport interface ClaudeDetection {\n supported: boolean;\n hooked: boolean;\n tokenMismatch?: boolean;\n message: string;\n binaryPath?: string;\n settingsPath: string;\n}\n\nexport function detectClaude(): ClaudeDetection {\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n\n let binaryPath: string | undefined;\n let supported = false;\n\n try {\n binaryPath = execSync('which claude', { encoding: 'utf-8' }).trim();\n supported = !!binaryPath;\n } catch {\n // claude not in PATH\n }\n\n if (!supported) {\n return {\n supported: false,\n hooked: false,\n message: 'Claude Code not found in PATH. Please install Claude Code first.',\n settingsPath,\n };\n }\n\n const currentToken = getHookToken();\n let hooked = false;\n let tokenMismatch = false;\n\n if (existsSync(settingsPath)) {\n try {\n const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n const hookStatus = checkHandsoffHooks(settings, currentToken);\n hooked = hookStatus.matched;\n tokenMismatch = hookStatus.mismatched;\n } catch {\n // malformed settings\n }\n }\n\n let message: string;\n if (hooked) {\n message = 'Claude Code hooks already configured.';\n } else if (tokenMismatch) {\n message = 'Claude Code hooks have mismatched token. Reconfiguration required.';\n } else {\n message = 'Claude Code detected.';\n }\n\n return {\n supported: true,\n hooked,\n tokenMismatch,\n message,\n binaryPath,\n settingsPath,\n };\n}\n\ninterface HookCheckResult {\n matched: boolean;\n mismatched: boolean;\n}\n\nfunction checkHandsoffHooks(settings: Record<string, unknown>, expectedToken: string | null): HookCheckResult {\n const hooks = settings.hooks as Record<string, unknown> | undefined;\n if (!hooks) return { matched: false, mismatched: false };\n\n let hasAnyHandsoffHook = false;\n let hasMatchingToken = false;\n\n for (const key of Object.keys(hooks)) {\n const entries = hooks[key] as unknown[];\n for (const entry of entries) {\n if (!entry || typeof entry !== 'object') continue;\n const e = entry as Record<string, unknown>;\n const inner = e.hooks;\n if (Array.isArray(inner)) {\n for (const h of inner) {\n const hookInfo = extractHandsoffHookInfo(h);\n if (hookInfo.isHandsoff) {\n hasAnyHandsoffHook = true;\n if (expectedToken && hookInfo.token === expectedToken) {\n hasMatchingToken = true;\n }\n }\n }\n }\n }\n }\n\n return {\n matched: hasMatchingToken,\n mismatched: hasAnyHandsoffHook && !hasMatchingToken,\n };\n}\n\nfunction extractHandsoffHookInfo(entry: unknown): { isHandsoff: boolean; token?: string } {\n if (!entry || typeof entry !== 'object') return { isHandsoff: false };\n const e = entry as Record<string, unknown>;\n if (e.type !== 'http') return { isHandsoff: false };\n const url = e.url as string;\n if (typeof url !== 'string') return { isHandsoff: false };\n\n // Check if it's a handsoff hook URL: http://localhost:{port}/hook/{token}/...\n const match = url.match(/^http:\\/\\/localhost:\\d+\\/hook\\/([^\\/]+)/);\n if (match) {\n return { isHandsoff: true, token: match[1] };\n }\n return { isHandsoff: false };\n}","import { execSync } from 'child_process';\n\nexport interface CodexDetection {\n supported: boolean;\n installed: boolean;\n message: string;\n binaryPath?: string;\n version?: string;\n}\n\nexport function detectCodex(): CodexDetection {\n let binaryPath: string | undefined;\n let installed = false;\n let version: string | undefined;\n\n try {\n binaryPath = execSync('which codex', { encoding: 'utf-8' }).trim();\n installed = !!binaryPath;\n version = execSync('codex --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();\n } catch {\n // codex not in PATH\n }\n\n if (!installed) {\n return {\n supported: false,\n installed: false,\n message: 'Codex CLI not found in PATH. Please install Codex CLI first.',\n };\n }\n\n return {\n supported: true,\n installed: true,\n message: `Codex CLI ${version} detected.`,\n binaryPath,\n version,\n };\n}\n","import { t } from '../../i18n/index.js';\nimport { confirm, input, checkbox, select } from '@inquirer/prompts';\n\nexport const prompts = {\n feishuAppId: (current?: string) => input({\n message: t('wizard.channel.feishu.appId'),\n default: current || '',\n }),\n\n feishuAppSecret: (current?: string) => input({\n message: t('wizard.channel.feishu.appSecret'),\n default: current || '',\n }),\n\n feishuAllowedUsers: (current?: string) => input({\n message: t('wizard.channel.feishu.allowedUsers'),\n default: current || '',\n }),\n\n codexEnable: (enabled: boolean) => confirm({\n message: t('wizard.codex.enable'),\n default: enabled,\n }),\n\n codexCommand: (current?: string) => input({\n message: t('wizard.codex.command'),\n default: current || 'codex app-server --listen stdio://',\n }),\n\n codexWorkDir: (current?: string) => input({\n message: t('wizard.codex.workDir'),\n default: current || '',\n }),\n\n codexModel: (current?: string) => input({\n message: t('wizard.codex.model'),\n default: current || '',\n }),\n\n codexApprovalPolicy: (current?: string) => input({\n message: t('wizard.codex.approvalPolicy'),\n default: current || '',\n }),\n\n cliActionSelect: (hooked: boolean) => select({\n message: t('wizard.cli.actionQuestion'),\n choices: hooked\n ? [\n { name: t('wizard.cli.updateAction'), value: 'update' },\n { name: t('wizard.cli.backAction'), value: 'back' },\n ]\n : [\n { name: t('wizard.cli.injectAction'), value: 'inject' },\n { name: t('wizard.cli.backAction'), value: 'back' },\n ],\n }),\n\n cliHookSelect: (selected?: string[]) => checkbox({\n message: t('wizard.cli.hookCheckbox'),\n choices: [\n { name: 'Stop', value: 'Stop', checked: selected?.includes('Stop') ?? true },\n { name: 'SessionStart', value: 'SessionStart', checked: selected?.includes('SessionStart') ?? true },\n { name: 'SessionEnd', value: 'SessionEnd', checked: selected?.includes('SessionEnd') ?? true },\n { name: 'PermissionRequest', value: 'PermissionRequest', checked: selected?.includes('PermissionRequest') ?? true },\n { name: 'UserPromptSubmit', value: 'UserPromptSubmit', checked: selected?.includes('UserPromptSubmit') ?? false },\n { name: 'PostToolUse', value: 'PostToolUse', checked: selected?.includes('PostToolUse') ?? false },\n { name: 'PostToolUseFailure', value: 'PostToolUseFailure', checked: selected?.includes('PostToolUseFailure') ?? false },\n { name: 'Notification', value: 'Notification', checked: selected?.includes('Notification') ?? false },\n { name: 'SubagentStart', value: 'SubagentStart', checked: selected?.includes('SubagentStart') ?? false },\n { name: 'SubagentStop', value: 'SubagentStop', checked: selected?.includes('SubagentStop') ?? false },\n ],\n }),\n\n botToken: (current?: string) => input({\n message: t('wizard.channel.telegram.botToken'),\n default: current || '',\n }),\n\n allowedUsers: (current?: string) => input({\n message: t('wizard.channel.telegram.allowedUsers'),\n default: current || '',\n }),\n\n channelMenuSelect: (channels: Array<{ name: string; status: string }>) => select({\n message: t('wizard.menu.select'),\n choices: [\n ...channels.map(c => ({\n name: `${c.name} ${c.status}`,\n value: c.name,\n })),\n { name: t('wizard.menu.next'), value: '__next__' },\n ],\n }),\n\n notifyTypes: (selected?: string[]) => checkbox({\n message: t('wizard.notify.checkbox'),\n choices: [\n { name: 'permission_request', value: 'permission_request', checked: selected?.includes('permission_request') },\n { name: 'question_request', value: 'question_request', checked: selected?.includes('question_request') },\n { name: 'finished', value: 'finished', checked: selected?.includes('finished') },\n { name: 'session_start', value: 'session_start', checked: selected?.includes('session_start') },\n { name: 'error', value: 'error', checked: selected?.includes('error') },\n ],\n }),\n\n channelConfigError: () => select({\n message: t('wizard.menu.testFailed'),\n choices: [\n { name: t('wizard.menu.retry'), value: 'retry' },\n { name: t('wizard.menu.reenter'), value: 'reinput' },\n { name: t('wizard.menu.backToMenu'), value: 'skip' },\n ],\n }),\n\n restartGateway: () => confirm({\n message: t('wizard.menu.restartQuestion'),\n default: true,\n }),\n\n bindingAgentSelect: (agents: Array<{ name: string; value: string }>) => select({\n message: 'Select an agent to bind:',\n choices: agents.map(a => ({ name: a.name, value: a.value })),\n }),\n\n bindingConfirm: (agentName: string, channelName: string) => select({\n message: `🤖 Bind ${agentName} to ${channelName} — confirm?`,\n choices: [\n { name: 'Confirm binding', value: 'confirm' },\n { name: 'Cancel', value: 'cancel' },\n ],\n }),\n\n pairContinue: () => select({\n message: 'Add another pair?',\n choices: [\n { name: 'Add another pair', value: 'continue' },\n { name: 'Finish setup', value: 'finish' },\n ],\n }),\n\n agentSelect: (agents: Array<{ name: string; value: string; status: string }>) => select({\n message: 'Select an agent to configure:',\n choices: agents.map(a => ({ name: `${a.name} ${a.status}`, value: a.value })),\n }),\n\n channelSelect: (channels: Array<{ name: string; value: string; status: string }>) => select({\n message: 'Select a channel to configure:',\n choices: channels.map(c => ({ name: `${c.name} ${c.status}`, value: c.value })),\n }),\n};\n","import { detectClaude } from '../detectors/claude.js';\nimport { detectCodex } from '../detectors/codex.js';\nimport { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport { getOrCreateHookToken, getHookToken } from '../../../shared/credentials.js';\nimport { mergeHooks } from '../../../shared/settings-merge.js';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 2';\n\nexport async function stepCli(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const cliName = state.currentCliName || 'claude';\n\n console.log(pc.bold(`\\n${STEP} — Configure Agent\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n if (cliName === 'claude') {\n const detection = state.claudeDetection ?? detectClaude();\n\n if (!detection.supported) {\n console.log(pc.yellow(`! ${detection.message}`));\n console.log(pc.gray(` ${t('wizard.cli.runAgain')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n console.log(pc.green(`* ${t('wizard.cli.detected')}`));\n console.log(pc.gray(` Settings: ${detection.settingsPath}`));\n\n const port = loadConfig().general.hook_server_port;\n const token = getHookToken();\n console.log(pc.gray(` Gateway: http://localhost:${port}/hook/${token ? token.substring(0, 8) + '...' : 'unknown'}`));\n\n if (detection.hooked) {\n console.log(pc.green(` ${t('wizard.cli.hooksInstalled')}`));\n } else if (detection.tokenMismatch) {\n console.log(pc.red(` ${t('wizard.cli.hooksTokenMismatch')}`));\n } else {\n console.log(pc.yellow(` ${t('wizard.cli.hooksNotInstalled')}`));\n }\n console.log('');\n\n const action = await prompts.cliActionSelect(detection.hooked);\n if (action === 'back') {\n console.log('');\n return { action: 'next', next: 'cli-menu' };\n }\n\n const selectedHooks = await prompts.cliHookSelect();\n if (selectedHooks.length === 0) {\n console.log(pc.yellow(`! ${t('wizard.cli.noHooksSelected')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n const spinner = ora(t('wizard.cli.injecting')).start();\n try {\n injectClaudeHooks(detection.settingsPath, selectedHooks);\n spinner.succeed(t('wizard.cli.injected'));\n\n state.itemStatus.set('claude', 'configured');\n state.sessionConfigured.add('claude');\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n claude: { adapter: 'hooks' },\n };\n state.validationResults.set('claude', { ok: true });\n return { action: 'next', next: 'channel-select' };\n } catch (err) {\n spinner.fail(t('wizard.cli.failed', { error: String(err) }));\n state.itemStatus.set('claude', 'error');\n state.validationResults.set('claude', { ok: false, message: String(err) });\n }\n }\n\n if (cliName === 'codex') {\n const detection = state.codexDetection ?? detectCodex();\n const config = loadConfig();\n const current = config.agent.codex;\n\n if (!detection.installed) {\n console.log(pc.yellow(`! ${t('wizard.codex.notDetected')}`));\n console.log(pc.gray(` ${detection.message}\\n`));\n state.itemStatus.set('codex', 'not-found');\n state.validationResults.set('codex', { ok: false, message: detection.message });\n return { action: 'next', next: 'cli-menu' };\n }\n\n console.log(pc.green(`* ${t('wizard.codex.detected')}`));\n console.log(pc.gray(` Binary: ${detection.binaryPath}`));\n console.log(pc.gray(` Version: ${detection.version || 'unknown'}`));\n console.log('');\n\n const enabled = await prompts.codexEnable(current?.enabled === true);\n\n if (!enabled) {\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n codex: {\n ...(current || {}),\n enabled: false,\n },\n };\n state.itemStatus.set('codex', 'unconfigured');\n state.validationResults.set('codex', { ok: true, message: t('wizard.codex.disabled') });\n console.log(pc.gray(` ${t('wizard.codex.disabled')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n const commandInput = await prompts.codexCommand((current?.command || []).join(' '));\n const workDir = await prompts.codexWorkDir(current?.work_dir || '');\n const model = await prompts.codexModel(current?.model || '');\n const approvalPolicy = await prompts.codexApprovalPolicy(current?.approval_policy || '');\n\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n codex: {\n ...(current || {}),\n enabled: true,\n command: parseCommandInput(commandInput),\n work_dir: workDir,\n model,\n approval_policy: approvalPolicy,\n },\n };\n state.itemStatus.set('codex', 'configured');\n state.sessionConfigured.add('codex');\n state.validationResults.set('codex', { ok: true, message: t('wizard.codex.enabled') });\n console.log(pc.green(` ${t('wizard.codex.enabled')}\\n`));\n return { action: 'next', next: 'channel-select' };\n }\n\n return { action: 'next', next: 'cli-menu' };\n}\n\nfunction parseCommandInput(input: string): string[] {\n const tokens = input\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n\n return tokens.length > 0 ? tokens : ['codex', 'app-server', '--listen', 'stdio://'];\n}\n\nfunction injectClaudeHooks(settingsPath: string, events: string[]): void {\n const port = loadConfig().general.hook_server_port;\n\n // Use canonical hook token: create if missing, reuse if exists\n const token = getOrCreateHookToken();\n\n const baseUrl = `http://localhost:${port}/hook/${token}`;\n const hooksConfig = generateHooksConfig(baseUrl, events);\n\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n } catch {\n // ignore\n }\n }\n\n const mergedSettings = mergeHooks(\n currentSettings,\n hooksConfig as Record<string, import('../../../shared/settings-merge.js').HookEntry[]>\n );\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2));\n}\n\nfunction generateHooksConfig(baseUrl: string, events: string[]): Record<string, unknown[]> {\n const createEntry = (event: string) => ({\n matcher: '',\n hooks: [{ type: 'http' as const, url: `${baseUrl}/${event}` }],\n });\n\n const config: Record<string, unknown[]> = {};\n for (const event of events) {\n config[event] = [createEntry(event)];\n }\n return config;\n}\n","import { loadConfig } from '../../../config.js';\nimport type { ItemStatus } from '../state.js';\n\nexport type ChannelType = 'logger' | 'telegram' | 'feishu';\n\nexport interface ChannelDetection {\n configured: boolean;\n error?: string;\n}\n\nexport async function detectChannel(name: ChannelType): Promise<ChannelDetection> {\n const config = loadConfig();\n\n switch (name) {\n case 'logger':\n return { configured: config.channel.logger?.enabled === true };\n case 'telegram': {\n const token = config.channel.telegram?.bot_token;\n if (!token || token === 'YOUR_BOT_TOKEN') {\n return { configured: false };\n }\n try {\n const response = await fetch(`https://api.telegram.org/bot${token}/getMe`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n return { configured: false, error: `Telegram API error: ${response.status}` };\n }\n return { configured: true };\n } catch (err) {\n return { configured: false, error: `Connection failed: ${err}` };\n }\n }\n case 'feishu': {\n const feishuConfig = config.channel.feishu;\n if (!feishuConfig?.enabled || !feishuConfig?.app_id) {\n return { configured: false };\n }\n // 检查 allowed_users 是否配置\n const allowedUsers = feishuConfig.allowed_users;\n if (!allowedUsers || allowedUsers.length === 0) {\n return { configured: false, error: 'Missing allowed_users' };\n }\n return { configured: true };\n }\n default:\n return { configured: false };\n }\n}\n\nexport function getChannelStatusLabel(status: ItemStatus, error?: string): string {\n switch (status) {\n case 'configured': return '[done]';\n case 'detected': return '[detected]';\n case 'not-found': return '[not found]';\n case 'error': return `[error]${error ? ` (${error})` : ''}`;\n default: return '';\n }\n}\n","import { prompts } from '../prompts.js';\nimport { getChannelStatusLabel, type ChannelType } from '../detectors/channel.js';\nimport pc from 'picocolors';\nimport { t } from '../../../i18n/index.js';\nimport type { WizardState } from '../state.js';\n\nexport async function stepChannelMenu(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.channel')}\\n`));\n\n const channelNames: ChannelType[] = ['logger', 'telegram', 'feishu'];\n const channels = channelNames.map(name => {\n const status = state.itemStatus.get(name) || 'unconfigured';\n const validation = state.validationResults.get(name);\n return {\n name,\n status: getChannelStatusLabel(status, validation?.message),\n };\n });\n\n const choice = await prompts.channelMenuSelect(channels);\n\n if (choice === '__next__') {\n return { action: 'next', next: 'final' };\n }\n\n state.currentChannelName = choice;\n return { action: 'next', next: 'channel-config' };\n}\n\nexport async function stepCliMenu(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.cli')}\\n`));\n\n const claudeStatus = state.itemStatus.get('claude') || 'unconfigured';\n let claudeLabel = getChannelStatusLabel(claudeStatus);\n if (state.claudeDetection?.tokenMismatch) {\n claudeLabel = pc.yellow('[update needed]');\n }\n\n const codexStatus = state.itemStatus.get('codex') || 'not-found';\n const codexLabel = getChannelStatusLabel(codexStatus, state.validationResults.get('codex')?.message);\n\n const cliOptions = [\n { name: 'claude', status: claudeLabel },\n { name: 'codex', status: codexLabel },\n ];\n\n const choice = await prompts.channelMenuSelect(cliOptions);\n\n if (choice === '__next__') {\n return { action: 'next', next: 'channel-menu' };\n }\n\n state.currentCliName = choice;\n return { action: 'next', next: 'cli' };\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 4';\n\nexport async function stepChannelConfig(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const channelName = state.currentChannelName || 'telegram';\n\n console.log(pc.bold(`\\n${STEP} — Configure Channel\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n while (true) {\n const cfg = loadConfig();\n const channelMap = cfg.channel as Record<string, unknown>;\n const currentConfig = (channelMap[channelName] ?? {}) as Record<string, unknown>;\n\n if (channelName === 'telegram') {\n const botToken = await prompts.botToken(currentConfig.bot_token as string | undefined);\n const allowedUsers = await prompts.allowedUsers(String(currentConfig.allowed_users || ''));\n\n const userIds = allowedUsers\n .split(',')\n .map(s => s.trim())\n .filter(s => s.length > 0 && /^\\d+$/.test(s));\n\n const spinner = ora(t('wizard.channel.telegram.testing')).start();\n let connected = false;\n try {\n const response = await fetch(`https://api.telegram.org/bot${botToken}/getMe`, {\n signal: AbortSignal.timeout(8000),\n });\n if (!response.ok) {\n spinner.fail(t('wizard.channel.telegram.apiError', { status: response.status }));\n } else {\n spinner.succeed(t('wizard.channel.telegram.connected'));\n connected = true;\n }\n } catch (err) {\n spinner.fail(t('wizard.channel.telegram.connFailed', { error: String(err) }));\n }\n\n if (!connected) {\n state.itemStatus.set(channelName, 'error');\n const choice = await prompts.channelConfigError();\n if (choice === 'retry' || choice === 'reinput') {\n continue;\n }\n state.itemStatus.set(channelName, 'unconfigured');\n return { action: 'next', next: 'channel-select' };\n }\n\n const msgSpinner = ora(t('wizard.channel.telegram.sendingTest')).start();\n try {\n await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ chat_id: userIds[0] || 0, text: t('wizard.channel.telegram.testContent') }),\n signal: AbortSignal.timeout(8000),\n });\n msgSpinner.succeed(t('wizard.channel.telegram.testSent'));\n } catch {\n msgSpinner.warn(t('wizard.channel.telegram.testWarning'));\n }\n\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n telegram: { enabled: true, bot_token: botToken, allowed_users: userIds },\n };\n state.itemStatus.set('telegram', 'configured');\n state.sessionConfigured.add('telegram');\n state.validationResults.set('telegram', { ok: true });\n return { action: 'next', next: 'binding-confirm' };\n }\n\n if (channelName === 'logger') {\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n logger: { enabled: true },\n };\n state.itemStatus.set('logger', 'configured');\n state.sessionConfigured.add('logger');\n return { action: 'next', next: 'binding-confirm' };\n }\n\n if (channelName === 'feishu') {\n const appId = await prompts.feishuAppId(String(currentConfig.app_id || ''));\n const appSecret = await prompts.feishuAppSecret(String(currentConfig.app_secret || ''));\n const allowedUsersInput = await prompts.feishuAllowedUsers(String(currentConfig.allowed_users || ''));\n\n if (!appId || !appSecret) {\n console.log(pc.yellow(`! ${t('wizard.channel.feishu.required')}\\n`));\n state.itemStatus.set('feishu', 'unconfigured');\n return { action: 'next', next: 'channel-select' };\n }\n\n // 解析用户ID列表(支持逗号分隔)\n const allowedUsers = allowedUsersInput\n .split(',')\n .map(s => s.trim())\n .filter(s => s.length > 0);\n\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n feishu: { enabled: true, app_id: appId, app_secret: appSecret, allowed_users: allowedUsers },\n };\n state.itemStatus.set('feishu', 'configured');\n state.sessionConfigured.add('feishu');\n return { action: 'next', next: 'binding-confirm' };\n }\n\n return { action: 'next', next: 'agent-select' };\n }\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nexport async function stepChannelNotify(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const channelName = state.currentChannelName || 'telegram';\n\n console.log(pc.bold(`\\n${t('wizard.notify.title', { channel: channelName })}\\n`));\n\n const cfg = loadConfig();\n const channelConfig = cfg.channel[channelName as keyof typeof cfg.channel] as Record<string, unknown> | undefined || {};\n const currentTypes = (channelConfig.notify_types as string[]) || [];\n\n const selected = await prompts.notifyTypes(currentTypes);\n\n if (!state.pendingChanges.channel) state.pendingChanges.channel = {};\n if (!state.pendingChanges.channel[channelName]) state.pendingChanges.channel[channelName] = {};\n\n state.pendingChanges.channel[channelName] = {\n ...(state.pendingChanges.channel[channelName] as Record<string, unknown>),\n notify_types: selected,\n };\n\n console.log(pc.green(`\\n✓ ${t('wizard.notify.saved', { channel: channelName })}\\n`));\n\n return { action: 'next', next: 'channel-menu' };\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { detectCodex } from '../detectors/codex.js';\nimport { stepCli } from './cli.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 1';\n\nexport async function stepAgentSelect(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Select Agent\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = config.bindings ?? {};\n\n const agents: Array<{ name: string; value: string; status: string }> = [];\n\n // claude\n const claudeConfigured = !!config.agent.claude;\n const claudeBoundTo = currentBindings['claude'];\n const claudeStatus = claudeBoundTo\n ? pc.green(`[bound to ${claudeBoundTo}]`)\n : (claudeConfigured ? pc.green('[configured]') : pc.gray('[not configured]'));\n agents.push({ name: 'claude', value: 'claude', status: claudeStatus });\n\n // codex\n const codexDetection = detectCodex();\n const codexConfigured = !!config.agent.codex?.enabled;\n const codexBoundTo = currentBindings['codex'];\n const codexStatus = codexBoundTo\n ? pc.green(`[bound to ${codexBoundTo}]`)\n : (codexConfigured ? pc.green('[configured]') : (codexDetection.installed ? pc.gray('[not configured]') : pc.red('[not installed]')));\n agents.push({ name: 'codex', value: 'codex', status: codexStatus });\n\n const choice = await prompts.agentSelect(agents);\n\n state.currentAgentName = choice;\n state.currentCliName = choice;\n\n // Run the existing stepCli for this agent\n const result = await stepCli(state);\n\n // After stepCli, always proceed to channel-select\n if (result.action === 'back') {\n return { action: 'next', next: 'pair-continue' };\n }\n\n // If stepCli indicates the agent was not usable (e.g. codex not installed),\n // return to agent-select so the user can pick a different agent.\n if (result.next === 'cli-menu') {\n return { action: 'next', next: 'agent-select' };\n }\n\n return { action: 'next', next: 'channel-select' };\n}","import { createHash } from 'crypto';\n\n/**\n * Generate a channel instance ID from channel type and its credential.\n * Format: \"channelType:hash\" e.g. \"telegram:abc123def\"\n */\nexport function getChannelInstanceId(channelType: string, credential: string): string {\n const hash = createHash('sha256').update(credential).digest('hex').slice(0, 12);\n return `${channelType}:${hash}`;\n}\n\n/**\n * Parse a channel instance ID back into its components.\n */\nexport function parseChannelInstanceId(instanceId: string): { channelType: string; hash: string } | null {\n const parts = instanceId.split(':');\n if (parts.length !== 2) return null;\n return { channelType: parts[0], hash: parts[1] };\n}\n\n/**\n * Get display label for a channel instance ID.\n * Uses short hash for display purposes.\n */\nexport function getChannelInstanceLabel(channelType: string, hash: string, displayName?: string): string {\n return displayName ?? `${channelType} (${hash})`;\n}","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\nimport { stepChannelConfig } from './channel-config.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 3';\n\nexport async function stepChannelSelect(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Select Channel\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = config.bindings ?? {};\n\n // Merge pending channel changes from current wizard session so we reflect unsaved edits\n const pendingChannels = state.pendingChanges.channel ?? {};\n const mergedTelegram = pendingChannels.telegram\n ? { ...config.channel.telegram, ...pendingChannels.telegram }\n : config.channel.telegram;\n const mergedFeishu = pendingChannels.feishu\n ? { ...config.channel.feishu, ...pendingChannels.feishu }\n : config.channel.feishu;\n const mergedLogger = pendingChannels.logger\n ? { ...config.channel.logger, ...pendingChannels.logger }\n : config.channel.logger;\n\n const channels: Array<{ name: string; value: string; status: string }> = [];\n\n // logger\n const loggerEnabled = mergedLogger?.enabled === true;\n const loggerInstanceId = 'logger:default';\n const loggerBoundAgent = Object.entries(currentBindings).find(([, v]) => v === loggerInstanceId)?.[0];\n const loggerStatus = loggerBoundAgent\n ? pc.green(`[bound to ${loggerBoundAgent}]`)\n : (loggerEnabled ? pc.green('[configured]') : pc.gray('[not configured]'));\n channels.push({ name: 'logger', value: 'logger', status: loggerStatus });\n\n // telegram\n if (mergedTelegram?.enabled && mergedTelegram.bot_token) {\n const instanceId = getChannelInstanceId('telegram', mergedTelegram.bot_token as string);\n const boundAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n const status = boundAgent\n ? pc.green(`[bound to ${boundAgent}]`)\n : pc.green('[configured]');\n channels.push({ name: 'telegram', value: 'telegram', status });\n } else {\n channels.push({ name: 'telegram', value: 'telegram', status: pc.gray('[not configured]') });\n }\n\n // feishu\n if (mergedFeishu?.enabled && mergedFeishu.app_id) {\n const instanceId = getChannelInstanceId('feishu', mergedFeishu.app_id as string);\n const boundAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n const status = boundAgent\n ? pc.green(`[bound to ${boundAgent}]`)\n : pc.green('[configured]');\n channels.push({ name: 'feishu', value: 'feishu', status });\n } else {\n channels.push({ name: 'feishu', value: 'feishu', status: pc.gray('[not configured]') });\n }\n\n const choice = await prompts.channelSelect(channels);\n\n state.currentChannelName = choice;\n\n // Run stepChannelConfig for this channel\n const result = await stepChannelConfig(state);\n\n if (result.action === 'back') {\n return { action: 'next', next: 'agent-select' };\n }\n\n return { action: 'next', next: 'binding-confirm' };\n}","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 5';\n\nexport async function stepBindingConfirm(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const agentName = state.currentAgentName!;\n const channelName = state.currentChannelName!;\n\n console.log(pc.bold(`\\n${STEP} — Confirm Binding\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = { ...(config.bindings ?? {}) } as Record<string, string | undefined>;\n\n // Merge any wizard-session bindings that were already staged\n for (const [a, cid] of Object.entries(state.bindings)) {\n if (cid) currentBindings[a] = cid;\n }\n\n // Use pending channel changes if they exist (not yet written to disk)\n const pendingChannel = state.pendingChanges.channel?.[channelName] as Record<string, unknown> | undefined;\n const telegramConfig = pendingChannel && channelName === 'telegram'\n ? { ...config.channel.telegram, ...pendingChannel }\n : config.channel.telegram;\n const feishuConfig = pendingChannel && channelName === 'feishu'\n ? { ...config.channel.feishu, ...pendingChannel }\n : config.channel.feishu;\n\n // Get agent's current binding\n const agentCurrentChannel = currentBindings[agentName];\n\n // Get channel's current binding\n let channelCurrentAgent: string | undefined;\n let instanceId: string | undefined;\n if (channelName === 'telegram' && telegramConfig?.bot_token) {\n instanceId = getChannelInstanceId('telegram', telegramConfig.bot_token as string);\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n } else if (channelName === 'feishu' && feishuConfig?.app_id) {\n instanceId = getChannelInstanceId('feishu', feishuConfig.app_id as string);\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n } else if (channelName === 'logger') {\n instanceId = 'logger:default';\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n }\n\n console.log(` ${pc.cyan(agentName)} current binding: ${agentCurrentChannel ? pc.yellow(agentCurrentChannel) : pc.gray('none')}`);\n console.log(` ${pc.cyan(channelName)} current binding: ${channelCurrentAgent ? pc.yellow(channelCurrentAgent) : pc.gray('none')}`);\n console.log('');\n\n const choice = await prompts.bindingConfirm(agentName, channelName);\n\n if (choice === 'confirm' && instanceId) {\n const oldChannelId = currentBindings[agentName];\n\n // Remove conflicting binding (another agent bound to same channel)\n for (const [a, cid] of Object.entries(currentBindings)) {\n if (cid === instanceId && a !== agentName) {\n delete state.bindings[a];\n }\n }\n\n if (oldChannelId && oldChannelId !== instanceId) {\n console.log(pc.yellow(` ⚠ ${agentName} migrated from ${oldChannelId} to ${instanceId}`));\n }\n state.bindings[agentName] = instanceId;\n state.sessionConfigured.add(`binding:${agentName}`);\n console.log(pc.green(` ✓ ${agentName} bound to ${channelName}`));\n } else {\n console.log(pc.gray(` Binding cancelled`));\n }\n\n console.log('');\n return { action: 'next', next: 'pair-continue' };\n}\n","import { prompts } from '../prompts.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 6';\n\nexport async function stepPairContinue(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Add Another Pair?\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const choice = await prompts.pairContinue();\n\n if (choice === 'continue') {\n // Reset current pair state for next iteration\n state.currentAgentName = undefined;\n state.currentChannelName = undefined;\n return { action: 'next', next: 'agent-select' };\n }\n\n // finish — go to final\n return { action: 'next', next: 'final' };\n}\n","import { spawn } from 'child_process';\nimport { exec } from 'child_process';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync, existsSync } from 'fs';\nimport { readPidFile, removePidFile, isProcessRunning } from '../shared/pidfile.js';\nimport { t } from '../i18n/index.js';\n\nfunction isPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n exec(`lsof -i :${port}`, (err) => {\n resolve(!err);\n });\n });\n}\n\nexport class DaemonManager {\n private pidFilePath: string;\n private port: number;\n private lastError?: string;\n\n constructor(pidFilePath: string, port: number) {\n this.pidFilePath = pidFilePath;\n this.port = port;\n }\n\n getPort(): number {\n return this.port;\n }\n\n getPidFilePath(): string {\n return this.pidFilePath;\n }\n\n getLastError(): string | undefined {\n return this.lastError;\n }\n\n isRunning(): boolean {\n const data = readPidFile(this.pidFilePath);\n if (!data) return false;\n\n // Check if process actually exists\n if (!isProcessRunning(data.pid)) {\n // Cleanup stale PID file\n removePidFile(this.pidFilePath);\n return false;\n }\n\n return true;\n }\n\n async start(): Promise<boolean> {\n this.lastError = undefined;\n\n const existingPidData = readPidFile(this.pidFilePath);\n if (existingPidData && isProcessRunning(existingPidData.pid)) {\n if (!existingPidData.token) {\n console.log(t('daemon.lackingToken'));\n await this.stop();\n await this.waitForPortFree();\n } else {\n console.log(t('daemon.alreadyRunning'));\n return true;\n }\n }\n\n try {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logDir = join(homedir, '.handsoff', 'logs');\n mkdirSync(logDir, { recursive: true });\n\n // Ensure PID file is removed before starting\n removePidFile(this.pidFilePath);\n\n const __dirname = dirname(fileURLToPath(import.meta.url));\n let daemonScript = join(__dirname, '..', 'gateway', 'process.js');\n\n if (!existsSync(daemonScript)) {\n daemonScript = join(__dirname, '..', '..', 'src', 'gateway', 'process.ts');\n }\n\n if (!existsSync(daemonScript)) {\n this.lastError = t('daemon.scriptNotFound', { path: daemonScript });\n console.error(this.lastError);\n return false;\n }\n\n // Start daemon in detached mode - it will run independently\n const logFile = join(logDir, 'gateway.log');\n\n // In dev mode the fallback script is a .ts file — use tsx to run it\n const isDev = daemonScript.endsWith('.ts');\n const execPath = isDev\n ? join(__dirname, '..', '..', 'node_modules', '.bin', 'tsx')\n : process.execPath;\n\n // Spawn detached daemon\n const child = spawn(execPath, [daemonScript], {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n HANDSOFF_DAEMON: 'true',\n HANDSOFF_PORT: String(this.port),\n HANDSOFF_PID_FILE: this.pidFilePath,\n },\n });\n child.unref();\n\n // Wait for daemon to start and write PID file\n // Daemon startup may take up to 20 seconds due to channel initialization (e.g., Telegram)\n let pidData = null;\n for (let i = 0; i < 30; i++) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n pidData = readPidFile(this.pidFilePath);\n if (pidData) {\n if (isProcessRunning(pidData.pid)) {\n console.log(t('daemon.startedOnPort', { port: this.port }));\n return true;\n }\n }\n }\n\n this.lastError = t('daemon.startFailed');\n console.error(this.lastError);\n console.error(t('daemon.checkLogs', { path: logFile }));\n return false;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.lastError = t('daemon.startError', { error: errorMsg });\n console.error(this.lastError);\n return false;\n }\n }\n\n async stop(): Promise<boolean> {\n const data = readPidFile(this.pidFilePath);\n if (!data) {\n // console.log('No daemon PID file found');\n return true;\n }\n\n try {\n // Kill the process\n process.kill(data.pid, 'SIGTERM');\n\n // Wait for process to exit\n let attempts = 0;\n while (isProcessRunning(data.pid) && attempts < 10) {\n await new Promise(resolve => setTimeout(resolve, 200));\n attempts++;\n }\n\n if (isProcessRunning(data.pid)) {\n // Force kill\n process.kill(data.pid, 'SIGKILL');\n }\n\n removePidFile(this.pidFilePath);\n // console.log('Daemon stopped');\n return true;\n } catch (error) {\n // console.error('Failed to stop daemon:', error);\n return false;\n }\n }\n\n async forceCleanup(): Promise<void> {\n removePidFile(this.pidFilePath);\n }\n\n private async waitForPortFree(maxWaitMs: number = 5000): Promise<void> {\n const startTime = Date.now();\n while (await isPortInUse(this.port)) {\n if (Date.now() - startTime > maxWaitMs) {\n console.log(t('daemon.portInUse', { port: this.port, ms: maxWaitMs }));\n break;\n }\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n }\n}\n","import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { mkdirSync } from 'fs';\n\nexport interface PidFileData {\n pid: number;\n port: number;\n startedAt: string;\n version?: string;\n agents?: string[];\n channels?: string[];\n token?: string;\n}\n\nexport function writePidFile(pidFilePath: string, data: PidFileData): void {\n // Validate pid is a positive integer\n if (!Number.isInteger(data.pid) || data.pid <= 0) {\n throw new TypeError(`Invalid pid: ${data.pid}. Must be a positive integer.`);\n }\n\n // Validate port is a positive integer between 1-65535\n if (!Number.isInteger(data.port) || data.port < 1 || data.port > 65535) {\n throw new TypeError(`Invalid port: ${data.port}. Must be an integer between 1 and 65535.`);\n }\n\n mkdirSync(dirname(pidFilePath), { recursive: true });\n writeFileSync(pidFilePath, JSON.stringify(data, null, 2));\n}\n\nexport function readPidFile(pidFilePath: string): PidFileData | null {\n if (!existsSync(pidFilePath)) {\n return null;\n }\n try {\n const content = readFileSync(pidFilePath, 'utf-8');\n return JSON.parse(content) as PidFileData;\n } catch {\n return null;\n }\n}\n\nexport function removePidFile(pidFilePath: string): void {\n if (existsSync(pidFilePath)) {\n unlinkSync(pidFilePath);\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import { prompts } from '../prompts.js';\nimport { DaemonManager } from '../../daemon.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\n\nexport async function stepFinal(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.complete')}\\n`));\n\n if (state.sessionConfigured.size === 0) {\n console.log(pc.gray(` ${t('wizard.final.noItems')}\\n`));\n } else {\n for (const item of state.sessionConfigured) {\n const result = state.validationResults.get(item);\n if (result?.ok) {\n console.log(pc.green(`* ${t('wizard.final.itemOk', { item })}`));\n }\n }\n console.log('');\n }\n\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const port = loadConfig().general.hook_server_port;\n const daemon = new DaemonManager(pidFilePath, port);\n const hasChanges = state.sessionConfigured.size > 0 || Object.keys(state.pendingChanges).length > 0 || Object.keys(state.bindings).length > 0;\n\n if (daemon.isRunning()) {\n if (hasChanges) {\n console.log(pc.blue(`i ${t('wizard.final.runningChanges')}\\n`));\n console.log(pc.yellow(` ${t('wizard.final.configModified')}\\n`));\n const shouldRestart = await prompts.restartGateway();\n if (shouldRestart) {\n const spinner = ora(t('wizard.final.restarting')).start();\n await daemon.stop();\n const started = await daemon.start();\n if (started) {\n spinner.succeed(t('wizard.final.restarted'));\n } else {\n spinner.fail(t('wizard.final.startFailed', { error: daemon.getLastError() ?? 'unknown' }));\n }\n } else {\n console.log(pc.gray(` ${t('wizard.final.restartTip')}\\n`));\n }\n } else {\n console.log(pc.blue(`i ${t('wizard.final.running')}\\n`));\n console.log(pc.green(` ${t('wizard.final.runningReady')}\\n`));\n }\n } else {\n console.log(pc.blue(`i ${t('wizard.final.notRunning')}\\n`));\n if (hasChanges) {\n console.log(pc.yellow(` ${t('wizard.final.configModifiedStart')}\\n`));\n }\n const shouldStart = await prompts.restartGateway();\n if (shouldStart) {\n const spinner2 = ora(t('wizard.final.starting')).start();\n const started = await daemon.start();\n if (started) {\n spinner2.succeed(t('wizard.final.started'));\n } else {\n spinner2.fail(t('wizard.final.startFailed', { error: daemon.getLastError() ?? 'unknown' }));\n }\n } else {\n console.log(pc.gray(` ${t('wizard.final.startTip')}\\n`));\n }\n }\n\n console.log(pc.green(`\\n${t('wizard.final.done')}\\n`));\n return { action: 'next', next: 'done' };\n}\n","import { Command } from 'commander';\nimport { createReadStream } from 'fs';\nimport { stat, readFile } from 'fs/promises';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { readdirSync, statSync, existsSync } from 'fs';\n\ninterface SessionFile {\n sessionId: string;\n agentType: string;\n date: string;\n path: string;\n size: number;\n}\n\ninterface PersistedEvent {\n v: number;\n ts: string;\n type?: string;\n text?: string;\n tool?: { name?: string; input?: Record<string, unknown>; output?: string };\n [key: string]: unknown;\n}\n\nconst SESSIONS_DIR = join(homedir(), '.handsoff', 'sessions');\n\n/**\n * Format bytes to human readable string\n */\nfunction formatSize(bytes: number): string {\n if (bytes === 0) return '0B';\n const units = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n return `${size.toFixed(i === 0 ? 0 : 1)}${units[i]}`;\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * List all session files from the sessions directory\n */\nfunction listSessions(): SessionFile[] {\n const sessions: SessionFile[] = [];\n\n if (!existsSync(SESSIONS_DIR)) {\n return sessions;\n }\n\n const entries = readdirSync(SESSIONS_DIR, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(entry.name)) {\n const date = entry.name;\n const dateDir = join(SESSIONS_DIR, date);\n const files = readdirSync(dateDir);\n\n for (const fileName of files) {\n if (fileName.endsWith('.jsonl')) {\n const filePath = join(dateDir, fileName);\n const stats = statSync(filePath);\n\n // Parse filename: {agentType}-{sessionId}.jsonl\n // agentType is the first part, sessionId is everything after the first dash\n const match = fileName.match(/^([^-]+)-(.+)\\.jsonl$/);\n if (match) {\n const [, agentType, sessionId] = match;\n sessions.push({\n sessionId,\n agentType,\n date,\n path: filePath,\n size: stats.size,\n });\n }\n }\n }\n }\n }\n\n // Sort by date descending, then by sessionId\n return sessions.sort((a, b) => {\n if (a.date !== b.date) {\n return b.date.localeCompare(a.date);\n }\n return a.sessionId.localeCompare(b.sessionId);\n });\n}\n\n/**\n * Find session file by session ID (partial match supported)\n */\nfunction findSessionFile(sessionId: string): SessionFile | undefined {\n const sessions = listSessions();\n\n // Try exact match first\n const match = sessions.find(s => s.sessionId === sessionId);\n if (match) return match;\n\n // Try partial match\n const matches = sessions.filter(s => s.sessionId.includes(sessionId));\n if (matches.length === 1) {\n return matches[0];\n }\n\n if (matches.length > 1) {\n console.error(`Multiple sessions match \"${sessionId}\":`);\n for (const s of matches) {\n console.error(` - ${s.sessionId} (${s.agentType}, ${s.date})`);\n }\n return undefined;\n }\n\n return undefined;\n}\n\n/**\n * Format and print an event\n */\nfunction printEvent(event: PersistedEvent): void {\n const timestamp = new Date(event.ts);\n const timeStr = timestamp.toTimeString().split(' ')[0]; // HH:MM:SS\n\n const type = event.type || 'unknown';\n const typeStr = type.padEnd(16);\n\n let content = '';\n if (event.tool?.name) {\n content = `Tool: ${event.tool.name}`;\n } else if (event.text) {\n content = event.text;\n } else if (typeof event.content === 'string') {\n content = event.content;\n } else {\n // Try to extract meaningful content from other fields\n const { ...rest } = event;\n const keys = Object.keys(rest);\n if (keys.length > 0) {\n content = `${keys[0]}: ${JSON.stringify(rest[keys[0]])}`;\n }\n }\n\n // Truncate long content\n if (content.length > 60) {\n content = content.substring(0, 57) + '...';\n }\n\n console.log(`[${timeStr}] ${typeStr} ${content}`);\n}\n\n/**\n * Read all events from a session file\n */\nasync function* readEvents(filePath: string): AsyncIterable<PersistedEvent> {\n if (!existsSync(filePath)) {\n return;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.length > 0);\n\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as PersistedEvent;\n yield event;\n } catch {\n // Skip invalid JSON lines\n continue;\n }\n }\n}\n\n/**\n * Display list of all sessions\n */\nasync function showSessionList(): Promise<void> {\n const sessions = listSessions();\n\n if (sessions.length === 0) {\n console.log('No sessions found.');\n console.log(`Sessions directory: ${SESSIONS_DIR}`);\n return;\n }\n\n console.log('Sessions:\\n');\n console.log(` Agent Session ID Date Size`);\n console.log(` --------- ------------------------ ---------- ------`);\n\n for (const session of sessions) {\n const agentStr = session.agentType.padEnd(9);\n const sessionStr = session.sessionId.padEnd(24).substring(0, 24);\n const dateStr = session.date;\n const sizeStr = formatSize(session.size).padStart(6);\n console.log(` ${agentStr} ${sessionStr} ${dateStr} ${sizeStr}`);\n }\n}\n\n/**\n * Tail a session file in real-time\n */\nasync function tailSession(sessionId: string): Promise<void> {\n const session = findSessionFile(sessionId);\n if (!session) {\n console.error(`Session not found: ${sessionId}`);\n process.exit(1);\n }\n\n console.log(`Tailing session: ${session.sessionId} (${session.agentType})`);\n console.log(`File: ${session.path}`);\n console.log('Press Ctrl+C to exit\\n');\n\n // Read and display existing content first\n for await (const event of readEvents(session.path)) {\n printEvent(event);\n }\n\n // Get current file size\n let lastSize = (await stat(session.path)).size;\n\n // Set up Ctrl+C handler\n let running = true;\n process.on('SIGINT', () => {\n running = false;\n console.log('\\n');\n process.exit(0);\n });\n\n // Poll for new content\n while (running) {\n await sleep(1000);\n\n try {\n const stats = await stat(session.path);\n if (stats.size > lastSize) {\n // Read new content\n const stream = createReadStream(session.path, {\n start: lastSize,\n encoding: 'utf-8',\n });\n\n let newContent = '';\n stream.on('data', (chunk) => {\n newContent += chunk;\n });\n\n await new Promise<void>((resolve) => {\n stream.on('end', () => resolve());\n stream.on('error', () => resolve());\n });\n\n // Parse and print new lines\n const lines = newContent.split('\\n').filter(line => line.trim());\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as PersistedEvent;\n printEvent(event);\n } catch {\n // Skip invalid JSON\n }\n }\n\n lastSize = stats.size;\n }\n } catch (error) {\n // File might have been deleted, exit gracefully\n console.error('\\nError reading session file:', error);\n break;\n }\n }\n}\n\n/**\n * Replay a session with original timing\n */\nasync function replaySession(sessionId: string): Promise<void> {\n const session = findSessionFile(sessionId);\n if (!session) {\n console.error(`Session not found: ${sessionId}`);\n process.exit(1);\n }\n\n console.log(`Replaying session: ${session.sessionId} (${session.agentType})`);\n console.log(`File: ${session.path}\\n`);\n\n const events: PersistedEvent[] = [];\n for await (const event of readEvents(session.path)) {\n events.push(event);\n }\n\n if (events.length === 0) {\n console.log('No events in session.');\n return;\n }\n\n // Set up Ctrl+C handler\n let running = true;\n process.on('SIGINT', () => {\n running = false;\n console.log('\\nReplay interrupted.');\n process.exit(0);\n });\n\n let lastTimestamp: number | null = null;\n\n for (const event of events) {\n if (!running) break;\n\n const currentTimestamp = new Date(event.ts).getTime();\n\n if (lastTimestamp !== null) {\n const delay = currentTimestamp - lastTimestamp;\n // Cap delay at 1 second for replay\n const replayDelay = Math.min(delay, 1000);\n if (replayDelay > 0) {\n await sleep(replayDelay);\n }\n }\n\n printEvent(event);\n lastTimestamp = currentTimestamp;\n }\n\n console.log('\\nReplay complete.');\n}\n\nexport const logsCommand = new Command('logs')\n .description('View session logs')\n .option('-t, --tail <session>', 'Tail a live session')\n .option('-r, --replay <session>', 'Replay session with original timing')\n .action(async (options) => {\n try {\n if (options.tail) {\n await tailSession(options.tail);\n } else if (options.replay) {\n await replaySession(options.replay);\n } else {\n await showSessionList();\n }\n } catch (error) {\n console.error('Failed to read logs:', error);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { loadConfig } from '../config.js';\nimport { DaemonManager } from './daemon.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { t } from '../i18n/index.js';\n\n// TODO: Will be moved to adapters/agent/claude.ts\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nexport const statusCommand = new Command('status')\n .description('Show current status')\n .action(() => {\n const config = loadConfig();\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const daemon = new DaemonManager(pidFilePath, config.general.hook_server_port);\n\n console.log(`\\n${t('status.title')}\\n`);\n\n // Daemon status\n console.log(daemon.isRunning() ? t('status.daemon.running') : t('status.daemon.notRunning'));\n\n console.log(t('status.port', { port: config.general.hook_server_port }));\n console.log(`${t('status.logLevel', { level: config.general.log_level })}\\n`);\n\n // Channels\n console.log(t('status.channels'));\n console.log(` ${config.channel.telegram?.enabled ? t('status.telegram.enabled') : t('status.telegram.disabled')}`);\n console.log(` ${config.channel.feishu?.enabled ? t('status.feishu.enabled') : t('status.feishu.disabled')}\\n`);\n\n // Settings backup\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(backupPath)) {\n console.log(t('status.settingsBackup'));\n } else {\n console.log(t('status.settingsNoBackup'));\n }\n\n // Paths\n const home = homedir();\n console.log(`\\n${t('status.paths')}`);\n console.log(` ${t('status.pathConfig', { path: `${home}/.handsoff/config.toml` })}`);\n console.log(` ${t('status.pathLogs', { path: `${home}/.handsoff/logs/gateway.log` })}`);\n console.log(` ${t('status.pathBackup', { path: `${home}/.claude/settings.json.handsoff-backup` })}\\n`);\n });\n","import { Command } from 'commander';\nimport { DaemonManager } from './daemon.js';\nimport { loadConfig } from '../config.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { t } from '../i18n/index.js';\n\nexport const stopCommand = new Command('stop')\n .description('Stop the handsoff daemon and restore settings')\n .action(async () => {\n const config = loadConfig();\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const daemon = new DaemonManager(pidFilePath, config.general.hook_server_port);\n\n // Check if running\n if (!daemon.isRunning()) {\n console.log(t('cli.stop.notRunning'));\n } else {\n console.log(t('cli.stop.stopping'));\n const stopped = await daemon.stop();\n if (stopped) {\n console.log(t('cli.stop.stopped'));\n } else {\n console.error(t('cli.stop.failed'));\n }\n }\n\n // Restore Claude settings (TODO: move to adapters/agent/claude.ts)\n });\n","import { Command } from 'commander';\nimport { join } from 'path';\nimport { DaemonManager } from './daemon.js';\nimport { homedir } from 'os';\n\nimport { loadConfig } from '../config.js';\nimport { t } from '../i18n/index.js';\n\nconst PID_FILE = join(homedir(), '.handsoff', 'handsoff.pid');\n\nexport const gatewayCommand = new Command('gateway')\n .description('Manage handsoff Gateway daemon')\n .addCommand(\n new Command('start')\n .description('Start or restart the Gateway daemon')\n .option('-p, --port <port>', 'Port to listen on')\n .action(async (options) => {\n const config = loadConfig();\n const port = options.port ? parseInt(options.port, 10) : config.general.hook_server_port;\n const daemon = new DaemonManager(PID_FILE, port);\n\n // If already running, stop it first\n if (daemon.isRunning()) {\n console.log(t('gateway.stopping'));\n await daemon.stop();\n }\n\n const started = await daemon.start();\n if (started) {\n console.log(t('gateway.startedOnPort', { port }));\n } else {\n const error = daemon.getLastError();\n console.error(t('gateway.startFailed'));\n if (error) {\n console.error(t('gateway.error', { error }));\n }\n const logPath = join(homedir(), '.handsoff', 'logs', 'gateway.log');\n console.error(` ${t('gateway.checkLogs', { path: logPath })}`);\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('stop')\n .description('Stop the Gateway daemon')\n .action(async () => {\n const config = loadConfig();\n const daemon = new DaemonManager(PID_FILE, config.general.hook_server_port);\n\n if (!daemon.isRunning()) {\n console.log(t('gateway.notRunning'));\n return;\n }\n\n console.log(t('gateway.stopping'));\n const stopped = await daemon.stop();\n if (stopped) {\n console.log(t('gateway.stopped'));\n } else {\n console.error(t('gateway.stopFailed'));\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('restart')\n .description('Restart the Gateway daemon')\n .option('-p, --port <port>', 'Port to listen on')\n .action(async (options) => {\n const config = loadConfig();\n const port = options.port ? parseInt(options.port, 10) : config.general.hook_server_port;\n const daemon = new DaemonManager(PID_FILE, port);\n\n await daemon.stop();\n const started = await daemon.start();\n\n if (started) {\n console.log(t('gateway.restartedOnPort', { port }));\n } else {\n const error = daemon.getLastError();\n console.error(t('gateway.restartFailed'));\n if (error) {\n console.error(t('gateway.error', { error }));\n }\n const logPath = join(homedir(), '.handsoff', 'logs', 'gateway.log');\n console.error(` ${t('gateway.checkLogs', { path: logPath })}`);\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('status')\n .description('Check Gateway status')\n .action(async () => {\n const config = loadConfig();\n try {\n const response = await fetch(`http://localhost:${config.general.hook_server_port}/status`);\n if (response.ok) {\n const status = await response.json() as { running?: boolean; sessions?: Array<{ agentType?: string; sessionId?: string; id?: string }>; clients?: number };\n console.log(t('gateway.status.title'));\n console.log(` ${t('gateway.status.running', { value: status.running ?? true })}`);\n console.log(` ${t('gateway.status.sessions', { count: status.sessions?.length ?? (typeof status.sessions === 'number' ? status.sessions : 0) })}`);\n console.log(` ${t('gateway.status.clients', { count: status.clients ?? 0 })}`);\n\n if (status.sessions && status.sessions.length > 0) {\n console.log(`\\n ${t('gateway.status.activeSessions')}`);\n for (const session of status.sessions) {\n const agentType = session.agentType || 'unknown';\n const sessionId = session.sessionId || session.id || 'unknown';\n console.log(` - ${agentType}/${sessionId}`);\n }\n }\n } else {\n console.log(t('gateway.status.notResponding'));\n }\n } catch {\n console.log(t('gateway.status.notRunning'));\n }\n })\n );\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { t } from '../../i18n/index.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Debug command for capturing and inspecting raw hook payloads\n */\nexport const debugCommand = new Command('debug')\n .description('Debug tools for Handsoff')\n .addCommand(\n new Command('hooks')\n .description('Capture and log raw hook payloads for debugging')\n .option('-p, --port <port>', 'Port to listen on', '16792')\n .action(async (options) => {\n const port = parseInt(options.port, 10);\n\n console.log(t('cli.debug.starting', { port }));\n console.log(t('cli.debug.capturing'));\n console.log(t('cli.debug.pressCtrlC'));\n\n // Run the hook-capture script\n const captureScript = join(__dirname, 'hook-capture.js');\n const proc = spawn('node', [captureScript], {\n stdio: 'inherit',\n env: { ...process.env, HANDSOFF_DEBUG_PORT: String(port) },\n });\n\n proc.on('exit', (code) => {\n process.exit(code || 0);\n });\n\n // Handle Ctrl+C\n process.on('SIGINT', () => {\n console.log(t('cli.debug.stopping'));\n proc.kill('SIGINT');\n });\n })\n );\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { DaemonManager } from '../daemon.js';\nimport { mergeHooks, type HookEntry } from '../../shared/settings-merge.js';\nimport { loadConfig } from '../../config.js';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { readPidFile } from '../../shared/pidfile.js';\nimport { t } from '../../i18n/index.js';\n\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nfunction backupSettings(settingsPath: string): void {\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(settingsPath)) {\n writeFileSync(backupPath, readFileSync(settingsPath, 'utf-8'));\n }\n}\n\nfunction writeSettings(settingsPath: string, settings: Record<string, unknown>): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n}\n\n/**\n * Generate unified hooks configuration\n *\n * Uses a single endpoint (/hook/{token}/event) for all events,\n * with the event type passed in the request body.\n *\n * This allows different CLI tools to use the same URL structure.\n */\nfunction generateHooksConfig(port: number, token: string): Record<string, HookEntry[]> {\n const unifiedUrl = `http://localhost:${port}/hook/${token}/event`;\n const createHookEntry = (): HookEntry => ({\n matcher: '',\n hooks: [{ type: 'http', url: unifiedUrl }],\n });\n\n return {\n Stop: [createHookEntry()],\n PostToolUse: [createHookEntry()],\n PostToolUseFailure: [createHookEntry()],\n Notification: [createHookEntry()],\n PreToolUse: [createHookEntry()],\n SubagentStart: [createHookEntry()],\n SubagentStop: [createHookEntry()],\n SessionStart: [createHookEntry()],\n SessionEnd: [createHookEntry()],\n UserPromptSubmit: [createHookEntry()],\n PermissionRequest: [createHookEntry()],\n };\n}\n\nexport function registerClaudeCommand(program: Command) {\n program\n .command('claude')\n .description('Start Claude Code with handsoff integration')\n .option('-d, --directory <dir>', 'Working directory for Claude')\n .action(async (options) => {\n const config = loadConfig();\n const port = config.general.hook_server_port;\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n\n // Step 1: Ensure daemon is running\n const daemon = new DaemonManager(pidFilePath, port);\n let daemonStarted = false;\n\n if (daemon.isRunning()) {\n console.log(t('cli.agent.alreadyRunning'));\n daemonStarted = true;\n } else {\n console.log(t('cli.agent.starting'));\n daemonStarted = await daemon.start();\n if (!daemonStarted) {\n console.error(t('cli.agent.startFailed'));\n process.exit(1);\n }\n console.log(t('cli.agent.started'));\n }\n\n // Step 2: Inject hooks into Claude settings\n console.log(t('cli.agent.configuring'));\n\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n\n // Create backup if not exists\n if (!existsSync(backupPath)) {\n backupSettings(settingsPath);\n console.log(t('cli.agent.settingsBacked'));\n }\n\n // Read token from daemon PID file\n const pidData = readPidFile(pidFilePath);\n const token = pidData?.token;\n if (!token) {\n console.error(t('cli.agent.tokenNotFound'));\n process.exit(1);\n }\n\n // Generate hooks config with daemon's token\n const hooksConfig = generateHooksConfig(port, token);\n\n // Read current settings and merge\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n }\n\n const mergedSettings = mergeHooks(currentSettings, hooksConfig);\n writeSettings(settingsPath, mergedSettings);\n console.log(t('cli.agent.hooksConfigured'));\n\n // Step 3: Launch Claude\n const workDir = options.directory || process.cwd();\n\n console.log(t('cli.agent.startingIn', { dir: workDir }));\n console.log(t('cli.agent.pressCtrlC') + '\\n');\n\n const claudeProcess = spawn('claude', [], {\n cwd: workDir,\n stdio: 'inherit',\n shell: true,\n });\n\n claudeProcess.on('exit', (code) => {\n console.log(t('cli.agent.exited', { code }));\n console.log(t('cli.agent.daemonRunning'));\n console.log(t('cli.agent.tipStop'));\n process.exit(code || 0);\n });\n\n // Handle Ctrl+C in this process\n process.on('SIGINT', () => {\n console.log(t('cli.agent.detaching'));\n claudeProcess.kill('SIGINT');\n });\n });\n}\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { DaemonManager } from '../daemon.js';\nimport { loadConfig } from '../../config.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { t } from '../../i18n/index.js';\nimport { createAgentLogger } from '../../shared/logger.js';\n\nfunction isCodexInstalled(): boolean {\n try {\n execSync('codex --version', { encoding: 'utf8', stdio: 'pipe', windowsHide: true });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getCodexVersion(): string | undefined {\n try {\n return execSync('codex --version', { encoding: 'utf8', stdio: 'pipe', windowsHide: true }).trim();\n } catch {\n return undefined;\n }\n}\n\nexport function registerCodexCommand(program: Command) {\n program\n .command('codex')\n .description('Start Codex CLI with handsoff integration')\n .option('-d, --directory <dir>', 'Working directory for Codex')\n .action(async (options) => {\n const version = getCodexVersion();\n\n // Check if Codex is installed\n if (!isCodexInstalled()) {\n console.error('\\n' + t('cli.codex.notInstalled') + '\\n');\n console.error(t('cli.codex.installMethods') + '\\n');\n console.error(t('cli.codex.option1npm') + '\\n');\n console.error(t('cli.codex.option2brew') + '\\n');\n console.error(t('cli.codex.alternative') + '\\n');\n process.exit(1);\n }\n\n const config = loadConfig();\n const port = config.general.hook_server_port;\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n\n // Step 1: Ensure daemon is running\n const daemon = new DaemonManager(pidFilePath, port);\n let daemonStarted = false;\n\n if (daemon.isRunning()) {\n console.log(t('cli.codex.alreadyRunning'));\n daemonStarted = true;\n } else {\n console.log(t('cli.codex.starting'));\n daemonStarted = await daemon.start();\n if (!daemonStarted) {\n console.error(t('cli.codex.startFailed'));\n process.exit(1);\n }\n console.log(t('cli.codex.started'));\n }\n\n // Step 2: Verify daemon has Codex adapter enabled\n if (!config.agent.codex?.enabled) {\n console.error(t('cli.codex.notEnabled'));\n console.error(t('cli.codex.enableHint'));\n process.exit(1);\n }\n\n // Step 3: Launch Codex with user's local configuration\n const workDir = options.directory || process.cwd();\n const codexCommand = config.agent.codex?.command?.[0] || 'codex';\n const codexArgs = config.agent.codex?.command?.slice(1) || ['app-server', '--listen', 'stdio://'];\n\n console.log(t('cli.codex.startingIn', { dir: workDir, version: version || 'unknown' }));\n console.log(t('cli.codex.pressCtrlC') + '\\n');\n\n const codexProcess = spawn(codexCommand, codexArgs, {\n cwd: workDir,\n stdio: 'inherit',\n shell: true,\n });\n\n const logger = createAgentLogger('codex');\n logger.info({ command: codexCommand, args: codexArgs, cwd: workDir }, 'Codex CLI spawned');\n\n codexProcess.on('exit', (code) => {\n logger.info({ code }, 'Codex CLI exited');\n console.log(t('cli.codex.exited', { code }));\n console.log(t('cli.codex.daemonRunning'));\n process.exit(code || 0);\n });\n\n codexProcess.on('error', (err) => {\n logger.error({ error: err.message }, 'Codex CLI spawn failed');\n });\n\n process.on('SIGINT', () => {\n console.log(t('cli.codex.detaching'));\n codexProcess.kill('SIGINT');\n });\n\n process.on('SIGTERM', () => {\n console.log(t('cli.codex.detaching'));\n codexProcess.kill('SIGTERM');\n });\n });\n}","import pino from 'pino';\nimport { mkdirSync, existsSync, appendFileSync } from 'fs';\nimport { dirname } from 'path';\nimport { hostname } from 'os';\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\nlet fileLogger: pino.Logger | null = null;\nlet consoleLogger: pino.Logger | null = null;\nlet currentLogLevel: LogLevel = LogLevel.INFO;\n\nfunction createSyncLogger(logFilePath: string, minLevel: LogLevel = LogLevel.INFO): pino.Logger {\n const hostnameValue = hostname();\n\n const writeLog = (level: string, msg: string, obj?: object) => {\n try {\n const logDir = dirname(logFilePath);\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n const logEntry: Record<string, unknown> = {\n level,\n time: Date.now(),\n msg,\n pid: process.pid,\n hostname: hostnameValue,\n ...obj,\n };\n const line = JSON.stringify(logEntry) + '\\n';\n appendFileSync(logFilePath, line);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`[Logger] Failed to write to ${logFilePath}:`, err);\n }\n };\n\n const log = (logLevel: string) => {\n const minLevelNum = LOG_LEVEL_MAP[minLevel] ?? LOG_LEVEL_MAP.info;\n const callLevelNum = LOG_LEVEL_MAP[logLevel] ?? LOG_LEVEL_MAP.info;\n return (obj: object | string, msg?: string) => {\n if (callLevelNum < minLevelNum) return;\n if (typeof obj === 'string') {\n writeLog(logLevel, obj);\n } else {\n writeLog(logLevel, msg || '', obj);\n }\n };\n };\n\n const createChild = (_bindings: object): pino.Logger => {\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n };\n\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n\nexport function setupFileLogging(logFilePath: string, level: LogLevel = LogLevel.INFO): pino.Logger {\n currentLogLevel = level;\n fileLogger = createSyncLogger(logFilePath, level);\n return fileLogger;\n}\n\nexport function getFileLogger(): pino.Logger | null {\n return fileLogger;\n}\n\nexport function createChannelLogger(channelName: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/channels/${channelName}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createAgentLogger(agentType: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/agents/${agentType}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createSessionLogger(sessionId: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const date = new Date().toISOString().split('T')[0];\n const logFile = `${homedir}/.handsoff/logs/sessions/${date}/${sessionId}.jsonl`;\n\n // Session logs are always written (NDJSON timeline), ignore currentLogLevel\n return createSyncLogger(logFile, LogLevel.DEBUG);\n}\n\nexport function getLogger(_level?: LogLevel): pino.Logger {\n if (!consoleLogger) {\n // Prefer fileLogger's level if set, otherwise use provided level or default to INFO\n const effectiveLevel = _level ?? (fileLogger ? (fileLogger as unknown as { level: string }).level as LogLevel : LogLevel.INFO);\n consoleLogger = pino({\n level: effectiveLevel,\n });\n }\n\n const delegate = (method: 'info' | 'warn' | 'error' | 'debug') => {\n return (obj: object | string, msg?: string) => {\n const target = fileLogger || consoleLogger;\n if (target) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (target as any)[method](obj, msg);\n }\n };\n };\n\n return {\n info: delegate('info'),\n warn: delegate('warn'),\n error: delegate('error'),\n debug: delegate('debug'),\n child: () => getLogger(_level),\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n","import { Command } from 'commander';\nimport { registerClaudeCommand } from './claude.js';\nimport { registerCodexCommand } from './codex.js';\n\nexport function registerAgentCommands(program: Command) {\n registerClaudeCommand(program);\n registerCodexCommand(program);\n}\n"],"mappings":"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","names":["Command","existsSync","readFileSync","writeFileSync","mkdirSync","homedir","join","dirname","readFileSync","existsSync","join","homedir","join","homedir","existsSync","writeFileSync","readFileSync","mkdirSync","dirname","Command","existsSync","join","homedir","confirm","existsSync","join","homedir","writeFileSync","mkdirSync","join","homedir","TOML","join","homedir","mkdirSync","TOML","writeFileSync","readFileSync","existsSync","join","homedir","join","homedir","existsSync","readFileSync","execSync","writeFileSync","existsSync","readFileSync","mkdirSync","dirname","input","generateHooksConfig","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","pc","pc","pc","ora","STEP","pc","pc","STEP","pc","STEP","pc","STEP","pc","STEP","join","dirname","mkdirSync","existsSync","writeFileSync","readFileSync","existsSync","existsSync","readFileSync","homedir","join","mkdirSync","__dirname","dirname","existsSync","join","homedir","pc","ora","join","homedir","existsSync","Command","join","homedir","existsSync","confirm","Command","homedir","join","existsSync","Command","homedir","join","existsSync","getSettingsPath","join","homedir","Command","existsSync","Command","homedir","join","Command","join","homedir","Command","join","homedir","join","homedir","Command","Command","spawn","fileURLToPath","dirname","join","__filename","fileURLToPath","__dirname","dirname","Command","join","spawn","spawn","homedir","join","dirname","readFileSync","existsSync","writeFileSync","mkdirSync","getSettingsPath","join","homedir","backupSettings","existsSync","writeFileSync","readFileSync","writeSettings","mkdirSync","dirname","generateHooksConfig","program","spawn","spawn","homedir","join","execSync","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","homedir","execSync","program","join","homedir","spawn","program","Command"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/attach.ts","../../src/shared/settings-merge.ts","../../src/shared/credentials.ts","../../src/config.ts","../../src/i18n/index.ts","../../src/i18n/locales/en.ts","../../src/cli/init.ts","../../src/cli/wizard/engine.ts","../../src/cli/wizard/state.ts","../../src/cli/wizard/applicator.ts","../../src/cli/wizard/detectors/claude.ts","../../src/cli/wizard/detectors/codex.ts","../../src/cli/wizard/prompts.ts","../../src/cli/wizard/steps/cli.ts","../../src/cli/wizard/detectors/channel.ts","../../src/cli/wizard/steps/channel-menu.ts","../../src/cli/wizard/steps/channel-config.ts","../../src/cli/wizard/steps/channel-notify.ts","../../src/cli/wizard/steps/agent-select.ts","../../src/shared/channelInstance.ts","../../src/cli/wizard/steps/channel-select.ts","../../src/cli/wizard/steps/binding-confirm.ts","../../src/cli/wizard/steps/pair-continue.ts","../../src/cli/daemon.ts","../../src/shared/pidfile.ts","../../src/cli/wizard/steps/final.ts","../../src/cli/logs.ts","../../src/cli/status.ts","../../src/cli/stop.ts","../../src/cli/gateway.ts","../../src/cli/debug/index.ts","../../src/cli/agent/claude.ts","../../src/cli/agent/codex.ts","../../src/shared/logger.ts","../../src/cli/agent/index.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { attachCommand } from './attach.js';\nimport { initCommand } from './init.js';\nimport { logsCommand } from './logs.js';\nimport { statusCommand } from './status.js';\nimport { stopCommand } from './stop.js';\nimport { gatewayCommand } from './gateway.js';\nimport { debugCommand } from './debug/index.js';\nimport { registerAgentCommands } from './agent/index.js';\n\nconst program = new Command();\n\nprogram\n .name('handsoff')\n .description('Leave your desk, not your code. Remote control for AI coding assistants via messaging platforms')\n .version('0.1.0');\n\nprogram.addCommand(attachCommand);\nprogram.addCommand(debugCommand);\nprogram.addCommand(initCommand);\nprogram.addCommand(logsCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(stopCommand);\nprogram.addCommand(gatewayCommand);\n\n// Register agent shortcut commands (e.g., handsoff claude)\nregisterAgentCommands(program);\n\nprogram.parse(process.argv);\n","import { Command } from 'commander';\nimport { mergeHooks } from '../shared/settings-merge.js';\nimport { getHookToken } from '../shared/credentials.js';\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { loadConfig } from '../config.js';\nimport { t } from '../i18n/index.js';\n\n// TODO: These will be migrated to adapters/agent/claude.ts\ntype HookEntry = {\n matcher: string;\n hooks: Array<{ type: string; url: string }>;\n};\n\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nfunction backupSettings(settingsPath: string): void {\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(settingsPath)) {\n writeFileSync(backupPath, readFileSync(settingsPath, 'utf-8'));\n }\n}\n\nfunction writeSettings(settingsPath: string, settings: Record<string, unknown>): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n}\n\nfunction getGatewayBaseUrl(port: number): string {\n return `http://localhost:${port}`;\n}\n\nasync function checkGatewayHealth(port: number): Promise<boolean> {\n try {\n const response = await fetch(`${getGatewayBaseUrl(port)}/health`, {\n method: 'GET',\n signal: AbortSignal.timeout(5000),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nfunction generateHooksConfig(token: string, port: number): Record<string, HookEntry[]> {\n const baseUrl = `${getGatewayBaseUrl(port)}/hook/${token}`;\n\n // Create hook entries with empty matcher (matches all)\n const createHookEntry = (event: string): HookEntry => ({\n matcher: '',\n hooks: [{ type: 'http', url: `${baseUrl}/${event}` }],\n });\n\n return {\n Stop: [createHookEntry('Stop')],\n SessionStart: [createHookEntry('SessionStart')],\n SessionEnd: [createHookEntry('SessionEnd')],\n UserPromptSubmit: [createHookEntry('UserPromptSubmit')],\n PermissionRequest: [createHookEntry('PermissionRequest')],\n };\n}\n\nexport const attachCommand = new Command('attach')\n .description('Attach an agent to the Gateway')\n .argument('<agent-type>', 'Agent type (e.g., claude)')\n .action(async (agentType: string) => {\n // Load config first to get the correct port\n const config = loadConfig();\n const gatewayPort = config.general.hook_server_port;\n\n // Step 1: Check Gateway is running\n console.log(t('cli.attach.checking'));\n const isHealthy = await checkGatewayHealth(gatewayPort);\n\n if (!isHealthy) {\n console.error(t('cli.attach.notRunning'));\n process.exit(1);\n }\n\n console.log(t('cli.attach.running'));\n\n // Step 2: Load hook token from credentials\n const hookToken = getHookToken();\n if (!hookToken) {\n console.error(t('cli.attach.tokenNotFound'));\n process.exit(1);\n }\n\n const token = hookToken.substring(0, 8) + '...';\n console.log(t('cli.attach.usingToken', { token }));\n\n // Step 3: Backup existing settings\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n\n if (!existsSync(backupPath)) {\n backupSettings(settingsPath);\n console.log(t('cli.attach.settingsBacked', { path: backupPath }));\n }\n\n // Step 4: Merge hooks into settings.json\n console.log(t('cli.attach.configuringHooks'));\n\n // Read current settings\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n }\n\n // Generate hooks config with the persistent token and port\n const hooksConfig = generateHooksConfig(hookToken, gatewayPort);\n\n // Merge hooks (preserving existing non-handsoff hooks)\n const mergedSettings = mergeHooks(currentSettings, hooksConfig);\n writeSettings(settingsPath, mergedSettings);\n\n // Step 5: Display success message\n console.log('');\n console.log(t('cli.attach.attached', { agent: agentType }));\n console.log('');\n console.log(t('cli.attach.connected'));\n console.log(t('cli.attach.start'));\n console.log('');\n console.log(t('cli.attach.forwarding'));\n console.log(t('cli.attach.tipStatus'));\n console.log(t('cli.attach.tipDetach'));\n });\n","// Inner hook configuration (the actual HTTP hook)\nexport interface HookConfig {\n type: string;\n url: string;\n}\n\n// Outer hook entry with matcher (Claude Code's format)\nexport interface HookEntry {\n matcher: string;\n hooks: HookConfig[];\n}\n\nexport interface ClaudeSettings {\n hooks?: Record<string, HookEntry[]>;\n [key: string]: unknown;\n}\n\n// Check if a hook config is from handsoff (by URL pattern)\nexport function isHandsoffHook(hook: HookConfig): boolean {\n return hook.type === 'http' && hook.url.includes('/hook/');\n}\n\n// Check if a hook entry contains handsoff hooks\nexport function isHandsoffEntry(entry: HookEntry): boolean {\n return entry.hooks.some(hook => isHandsoffHook(hook));\n}\n\nexport function extractTokenFromUrl(url: string): string | null {\n const match = url.match(/\\/hook\\/([^/]+)/);\n return match?.[1] || null;\n}\n\nexport function removeHandsoffHooks(settings: ClaudeSettings): ClaudeSettings {\n if (!settings.hooks) return settings;\n\n const cleanedHooks: Record<string, HookEntry[]> = {};\n\n for (const [eventName, entries] of Object.entries(settings.hooks)) {\n // Filter out entries that contain handsoff hooks\n const cleanedEntries = entries.filter(entry => !isHandsoffEntry(entry));\n if (cleanedEntries.length > 0) {\n cleanedHooks[eventName] = cleanedEntries;\n }\n }\n\n return { ...settings, hooks: cleanedHooks };\n}\n\nexport function mergeHooks(\n existing: ClaudeSettings,\n newHooks: Record<string, HookEntry[]>\n): ClaudeSettings {\n // Remove all existing handsoff hooks\n const cleaned = removeHandsoffHooks(existing);\n\n const mergedHooks: Record<string, HookEntry[]> = {};\n\n // Get all event names from both existing (cleaned) and new hooks\n const allEvents = new Set([\n ...Object.keys(cleaned.hooks || {}),\n ...Object.keys(newHooks)\n ]);\n\n for (const eventName of allEvents) {\n const existingEntries = cleaned.hooks?.[eventName] || [];\n const newEntries = newHooks[eventName] || [];\n\n // Filter out any new entries that already exist with same URL\n const existingUrls = new Set(\n existingEntries.flatMap(e => e.hooks.map(h => h.url))\n );\n const uniqueNewEntries = newEntries.filter(\n entry => !entry.hooks.some(h => existingUrls.has(h.url))\n );\n\n const merged = [...uniqueNewEntries, ...existingEntries];\n\n // Only include event if it has hooks\n if (merged.length > 0) {\n mergedHooks[eventName] = merged;\n }\n }\n\n return { ...cleaned, hooks: mergedHooks };\n}\n","import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { homedir } from 'os';\nimport { randomBytes } from 'crypto';\n\nexport interface Credentials {\n version: string;\n hookToken: string;\n createdAt: string;\n}\n\nconst CREDENTIALS_VERSION = '1';\nconst DEFAULT_TOKEN_LENGTH = 8;\n\nfunction getCredentialsPath(): string {\n return join(homedir(), '.handsoff', 'credentials.json');\n}\n\nfunction generateToken(): string {\n return randomBytes(DEFAULT_TOKEN_LENGTH).toString('hex');\n}\n\nexport function loadCredentials(): Credentials | null {\n const path = getCredentialsPath();\n\n if (!existsSync(path)) {\n return null;\n }\n\n try {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content) as Credentials;\n } catch (error) {\n console.error(`Failed to load credentials from ${path}:`, error);\n return null;\n }\n}\n\nexport function saveCredentials(credentials: Credentials): void {\n const path = getCredentialsPath();\n // Ensure directory exists before writing\n const dir = dirname(path);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(path, JSON.stringify(credentials, null, 2), { mode: 0o600 });\n}\n\nexport function getOrCreateHookToken(): string {\n const existing = loadCredentials();\n\n if (existing?.hookToken) {\n return existing.hookToken;\n }\n\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n\nexport function getHookToken(): string | null {\n return loadCredentials()?.hookToken ?? null;\n}\n\nexport function resetCredentials(): string {\n const newToken = generateToken();\n const credentials: Credentials = {\n version: CREDENTIALS_VERSION,\n hookToken: newToken,\n createdAt: new Date().toISOString(),\n };\n\n saveCredentials(credentials);\n return newToken;\n}\n","import { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport dotenv from 'dotenv';\n// Note: Notification types removed - using EventBus architecture now\n\n// Load .env file if exists\ndotenv.config();\n\nexport interface GeneralConfig {\n default_agent: string;\n log_level: string;\n hook_server_port: number;\n}\n\nexport interface TelegramConfig {\n enabled: boolean;\n bot_token: string;\n allowed_users: string[];\n notify_types?: string[];\n}\n\nexport interface FeishuConfig {\n enabled: boolean;\n app_id: string;\n app_secret: string;\n allowed_users?: string[];\n notify_types?: string[];\n}\n\nexport interface ClaudeAgentConfig {\n adapter?: 'hooks' | 'remote';\n binary: string;\n work_dir: string;\n model: string;\n permission_mode: string;\n}\n\nexport interface AgentPermissionConfig {\n lowRiskTools: string[];\n}\n\nexport interface CodexAgentConfig {\n enabled: boolean;\n command: string[];\n work_dir: string;\n model: string;\n approval_policy: string;\n sandbox_mode: string;\n}\n\nexport interface LoggerConfig {\n enabled: boolean;\n notify_types?: string[];\n}\n\nexport interface PermissionConfig {\n timeout_ms: number;\n default_on_timeout: 'allow' | 'deny';\n}\n\nexport interface ChannelConfig {\n logger?: LoggerConfig;\n telegram?: TelegramConfig;\n feishu?: FeishuConfig;\n permission?: PermissionConfig;\n}\n\nexport interface AppChannelConfig {\n enabled: boolean;\n channel_id: string;\n auth_token: string;\n heartbeat_interval_ms?: number;\n notify_types?: string[];\n}\n\nexport interface ChannelsConfig {\n app?: AppChannelConfig;\n}\n\nexport interface AgentConfig {\n claude?: ClaudeAgentConfig & { permission?: AgentPermissionConfig };\n codex?: CodexAgentConfig;\n}\n\nexport interface BindingsConfig {\n claude?: string; // \"channelType:channelInstanceId\" e.g. \"telegram:abc123\"\n codex?: string;\n}\n\nexport interface Config {\n general: GeneralConfig;\n channel: ChannelConfig;\n channels?: ChannelsConfig;\n agent: AgentConfig;\n bindings: BindingsConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n general: {\n default_agent: 'claude',\n log_level: 'info',\n hook_server_port: 9876,\n },\n channel: {\n logger: {\n enabled: true,\n },\n telegram: {\n enabled: true,\n bot_token: '',\n allowed_users: [],\n },\n feishu: {\n enabled: false,\n app_id: '',\n app_secret: '',\n allowed_users: [],\n notify_types: [],\n },\n permission: {\n timeout_ms: 300000, // 5 minutes\n default_on_timeout: 'deny',\n },\n },\n agent: {\n claude: {\n adapter: 'hooks',\n binary: 'claude',\n work_dir: '',\n model: '',\n permission_mode: '',\n permission: {\n lowRiskTools: ['Read', 'Glob', 'Grep', 'List', 'WebSearch', 'codesearch'],\n },\n },\n codex: {\n enabled: false,\n command: ['codex', 'app-server', '--listen', 'stdio://'],\n work_dir: '',\n model: '',\n approval_policy: '',\n sandbox_mode: '',\n },\n },\n channels: {},\n bindings: {},\n};\n\nfunction getConfigPath(): string {\n return join(homedir(), '.handsoff', 'config.toml');\n}\n\nfunction mergeWithDefaults(raw: any): Config {\n return {\n general: {\n ...DEFAULT_CONFIG.general,\n ...(raw.general || {}),\n hook_server_port: parseInt(\n process.env.HANDSOFF_HOOK_SERVER_PORT ||\n String(raw.general?.hook_server_port || DEFAULT_CONFIG.general.hook_server_port),\n 10\n ),\n },\n channel: {\n logger: {\n ...DEFAULT_CONFIG.channel.logger,\n ...(raw.channel?.logger || {}),\n notify_types: raw.channel?.logger?.notify_types,\n },\n telegram: {\n ...DEFAULT_CONFIG.channel.telegram,\n ...(raw.channel?.telegram || {}),\n allowed_users: (raw.channel?.telegram?.allowed_users || []).map(String),\n bot_token:\n process.env.HANDSOFF_TELEGRAM_BOT_TOKEN ||\n raw.channel?.telegram?.bot_token ||\n '',\n notify_types: raw.channel?.telegram?.notify_types,\n },\n feishu: {\n ...DEFAULT_CONFIG.channel.feishu,\n ...(raw.channel?.feishu || {}),\n allowed_users: raw.channel?.feishu?.allowed_users || [],\n app_id:\n process.env.HANDSOFF_FEISHU_APP_ID || raw.channel?.feishu?.app_id || '',\n app_secret:\n process.env.HANDSOFF_FEISHU_APP_SECRET ||\n raw.channel?.feishu?.app_secret ||\n '',\n notify_types: raw.channel?.feishu?.notify_types,\n },\n permission: {\n ...DEFAULT_CONFIG.channel.permission,\n ...(raw.channel?.permission || {}),\n // Support env var override\n timeout_ms: parseInt(\n process.env.HANDSOFF_PERMISSION_TIMEOUT_MS ||\n String(\n raw.channel?.permission?.timeout_ms ||\n DEFAULT_CONFIG.channel.permission!.timeout_ms\n ),\n 10\n ),\n default_on_timeout:\n (process.env.HANDSOFF_PERMISSION_DEFAULT as 'allow' | 'deny') ||\n raw.channel?.permission?.default_on_timeout ||\n DEFAULT_CONFIG.channel.permission!.default_on_timeout,\n },\n },\n agent: {\n claude: {\n ...DEFAULT_CONFIG.agent.claude,\n ...(raw.agent?.claude || {}),\n permission: {\n ...DEFAULT_CONFIG.agent.claude!.permission,\n ...(raw.agent?.claude?.permission || {}),\n },\n },\n codex: {\n ...DEFAULT_CONFIG.agent.codex!,\n ...(raw.agent?.codex || {}),\n command: raw.agent?.codex?.command\n ? raw.agent.codex.command\n : DEFAULT_CONFIG.agent.codex!.command,\n work_dir: raw.agent?.codex?.work_dir || DEFAULT_CONFIG.agent.codex!.work_dir,\n model: raw.agent?.codex?.model || DEFAULT_CONFIG.agent.codex!.model,\n approval_policy: raw.agent?.codex?.approval_policy || DEFAULT_CONFIG.agent.codex!.approval_policy,\n sandbox_mode: raw.agent?.codex?.sandbox_mode || DEFAULT_CONFIG.agent.codex!.sandbox_mode,\n },\n },\n channels: {\n ...DEFAULT_CONFIG.channels,\n ...(raw.channels || {}),\n app: raw.channels?.app\n ? {\n enabled: raw.channels.app.enabled === true,\n channel_id: String(raw.channels.app.channel_id || ''),\n auth_token: String(raw.channels.app.auth_token || ''),\n heartbeat_interval_ms: raw.channels.app.heartbeat_interval_ms\n ? parseInt(String(raw.channels.app.heartbeat_interval_ms), 10)\n : undefined,\n notify_types: Array.isArray(raw.channels.app.notify_types)\n ? raw.channels.app.notify_types.map(String)\n : undefined,\n }\n : DEFAULT_CONFIG.channels?.app,\n },\n bindings: {\n ...DEFAULT_CONFIG.bindings,\n ...(raw.bindings || {}),\n },\n };\n}\n\nexport function loadConfig(): Config {\n const configPath = getConfigPath();\n\n if (!existsSync(configPath)) {\n return DEFAULT_CONFIG;\n }\n\n try {\n const content = readFileSync(configPath, 'utf-8');\n const raw = TOML.parse(content) as any;\n return mergeWithDefaults(raw);\n } catch (error) {\n console.error(`Failed to load config from ${configPath}:`, error);\n return DEFAULT_CONFIG;\n }\n}\n","// src/i18n/index.ts\nimport './types.js';\nimport i18next from 'i18next';\nimport en from './locales/en.js';\n\nconst lng = process.env.HANDSOFF_LANG ?? 'en';\n\ni18next.init({\n initImmediate: false,\n lng,\n fallbackLng: 'en',\n resources: { en: { translation: en } },\n interpolation: { escapeValue: false },\n});\n\nexport const t = i18next.t.bind(i18next);\n","// src/i18n/locales/en.ts\nexport default {\n wizard: {\n section: {\n cli: '[ CLI Configuration ]',\n channel: '[ Channel Configuration ]',\n complete: '[ Setup Complete ]',\n },\n cli: {\n runAgain: 'Run init again when Claude Code is installed.',\n detected: 'Claude Code detected.',\n hooksInstalled: 'Hooks already installed.',\n hooksNotInstalled: 'Hooks not installed.',\n hooksTokenMismatch: 'Hooks have outdated token - reconfiguration required.',\n actionQuestion: 'Select action:',\n injectAction: 'Inject hooks configuration',\n updateAction: 'Update hooks configuration',\n backAction: 'Back',\n hookCheckbox: 'Select hooks:',\n noHooksSelected: 'No hooks selected, skipping injection.',\n injecting: 'Injecting hooks...',\n injected: 'Hooks injected',\n failed: 'Failed: {{error}}',\n remoteModeSkipHooks: 'Remote mode does not require hooks; skipping injection.',\n },\n channel: {\n configuring: 'Configuring {{channel}}',\n telegram: {\n botToken: 'Telegram bot token:',\n allowedUsers: 'Allowed Telegram user IDs (comma-separated):',\n testing: 'Testing Telegram connection...',\n connected: 'Connected to Telegram',\n sendingTest: 'Sending test message...',\n testSent: 'Test message sent',\n testContent: 'Handsoff test message',\n testWarning: 'Could not send test message (user may not have messaged bot yet)',\n apiError: 'API error: {{status}}',\n connFailed: 'Connection failed: {{error}}',\n },\n feishu: {\n appId: 'Feishu App ID:',\n appSecret: 'Feishu App Secret:',\n allowedUsers: 'Allowed User IDs (comma-separated, e.g., ou_xxx,oc_xxx):',\n required: 'app_id and app_secret are required. Skipping.',\n },\n },\n codex: {\n enable: 'Enable Codex agent integration?',\n command: 'Codex app-server command:',\n workDir: 'Default Codex working directory (optional):',\n model: 'Default Codex model (optional):',\n approvalPolicy: 'Default Codex approval policy (optional):',\n detected: 'Codex CLI detected.',\n notDetected: 'Codex CLI not found in PATH.',\n enabled: 'Codex integration enabled.',\n disabled: 'Codex integration disabled.',\n },\n notify: {\n title: 'Notification types for {{channel}}',\n checkbox: 'Notification types:',\n saved: 'Notification types saved for {{channel}}',\n },\n menu: {\n select: 'Select:',\n next: '--- Next ---',\n testFailed: 'Test failed. Action:',\n retry: 'Retry',\n reenter: 'Re-enter',\n backToMenu: 'Back to menu',\n restartQuestion: 'Restart Gateway now?',\n },\n final: {\n noItems: 'No items configured.',\n itemOk: '{{item}}: OK',\n running: 'Gateway is running',\n runningChanges: 'Gateway is running with pending changes',\n configModified: 'Configuration was modified. Restart required to apply changes.',\n runningReady: 'Gateway is already running and ready.',\n notRunning: 'Gateway is not running',\n configModifiedStart: 'Configuration was modified. Starting Gateway with new configuration.',\n restarting: 'Restarting...',\n restarted: 'Gateway restarted with new configuration',\n starting: 'Starting...',\n started: 'Gateway started',\n startFailed: 'Failed: {{error}}',\n restartTip: 'Run `handsoff gateway start` to restart.',\n startTip: 'Run `handsoff gateway start` to start.',\n done: 'Done.',\n },\n },\n\n gateway: {\n stopping: 'Stopping daemon...',\n startedOnPort: 'Gateway started on port {{port}}',\n stopped: 'Daemon stopped',\n notRunning: 'Daemon is not running',\n restartedOnPort: 'Gateway restarted on port {{port}}',\n startFailed: 'Failed to start Gateway',\n stopFailed: 'Failed to stop Gateway',\n restartFailed: 'Failed to restart Gateway',\n error: ' Error: {{error}}',\n checkLogs: 'Check logs at: {{path}}',\n status: {\n title: 'Gateway Status:',\n running: 'Running: {{value}}',\n sessions: 'Sessions: {{count}}',\n clients: 'Connected clients: {{count}}',\n activeSessions: 'Active sessions:',\n notResponding: 'Gateway is not responding',\n notRunning: 'Gateway is not running',\n },\n },\n\n daemon: {\n alreadyRunning: 'Daemon is already running',\n startedOnPort: 'Daemon started on port {{port}}',\n startFailed: 'Daemon failed to start. Check logs for details.',\n checkLogs: 'Check logs at: {{path}}',\n portInUse: 'Warning: Port {{port}} still in use after {{ms}}ms',\n startError: 'Failed to start daemon: {{error}}',\n lackingToken: 'Daemon is running but PID file lacks token, restarting...',\n scriptNotFound: 'Daemon script not found: {{path}}',\n },\n\n status: {\n title: '=== Handsoff Status ===',\n daemon: {\n running: 'Daemon: ✓ Running',\n notRunning: 'Daemon: ✗ Not running',\n },\n port: 'Port: {{port}}',\n logLevel: 'Log Level: {{level}}',\n channels: 'Channels:',\n telegram: {\n enabled: 'Telegram: ✓ Enabled',\n disabled: 'Telegram: ✗ Disabled',\n },\n feishu: {\n enabled: 'Feishu: ✓ Enabled',\n disabled: 'Feishu: ✗ Disabled',\n },\n settingsBackup: 'Settings: ✓ Backup exists',\n settingsNoBackup: 'Settings: ✗ No backup',\n paths: 'Paths:',\n pathConfig: 'Config: {{path}}',\n pathLogs: 'Logs: {{path}}',\n pathBackup: 'Backup: {{path}}',\n },\n\n cli: {\n init: {\n configExists: 'Configuration exists. Continue?',\n cancelled: 'Cancelled.',\n },\n stop: {\n notRunning: 'Handsoff daemon is not running',\n stopping: 'Stopping handsoff daemon...',\n stopped: 'Daemon stopped successfully',\n failed: 'Failed to stop daemon cleanly',\n },\n attach: {\n checking: 'Checking Gateway status...',\n running: 'Gateway is running',\n notRunning: 'Gateway is not running. Start it with: handsoff gateway start',\n tokenNotFound: 'Hook token not found. Please run \"handsoff init\" first.',\n attached: 'Successfully attached {{agent}} to Gateway',\n start: 'Start \"claude\" to begin a session.',\n usingToken: 'Using hook token: {{token}}',\n settingsBacked: 'Claude settings backed up to: {{path}}',\n configuringHooks: 'Configuring hooks in Claude settings...',\n connected: 'Your Claude Code is now connected to handsoff Gateway.',\n forwarding: 'Events will be forwarded to connected clients.',\n tipStatus: 'Use \"handsoff gateway status\" to check status',\n tipDetach: 'Use \"handsoff detach\" to remove hooks and restore settings',\n },\n agent: {\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n tokenNotFound: 'Failed to get token from daemon',\n hooksConfigured: 'Claude hooks configured',\n startingIn: 'Starting Claude Code in {{dir}}...',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n configuring: 'Configuring Claude Code...',\n settingsBacked: 'Claude settings backed up',\n exited: '\\nClaude Code exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n tipStop: 'Use \"handsoff stop\" to stop the daemon and restore settings',\n detaching: '\\nDetaching from Claude...',\n },\n codex: {\n notInstalled: 'Codex CLI is not installed',\n installMethods: 'Please install Codex CLI using one of these methods:',\n option1npm: 'Option 1 - npm (recommended): npm install -g @openai/codex',\n option2brew: 'Option 2 - Homebrew (macOS): brew install --cask codex',\n alternative: 'Alternatively, use Claude Code: handsoff claude',\n alreadyRunning: 'Handsoff daemon is already running',\n starting: 'Starting handsoff daemon...',\n started: 'Daemon started',\n startFailed: 'Failed to start daemon',\n notEnabled: 'Codex adapter is not enabled in handsoff config.',\n enableHint: 'Enable it with \"handsoff init\" or by setting agent.codex.enabled = true in ~/.handsoff/config.toml, then restart the daemon.',\n startingIn: 'Starting Codex CLI {{version}} in {{dir}}',\n pressCtrlC: 'Press Ctrl+C to stop (handsoff daemon will keep running)',\n exited: '\\nCodex CLI exited with code {{code}}',\n daemonRunning: 'Handsoff daemon is still running in the background',\n detaching: '\\nDetaching from Codex...',\n },\n debug: {\n starting: 'Starting hook debug server on port {{port}}',\n capturing: 'This will capture all incoming webhook requests...',\n pressCtrlC: 'Press Ctrl+C to stop.',\n stopping: '\\nStopping debug server...',\n },\n },\n\n notifications: {\n permission: {\n title: '🔐 Permission Request',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n args: 'Args: {{args}}',\n requestId: 'Request ID: {{requestId}}',\n allow: '✅ Allow',\n deny: '❌ Deny',\n },\n finished: {\n titleTelegram: '✅ Task Completed',\n titleLogger: '🏁 Task Completed',\n session: 'Session: {{sessionId}}',\n message: 'Message: {{message}}',\n eventType: 'Type: {{eventType}}',\n },\n sessionStart: {\n title: '🟢 Session Started',\n session: 'Session: {{sessionId}}',\n },\n error: {\n title: '❌ Error',\n session: 'Session: {{sessionId}}',\n tool: 'Tool: {{toolName}}',\n message: 'Message: {{message}}',\n },\n unauthorized: 'You are not authorized to use this bot.',\n received: 'Message received.',\n processingError: 'Error processing message.',\n },\n};\n","import { Command } from 'commander';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { confirm } from '@inquirer/prompts';\nimport { WizardEngine } from './wizard/engine.js';\nimport { t } from '../i18n/index.js';\nimport { getOrCreateHookToken, resetCredentials } from '../shared/credentials.js';\n\nexport const initCommand = new Command('init')\n .description('Initialize handsoff configuration')\n .option('-f, --force', 'Force reinitialize (regenerate token)')\n .action(async (options) => {\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n\n if (existsSync(configPath) && !options.force) {\n const overwrite = await confirm({\n message: t('cli.init.configExists'),\n default: false,\n });\n if (!overwrite) {\n console.log(t('cli.init.cancelled'));\n return;\n }\n }\n\n // Ensure hook token is created early, even if user skips CLI configuration\n // When --force is used, regenerate the token\n if (options.force) {\n resetCredentials();\n } else {\n getOrCreateHookToken();\n }\n\n const wizard = new WizardEngine();\n await wizard.run();\n });\n","import { existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { createInitialState, type WizardState, type WizardStep } from './state.js';\nimport { ConfigApplicator } from './applicator.js';\nimport { stepCli } from './steps/cli.js';\nimport { stepCliMenu } from './steps/channel-menu.js';\nimport { stepChannelConfig } from './steps/channel-config.js';\nimport { stepChannelNotify } from './steps/channel-notify.js';\nimport { stepAgentSelect } from './steps/agent-select.js';\nimport { stepChannelSelect } from './steps/channel-select.js';\nimport { stepBindingConfirm } from './steps/binding-confirm.js';\nimport { stepPairContinue } from './steps/pair-continue.js';\nimport { stepFinal } from './steps/final.js';\nimport { detectClaude } from './detectors/claude.js';\nimport { detectCodex } from './detectors/codex.js';\nimport { detectChannel } from './detectors/channel.js';\nimport { loadConfig } from '../../config.js';\n\nexport class WizardEngine {\n private state: WizardState;\n private applicator: ConfigApplicator;\n\n constructor() {\n const configPath = join(homedir(), '.handsoff', 'config.toml');\n const hasExistingConfig = existsSync(configPath);\n this.state = createInitialState(hasExistingConfig);\n this.applicator = new ConfigApplicator();\n }\n\n async run(): Promise<void> {\n await this.detectAllStatus();\n\n while (this.state.current !== 'done' && this.state.current !== 'quit') {\n if (this.state.current === 'final' && this.hasChanges()) {\n this.applicator.apply(this.state.pendingChanges, this.state.bindings);\n }\n\n const result = await this.runStep(this.state.current);\n\n if (result.action === 'next') {\n this.state.previous = this.state.current;\n this.state.current = result.next! as WizardStep;\n } else if (result.action === 'back') {\n this.state.current = this.state.previous || 'agent-select';\n } else if (result.action === 'quit') {\n this.state.current = 'quit';\n }\n }\n }\n\n private async detectAllStatus(): Promise<void> {\n const config = loadConfig();\n const claude = detectClaude();\n this.state.claudeDetection = claude;\n this.state.itemStatus.set('claude', claude.hooked ? 'configured' : 'unconfigured');\n\n const codex = detectCodex();\n this.state.codexDetection = codex;\n this.state.itemStatus.set(\n 'codex',\n config.agent.codex?.enabled ? 'configured' : (codex.installed ? 'detected' : 'not-found')\n );\n\n const channelNames = ['logger', 'telegram', 'feishu'] as const;\n for (const name of channelNames) {\n const detection = await detectChannel(name);\n if (detection.configured) {\n this.state.itemStatus.set(name, 'configured');\n } else if (detection.error) {\n this.state.itemStatus.set(name, 'error');\n }\n }\n }\n\n private async runStep(step: WizardStep) {\n switch (step) {\n case 'agent-select':\n return await stepAgentSelect(this.state);\n case 'channel-select':\n return await stepChannelSelect(this.state);\n case 'binding-confirm':\n return await stepBindingConfirm(this.state);\n case 'pair-continue':\n return await stepPairContinue(this.state);\n case 'cli':\n return await stepCli(this.state);\n case 'cli-menu':\n return await stepCliMenu(this.state);\n case 'channel-config':\n return await stepChannelConfig(this.state);\n case 'channel-notify':\n return await stepChannelNotify(this.state);\n case 'final':\n return await stepFinal(this.state);\n default:\n return { action: 'next', next: 'done' as const };\n }\n }\n\n private hasChanges(): boolean {\n return this.state.sessionConfigured.size > 0 ||\n Object.keys(this.state.pendingChanges).length > 0 ||\n Object.keys(this.state.bindings).length > 0;\n }\n}\n","import type { ClaudeDetection } from './detectors/claude.js';\nimport type { CodexDetection } from './detectors/codex.js';\n\nexport type WizardStep = 'cli' | 'cli-menu' | 'agent-select' | 'channel-select' | 'binding-confirm' | 'pair-continue' | 'channel-config' | 'channel-notify' | 'final' | 'done' | 'quit';\n\nexport type ItemStatus = 'configured' | 'unconfigured' | 'error' | 'detected' | 'not-found';\n\nexport interface WizardState {\n current: WizardStep;\n previous?: WizardStep;\n hasExistingConfig: boolean;\n claudeDetection?: ClaudeDetection;\n codexDetection?: CodexDetection;\n pendingChanges: {\n agent?: {\n claude?: Record<string, unknown>;\n codex?: Record<string, unknown>;\n };\n channel?: Record<string, Record<string, unknown>>;\n };\n bindings: Record<string, string>;\n itemStatus: Map<string, ItemStatus>;\n sessionConfigured: Set<string>;\n validationResults: Map<string, { ok: boolean; message?: string }>;\n currentAgentName?: string;\n currentChannelName?: string;\n currentCliName?: string;\n}\n\nexport function createInitialState(hasExistingConfig: boolean): WizardState {\n return {\n current: 'agent-select',\n hasExistingConfig,\n pendingChanges: {},\n bindings: {},\n itemStatus: new Map(),\n sessionConfigured: new Set(),\n validationResults: new Map(),\n };\n}\n","import { writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport TOML from '@iarna/toml';\nimport { loadConfig } from '../../config.js';\nimport type { WizardState } from './state.js';\n\nexport class ConfigApplicator {\n apply(pending: WizardState['pendingChanges'], bindings?: Record<string, string>): void {\n const current = loadConfig();\n\n const merged = {\n ...current,\n general: { ...current.general },\n channel: {\n ...current.channel,\n logger: pending.channel?.logger\n ? { ...(current.channel?.logger ?? {}), ...pending.channel.logger }\n : current.channel?.logger,\n telegram: pending.channel?.telegram\n ? { ...(current.channel?.telegram ?? {}), ...pending.channel.telegram }\n : current.channel?.telegram,\n feishu: pending.channel?.feishu\n ? { ...(current.channel?.feishu ?? {}), ...pending.channel.feishu }\n : current.channel?.feishu,\n permission: pending.channel?.permission\n ? { ...(current.channel?.permission ?? {}), ...pending.channel.permission }\n : current.channel?.permission,\n },\n agent: {\n ...current.agent,\n ...(pending.agent?.claude ? {\n claude: { ...(current.agent?.claude ?? {}), ...pending.agent.claude },\n } : {}),\n ...(pending.agent?.codex ? {\n codex: { ...(current.agent?.codex ?? {}), ...pending.agent.codex },\n } : {}),\n },\n };\n\n let finalConfig = merged;\n if (bindings && Object.keys(bindings).length > 0) {\n const finalBindings = { ...(merged.bindings || {}) } as Record<string, string>;\n for (const [agent, channelId] of Object.entries(bindings)) {\n // Remove conflicting bindings (another agent bound to same channel)\n for (const [a, cid] of Object.entries(finalBindings)) {\n if (cid === channelId && a !== agent) {\n delete finalBindings[a];\n }\n }\n finalBindings[agent] = channelId;\n }\n finalConfig = {\n ...merged,\n bindings: finalBindings,\n };\n }\n\n const configDir = join(homedir(), '.handsoff');\n mkdirSync(configDir, { recursive: true });\n const configPath = join(configDir, 'config.toml');\n const content = TOML.stringify(finalConfig as unknown as Parameters<typeof TOML.stringify>[0]);\n writeFileSync(configPath, content);\n }\n}\n","import { execSync } from 'child_process';\nimport { readFileSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport { getHookToken } from '../../../shared/credentials.js';\n\nexport interface ClaudeDetection {\n supported: boolean;\n hooked: boolean;\n tokenMismatch?: boolean;\n message: string;\n binaryPath?: string;\n settingsPath: string;\n}\n\nexport function detectClaude(): ClaudeDetection {\n const settingsPath = join(homedir(), '.claude', 'settings.json');\n\n let binaryPath: string | undefined;\n let supported = false;\n\n try {\n binaryPath = execSync('which claude', { encoding: 'utf-8' }).trim();\n supported = !!binaryPath;\n } catch {\n // claude not in PATH\n }\n\n if (!supported) {\n return {\n supported: false,\n hooked: false,\n message: 'Claude Code not found in PATH. Please install Claude Code first.',\n settingsPath,\n };\n }\n\n const currentToken = getHookToken();\n let hooked = false;\n let tokenMismatch = false;\n\n if (existsSync(settingsPath)) {\n try {\n const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n const hookStatus = checkHandsoffHooks(settings, currentToken);\n hooked = hookStatus.matched;\n tokenMismatch = hookStatus.mismatched;\n } catch {\n // malformed settings\n }\n }\n\n let message: string;\n if (hooked) {\n message = 'Claude Code hooks already configured.';\n } else if (tokenMismatch) {\n message = 'Claude Code hooks have mismatched token. Reconfiguration required.';\n } else {\n message = 'Claude Code detected.';\n }\n\n return {\n supported: true,\n hooked,\n tokenMismatch,\n message,\n binaryPath,\n settingsPath,\n };\n}\n\ninterface HookCheckResult {\n matched: boolean;\n mismatched: boolean;\n}\n\nfunction checkHandsoffHooks(settings: Record<string, unknown>, expectedToken: string | null): HookCheckResult {\n const hooks = settings.hooks as Record<string, unknown> | undefined;\n if (!hooks) return { matched: false, mismatched: false };\n\n let hasAnyHandsoffHook = false;\n let hasMatchingToken = false;\n\n for (const key of Object.keys(hooks)) {\n const entries = hooks[key] as unknown[];\n for (const entry of entries) {\n if (!entry || typeof entry !== 'object') continue;\n const e = entry as Record<string, unknown>;\n const inner = e.hooks;\n if (Array.isArray(inner)) {\n for (const h of inner) {\n const hookInfo = extractHandsoffHookInfo(h);\n if (hookInfo.isHandsoff) {\n hasAnyHandsoffHook = true;\n if (expectedToken && hookInfo.token === expectedToken) {\n hasMatchingToken = true;\n }\n }\n }\n }\n }\n }\n\n return {\n matched: hasMatchingToken,\n mismatched: hasAnyHandsoffHook && !hasMatchingToken,\n };\n}\n\nfunction extractHandsoffHookInfo(entry: unknown): { isHandsoff: boolean; token?: string } {\n if (!entry || typeof entry !== 'object') return { isHandsoff: false };\n const e = entry as Record<string, unknown>;\n if (e.type !== 'http') return { isHandsoff: false };\n const url = e.url as string;\n if (typeof url !== 'string') return { isHandsoff: false };\n\n // Check if it's a handsoff hook URL: http://localhost:{port}/hook/{token}/...\n const match = url.match(/^http:\\/\\/localhost:\\d+\\/hook\\/([^\\/]+)/);\n if (match) {\n return { isHandsoff: true, token: match[1] };\n }\n return { isHandsoff: false };\n}","import { execSync } from 'child_process';\n\nexport interface CodexDetection {\n supported: boolean;\n installed: boolean;\n message: string;\n binaryPath?: string;\n version?: string;\n}\n\nexport function detectCodex(): CodexDetection {\n let binaryPath: string | undefined;\n let installed = false;\n let version: string | undefined;\n\n try {\n binaryPath = execSync('which codex', { encoding: 'utf-8' }).trim();\n installed = !!binaryPath;\n version = execSync('codex --version', { encoding: 'utf-8', stdio: 'pipe' }).trim();\n } catch {\n // codex not in PATH\n }\n\n if (!installed) {\n return {\n supported: false,\n installed: false,\n message: 'Codex CLI not found in PATH. Please install Codex CLI first.',\n };\n }\n\n return {\n supported: true,\n installed: true,\n message: `Codex CLI ${version} detected.`,\n binaryPath,\n version,\n };\n}\n","import { t } from '../../i18n/index.js';\nimport { confirm, input, checkbox, select } from '@inquirer/prompts';\n\nexport const prompts = {\n feishuAppId: (current?: string) => input({\n message: t('wizard.channel.feishu.appId'),\n default: current || '',\n }),\n\n feishuAppSecret: (current?: string) => input({\n message: t('wizard.channel.feishu.appSecret'),\n default: current || '',\n }),\n\n feishuAllowedUsers: (current?: string) => input({\n message: t('wizard.channel.feishu.allowedUsers'),\n default: current || '',\n }),\n\n codexEnable: (enabled: boolean) => confirm({\n message: t('wizard.codex.enable'),\n default: enabled,\n }),\n\n codexCommand: (current?: string) => input({\n message: t('wizard.codex.command'),\n default: current || 'codex app-server --listen stdio://',\n }),\n\n codexWorkDir: (current?: string) => input({\n message: t('wizard.codex.workDir'),\n default: current || '',\n }),\n\n codexModel: (current?: string) => input({\n message: t('wizard.codex.model'),\n default: current || '',\n }),\n\n codexApprovalPolicy: (current?: string) => input({\n message: t('wizard.codex.approvalPolicy'),\n default: current || '',\n }),\n\n cliActionSelect: (hooked: boolean) => select({\n message: t('wizard.cli.actionQuestion'),\n choices: hooked\n ? [\n { name: t('wizard.cli.updateAction'), value: 'update' },\n { name: t('wizard.cli.backAction'), value: 'back' },\n ]\n : [\n { name: t('wizard.cli.injectAction'), value: 'inject' },\n { name: t('wizard.cli.backAction'), value: 'back' },\n ],\n }),\n\n claudeMode: () => select({\n message: 'Choose Claude integration mode:',\n choices: [\n { name: 'Hook mode (local one-way)', value: 'hooks' },\n { name: 'Remote mode (managed two-way)', value: 'remote' },\n ],\n }),\n\n cliHookSelect: (selected?: string[]) => checkbox({\n message: t('wizard.cli.hookCheckbox'),\n choices: [\n { name: 'Stop', value: 'Stop', checked: selected?.includes('Stop') ?? true },\n { name: 'SessionStart', value: 'SessionStart', checked: selected?.includes('SessionStart') ?? true },\n { name: 'SessionEnd', value: 'SessionEnd', checked: selected?.includes('SessionEnd') ?? true },\n { name: 'PermissionRequest', value: 'PermissionRequest', checked: selected?.includes('PermissionRequest') ?? true },\n { name: 'UserPromptSubmit', value: 'UserPromptSubmit', checked: selected?.includes('UserPromptSubmit') ?? false },\n { name: 'PostToolUse', value: 'PostToolUse', checked: selected?.includes('PostToolUse') ?? false },\n { name: 'PostToolUseFailure', value: 'PostToolUseFailure', checked: selected?.includes('PostToolUseFailure') ?? false },\n { name: 'Notification', value: 'Notification', checked: selected?.includes('Notification') ?? false },\n { name: 'SubagentStart', value: 'SubagentStart', checked: selected?.includes('SubagentStart') ?? false },\n { name: 'SubagentStop', value: 'SubagentStop', checked: selected?.includes('SubagentStop') ?? false },\n ],\n }),\n\n botToken: (current?: string) => input({\n message: t('wizard.channel.telegram.botToken'),\n default: current || '',\n }),\n\n allowedUsers: (current?: string) => input({\n message: t('wizard.channel.telegram.allowedUsers'),\n default: current || '',\n }),\n\n channelMenuSelect: (channels: Array<{ name: string; status: string }>) => select({\n message: t('wizard.menu.select'),\n choices: [\n ...channels.map(c => ({\n name: `${c.name} ${c.status}`,\n value: c.name,\n })),\n { name: t('wizard.menu.next'), value: '__next__' },\n ],\n }),\n\n notifyTypes: (selected?: string[]) => checkbox({\n message: t('wizard.notify.checkbox'),\n choices: [\n { name: 'permission_request', value: 'permission_request', checked: selected?.includes('permission_request') },\n { name: 'question_request', value: 'question_request', checked: selected?.includes('question_request') },\n { name: 'finished', value: 'finished', checked: selected?.includes('finished') },\n { name: 'session_start', value: 'session_start', checked: selected?.includes('session_start') },\n { name: 'error', value: 'error', checked: selected?.includes('error') },\n ],\n }),\n\n channelConfigError: () => select({\n message: t('wizard.menu.testFailed'),\n choices: [\n { name: t('wizard.menu.retry'), value: 'retry' },\n { name: t('wizard.menu.reenter'), value: 'reinput' },\n { name: t('wizard.menu.backToMenu'), value: 'skip' },\n ],\n }),\n\n restartGateway: () => confirm({\n message: t('wizard.menu.restartQuestion'),\n default: true,\n }),\n\n bindingAgentSelect: (agents: Array<{ name: string; value: string }>) => select({\n message: 'Select an agent to bind:',\n choices: agents.map(a => ({ name: a.name, value: a.value })),\n }),\n\n bindingConfirm: (agentName: string, channelName: string) => select({\n message: `🤖 Bind ${agentName} to ${channelName} — confirm?`,\n choices: [\n { name: 'Confirm binding', value: 'confirm' },\n { name: 'Cancel', value: 'cancel' },\n ],\n }),\n\n pairContinue: () => select({\n message: 'Add another pair?',\n choices: [\n { name: 'Add another pair', value: 'continue' },\n { name: 'Finish setup', value: 'finish' },\n ],\n }),\n\n agentSelect: (agents: Array<{ name: string; value: string; status: string }>) => select({\n message: 'Select an agent to configure:',\n choices: agents.map(a => ({ name: `${a.name} ${a.status}`, value: a.value })),\n }),\n\n channelSelect: (channels: Array<{ name: string; value: string; status: string }>) => select({\n message: 'Select a channel to configure:',\n choices: channels.map(c => ({ name: `${c.name} ${c.status}`, value: c.value })),\n }),\n};\n","import { detectClaude } from '../detectors/claude.js';\nimport { detectCodex } from '../detectors/codex.js';\nimport { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport { writeFileSync, existsSync, readFileSync, mkdirSync } from 'fs';\nimport { dirname } from 'path';\nimport { getOrCreateHookToken, getHookToken } from '../../../shared/credentials.js';\nimport { mergeHooks } from '../../../shared/settings-merge.js';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\nimport { execSync } from 'child_process';\n\nconst STEP = 'STEP 2';\n\nexport async function stepCli(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const cliName = state.currentCliName || 'claude';\n\n console.log(pc.bold(`\\n${STEP} — Configure Agent\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n if (cliName === 'claude') {\n const detection = state.claudeDetection ?? detectClaude();\n\n if (!detection.supported) {\n console.log(pc.yellow(`! ${detection.message}`));\n console.log(pc.gray(` ${t('wizard.cli.runAgain')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n console.log(pc.green(`* ${t('wizard.cli.detected')}`));\n console.log(pc.gray(` Settings: ${detection.settingsPath}`));\n\n const port = loadConfig().general.hook_server_port;\n const token = getHookToken();\n console.log(pc.gray(` Gateway: http://localhost:${port}/hook/${token ? token.substring(0, 8) + '...' : 'unknown'}`));\n\n if (detection.hooked) {\n console.log(pc.green(` ${t('wizard.cli.hooksInstalled')}`));\n } else if (detection.tokenMismatch) {\n console.log(pc.red(` ${t('wizard.cli.hooksTokenMismatch')}`));\n } else {\n console.log(pc.yellow(` ${t('wizard.cli.hooksNotInstalled')}`));\n }\n console.log('');\n\n const mode = await prompts.claudeMode();\n\n if (mode === 'hooks') {\n const action = await prompts.cliActionSelect(detection.hooked);\n if (action === 'back') {\n console.log('');\n return { action: 'next', next: 'cli-menu' };\n }\n\n const selectedHooks = await prompts.cliHookSelect();\n if (selectedHooks.length === 0) {\n console.log(pc.yellow(`! ${t('wizard.cli.noHooksSelected')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n const spinner = ora(t('wizard.cli.injecting')).start();\n try {\n injectClaudeHooks(detection.settingsPath, selectedHooks);\n spinner.succeed(t('wizard.cli.injected'));\n } catch (err) {\n spinner.fail(t('wizard.cli.failed', { error: String(err) }));\n state.itemStatus.set('claude', 'error');\n state.validationResults.set('claude', { ok: false, message: String(err) });\n return { action: 'next', next: 'cli-menu' };\n }\n } else {\n console.log(pc.yellow(`! ${t('wizard.cli.remoteModeSkipHooks')}`));\n try {\n execSync('claude --version', { stdio: 'ignore' });\n } catch {\n console.log(pc.yellow('! claude CLI not found in PATH; remote mode may not work until it is installed.'));\n }\n }\n\n state.itemStatus.set('claude', 'configured');\n state.sessionConfigured.add('claude');\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n claude: {\n ...(state.pendingChanges.agent?.claude || {}),\n adapter: mode,\n },\n };\n state.validationResults.set('claude', { ok: true });\n return { action: 'next', next: 'channel-select' };\n }\n\n if (cliName === 'codex') {\n const detection = state.codexDetection ?? detectCodex();\n const config = loadConfig();\n const current = config.agent.codex;\n\n if (!detection.installed) {\n console.log(pc.yellow(`! ${t('wizard.codex.notDetected')}`));\n console.log(pc.gray(` ${detection.message}\\n`));\n state.itemStatus.set('codex', 'not-found');\n state.validationResults.set('codex', { ok: false, message: detection.message });\n return { action: 'next', next: 'cli-menu' };\n }\n\n console.log(pc.green(`* ${t('wizard.codex.detected')}`));\n console.log(pc.gray(` Binary: ${detection.binaryPath}`));\n console.log(pc.gray(` Version: ${detection.version || 'unknown'}`));\n console.log('');\n\n const enabled = await prompts.codexEnable(current?.enabled === true);\n\n if (!enabled) {\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n codex: {\n ...(current || {}),\n enabled: false,\n },\n };\n state.itemStatus.set('codex', 'unconfigured');\n state.validationResults.set('codex', { ok: true, message: t('wizard.codex.disabled') });\n console.log(pc.gray(` ${t('wizard.codex.disabled')}\\n`));\n return { action: 'next', next: 'cli-menu' };\n }\n\n const commandInput = await prompts.codexCommand((current?.command || []).join(' '));\n const workDir = await prompts.codexWorkDir(current?.work_dir || '');\n const model = await prompts.codexModel(current?.model || '');\n const approvalPolicy = await prompts.codexApprovalPolicy(current?.approval_policy || '');\n\n state.pendingChanges.agent = {\n ...(state.pendingChanges.agent || {}),\n codex: {\n ...(current || {}),\n enabled: true,\n command: parseCommandInput(commandInput),\n work_dir: workDir,\n model,\n approval_policy: approvalPolicy,\n },\n };\n state.itemStatus.set('codex', 'configured');\n state.sessionConfigured.add('codex');\n state.validationResults.set('codex', { ok: true, message: t('wizard.codex.enabled') });\n console.log(pc.green(` ${t('wizard.codex.enabled')}\\n`));\n return { action: 'next', next: 'channel-select' };\n }\n\n return { action: 'next', next: 'cli-menu' };\n}\n\nfunction parseCommandInput(input: string): string[] {\n const tokens = input\n .trim()\n .split(/\\s+/)\n .filter(Boolean);\n\n return tokens.length > 0 ? tokens : ['codex', 'app-server', '--listen', 'stdio://'];\n}\n\nfunction injectClaudeHooks(settingsPath: string, events: string[]): void {\n const port = loadConfig().general.hook_server_port;\n\n // Use canonical hook token: create if missing, reuse if exists\n const token = getOrCreateHookToken();\n\n const baseUrl = `http://localhost:${port}/hook/${token}`;\n const hooksConfig = generateHooksConfig(baseUrl, events);\n\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n try {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n } catch {\n // ignore\n }\n }\n\n const mergedSettings = mergeHooks(\n currentSettings,\n hooksConfig as Record<string, import('../../../shared/settings-merge.js').HookEntry[]>\n );\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(mergedSettings, null, 2));\n}\n\nfunction generateHooksConfig(baseUrl: string, events: string[]): Record<string, unknown[]> {\n const createEntry = (event: string) => ({\n matcher: '',\n hooks: [{ type: 'http' as const, url: `${baseUrl}/${event}` }],\n });\n\n const config: Record<string, unknown[]> = {};\n for (const event of events) {\n config[event] = [createEntry(event)];\n }\n return config;\n}\n","import { loadConfig } from '../../../config.js';\nimport type { ItemStatus } from '../state.js';\n\nexport type ChannelType = 'logger' | 'telegram' | 'feishu';\n\nexport interface ChannelDetection {\n configured: boolean;\n error?: string;\n}\n\nexport async function detectChannel(name: ChannelType): Promise<ChannelDetection> {\n const config = loadConfig();\n\n switch (name) {\n case 'logger':\n return { configured: config.channel.logger?.enabled === true };\n case 'telegram': {\n const token = config.channel.telegram?.bot_token;\n if (!token || token === 'YOUR_BOT_TOKEN') {\n return { configured: false };\n }\n try {\n const response = await fetch(`https://api.telegram.org/bot${token}/getMe`, {\n signal: AbortSignal.timeout(5000),\n });\n if (!response.ok) {\n return { configured: false, error: `Telegram API error: ${response.status}` };\n }\n return { configured: true };\n } catch (err) {\n return { configured: false, error: `Connection failed: ${err}` };\n }\n }\n case 'feishu': {\n const feishuConfig = config.channel.feishu;\n if (!feishuConfig?.enabled || !feishuConfig?.app_id) {\n return { configured: false };\n }\n // 检查 allowed_users 是否配置\n const allowedUsers = feishuConfig.allowed_users;\n if (!allowedUsers || allowedUsers.length === 0) {\n return { configured: false, error: 'Missing allowed_users' };\n }\n return { configured: true };\n }\n default:\n return { configured: false };\n }\n}\n\nexport function getChannelStatusLabel(status: ItemStatus, error?: string): string {\n switch (status) {\n case 'configured': return '[done]';\n case 'detected': return '[detected]';\n case 'not-found': return '[not found]';\n case 'error': return `[error]${error ? ` (${error})` : ''}`;\n default: return '';\n }\n}\n","import { prompts } from '../prompts.js';\nimport { getChannelStatusLabel, type ChannelType } from '../detectors/channel.js';\nimport pc from 'picocolors';\nimport { t } from '../../../i18n/index.js';\nimport type { WizardState } from '../state.js';\n\nexport async function stepChannelMenu(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.channel')}\\n`));\n\n const channelNames: ChannelType[] = ['logger', 'telegram', 'feishu'];\n const channels = channelNames.map(name => {\n const status = state.itemStatus.get(name) || 'unconfigured';\n const validation = state.validationResults.get(name);\n return {\n name,\n status: getChannelStatusLabel(status, validation?.message),\n };\n });\n\n const choice = await prompts.channelMenuSelect(channels);\n\n if (choice === '__next__') {\n return { action: 'next', next: 'final' };\n }\n\n state.currentChannelName = choice;\n return { action: 'next', next: 'channel-config' };\n}\n\nexport async function stepCliMenu(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.cli')}\\n`));\n\n const claudeStatus = state.itemStatus.get('claude') || 'unconfigured';\n let claudeLabel = getChannelStatusLabel(claudeStatus);\n if (state.claudeDetection?.tokenMismatch) {\n claudeLabel = pc.yellow('[update needed]');\n }\n\n const codexStatus = state.itemStatus.get('codex') || 'not-found';\n const codexLabel = getChannelStatusLabel(codexStatus, state.validationResults.get('codex')?.message);\n\n const cliOptions = [\n { name: 'claude', status: claudeLabel },\n { name: 'codex', status: codexLabel },\n ];\n\n const choice = await prompts.channelMenuSelect(cliOptions);\n\n if (choice === '__next__') {\n return { action: 'next', next: 'channel-menu' };\n }\n\n state.currentCliName = choice;\n return { action: 'next', next: 'cli' };\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 4';\n\nexport async function stepChannelConfig(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const channelName = state.currentChannelName || 'telegram';\n\n console.log(pc.bold(`\\n${STEP} — Configure Channel\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n while (true) {\n const cfg = loadConfig();\n const channelMap = cfg.channel as Record<string, unknown>;\n const currentConfig = (channelMap[channelName] ?? {}) as Record<string, unknown>;\n\n if (channelName === 'telegram') {\n const botToken = await prompts.botToken(currentConfig.bot_token as string | undefined);\n const allowedUsers = await prompts.allowedUsers(String(currentConfig.allowed_users || ''));\n\n const userIds = allowedUsers\n .split(',')\n .map(s => s.trim())\n .filter(s => s.length > 0 && /^\\d+$/.test(s));\n\n const spinner = ora(t('wizard.channel.telegram.testing')).start();\n let connected = false;\n try {\n const response = await fetch(`https://api.telegram.org/bot${botToken}/getMe`, {\n signal: AbortSignal.timeout(8000),\n });\n if (!response.ok) {\n spinner.fail(t('wizard.channel.telegram.apiError', { status: response.status }));\n } else {\n spinner.succeed(t('wizard.channel.telegram.connected'));\n connected = true;\n }\n } catch (err) {\n spinner.fail(t('wizard.channel.telegram.connFailed', { error: String(err) }));\n }\n\n if (!connected) {\n state.itemStatus.set(channelName, 'error');\n const choice = await prompts.channelConfigError();\n if (choice === 'retry' || choice === 'reinput') {\n continue;\n }\n state.itemStatus.set(channelName, 'unconfigured');\n return { action: 'next', next: 'channel-select' };\n }\n\n const msgSpinner = ora(t('wizard.channel.telegram.sendingTest')).start();\n try {\n await fetch(`https://api.telegram.org/bot${botToken}/sendMessage`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ chat_id: userIds[0] || 0, text: t('wizard.channel.telegram.testContent') }),\n signal: AbortSignal.timeout(8000),\n });\n msgSpinner.succeed(t('wizard.channel.telegram.testSent'));\n } catch {\n msgSpinner.warn(t('wizard.channel.telegram.testWarning'));\n }\n\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n telegram: { enabled: true, bot_token: botToken, allowed_users: userIds },\n };\n state.itemStatus.set('telegram', 'configured');\n state.sessionConfigured.add('telegram');\n state.validationResults.set('telegram', { ok: true });\n return { action: 'next', next: 'binding-confirm' };\n }\n\n if (channelName === 'logger') {\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n logger: { enabled: true },\n };\n state.itemStatus.set('logger', 'configured');\n state.sessionConfigured.add('logger');\n return { action: 'next', next: 'binding-confirm' };\n }\n\n if (channelName === 'feishu') {\n const appId = await prompts.feishuAppId(String(currentConfig.app_id || ''));\n const appSecret = await prompts.feishuAppSecret(String(currentConfig.app_secret || ''));\n const allowedUsersInput = await prompts.feishuAllowedUsers(String(currentConfig.allowed_users || ''));\n\n if (!appId || !appSecret) {\n console.log(pc.yellow(`! ${t('wizard.channel.feishu.required')}\\n`));\n state.itemStatus.set('feishu', 'unconfigured');\n return { action: 'next', next: 'channel-select' };\n }\n\n // 解析用户ID列表(支持逗号分隔)\n const allowedUsers = allowedUsersInput\n .split(',')\n .map(s => s.trim())\n .filter(s => s.length > 0);\n\n state.pendingChanges.channel = {\n ...(state.pendingChanges.channel || {}),\n feishu: { enabled: true, app_id: appId, app_secret: appSecret, allowed_users: allowedUsers },\n };\n state.itemStatus.set('feishu', 'configured');\n state.sessionConfigured.add('feishu');\n return { action: 'next', next: 'binding-confirm' };\n }\n\n return { action: 'next', next: 'agent-select' };\n }\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nexport async function stepChannelNotify(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const channelName = state.currentChannelName || 'telegram';\n\n console.log(pc.bold(`\\n${t('wizard.notify.title', { channel: channelName })}\\n`));\n\n const cfg = loadConfig();\n const channelConfig = cfg.channel[channelName as keyof typeof cfg.channel] as Record<string, unknown> | undefined || {};\n const currentTypes = (channelConfig.notify_types as string[]) || [];\n\n const selected = await prompts.notifyTypes(currentTypes);\n\n if (!state.pendingChanges.channel) state.pendingChanges.channel = {};\n if (!state.pendingChanges.channel[channelName]) state.pendingChanges.channel[channelName] = {};\n\n state.pendingChanges.channel[channelName] = {\n ...(state.pendingChanges.channel[channelName] as Record<string, unknown>),\n notify_types: selected,\n };\n\n console.log(pc.green(`\\n✓ ${t('wizard.notify.saved', { channel: channelName })}\\n`));\n\n return { action: 'next', next: 'channel-menu' };\n}\n","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { detectCodex } from '../detectors/codex.js';\nimport { stepCli } from './cli.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 1';\n\nexport async function stepAgentSelect(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Select Agent\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = config.bindings ?? {};\n\n const agents: Array<{ name: string; value: string; status: string }> = [];\n\n // claude\n const claudeConfigured = !!config.agent.claude;\n const claudeBoundTo = currentBindings['claude'];\n const claudeStatus = claudeBoundTo\n ? pc.green(`[bound to ${claudeBoundTo}]`)\n : (claudeConfigured ? pc.green('[configured]') : pc.gray('[not configured]'));\n agents.push({ name: 'claude', value: 'claude', status: claudeStatus });\n\n // codex\n const codexDetection = detectCodex();\n const codexConfigured = !!config.agent.codex?.enabled;\n const codexBoundTo = currentBindings['codex'];\n const codexStatus = codexBoundTo\n ? pc.green(`[bound to ${codexBoundTo}]`)\n : (codexConfigured ? pc.green('[configured]') : (codexDetection.installed ? pc.gray('[not configured]') : pc.red('[not installed]')));\n agents.push({ name: 'codex', value: 'codex', status: codexStatus });\n\n const choice = await prompts.agentSelect(agents);\n\n state.currentAgentName = choice;\n state.currentCliName = choice;\n\n // Run the existing stepCli for this agent\n const result = await stepCli(state);\n\n // After stepCli, always proceed to channel-select\n if (result.action === 'back') {\n return { action: 'next', next: 'pair-continue' };\n }\n\n // If stepCli indicates the agent was not usable (e.g. codex not installed),\n // return to agent-select so the user can pick a different agent.\n if (result.next === 'cli-menu') {\n return { action: 'next', next: 'agent-select' };\n }\n\n return { action: 'next', next: 'channel-select' };\n}","import { createHash } from 'crypto';\n\n/**\n * Generate a channel instance ID from channel type and its credential.\n * Format: \"channelType:hash\" e.g. \"telegram:abc123def\"\n */\nexport function getChannelInstanceId(channelType: string, credential: string): string {\n const hash = createHash('sha256').update(credential).digest('hex').slice(0, 12);\n return `${channelType}:${hash}`;\n}\n\n/**\n * Parse a channel instance ID back into its components.\n */\nexport function parseChannelInstanceId(instanceId: string): { channelType: string; hash: string } | null {\n const parts = instanceId.split(':');\n if (parts.length !== 2) return null;\n return { channelType: parts[0], hash: parts[1] };\n}\n\n/**\n * Get display label for a channel instance ID.\n * Uses short hash for display purposes.\n */\nexport function getChannelInstanceLabel(channelType: string, hash: string, displayName?: string): string {\n return displayName ?? `${channelType} (${hash})`;\n}","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\nimport { stepChannelConfig } from './channel-config.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 3';\n\nexport async function stepChannelSelect(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Select Channel\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = config.bindings ?? {};\n\n // Merge pending channel changes from current wizard session so we reflect unsaved edits\n const pendingChannels = state.pendingChanges.channel ?? {};\n const mergedTelegram = pendingChannels.telegram\n ? { ...config.channel.telegram, ...pendingChannels.telegram }\n : config.channel.telegram;\n const mergedFeishu = pendingChannels.feishu\n ? { ...config.channel.feishu, ...pendingChannels.feishu }\n : config.channel.feishu;\n const mergedLogger = pendingChannels.logger\n ? { ...config.channel.logger, ...pendingChannels.logger }\n : config.channel.logger;\n\n const channels: Array<{ name: string; value: string; status: string }> = [];\n\n // logger\n const loggerEnabled = mergedLogger?.enabled === true;\n const loggerInstanceId = 'logger:default';\n const loggerBoundAgent = Object.entries(currentBindings).find(([, v]) => v === loggerInstanceId)?.[0];\n const loggerStatus = loggerBoundAgent\n ? pc.green(`[bound to ${loggerBoundAgent}]`)\n : (loggerEnabled ? pc.green('[configured]') : pc.gray('[not configured]'));\n channels.push({ name: 'logger', value: 'logger', status: loggerStatus });\n\n // telegram\n if (mergedTelegram?.enabled && mergedTelegram.bot_token) {\n const instanceId = getChannelInstanceId('telegram', mergedTelegram.bot_token as string);\n const boundAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n const status = boundAgent\n ? pc.green(`[bound to ${boundAgent}]`)\n : pc.green('[configured]');\n channels.push({ name: 'telegram', value: 'telegram', status });\n } else {\n channels.push({ name: 'telegram', value: 'telegram', status: pc.gray('[not configured]') });\n }\n\n // feishu\n if (mergedFeishu?.enabled && mergedFeishu.app_id) {\n const instanceId = getChannelInstanceId('feishu', mergedFeishu.app_id as string);\n const boundAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n const status = boundAgent\n ? pc.green(`[bound to ${boundAgent}]`)\n : pc.green('[configured]');\n channels.push({ name: 'feishu', value: 'feishu', status });\n } else {\n channels.push({ name: 'feishu', value: 'feishu', status: pc.gray('[not configured]') });\n }\n\n const choice = await prompts.channelSelect(channels);\n\n state.currentChannelName = choice;\n\n // Run stepChannelConfig for this channel\n const result = await stepChannelConfig(state);\n\n if (result.action === 'back') {\n return { action: 'next', next: 'agent-select' };\n }\n\n return { action: 'next', next: 'binding-confirm' };\n}","import { prompts } from '../prompts.js';\nimport { loadConfig } from '../../../config.js';\nimport { getChannelInstanceId } from '../../../shared/channelInstance.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 5';\n\nexport async function stepBindingConfirm(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n const agentName = state.currentAgentName!;\n const channelName = state.currentChannelName!;\n\n console.log(pc.bold(`\\n${STEP} — Confirm Binding\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const config = loadConfig();\n const currentBindings = { ...(config.bindings ?? {}) } as Record<string, string | undefined>;\n\n // Merge any wizard-session bindings that were already staged\n for (const [a, cid] of Object.entries(state.bindings)) {\n if (cid) currentBindings[a] = cid;\n }\n\n // Use pending channel changes if they exist (not yet written to disk)\n const pendingChannel = state.pendingChanges.channel?.[channelName] as Record<string, unknown> | undefined;\n const telegramConfig = pendingChannel && channelName === 'telegram'\n ? { ...config.channel.telegram, ...pendingChannel }\n : config.channel.telegram;\n const feishuConfig = pendingChannel && channelName === 'feishu'\n ? { ...config.channel.feishu, ...pendingChannel }\n : config.channel.feishu;\n\n // Get agent's current binding\n const agentCurrentChannel = currentBindings[agentName];\n\n // Get channel's current binding\n let channelCurrentAgent: string | undefined;\n let instanceId: string | undefined;\n if (channelName === 'telegram' && telegramConfig?.bot_token) {\n instanceId = getChannelInstanceId('telegram', telegramConfig.bot_token as string);\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n } else if (channelName === 'feishu' && feishuConfig?.app_id) {\n instanceId = getChannelInstanceId('feishu', feishuConfig.app_id as string);\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n } else if (channelName === 'logger') {\n instanceId = 'logger:default';\n channelCurrentAgent = Object.entries(currentBindings).find(([, v]) => v === instanceId)?.[0];\n }\n\n console.log(` ${pc.cyan(agentName)} current binding: ${agentCurrentChannel ? pc.yellow(agentCurrentChannel) : pc.gray('none')}`);\n console.log(` ${pc.cyan(channelName)} current binding: ${channelCurrentAgent ? pc.yellow(channelCurrentAgent) : pc.gray('none')}`);\n console.log('');\n\n const choice = await prompts.bindingConfirm(agentName, channelName);\n\n if (choice === 'confirm' && instanceId) {\n const oldChannelId = currentBindings[agentName];\n\n // Remove conflicting binding (another agent bound to same channel)\n for (const [a, cid] of Object.entries(currentBindings)) {\n if (cid === instanceId && a !== agentName) {\n delete state.bindings[a];\n }\n }\n\n if (oldChannelId && oldChannelId !== instanceId) {\n console.log(pc.yellow(` ⚠ ${agentName} migrated from ${oldChannelId} to ${instanceId}`));\n }\n state.bindings[agentName] = instanceId;\n state.sessionConfigured.add(`binding:${agentName}`);\n console.log(pc.green(` ✓ ${agentName} bound to ${channelName}`));\n } else {\n console.log(pc.gray(` Binding cancelled`));\n }\n\n console.log('');\n return { action: 'next', next: 'pair-continue' };\n}\n","import { prompts } from '../prompts.js';\nimport pc from 'picocolors';\nimport type { WizardState } from '../state.js';\n\nconst STEP = 'STEP 6';\n\nexport async function stepPairContinue(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${STEP} — Add Another Pair?\\n`));\n console.log(pc.gray(`${'─'.repeat(50)}\\n`));\n\n const choice = await prompts.pairContinue();\n\n if (choice === 'continue') {\n // Reset current pair state for next iteration\n state.currentAgentName = undefined;\n state.currentChannelName = undefined;\n return { action: 'next', next: 'agent-select' };\n }\n\n // finish — go to final\n return { action: 'next', next: 'final' };\n}\n","import { spawn } from 'child_process';\nimport { exec } from 'child_process';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\nimport { mkdirSync, existsSync } from 'fs';\nimport { readPidFile, removePidFile, isProcessRunning } from '../shared/pidfile.js';\nimport { t } from '../i18n/index.js';\n\nfunction isPortInUse(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n exec(`lsof -i :${port}`, (err) => {\n resolve(!err);\n });\n });\n}\n\nexport class DaemonManager {\n private pidFilePath: string;\n private port: number;\n private lastError?: string;\n\n constructor(pidFilePath: string, port: number) {\n this.pidFilePath = pidFilePath;\n this.port = port;\n }\n\n getPort(): number {\n return this.port;\n }\n\n getPidFilePath(): string {\n return this.pidFilePath;\n }\n\n getLastError(): string | undefined {\n return this.lastError;\n }\n\n isRunning(): boolean {\n const data = readPidFile(this.pidFilePath);\n if (!data) return false;\n\n // Check if process actually exists\n if (!isProcessRunning(data.pid)) {\n // Cleanup stale PID file\n removePidFile(this.pidFilePath);\n return false;\n }\n\n return true;\n }\n\n async start(): Promise<boolean> {\n this.lastError = undefined;\n\n const existingPidData = readPidFile(this.pidFilePath);\n if (existingPidData && isProcessRunning(existingPidData.pid)) {\n if (!existingPidData.token) {\n console.log(t('daemon.lackingToken'));\n await this.stop();\n await this.waitForPortFree();\n } else {\n console.log(t('daemon.alreadyRunning'));\n return true;\n }\n }\n\n try {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logDir = join(homedir, '.handsoff', 'logs');\n mkdirSync(logDir, { recursive: true });\n\n // Ensure PID file is removed before starting\n removePidFile(this.pidFilePath);\n\n const __dirname = dirname(fileURLToPath(import.meta.url));\n let daemonScript = join(__dirname, '..', 'gateway', 'process.js');\n\n if (!existsSync(daemonScript)) {\n daemonScript = join(__dirname, '..', '..', 'src', 'gateway', 'process.ts');\n }\n\n if (!existsSync(daemonScript)) {\n this.lastError = t('daemon.scriptNotFound', { path: daemonScript });\n console.error(this.lastError);\n return false;\n }\n\n // Start daemon in detached mode - it will run independently\n const logFile = join(logDir, 'gateway.log');\n\n // In dev mode the fallback script is a .ts file — use tsx to run it\n const isDev = daemonScript.endsWith('.ts');\n const execPath = isDev\n ? join(__dirname, '..', '..', 'node_modules', '.bin', 'tsx')\n : process.execPath;\n\n // Spawn detached daemon\n const child = spawn(execPath, [daemonScript], {\n detached: true,\n stdio: 'ignore',\n env: {\n ...process.env,\n HANDSOFF_DAEMON: 'true',\n HANDSOFF_PORT: String(this.port),\n HANDSOFF_PID_FILE: this.pidFilePath,\n },\n });\n child.unref();\n\n // Wait for daemon to start and write PID file\n // Daemon startup may take up to 20 seconds due to channel initialization (e.g., Telegram)\n let pidData = null;\n for (let i = 0; i < 30; i++) {\n await new Promise(resolve => setTimeout(resolve, 1000));\n pidData = readPidFile(this.pidFilePath);\n if (pidData) {\n if (isProcessRunning(pidData.pid)) {\n console.log(t('daemon.startedOnPort', { port: this.port }));\n return true;\n }\n }\n }\n\n this.lastError = t('daemon.startFailed');\n console.error(this.lastError);\n console.error(t('daemon.checkLogs', { path: logFile }));\n return false;\n } catch (error) {\n const errorMsg = error instanceof Error ? error.message : String(error);\n this.lastError = t('daemon.startError', { error: errorMsg });\n console.error(this.lastError);\n return false;\n }\n }\n\n async stop(): Promise<boolean> {\n const data = readPidFile(this.pidFilePath);\n if (!data) {\n // console.log('No daemon PID file found');\n return true;\n }\n\n try {\n // Kill the process\n process.kill(data.pid, 'SIGTERM');\n\n // Wait for process to exit\n let attempts = 0;\n while (isProcessRunning(data.pid) && attempts < 10) {\n await new Promise(resolve => setTimeout(resolve, 200));\n attempts++;\n }\n\n if (isProcessRunning(data.pid)) {\n // Force kill\n process.kill(data.pid, 'SIGKILL');\n }\n\n removePidFile(this.pidFilePath);\n // console.log('Daemon stopped');\n return true;\n } catch (error) {\n // console.error('Failed to stop daemon:', error);\n return false;\n }\n }\n\n async forceCleanup(): Promise<void> {\n removePidFile(this.pidFilePath);\n }\n\n private async waitForPortFree(maxWaitMs: number = 5000): Promise<void> {\n const startTime = Date.now();\n while (await isPortInUse(this.port)) {\n if (Date.now() - startTime > maxWaitMs) {\n console.log(t('daemon.portInUse', { port: this.port, ms: maxWaitMs }));\n break;\n }\n await new Promise(resolve => setTimeout(resolve, 200));\n }\n }\n}\n","import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';\nimport { dirname } from 'path';\nimport { mkdirSync } from 'fs';\n\nexport interface PidFileData {\n pid: number;\n port: number;\n startedAt: string;\n version?: string;\n agents?: string[];\n channels?: string[];\n token?: string;\n}\n\nexport function writePidFile(pidFilePath: string, data: PidFileData): void {\n // Validate pid is a positive integer\n if (!Number.isInteger(data.pid) || data.pid <= 0) {\n throw new TypeError(`Invalid pid: ${data.pid}. Must be a positive integer.`);\n }\n\n // Validate port is a positive integer between 1-65535\n if (!Number.isInteger(data.port) || data.port < 1 || data.port > 65535) {\n throw new TypeError(`Invalid port: ${data.port}. Must be an integer between 1 and 65535.`);\n }\n\n mkdirSync(dirname(pidFilePath), { recursive: true });\n writeFileSync(pidFilePath, JSON.stringify(data, null, 2));\n}\n\nexport function readPidFile(pidFilePath: string): PidFileData | null {\n if (!existsSync(pidFilePath)) {\n return null;\n }\n try {\n const content = readFileSync(pidFilePath, 'utf-8');\n return JSON.parse(content) as PidFileData;\n } catch {\n return null;\n }\n}\n\nexport function removePidFile(pidFilePath: string): void {\n if (existsSync(pidFilePath)) {\n unlinkSync(pidFilePath);\n }\n}\n\nexport function isProcessRunning(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n","import { prompts } from '../prompts.js';\nimport { DaemonManager } from '../../daemon.js';\nimport { loadConfig } from '../../../config.js';\nimport { t } from '../../../i18n/index.js';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport pc from 'picocolors';\nimport ora from 'ora';\nimport type { WizardState } from '../state.js';\n\nexport async function stepFinal(state: WizardState): Promise<{ action: 'next' | 'back' | 'quit'; next?: string }> {\n console.log(pc.bold(`\\n${t('wizard.section.complete')}\\n`));\n\n if (state.sessionConfigured.size === 0) {\n console.log(pc.gray(` ${t('wizard.final.noItems')}\\n`));\n } else {\n for (const item of state.sessionConfigured) {\n const result = state.validationResults.get(item);\n if (result?.ok) {\n console.log(pc.green(`* ${t('wizard.final.itemOk', { item })}`));\n }\n }\n console.log('');\n }\n\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const port = loadConfig().general.hook_server_port;\n const daemon = new DaemonManager(pidFilePath, port);\n const hasChanges = state.sessionConfigured.size > 0 || Object.keys(state.pendingChanges).length > 0 || Object.keys(state.bindings).length > 0;\n\n if (daemon.isRunning()) {\n if (hasChanges) {\n console.log(pc.blue(`i ${t('wizard.final.runningChanges')}\\n`));\n console.log(pc.yellow(` ${t('wizard.final.configModified')}\\n`));\n const shouldRestart = await prompts.restartGateway();\n if (shouldRestart) {\n const spinner = ora(t('wizard.final.restarting')).start();\n await daemon.stop();\n const started = await daemon.start();\n if (started) {\n spinner.succeed(t('wizard.final.restarted'));\n } else {\n spinner.fail(t('wizard.final.startFailed', { error: daemon.getLastError() ?? 'unknown' }));\n }\n } else {\n console.log(pc.gray(` ${t('wizard.final.restartTip')}\\n`));\n }\n } else {\n console.log(pc.blue(`i ${t('wizard.final.running')}\\n`));\n console.log(pc.green(` ${t('wizard.final.runningReady')}\\n`));\n }\n } else {\n console.log(pc.blue(`i ${t('wizard.final.notRunning')}\\n`));\n if (hasChanges) {\n console.log(pc.yellow(` ${t('wizard.final.configModifiedStart')}\\n`));\n }\n const shouldStart = await prompts.restartGateway();\n if (shouldStart) {\n const spinner2 = ora(t('wizard.final.starting')).start();\n const started = await daemon.start();\n if (started) {\n spinner2.succeed(t('wizard.final.started'));\n } else {\n spinner2.fail(t('wizard.final.startFailed', { error: daemon.getLastError() ?? 'unknown' }));\n }\n } else {\n console.log(pc.gray(` ${t('wizard.final.startTip')}\\n`));\n }\n }\n\n console.log(pc.green(`\\n${t('wizard.final.done')}\\n`));\n return { action: 'next', next: 'done' };\n}\n","import { Command } from 'commander';\nimport { createReadStream } from 'fs';\nimport { stat, readFile } from 'fs/promises';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { readdirSync, statSync, existsSync } from 'fs';\n\ninterface SessionFile {\n sessionId: string;\n agentType: string;\n date: string;\n path: string;\n size: number;\n}\n\ninterface PersistedEvent {\n v: number;\n ts: string;\n type?: string;\n text?: string;\n tool?: { name?: string; input?: Record<string, unknown>; output?: string };\n [key: string]: unknown;\n}\n\nconst SESSIONS_DIR = join(homedir(), '.handsoff', 'sessions');\n\n/**\n * Format bytes to human readable string\n */\nfunction formatSize(bytes: number): string {\n if (bytes === 0) return '0B';\n const units = ['B', 'KB', 'MB', 'GB'];\n const i = Math.floor(Math.log(bytes) / Math.log(1024));\n const size = bytes / Math.pow(1024, i);\n return `${size.toFixed(i === 0 ? 0 : 1)}${units[i]}`;\n}\n\n/**\n * Sleep for specified milliseconds\n */\nfunction sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n}\n\n/**\n * List all session files from the sessions directory\n */\nfunction listSessions(): SessionFile[] {\n const sessions: SessionFile[] = [];\n\n if (!existsSync(SESSIONS_DIR)) {\n return sessions;\n }\n\n const entries = readdirSync(SESSIONS_DIR, { withFileTypes: true });\n\n for (const entry of entries) {\n if (entry.isDirectory() && /^\\d{4}-\\d{2}-\\d{2}$/.test(entry.name)) {\n const date = entry.name;\n const dateDir = join(SESSIONS_DIR, date);\n const files = readdirSync(dateDir);\n\n for (const fileName of files) {\n if (fileName.endsWith('.jsonl')) {\n const filePath = join(dateDir, fileName);\n const stats = statSync(filePath);\n\n // Parse filename: {agentType}-{sessionId}.jsonl\n // agentType is the first part, sessionId is everything after the first dash\n const match = fileName.match(/^([^-]+)-(.+)\\.jsonl$/);\n if (match) {\n const [, agentType, sessionId] = match;\n sessions.push({\n sessionId,\n agentType,\n date,\n path: filePath,\n size: stats.size,\n });\n }\n }\n }\n }\n }\n\n // Sort by date descending, then by sessionId\n return sessions.sort((a, b) => {\n if (a.date !== b.date) {\n return b.date.localeCompare(a.date);\n }\n return a.sessionId.localeCompare(b.sessionId);\n });\n}\n\n/**\n * Find session file by session ID (partial match supported)\n */\nfunction findSessionFile(sessionId: string): SessionFile | undefined {\n const sessions = listSessions();\n\n // Try exact match first\n const match = sessions.find(s => s.sessionId === sessionId);\n if (match) return match;\n\n // Try partial match\n const matches = sessions.filter(s => s.sessionId.includes(sessionId));\n if (matches.length === 1) {\n return matches[0];\n }\n\n if (matches.length > 1) {\n console.error(`Multiple sessions match \"${sessionId}\":`);\n for (const s of matches) {\n console.error(` - ${s.sessionId} (${s.agentType}, ${s.date})`);\n }\n return undefined;\n }\n\n return undefined;\n}\n\n/**\n * Format and print an event\n */\nfunction printEvent(event: PersistedEvent): void {\n const timestamp = new Date(event.ts);\n const timeStr = timestamp.toTimeString().split(' ')[0]; // HH:MM:SS\n\n const type = event.type || 'unknown';\n const typeStr = type.padEnd(16);\n\n let content = '';\n if (event.tool?.name) {\n content = `Tool: ${event.tool.name}`;\n } else if (event.text) {\n content = event.text;\n } else if (typeof event.content === 'string') {\n content = event.content;\n } else {\n // Try to extract meaningful content from other fields\n const { ...rest } = event;\n const keys = Object.keys(rest);\n if (keys.length > 0) {\n content = `${keys[0]}: ${JSON.stringify(rest[keys[0]])}`;\n }\n }\n\n // Truncate long content\n if (content.length > 60) {\n content = content.substring(0, 57) + '...';\n }\n\n console.log(`[${timeStr}] ${typeStr} ${content}`);\n}\n\n/**\n * Read all events from a session file\n */\nasync function* readEvents(filePath: string): AsyncIterable<PersistedEvent> {\n if (!existsSync(filePath)) {\n return;\n }\n\n const content = await readFile(filePath, 'utf-8');\n const lines = content.trim().split('\\n').filter(line => line.length > 0);\n\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as PersistedEvent;\n yield event;\n } catch {\n // Skip invalid JSON lines\n continue;\n }\n }\n}\n\n/**\n * Display list of all sessions\n */\nasync function showSessionList(): Promise<void> {\n const sessions = listSessions();\n\n if (sessions.length === 0) {\n console.log('No sessions found.');\n console.log(`Sessions directory: ${SESSIONS_DIR}`);\n return;\n }\n\n console.log('Sessions:\\n');\n console.log(` Agent Session ID Date Size`);\n console.log(` --------- ------------------------ ---------- ------`);\n\n for (const session of sessions) {\n const agentStr = session.agentType.padEnd(9);\n const sessionStr = session.sessionId.padEnd(24).substring(0, 24);\n const dateStr = session.date;\n const sizeStr = formatSize(session.size).padStart(6);\n console.log(` ${agentStr} ${sessionStr} ${dateStr} ${sizeStr}`);\n }\n}\n\n/**\n * Tail a session file in real-time\n */\nasync function tailSession(sessionId: string): Promise<void> {\n const session = findSessionFile(sessionId);\n if (!session) {\n console.error(`Session not found: ${sessionId}`);\n process.exit(1);\n }\n\n console.log(`Tailing session: ${session.sessionId} (${session.agentType})`);\n console.log(`File: ${session.path}`);\n console.log('Press Ctrl+C to exit\\n');\n\n // Read and display existing content first\n for await (const event of readEvents(session.path)) {\n printEvent(event);\n }\n\n // Get current file size\n let lastSize = (await stat(session.path)).size;\n\n // Set up Ctrl+C handler\n let running = true;\n process.on('SIGINT', () => {\n running = false;\n console.log('\\n');\n process.exit(0);\n });\n\n // Poll for new content\n while (running) {\n await sleep(1000);\n\n try {\n const stats = await stat(session.path);\n if (stats.size > lastSize) {\n // Read new content\n const stream = createReadStream(session.path, {\n start: lastSize,\n encoding: 'utf-8',\n });\n\n let newContent = '';\n stream.on('data', (chunk) => {\n newContent += chunk;\n });\n\n await new Promise<void>((resolve) => {\n stream.on('end', () => resolve());\n stream.on('error', () => resolve());\n });\n\n // Parse and print new lines\n const lines = newContent.split('\\n').filter(line => line.trim());\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as PersistedEvent;\n printEvent(event);\n } catch {\n // Skip invalid JSON\n }\n }\n\n lastSize = stats.size;\n }\n } catch (error) {\n // File might have been deleted, exit gracefully\n console.error('\\nError reading session file:', error);\n break;\n }\n }\n}\n\n/**\n * Replay a session with original timing\n */\nasync function replaySession(sessionId: string): Promise<void> {\n const session = findSessionFile(sessionId);\n if (!session) {\n console.error(`Session not found: ${sessionId}`);\n process.exit(1);\n }\n\n console.log(`Replaying session: ${session.sessionId} (${session.agentType})`);\n console.log(`File: ${session.path}\\n`);\n\n const events: PersistedEvent[] = [];\n for await (const event of readEvents(session.path)) {\n events.push(event);\n }\n\n if (events.length === 0) {\n console.log('No events in session.');\n return;\n }\n\n // Set up Ctrl+C handler\n let running = true;\n process.on('SIGINT', () => {\n running = false;\n console.log('\\nReplay interrupted.');\n process.exit(0);\n });\n\n let lastTimestamp: number | null = null;\n\n for (const event of events) {\n if (!running) break;\n\n const currentTimestamp = new Date(event.ts).getTime();\n\n if (lastTimestamp !== null) {\n const delay = currentTimestamp - lastTimestamp;\n // Cap delay at 1 second for replay\n const replayDelay = Math.min(delay, 1000);\n if (replayDelay > 0) {\n await sleep(replayDelay);\n }\n }\n\n printEvent(event);\n lastTimestamp = currentTimestamp;\n }\n\n console.log('\\nReplay complete.');\n}\n\nexport const logsCommand = new Command('logs')\n .description('View session logs')\n .option('-t, --tail <session>', 'Tail a live session')\n .option('-r, --replay <session>', 'Replay session with original timing')\n .action(async (options) => {\n try {\n if (options.tail) {\n await tailSession(options.tail);\n } else if (options.replay) {\n await replaySession(options.replay);\n } else {\n await showSessionList();\n }\n } catch (error) {\n console.error('Failed to read logs:', error);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { loadConfig } from '../config.js';\nimport { DaemonManager } from './daemon.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { existsSync } from 'fs';\nimport { t } from '../i18n/index.js';\n\n// TODO: Will be moved to adapters/agent/claude.ts\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nexport const statusCommand = new Command('status')\n .description('Show current status')\n .action(() => {\n const config = loadConfig();\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const daemon = new DaemonManager(pidFilePath, config.general.hook_server_port);\n\n console.log(`\\n${t('status.title')}\\n`);\n\n // Daemon status\n console.log(daemon.isRunning() ? t('status.daemon.running') : t('status.daemon.notRunning'));\n\n console.log(t('status.port', { port: config.general.hook_server_port }));\n console.log(`${t('status.logLevel', { level: config.general.log_level })}\\n`);\n\n // Channels\n console.log(t('status.channels'));\n console.log(` ${config.channel.telegram?.enabled ? t('status.telegram.enabled') : t('status.telegram.disabled')}`);\n console.log(` ${config.channel.feishu?.enabled ? t('status.feishu.enabled') : t('status.feishu.disabled')}\\n`);\n\n // Settings backup\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(backupPath)) {\n console.log(t('status.settingsBackup'));\n } else {\n console.log(t('status.settingsNoBackup'));\n }\n\n // Paths\n const home = homedir();\n console.log(`\\n${t('status.paths')}`);\n console.log(` ${t('status.pathConfig', { path: `${home}/.handsoff/config.toml` })}`);\n console.log(` ${t('status.pathLogs', { path: `${home}/.handsoff/logs/gateway.log` })}`);\n console.log(` ${t('status.pathBackup', { path: `${home}/.claude/settings.json.handsoff-backup` })}\\n`);\n });\n","import { Command } from 'commander';\nimport { DaemonManager } from './daemon.js';\nimport { loadConfig } from '../config.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { t } from '../i18n/index.js';\n\nexport const stopCommand = new Command('stop')\n .description('Stop the handsoff daemon and restore settings')\n .action(async () => {\n const config = loadConfig();\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n const daemon = new DaemonManager(pidFilePath, config.general.hook_server_port);\n\n // Check if running\n if (!daemon.isRunning()) {\n console.log(t('cli.stop.notRunning'));\n } else {\n console.log(t('cli.stop.stopping'));\n const stopped = await daemon.stop();\n if (stopped) {\n console.log(t('cli.stop.stopped'));\n } else {\n console.error(t('cli.stop.failed'));\n }\n }\n\n // Restore Claude settings (TODO: move to adapters/agent/claude.ts)\n });\n","import { Command } from 'commander';\nimport { join } from 'path';\nimport { DaemonManager } from './daemon.js';\nimport { homedir } from 'os';\n\nimport { loadConfig } from '../config.js';\nimport { t } from '../i18n/index.js';\n\nconst PID_FILE = join(homedir(), '.handsoff', 'handsoff.pid');\n\nexport const gatewayCommand = new Command('gateway')\n .description('Manage handsoff Gateway daemon')\n .addCommand(\n new Command('start')\n .description('Start or restart the Gateway daemon')\n .option('-p, --port <port>', 'Port to listen on')\n .action(async (options) => {\n const config = loadConfig();\n const port = options.port ? parseInt(options.port, 10) : config.general.hook_server_port;\n const daemon = new DaemonManager(PID_FILE, port);\n\n // If already running, stop it first\n if (daemon.isRunning()) {\n console.log(t('gateway.stopping'));\n await daemon.stop();\n }\n\n const started = await daemon.start();\n if (started) {\n console.log(t('gateway.startedOnPort', { port }));\n } else {\n const error = daemon.getLastError();\n console.error(t('gateway.startFailed'));\n if (error) {\n console.error(t('gateway.error', { error }));\n }\n const logPath = join(homedir(), '.handsoff', 'logs', 'gateway.log');\n console.error(` ${t('gateway.checkLogs', { path: logPath })}`);\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('stop')\n .description('Stop the Gateway daemon')\n .action(async () => {\n const config = loadConfig();\n const daemon = new DaemonManager(PID_FILE, config.general.hook_server_port);\n\n if (!daemon.isRunning()) {\n console.log(t('gateway.notRunning'));\n return;\n }\n\n console.log(t('gateway.stopping'));\n const stopped = await daemon.stop();\n if (stopped) {\n console.log(t('gateway.stopped'));\n } else {\n console.error(t('gateway.stopFailed'));\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('restart')\n .description('Restart the Gateway daemon')\n .option('-p, --port <port>', 'Port to listen on')\n .action(async (options) => {\n const config = loadConfig();\n const port = options.port ? parseInt(options.port, 10) : config.general.hook_server_port;\n const daemon = new DaemonManager(PID_FILE, port);\n\n await daemon.stop();\n const started = await daemon.start();\n\n if (started) {\n console.log(t('gateway.restartedOnPort', { port }));\n } else {\n const error = daemon.getLastError();\n console.error(t('gateway.restartFailed'));\n if (error) {\n console.error(t('gateway.error', { error }));\n }\n const logPath = join(homedir(), '.handsoff', 'logs', 'gateway.log');\n console.error(` ${t('gateway.checkLogs', { path: logPath })}`);\n process.exit(1);\n }\n })\n )\n .addCommand(\n new Command('status')\n .description('Check Gateway status')\n .action(async () => {\n const config = loadConfig();\n try {\n const response = await fetch(`http://localhost:${config.general.hook_server_port}/status`);\n if (response.ok) {\n const status = await response.json() as { running?: boolean; sessions?: Array<{ agentType?: string; sessionId?: string; id?: string }>; clients?: number };\n console.log(t('gateway.status.title'));\n console.log(` ${t('gateway.status.running', { value: status.running ?? true })}`);\n console.log(` ${t('gateway.status.sessions', { count: status.sessions?.length ?? (typeof status.sessions === 'number' ? status.sessions : 0) })}`);\n console.log(` ${t('gateway.status.clients', { count: status.clients ?? 0 })}`);\n\n if (status.sessions && status.sessions.length > 0) {\n console.log(`\\n ${t('gateway.status.activeSessions')}`);\n for (const session of status.sessions) {\n const agentType = session.agentType || 'unknown';\n const sessionId = session.sessionId || session.id || 'unknown';\n console.log(` - ${agentType}/${sessionId}`);\n }\n }\n } else {\n console.log(t('gateway.status.notResponding'));\n }\n } catch {\n console.log(t('gateway.status.notRunning'));\n }\n })\n );\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { t } from '../../i18n/index.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Debug command for capturing and inspecting raw hook payloads\n */\nexport const debugCommand = new Command('debug')\n .description('Debug tools for Handsoff')\n .addCommand(\n new Command('hooks')\n .description('Capture and log raw hook payloads for debugging')\n .option('-p, --port <port>', 'Port to listen on', '16792')\n .action(async (options) => {\n const port = parseInt(options.port, 10);\n\n console.log(t('cli.debug.starting', { port }));\n console.log(t('cli.debug.capturing'));\n console.log(t('cli.debug.pressCtrlC'));\n\n // Run the hook-capture script\n const captureScript = join(__dirname, 'hook-capture.js');\n const proc = spawn('node', [captureScript], {\n stdio: 'inherit',\n env: { ...process.env, HANDSOFF_DEBUG_PORT: String(port) },\n });\n\n proc.on('exit', (code) => {\n process.exit(code || 0);\n });\n\n // Handle Ctrl+C\n process.on('SIGINT', () => {\n console.log(t('cli.debug.stopping'));\n proc.kill('SIGINT');\n });\n })\n );\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { DaemonManager } from '../daemon.js';\nimport { mergeHooks, type HookEntry } from '../../shared/settings-merge.js';\nimport { loadConfig } from '../../config.js';\nimport { homedir } from 'os';\nimport { join, dirname } from 'path';\nimport { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { readPidFile } from '../../shared/pidfile.js';\nimport { t } from '../../i18n/index.js';\n\nfunction getSettingsPath(): string {\n return join(homedir(), '.claude', 'settings.json');\n}\n\nfunction backupSettings(settingsPath: string): void {\n const backupPath = settingsPath + '.handsoff-backup';\n if (existsSync(settingsPath)) {\n writeFileSync(backupPath, readFileSync(settingsPath, 'utf-8'));\n }\n}\n\nfunction writeSettings(settingsPath: string, settings: Record<string, unknown>): void {\n mkdirSync(dirname(settingsPath), { recursive: true });\n writeFileSync(settingsPath, JSON.stringify(settings, null, 2));\n}\n\n/**\n * Generate unified hooks configuration\n *\n * Uses a single endpoint (/hook/{token}/event) for all events,\n * with the event type passed in the request body.\n *\n * This allows different CLI tools to use the same URL structure.\n */\nfunction generateHooksConfig(port: number, token: string): Record<string, HookEntry[]> {\n const unifiedUrl = `http://localhost:${port}/hook/${token}/event`;\n const createHookEntry = (): HookEntry => ({\n matcher: '',\n hooks: [{ type: 'http', url: unifiedUrl }],\n });\n\n return {\n Stop: [createHookEntry()],\n PostToolUse: [createHookEntry()],\n PostToolUseFailure: [createHookEntry()],\n Notification: [createHookEntry()],\n PreToolUse: [createHookEntry()],\n SubagentStart: [createHookEntry()],\n SubagentStop: [createHookEntry()],\n SessionStart: [createHookEntry()],\n SessionEnd: [createHookEntry()],\n UserPromptSubmit: [createHookEntry()],\n PermissionRequest: [createHookEntry()],\n };\n}\n\nexport function registerClaudeCommand(program: Command) {\n program\n .command('claude')\n .description('Start Claude Code with handsoff integration')\n .option('-d, --directory <dir>', 'Working directory for Claude')\n .action(async (options) => {\n const config = loadConfig();\n const port = config.general.hook_server_port;\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n\n // Step 1: Ensure daemon is running\n const daemon = new DaemonManager(pidFilePath, port);\n let daemonStarted = false;\n\n if (daemon.isRunning()) {\n console.log(t('cli.agent.alreadyRunning'));\n daemonStarted = true;\n } else {\n console.log(t('cli.agent.starting'));\n daemonStarted = await daemon.start();\n if (!daemonStarted) {\n console.error(t('cli.agent.startFailed'));\n process.exit(1);\n }\n console.log(t('cli.agent.started'));\n }\n\n // Step 2: Inject hooks into Claude settings\n console.log(t('cli.agent.configuring'));\n\n const settingsPath = getSettingsPath();\n const backupPath = settingsPath + '.handsoff-backup';\n\n // Create backup if not exists\n if (!existsSync(backupPath)) {\n backupSettings(settingsPath);\n console.log(t('cli.agent.settingsBacked'));\n }\n\n // Read token from daemon PID file\n const pidData = readPidFile(pidFilePath);\n const token = pidData?.token;\n if (!token) {\n console.error(t('cli.agent.tokenNotFound'));\n process.exit(1);\n }\n\n // Generate hooks config with daemon's token\n const hooksConfig = generateHooksConfig(port, token);\n\n // Read current settings and merge\n let currentSettings: Record<string, unknown> = {};\n if (existsSync(settingsPath)) {\n currentSettings = JSON.parse(readFileSync(settingsPath, 'utf-8'));\n }\n\n const mergedSettings = mergeHooks(currentSettings, hooksConfig);\n writeSettings(settingsPath, mergedSettings);\n console.log(t('cli.agent.hooksConfigured'));\n\n // Step 3: Launch Claude\n const workDir = options.directory || process.cwd();\n\n console.log(t('cli.agent.startingIn', { dir: workDir }));\n console.log(t('cli.agent.pressCtrlC') + '\\n');\n\n const claudeProcess = spawn('claude', [], {\n cwd: workDir,\n stdio: 'inherit',\n shell: true,\n });\n\n claudeProcess.on('exit', (code) => {\n console.log(t('cli.agent.exited', { code }));\n console.log(t('cli.agent.daemonRunning'));\n console.log(t('cli.agent.tipStop'));\n process.exit(code || 0);\n });\n\n // Handle Ctrl+C in this process\n process.on('SIGINT', () => {\n console.log(t('cli.agent.detaching'));\n claudeProcess.kill('SIGINT');\n });\n });\n}\n","import { Command } from 'commander';\nimport { spawn } from 'child_process';\nimport { DaemonManager } from '../daemon.js';\nimport { loadConfig } from '../../config.js';\nimport { homedir } from 'os';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport { t } from '../../i18n/index.js';\nimport { createAgentLogger } from '../../shared/logger.js';\n\nfunction isCodexInstalled(): boolean {\n try {\n execSync('codex --version', { encoding: 'utf8', stdio: 'pipe', windowsHide: true });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction getCodexVersion(): string | undefined {\n try {\n return execSync('codex --version', { encoding: 'utf8', stdio: 'pipe', windowsHide: true }).trim();\n } catch {\n return undefined;\n }\n}\n\nexport function registerCodexCommand(program: Command) {\n program\n .command('codex')\n .description('Start Codex CLI with handsoff integration')\n .option('-d, --directory <dir>', 'Working directory for Codex')\n .action(async (options) => {\n const version = getCodexVersion();\n\n // Check if Codex is installed\n if (!isCodexInstalled()) {\n console.error('\\n' + t('cli.codex.notInstalled') + '\\n');\n console.error(t('cli.codex.installMethods') + '\\n');\n console.error(t('cli.codex.option1npm') + '\\n');\n console.error(t('cli.codex.option2brew') + '\\n');\n console.error(t('cli.codex.alternative') + '\\n');\n process.exit(1);\n }\n\n const config = loadConfig();\n const port = config.general.hook_server_port;\n const pidFilePath = join(homedir(), '.handsoff', 'handsoff.pid');\n\n // Step 1: Ensure daemon is running\n const daemon = new DaemonManager(pidFilePath, port);\n let daemonStarted = false;\n\n if (daemon.isRunning()) {\n console.log(t('cli.codex.alreadyRunning'));\n daemonStarted = true;\n } else {\n console.log(t('cli.codex.starting'));\n daemonStarted = await daemon.start();\n if (!daemonStarted) {\n console.error(t('cli.codex.startFailed'));\n process.exit(1);\n }\n console.log(t('cli.codex.started'));\n }\n\n // Step 2: Verify daemon has Codex adapter enabled\n if (!config.agent.codex?.enabled) {\n console.error(t('cli.codex.notEnabled'));\n console.error(t('cli.codex.enableHint'));\n process.exit(1);\n }\n\n // Step 3: Launch Codex with user's local configuration\n const workDir = options.directory || process.cwd();\n const codexCommand = config.agent.codex?.command?.[0] || 'codex';\n const codexArgs = config.agent.codex?.command?.slice(1) || ['app-server', '--listen', 'stdio://'];\n\n console.log(t('cli.codex.startingIn', { dir: workDir, version: version || 'unknown' }));\n console.log(t('cli.codex.pressCtrlC') + '\\n');\n\n const codexProcess = spawn(codexCommand, codexArgs, {\n cwd: workDir,\n stdio: 'inherit',\n shell: true,\n });\n\n const logger = createAgentLogger('codex');\n logger.info({ command: codexCommand, args: codexArgs, cwd: workDir }, 'Codex CLI spawned');\n\n codexProcess.on('exit', (code) => {\n logger.info({ code }, 'Codex CLI exited');\n console.log(t('cli.codex.exited', { code }));\n console.log(t('cli.codex.daemonRunning'));\n process.exit(code || 0);\n });\n\n codexProcess.on('error', (err) => {\n logger.error({ error: err.message }, 'Codex CLI spawn failed');\n });\n\n process.on('SIGINT', () => {\n console.log(t('cli.codex.detaching'));\n codexProcess.kill('SIGINT');\n });\n\n process.on('SIGTERM', () => {\n console.log(t('cli.codex.detaching'));\n codexProcess.kill('SIGTERM');\n });\n });\n}","import pino from 'pino';\nimport { mkdirSync, existsSync, appendFileSync } from 'fs';\nimport { dirname } from 'path';\nimport { hostname } from 'os';\n\nexport enum LogLevel {\n DEBUG = 'debug',\n INFO = 'info',\n WARN = 'warn',\n ERROR = 'error',\n}\n\nconst LOG_LEVEL_MAP: Record<string, number> = {\n debug: 20,\n info: 30,\n warn: 40,\n error: 50,\n};\n\nlet fileLogger: pino.Logger | null = null;\nlet consoleLogger: pino.Logger | null = null;\nlet currentLogLevel: LogLevel = LogLevel.INFO;\n\nfunction createSyncLogger(logFilePath: string, minLevel: LogLevel = LogLevel.INFO): pino.Logger {\n const hostnameValue = hostname();\n\n const writeLog = (level: string, msg: string, obj?: object) => {\n try {\n const logDir = dirname(logFilePath);\n if (!existsSync(logDir)) {\n mkdirSync(logDir, { recursive: true });\n }\n const logEntry: Record<string, unknown> = {\n level,\n time: Date.now(),\n msg,\n pid: process.pid,\n hostname: hostnameValue,\n ...obj,\n };\n const line = JSON.stringify(logEntry) + '\\n';\n appendFileSync(logFilePath, line);\n } catch (err) {\n // eslint-disable-next-line no-console\n console.error(`[Logger] Failed to write to ${logFilePath}:`, err);\n }\n };\n\n const log = (logLevel: string) => {\n const minLevelNum = LOG_LEVEL_MAP[minLevel] ?? LOG_LEVEL_MAP.info;\n const callLevelNum = LOG_LEVEL_MAP[logLevel] ?? LOG_LEVEL_MAP.info;\n return (obj: object | string, msg?: string) => {\n if (callLevelNum < minLevelNum) return;\n if (typeof obj === 'string') {\n writeLog(logLevel, obj);\n } else {\n writeLog(logLevel, msg || '', obj);\n }\n };\n };\n\n const createChild = (_bindings: object): pino.Logger => {\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n };\n\n return {\n info: log('info'),\n warn: log('warn'),\n error: log('error'),\n debug: log('debug'),\n child: createChild,\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n\nexport function setupFileLogging(logFilePath: string, level: LogLevel = LogLevel.INFO): pino.Logger {\n currentLogLevel = level;\n fileLogger = createSyncLogger(logFilePath, level);\n return fileLogger;\n}\n\nexport function getFileLogger(): pino.Logger | null {\n return fileLogger;\n}\n\nexport function createChannelLogger(channelName: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/channels/${channelName}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createAgentLogger(agentType: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const logFile = `${homedir}/.handsoff/logs/agents/${agentType}.log`;\n return createSyncLogger(logFile, currentLogLevel);\n}\n\nexport function createSessionLogger(sessionId: string): pino.Logger {\n const homedir = process.env.HOME || process.env.USERPROFILE || '';\n const date = new Date().toISOString().split('T')[0];\n const logFile = `${homedir}/.handsoff/logs/sessions/${date}/${sessionId}.jsonl`;\n\n // Session logs are always written (NDJSON timeline), ignore currentLogLevel\n return createSyncLogger(logFile, LogLevel.DEBUG);\n}\n\nexport function getLogger(_level?: LogLevel): pino.Logger {\n if (!consoleLogger) {\n // Prefer fileLogger's level if set, otherwise use provided level or default to INFO\n const effectiveLevel = _level ?? (fileLogger ? (fileLogger as unknown as { level: string }).level as LogLevel : LogLevel.INFO);\n consoleLogger = pino({\n level: effectiveLevel,\n });\n }\n\n const delegate = (method: 'info' | 'warn' | 'error' | 'debug') => {\n return (obj: object | string, msg?: string) => {\n const target = fileLogger || consoleLogger;\n if (target) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (target as any)[method](obj, msg);\n }\n };\n };\n\n return {\n info: delegate('info'),\n warn: delegate('warn'),\n error: delegate('error'),\n debug: delegate('debug'),\n child: () => getLogger(_level),\n level: 'debug',\n levels: LOG_LEVEL_MAP,\n } as unknown as pino.Logger;\n}\n","import { Command } from 'commander';\nimport { registerClaudeCommand } from './claude.js';\nimport { registerCodexCommand } from './codex.js';\n\nexport function registerAgentCommands(program: Command) {\n registerClaudeCommand(program);\n registerCodexCommand(program);\n}\n"],"mappings":"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","names":["Command","existsSync","readFileSync","writeFileSync","mkdirSync","homedir","join","dirname","readFileSync","existsSync","join","homedir","join","homedir","existsSync","writeFileSync","readFileSync","mkdirSync","dirname","Command","existsSync","join","homedir","confirm","existsSync","join","homedir","writeFileSync","mkdirSync","join","homedir","TOML","join","homedir","mkdirSync","TOML","writeFileSync","readFileSync","existsSync","join","homedir","join","homedir","existsSync","readFileSync","execSync","writeFileSync","existsSync","readFileSync","mkdirSync","dirname","execSync","input","generateHooksConfig","existsSync","readFileSync","mkdirSync","dirname","writeFileSync","pc","pc","pc","ora","STEP","pc","pc","STEP","pc","STEP","pc","STEP","pc","STEP","join","dirname","mkdirSync","existsSync","writeFileSync","readFileSync","existsSync","existsSync","readFileSync","homedir","join","mkdirSync","__dirname","dirname","existsSync","join","homedir","pc","ora","join","homedir","existsSync","Command","join","homedir","existsSync","confirm","Command","homedir","join","existsSync","Command","homedir","join","existsSync","getSettingsPath","join","homedir","Command","existsSync","Command","homedir","join","Command","join","homedir","Command","join","homedir","join","homedir","Command","Command","spawn","fileURLToPath","dirname","join","__filename","fileURLToPath","__dirname","dirname","Command","join","spawn","spawn","homedir","join","dirname","readFileSync","existsSync","writeFileSync","mkdirSync","getSettingsPath","join","homedir","backupSettings","existsSync","writeFileSync","readFileSync","writeSettings","mkdirSync","dirname","generateHooksConfig","program","spawn","spawn","homedir","join","execSync","mkdirSync","existsSync","dirname","dirname","existsSync","mkdirSync","homedir","execSync","program","join","homedir","spawn","program","Command"]}
|