@pushary/agent-hooks 0.87.2 → 0.87.3

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 (63) hide show
  1. package/data/cursor-plugin/hooks/hooks.json +7 -0
  2. package/data/cursor-plugin/scripts/pushary-gate.mjs +85 -28
  3. package/data/cursor-plugin/scripts/pushary-gate.test.mjs +42 -1
  4. package/dist/bin/pushary-bell-hook.js +4 -4
  5. package/dist/bin/pushary-bell.js +7 -6
  6. package/dist/bin/pushary-claude.js +14 -11
  7. package/dist/bin/pushary-clean.js +36 -20
  8. package/dist/bin/pushary-codex-bridge.js +6 -5
  9. package/dist/bin/pushary-codex-hook.js +129 -52
  10. package/dist/bin/pushary-codex.js +4 -3
  11. package/dist/bin/pushary-connect.js +6 -6
  12. package/dist/bin/pushary-daemon.js +5 -4
  13. package/dist/bin/pushary-disconnect.js +65 -8
  14. package/dist/bin/pushary-doctor.js +79 -18
  15. package/dist/bin/pushary-elicitation-hook.js +1 -1
  16. package/dist/bin/pushary-gemini-bridge.js +6 -5
  17. package/dist/bin/pushary-gemini-hook.js +12 -10
  18. package/dist/bin/pushary-hook.js +6 -5
  19. package/dist/bin/pushary-login.js +4 -4
  20. package/dist/bin/pushary-logout.js +5 -4
  21. package/dist/bin/pushary-mode.js +3 -3
  22. package/dist/bin/pushary-notification-hook.js +4 -3
  23. package/dist/bin/pushary-opencode-hook.d.ts +1 -0
  24. package/dist/bin/pushary-opencode-hook.js +329 -0
  25. package/dist/bin/pushary-permission-denied-hook.js +6 -5
  26. package/dist/bin/pushary-permission-hook.js +6 -5
  27. package/dist/bin/pushary-post-hook.js +4 -3
  28. package/dist/bin/pushary-prompt-hook.js +4 -3
  29. package/dist/bin/pushary-session-end-hook.js +4 -3
  30. package/dist/bin/pushary-session-start-hook.js +4 -3
  31. package/dist/bin/pushary-setup.js +238 -84
  32. package/dist/bin/pushary-stats.js +2 -2
  33. package/dist/bin/pushary-status.js +5 -5
  34. package/dist/bin/pushary-stop-hook.js +4 -3
  35. package/dist/bin/pushary-stopfailure-hook.js +4 -3
  36. package/dist/bin/pushary-upgrade.js +7 -6
  37. package/dist/bin/pushary-wait.js +3 -3
  38. package/dist/{chunk-5646VKR4.js → chunk-2JYQAW4B.js} +5 -53
  39. package/dist/chunk-7J67NYK4.js +287 -0
  40. package/dist/{chunk-M7RYIZX6.js → chunk-B7ZBHWOW.js} +10 -1
  41. package/dist/{chunk-7YJS2VTG.js → chunk-DMW54VWK.js} +12 -1
  42. package/dist/{chunk-LT2VLPUK.js → chunk-DPUOW6NS.js} +18 -2
  43. package/dist/{chunk-3LKYBFWA.js → chunk-EJL3PJU7.js} +1 -1
  44. package/dist/chunk-GIRT7677.js +11 -0
  45. package/dist/{chunk-HAUTLCMA.js → chunk-ICERLAE2.js} +1 -1
  46. package/dist/{chunk-ZZE6FN7T.js → chunk-K42RXJPG.js} +52 -1
  47. package/dist/{chunk-Y3UTTFTZ.js → chunk-KBS53WOE.js} +1 -1
  48. package/dist/{chunk-SJVLFIYP.js → chunk-KCAFCGGY.js} +1 -1
  49. package/dist/{chunk-A4I5JGCW.js → chunk-KFAH6KRE.js} +1 -1
  50. package/dist/{chunk-QBWYNVKY.js → chunk-LGVHYFIB.js} +1 -1
  51. package/dist/{chunk-HJ44HIUW.js → chunk-OMA2OZRE.js} +11 -9
  52. package/dist/{chunk-ECEUMWBH.js → chunk-QLMX5LLV.js} +1 -1
  53. package/dist/{chunk-XW5CHAQX.js → chunk-TAYHEJFF.js} +2 -2
  54. package/dist/{chunk-JAICP7BA.js → chunk-TD3M232T.js} +1 -1
  55. package/dist/{chunk-WLLBFDVY.js → chunk-TV3UFGT7.js} +1 -1
  56. package/dist/{chunk-7MBDFNUC.js → chunk-VIHRP25S.js} +1 -1
  57. package/dist/{chunk-B3V2H6SA.js → chunk-VL5ZNK6V.js} +43 -12
  58. package/dist/{chunk-V2XPF77V.js → chunk-VOE4SYPR.js} +42 -279
  59. package/dist/{chunk-OT4YD54Q.js → chunk-YX6ZKCC5.js} +1 -1
  60. package/dist/{chunk-2T3GX7WG.js → chunk-YYTLTEGU.js} +1 -1
  61. package/dist/chunk-ZGC3W23N.js +371 -0
  62. package/dist/src/index.js +6 -5
  63. package/package.json +2 -1
