@pushary/agent-hooks 1.9.60 → 1.9.62

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 (125) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +6 -0
  3. package/dist/{api-ASQA5PZM.js → api-7HLZRIUV.js} +15 -12
  4. package/dist/bin/pushary-bell-hook.js +28 -27
  5. package/dist/bin/pushary-bell.js +11 -10
  6. package/dist/bin/pushary-claude.js +34 -26
  7. package/dist/bin/pushary-clean.js +36 -34
  8. package/dist/bin/pushary-codex-bridge.js +22 -21
  9. package/dist/bin/pushary-codex-hook.js +49 -35
  10. package/dist/bin/pushary-codex-session.js +9 -8
  11. package/dist/bin/pushary-codex.js +15 -14
  12. package/dist/bin/pushary-connect.js +28 -27
  13. package/dist/bin/pushary-cowork.js +6 -5
  14. package/dist/bin/pushary-daemon.js +38 -37
  15. package/dist/bin/pushary-disconnect.js +27 -26
  16. package/dist/bin/pushary-doctor.js +41 -40
  17. package/dist/bin/pushary-elicitation-hook.js +30 -27
  18. package/dist/bin/pushary-gemini-bridge.js +16 -15
  19. package/dist/bin/pushary-gemini-hook.js +38 -29
  20. package/dist/bin/pushary-hook.js +33 -31
  21. package/dist/bin/pushary-login.js +15 -14
  22. package/dist/bin/pushary-logout.js +28 -27
  23. package/dist/bin/pushary-mcp.js +12 -11
  24. package/dist/bin/pushary-mode.js +15 -14
  25. package/dist/bin/pushary-notification-hook.js +27 -26
  26. package/dist/bin/pushary-opencode-hook.js +40 -30
  27. package/dist/bin/pushary-permission-denied-hook.js +32 -31
  28. package/dist/bin/pushary-permission-hook.js +31 -30
  29. package/dist/bin/pushary-post-hook.js +27 -26
  30. package/dist/bin/pushary-prompt-hook.js +27 -26
  31. package/dist/bin/pushary-session-end-hook.js +27 -26
  32. package/dist/bin/pushary-session-start-hook.js +34 -33
  33. package/dist/bin/pushary-setup.js +4195 -93
  34. package/dist/bin/pushary-stats.js +6 -5
  35. package/dist/bin/pushary-status.js +32 -31
  36. package/dist/bin/pushary-stop-hook.js +27 -26
  37. package/dist/bin/pushary-stopfailure-hook.js +27 -26
  38. package/dist/bin/pushary-suggestions.js +15 -14
  39. package/dist/bin/pushary-transcript-register.js +19 -18
  40. package/dist/bin/pushary-transcripts.js +8 -7
  41. package/dist/bin/pushary-upgrade.js +43 -37
  42. package/dist/bin/pushary-wait.js +15 -14
  43. package/dist/bin/pushary.js +8 -7
  44. package/dist/{chunk-RPPXQNIA.js → chunk-3IFCXMC6.js} +1 -1
  45. package/dist/{chunk-WXPVVXBU.js → chunk-3LBB7GVF.js} +4 -4
  46. package/dist/{chunk-WFSGCFXQ.js → chunk-3YGUWPNZ.js} +2 -6
  47. package/dist/{chunk-SVQWHV65.js → chunk-44FNEAXK.js} +1 -1
  48. package/dist/{chunk-YPD3MTFU.js → chunk-4K6YZPZ3.js} +1 -1
  49. package/dist/{chunk-PUHP4IBA.js → chunk-557ZE5EX.js} +4 -4
  50. package/dist/{chunk-HC3FHDKB.js → chunk-5R23J52J.js} +6 -6
  51. package/dist/{chunk-625DZLT5.js → chunk-67Q3Q5IO.js} +8 -6
  52. package/dist/{chunk-QGSHV3WO.js → chunk-6HIYOY6I.js} +77 -18
  53. package/dist/{chunk-L3AFVFGQ.js → chunk-6JAWNRDR.js} +2 -2
  54. package/dist/{chunk-6MJWYYAS.js → chunk-6YSEOXP5.js} +47 -3
  55. package/dist/{chunk-VIJIG5YL.js → chunk-7E2ZN7XA.js} +2 -2
  56. package/dist/{chunk-QLMOU57V.js → chunk-7EHZXZB2.js} +33 -20
  57. package/dist/{chunk-2AELPDMT.js → chunk-7ETELRQX.js} +1 -1
  58. package/dist/{chunk-7BHI3PZN.js → chunk-7GU4PXE5.js} +1 -1
  59. package/dist/{chunk-CDQHQAS7.js → chunk-7NJ4TDUH.js} +5 -5
  60. package/dist/{chunk-X3YKQJCZ.js → chunk-7NXB7OVX.js} +1 -1
  61. package/dist/{chunk-XEJOPVCG.js → chunk-A4CZPUQ6.js} +1 -1
  62. package/dist/{chunk-YGE6ML3O.js → chunk-AFV3FQNG.js} +4 -4
  63. package/dist/{chunk-V57XLKZL.js → chunk-BIUSODLS.js} +2 -2
  64. package/dist/{chunk-2QREHU4O.js → chunk-CFIQ3252.js} +3 -3
  65. package/dist/{chunk-BG4Y64FW.js → chunk-DFKEJARZ.js} +1 -1
  66. package/dist/{chunk-S54C6TQC.js → chunk-EA6574W2.js} +5 -5
  67. package/dist/{chunk-FDWMG6NY.js → chunk-EO6CL4PD.js} +2 -2
  68. package/dist/{chunk-SEILUNWB.js → chunk-ESXGCZDA.js} +26 -3
  69. package/dist/{chunk-CEQ2AZH4.js → chunk-EUNSJKJJ.js} +8 -8
  70. package/dist/{chunk-56JCQQLS.js → chunk-EVZDYG7L.js} +2 -2
  71. package/dist/{chunk-4MUFZU2G.js → chunk-F35YILEN.js} +1 -1
  72. package/dist/{chunk-ERK24P76.js → chunk-FG5HMJ7C.js} +1 -1
  73. package/dist/{chunk-NKLNU577.js → chunk-FX7KDF47.js} +3 -3
  74. package/dist/{chunk-AXJLJJ3M.js → chunk-FXECTHAG.js} +73 -2
  75. package/dist/chunk-FYS27SUS.js +216 -0
  76. package/dist/{chunk-O6IUZGWV.js → chunk-G3ZDCYMU.js} +1 -1
  77. package/dist/{chunk-ELLJPP6O.js → chunk-GFAG72LR.js} +2 -2
  78. package/dist/{chunk-ATKN4BJT.js → chunk-GV43RXR2.js} +1 -1
  79. package/dist/{chunk-4MWRR5IT.js → chunk-HSRNWCXJ.js} +3 -3
  80. package/dist/{chunk-IF26ZGZ7.js → chunk-LCNN7UOE.js} +3 -3
  81. package/dist/{chunk-WXZHQ3TT.js → chunk-LILS32LF.js} +5 -5
  82. package/dist/{chunk-33OOEVPG.js → chunk-LL2KHEJH.js} +1 -1
  83. package/dist/{chunk-W2IVTHIG.js → chunk-LWR5VKNC.js} +18 -10
  84. package/dist/{chunk-QUBIEZXC.js → chunk-M7MEVILL.js} +3 -3
  85. package/dist/chunk-MLKGABMK.js +9 -0
  86. package/dist/{chunk-XV6S5PWW.js → chunk-MURJ4WAL.js} +1 -1
  87. package/dist/{chunk-FUZ5VYWD.js → chunk-MYEALNW6.js} +1 -1
  88. package/dist/{chunk-ADR3KHOC.js → chunk-NAZRRXZM.js} +2 -2
  89. package/dist/{chunk-ZGOJLNKS.js → chunk-NZLQ6GMX.js} +4 -4
  90. package/dist/{chunk-K4MBKXAE.js → chunk-OZRT64BB.js} +1 -1
  91. package/dist/{chunk-Y5VKZNFN.js → chunk-PSCXEH42.js} +2 -2
  92. package/dist/{chunk-METMK3L4.js → chunk-Q4WTIKM6.js} +3 -3
  93. package/dist/{chunk-U7NR4JVD.js → chunk-QIPW7OVB.js} +4 -4
  94. package/dist/{chunk-USE5IEEW.js → chunk-R3CLBNST.js} +1 -1
  95. package/dist/{chunk-7WFRY6OL.js → chunk-RFCEVROB.js} +2 -2
  96. package/dist/{chunk-EZHY65QA.js → chunk-RSNN2TPE.js} +13 -8
  97. package/dist/{chunk-DJ7EZIQA.js → chunk-RU37NSZH.js} +3 -3
  98. package/dist/{chunk-J4KQL7YZ.js → chunk-SDOWT67G.js} +5 -5
  99. package/dist/{chunk-4PZXI7WU.js → chunk-SJCPIYWJ.js} +2 -2
  100. package/dist/{chunk-MUNL23WE.js → chunk-SJJYXMJP.js} +6 -6
  101. package/dist/{chunk-6LOQE4J4.js → chunk-TMHE5CVX.js} +3 -3
  102. package/dist/{chunk-GAMVAORR.js → chunk-UUAVYIWJ.js} +1 -1
  103. package/dist/{chunk-Y5V4PA2Z.js → chunk-UWCPY4RY.js} +2 -2
  104. package/dist/{chunk-5RU35K57.js → chunk-VF3IL56Q.js} +2 -2
  105. package/dist/{chunk-WN3RACVD.js → chunk-W3CBFLIX.js} +3 -3
  106. package/dist/{chunk-RLVJ6TVL.js → chunk-W6MYFAOK.js} +26 -18
  107. package/dist/{chunk-CSOROFJY.js → chunk-YQK72JGV.js} +5 -5
  108. package/dist/{chunk-7JXJJNQ5.js → chunk-ZEDGKCCM.js} +1 -1
  109. package/dist/{chunk-SOCJ2N3E.js → chunk-ZJFJUAHS.js} +6 -6
  110. package/dist/{codex-app-cards-switch-ZO76D2NY.js → codex-app-cards-switch-IIL7IPP6.js} +12 -11
  111. package/dist/{codex-desktop-launch-MJT5E3O3.js → codex-desktop-launch-XCLMYVBD.js} +2 -1
  112. package/dist/{codex-session-launch-PTFCVIC7.js → codex-session-launch-UMVALJ3A.js} +19 -18
  113. package/dist/{config-SXV6XNVU.js → config-5N3GUJD5.js} +4 -3
  114. package/dist/{global-upgrade-ETDP32LO.js → global-upgrade-5F4CSXED.js} +10 -9
  115. package/dist/{identity-OOLIOSMR.js → identity-7ULYW4RL.js} +5 -4
  116. package/dist/{live-capabilities-2XIFA7YO.js → live-capabilities-QTSFXA6T.js} +5 -4
  117. package/dist/{paths-IIOQZESZ.js → paths-HEMK2ALW.js} +4 -3
  118. package/dist/{reapply-KFAJSKOQ.js → reapply-AMFKVYZV.js} +27 -26
  119. package/dist/src/index.d.ts +1 -0
  120. package/dist/src/index.js +22 -21
  121. package/dist/{upgrade-lock-T6ILR644.js → upgrade-lock-IAZC5644.js} +5 -4
  122. package/dist/usage-NEFDYSRT.js +11 -0
  123. package/package.json +1 -1
  124. package/dist/chunk-6MC2XXFD.js +0 -126
  125. package/dist/usage-6TN7FVWS.js +0 -10
