@pushary/agent-hooks 0.86.0 → 0.87.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 (58) hide show
  1. package/dist/bin/pushary-bell-hook.js +4 -4
  2. package/dist/bin/pushary-bell.js +6 -6
  3. package/dist/bin/pushary-claude.js +12 -10
  4. package/dist/bin/pushary-clean.js +6 -6
  5. package/dist/bin/pushary-codex-bridge.js +5 -5
  6. package/dist/bin/pushary-codex-hook.js +13 -29
  7. package/dist/bin/pushary-codex.js +6 -4
  8. package/dist/bin/pushary-connect.js +6 -6
  9. package/dist/bin/pushary-daemon.js +4 -4
  10. package/dist/bin/pushary-disconnect.js +22 -8
  11. package/dist/bin/pushary-doctor.js +21 -15
  12. package/dist/bin/pushary-elicitation-hook.d.ts +1 -0
  13. package/dist/bin/pushary-elicitation-hook.js +210 -0
  14. package/dist/bin/pushary-gemini-bridge.js +5 -5
  15. package/dist/bin/pushary-gemini-hook.js +10 -8
  16. package/dist/bin/pushary-hook.js +6 -5
  17. package/dist/bin/pushary-login.js +4 -4
  18. package/dist/bin/pushary-logout.js +4 -4
  19. package/dist/bin/pushary-mode.js +3 -3
  20. package/dist/bin/pushary-notification-hook.js +4 -3
  21. package/dist/bin/pushary-permission-denied-hook.js +6 -5
  22. package/dist/bin/pushary-permission-hook.js +6 -5
  23. package/dist/bin/pushary-post-hook.js +4 -3
  24. package/dist/bin/pushary-prompt-hook.js +4 -3
  25. package/dist/bin/pushary-session-end-hook.js +4 -3
  26. package/dist/bin/pushary-session-start-hook.js +4 -3
  27. package/dist/bin/pushary-setup.js +19 -15
  28. package/dist/bin/pushary-stats.js +2 -2
  29. package/dist/bin/pushary-status.js +5 -5
  30. package/dist/bin/pushary-stop-hook.js +4 -3
  31. package/dist/bin/pushary-stopfailure-hook.js +4 -3
  32. package/dist/bin/pushary-upgrade.js +8 -7
  33. package/dist/bin/pushary-wait.js +3 -3
  34. package/dist/{chunk-5EUZYWID.js → chunk-2T3GX7WG.js} +1 -1
  35. package/dist/{chunk-GK4CED6Z.js → chunk-5646VKR4.js} +7 -3
  36. package/dist/{chunk-MNQI6ZZU.js → chunk-7MBDFNUC.js} +1 -1
  37. package/dist/{chunk-CY4TZK5O.js → chunk-7YJS2VTG.js} +31 -4
  38. package/dist/{chunk-PZR4XMFU.js → chunk-A3PFIWWN.js} +1 -1
  39. package/dist/{chunk-2TZCZ7CL.js → chunk-A4I5JGCW.js} +1 -1
  40. package/dist/{chunk-VPJAAGD4.js → chunk-B3V2H6SA.js} +37 -17
  41. package/dist/{chunk-XPAGN3SC.js → chunk-ECEUMWBH.js} +1 -1
  42. package/dist/{chunk-2255DZ74.js → chunk-HAUTLCMA.js} +1 -1
  43. package/dist/{chunk-S3UD7O35.js → chunk-HJ44HIUW.js} +12 -28
  44. package/dist/{chunk-QW27ZFA4.js → chunk-IWL5LWIE.js} +1 -1
  45. package/dist/chunk-J3YDT4HM.js +128 -0
  46. package/dist/{chunk-N52CIK47.js → chunk-JAICP7BA.js} +1 -1
  47. package/dist/{chunk-HSGEEBBL.js → chunk-M7RYIZX6.js} +3 -3
  48. package/dist/{chunk-7G5VO76N.js → chunk-OT4YD54Q.js} +1 -1
  49. package/dist/{chunk-VZNDR3Z7.js → chunk-QBWYNVKY.js} +1 -1
  50. package/dist/{chunk-MTKR4YLW.js → chunk-SJVLFIYP.js} +1 -1
  51. package/dist/{chunk-33T5OOKP.js → chunk-V2XPF77V.js} +96 -161
  52. package/dist/{chunk-FOY5FISQ.js → chunk-WLLBFDVY.js} +1 -1
  53. package/dist/{chunk-Q7N3XGWM.js → chunk-XW5CHAQX.js} +2 -2
  54. package/dist/{chunk-7C5CJC3H.js → chunk-Y3UTTFTZ.js} +1 -1
  55. package/dist/{chunk-2C6B6V2U.js → chunk-ZZE6FN7T.js} +1 -1
  56. package/dist/src/index.d.ts +2 -2
  57. package/dist/src/index.js +10 -8
  58. package/package.json +3 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  codexHomeFrom
