@juspay/shooter 1.10.0 → 1.12.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.
Files changed (163) hide show
  1. package/.claude/hooks/notifier.cjs +24 -242
  2. package/bin/lib/tunnel-discovery.cjs +519 -0
  3. package/bin/shooter.cjs +204 -49
  4. package/build/client/_app/immutable/chunks/{CmtInjm0.js → DTGtOxE1.js} +1 -1
  5. package/build/client/_app/immutable/chunks/DTGtOxE1.js.br +0 -0
  6. package/build/client/_app/immutable/chunks/DTGtOxE1.js.gz +0 -0
  7. package/build/client/_app/immutable/chunks/{DfKeHoAm.js → DfsJh23H.js} +1 -1
  8. package/build/client/_app/immutable/chunks/DfsJh23H.js.br +0 -0
  9. package/build/client/_app/immutable/chunks/DfsJh23H.js.gz +0 -0
  10. package/build/client/_app/immutable/chunks/DlSs5Yra.js +3 -0
  11. package/build/client/_app/immutable/chunks/DlSs5Yra.js.br +0 -0
  12. package/build/client/_app/immutable/chunks/DlSs5Yra.js.gz +0 -0
  13. package/build/client/_app/immutable/entry/{app.Dp9YhfEg.js → app.B-sEFuLK.js} +2 -2
  14. package/build/client/_app/immutable/entry/app.B-sEFuLK.js.br +0 -0
  15. package/build/client/_app/immutable/entry/app.B-sEFuLK.js.gz +0 -0
  16. package/build/client/_app/immutable/entry/start.A2buqyYO.js +1 -0
  17. package/build/client/_app/immutable/entry/start.A2buqyYO.js.br +2 -0
  18. package/build/client/_app/immutable/entry/start.A2buqyYO.js.gz +0 -0
  19. package/build/client/_app/immutable/nodes/{0.B-M6sgow.js → 0.-0SstbRm.js} +1 -1
  20. package/build/client/_app/immutable/nodes/0.-0SstbRm.js.br +0 -0
  21. package/build/client/_app/immutable/nodes/0.-0SstbRm.js.gz +0 -0
  22. package/build/client/_app/immutable/nodes/{1.C8aY7Yn3.js → 1.BVLzPogE.js} +1 -1
  23. package/build/client/_app/immutable/nodes/1.BVLzPogE.js.br +0 -0
  24. package/build/client/_app/immutable/nodes/1.BVLzPogE.js.gz +0 -0
  25. package/build/client/_app/immutable/nodes/{2.YJZruh1H.js → 2.CiUyTQg5.js} +1 -1
  26. package/build/client/_app/immutable/nodes/2.CiUyTQg5.js.br +0 -0
  27. package/build/client/_app/immutable/nodes/2.CiUyTQg5.js.gz +0 -0
  28. package/build/client/_app/immutable/nodes/{3.VV-tRemY.js → 3.C9vlOBU0.js} +1 -1
  29. package/build/client/_app/immutable/nodes/3.C9vlOBU0.js.br +0 -0
  30. package/build/client/_app/immutable/nodes/3.C9vlOBU0.js.gz +0 -0
  31. package/build/client/_app/immutable/nodes/{6.CDJA8Na9.js → 6.BSsUBbIT.js} +1 -1
  32. package/build/client/_app/immutable/nodes/6.BSsUBbIT.js.br +0 -0
  33. package/build/client/_app/immutable/nodes/6.BSsUBbIT.js.gz +0 -0
  34. package/build/client/_app/immutable/nodes/{7.BX9znBYU.js → 7.BIQq9Yuz.js} +1 -1
  35. package/build/client/_app/immutable/nodes/7.BIQq9Yuz.js.br +0 -0
  36. package/build/client/_app/immutable/nodes/7.BIQq9Yuz.js.gz +0 -0
  37. package/build/client/_app/immutable/nodes/{8.CmdrNdfj.js → 8.BU_sJ5_M.js} +1 -1
  38. package/build/client/_app/immutable/nodes/8.BU_sJ5_M.js.br +0 -0
  39. package/build/client/_app/immutable/nodes/8.BU_sJ5_M.js.gz +0 -0
  40. package/build/client/_app/immutable/nodes/{9.BSleOtKF.js → 9.C1vJI771.js} +1 -1
  41. package/build/client/_app/immutable/nodes/9.C1vJI771.js.br +0 -0
  42. package/build/client/_app/immutable/nodes/9.C1vJI771.js.gz +0 -0
  43. package/build/client/_app/version.json +1 -1
  44. package/build/client/_app/version.json.br +0 -0
  45. package/build/client/_app/version.json.gz +0 -0
  46. package/build/server/chunks/{0-vSdphvn2.js → 0-DgzcVTc0.js} +3 -3
  47. package/build/server/chunks/{0-vSdphvn2.js.map → 0-DgzcVTc0.js.map} +1 -1
  48. package/build/server/chunks/{1-B5tn1ob0.js → 1-iMvE8O_M.js} +3 -3
  49. package/build/server/chunks/{1-B5tn1ob0.js.map → 1-iMvE8O_M.js.map} +1 -1
  50. package/build/server/chunks/{2-CUbzGnZ8.js → 2-BJrmwHii.js} +3 -3
  51. package/build/server/chunks/{2-CUbzGnZ8.js.map → 2-BJrmwHii.js.map} +1 -1
  52. package/build/server/chunks/{3-BR90tKg7.js → 3-Ds3b4DfT.js} +3 -3
  53. package/build/server/chunks/{3-BR90tKg7.js.map → 3-Ds3b4DfT.js.map} +1 -1
  54. package/build/server/chunks/{4-CbejE1SC.js → 4-BtYdKCVW.js} +2 -2
  55. package/build/server/chunks/{4-CbejE1SC.js.map → 4-BtYdKCVW.js.map} +1 -1
  56. package/build/server/chunks/{5-BwqumuR1.js → 5-CvJK3PiH.js} +2 -2
  57. package/build/server/chunks/{5-BwqumuR1.js.map → 5-CvJK3PiH.js.map} +1 -1
  58. package/build/server/chunks/{6-cW7umWCt.js → 6-DEbZkQEO.js} +3 -3
  59. package/build/server/chunks/{6-cW7umWCt.js.map → 6-DEbZkQEO.js.map} +1 -1
  60. package/build/server/chunks/{7-D3cb9T2g.js → 7-BrQeR-CO.js} +3 -3
  61. package/build/server/chunks/{7-D3cb9T2g.js.map → 7-BrQeR-CO.js.map} +1 -1
  62. package/build/server/chunks/{8-BEgZo4wA.js → 8-e5TDwEpx.js} +3 -3
  63. package/build/server/chunks/{8-BEgZo4wA.js.map → 8-e5TDwEpx.js.map} +1 -1
  64. package/build/server/chunks/{9-Dy8aTTtf.js → 9-1iqRqatJ.js} +3 -3
  65. package/build/server/chunks/{9-Dy8aTTtf.js.map → 9-1iqRqatJ.js.map} +1 -1
  66. package/build/server/chunks/{Button-Dpueno77.js → Button-B5dU-ntz.js} +2 -2
  67. package/build/server/chunks/{Button-Dpueno77.js.map → Button-B5dU-ntz.js.map} +1 -1
  68. package/build/server/chunks/{Icon-aOLx5ELI.js → Icon-C7Ml3GX6.js} +3 -3
  69. package/build/server/chunks/{Icon-aOLx5ELI.js.map → Icon-C7Ml3GX6.js.map} +1 -1
  70. package/build/server/chunks/{Input-Cq7ZdLxS.js → Input-CPGO0sbS.js} +2 -2
  71. package/build/server/chunks/{Input-Cq7ZdLxS.js.map → Input-CPGO0sbS.js.map} +1 -1
  72. package/build/server/chunks/{Pill-Bn597jm0.js → Pill-CcrtCejm.js} +3 -3
  73. package/build/server/chunks/{Pill-Bn597jm0.js.map → Pill-CcrtCejm.js.map} +1 -1
  74. package/build/server/chunks/{Shimmer-5o7MVwXF.js → Shimmer-C5jkvGr1.js} +2 -2
  75. package/build/server/chunks/{Shimmer-5o7MVwXF.js.map → Shimmer-C5jkvGr1.js.map} +1 -1
  76. package/build/server/chunks/{_error.svelte-C85mEsv9.js → _error.svelte-CSIxs-ab.js} +8 -8
  77. package/build/server/chunks/{_error.svelte-C85mEsv9.js.map → _error.svelte-CSIxs-ab.js.map} +1 -1
  78. package/build/server/chunks/{_layout.svelte-rpYLLajc.js → _layout.svelte-noB4j-v2.js} +10 -10
  79. package/build/server/chunks/{_layout.svelte-rpYLLajc.js.map → _layout.svelte-noB4j-v2.js.map} +1 -1
  80. package/build/server/chunks/{_page.svelte-BfCXobKv.js → _page.svelte-B6qyh-K-.js} +11 -11
  81. package/build/server/chunks/{_page.svelte-BfCXobKv.js.map → _page.svelte-B6qyh-K-.js.map} +1 -1
  82. package/build/server/chunks/{_page.svelte-CA46TyHk.js → _page.svelte-BUkm2304.js} +5 -5
  83. package/build/server/chunks/{_page.svelte-CA46TyHk.js.map → _page.svelte-BUkm2304.js.map} +1 -1
  84. package/build/server/chunks/{_page.svelte-B6O0uTrK.js → _page.svelte-BV0XyYJZ.js} +4 -4
  85. package/build/server/chunks/{_page.svelte-B6O0uTrK.js.map → _page.svelte-BV0XyYJZ.js.map} +1 -1
  86. package/build/server/chunks/{_page.svelte-CCpVmMpU.js → _page.svelte-BfB8maoc.js} +9 -9
  87. package/build/server/chunks/{_page.svelte-CCpVmMpU.js.map → _page.svelte-BfB8maoc.js.map} +1 -1
  88. package/build/server/chunks/{_page.svelte-DjADcbfZ.js → _page.svelte-C60lAagP.js} +8 -8
  89. package/build/server/chunks/{_page.svelte-DjADcbfZ.js.map → _page.svelte-C60lAagP.js.map} +1 -1
  90. package/build/server/chunks/{_page.svelte-DUj1mSq0.js → _page.svelte-Dmg-RFCg.js} +7 -7
  91. package/build/server/chunks/{_page.svelte-DUj1mSq0.js.map → _page.svelte-Dmg-RFCg.js.map} +1 -1
  92. package/build/server/chunks/{_page.svelte-fkR4xqGu.js → _page.svelte-DnTpPnPR.js} +5 -5
  93. package/build/server/chunks/{_page.svelte-fkR4xqGu.js.map → _page.svelte-DnTpPnPR.js.map} +1 -1
  94. package/build/server/chunks/{_page.svelte-D0FBtMtH.js → _page.svelte-DuzZr5dA.js} +11 -11
  95. package/build/server/chunks/{_page.svelte-D0FBtMtH.js.map → _page.svelte-DuzZr5dA.js.map} +1 -1
  96. package/build/server/chunks/{_server.ts-HGYjOWF2.js → _server.ts-C-W5J15L.js} +2 -2
  97. package/build/server/chunks/{_server.ts-HGYjOWF2.js.map → _server.ts-C-W5J15L.js.map} +1 -1
  98. package/build/server/chunks/_server.ts-CvJKTS3Z.js +35 -0
  99. package/build/server/chunks/_server.ts-CvJKTS3Z.js.map +1 -0
  100. package/build/server/chunks/{_server.ts-BBLuxvp6.js → _server.ts-tChyh9FX.js} +43 -8
  101. package/build/server/chunks/_server.ts-tChyh9FX.js.map +1 -0
  102. package/build/server/chunks/{cache-5_eamjtv.js → cache-Me3zUAaD.js} +2 -2
  103. package/build/server/chunks/{cache-5_eamjtv.js.map → cache-Me3zUAaD.js.map} +1 -1
  104. package/build/server/chunks/{client-w1WsLDGu.js → client-CfNnl32g.js} +4 -4
  105. package/build/server/chunks/{client-w1WsLDGu.js.map → client-CfNnl32g.js.map} +1 -1
  106. package/build/server/chunks/client2-DDP30_vY.js +7 -0
  107. package/build/server/chunks/{client2-B5wCRDQi.js.map → client2-DDP30_vY.js.map} +1 -1
  108. package/build/server/chunks/{index-DMikC9Qy.js → index-CJrGuxuM.js} +2 -2
  109. package/build/server/chunks/{index-DMikC9Qy.js.map → index-CJrGuxuM.js.map} +1 -1
  110. package/build/server/chunks/{index-server-DHNcb_Bd.js → index-server--49oHtA0.js} +2 -2
  111. package/build/server/chunks/{index-server-DHNcb_Bd.js.map → index-server--49oHtA0.js.map} +1 -1
  112. package/build/server/chunks/{index2-BTTf6mSG.js → index2-MY7PXeAc.js} +2 -2
  113. package/build/server/chunks/{index2-BTTf6mSG.js.map → index2-MY7PXeAc.js.map} +1 -1
  114. package/build/server/chunks/pending-requests-C9p57WoU.js +174 -0
  115. package/build/server/chunks/pending-requests-C9p57WoU.js.map +1 -0
  116. package/build/server/chunks/{root-DhBbA8QD.js → root-xvQIR1Bt.js} +2 -2
  117. package/build/server/chunks/{root-DhBbA8QD.js.map → root-xvQIR1Bt.js.map} +1 -1
  118. package/build/server/chunks/{state.svelte-M8y8rROy.js → state.svelte-RCtlkrNH.js} +3 -3
  119. package/build/server/chunks/{state.svelte-M8y8rROy.js.map → state.svelte-RCtlkrNH.js.map} +1 -1
  120. package/build/server/chunks/{stores-CwkRmCHA.js → stores-C-LqoonT.js} +4 -4
  121. package/build/server/chunks/{stores-CwkRmCHA.js.map → stores-C-LqoonT.js.map} +1 -1
  122. package/build/server/index.js +4 -4
  123. package/build/server/index.js.map +1 -1
  124. package/build/server/manifest.js +20 -13
  125. package/build/server/manifest.js.map +1 -1
  126. package/package.json +2 -2
  127. package/src/lib/modules/server/apn/pending-requests.ts +156 -33
  128. package/src/lib/types/decision.ts +114 -0
  129. package/src/lib/types/index.ts +1 -0
  130. package/src/routes/api/decide/[requestId]/+server.ts +46 -0
  131. package/src/routes/api/response/+server.ts +61 -11
  132. package/build/client/_app/immutable/chunks/BFXEYMV8.js +0 -3
  133. package/build/client/_app/immutable/chunks/BFXEYMV8.js.br +0 -0
  134. package/build/client/_app/immutable/chunks/BFXEYMV8.js.gz +0 -0
  135. package/build/client/_app/immutable/chunks/CmtInjm0.js.br +0 -0
  136. package/build/client/_app/immutable/chunks/CmtInjm0.js.gz +0 -0
  137. package/build/client/_app/immutable/chunks/DfKeHoAm.js.br +0 -0
  138. package/build/client/_app/immutable/chunks/DfKeHoAm.js.gz +0 -0
  139. package/build/client/_app/immutable/entry/app.Dp9YhfEg.js.br +0 -0
  140. package/build/client/_app/immutable/entry/app.Dp9YhfEg.js.gz +0 -0
  141. package/build/client/_app/immutable/entry/start.Bc5yZsyK.js +0 -1
  142. package/build/client/_app/immutable/entry/start.Bc5yZsyK.js.br +0 -2
  143. package/build/client/_app/immutable/entry/start.Bc5yZsyK.js.gz +0 -0
  144. package/build/client/_app/immutable/nodes/0.B-M6sgow.js.br +0 -0
  145. package/build/client/_app/immutable/nodes/0.B-M6sgow.js.gz +0 -0
  146. package/build/client/_app/immutable/nodes/1.C8aY7Yn3.js.br +0 -0
  147. package/build/client/_app/immutable/nodes/1.C8aY7Yn3.js.gz +0 -0
  148. package/build/client/_app/immutable/nodes/2.YJZruh1H.js.br +0 -0
  149. package/build/client/_app/immutable/nodes/2.YJZruh1H.js.gz +0 -0
  150. package/build/client/_app/immutable/nodes/3.VV-tRemY.js.br +0 -0
  151. package/build/client/_app/immutable/nodes/3.VV-tRemY.js.gz +0 -0
  152. package/build/client/_app/immutable/nodes/6.CDJA8Na9.js.br +0 -0
  153. package/build/client/_app/immutable/nodes/6.CDJA8Na9.js.gz +0 -0
  154. package/build/client/_app/immutable/nodes/7.BX9znBYU.js.br +0 -0
  155. package/build/client/_app/immutable/nodes/7.BX9znBYU.js.gz +0 -0
  156. package/build/client/_app/immutable/nodes/8.CmdrNdfj.js.br +0 -0
  157. package/build/client/_app/immutable/nodes/8.CmdrNdfj.js.gz +0 -0
  158. package/build/client/_app/immutable/nodes/9.BSleOtKF.js.br +0 -0
  159. package/build/client/_app/immutable/nodes/9.BSleOtKF.js.gz +0 -0
  160. package/build/server/chunks/_server.ts-BBLuxvp6.js.map +0 -1
  161. package/build/server/chunks/client2-B5wCRDQi.js +0 -7
  162. package/build/server/chunks/pending-requests-B-JNGxpk.js +0 -96
  163. package/build/server/chunks/pending-requests-B-JNGxpk.js.map +0 -1