@@ -4,19 +4,19 @@ import {
4
4
  outcomeOfFailedAsk,
5
5
  reportMachineDenial,
6
6
  storedWaitDeadline
7
- } from "./chunk-625DZLT5.js";
7
+ } from "./chunk-67Q3Q5IO.js";
8
8
  import {
9
9
  isGatingMoment,
10
10
  recordKeylessMoment
11
- } from "./chunk-SVQWHV65.js";
11
+ } from "./chunk-44FNEAXK.js";
12
12
  import {
13
13
  isDeferAnswer,
14
14
  oncePerSession
15
- } from "./chunk-RPPXQNIA.js";
15
+ } from "./chunk-3IFCXMC6.js";
16
16
  import {
17
17
  activeHookSource,
18
18
  activeIdentity
19
- } from "./chunk-PUHP4IBA.js";
19
+ } from "./chunk-557ZE5EX.js";
20
20
  import {
21
21
  DEFAULT_SESSION,
22
22
  UNNAMED_ACTION,
@@ -40,10 +40,10 @@ import {
40
40
  reportEvent,
41
41
  scopePathFor,
42
42
  settleQuestionsForToolUse
43
- } from "./chunk-W2IVTHIG.js";
43
+ } from "./chunk-LWR5VKNC.js";
44
44
  import {
45
45
  repoKeyFor
46
- } from "./chunk-YPD3MTFU.js";
46
+ } from "./chunk-4K6YZPZ3.js";
47
47
  import {
48
48
  askUser,
49
49
  cancelQuestion,
@@ -52,26 +52,27 @@ import {
52
52
  isAwayPaused,
53
53
  isDecisionStopped,
54
54
  isLocalQuestionHandoff,
55
+ isQuestionLimitRefusal,
55
56
  pollForAnswer,
56
57
  reportClientError,
57
58
  requestGate,
58
59
  sendNotification,
59
60
  waitForQuestion,
60
61
  waitsForThePhone
61
- } from "./chunk-EZHY65QA.js";
62
+ } from "./chunk-RSNN2TPE.js";
62
63
  import {
63
64
  getMachineId
64
- } from "./chunk-O6IUZGWV.js";
65
+ } from "./chunk-G3ZDCYMU.js";
65
66
  import {
66
67
  claudeConfigDir
67
- } from "./chunk-6MJWYYAS.js";
68
+ } from "./chunk-6YSEOXP5.js";
68
69
  import {
69
70
  getApiKey,
70
71
  getBaseUrl
71
- } from "./chunk-BG4Y64FW.js";
72
+ } from "./chunk-DFKEJARZ.js";
72
73
  import {
73
74
  NPX_LATEST_COMMAND
74
- } from "./chunk-ERK24P76.js";
75
+ } from "./chunk-FG5HMJ7C.js";
75
76
  import {
76
77
  AGENT_QUESTION_STRATEGY,
77
78
  AGENT_QUESTION_TOOL,
@@ -80,6 +81,7 @@ import {
80
81
  GATE_WIRE,
81
82
  HANDED_BACK_REASON,
82
83
  PLAN_DECLINED_REASON,
84
+ QUESTION_LIMIT_PROMPT_REASON,
83
85
  SCOPE_BATCH_REASON,
84
86
  SOLE_GATE_SIGNED_OUT_REASON,
85
87
  SOLE_GATE_SUBSCRIPTION_REASON,
@@ -109,14 +111,17 @@ import {
109
111
  hookWaitDeadline,
110
112
  hookWritePath,
111
113
  isBlockedActionRequest,
114
+ isCursorHookPayload,
112
115
  isPermissionRequestOwnedByPreToolUse,
113
116
  isPusharyOwnTool,
114
117
  parseAgentQuestions,
115
118
  questionHandedToTheTerminal,
119
+ questionLimitHandBack,
120
+ refusesWhenUnanswered,
116
121
  resolveGate,
117
122
  timeoutActionWithoutLocalPrompt,
118
123
  unansweredRefusalReason
119
- } from "./chunk-AXJLJJ3M.js";
124
+ } from "./chunk-FXECTHAG.js";
120
125
 
121
126
  // src/claude-permission-rules.ts
122
127
  import { readFileSync, statSync } from "fs";
@@ -197,8 +202,12 @@ var allowWithInput = (updatedInput) => claudePreToolUseOutput("allow", void 0, u
197
202
  var ask = (reason) => claudePreToolUseOutput("ask", reason);
198
203
  var halted = (reason) => claudeStoppedPreToolUseOutput(reason);
199
204
  var undecidedCall = (reason) => PUSHARY_IS_SOLE_GATE ? deny(reason) : void 0;
200
- var outcomeOfFailedPermissionAsk = (error, sessionId) => outcomeOfFailedAsk(error, sessionId, halted(UNVERIFIABLE_APPROVAL_REASON)) ?? undecidedCall(SOLE_GATE_SUBSCRIPTION_REASON);
201
- var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, timeoutAction, sessionId, machineId, toolName, toolTarget, decision, signals) => {
205
+ var questionLimitOutput = (handBack) => handBack.kind === "refuse" ? deny(handBack.reason) : ask(QUESTION_LIMIT_PROMPT_REASON);
206
+ var outcomeOfFailedPermissionAsk = (error, sessionId, questionLimitFacts) => {
207
+ if (isQuestionLimitRefusal(error)) return questionLimitOutput(questionLimitHandBack(questionLimitFacts));
208
+ return outcomeOfFailedAsk(error, sessionId, halted(UNVERIFIABLE_APPROVAL_REASON)) ?? undecidedCall(SOLE_GATE_SUBSCRIPTION_REASON);
209
+ };
210
+ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, timeoutAction, sessionId, machineId, toolName, toolTarget, decision, signals, agentPromptFollows) => {
202
211
  const effectiveWait = effectiveWaitSeconds(timeoutAction, timeoutSeconds, "claude");
203
212
  const now = Date.now();
204
213
  const requestedDeadline = hookWaitDeadline(START_MS, effectiveWait, "claude", now);
@@ -218,7 +227,10 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
218
227
  ...decision
219
228
  });