3
- } from "./chunk-VPJAAGD4.js";
3
+ } from "./chunk-B3V2H6SA.js";
4
4
 
5
5
  // src/vscode-config.ts
6
6
  import { homedir } from "os";
@@ -0,0 +1,128 @@
1
+ import {
2
+ callMcpTool
3
+ } from "./chunk-BSZYIAZL.js";
4
+ import {
5
+ installProxyDispatcher
6
+ } from "./chunk-SAF6HGAA.js";
7
+
8
+ // src/api.ts
9
+ import { randomUUID } from "crypto";
10
+
11
+ // src/validate.ts
12
+ var isPolicyConfig = (data) => {
13
+ if (!data || typeof data !== "object") return false;
14
+ const d = data;
15
+ return Array.isArray(d.policies) && typeof d.defaultTimeoutSeconds === "number" && typeof d.defaultTimeoutAction === "string";
16
+ };
17
+ var isAskUserResponse = (data) => {
18
+ if (!data || typeof data !== "object") return false;
19
+ const d = data;
20
+ return typeof d.correlationId === "string" && typeof d.status === "string";
21
+ };
22
+ var isWaitForAnswerResponse = (data) => {
23
+ if (!data || typeof data !== "object") return false;
24
+ const d = data;
25
+ return typeof d.answered === "boolean";
26
+ };
27
+
28
+ // src/api.ts
29
+ installProxyDispatcher();
30
+ var askUser = async (apiKey, params, timeoutMs = 15e3) => {
31
+ const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
32
+ const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
33
+ if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
34
+ return result;
35
+ };
36
+ var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4) => {
37
+ const result = await callMcpTool(apiKey, "wait_for_answer", {
38
+ correlationId,
39
+ timeoutMs
40
+ }, { timeoutMs: timeoutMs + 1e4 });
41
+ if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
42
+ return result;
43
+ };
44
+ var pollForAnswer = async (apiKey, correlationId, deadlineMs, pollInterval = 2e3) => {
45
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
46
+ while (Date.now() < deadlineMs) {
47
+ const remaining = Math.min(Math.max(deadlineMs - Date.now(), 1e3), 3e4);
48
+ let answer;
49
+ try {
50
+ answer = await waitForAnswer(apiKey, correlationId, remaining);
51
+ } catch {
52
+ if (Date.now() + pollInterval >= deadlineMs) break;
53
+ await sleep(pollInterval);
54
+ continue;
55
+ }
56
+ if (answer.answered) return answer;
57
+ if (Date.now() + pollInterval >= deadlineMs) break;
58
+ await sleep(pollInterval);
59
+ }
60
+ return { answered: false };
61
+ };
62
+ var cancelQuestion = async (apiKey, correlationId) => {
63
+ await callMcpTool(apiKey, "cancel_question", { correlationId });
64
+ };
65
+ var sendNotification = async (apiKey, params, timeoutMs = 15e3) => {
66
+ await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: 3, timeoutMs });
67
+ };
68
+
69
+ // src/pending.ts
70
+ import { join } from "path";
71
+ import { tmpdir } from "os";
72
+ import { existsSync, mkdirSync, writeFileSync, readdirSync, unlinkSync, rmSync, statSync } from "fs";
73
+ var PENDING_DIR = join(tmpdir(), "pushary-pending");
74
+ var DEFAULT_SESSION = "_no_session";
75
+ var GRACE_MS = 10 * 60 * 1e3;
76
+ var sanitize = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
77
+ var dirFor = (sessionId) => join(PENDING_DIR, sanitize(sessionId));
78
+ var isDefaultSession = (sessionId) => sanitize(sessionId) === DEFAULT_SESSION;
79
+ var savePendingQuestion = (sessionId, correlationId) => {
80
+ const dir = dirFor(sessionId);
81
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
82
+ writeFileSync(join(dir, correlationId), "", "utf-8");
83
+ };
84
+ var listPendingQuestions = (sessionId) => {
85
+ const dir = dirFor(sessionId);
86
+ let files;
87
+ try {
88
+ files = readdirSync(dir);
89
+ } catch {
90
+ return [];
91
+ }
92
+ if (!isDefaultSession(sessionId)) return files;
93
+ const cutoff = Date.now() - GRACE_MS;
94
+ return files.filter((name) => {
95
+ try {
96
+ return statSync(join(dir, name)).mtimeMs < cutoff;
97
+ } catch {
98
+ return false;
99
+ }
100
+ });
101
+ };
102
+ var removePendingQuestion = (sessionId, correlationId) => {
103
+ try {
104
+ unlinkSync(join(dirFor(sessionId), correlationId));
105
+ } catch {
106
+ }
107
+ };
108
+ var removePendingSession = (sessionId) => {
109
+ try {
110
+ rmSync(dirFor(sessionId), { recursive: true, force: true });
111
+ } catch {
112
+ }
113
+ };
114
+
115
+ export {
116
+ isPolicyConfig,
117
+ askUser,
118
+ waitForAnswer,
119
+ pollForAnswer,
120
+ cancelQuestion,
121
+ sendNotification,
122
+ DEFAULT_SESSION,
123
+ isDefaultSession,
124
+ savePendingQuestion,
125
+ listPendingQuestions,
126
+ removePendingQuestion,
127
+ removePendingSession
128
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeKeyCheck,
3
3
  keyCheckFromResponse
4
- } from "./chunk-2TZCZ7CL.js";
4
+ } from "./chunk-A4I5JGCW.js";
5
5
  import {
6
6
  createIo
7
7
  } from "./chunk-5RUIFDTP.js";