@@ -9,6 +9,19 @@ import {
9
9
  sendNotification,
10
10
  waitForAnswer
11
11
  } from "./chunk-J3YDT4HM.js";
12
+ import {
13
+ deriveReceiptMeta,
14
+ deriveToolTarget,
15
+ describeToolCall,
16
+ isToolResultError,
17
+ parseApplyPatchFiles,
18
+ parseApplyPatchOps,
19
+ sessionEndAction,
20
+ sessionStartAction,
21
+ summarizeStop,
22
+ taskTitleFrom,
23
+ toolResultErrorText
24
+ } from "./chunk-7J67NYK4.js";
12
25
  import {
13
26
  getMachineId
14
27
  } from "./chunk-RN3NOEJF.js";
@@ -17,26 +30,20 @@ import {
17
30
  } from "./chunk-BSZYIAZL.js";
18
31
  import {
19
32
  reportedInstallSource
20
- } from "./chunk-Y3UTTFTZ.js";
33
+ } from "./chunk-KBS53WOE.js";
21
34
  import {
22
35
  getApiKey,
23
36
  getBaseUrl
24
37
  } from "./chunk-2UMNXADU.js";
25
38
  import {
26
- ACTION_BODY_MAX,
27
- AGENT_LABELS_BY_TYPE,
28
- DECISION_LINE_MAX,
29
- FILE_TARGET_TOOLS,
30
39
  gateOutputFor,
31
40
  isAutoApprove,
32
41
  localRepoKey,
33
42
  modeStateFromResponse,
34
43
  normalizeRepoRemote,
35
- redactSecrets,
36
- redactSecretsDeep,
37
44
  resolveAutoResolveOrigin,
38
45
  resolvePolicy
39
- } from "./chunk-7YJS2VTG.js";
46
+ } from "./chunk-DMW54VWK.js";
40
47
 
41
48
  // src/policy.ts
42
49
  import { createHash } from "crypto";
@@ -45,9 +52,10 @@ import { join } from "path";
45
52
  import { tmpdir } from "os";
46
53
  var CACHE_TTL_MS = 60 * 1e3;
47
54
  var STALE_CACHE_MAX_MS = 12 * 60 * 60 * 1e3;
55
+ var REPO_AWARE_AGENTS = ["claude_code", "codex", "gemini_cli", "opencode"];
48
56
  var policyRequestFor = (agentType) => ({
49
57
  agent: agentType,
50
- repoAware: ["claude_code", "codex", "gemini_cli"].includes(agentType)
58
+ repoAware: REPO_AWARE_AGENTS.includes(agentType)
51
59
  });