220
229
  } catch (error) {
221
- return outcomeOfFailedPermissionAsk(error, sessionId);
230
+ return outcomeOfFailedPermissionAsk(error, sessionId, {
231
+ refusesUnanswered: refusesWhenUnanswered({ mode: "push_only", timeoutAction }),
232
+ agentPromptFollows
233
+ });
222
234
  }
223
235
  if (isDecisionStopped(result)) return halted(DECISION_STOP_REASON);
224
236
  const deadline = storedWaitDeadline(result, requestedDeadline);
@@ -246,7 +258,7 @@ var handlePushOnly = async (apiKey, description, projectName, timeoutSeconds, ti
246
258
  var handleTerminalOnly = () => {
247
259
  return ask();
248
260
  };
249
- var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds, sessionId, machineId, toolName, toolTarget, decision, signals) => {
261
+ var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds, sessionId, machineId, toolName, toolTarget, decision, signals, agentPromptFollows) => {
250
262
  const requestedDeadline = hookWaitDeadline(START_MS, pushFirstSeconds, "claude", Date.now());
251
263
  let result;
252
264
  try {
@@ -263,7 +275,7 @@ var handlePushFirst = async (apiKey, description, projectName, pushFirstSeconds,
263
275
  ...decision
264
276
  });
265
277
  } catch (error) {
266
- return outcomeOfFailedPermissionAsk(error, sessionId);
278
+ return outcomeOfFailedPermissionAsk(error, sessionId, { refusesUnanswered: false, agentPromptFollows });
267
279
  }
