{
  "version": 3,
  "sources": ["../../../src/hooks/ts/lib/worker-session.ts", "../../../src/hooks/ts/post-tool-use/update-tab-on-action.ts"],
  "sourcesContent": ["/**\n * Worker-session detection.\n *\n * A disposable headless worker (a `claude -p` run started by an orchestrating\n * session, possibly against a different model provider with a different\n * context window) shares the project directory and the hook configuration\n * with the real session that spawned it. Left alone, the hooks treat it as a\n * session in its own right: they inject project context into it, create and\n * rename a numbered session note for it, autosave it, and enqueue a\n * model-written handover for it. Its compactions also land in the project's\n * transcript folder, where they are indistinguishable from a real session's\n * and drag the measured compaction trigger down (observed 2026-09-17: two\n * workers compacting at ~151k tokens pulled a project's trigger from ~784k\n * to ~151k, and the real session's handover fired at ~50k tokens).\n *\n * The launcher marks such sessions with `PAI_WORKER=1`. Every hook that does\n * per-session bookkeeping returns immediately when this predicate is true.\n * Deliberately NOT guarded: the security validator (a worker's shell\n * commands must still be checked) and observability capture.\n */\nexport function isWorkerSession(env: NodeJS.ProcessEnv = process.env): boolean {\n  return env.PAI_WORKER === \"1\";\n}\n", "#!/usr/bin/env node\n/**\n * Tab Title Update on Action Tools\n * Updates Kitty tab title when action tools complete (Edit, Write, Bash, Task)\n * Uses the tool's description directly - no AI call needed\n *\n * PAI-safe: No sensitive data, just tool descriptions\n */\n\nimport { isWorkerSession } from \"../lib/worker-session.js\";\nimport { execSync } from 'child_process';\n\n// Action tools that warrant a tab title update\nconst ACTION_TOOLS = new Set([\n  'Edit',\n  'Write',\n  'Bash',\n  'Task',\n  'NotebookEdit',\n  'MultiEdit'\n]);\n\ninterface HookInput {\n  session_id: string;\n  tool_name: string;\n  tool_input: {\n    description?: string;\n    command?: string;\n    file_path?: string;\n    prompt?: string;\n    subagent_type?: string;\n  };\n  tool_response?: unknown;\n  hook_event_name: string;\n}\n\n/**\n * Read stdin with timeout\n */\nasync function readStdinWithTimeout(timeout: number = 3000): Promise<string> {\n  return new Promise((resolve, reject) => {\n    let data = '';\n    const timer = setTimeout(() => {\n      reject(new Error('Timeout'));\n    }, timeout);\n\n    process.stdin.on('data', (chunk) => {\n      data += chunk.toString();\n    });\n\n    process.stdin.on('end', () => {\n      clearTimeout(timer);\n      resolve(data);\n    });\n\n    process.stdin.on('error', (err) => {\n      clearTimeout(timer);\n      reject(err);\n    });\n  });\n}\n\n/**\n * Update Kitty tab title using escape codes\n */\nfunction setTabTitle(title: string): void {\n  try {\n    // Truncate to reasonable length\n    const truncated = title.length > 50 ? title.slice(0, 47) + '...' : title;\n    const escaped = truncated.replace(/'/g, \"'\\\\''\");\n\n    // Multiple escape sequences for compatibility\n    execSync(`printf '\\\\033]0;${escaped}\\\\007' >&2`, { stdio: ['pipe', 'pipe', 'inherit'] });\n    execSync(`printf '\\\\033]2;${escaped}\\\\007' >&2`, { stdio: ['pipe', 'pipe', 'inherit'] });\n    execSync(`printf '\\\\033]30;${escaped}\\\\007' >&2`, { stdio: ['pipe', 'pipe', 'inherit'] });\n  } catch {\n    // Silently fail - don't interrupt Claude's work\n  }\n}\n\n/**\n * Generate a human-readable title from tool input\n */\nfunction generateTitle(toolName: string, input: HookInput['tool_input']): string {\n  // Use explicit description if provided\n  if (input.description) {\n    return input.description;\n  }\n\n  // Generate based on tool type\n  switch (toolName) {\n    case 'Edit':\n    case 'Write':\n    case 'MultiEdit':\n    case 'NotebookEdit':\n      if (input.file_path) {\n        const filename = input.file_path.split('/').pop() || input.file_path;\n        return `Editing ${filename}`;\n      }\n      return `Editing file`;\n\n    case 'Bash':\n      if (input.command) {\n        // Extract first command word\n        const cmd = input.command.split(/\\s+/)[0].split('/').pop() || 'command';\n        return `Running ${cmd}`;\n      }\n      return 'Running command';\n\n    case 'Task':\n      if (input.subagent_type) {\n        return `Agent: ${input.subagent_type}`;\n      }\n      if (input.prompt) {\n        const words = input.prompt.slice(0, 30).split(/\\s+/).slice(0, 3).join(' ');\n        return `Task: ${words}...`;\n      }\n      return 'Spawning agent';\n\n    default:\n      return `${toolName}...`;\n  }\n}\n\nasync function main() {\n  if (isWorkerSession()) return; // disposable worker: no per-session bookkeeping\n  try {\n    const input = await readStdinWithTimeout();\n    const data: HookInput = JSON.parse(input);\n\n    // Only process action tools\n    if (!ACTION_TOOLS.has(data.tool_name)) {\n      process.exit(0);\n    }\n\n    // Generate and set title\n    const title = generateTitle(data.tool_name, data.tool_input);\n    setTabTitle(title);\n\n    process.exit(0);\n  } catch {\n    // Silently exit - don't interrupt Claude's flow\n    process.exit(0);\n  }\n}\n\nmain();\n"],
  "mappings": ";;;;;;AAoBO,SAAS,gBAAgB,MAAyB,QAAQ,KAAc;AAC7E,SAAO,IAAI,eAAe;AAC5B;;;ACZA,SAAS,gBAAgB;AAGzB,IAAM,eAAe,oBAAI,IAAI;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAmBD,eAAe,qBAAqB,UAAkB,KAAuB;AAC3E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,OAAO;AACX,UAAM,QAAQ,WAAW,MAAM;AAC7B,aAAO,IAAI,MAAM,SAAS,CAAC;AAAA,IAC7B,GAAG,OAAO;AAEV,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAU;AAClC,cAAQ,MAAM,SAAS;AAAA,IACzB,CAAC;AAED,YAAQ,MAAM,GAAG,OAAO,MAAM;AAC5B,mBAAa,KAAK;AAClB,cAAQ,IAAI;AAAA,IACd,CAAC;AAED,YAAQ,MAAM,GAAG,SAAS,CAAC,QAAQ;AACjC,mBAAa,KAAK;AAClB,aAAO,GAAG;AAAA,IACZ,CAAC;AAAA,EACH,CAAC;AACH;AAKA,SAAS,YAAY,OAAqB;AACxC,MAAI;AAEF,UAAM,YAAY,MAAM,SAAS,KAAK,MAAM,MAAM,GAAG,EAAE,IAAI,QAAQ;AACnE,UAAM,UAAU,UAAU,QAAQ,MAAM,OAAO;AAG/C,aAAS,mBAAmB,OAAO,cAAc,EAAE,OAAO,CAAC,QAAQ,QAAQ,SAAS,EAAE,CAAC;AACvF,aAAS,mBAAmB,OAAO,cAAc,EAAE,OAAO,CAAC,QAAQ,QAAQ,SAAS,EAAE,CAAC;AACvF,aAAS,oBAAoB,OAAO,cAAc,EAAE,OAAO,CAAC,QAAQ,QAAQ,SAAS,EAAE,CAAC;AAAA,EAC1F,QAAQ;AAAA,EAER;AACF;AAKA,SAAS,cAAc,UAAkB,OAAwC;AAE/E,MAAI,MAAM,aAAa;AACrB,WAAO,MAAM;AAAA,EACf;AAGA,UAAQ,UAAU;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,UAAI,MAAM,WAAW;AACnB,cAAM,WAAW,MAAM,UAAU,MAAM,GAAG,EAAE,IAAI,KAAK,MAAM;AAC3D,eAAO,WAAW,QAAQ;AAAA,MAC5B;AACA,aAAO;AAAA,IAET,KAAK;AACH,UAAI,MAAM,SAAS;AAEjB,cAAM,MAAM,MAAM,QAAQ,MAAM,KAAK,EAAE,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,KAAK;AAC9D,eAAO,WAAW,GAAG;AAAA,MACvB;AACA,aAAO;AAAA,IAET,KAAK;AACH,UAAI,MAAM,eAAe;AACvB,eAAO,UAAU,MAAM,aAAa;AAAA,MACtC;AACA,UAAI,MAAM,QAAQ;AAChB,cAAM,QAAQ,MAAM,OAAO,MAAM,GAAG,EAAE,EAAE,MAAM,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,GAAG;AACzE,eAAO,SAAS,KAAK;AAAA,MACvB;AACA,aAAO;AAAA,IAET;AACE,aAAO,GAAG,QAAQ;AAAA,EACtB;AACF;AAEA,eAAe,OAAO;AACpB,MAAI,gBAAgB,EAAG;AACvB,MAAI;AACF,UAAM,QAAQ,MAAM,qBAAqB;AACzC,UAAM,OAAkB,KAAK,MAAM,KAAK;AAGxC,QAAI,CAAC,aAAa,IAAI,KAAK,SAAS,GAAG;AACrC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAGA,UAAM,QAAQ,cAAc,KAAK,WAAW,KAAK,UAAU;AAC3D,gBAAY,KAAK;AAEjB,YAAQ,KAAK,CAAC;AAAA,EAChB,QAAQ;AAEN,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;",
  "names": []
}