52
60
  var policyCacheFile = (apiKey, agent, repoAware = false) => {
53
61
  const parts = [apiKey, agent, repoAware ? "repoAware" : void 0].filter(Boolean);
@@ -178,254 +186,13 @@ var fetchModeState = async (apiKey, sessionId, reuseWithinMs = 0) => {
178
186
  };
179
187
  var fetchModeOverride = async (apiKey) => (await fetchModeState(apiKey)).mode;
180
188
 
181
- // ../hook-mapping/src/describe.ts
182
- import { isAbsolute, relative, resolve } from "path";
183
- var hookPrefixes = {
184
- Bash: (input) => `bash: ${input.command ?? "(no command)"}`,
185
- PowerShell: (input) => `powershell: ${input.command ?? "(no command)"}`,
186
- Monitor: (input) => `monitor: ${input.command ?? "(no command)"}`,
187
- Write: (input) => `write file: ${input.file_path ?? "(unknown path)"}`,
188
- Edit: (input) => `edit file: ${input.file_path ?? "(unknown path)"}`,
189
- MultiEdit: (input) => `edit file: ${input.file_path ?? "(unknown path)"}`,
190
- Read: (input) => `read file: ${input.file_path ?? "(unknown path)"}`,
191
- // Without an entry here the fallback stringifies the whole tool input, and for
192
- // ExitPlanMode that input IS the plan: the action line became a truncated dump of
193
- // the plan markdown. The plan belongs in the body, not the one-line summary.
194
- ExitPlanMode: () => "finished planning and wants to start coding"
195
- };
196
- var describeTodoProgress = (todos) => {
197
- if (!Array.isArray(todos)) return "updated the plan";
198
- const items = todos.filter((t) => !!t && typeof t === "object");
199
- const total = items.length;
200
- if (total === 0) return "updated the plan";
201
- const done = items.filter((t) => t.status === "completed").length;
202
- const current = items.find((t) => t.status === "in_progress");
203
- const label = current ? [current.activeForm, current.content].find((v) => typeof v === "string" && v.trim().length > 0) : void 0;
204
- if (done >= total) return `finished all ${total} tasks`;
205
- if (label) return `${label.trim()} (${done}/${total} done)`;
206
- return `${done}/${total} tasks done`;
207
- };
208
- var eventPrefixes = {
209
- Bash: (input) => `ran: ${String(input.command ?? "")}`,
210
- PowerShell: (input) => `ran: ${String(input.command ?? "")}`,
211
- Monitor: (input) => `ran: ${String(input.command ?? "")}`,
212
- Write: (input) => `wrote: ${input.file_path ?? "unknown"}`,
213
- Edit: (input) => `edited: ${input.file_path ?? "unknown"}`,
214
- MultiEdit: (input) => `edited: ${input.file_path ?? "unknown"}`,
215
- Read: (input) => `read: ${input.file_path ?? "unknown"}`,
216
- TodoWrite: (input) => describeTodoProgress(input.todos)
217
- };
218
- var EVENT_ACTION_MAX = 120;
219
- var HOOK_FALLBACK_MAX = 200;
220
- var describeToolCall = (toolName, toolInput, format = "hook") => {
221
- const prefixes = format === "hook" ? hookPrefixes : eventPrefixes;
222
- const builder = prefixes[toolName];
223
- const raw = builder ? builder(toolInput) : format === "hook" ? `${toolName}: ${JSON.stringify(toolInput)}` : `${toolName}: done`;
224
- const redacted = redactSecrets(raw);
225
- if (format === "event") return redacted.slice(0, EVENT_ACTION_MAX);
226
- return builder ? redacted : redacted.slice(0, HOOK_FALLBACK_MAX);
227
- };
228
- var TOOL_TARGET_MAX_LENGTH = 80;
229
- var deriveCommandHead = (command) => {
230
- if (typeof command !== "string") return void 0;
231
- const head = command.trim().split(/\s+/).slice(0, 2).join(" ");
232
- return head ? redactSecrets(head).slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
233
- };
234
- var deriveToolTarget = (toolName, toolInput) => {
235
- if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor") {
236
- return deriveCommandHead(toolInput.command);
237
- }
238
- if (FILE_TARGET_TOOLS.has(toolName)) {
239
- const filePath = toolInput.file_path;
240
- if (typeof filePath !== "string") return void 0;
241
- const separator = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
242
- const base = filePath.slice(separator + 1);
243
- const dot = base.lastIndexOf(".");
244
- if (dot <= 0) return void 0;
245
- return base.slice(dot).slice(0, TOOL_TARGET_MAX_LENGTH);
246
- }
247
- return void 0;
248
- };
249
- var SCRIPT_RUNNERS = /* @__PURE__ */ new Set(["npm", "pnpm", "yarn", "bun", "npx", "deno", "rake", "make", "just", "task", "turbo"]);
250
- var RUN_SUBCOMMANDS = /* @__PURE__ */ new Set(["run", "run-script", "exec", "task"]);
251
- var deriveReceiptCommandHead = (command) => {
252
- if (typeof command !== "string") return void 0;
253
- const tokens = command.trim().split(/\s+/);
254
- const [first, second] = tokens;
255
- const keep = first && second && SCRIPT_RUNNERS.has(first.toLowerCase()) && RUN_SUBCOMMANDS.has(second.toLowerCase()) ? 3 : 2;
256
- const head = tokens.slice(0, keep).join(" ");
257
- return head ? redactSecrets(head).slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
258
- };
259
- var RECEIPT_TARGET_MAX_LENGTH = 256;
260
- var parseApplyPatchOps = (command) => {
261
- if (typeof command !== "string") return [];
262
- const ops = [];
263
- for (const line of command.split("\n")) {
264
- const file = line.match(/^\*\*\*\s+(Add|Update|Delete) File:\s+(.+?)\s*$/);
265
- if (file) {
266
- ops.push({ op: file[1].toLowerCase(), path: file[2] });
267
- continue;
268
- }
269
- const move = line.match(/^\*\*\*\s+Move to:\s+(.+?)\s*$/);
270
- if (move) ops.push({ op: "move", path: move[1] });
271
- }
272
- return ops;
273
- };
274
- var parseApplyPatchFiles = (command) => [...new Set(parseApplyPatchOps(command).map((entry) => entry.path))];
275
- var EXIT_CODE_FAILURE = /^Error: Exit code \d+/;
276
- var isToolResultError = (toolResult) => {
277
- try {
278
- if (typeof toolResult === "string") return EXIT_CODE_FAILURE.test(toolResult);
279
- if (!toolResult || typeof toolResult !== "object") return false;
280
- return "error" in toolResult || "is_error" in toolResult;
281
- } catch {
282
- return false;
283
- }
284
- };
285
- var toolResultErrorText = (toolResult) => {
286
- try {
287
- const raw = typeof toolResult === "string" ? toolResult : toolResult && typeof toolResult === "object" ? String(
288
- toolResult.error ?? toolResult.stderr ?? ""
289
- ) : "";
290
- return redactSecrets(raw);
291
- } catch {
292
- return "";
293
- }
294
- };
295
- var relativizeReceiptPath = (filePath, cwd) => {
296
- if (!cwd || !isAbsolute(filePath)) return filePath;
297
- return relative(cwd, filePath);
298
- };
299
- var deriveReceiptMeta = (toolName, toolInput, toolResult, cwd) => {
300
- try {
301
- const ok = !isToolResultError(toolResult);
302
- if (toolName === "apply_patch") {
303
- const files = parseApplyPatchFiles(toolInput.command);
304
- const target = files.length === 1 ? files[0] : toolInput.command;
305
- if (typeof target !== "string" || !target) return void 0;
306
- return { kind: "edit", target: redactSecrets(target).slice(0, RECEIPT_TARGET_MAX_LENGTH), ok };
307
- }
308
- const canonicalTool = {
309
- run_shell_command: "Bash",
310
- write_file: "Write",
311
- replace: "Edit"
312
- }[toolName] ?? toolName;
313
- const canonicalInput = canonicalTool === toolName ? toolInput : {
314
- ...toolInput,
315
- file_path: toolInput.file_path ?? toolInput.absolute_path ?? toolInput.path
316
- };
317
- if (FILE_TARGET_TOOLS.has(canonicalTool)) {
318
- const filePath = canonicalInput.file_path;
319
- if (typeof filePath !== "string" || !filePath) return void 0;
320
- return {
321
- kind: canonicalTool === "Write" ? "write" : "edit",
322
- // A path is an unlikely place for a credential but not an impossible one
323
- // (a token in a temp directory name), and this field is persisted.
324
- target: redactSecrets(relativizeReceiptPath(filePath, cwd)).slice(0, RECEIPT_TARGET_MAX_LENGTH),
325
- ok
326
- };
327
- }
328
- if (canonicalTool === "Bash" || canonicalTool === "PowerShell" || canonicalTool === "Monitor") {
329
- const head = deriveReceiptCommandHead(canonicalInput.command);
330
- if (!head) return void 0;
331
- return {
332
- kind: head === "git commit" ? "commit" : "bash",
333
- target: head,
334
- ok
335
- };
336
- }
337
- return void 0;
338
- } catch {
339
- return void 0;
340
- }
341
- };
342
- var scopePathFor = (toolName, toolInput, cwd) => {
343
- const meta = deriveReceiptMeta(toolName, toolInput, void 0, cwd);
344
- if (!meta) return void 0;
345
- return meta.kind === "edit" || meta.kind === "write" ? meta.target : void 0;
346
- };
347
- var firstString = (...values) => values.find((v) => typeof v === "string" && v.length > 0);
348
- var ACTION_BODY_TRUNCATION_MARKER = "\n\u2026 [truncated]";
349
- var capActionBody = (text) => text.length <= ACTION_BODY_MAX ? text : `${text.slice(0, ACTION_BODY_MAX - ACTION_BODY_TRUNCATION_MARKER.length)}${ACTION_BODY_TRUNCATION_MARKER}`;
350
- var rawActionBody = (toolName, toolInput) => {
351
- if (toolName === "Edit" || toolName === "replace") {
352
- const before = firstString(toolInput.old_string);
353
- const after = firstString(toolInput.new_string);
354
- if (before === void 0 && after === void 0) return void 0;
355
- return `- ${before ?? ""}
356
- + ${after ?? ""}`;
357
- }
358
- if (toolName === "Write" || toolName === "write_file") return firstString(toolInput.content);
359
- if (toolName === "ExitPlanMode") return firstString(toolInput.plan);
360
- if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor" || toolName === "run_shell_command" || toolName === "shell" || toolName === "apply_patch") {
361
- return firstString(toolInput.command);
362
- }
363
- return void 0;
364
- };
365
- var deriveActionBody = (toolName, toolInput) => {
366
- try {
367
- const raw = rawActionBody(toolName, toolInput);
368
- if (!raw) return void 0;
369
- return capActionBody(redactSecretsDeep(raw));
370
- } catch {
371
- return void 0;
372
- }
373
- };
374
- var deriveAction = (toolName, toolInput) => describeToolCall(toolName, toolInput, "hook").slice(0, DECISION_LINE_MAX);
375
- var BLOCKER_BY_MODE = {
376
- push_only: "Approval required before this runs",
377
- push_first: "Paused for your approval before continuing",
378
- escalate: "Escalated to you after the approval timeout"
379
- };
380
- var deriveBlocker = (mode, reason) => {
381
- const text = reason?.replace(/\s+/g, " ").trim() || BLOCKER_BY_MODE[mode] || "Waiting for your approval";
382
- return text.slice(0, DECISION_LINE_MAX);
383
- };
384
-
385
- // ../hook-mapping/src/map.ts
386
- import { basename } from "path";
387
- var AGENT_IDENTITIES = {
388
- claude: { type: "claude_code", label: AGENT_LABELS_BY_TYPE.claude_code },
389
- codex: { type: "codex", label: AGENT_LABELS_BY_TYPE.codex },
390
- gemini: { type: "gemini_cli", label: AGENT_LABELS_BY_TYPE.gemini_cli },
391
- cursor: { type: "cursor", label: AGENT_LABELS_BY_TYPE.cursor },
392
- vscode: { type: "vscode", label: AGENT_LABELS_BY_TYPE.vscode }
393
- };
394
- var TASK_TITLE_MAX_LENGTH = 120;
395
- var STOP_SUMMARY_MAX_LENGTH = 200;
396
- var SESSION_END_ACTIONS = {
397
- clear: "Session cleared",
398
- logout: "Logged out",
399
- resume: "Session suspended",
400
- prompt_input_exit: "Session ended",
401
- bypass_permissions_disabled: "Session ended",
402
- other: "Session ended"
403
- };
404
- var countArray = (value) => Array.isArray(value) ? value.length : 0;
405
- var summarizeFinalMessage = (message) => {
406
- if (typeof message !== "string") return "Session ended";
407
- const collapsed = message.replace(/\s+/g, " ").trim();
408
- if (!collapsed) return "Session ended";
409
- return collapsed.slice(0, STOP_SUMMARY_MAX_LENGTH);
410
- };
411
- var summarizeStop = (input) => {
412
- const running = countArray(input.background_tasks);
413
- if (running > 0) return `Paused with ${running} background task${running === 1 ? "" : "s"} still running`;
414
- const crons = countArray(input.session_crons);
415
- if (crons > 0) return `Idle until a scheduled task wakes it (${crons} pending)`;
416
- return summarizeFinalMessage(input.last_assistant_message);
417
- };
418
- var sessionStartAction = (source) => source === "resume" ? "Session resumed" : "Session started";
419
- var sessionEndAction = (reason) => typeof reason === "string" && SESSION_END_ACTIONS[reason] || "Session ended";
420
- var taskTitleFrom = (prompt) => typeof prompt === "string" ? prompt.replace(/\s+/g, " ").trim().slice(0, TASK_TITLE_MAX_LENGTH) || void 0 : void 0;
421
-
422
189
  // src/repo.ts