268
280
  if (isDecisionStopped(result)) return halted(DECISION_STOP_REASON);
269
281
  if (waitsForThePhone(result)) announceWait(pushFirstSeconds, result.answerUrl, sessionId);
@@ -324,6 +336,7 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
324
336
  const sessionId = input.session_id;
325
337
  const toolTarget = deriveToolTarget(input.tool_name, input.tool_input);
326
338
  const ownPrompt = hasItsOwnApprovalPrompt(ACTIVE_SOURCE);
339
+ const agentPromptFollows = ownPrompt && !isCursorHookPayload(input);
327
340
  const intent = readLastPrompt(sessionId ?? DEFAULT_SESSION) ?? (input.transcript_path ? readLastUserPrompt(input.transcript_path) : void 0);
328
341
  const decision = {
329
342
  toolPath: hookWritePath(input.tool_name, input.tool_input),
@@ -347,15 +360,15 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
347
360
  const runHandler = () => {
348
361
  switch (ownPrompt ? toolPolicy.mode : approvalModeWithoutLocalPrompt(toolPolicy.mode)) {
349
362
  case "push_only":
350
- return handlePushOnly(apiKey, description, projectName, toolPolicy.timeoutSeconds, ownPrompt ? toolPolicy.timeoutAction : timeoutActionWithoutLocalPrompt(toolPolicy), sessionId, machineId, input.tool_name, toolTarget, decision, signals);
363
+ return handlePushOnly(apiKey, description, projectName, toolPolicy.timeoutSeconds, ownPrompt ? toolPolicy.timeoutAction : timeoutActionWithoutLocalPrompt(toolPolicy), sessionId, machineId, input.tool_name, toolTarget, decision, signals, agentPromptFollows);
351
364
  case "terminal_only":
352
365
  return Promise.resolve(handleTerminalOnly());
353
366
  case "push_first":
354
- return handlePushFirst(apiKey, description, projectName, toolPolicy.pushFirstSeconds, sessionId, machineId, input.tool_name, toolTarget, decision, signals);
367
+ return handlePushFirst(apiKey, description, projectName, toolPolicy.pushFirstSeconds, sessionId, machineId, input.tool_name, toolTarget, decision, signals, agentPromptFollows);
355
368
  case "notify_only":
356
369
  return handleNotifyOnly(apiKey, description, projectName, sessionId, machineId);
357
370
  default:
358
- return handlePushFirst(apiKey, description, projectName, toolPolicy.pushFirstSeconds, sessionId, machineId, input.tool_name, toolTarget, decision, signals);
371
+ return handlePushFirst(apiKey, description, projectName, toolPolicy.pushFirstSeconds, sessionId, machineId, input.tool_name, toolTarget, decision, signals, agentPromptFollows);
359
372
  }
360
373
  };
361
374
  const result = await runHandler();
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactSecretsFromContent
3
- } from "./chunk-AXJLJJ3M.js";
3
+ } from "./chunk-FXECTHAG.js";
4
4
 
5
5
  // src/crypto.ts
6
6
  import nacl from "tweetnacl";
@@ -7,7 +7,7 @@ import {
7
7
  } from "./chunk-KZERVKTD.js";
8
8
  import {
9
9
  redactSecretsFromContent
10
- } from "./chunk-AXJLJJ3M.js";
10
+ } from "./chunk-FXECTHAG.js";
11
11
 
12
12
  // src/cli/json.ts
13
13
  var writeStdoutFully = (text) => new Promise((resolve, reject) => {
@@ -2,24 +2,24 @@ import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  GEMINI_HOOK_EVENTS,
4
4
  hasGeminiHooks
5
- } from "./chunk-IF26ZGZ7.js";
5
+ } from "./chunk-LCNN7UOE.js";
6
6
  import {
7
7
  AGENT_CHOICES
8
- } from "./chunk-XV6S5PWW.js";
8
+ } from "./chunk-MURJ4WAL.js";
9
9
  import {
10
10
  BELL_HOOK_BINARY
11
- } from "./chunk-4MUFZU2G.js";
11
+ } from "./chunk-F35YILEN.js";
12
12
  import {
13
13
  CODEX_HOOK_EVENTS,
14
14
  HOOK_SHELL,
15
15
  hasCodexHooks,
16
16
  holdBudgetOf
17
- } from "./chunk-6MJWYYAS.js";
17
+ } from "./chunk-6YSEOXP5.js";
18
18
  import {
19
19
  CURSOR_GATE_EVENTS,
20
20
  HOOK_LOCATOR_BINARY,
21
21
  hookCommandHoldBudget
22
- } from "./chunk-AXJLJJ3M.js";
22
+ } from "./chunk-FXECTHAG.js";
23
23
 