@@ -7,9 +7,9 @@ var HOOK_SHELL = "/bin/sh -c";
7
7
  var LOCATE = 'B=$(command -v "$0") || exit 0; [ -f "$B" ] || exit 0; [ -x "$B" ] || exit 0';
8
8
  var NODE_PRESENT = "command -v node >/dev/null 2>&1 || exit 0";
9
9
  var HOOK_GUARD_SCRIPTS = {
10
- native_binary: `${LOCATE}; exec "$B"`,
11
- node_binary: `${LOCATE}; ${NODE_PRESENT}; exec "$B"`,
12
- node_script: `[ -f "$0" ] || exit 0; ${NODE_PRESENT}; exec node "$0"`
10
+ native_binary: `${LOCATE}; exec "$B" "$@"`,
11
+ node_binary: `${LOCATE}; ${NODE_PRESENT}; exec "$B" "$@"`,
12
+ node_script: `[ -f "$0" ] || exit 0; ${NODE_PRESENT}; exec node "$0" "$@"`
13
13
  };
14
14
  var BINARY_GUARDS = {
15
15
  native: "native_binary",
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6MTNS63X.js";
10
10
  import {
11
11
  resolveInstallSourceFor
12
- } from "./chunk-7C5CJC3H.js";
12
+ } from "./chunk-Y3UTTFTZ.js";
13
13
  import {
14
14
  configFilePath
15
15
  } from "./chunk-2UMNXADU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-VPJAAGD4.js";
3
+ } from "./chunk-B3V2H6SA.js";
4
4
  import {
5
5
  readJsonSafe
6
6
  } from "./chunk-6MTNS63X.js";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-VT4IVERX.js";
8
8
  import {
9
9
  pusharyDir
10
- } from "./chunk-VPJAAGD4.js";
10
+ } from "./chunk-B3V2H6SA.js";
11
11
  import {
12
12
  getMachineId
13
13
  } from "./chunk-RN3NOEJF.js";
@@ -1,22 +1,30 @@
1
+ import {
2
+ DEFAULT_SESSION,
3
+ cancelQuestion,
4
+ isDefaultSession,
5
+ isPolicyConfig,
6
+ listPendingQuestions,
7
+ removePendingQuestion,
8
+ removePendingSession,
9
+ sendNotification,
10
+ waitForAnswer
11
+ } from "./chunk-J3YDT4HM.js";
1
12
  import {
2
13
  getMachineId
3
14
  } from "./chunk-RN3NOEJF.js";
4
15
  import {
5
- callMcpTool,
6
16
  withRetry
7
17
  } from "./chunk-BSZYIAZL.js";
8
- import {
9
- installProxyDispatcher
10
- } from "./chunk-SAF6HGAA.js";
11
18
  import {
12
19
  reportedInstallSource
13
- } from "./chunk-7C5CJC3H.js";
20
+ } from "./chunk-Y3UTTFTZ.js";
14
21
  import {
15
22
  getApiKey,
16
23
  getBaseUrl
17
24
  } from "./chunk-2UMNXADU.js";
18
25
  import {
19
26
  ACTION_BODY_MAX,
27
+ AGENT_LABELS_BY_TYPE,
20
28
  DECISION_LINE_MAX,
21
29
  FILE_TARGET_TOOLS,
22
30
  gateOutputFor,
@@ -28,32 +36,13 @@ import {
28
36
  redactSecretsDeep,
29
37
  resolveAutoResolveOrigin,
30
38
  resolvePolicy
31
- } from "./chunk-CY4TZK5O.js";
39
+ } from "./chunk-7YJS2VTG.js";
32
40
 
33
41
  // src/policy.ts