423
190
  import { existsSync as existsSync2, readFileSync as readFileSync2, statSync } from "fs";
424
- import { basename as basename2, dirname, isAbsolute as isAbsolute2, join as join2, resolve as resolve2 } from "path";
191
+ import { basename, dirname, isAbsolute, join as join2, resolve } from "path";
425
192
  var MAX_PARENT_WALK = 64;
426
193
  var GIT_FILE_PREFIX = "gitdir:";
427
194
  var findGitDir = (startDir) => {
428
- let current = resolve2(startDir);
195
+ let current = resolve(startDir);
429
196
  for (let depth = 0; depth < MAX_PARENT_WALK; depth += 1) {
430
197
  const candidate = join2(current, ".git");
431
198
  try {
@@ -434,7 +201,7 @@ var findGitDir = (startDir) => {
434
201
  const pointer = readFileSync2(candidate, "utf-8").trim();
435
202
  if (pointer.startsWith(GIT_FILE_PREFIX)) {
436
203
  const target = pointer.slice(GIT_FILE_PREFIX.length).trim();
437
- return isAbsolute2(target) ? target : resolve2(current, target);
204
+ return isAbsolute(target) ? target : resolve(current, target);
438
205
  }
439
206
  }
440
207
  } catch {
@@ -480,9 +247,9 @@ var deriveRepoKey = (cwd) => {
480
247
  const normalized = remote ? normalizeRepoRemote(remote) : void 0;
481
248
  if (normalized) return normalized;
482
249
  const root = gitDir.endsWith(".git") ? dirname(gitDir) : dir;
483
- return localRepoKey(basename2(root));
250
+ return localRepoKey(basename(root));
484
251
  }
485
- return localRepoKey(basename2(resolve2(dir)));
252
+ return localRepoKey(basename(resolve(dir)));
486
253
  } catch {
487
254
  return void 0;
488
255
  }
@@ -675,7 +442,7 @@ var readNewUsage = (transcriptPath, sessionId) => {
675
442
  };
676
443
 
677
444
  // src/codex-adapter.ts
678
- import { resolve as resolve3 } from "path";
445
+ import { resolve as resolve2 } from "path";
679
446
  var CODEX_AGENT = { type: "codex", label: "Codex" };
680
447
  var codexAllow = () => ({ kind: "allow" });
681
448
  var codexDeny = (reason) => ({ kind: "deny", reason });
@@ -704,7 +471,7 @@ var toPolicyLookup = (toolName, toolInput, cwd) => {
704
471
  const command = toolInput.command;
705
472
  const files = parseApplyPatchFiles(command);
706
473
  if (files.length === 1) {
707
- return { tool: "Edit", input: { file_path: cwd ? resolve3(cwd, files[0]) : files[0] } };
474
+ return { tool: "Edit", input: { file_path: cwd ? resolve2(cwd, files[0]) : files[0] } };
708
475
  }
709
476
  return { tool: "Edit", input: typeof command === "string" ? { file_path: command } : {} };
710
477
  };
@@ -720,7 +487,7 @@ var toPolicyLookups = (toolName, toolInput, cwd) => {
720
487
  }
721
488
  return {
722
489
  tool: "Edit",
723
- inputs: files.map((file) => ({ file_path: cwd ? resolve3(cwd, file) : file }))
490
+ inputs: files.map((file) => ({ file_path: cwd ? resolve2(cwd, file) : file }))
724
491
  };
725
492
  };
726
493
  var permissionTimeoutDecision = (timeoutAction) => {
@@ -750,7 +517,7 @@ var throttlePass = (key, windowMs) => {
750
517
  };
751
518
 
752
519
  // src/events.ts
753
- import { basename as basename3, join as join5 } from "path";
520
+ import { basename as basename2, join as join5 } from "path";
754
521
  import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
755
522
  import { tmpdir as tmpdir4 } from "os";
756
523
  var INTENT_DIR = join5(tmpdir4(), "pushary-intent");
@@ -939,7 +706,7 @@ var reportEvent = async (event, options = {}) => {
939
706
  var NON_GATED_MIRROR_TOOLS = /* @__PURE__ */ new Set(["TodoWrite"]);
940
707
  var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
941
708
  try {
942
- const projectName = basename3(input.cwd ?? process.cwd());
709
+ const projectName = basename2(input.cwd ?? process.cwd());
943
710
  const action = describeToolCall(input.tool_name, input.tool_input, "event");
944
711
  const lookup = toPolicyLookup(input.tool_name, input.tool_input);
945
712
  const toolResult = input.tool_response ?? input.tool_result;
@@ -993,7 +760,7 @@ var handlePostToolUse = async (input, agent = CLAUDE_CODE_AGENT) => {
993
760
  };
994
761
  var handleUserPrompt = async (input, agent = CLAUDE_CODE_AGENT) => {
995
762
  try {
996
- const projectName = basename3(input.cwd ?? process.cwd());
763
+ const projectName = basename2(input.cwd ?? process.cwd());
997
764
  const sessionKey = input.session_id || DEFAULT_SESSION;
998
765
  const titlesEnabled = process.env.PUSHARY_TASK_TITLES !== "off";
999
766
  const taskTitle = titlesEnabled ? taskTitleFrom(input.prompt) : void 0;
@@ -1023,7 +790,7 @@ var handleUserPrompt = async (input, agent = CLAUDE_CODE_AGENT) => {
1023
790
  };
1024
791
  var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
1025
792
  try {
1026
- const projectName = basename3(input.cwd ?? process.cwd());
793
+ const projectName = basename2(input.cwd ?? process.cwd());
1027
794
  const sessionKey = input.session_id || DEFAULT_SESSION;
1028
795
  const late = await reconcilePendingQuestions(sessionKey);
1029
796
  const tasks = [
@@ -1059,7 +826,7 @@ var handleStop = async (input, agent = CLAUDE_CODE_AGENT) => {
1059
826
  };
1060
827
  var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
1061
828
  try {
1062
- const projectName = basename3(input.cwd ?? process.cwd());
829
+ const projectName = basename2(input.cwd ?? process.cwd());
1063
830
  const action = sessionStartAction(input.source);
1064
831
  await reportEvent({
1065
832
  event: "session_start",
@@ -1071,16 +838,18 @@ var handleSessionStart = async (input, agent = CLAUDE_CODE_AGENT) => {
1071
838
  } catch {
1072
839
  }
1073
840
  };
1074
- var handleSessionEnd = async (input, agent = CLAUDE_CODE_AGENT) => {
841
+ var handleSessionEnd = async (input, agent = CLAUDE_CODE_AGENT, options = {}) => {
1075
842
  try {
1076
- const projectName = basename3(input.cwd ?? process.cwd());
843
+ const projectName = basename2(input.cwd ?? process.cwd());
1077
844
  const action = sessionEndAction(input.reason);
1078
845
  const sessionKey = input.session_id || DEFAULT_SESSION;
1079
- const late = await reconcilePendingQuestions(sessionKey);
1080
- if (late.length > 0) {
1081
- await notifyLateAnswers(getApiKey(), late, `${agent.label} - ${projectName}`, input.session_id).catch(() => {
1082
- });
1083
- for (const l of late) removePendingQuestion(sessionKey, l.correlationId);
846
+ if (options.reconcile ?? true) {
847
+ const late = await reconcilePendingQuestions(sessionKey);
848
+ if (late.length > 0) {
849
+ await notifyLateAnswers(getApiKey(), late, `${agent.label} - ${projectName}`, input.session_id).catch(() => {
850
+ });
851
+ for (const l of late) removePendingQuestion(sessionKey, l.correlationId);
852
+ }
1084
853
  }
1085
854
  if (!isDefaultSession(sessionKey)) removePendingSession(sessionKey);
1086
855
  await reportEvent({
@@ -1089,7 +858,7 @@ var handleSessionEnd = async (input, agent = CLAUDE_CODE_AGENT) => {
1089
858
  agentName: `${agent.label} - ${projectName}`,
1090
859
  action,
1091
860
  sessionId: input.session_id
1092
- }, { maxAttempts: 2, timeoutMs: 3e3 });
861
+ }, { maxAttempts: options.reportAttempts ?? 2, timeoutMs: options.reportTimeoutMs ?? 3e3 });
1093
862
  } catch {
1094
863
  }
1095
864
  };
@@ -1097,7 +866,7 @@ var NOTIFICATION_PUSH_TYPES = /* @__PURE__ */ new Set(["idle_prompt", "agent_nee
1097
866
  var NOTIFICATION_THROTTLE_MS = 60 * 1e3;
1098
867
  var handleNotification = async (input, agent = CLAUDE_CODE_AGENT) => {
1099
868
  try {
1100
- const projectName = basename3(input.cwd ?? process.cwd());
869
+ const projectName = basename2(input.cwd ?? process.cwd());
1101
870
  const notifType = input.notification_type ?? input.type ?? "";
1102
871
  const sessionKey = input.session_id || DEFAULT_SESSION;
1103
872
  if (NOTIFICATION_PUSH_TYPES.has(notifType)) {
@@ -1170,7 +939,7 @@ var handleStopFailure = async (input, agent = CLAUDE_CODE_AGENT) => {
1170
939
  } catch {
1171
940
  return;
1172
941
  }
1173
- const projectName = basename3(input.cwd ?? process.cwd());
942
+ const projectName = basename2(input.cwd ?? process.cwd());
1174
943
  const mode = await fetchModeState(apiKey, input.session_id, MODE_REUSE_MS).catch(() => null);
1175
944
  if (mode?.kill || mode?.mode === "terminal_only") return;
1176
945
  const reason = describeStopFailure(input.error);
@@ -1191,12 +960,6 @@ export {
1191
960
  getPolicy,
1192
961
  fetchModeState,
1193
962
  fetchModeOverride,
1194
- describeToolCall,
1195
- deriveToolTarget,
1196
- scopePathFor,
1197
- deriveActionBody,
1198
- deriveAction,
1199
- deriveBlocker,
1200
963
  repoKeyFor,
1201
964
  throttlePass,
1202
965
  readLastUserPrompt,
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6MTNS63X.js";
10
10
  import {
11
11
  resolveInstallSourceFor
12
- } from "./chunk-Y3UTTFTZ.js";
12
+ } from "./chunk-KBS53WOE.js";
13
13
  import {
14
14
  configFilePath
15
15
  } from "./chunk-2UMNXADU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readConfigFileKey
3
- } from "./chunk-OT4YD54Q.js";
3
+ } from "./chunk-YX6ZKCC5.js";
4
4
 
5
5
  // src/bell/fleet.ts
6
6
  import { closeSync, constants, futimesSync, lstatSync, mkdirSync, openSync, readdirSync, unlinkSync } from "fs";