24
24
  // src/diagnostics/bridge.ts
25
25
  import { execFileSync } from "child_process";
@@ -2,7 +2,7 @@ import {
2
2
  isApprovalMode,
3
3
  isRecord,
4
4
  isTimeoutAction
5
- } from "./chunk-AXJLJJ3M.js";
5
+ } from "./chunk-FXECTHAG.js";
6
6
 
7
7
  // src/cli/settings-response.ts
8
8
  var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_HOLD_BUDGET_ENV,
3
3
  hookHoldBudgetProof
4
- } from "./chunk-AXJLJJ3M.js";
4
+ } from "./chunk-FXECTHAG.js";
5
5
 
6
6
  // src/hold-budget.ts
7
7
  var takeHookHoldBudget = (args = process.argv.slice(2), env = process.env) => {
@@ -2,25 +2,25 @@ import {
2
2
  SIGNED_OUT_ON_MAC_MESSAGE,
3
3
  describeSignedOutKey,
4
4
  readSignedOutDiagnosis
5
- } from "./chunk-ADR3KHOC.js";
5
+ } from "./chunk-NAZRRXZM.js";
6
6
  import {
7
7
  createIo
8
8
  } from "./chunk-FO3MDD26.js";
9
9
  import {
10
10
  readKeySource
11
- } from "./chunk-WN3RACVD.js";
11
+ } from "./chunk-W3CBFLIX.js";
12
12
  import {
13
13
  absoluteUrl,
14
14
  checkApiKey,
15
15
  describeKeyCheck,
16
16
  keyCheckFromResponse
17
- } from "./chunk-METMK3L4.js";
17
+ } from "./chunk-Q4WTIKM6.js";
18
18
  import {
19
19
  EXIT
20
20
  } from "./chunk-KZERVKTD.js";
21
21
  import {
22
22
  getBaseUrl
23
- } from "./chunk-BG4Y64FW.js";
23
+ } from "./chunk-DFKEJARZ.js";
24
24
 
25
25
  // src/cli/report-key.ts
26
26
  var { dim, yellow } = createIo();
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  CODEX_HOOK_STATUS
3
- } from "./chunk-56JCQQLS.js";
3
+ } from "./chunk-EVZDYG7L.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-ERK24P76.js";
6
+ } from "./chunk-FG5HMJ7C.js";
7
7
 
8
8
  // src/setup/codex-trust.ts
9
9
  var CODEX_TRUST_TELEMETRY = {
@@ -366,9 +366,9 @@ var installGlobally = (options) => {
366
366
  }
367
367
  const started = (async () => {
368
368
  if (!npmIsOnPath()) throw new NpmMissingError();
369
- const { withUpgradeLock } = await import("./global-upgrade-ETDP32LO.js");
370
- const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-T6ILR644.js");
371
- const { autoUpdateLock } = await import("./paths-IIOQZESZ.js");
369
+ const { withUpgradeLock } = await import("./global-upgrade-5F4CSXED.js");
370
+ const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-IAZC5644.js");
371
+ const { autoUpdateLock } = await import("./paths-HEMK2ALW.js");
372
372
  let result = "skipped";
373
373
  const install = async () => {
374
374
  const platform = process.platform;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-ERK24P76.js";
3
+ } from "./chunk-FG5HMJ7C.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -1,22 +1,22 @@
1
1
  import {
2
2
  openCodeConfigDirFrom
3
- } from "./chunk-QGSHV3WO.js";
3
+ } from "./chunk-6HIYOY6I.js";
4
4
  import {
5
5
  nativeClaudeInstallPath
6
6
  } from "./chunk-VUFHYMSP.js";
7
7
  import {
8
8
  grokHome
9
- } from "./chunk-PUHP4IBA.js";
9
+ } from "./chunk-557ZE5EX.js";
10
10
  import {
11
11
  claudeConfigDir,
12
12
  codexHomeFrom
13
- } from "./chunk-6MJWYYAS.js";
13
+ } from "./chunk-6YSEOXP5.js";
14
14
  import {
15
15
  resolvePathBinary
16
- } from "./chunk-2QREHU4O.js";
16
+ } from "./chunk-CFIQ3252.js";
17
17
  import {
18
18
  HOOK_COMPATIBLE_PROFILES
19
- } from "./chunk-AXJLJJ3M.js";
19
+ } from "./chunk-FXECTHAG.js";
20
20
 
21
21
  // src/hermes-config.ts
22
22
  import { execFileSync } from "child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSseMessages
3
- } from "./chunk-SEILUNWB.js";
3
+ } from "./chunk-ESXGCZDA.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-ERK24P76.js";
6
+ } from "./chunk-FG5HMJ7C.js";
7
7
 
8
8
  // src/mcp-stdio-bridge.ts
9
9
  var MCP_BRIDGE_BINARY = "pushary-mcp";
@@ -1,12 +1,17 @@
1
1
  import {
2
2
  keyCheckFromResponse
3
- } from "./chunk-METMK3L4.js";
3
+ } from "./chunk-Q4WTIKM6.js";
4
4
  import {
5
5
  installNetworkDefaults
6
- } from "./chunk-4MWRR5IT.js";
6
+ } from "./chunk-HSRNWCXJ.js";
7
7
  import {
8
8
  getBaseUrl
9
- } from "./chunk-BG4Y64FW.js";
9
+ } from "./chunk-DFKEJARZ.js";
10
+ import {
11
+ isRecord,
12
+ isToolErrorResult,
13
+ toolFailureCodeOfResult
14
+ } from "./chunk-FXECTHAG.js";
10
15
 