34
42
  import { createHash } from "crypto";
35
43
  import { existsSync, readFileSync, writeFileSync } from "fs";
36
44
  import { join } from "path";
37
45
  import { tmpdir } from "os";
38
-
39
- // src/validate.ts
40
- var isPolicyConfig = (data) => {
41
- if (!data || typeof data !== "object") return false;
42
- const d = data;
43
- return Array.isArray(d.policies) && typeof d.defaultTimeoutSeconds === "number" && typeof d.defaultTimeoutAction === "string";
44
- };
45
- var isAskUserResponse = (data) => {
46
- if (!data || typeof data !== "object") return false;
47
- const d = data;
48
- return typeof d.correlationId === "string" && typeof d.status === "string";
49
- };
50
- var isWaitForAnswerResponse = (data) => {
51
- if (!data || typeof data !== "object") return false;
52
- const d = data;
53
- return typeof d.answered === "boolean";
54
- };
55
-
56
- // src/policy.ts
57
46
  var CACHE_TTL_MS = 60 * 1e3;
58
47
  var STALE_CACHE_MAX_MS = 12 * 60 * 60 * 1e3;
59
48
  var policyRequestFor = (agentType) => ({
@@ -189,32 +178,8 @@ var fetchModeState = async (apiKey, sessionId, reuseWithinMs = 0) => {
189
178
  };
190
179
  var fetchModeOverride = async (apiKey) => (await fetchModeState(apiKey)).mode;
191
180
 
192
- // src/api.ts
193
- import { randomUUID } from "crypto";
194
- installProxyDispatcher();
195
- var askUser = async (apiKey, params, timeoutMs = 15e3) => {
196
- const identified = params.toolUseId || params.requestId ? params : { ...params, requestId: randomUUID() };
197
- const result = await callMcpTool(apiKey, "ask_user", { ...identified, wait: false }, { maxRetries: 3, timeoutMs });
198
- if (!isAskUserResponse(result)) throw new Error("Invalid ask_user response");
199
- return result;
200
- };
201
- var waitForAnswer = async (apiKey, correlationId, timeoutMs = 3e4) => {
202
- const result = await callMcpTool(apiKey, "wait_for_answer", {
203
- correlationId,
204
- timeoutMs
205
- }, { timeoutMs: timeoutMs + 1e4 });
206
- if (!isWaitForAnswerResponse(result)) throw new Error("Invalid wait_for_answer response");
207
- return result;
208
- };
209
- var cancelQuestion = async (apiKey, correlationId) => {
210
- await callMcpTool(apiKey, "cancel_question", { correlationId });
211
- };
212
- var sendNotification = async (apiKey, params, timeoutMs = 15e3) => {
213
- await callMcpTool(apiKey, "send_notification", { ...params }, { maxRetries: 3, timeoutMs });
214
- };
215
-
216
181
  // ../hook-mapping/src/describe.ts
217
- import { isAbsolute, relative } from "path";
182
+ import { isAbsolute, relative, resolve } from "path";
218
183
  var hookPrefixes = {
219
184
  Bash: (input) => `bash: ${input.command ?? "(no command)"}`,
220
185
  PowerShell: (input) => `powershell: ${input.command ?? "(no command)"}`,
@@ -292,6 +257,21 @@ var deriveReceiptCommandHead = (command) => {
292
257
  return head ? redactSecrets(head).slice(0, TOOL_TARGET_MAX_LENGTH) : void 0;
293
258
  };
294
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))];
295
275
  var EXIT_CODE_FAILURE = /^Error: Exit code \d+/;