@@ -64,17 +64,10 @@ if (IS_CLAUDE_CODE && !API_KEY) {
64
64
  process.exit(1);
65
65
  }
66
66
 
67
- // Completion detection timeout
68
- const COMPLETION_TIMEOUT = 45000; // 45 seconds
69
-
70
67
  // Bidirectional permission response polling
71
68
  const PERMISSION_TIMEOUT = parseInt(process.env.SHOOTER_PERMISSION_TIMEOUT || '120') * 1000;
72
69
  const POLL_INTERVAL = 2000; // 2 seconds between polls
73
70
  const RESPONSE_URL = `${BASE_URL}/api/response`;
74
- const STATE_DIR = `/tmp/claude_session_tracker`;
75
-
76
- // Global timeout tracker per project (for OpenCode)
77
- const completionTimers = new Map();
78
71
 
79
72
  // Debug logging flag
80
73
  const DEBUG_ENABLED = process.env.SHOOTER_DEBUG === 'true';
@@ -190,18 +183,27 @@ function readStdin() {
190
183
  /**
191
184
  * Common Event Format - all events normalized to this structure
192
185
  *
193
- * eventType values:
194
- * 'tool.before' - Tool is about to execute (activity tracking)
195
- * 'tool.after' - Tool finished executing (activity tracking)
196
- * 'session.idle' - Agent finished responding (completion timer)
186
+ * eventType values handled by the dispatcher:
187
+ * 'tool.before' - Tool is about to execute (debug log only)
188
+ * 'tool.after' - Tool finished executing (debug log only)
197
189
  * 'session.start' - New session started
190
+ * 'session.end' - Session terminated
191
+ * 'subagent.start' - Subagent spawned
192
+ * 'subagent.stop' - Subagent finished
193
+ * 'user.prompt' - User submitted a prompt
198
194
  * 'permission' - Agent needs permission to run a tool
195
+ * 'permission_notification' - Permission dialog opened (informational)
199
196
  * 'question' - Agent is asking user a question / presenting options
200
197
  * 'idle_input' - Agent is idle, waiting for user to type
201
198
  * 'intervention' - Generic intervention needed (fallback)
202
- * 'error' - An error occurred
203
- * 'check.completion' - Manual completion check
204
- * 'session.status' - Internal status update (ignored)
199
+ * 'error' - An error occurred (debug log only — not actionable from phone)
200
+ * 'context.compact' - Context about to be compacted (debug log only)
201
+ *
202
+ * Other event types emitted by adapters (e.g. 'session.idle', 'task.completed',
203
+ * 'teammate.idle', 'check.completion', 'session.status') fall through to the
204
+ * dispatcher's default case and are silently ignored — agent-idle and
205
+ * task-completion notifications were intentionally removed because they
206
+ * aren't actionable remotely.
205
207
  */
206
208
  function createCommonEvent(source, eventType, data = {}) {
207
209
  return {
@@ -412,15 +414,9 @@ function adaptOpenCodeEvent(hookEventType, hookData = {}) {
412
414
  }
413
415
 
414
416
  // ============================================
415
- // SECTION 5: Session State Management
417
+ // SECTION 5: Project / Session Identification
416
418
  // ============================================
417
419
 
418
- function ensureStateDir() {
419
- if (!fs.existsSync(STATE_DIR)) {
420
- fs.mkdirSync(STATE_DIR, { recursive: true });
421
- }
422
- }
423
-
424
420
  function getProjectName() {
425
421
  return path.basename(process.cwd()) || 'unknown';
426
422
  }
@@ -432,45 +428,6 @@ function getSessionIdentifier() {
432
428
  return `${projectName}_${runtime}_${pid}`;
433
429
  }
434
430
 
435
- function getSessionState() {
436
- ensureStateDir();
437
- const sessionId = getSessionIdentifier();
438
- const stateFile = path.join(STATE_DIR, `session_state_${sessionId}.json`);
439
-
440
- try {
441
- if (fs.existsSync(stateFile)) {
442
- const data = fs.readFileSync(stateFile, 'utf8');
443
- return JSON.parse(data);
444
- }
445
- } catch (error) {
446
- debugLog(`Could not read session state: ${error.message}`);
447
- }
448
-
449
- const projectName = getProjectName();
450
- return {
451
- lastStopTime: null,
452
- lastActivityTime: Date.now(),
453
- sessionId: sessionId,
454
- pendingCompletion: false,
455
- project: projectName,
456
- recentTools: [],
457
- recentFiles: [],
458
- totalToolUses: 0,
459
- };
460
- }
461
-
462
- function saveSessionState(state) {
463
- ensureStateDir();
464
- const sessionId = getSessionIdentifier();
465
- const stateFile = path.join(STATE_DIR, `session_state_${sessionId}.json`);
466
-
467
- try {
468
- fs.writeFileSync(stateFile, JSON.stringify(state, null, 2));
469
- } catch (error) {
470
- debugLog(`Could not save session state: ${error.message}`);
471
- }
472
- }
473
-
474
431
  // ============================================
475
432
  // SECTION 6: Event Processor (Source-Agnostic)
476
433
  // ============================================
@@ -490,10 +447,6 @@ async function processEvent(event) {
490
447
  handleToolEnd(event);
491
448
  break;
492
449
 
493
- case 'session.idle':
494
- handleSessionIdle(event);
495
- break;
496
-
497
450
  case 'session.start':
498
451
  handleSessionStart(event);
499
452
  break;
@@ -524,10 +477,6 @@ async function processEvent(event) {
524
477
  handleError(event);
525
478
  break;
526
479
 
527
- case 'check.completion':
528
- handleCheckCompletion(event);
529
- break;
530
-
531
480
  case 'session.end':
532
481
  handleSessionEnd(event);
533
482
  break;
@@ -544,14 +493,6 @@ async function processEvent(event) {
544
493
  handleUserPrompt(event);
545
494
  break;
546
495
 
547
- case 'teammate.idle':
548
- handleTeammateIdle(event);
549
- break;
550
-
551
- case 'task.completed':
552
- handleTaskCompleted(event);
553
- break;
554
-
555
496
  case 'context.compact':
556
497
  debugLog('Context compact event - tracking only');
557
498
  break;
@@ -571,55 +512,15 @@ async function processEvent(event) {
571
512
  // ============================================
572
513
 
573
514
  function handleToolStart(event) {
574
- const state = getSessionState();
575
- const now = Date.now();
576
-
577
515
  debugLog(`Tool starting: ${event.data.tool || 'unknown'}`);
578
-
579
- state.lastActivityTime = now;
580
- state.pendingCompletion = false;
581
-
582
- if (!state.recentTools) state.recentTools = [];
583
- if (!state.totalToolUses) state.totalToolUses = 0;
584
-
585
- state.recentTools.unshift(event.data.tool || 'unknown');
586
- state.recentTools = state.recentTools.slice(0, 10);
587
- state.totalToolUses++;
588
-
589
- saveSessionState(state);
590
-
591
- cancelCompletionTimer(event.projectName);
592
- debugLog(`Activity detected, completion timer cancelled (${state.totalToolUses} tools total)`);
593
516
  }
594
517
 
595
518
  function handleToolEnd(event) {
596
- const state = getSessionState();
597
- state.lastActivityTime = Date.now();
598
- saveSessionState(state);
599
519
  debugLog(`Tool complete: ${event.data.tool || 'unknown'}`);
600
520
  }
601
521
 
602
- function handleSessionIdle(event) {
603
- const state = getSessionState();
604
- const now = Date.now();
605
-
606
- debugLog(`Session idle detected - starting ${COMPLETION_TIMEOUT / 1000}s completion timer`);
607
-
608
- state.lastStopTime = now;
609
- state.pendingCompletion = true;
610
- saveSessionState(state);
611
-
612
- scheduleCompletionTimer(event.projectName);
613
- }
614
-
615
- function handleSessionStart(event) {
616
- const state = getSessionState();
617
- state.sessionId = Date.now().toString();
618
- state.lastActivityTime = Date.now();
619
- state.pendingCompletion = false;
620
- saveSessionState(state);
621
- cancelCompletionTimer(event.projectName);
622
- debugLog(`New session started: ${state.sessionId}`);
522
+ function handleSessionStart(_event) {
523
+ debugLog(`New session started: ${getSessionIdentifier()}`);
623
524
  }
624
525
 
625
526
  /**
@@ -825,52 +726,20 @@ function handleError(event) {
825
726
  debugLog(`Error detected (not notifying): ${event.data.message}`);
826
727
  }
827
728
 
828
- function handleCheckCompletion(event) {
829
- debugLog(`Manual completion check requested`);
830
- checkCompletion(event.projectName, event.source);
831
- }
832
-
833
- function handleSessionEnd(event) {
834
- const state = getSessionState();
835
- state.pendingCompletion = false;
836
- saveSessionState(state);
837
- cancelCompletionTimer(event.projectName);
838
- debugLog('Session ended - cleaned up state');
729
+ function handleSessionEnd(_event) {
730
+ debugLog('Session ended');
839
731
  }
840
732
 
841
733
  function handleSubagentStart(event) {
842
- const state = getSessionState();
843
- state.lastActivityTime = Date.now();
844
- state.pendingCompletion = false;
845
- saveSessionState(state);
846
- cancelCompletionTimer(event.projectName);
847
734
  debugLog(`Subagent started: ${event.data.agentType}`);
848
735
  }
849
736
 
850
737
  function handleSubagentStop(event) {
851
- const state = getSessionState();
852
- state.lastActivityTime = Date.now();
853
- saveSessionState(state);
854
738
  debugLog(`Subagent stopped: ${event.data.agentType}`);
855
739
  }
856
740
 
857
- function handleUserPrompt(event) {
858
- const state = getSessionState();
859
- state.lastActivityTime = Date.now();
860
- state.pendingCompletion = false;
861
- saveSessionState(state);
862
- cancelCompletionTimer(event.projectName);
863
- debugLog('User prompt submitted - activity detected');
864
- }
865
-
866
- function handleTeammateIdle(event) {
867
- // Informational only — no user input required. Skip notification.
868
- debugLog(`Teammate idle (not notifying): ${event.data.teammate}`);
869
- }
870
-
871
- function handleTaskCompleted(event) {
872
- // Informational only — task completion does not require a decision. Skip.
873
- debugLog(`Task completed (not notifying): ${event.data.message}`);
741
+ function handleUserPrompt(_event) {
742
+ debugLog('User prompt submitted');
874
743
  }
875
744
 
876
745
  // ============================================
@@ -1291,94 +1160,7 @@ function buildQuestionNotification(event, ctx = {}) {
1291
1160
  }
1292
1161
 
1293
1162
  // ============================================
1294
- // SECTION 9: Completion Timer Management
1295
- // ============================================
1296
-
1297
- function scheduleCompletionTimer(projectName) {
1298
- if (IS_CLAUDE_CODE) {
1299
- // Completion timer cannot work in Claude Code (each hook is a separate process)
1300
- return;
1301
- }
1302
- debugLog(`Scheduling completion check for ${projectName}`);
1303
- cancelCompletionTimer(projectName);
1304
-
1305
- const timer = setTimeout(() => {
1306
- debugLog(`Completion timer fired for ${projectName}`);
1307
- checkCompletion(projectName, RUNTIME);
1308
- }, COMPLETION_TIMEOUT);
1309
-
1310
- completionTimers.set(projectName, timer);
1311
- debugLog(`Completion timer scheduled (45s)`);
1312
- }
1313
-
1314
- function cancelCompletionTimer(projectName) {
1315
- const existingTimer = completionTimers.get(projectName);
1316
- if (existingTimer) {
1317
- clearTimeout(existingTimer);
1318
- completionTimers.delete(projectName);
1319
- debugLog(`Completion timer cancelled for ${projectName}`);
1320
- }
1321
- }
1322
-
1323
- function checkCompletion(projectName, source) {
1324
- if (IS_CLAUDE_CODE) {
1325
- return;
1326
- }
1327
- const state = getSessionState();
1328
- const now = Date.now();
1329
-
1330
- debugLog(`Checking completion status for ${projectName}`);
1331
- debugLog(` pendingCompletion: ${state.pendingCompletion}`);
1332
- debugLog(` lastStopTime: ${state.lastStopTime}`);
1333
- debugLog(` lastActivityTime: ${state.lastActivityTime}`);
1334
-
1335
- if (
1336
- state.pendingCompletion &&
1337
- state.lastStopTime &&
1338
- state.lastActivityTime <= state.lastStopTime &&
1339
- now - state.lastStopTime >= COMPLETION_TIMEOUT
1340
- ) {
1341
- debugLog(`Conditions met - sending completion notification`);
1342
-
1343
- const message = createCompletionMessage(state, projectName);
1344
-
1345
- sendNotification(
1346
- `${projectName} · Session complete`,
1347
- message,
1348
- 'completion',
1349
- source,
1350
- 'Agent finished'
1351
- );
1352
-
1353
- state.pendingCompletion = false;
1354
- saveSessionState(state);
1355
- } else {
1356
- debugLog(`No completion notification needed`);
1357
- }
1358
- }
1359
-
1360
- function createCompletionMessage(state, _projectName) {
1361
- const timestamp = new Date().toLocaleTimeString();
1362
- const lines = [`Finished at ${timestamp}.`];
1363
-
1364
- const totalTools = state.totalToolUses || 0;
1365
- if (totalTools > 0) {
1366
- lines.push(`${totalTools} tools used.`);
1367
-
1368
- if (state.recentTools && state.recentTools.length > 0) {
1369
- lines.push(`Recent: ${state.recentTools.slice(0, 3).join(', ')}`);
1370
- }
1371
-
1372
- if (state.recentFiles && state.recentFiles.length > 0) {
1373
- lines.push(`Files: ${state.recentFiles.slice(0, 3).join(', ')}`);
1374
- }
1375
- }
1376
-
1377
- return lines.join('\n');
1378
- }
1379
-
1380
- // ============================================
1381
- // SECTION 10: Notification Service
1163
+ // SECTION 9: Notification Service
1382
1164
  // ============================================
1383
1165
 
1384
1166
  /**