11
16
  // src/retry.ts
12
17
  var isRetryable = (err) => {
@@ -49,6 +54,21 @@ var SubscriptionRequiredError = class extends Error {
49
54
  this.upgradeUrl = upgradeUrl;
50
55
  }
51
56
  };
57
+ var McpToolError = class extends Error {
58
+ tool;
59
+ failure;
60
+ constructor(tool, failure, message) {
61
+ super(message);
62
+ this.name = "McpToolError";
63
+ this.tool = tool;
64
+ this.failure = failure;
65
+ }
66
+ };
67
+ var firstTextOf = (content) => {
68
+ const first = Array.isArray(content) ? content[0] : void 0;
69
+ return isRecord(first) && typeof first.text === "string" && first.text.length > 0 ? first.text : null;
70
+ };
71
+ var toolErrorOf = (toolName, result) => new McpToolError(toolName, toolFailureCodeOfResult(result), firstTextOf(result.content) ?? `Pushary ${toolName} failed`);
52
72
  var parseSseMessages = (body) => {
53
73
  const messages = [];
54
74
  for (const event of body.split(/\r?\n\r?\n/)) {
@@ -124,6 +144,8 @@ var callMcpTool = async (apiKey, toolName, params, options = {}) => {
124
144
  method: "tools/call",
125
145
  params: { name: toolName, arguments: params }
126
146
  }, options);
147
+ const result = data.result;
148
+ if (isToolErrorResult(result)) throw toolErrorOf(toolName, result);
127
149
  const text = data.result?.content?.[0]?.text;
128
150
  if (!text) throw new Error("Empty response from Pushary");
129
151
  return JSON.parse(text);
@@ -133,6 +155,7 @@ export {
133
155
  isRetryable,
134
156
  withRetry,
135
157
  SubscriptionRequiredError,
158
+ McpToolError,
136
159
  parseSseMessages,
137
160
  sendMcpRequest,
138
161
  callMcpTool
@@ -6,39 +6,39 @@ import {
6
6
  } from "./chunk-QW3FRUFB.js";
7
7
  import {
8
8
  ensureDaemonRunning
9
- } from "./chunk-HC3FHDKB.js";
9
+ } from "./chunk-5R23J52J.js";
10
10
  import {
11
11
  hookOwnerOf
12
- } from "./chunk-CDQHQAS7.js";
12
+ } from "./chunk-7NJ4TDUH.js";
13
13
  import {
14
14
  buildTranscriptRecords,
15
15
  decodePublicKey,
16
16
  generateSessionKey,
17
17
  wrapSessionKey
18
- } from "./chunk-2AELPDMT.js";
18
+ } from "./chunk-7ETELRQX.js";
19
19
  import {
20
20
  fetchTranscriptRecipients,
21
21
  uploadTranscriptRecords
22
- } from "./chunk-GAMVAORR.js";
22
+ } from "./chunk-UUAVYIWJ.js";
23
23
  import {
24
24
  transcriptEnvironmentPreference,
25
25
  transcriptsEnabled
26
- } from "./chunk-7JXJJNQ5.js";
26
+ } from "./chunk-ZEDGKCCM.js";
27
27
  import {
28
28
  readTranscriptPreference
29
- } from "./chunk-WN3RACVD.js";
29
+ } from "./chunk-W3CBFLIX.js";
30
30
  import {
31
31
  claudeConfigDir,
32
32
  codexHome,
33
33
  pusharyDir
34
- } from "./chunk-6MJWYYAS.js";
34
+ } from "./chunk-6YSEOXP5.js";
35
35
  import {
36
36
  writeJsonAtomic
37
37
  } from "./chunk-QENTGE75.js";
38
38
  import {
39
39
  getApiKey,
40
40
  getBaseUrl
41
- } from "./chunk-BG4Y64FW.js";
41
+ } from "./chunk-DFKEJARZ.js";
42
42
 
43
43
  // src/transcript-registration.ts
44
44
  import { createHash } from "crypto";
@@ -7,10 +7,10 @@ import {
7
7
  codexHome,
8
8
  codexHooksJsonIn,
9
9
  isPusharyCodexCommand
10
- } from "./chunk-6MJWYYAS.js";
10
+ } from "./chunk-6YSEOXP5.js";
11
11
  import {
12
12
  resolvePathBinary
13
- } from "./chunk-2QREHU4O.js";
13
+ } from "./chunk-CFIQ3252.js";
14
14
  import {
15
15
  getPackageVersion
16
16
  } from "./chunk-QTOLNRET.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-6MJWYYAS.js";
3
+ } from "./chunk-6YSEOXP5.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -2,7 +2,7 @@ import {
2
2
  DISCONNECT_AGENT_IDS,
3
3
  SETUP_AGENT_CHOICES,
4
4
  isApprovalMode
5
- } from "./chunk-AXJLJJ3M.js";
5
+ } from "./chunk-FXECTHAG.js";
6
6
 
7
7
  // src/cli/mode-request.ts
8
8
  var parseDuration = (value) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SETUP_FLAGS
3
- } from "./chunk-XV6S5PWW.js";
3
+ } from "./chunk-MURJ4WAL.js";
4
4
  import {
5
5
  parseFlags
6
6
  } from "./chunk-NMUI3ZWG.js";
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-PPY5N2E6.js";
10
10
  import {
11
11
  NPX_LATEST_COMMAND
12
- } from "./chunk-ERK24P76.js";
12
+ } from "./chunk-FG5HMJ7C.js";
13
13
  import {
14
14
  CLAUDE_CONNECTOR_GUIDE,
15
15
  CLAUDE_CONNECTOR_STEPS,
@@ -17,7 +17,7 @@ import {
17
17
  CLAUDE_CONNECTOR_URL,
18
18
  COWORK_CONNECTOR_LIMIT,
19
19
  COWORK_STANDING_INSTRUCTIONS
20
- } from "./chunk-AXJLJJ3M.js";
20
+ } from "./chunk-FXECTHAG.js";
21
21
 
