{
  "version": 3,
  "sources": ["../../../src/hooks/ts/lib/worker-session.ts", "../../../src/hooks/ts/user-prompt/update-tab-titles.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 Hook\n * Updates tab title based on user prompt\n *\n * Note: All context loading handled by PAI skill system (core identity in skill description, full context in SKILL.md)\n */\n\nimport { isWorkerSession } from \"../lib/worker-session.js\";\nimport { execSync } from 'child_process';\n\ninterface HookInput {\n  session_id: string;\n  prompt: string;\n  transcript_path: string;\n  hook_event_name: string;\n}\n\n/**\n * Read stdin with timeout\n */\nasync function readStdinWithTimeout(timeout: number = 5000): Promise<string> {\n  return new Promise((resolve, reject) => {\n    let data = '';\n    const timer = setTimeout(() => {\n      reject(new Error('Timeout reading from stdin'));\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\nasync function main() {\n  if (isWorkerSession()) return; // disposable worker: no per-session bookkeeping\n  try {\n    // Read the hook input from stdin\n    const input = await readStdinWithTimeout();\n    const data: HookInput = JSON.parse(input);\n\n    const prompt = data.prompt || '';\n\n    // UPDATE TAB TITLE\n    // Generate quick fallback tab title\n    let tabTitle = 'Processing request...';\n    if (prompt) {\n      const words = prompt.replace(/[^\\w\\s]/g, ' ').trim().split(/\\s+/)\n        .filter(w => w.length > 2 && !['the', 'and', 'but', 'for', 'are', 'with', 'you', 'can'].includes(w.toLowerCase()))\n        .slice(0, 3);\n\n      if (words.length > 0) {\n        tabTitle = words[0].charAt(0).toUpperCase() + words[0].slice(1).toLowerCase();\n        if (words.length > 1) {\n          tabTitle += ' ' + words.slice(1).map(w => w.toLowerCase()).join(' ');\n        }\n        tabTitle += '...';\n      }\n    }\n\n    // Set initial tab title with recycle emoji\n    try {\n      const titleWithEmoji = '\u267B\uFE0F ' + tabTitle;\n      const escapedTitle = titleWithEmoji.replace(/'/g, \"'\\\\''\");\n      execSync(`printf '\\\\033]0;${escapedTitle}\\\\007' >&2`);\n      execSync(`printf '\\\\033]2;${escapedTitle}\\\\007' >&2`);\n      execSync(`printf '\\\\033]30;${escapedTitle}\\\\007' >&2`);\n    } catch (e) {\n      // Silently fail\n    }\n\n    process.exit(0);\n  } catch (error) {\n    // Silently fail to not interrupt Claude's flow\n    console.error('Tab title update error:', error);\n    process.exit(0);\n  }\n}\n\nmain();\n"],
  "mappings": ";;;;;;AAoBO,SAAS,gBAAgB,MAAyB,QAAQ,KAAc;AAC7E,SAAO,IAAI,eAAe;AAC5B;;;ACbA,SAAS,gBAAgB;AAYzB,eAAe,qBAAqB,UAAkB,KAAuB;AAC3E,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,QAAI,OAAO;AACX,UAAM,QAAQ,WAAW,MAAM;AAC7B,aAAO,IAAI,MAAM,4BAA4B,CAAC;AAAA,IAChD,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;AAEA,eAAe,OAAO;AACpB,MAAI,gBAAgB,EAAG;AACvB,MAAI;AAEF,UAAM,QAAQ,MAAM,qBAAqB;AACzC,UAAM,OAAkB,KAAK,MAAM,KAAK;AAExC,UAAM,SAAS,KAAK,UAAU;AAI9B,QAAI,WAAW;AACf,QAAI,QAAQ;AACV,YAAM,QAAQ,OAAO,QAAQ,YAAY,GAAG,EAAE,KAAK,EAAE,MAAM,KAAK,EAC7D,OAAO,OAAK,EAAE,SAAS,KAAK,CAAC,CAAC,OAAO,OAAO,OAAO,OAAO,OAAO,QAAQ,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC,EAChH,MAAM,GAAG,CAAC;AAEb,UAAI,MAAM,SAAS,GAAG;AACpB,mBAAW,MAAM,CAAC,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,CAAC,EAAE,MAAM,CAAC,EAAE,YAAY;AAC5E,YAAI,MAAM,SAAS,GAAG;AACpB,sBAAY,MAAM,MAAM,MAAM,CAAC,EAAE,IAAI,OAAK,EAAE,YAAY,CAAC,EAAE,KAAK,GAAG;AAAA,QACrE;AACA,oBAAY;AAAA,MACd;AAAA,IACF;AAGA,QAAI;AACF,YAAM,iBAAiB,kBAAQ;AAC/B,YAAM,eAAe,eAAe,QAAQ,MAAM,OAAO;AACzD,eAAS,mBAAmB,YAAY,YAAY;AACpD,eAAS,mBAAmB,YAAY,YAAY;AACpD,eAAS,oBAAoB,YAAY,YAAY;AAAA,IACvD,SAAS,GAAG;AAAA,IAEZ;AAEA,YAAQ,KAAK,CAAC;AAAA,EAChB,SAAS,OAAO;AAEd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,YAAQ,KAAK,CAAC;AAAA,EAChB;AACF;AAEA,KAAK;",
  "names": []
}