296
276
  var isToolResultError = (toolResult) => {
297
277
  try {
@@ -319,19 +299,34 @@ var relativizeReceiptPath = (filePath, cwd) => {
319
299
  var deriveReceiptMeta = (toolName, toolInput, toolResult, cwd) => {
320
300
  try {
321
301
  const ok = !isToolResultError(toolResult);
322
- if (FILE_TARGET_TOOLS.has(toolName)) {
323
- const filePath = toolInput.file_path;
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;
324
319
  if (typeof filePath !== "string" || !filePath) return void 0;
325
320
  return {
326
- kind: toolName === "Write" ? "write" : "edit",
321
+ kind: canonicalTool === "Write" ? "write" : "edit",
327
322
  // A path is an unlikely place for a credential but not an impossible one
328
323
  // (a token in a temp directory name), and this field is persisted.
329
324
  target: redactSecrets(relativizeReceiptPath(filePath, cwd)).slice(0, RECEIPT_TARGET_MAX_LENGTH),
330
325
  ok
331
326
  };
332
327
  }
333
- if (toolName === "Bash" || toolName === "PowerShell" || toolName === "Monitor") {
334
- const head = deriveReceiptCommandHead(toolInput.command);
328
+ if (canonicalTool === "Bash" || canonicalTool === "PowerShell" || canonicalTool === "Monitor") {
329
+ const head = deriveReceiptCommandHead(canonicalInput.command);
335
330
  if (!head) return void 0;
336
331
  return {
337
332
  kind: head === "git commit" ? "commit" : "bash",
@@ -389,6 +384,13 @@ var deriveBlocker = (mode, reason) => {
389
384
 
390
385
  // ../hook-mapping/src/map.ts
391
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
+ };
392
394
  var TASK_TITLE_MAX_LENGTH = 120;
393
395
  var STOP_SUMMARY_MAX_LENGTH = 200;
394
396
  var SESSION_END_ACTIONS = {
@@ -417,68 +419,22 @@ var sessionStartAction = (source) => source === "resume" ? "Session resumed" : "
417
419
  var sessionEndAction = (reason) => typeof reason === "string" && SESSION_END_ACTIONS[reason] || "Session ended";
418
420
  var taskTitleFrom = (prompt) => typeof prompt === "string" ? prompt.replace(/\s+/g, " ").trim().slice(0, TASK_TITLE_MAX_LENGTH) || void 0 : void 0;
419
421
 
420
- // src/pending.ts
421
- import { join as join2 } from "path";
422
- import { tmpdir as tmpdir2 } from "os";
423
- import { existsSync as existsSync2, mkdirSync, writeFileSync as writeFileSync2, readdirSync, unlinkSync, rmSync, statSync } from "fs";
424
- var PENDING_DIR = join2(tmpdir2(), "pushary-pending");
425
- var DEFAULT_SESSION = "_no_session";
426
- var GRACE_MS = 10 * 60 * 1e3;
427
- var sanitize = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
428
- var dirFor = (sessionId) => join2(PENDING_DIR, sanitize(sessionId));
429
- var isDefaultSession = (sessionId) => sanitize(sessionId) === DEFAULT_SESSION;
430
- var savePendingQuestion = (sessionId, correlationId) => {
431
- const dir = dirFor(sessionId);
432
- if (!existsSync2(dir)) mkdirSync(dir, { recursive: true });
433
- writeFileSync2(join2(dir, correlationId), "", "utf-8");
434
- };
435
- var listPendingQuestions = (sessionId) => {
436
- const dir = dirFor(sessionId);
437
- let files;
438
- try {
439
- files = readdirSync(dir);
440
- } catch {
441
- return [];
442
- }
443
- if (!isDefaultSession(sessionId)) return files;
444
- const cutoff = Date.now() - GRACE_MS;
445
- return files.filter((name) => {
446
- try {
447
- return statSync(join2(dir, name)).mtimeMs < cutoff;
448
- } catch {
449
- return false;
450
- }
451
- });
452
- };
453
- var removePendingQuestion = (sessionId, correlationId) => {
454
- try {
455
- unlinkSync(join2(dirFor(sessionId), correlationId));
456
- } catch {
457
- }
458
- };
459
- var removePendingSession = (sessionId) => {
460
- try {
461
- rmSync(dirFor(sessionId), { recursive: true, force: true });
462
- } catch {
463
- }
464
- };
465
-
466
422
  // src/repo.ts
467
- import { existsSync as existsSync3, readFileSync as readFileSync2, statSync as statSync2 } from "fs";
468
- import { basename as basename2, dirname, isAbsolute as isAbsolute2, join as join3, resolve } from "path";
423
+ 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";
469
425
  var MAX_PARENT_WALK = 64;
470
426
  var GIT_FILE_PREFIX = "gitdir:";
471
427
  var findGitDir = (startDir) => {
472
- let current = resolve(startDir);
428
+ let current = resolve2(startDir);
473
429
  for (let depth = 0; depth < MAX_PARENT_WALK; depth += 1) {
474
- const candidate = join3(current, ".git");
430
+ const candidate = join2(current, ".git");
475
431
  try {
476
- if (existsSync3(candidate)) {
477
- if (statSync2(candidate).isDirectory()) return candidate;
432
+ if (existsSync2(candidate)) {
433
+ if (statSync(candidate).isDirectory()) return candidate;
478
434
  const pointer = readFileSync2(candidate, "utf-8").trim();
479
435
  if (pointer.startsWith(GIT_FILE_PREFIX)) {
480
436
  const target = pointer.slice(GIT_FILE_PREFIX.length).trim();
481
- return isAbsolute2(target) ? target : resolve(current, target);
437
+ return isAbsolute2(target) ? target : resolve2(current, target);
482
438
  }
483
439
  }
484
440
  } catch {
@@ -491,7 +447,7 @@ var findGitDir = (startDir) => {
491
447
  };
492
448
  var configPathFor = (gitDir) => {
493
449
  const index = gitDir.replace(/\\/g, "/").indexOf("/worktrees/");
494
- return index === -1 ? join3(gitDir, "config") : join3(gitDir.slice(0, index), "config");
450
+ return index === -1 ? join2(gitDir, "config") : join2(gitDir.slice(0, index), "config");
495
451
  };
496
452
  var ORIGIN_SECTION = /^\[remote "origin"\]/;
497
453
  var SECTION_HEADER = /^\[/;
@@ -499,7 +455,7 @@ var URL_LINE = /^url\s*=\s*(.+)$/;
499
455
  var readOriginRemote = (gitDir) => {
500
456
  try {
501
457
  const configPath = configPathFor(gitDir);
502
- if (!existsSync3(configPath)) return void 0;
458
+ if (!existsSync2(configPath)) return void 0;
503
459
  let inOrigin = false;
504
460
  for (const rawLine of readFileSync2(configPath, "utf-8").split("\n")) {
505
461
  const line = rawLine.trim();
@@ -526,7 +482,7 @@ var deriveRepoKey = (cwd) => {
526
482
  const root = gitDir.endsWith(".git") ? dirname(gitDir) : dir;
527
483
  return localRepoKey(basename2(root));
528
484
  }
529
- return localRepoKey(basename2(resolve(dir)));
485
+ return localRepoKey(basename2(resolve2(dir)));
530
486
  } catch {
531
487
  return void 0;
532
488
  }
@@ -548,9 +504,9 @@ var repoKeyFor = (cwd) => {
548
504
  };
549
505
 
550
506
  // src/usage.ts
551
- import { closeSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync3, readSync, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
552
- import { join as join4 } from "path";
553
- import { tmpdir as tmpdir3 } from "os";
507
+ import { closeSync, mkdirSync, openSync, readFileSync as readFileSync3, readSync, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
508
+ import { join as join3 } from "path";
509
+ import { tmpdir as tmpdir2 } from "os";
554
510
  var DEFAULT_PRICES = [
555
511
  { match: "opus-4-1", in: 15, out: 75 },
556
512
  { match: "opus-4-0", in: 15, out: 75 },
@@ -585,8 +541,8 @@ var estimateCostUsd = (usage, model) => {
585
541
  const perTokenOut = price.out / 1e6;
586
542
  return usage.inputTokens * perTokenIn + usage.outputTokens * perTokenOut + usage.cacheCreationTokens * perTokenIn * CACHE_WRITE_MULTIPLIER + usage.cacheReadTokens * perTokenIn * CACHE_READ_MULTIPLIER;
587
543
  };
588
- var stateDir = () => process.env.PUSHARY_USAGE_DIR?.trim() || join4(tmpdir3(), "pushary-usage");
589
- var stateFile = (sessionId) => join4(stateDir(), sessionId.replace(/[^a-zA-Z0-9_-]/g, "_"));
544
+ var stateDir = () => process.env.PUSHARY_USAGE_DIR?.trim() || join3(tmpdir2(), "pushary-usage");
545
+ var stateFile = (sessionId) => join3(stateDir(), sessionId.replace(/[^a-zA-Z0-9_-]/g, "_"));
590
546
  var emptyState = () => ({ offset: 0, tokensIn: 0, tokensOut: 0, costUsd: 0, recentIds: [] });
591
547
  var readState = (path) => {
592
548
  try {
@@ -665,7 +621,7 @@ var extractUserText = (content) => {
665
621
  };
666
622
  var readLastUserPrompt = (transcriptPath) => {
667
623
  try {
668
- const size = statSync3(transcriptPath).size;
624
+ const size = statSync2(transcriptPath).size;
669
625
  const start = Math.max(0, size - USER_PROMPT_TAIL_BYTES);
670
626
  const lines = readRange(transcriptPath, start, size).toString("utf-8").split("\n");
671
627
  for (let i = lines.length - 1; i >= 0; i -= 1) {
@@ -688,7 +644,7 @@ var readLastUserPrompt = (transcriptPath) => {
688
644
  };
689
645
  var readNewUsage = (transcriptPath, sessionId) => {
690
646
  try {
691
- const size = statSync3(transcriptPath).size;
647
+ const size = statSync2(transcriptPath).size;
692
648
  const path = stateFile(sessionId);
693
649
  let state = readState(path);
694
650
  if (size < state.offset) state = { ...emptyState(), recentIds: state.recentIds };
@@ -704,8 +660,8 @@ var readNewUsage = (transcriptPath, sessionId) => {
704
660
  state.offset += lastNewline + 1;
705
661
  }
706
662
  }
707
- mkdirSync2(stateDir(), { recursive: true });
708
- writeFileSync3(path, JSON.stringify(state), "utf-8");
663
+ mkdirSync(stateDir(), { recursive: true });
664
+ writeFileSync2(path, JSON.stringify(state), "utf-8");
709
665
  if (state.tokensIn === 0 && state.tokensOut === 0) return null;
710
666
  return {
711
667
  tokensIn: state.tokensIn,
@@ -719,7 +675,7 @@ var readNewUsage = (transcriptPath, sessionId) => {
719
675
  };
720
676
 
721
677
  // src/codex-adapter.ts
722
- import { resolve as resolve2 } from "path";
678
+ import { resolve as resolve3 } from "path";
723
679
  var CODEX_AGENT = { type: "codex", label: "Codex" };
724
680
  var codexAllow = () => ({ kind: "allow" });
725
681
  var codexDeny = (reason) => ({ kind: "deny", reason });
@@ -733,21 +689,6 @@ var toCodexWire = (event, decision) => {
733
689
  decision.kind === "deny" ? decision.reason : void 0
734
690
  ) ?? null;
735
691
  };
736
- var parseApplyPatchOps = (command) => {
737
- if (typeof command !== "string") return [];
738
- const ops = [];
739
- for (const line of command.split("\n")) {
740
- const file = line.match(/^\*\*\*\s+(Add|Update|Delete) File:\s+(.+?)\s*$/);
741
- if (file) {
742
- ops.push({ op: file[1].toLowerCase(), path: file[2] });
743
- continue;
744
- }
745
- const move = line.match(/^\*\*\*\s+Move to:\s+(.+?)\s*$/);
746
- if (move) ops.push({ op: "move", path: move[1] });
747
- }
748
- return ops;
749
- };
750
- var parseApplyPatchFiles = (command) => [...new Set(parseApplyPatchOps(command).map((entry) => entry.path))];
751
692
  var describeApplyPatch = (command) => {
752
693
  const ops = parseApplyPatchOps(command);
753
694
  if (ops.length === 0) return null;
@@ -763,7 +704,7 @@ var toPolicyLookup = (toolName, toolInput, cwd) => {
763
704
  const command = toolInput.command;
764
705
  const files = parseApplyPatchFiles(command);
765
706
  if (files.length === 1) {
766
- return { tool: "Edit", input: { file_path: cwd ? resolve2(cwd, files[0]) : files[0] } };
707
+ return { tool: "Edit", input: { file_path: cwd ? resolve3(cwd, files[0]) : files[0] } };
767
708
  }
768
709
  return { tool: "Edit", input: typeof command === "string" ? { file_path: command } : {} };
769
710
  };
@@ -779,7 +720,7 @@ var toPolicyLookups = (toolName, toolInput, cwd) => {
779
720
  }
780
721
  return {
781
722
  tool: "Edit",
782
- inputs: files.map((file) => ({ file_path: cwd ? resolve2(cwd, file) : file }))
723
+ inputs: files.map((file) => ({ file_path: cwd ? resolve3(cwd, file) : file }))
783
724
  };
784
725
  };
785
726
  var permissionTimeoutDecision = (timeoutAction) => {
@@ -790,18 +731,18 @@ var permissionTimeoutDecision = (timeoutAction) => {
790
731
  var preToolUseTimeoutDecision = (timeoutAction, denyReason = "No response within timeout") => timeoutAction === "deny" ? codexDeny(denyReason) : codexPass();
791
732
 
792
733
  // src/throttle.ts
793
- import { join as join5 } from "path";
794
- import { tmpdir as tmpdir4 } from "os";
734
+ import { join as join4 } from "path";
735
+ import { tmpdir as tmpdir3 } from "os";
795
736
  import { createHash as createHash2 } from "crypto";
796
- import { existsSync as existsSync4, mkdirSync as mkdirSync3, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
797
- var THROTTLE_DIR = join5(tmpdir4(), "pushary-throttle");
798
- var markerPath = (key) => join5(THROTTLE_DIR, createHash2("sha256").update(key).digest("hex").slice(0, 16));
737
+ import { existsSync as existsSync3, mkdirSync as mkdirSync2, statSync as statSync3, writeFileSync as writeFileSync3 } from "fs";
738
+ var THROTTLE_DIR = join4(tmpdir3(), "pushary-throttle");
739
+ var markerPath = (key) => join4(THROTTLE_DIR, createHash2("sha256").update(key).digest("hex").slice(0, 16));
799
740
  var throttlePass = (key, windowMs) => {
800
741
  try {
801
742
  const path = markerPath(key);
802
- if (existsSync4(path) && Date.now() - statSync4(path).mtimeMs < windowMs) return false;
803
- mkdirSync3(THROTTLE_DIR, { recursive: true });
804
- writeFileSync4(path, "", "utf-8");
743
+ if (existsSync3(path) && Date.now() - statSync3(path).mtimeMs < windowMs) return false;
744
+ mkdirSync2(THROTTLE_DIR, { recursive: true });
745
+ writeFileSync3(path, "", "utf-8");
805
746
  return true;
806
747
  } catch {
807
748
  return false;
@@ -809,27 +750,27 @@ var throttlePass = (key, windowMs) => {
809
750
  };
810
751
 
811
752
  // src/events.ts
812
- import { basename as basename3, join as join6 } from "path";
813
- import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, statSync as statSync5, writeFileSync as writeFileSync5 } from "fs";
814
- import { tmpdir as tmpdir5 } from "os";
815
- var INTENT_DIR = join6(tmpdir5(), "pushary-intent");
753
+ import { basename as basename3, join as join5 } from "path";
754
+ import { existsSync as existsSync4, mkdirSync as mkdirSync3, readFileSync as readFileSync4, statSync as statSync4, writeFileSync as writeFileSync4 } from "fs";
755
+ import { tmpdir as tmpdir4 } from "os";
756
+ var INTENT_DIR = join5(tmpdir4(), "pushary-intent");
816
757
  var INTENT_MAX_BYTES = 2048;
817
758
  var INTENT_GRACE_MS = 10 * 60 * 1e3;
818
759
  var sanitizeSession = (sessionId) => sessionId.replace(/[^A-Za-z0-9_-]/g, "_").slice(0, 128) || DEFAULT_SESSION;
819
- var intentFile = (sessionId) => join6(INTENT_DIR, sanitizeSession(sessionId));
760
+ var intentFile = (sessionId) => join5(INTENT_DIR, sanitizeSession(sessionId));
820
761
  var saveLastPrompt = (sessionId, prompt) => {
821
762
  try {
822
763
  const trimmed = prompt.replace(/\s+/g, " ").trim().slice(0, INTENT_MAX_BYTES);
823
764
  if (!trimmed) return;
824
- mkdirSync4(INTENT_DIR, { recursive: true });
825
- writeFileSync5(intentFile(sessionId), trimmed, "utf-8");
765
+ mkdirSync3(INTENT_DIR, { recursive: true });
766
+ writeFileSync4(intentFile(sessionId), trimmed, "utf-8");
826
767
  } catch {
827
768
  }
828
769
  };
829
770
  var readLastPrompt = (sessionId) => {
830
771
  try {
831
772
  const path = intentFile(sessionId);
832
- if (isDefaultSession(sessionId) && statSync5(path).mtimeMs < Date.now() - INTENT_GRACE_MS) return void 0;
773
+ if (isDefaultSession(sessionId) && statSync4(path).mtimeMs < Date.now() - INTENT_GRACE_MS) return void 0;
833
774
  const value = readFileSync4(path, "utf-8").trim();
834
775
  return value.length > 0 ? value : void 0;
835
776
  } catch {
@@ -888,7 +829,7 @@ var POLICY_CACHE_TTL_MS = 5 * 60 * 1e3;
888
829
  var readFreshCachedPolicy = (apiKey, agentType, sessionId) => {
889
830
  const request = policyRequestFor(agentType);
890
831
  const path = policyCacheFile(apiKey, request.agent, request.repoAware);
891
- if (!existsSync5(path)) return null;
832
+ if (!existsSync4(path)) return null;
892
833
  const cached = JSON.parse(readFileSync4(path, "utf-8"));
893
834
  if (!isPolicyConfig(cached)) return null;
894
835
  if ((cached._sessionId ?? null) !== (sessionId ?? null)) return null;
@@ -1250,18 +1191,12 @@ export {
1250
1191
  getPolicy,
1251
1192
  fetchModeState,
1252
1193
  fetchModeOverride,
1253
- askUser,
1254
- waitForAnswer,
1255
- cancelQuestion,
1256
- sendNotification,
1257
1194
  describeToolCall,
1258
1195
  deriveToolTarget,
1259
1196
  scopePathFor,
1260
1197
  deriveActionBody,
1261
1198
  deriveAction,
1262
1199
  deriveBlocker,
1263
- DEFAULT_SESSION,
1264
- savePendingQuestion,
1265
1200
  repoKeyFor,
1266
1201
  throttlePass,
1267
1202
  readLastUserPrompt,
@@ -5,7 +5,7 @@ import {
5
5
  generateSessionKey,
6
6
  uploadTranscriptRecords,
7
7
  wrapSessionKey
8
- } from "./chunk-XPAGN3SC.js";
8
+ } from "./chunk-ECEUMWBH.js";
9
9
 
10
10
  // src/live-session.ts
11
11
  var MAX_TRANSCRIPT_QUEUE = 100;