22
22
  // src/cli/cowork.ts
23
23
  import { readFileSync } from "fs";
@@ -976,6 +976,40 @@ var redactSecrets = (text2) => applyRedactionRules(SECRET_REDACTION_RULES, text2
976
976
  var redactSecretsFromContent = (text2) => applyRedactionRules(CUT_OFF_TEXT_REDACTION_RULES, text2);
977
977
  var redactSecretsDeep = (text2) => redactSecrets(text2).replace(HIGH_ENTROPY_RULE.pattern, HIGH_ENTROPY_RULE.replacement);
978
978
 
979
+ // ../contracts/src/cursor.ts
980
+ var CURSOR_GATE_EVENTS = ["beforeShellExecution", "beforeMCPExecution", "preToolUse"];
981
+ var CURSOR_GATE_SCRIPT = "pushary-gate.mjs";
982
+ var CURSOR_SHELL_TOOL = "Shell";
983
+ var CURSOR_MCP_TOOL_PREFIX = "MCP:";
984
+ var CURSOR_FILE_GATE_TOOLS = ["Write", "Delete", "Edit"];
985
+ var CURSOR_GATE_COVERAGE = [
986
+ { event: "beforeShellExecution", covers: { kind: "named", tools: [CURSOR_SHELL_TOOL] }, matcherNamesTools: false },
987
+ { event: "beforeMCPExecution", covers: { kind: "prefix", prefix: CURSOR_MCP_TOOL_PREFIX }, matcherNamesTools: false },
988
+ { event: "preToolUse", covers: { kind: "named", tools: CURSOR_FILE_GATE_TOOLS }, matcherNamesTools: true }
989
+ ];
990
+ var isCursorHookPayload = (value) => isRecord(value) && typeof value.cursor_version === "string" && value.cursor_version.length > 0;
991
+ var NO_CURSOR_GATE = [];
992
+ var PLAIN_TOOL_NAME = /^[\w:]+$/;
993
+ var matcherMatchesEveryCall = (matcher) => matcher === void 0 || matcher === "" || matcher === "*";
994
+ var isPlainToolName = (name) => PLAIN_TOOL_NAME.test(name);
995
+ var toolNamesInMatcher = (matcher) => {
996
+ if (typeof matcher !== "string") return [];
997
+ const names = matcher.split("|");
998
+ return names.every(isPlainToolName) ? names : [];
999
+ };
1000
+ var narrowedByMatcher = (covers, matcher) => {
1001
+ if (covers.kind !== "named") return null;
1002
+ const named = toolNamesInMatcher(matcher);
1003
+ const tools = covers.tools.filter((tool) => named.includes(tool));
1004
+ return tools.length > 0 ? { kind: "named", tools } : null;
1005
+ };
1006
+ var toolsCoveredByGateEntry = (coverage, matcher) => {
1007
+ if (matcherMatchesEveryCall(matcher)) return coverage.covers;
1008
+ return coverage.matcherNamesTools ? narrowedByMatcher(coverage.covers, matcher) : null;
1009
+ };
1010
+ var toolMatches = (match, toolName) => match.kind === "named" ? match.tools.includes(toolName) : toolName.startsWith(match.prefix);
1011
+ var cursorGateOwnsToolCall = (registration, toolName) => typeof toolName === "string" && registration.some((match) => toolMatches(match, toolName));
1012
+
979
1013
  // ../contracts/src/shell-analysis.ts
980
1014
  var SHELL_WORD_SEPARATOR = /[ \t\n]/;
981
1015
  var ARITHMETIC_EVALUATING_EXPANSION = /\$[#+=~^]*(?:[A-Za-z_][A-Za-z0-9_]*|[0-9]+|[-?$!@*#])?\[/;
@@ -2612,6 +2646,23 @@ var AUTH_REJECTION_REASONS = [
2612
2646
  "site_not_found",
2613
2647
  ...AGENT_SITE_REJECTION_REASONS
2614
2648
  ];
2649
+ var TOOL_FAILURE_META_KEY = "pushary/failure";
2650
+ var TOOL_FAILURE_CODES = {
2651
+ questionLimit: "question_limit",
2652
+ invalidRequest: "invalid_request"
2653
+ };
2654
+ var TOOL_FAILURE_CODE_VALUES = Object.values(TOOL_FAILURE_CODES);
2655
+ var isToolFailureCode = (value) => typeof value === "string" && TOOL_FAILURE_CODE_VALUES.includes(value);
2656
+ var isToolErrorResult = (result) => isRecord(result) && result.isError === true;
2657
+ var toolFailureMetaOf = (result) => {
2658
+ const meta = result._meta;
2659
+ return isRecord(meta) && Object.hasOwn(meta, TOOL_FAILURE_META_KEY) ? meta[TOOL_FAILURE_META_KEY] : void 0;
2660
+ };
2661
+ var toolFailureCodeOfResult = (result) => {
2662
+ if (!isToolErrorResult(result)) return null;
2663
+ const code = toolFailureMetaOf(result);
2664
+ return isToolFailureCode(code) ? code : null;
2665
+ };
2615
2666
 
2616
2667
  // ../contracts/src/setup-wire.ts
2617
2668
  var PAIR_TTL_SECONDS = 900;
@@ -3112,10 +3163,10 @@ var hookWaitDeadline = (startMs, policyWaitSeconds, agent, nowMs) => {
3112
3163
  var hookWaitClamped = (startMs, policyWaitSeconds, agent, nowMs) => startMs + hookMaxWaitSeconds(agent) * 1e3 < nowMs + Math.max(policyWaitSeconds, 0) * 1e3;
3113
3164
  var effectiveWaitSeconds = (timeoutAction, policySeconds, agent) => timeoutAction === "wait" ? hookMaxWaitSeconds(agent) : policySeconds;
3114
3165
  var OPENCODE_APPROVAL_EVENT = "permission.ask";
3115
- var CURSOR_GATE_EVENTS = ["beforeShellExecution", "beforeMCPExecution", "preToolUse"];
3116
3166
  var hasNativeApprovalPrompt = (source, event) => !(source === "cursor" && event === "preToolUse") && !(source === "antigravity" && event === "PreToolUse");
3117
3167
  var SUPPORT_EMAIL = "business@pushary.com";
3118
3168
  var SUPPORT_DISCORD = "https://discord.gg/9v3VvUByrr";
3169
+ var HOOK_VERSION_PATTERN = /^\d+\.\d+\.\d+$/;
3119
3170
  var HOOK_LOCATOR_BINARY = "pushary-bridge";
3120
3171
  var isTokenCount = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
3121
3172
  var reportableSessionId = (value) => typeof value === "string" && value.length > 0 && value.length <= SESSION_ID_MAX_LENGTH ? value : null;
@@ -5769,9 +5820,16 @@ var codexAskUnanswered = (ask) => ({ kind: "deny", reason: unansweredRefusalReas
5769
5820
  var ruleApprovesAfterItsFullWindow = (ask) => ask.mode === "push_only" && ask.fullWindowServed && ask.timeoutAction === "approve";
5770
5821
  var codexUnansweredPreToolUse = (ask) => ruleApprovesAfterItsFullWindow(ask) ? CODEX_ASK_PASSES : codexAskUnanswered(ask);
5771
5822
  var HANDED_BACK_REASON = "Handling on your machine";
5823
+ var HAND_BACK_TO_THE_AGENTS_PROMPT = { kind: "agent_prompt" };
5772
5824
  var HAND_BACK_WITHOUT_A_PROMPT = { kind: "refuse", reason: NO_AGENT_PROMPT_REASON };
5773
5825
  var CODEX_HAND_BACK_REASON = "You chose to handle this on your machine, so it did not run. Ask Codex to run it again while you are at your computer, or run it yourself.";
5774
5826
  var CODEX_PRE_TOOL_USE_HAND_BACK = { kind: "refuse", reason: CODEX_HAND_BACK_REASON };
5827
+ var QUESTION_LIMIT_REASON = "Pushary already has as many open questions in this session as it allows, so nobody was asked about this and it did not run. Wait until the person answers or cancels one before trying it again.";
5828
+ var QUESTION_LIMIT_PROMPT_REASON = "Pushary has too many open questions in this session, so this was not sent to the phone. Approve it here.";
5829
+ var QUESTION_LIMIT_REFUSAL = { kind: "refuse", reason: QUESTION_LIMIT_REASON };
5830
+ var questionLimitRefuses = ({ refusesUnanswered, agentPromptFollows }) => refusesUnanswered || !agentPromptFollows;
5831
+ var questionLimitHandBack = (facts) => questionLimitRefuses(facts) ? QUESTION_LIMIT_REFUSAL : HAND_BACK_TO_THE_AGENTS_PROMPT;
5832
+ var refusesWhenUnanswered = ({ mode, timeoutAction }) => mode === "push_only" && timeoutAction === "deny";
5775
5833
  var codexDeferredPreToolUse = () => ({ kind: "deny", reason: CODEX_PRE_TOOL_USE_HAND_BACK.reason });
5776
5834
  var isScopeReason = (scopeReason) => typeof scopeReason === "string" && scopeReason.length > 0;
5777
5835
  var scopeBreachReasonOf = (verdict) => verdict.kind === "gate" && isScopeReason(verdict.scopeReason) ? verdict.scopeReason : void 0;
@@ -6239,6 +6297,13 @@ export {
6239
6297
  redactSecrets,
6240
6298
  redactSecretsFromContent,
6241
6299
  redactSecretsDeep,
6300
+ CURSOR_GATE_EVENTS,
6301
+ CURSOR_GATE_SCRIPT,
6302
+ CURSOR_GATE_COVERAGE,
6303
+ isCursorHookPayload,
6304
+ NO_CURSOR_GATE,
6305
+ toolsCoveredByGateEntry,
6306
+ cursorGateOwnsToolCall,
6242
6307
  degradedLine,
6243
6308
  hookWritePath,
6244
6309
  MAX_HOOK_ACTIVATION_EVIDENCE_ROWS,
@@ -6246,6 +6311,9 @@ export {
6246
6311
  hookActivationResult,
6247
6312
  CLIENT_REPORT_PATH,
6248
6313
  clientContextHeaders,
6314
+ TOOL_FAILURE_CODES,
6315
+ isToolErrorResult,
6316
+ toolFailureCodeOfResult,
6249
6317
  PAIR_TTL_SECONDS,
6250
6318
  computerOsOfPlatform,
6251
6319
  SETUP_AGENT_CHOICES,
@@ -6290,10 +6358,10 @@ export {
6290
6358
  hookWaitClamped,
6291
6359
  effectiveWaitSeconds,
6292
6360
  OPENCODE_APPROVAL_EVENT,
6293
- CURSOR_GATE_EVENTS,
6294
6361
  hasNativeApprovalPrompt,
6295
6362
  SUPPORT_EMAIL,
6296
6363
  SUPPORT_DISCORD,
6364
+ HOOK_VERSION_PATTERN,
6297
6365
  HOOK_LOCATOR_BINARY,
6298
6366
  isTokenCount,
6299
6367
  reportableSessionId,
@@ -6342,6 +6410,9 @@ export {
6342
6410
  codexUnansweredPreToolUse,
6343
6411
  HANDED_BACK_REASON,
6344
6412
  HAND_BACK_WITHOUT_A_PROMPT,
6413
+ QUESTION_LIMIT_PROMPT_REASON,
6414
+ questionLimitHandBack,
6415
+ refusesWhenUnanswered,
6345
6416
  codexDeferredPreToolUse,
6346
6417
  scopeBreachReasonOf,
6347
6418
  codexPreToolUseDelivery,