@pushary/agent-hooks 1.9.12 → 1.9.14

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 (102) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/data/cursor-plugin/scripts/pushary-gate.mjs +7 -2
  3. package/dist/bin/pushary-bell-hook.js +25 -25
  4. package/dist/bin/pushary-bell.js +9 -9
  5. package/dist/bin/pushary-claude.js +26 -25
  6. package/dist/bin/pushary-clean.js +52 -30
  7. package/dist/bin/pushary-codex-bridge.js +17 -17
  8. package/dist/bin/pushary-codex-hook.js +30 -30
  9. package/dist/bin/pushary-codex.js +12 -12
  10. package/dist/bin/pushary-connect.js +24 -24
  11. package/dist/bin/pushary-cowork.js +5 -5
  12. package/dist/bin/pushary-daemon.js +31 -31
  13. package/dist/bin/pushary-disconnect.js +39 -25
  14. package/dist/bin/pushary-doctor.js +33 -33
  15. package/dist/bin/pushary-elicitation-hook.js +25 -25
  16. package/dist/bin/pushary-gemini-bridge.js +13 -13
  17. package/dist/bin/pushary-gemini-hook.js +27 -27
  18. package/dist/bin/pushary-hook.js +29 -29
  19. package/dist/bin/pushary-login.js +12 -12
  20. package/dist/bin/pushary-logout.js +10 -10
  21. package/dist/bin/pushary-mcp.js +9 -9
  22. package/dist/bin/pushary-mode.js +12 -12
  23. package/dist/bin/pushary-notification-hook.js +24 -24
  24. package/dist/bin/pushary-opencode-hook.js +26 -26
  25. package/dist/bin/pushary-permission-denied-hook.js +29 -29
  26. package/dist/bin/pushary-permission-hook.js +28 -28
  27. package/dist/bin/pushary-post-hook.js +24 -24
  28. package/dist/bin/pushary-prompt-hook.js +24 -24
  29. package/dist/bin/pushary-session-end-hook.js +24 -24
  30. package/dist/bin/pushary-session-start-hook.js +28 -28
  31. package/dist/bin/pushary-setup.js +69 -41
  32. package/dist/bin/pushary-stats.js +5 -5
  33. package/dist/bin/pushary-status.js +26 -26
  34. package/dist/bin/pushary-stop-hook.js +24 -24
  35. package/dist/bin/pushary-stopfailure-hook.js +24 -24
  36. package/dist/bin/pushary-suggestions.js +12 -12
  37. package/dist/bin/pushary-transcript-register.js +17 -17
  38. package/dist/bin/pushary-transcripts.js +7 -7
  39. package/dist/bin/pushary-upgrade.js +30 -30
  40. package/dist/bin/pushary-wait.js +12 -12
  41. package/dist/bin/pushary.js +6 -6
  42. package/dist/{chunk-FSCWOYK6.js → chunk-2A234H3F.js} +3 -3
  43. package/dist/{chunk-DYQ5QIDN.js → chunk-2NIBBM3N.js} +2 -2
  44. package/dist/{chunk-FLPXTN3Q.js → chunk-2Q6IT5PR.js} +1 -1
  45. package/dist/{chunk-LBDMCNQY.js → chunk-2QASSTM5.js} +2 -2
  46. package/dist/{chunk-AWD2SLNA.js → chunk-2WWHZTI5.js} +13 -4
  47. package/dist/{chunk-J5XCHLP4.js → chunk-2Z56BRTF.js} +2 -2
  48. package/dist/{chunk-MEHDBT5H.js → chunk-34PUBGLS.js} +2 -2
  49. package/dist/{chunk-BX2R7SIY.js → chunk-3KHQWC4F.js} +6 -6
  50. package/dist/{chunk-CMZ4CW5J.js → chunk-3U4R475X.js} +3 -3
  51. package/dist/{chunk-RBBMGCSZ.js → chunk-3XAUHY35.js} +1 -1
  52. package/dist/{chunk-E2FGVADR.js → chunk-42WYKVHL.js} +2 -2
  53. package/dist/{chunk-BNQKHPEC.js → chunk-4BXVGCPE.js} +4 -4
  54. package/dist/{chunk-Z6VYZSVA.js → chunk-5RONPCMH.js} +5 -5
  55. package/dist/{chunk-GP44LTXN.js → chunk-5UYAJVAQ.js} +1 -1
  56. package/dist/{chunk-CXKY5FGY.js → chunk-5VP72OOI.js} +8 -8
  57. package/dist/{chunk-M2P3HQA3.js → chunk-7MGNY7S3.js} +1 -1
  58. package/dist/{chunk-2QJ6K2SR.js → chunk-7SIZISYH.js} +5 -5
  59. package/dist/{chunk-ZC6EVOX6.js → chunk-AJRT3JGE.js} +1 -1
  60. package/dist/{chunk-UEQWLVJB.js → chunk-APG7IAUK.js} +1 -1
  61. package/dist/{chunk-CPUEZAE2.js → chunk-ARM4DMIL.js} +1 -1
  62. package/dist/{chunk-CATIBZQH.js → chunk-CIZQARGJ.js} +3 -3
  63. package/dist/{chunk-ZHF4JDVE.js → chunk-CT4BJEU7.js} +1 -1
  64. package/dist/{chunk-PKQ435Z2.js → chunk-DVTXGXXL.js} +1 -1
  65. package/dist/{chunk-WBSL4FBX.js → chunk-EB6LH3U6.js} +3 -3
  66. package/dist/{chunk-EYLQVCME.js → chunk-ECU2Y7D2.js} +2 -2
  67. package/dist/{chunk-RYBAJXV4.js → chunk-FKQMH2DW.js} +1 -1
  68. package/dist/{chunk-TZCHW6KR.js → chunk-H7MTFFNI.js} +4 -4
  69. package/dist/{chunk-SQJUXVLW.js → chunk-J5RQW52I.js} +2 -2
  70. package/dist/{chunk-4DWQNP52.js → chunk-JHDHC2M7.js} +4 -4
  71. package/dist/{chunk-NDZKDJQU.js → chunk-K2IUMMZJ.js} +1 -1
  72. package/dist/{chunk-PNBJAYSL.js → chunk-LETLRKSY.js} +1 -1
  73. package/dist/{chunk-5VUB6VVO.js → chunk-LRZMGU7T.js} +4 -4
  74. package/dist/{chunk-CKUACXAX.js → chunk-MSEUUAJ7.js} +5 -5
  75. package/dist/{chunk-QOBOIFGG.js → chunk-NAROM5IR.js} +37 -7
  76. package/dist/{chunk-3VPS7JPH.js → chunk-NMDGIMDV.js} +2 -2
  77. package/dist/{chunk-GTM7C36Y.js → chunk-NNCK2PUR.js} +2 -2
  78. package/dist/{chunk-JNDELCH5.js → chunk-NXJNYAP7.js} +1 -1
  79. package/dist/{chunk-VDPU4YQN.js → chunk-OMR3P7PJ.js} +27 -18
  80. package/dist/{chunk-BOHDM4T7.js → chunk-POJUUEGO.js} +10 -5
  81. package/dist/{chunk-DWHCF4RH.js → chunk-PWO6T7JG.js} +5 -5
  82. package/dist/chunk-Q7JWY33N.js +111 -0
  83. package/dist/{chunk-5HPC3RNE.js → chunk-QD6GQDYW.js} +1 -1
  84. package/dist/{chunk-TSGQYARU.js → chunk-RMWV3MYN.js} +4 -4
  85. package/dist/{chunk-KXCWWHYO.js → chunk-RV4U3LYL.js} +3 -3
  86. package/dist/{chunk-SJ7M37RL.js → chunk-SEQSZYLW.js} +5 -5
  87. package/dist/{chunk-JKGTASA2.js → chunk-VYXXAFIA.js} +1 -1
  88. package/dist/{chunk-7U26QSMF.js → chunk-WYPQKDKX.js} +8 -8
  89. package/dist/{chunk-2GBUL4NP.js → chunk-XJKM6NQS.js} +6 -6
  90. package/dist/{chunk-A2DW2RNT.js → chunk-Y6IKUCVF.js} +2 -2
  91. package/dist/{chunk-YZWUTWDG.js → chunk-YSVCBUT3.js} +2 -2
  92. package/dist/{chunk-OBGZUD73.js → chunk-ZECHTK3K.js} +3 -3
  93. package/dist/{chunk-WKP2KRTU.js → chunk-ZSL7B7NF.js} +2 -2
  94. package/dist/{chunk-2NKTEA42.js → chunk-ZVFKNSRX.js} +1 -1
  95. package/dist/{global-upgrade-OCZWEF3A.js → global-upgrade-P5CJ22AW.js} +6 -6
  96. package/dist/{paths-SOGZJICO.js → paths-XZE2MPTP.js} +2 -2
  97. package/dist/{reapply-DFG5IE6N.js → reapply-V4GMKCGP.js} +20 -20
  98. package/dist/src/index.d.ts +1 -0
  99. package/dist/src/index.js +19 -19
  100. package/dist/{upgrade-lock-XLE5GVWS.js → upgrade-lock-DQF62B6X.js} +3 -3
  101. package/package.json +1 -1
  102. package/dist/chunk-PMUOEEUE.js +0 -50
@@ -1,21 +1,21 @@
1
1
  import {
2
2
  defersToNativeMode,
3
3
  reportMachineDenial
4
- } from "./chunk-E2FGVADR.js";
4
+ } from "./chunk-42WYKVHL.js";
5
5
  import {
6
6
  isGatingMoment,
7
7
  recordKeylessMoment
8
- } from "./chunk-RBBMGCSZ.js";
8
+ } from "./chunk-3XAUHY35.js";
9
9
  import {
10
10
  announceSubscriptionRequired,
11
11
  denyReasonFrom,
12
12
  isDeferAnswer,
13
13
  oncePerSession
14
- } from "./chunk-CPUEZAE2.js";
14
+ } from "./chunk-ARM4DMIL.js";
15
15
  import {
16
16
  activeHookSource,
17
17
  activeIdentity
18
- } from "./chunk-BOHDM4T7.js";
18
+ } from "./chunk-POJUUEGO.js";
19
19
  import {
20
20
  DEFAULT_SESSION,
21
21
  UNNAMED_ACTION,
@@ -40,7 +40,7 @@ import {
40
40
  reportEvent,
41
41
  scopePathFor,
42
42
  settleQuestionsForToolUse
43
- } from "./chunk-7U26QSMF.js";
43
+ } from "./chunk-WYPQKDKX.js";
44
44
  import {
45
45
  askUser,
46
46
  cancelQuestion,
@@ -51,30 +51,33 @@ import {
51
51
  requestGate,
52
52
  sendNotification,
53
53
  waitForQuestion
54
- } from "./chunk-DWHCF4RH.js";
54
+ } from "./chunk-PWO6T7JG.js";
55
55
  import {
56
56
  SubscriptionRequiredError
57
- } from "./chunk-CATIBZQH.js";
57
+ } from "./chunk-CIZQARGJ.js";
58
58
  import {
59
59
  getMachineId
60
- } from "./chunk-2NKTEA42.js";
60
+ } from "./chunk-ZVFKNSRX.js";
61
61
  import {
62
62
  getApiKey,
63
63
  getBaseUrl
64
- } from "./chunk-ZC6EVOX6.js";
64
+ } from "./chunk-AJRT3JGE.js";
65
65
  import {
66
66
  NPX_LATEST_COMMAND
67
- } from "./chunk-RYBAJXV4.js";
67
+ } from "./chunk-FKQMH2DW.js";
68
68
  import {
69
69
  AGENT_QUESTION_STRATEGY,
70
70
  DECISION_STOP_REASON,
71
71
  GATE_BLOCK_REASON_MAX_LENGTH,
72
72
  GATE_WIRE,
73
73
  PLAN_DECLINED_REASON,
74
+ SOLE_GATE_SIGNED_OUT_REASON,
75
+ SOLE_GATE_UNDECIDED_REASON,
74
76
  UNVERIFIABLE_APPROVAL_REASON,
75
77
  WITHDRAWN_APPROVAL_REASON,
76
78
  agentQuestionStrategy,
77
79
  agentRulesAllowEveryInput,
80
+ approvalModeWithoutLocalPrompt,
78
81
  buildDecisionEpisodeFeatures,
79
82
  claudeAllowlistOwnsCall,
80
83
  claudeConsultsItsAllowlist,
@@ -87,6 +90,7 @@ import {
87
90
  editGoesToTheAgentsPrompt,
88
91
  effectiveWaitSeconds,
89
92
  hasNativeApprovalPrompt,
93
+ hookCompatibleProfileBySource,
90
94
  hookHoldWindowMs,
91
95
  hookWaitClamped,
92
96
  hookWaitDeadline,
@@ -98,7 +102,7 @@ import {
98
102
  parseAgentQuestions,
99
103
  questionHandedToTheTerminal,
100
104
  resolveGate
101
- } from "./chunk-QOBOIFGG.js";
105
+ } from "./chunk-NAROM5IR.js";
102
106
 
103
107
  // src/claude-permission-rules.ts
104
108
  import { readFileSync, statSync } from "fs";
@@ -171,12 +175,14 @@ import { basename } from "path";
171
175
  var START_MS = Date.now();
172
176
  var ACTIVE_AGENT = activeIdentity(process.argv);
173
177
  var ACTIVE_SOURCE = activeHookSource(process.argv);
178
+ var PUSHARY_IS_SOLE_GATE = ACTIVE_SOURCE !== null && hookCompatibleProfileBySource(ACTIVE_SOURCE)?.soleGate != null;
174
179
  var agentNameIn = (projectName) => `${ACTIVE_AGENT.label} - ${projectName}`;
175
180
  var allow = (reason) => claudePreToolUseOutput("allow", reason);
176
181
  var deny = (reason) => claudePreToolUseOutput("deny", reason);
177
182
  var allowWithInput = (updatedInput) => claudePreToolUseOutput("allow", void 0, updatedInput);
178
183
  var ask = (reason) => claudePreToolUseOutput("ask", reason);
179
184
  var halted = (reason) => claudeStoppedPreToolUseOutput(reason);
185
+ var undecidedCall = (reason) => PUSHARY_IS_SOLE_GATE ? deny(reason) : void 0;
180
186
  var outcomeOfFailedAsk = (error, sessionId, failure) => {
181
187
  if (!(error instanceof SubscriptionRequiredError)) return failure;
182
188
  announceSubscriptionRequired(error.upgradeUrl, sessionId);
@@ -311,6 +317,7 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
311
317
  const projectName = basename(input.cwd ?? process.cwd());
312
318
  const sessionId = input.session_id;
313
319
  const toolTarget = deriveToolTarget(input.tool_name, input.tool_input);
320
+ const ownPrompt = hasItsOwnApprovalPrompt(ACTIVE_SOURCE);
314
321
  const intent = readLastPrompt(sessionId ?? DEFAULT_SESSION) ?? (input.transcript_path ? readLastUserPrompt(input.transcript_path) : void 0);
315
322
  const decision = {
316
323
  toolPath: hookWritePath(input.tool_name, input.tool_input),
@@ -326,11 +333,12 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
326
333
  // no suffix here. Absent on runtimes that do not send one, and the server then
327
334
  // creates a fresh decision exactly as before.
328
335
  toolUseId: input.tool_use_id,
329
- sessionToolAware: true
336
+ sessionToolAware: true,
337
+ ...ownPrompt ? {} : { localSurfaceAvailable: false }
330
338
  };
331
339
  const signals = {};
332
340
  const runHandler = () => {
333
- switch (toolPolicy.mode) {
341
+ switch (ownPrompt ? toolPolicy.mode : approvalModeWithoutLocalPrompt(toolPolicy.mode)) {
334
342
  case "push_only":
335
343
  return handlePushOnly(apiKey, description, projectName, toolPolicy.timeoutSeconds, toolPolicy.timeoutAction, sessionId, machineId, input.tool_name, toolTarget, decision, signals);
336
344
  case "terminal_only":
@@ -349,10 +357,10 @@ var dispatchModeHandler = async (apiKey, input, toolPolicy, machineId, trainingC
349
357
  }
350
358
  return result;
351
359
  };
352
- var handsUnansweredToTheTerminal = (source) => source === null || hasNativeApprovalPrompt(source, "PreToolUse");
360
+ var hasItsOwnApprovalPrompt = (source) => source === null || hasNativeApprovalPrompt(source, "PreToolUse");
353
361
  var phoneWaitHandoff = (source, waitSeconds) => {
354
362
  if (waitSeconds <= 0) return "Waiting for your answer.";
355
- return handsUnansweredToTheTerminal(source) ? `Waiting ${waitSeconds}s, then this terminal takes over.` : `Waiting ${waitSeconds}s. If nobody answers, it does not run.`;
363
+ return hasItsOwnApprovalPrompt(source) ? `Waiting ${waitSeconds}s, then this terminal takes over.` : `Waiting ${waitSeconds}s. If nobody answers, it does not run.`;
356
364
  };
357
365
  var announceWait = (waitSeconds, answerUrl, sessionId) => {
358
366
  try {
@@ -591,7 +599,8 @@ var handlePreToolUse = async (input, canonical) => {
591
599
  try {
592
600
  apiKey = getApiKey();
593
601
  } catch {
594
- return handleKeyless(input);
602
+ handleKeyless(input);
603
+ return undecidedCall(SOLE_GATE_SIGNED_OUT_REASON);
595
604
  }
596
605
  try {
597
606
  const modeState = await fetchModeState(apiKey, input.session_id);
@@ -631,12 +640,12 @@ var handlePreToolUse = async (input, canonical) => {
631
640
  // State we could not establish, with an auto-approve on the table. No
632
641
  // opinion, so Claude Code's own flow runs as if the hook were absent.
633
642
  case "defer":
634
- return void 0;
643
+ return undecidedCall(SOLE_GATE_UNDECIDED_REASON);
635
644
  default:
636
645
  return dispatchModeHandler(apiKey, input, verdict.policy, getMachineId(), modeState.trainingConsent, verdict.scopeReason, verdict.scopePath);
637
646
  }
638
647
  } catch {
639
- return void 0;
648
+ return undecidedCall(SOLE_GATE_UNDECIDED_REASON);
640
649
  }
641
650
  };
642
651
  var permReqAllow = (updatedInput) => claudePermissionRequestOutput("allow", void 0, updatedInput);
@@ -3,25 +3,28 @@ import {
3
3
  addGeminiMcpServer,
4
4
  removeGeminiMcpServer,
5
5
  supportedClaudeEvents
6
- } from "./chunk-KXCWWHYO.js";
6
+ } from "./chunk-RV4U3LYL.js";
7
7
  import {
8
8
  CLAUDE_CODE_AGENT,
9
9
  parseApplyPatchFiles
10
- } from "./chunk-7U26QSMF.js";
10
+ } from "./chunk-WYPQKDKX.js";
11
11
  import {
12
12
  guardBinary,
13
+ guardBinaryRefusing,
13
14
  holdBudgetOf,
14
15
  isProtectedByScope,
15
16
  registerHookEntry
16
- } from "./chunk-AWD2SLNA.js";
17
+ } from "./chunk-2WWHZTI5.js";
17
18
  import {
18
19
  HOOK_LOCATOR_BINARY,
19
20
  PHONE_ANSWERED_TOOLS,
20
21
  hookCompatibleProfile,
21
22
  hookCompatibleProfileBySource,
23
+ pusharyMissingReason,
24
+ refusalOutput,
22
25
  toToolLookup,
23
26
  withHookHoldBudget
24
- } from "./chunk-QOBOIFGG.js";
27
+ } from "./chunk-NAROM5IR.js";
25
28
 
26
29
  // src/claude-config.ts
27
30
  import { join } from "path";
@@ -326,6 +329,8 @@ var commandFor = (profile, definition, resolve2) => {
326
329
  return withHookHoldBudget(command, holdBudgetOf(definition));
327
330
  };
328
331
  var writesBareHandler = (profile, definition) => profile.nonToolEntries === "handler" && !TOOL_MATCHED_EVENTS.has(definition.event);
332
+ var refusesWhenPusharyIsMissing = (profile, definition) => profile.soleGate !== null && definition.delivery === "approval";
333
+ var guardFor = (profile, definition, path) => refusesWhenPusharyIsMissing(profile, definition) ? guardBinaryRefusing(path, refusalOutput(profile, pusharyMissingReason(profile))) : guardBinary(path);
329
334
  var entryFor = (profile, definition, resolve2) => {
330
335
  const handler = { type: "command", command: commandFor(profile, definition, resolve2), timeout: definition.timeout };
331
336
  if (writesBareHandler(profile, definition)) return handler;
@@ -337,13 +342,13 @@ var entryFor = (profile, definition, resolve2) => {
337
342
  var addCompatibleHooks = (config, profile, binDir) => {
338
343
  const conflictAt = hooksShapeConflict(config, profile);
339
344
  if (conflictAt) return { ok: false, conflictAt };
340
- const resolve2 = (name) => guardBinary(binDir ? join2(binDir, name) : name);
341
345
  const hooks = descend(config, profile.hooksKeyPath);
342
346
  const supported = new Map(compatibleHookEvents(profile).map((hook) => [hook.event, hook]));
343
347
  for (const known of CLAUDE_HOOK_EVENTS) {
344
348
  const current = Array.isArray(hooks[known.event]) ? hooks[known.event] : [];
345
349
  const definition = supported.get(known.event);
346
350
  if (definition) {
351
+ const resolve2 = (name) => guardFor(profile, definition, binDir ? join2(binDir, name) : name);
347
352
  hooks[known.event] = registerHookEntry(current, isPusharyCompatibleEntry, entryFor(profile, definition, resolve2));
348
353
  continue;
349
354
  }
@@ -5,18 +5,18 @@ import {
5
5
  import {
6
6
  SubscriptionRequiredError,
7
7
  callMcpTool
8
- } from "./chunk-CATIBZQH.js";
8
+ } from "./chunk-CIZQARGJ.js";
9
9
  import {
10
10
  installNetworkDefaults,
11
11
  isNetworkFailure
12
- } from "./chunk-WBSL4FBX.js";
12
+ } from "./chunk-EB6LH3U6.js";
13
13
  import {
14
14
  clientReportClaims
15
- } from "./chunk-AWD2SLNA.js";
15
+ } from "./chunk-2WWHZTI5.js";
16
16
  import {
17
17
  getApiKey,
18
18
  getBaseUrl
19
- } from "./chunk-ZC6EVOX6.js";
19
+ } from "./chunk-AJRT3JGE.js";
20
20
  import {
21
21
  ASK_AGENT_NAME_MAX,
22
22
  ASK_QUESTION_MAX,
@@ -24,7 +24,7 @@ import {
24
24
  DECISION_LINE_MAX,
25
25
  degradedLine,
26
26
  truncateLine
27
- } from "./chunk-QOBOIFGG.js";
27
+ } from "./chunk-NAROM5IR.js";
28
28
 
29
29
  // src/client-report-claim.ts
30
30
  import { createHash } from "crypto";
@@ -0,0 +1,111 @@
1
+ import {
2
+ compatibleConfigFile,
3
+ hasCompatibleHooks
4
+ } from "./chunk-POJUUEGO.js";
5
+ import {
6
+ pusharyHookExecutable
7
+ } from "./chunk-SEQSZYLW.js";
8
+ import {
9
+ isProtectedByScope,
10
+ registerHookEntry
11
+ } from "./chunk-2WWHZTI5.js";
12
+
13
+ // src/cursor-config.ts
14
+ var hookCommandOf = (entry) => {
15
+ const command = entry && typeof entry === "object" && !Array.isArray(entry) ? entry.command : void 0;
16
+ return typeof command === "string" ? command : "";
17
+ };
18
+ var isPusharyCursorEntry = (entry) => pusharyHookExecutable(hookCommandOf(entry)) !== null;
19
+ var registerCursorGate = (existing, entry) => registerHookEntry(existing, isPusharyCursorEntry, entry);
20
+ var withoutPusharyCursorHooks = (hooks, scope) => {
21
+ let removed = 0;
22
+ const kept = {};
23
+ for (const [event, entries] of Object.entries(hooks)) {
24
+ if (!Array.isArray(entries)) {
25
+ kept[event] = entries;
26
+ continue;
27
+ }
28
+ const others = entries.filter((entry) => !isPusharyCursorEntry(entry) || isProtectedByScope(hookCommandOf(entry), scope));
29
+ removed += entries.length - others.length;
30
+ if (others.length > 0 || entries.length === 0) kept[event] = others;
31
+ }
32
+ return { hooks: kept, removed };
33
+ };
34
+ var CURSOR_PLUGIN_NAME = "pushary";
35
+ var CURSOR_PLUGIN_STAGING_PREFIX = ".pushary-staging-";
36
+ var CURSOR_PLUGIN_BACKUP_INFIX = ".pushary-backup-";
37
+ var isCursorPluginLeftover = (name) => name.startsWith(`${CURSOR_PLUGIN_NAME}${CURSOR_PLUGIN_BACKUP_INFIX}`) || name.startsWith(CURSOR_PLUGIN_STAGING_PREFIX);
38
+ var isPusharyCursorPluginManifest = (contents) => {
39
+ try {
40
+ const manifest = JSON.parse(contents);
41
+ return typeof manifest === "object" && manifest !== null && !Array.isArray(manifest) && manifest.name === CURSOR_PLUGIN_NAME;
42
+ } catch {
43
+ return false;
44
+ }
45
+ };
46
+
47
+ // src/sole-gate.ts
48
+ import { homedir } from "os";
49
+ import { join } from "path";
50
+ var soleGateFile = (gate, home = homedir()) => join(home, ...gate.file);
51
+ var soleGateReceiptFile = (gate, home = homedir()) => join(home, ...gate.receipt);
52
+ var soleGateReceipt = (gate) => ({ key: gate.key, value: gate.value });
53
+ var isJsonRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
54
+ var isSoleGateReceipt = (value, gate) => isJsonRecord(value) && value.key === gate.key && value.value === gate.value;
55
+ var parseJsonRecord = (raw) => {
56
+ if (raw === null) return { kind: "missing" };
57
+ try {
58
+ const value = JSON.parse(raw);
59
+ return isJsonRecord(value) ? { kind: "record", value } : { kind: "unreadable" };
60
+ } catch {
61
+ return { kind: "unreadable" };
62
+ }
63
+ };
64
+ var claimSoleGate = (settings, gate) => {
65
+ const current = settings[gate.key];
66
+ if (current === void 0) {
67
+ settings[gate.key] = gate.value;
68
+ return { kind: "claimed" };
69
+ }
70
+ return current === gate.value ? { kind: "already_sole_gate" } : { kind: "agent_prompt_chosen", current: String(current) };
71
+ };
72
+ var releaseSoleGateSetting = (settings, gate) => {
73
+ if (settings[gate.key] !== gate.value) return false;
74
+ delete settings[gate.key];
75
+ return true;
76
+ };
77
+ var stillGatedByPushary = (profile, files, home) => {
78
+ const hooks = parseJsonRecord(files.read(compatibleConfigFile(profile, home)));
79
+ if (hooks.kind === "missing") return false;
80
+ return hooks.kind === "unreadable" || hasCompatibleHooks(hooks.value, profile);
81
+ };
82
+ var releaseSoleGate = (profile, files, home) => {
83
+ const gate = profile.soleGate;
84
+ if (!gate) return null;
85
+ if (stillGatedByPushary(profile, files, home)) return { kind: "still_gated" };
86
+ const receiptPath = soleGateReceiptFile(gate, home);
87
+ const receipt = parseJsonRecord(files.read(receiptPath));
88
+ if (receipt.kind !== "record" || !isSoleGateReceipt(receipt.value, gate)) return { kind: "not_set_by_pushary" };
89
+ const path = soleGateFile(gate, home);
90
+ const settings = parseJsonRecord(files.read(path));
91
+ if (settings.kind === "unreadable") return { kind: "unreadable", path };
92
+ const restored = settings.kind === "record" && releaseSoleGateSetting(settings.value, gate);
93
+ if (restored) files.write(path, `${JSON.stringify(settings.value, null, 2)}
94
+ `);
95
+ files.remove(receiptPath);
96
+ return restored ? { kind: "restored", path } : { kind: "changed_since", path };
97
+ };
98
+
99
+ export {
100
+ registerCursorGate,
101
+ withoutPusharyCursorHooks,
102
+ CURSOR_PLUGIN_STAGING_PREFIX,
103
+ CURSOR_PLUGIN_BACKUP_INFIX,
104
+ isCursorPluginLeftover,
105
+ isPusharyCursorPluginManifest,
106
+ soleGateFile,
107
+ soleGateReceiptFile,
108
+ soleGateReceipt,
109
+ claimSoleGate,
110
+ releaseSoleGate
111
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readConfigFileKey
3
- } from "./chunk-3VPS7JPH.js";
3
+ } from "./chunk-NMDGIMDV.js";
4
4
 
5
5
  // src/bell/fleet.ts
6
6
  import { closeSync, constants, futimesSync, lstatSync, mkdirSync, openSync, readdirSync, unlinkSync } from "fs";
@@ -14,19 +14,19 @@ import {
14
14
  } from "./chunk-U4TMAANR.js";
15
15
  import {
16
16
  callMcpTool
17
- } from "./chunk-CATIBZQH.js";
17
+ } from "./chunk-CIZQARGJ.js";
18
18
  import {
19
19
  reportedInstallSource
20
- } from "./chunk-WKP2KRTU.js";
20
+ } from "./chunk-ZSL7B7NF.js";
21
21
  import {
22
22
  NPX_LATEST_COMMAND
23
- } from "./chunk-RYBAJXV4.js";
23
+ } from "./chunk-FKQMH2DW.js";
24
24
  import {
25
25
  NO_PAIRING_COMPUTER,
26
26
  PAIR_TTL_SECONDS,
27
27
  classifyConfirmResponse,
28
28
  isAnswerSource
29
- } from "./chunk-QOBOIFGG.js";
29
+ } from "./chunk-NAROM5IR.js";
30
30
 
31
31
  // src/reach.ts
32
32
  var reachVerdict = (channels) => {
@@ -5,16 +5,16 @@ import {
5
5
  import {
6
6
  NOTIFICATION_MATCHED_TYPES,
7
7
  POSTTOOLUSE_MIRRORED_TOOLS
8
- } from "./chunk-JKGTASA2.js";
8
+ } from "./chunk-VYXXAFIA.js";
9
9
  import {
10
10
  isProtectedByScope,
11
11
  registerHookEntry
12
- } from "./chunk-AWD2SLNA.js";
12
+ } from "./chunk-2WWHZTI5.js";
13
13
  import {
14
14
  CLAUDE_PRETOOLUSE_MATCHER,
15
15
  HOOK_BUDGETS,
16
16
  HOOK_LOCATOR_BINARY
17
- } from "./chunk-QOBOIFGG.js";
17
+ } from "./chunk-NAROM5IR.js";
18
18
 
19
19
  // src/gemini-config.ts
20
20
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -2,23 +2,23 @@ import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  GEMINI_HOOK_EVENTS,
4
4
  hasGeminiHooks
5
- } from "./chunk-KXCWWHYO.js";
5
+ } from "./chunk-RV4U3LYL.js";
6
6
  import {
7
7
  AGENT_CHOICES
8
- } from "./chunk-NDZKDJQU.js";
8
+ } from "./chunk-K2IUMMZJ.js";
9
9
  import {
10
10
  BELL_HOOK_BINARY
11
- } from "./chunk-JNDELCH5.js";
11
+ } from "./chunk-NXJNYAP7.js";
12
12
  import {
13
13
  CODEX_HOOK_EVENTS,
14
14
  hasCodexHooks,
15
15
  holdBudgetOf
16
- } from "./chunk-AWD2SLNA.js";
16
+ } from "./chunk-2WWHZTI5.js";
17
17
  import {
18
18
  CURSOR_GATE_EVENTS,
19
19
  HOOK_LOCATOR_BINARY,
20
20
  hookCommandHoldBudget
21
- } from "./chunk-QOBOIFGG.js";
21
+ } from "./chunk-NAROM5IR.js";
22
22
 
23
23
  // src/diagnostics/bridge.ts
24
24
  import { execFileSync } from "child_process";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PRETOOLUSE_GATED_TOOLS
3
- } from "./chunk-QOBOIFGG.js";
3
+ } from "./chunk-NAROM5IR.js";
4
4
 
5
5
  // src/claude-tools.ts
6
6
  var POSTTOOLUSE_MIRROR_ONLY_TOOLS = ["TodoWrite", "Task", "WebFetch", "WebSearch"];
@@ -2,7 +2,7 @@ import {
2
2
  IDLE_PROMPT_NOTIFICATION,
3
3
  NOTIFICATION_PUSH_TYPES,
4
4
  POSTTOOLUSE_MIRROR_ONLY_TOOLS
5
- } from "./chunk-JKGTASA2.js";
5
+ } from "./chunk-VYXXAFIA.js";
6
6
  import {
7
7
  cancelQuestion,
8
8
  clientErrorKindOf,
@@ -10,26 +10,26 @@ import {
10
10
  reportClientError,
11
11
  sendNotification,
12
12
  waitForAnswer
13
- } from "./chunk-DWHCF4RH.js";
13
+ } from "./chunk-PWO6T7JG.js";
14
14
  import {
15
15
  withRetry
16
- } from "./chunk-CATIBZQH.js";
16
+ } from "./chunk-CIZQARGJ.js";
17
17
  import {
18
18
  getMachineId
19
- } from "./chunk-2NKTEA42.js";
19
+ } from "./chunk-ZVFKNSRX.js";
20
20
  import {
21
21
  reportedInstallSource
22
- } from "./chunk-WKP2KRTU.js";
22
+ } from "./chunk-ZSL7B7NF.js";
23
23
  import {
24
24
  canonicalJson
25
- } from "./chunk-AWD2SLNA.js";
25
+ } from "./chunk-2WWHZTI5.js";
26
26
  import {
27
27
  writeFileAtomic
28
28
  } from "./chunk-T7E75EKA.js";
29
29
  import {
30
30
  getApiKey,
31
31
  getBaseUrl
32
- } from "./chunk-ZC6EVOX6.js";
32
+ } from "./chunk-AJRT3JGE.js";
33
33
  import {
34
34
  ACTION_BODY_MAX,
35
35
  AGENT_LABELS_BY_TYPE,
@@ -58,7 +58,7 @@ import {
58
58
  resolvePolicy,
59
59
  toToolLookup,
60
60
  truncateLine
61
- } from "./chunk-QOBOIFGG.js";
61
+ } from "./chunk-NAROM5IR.js";
62
62
 
63
63
  // ../hook-mapping/src/describe.ts
64
64
  import { isAbsolute, relative, resolve } from "path";
@@ -3,27 +3,27 @@ import {
3
3
  expectedLaunchCapabilities,
4
4
  hasSpawnProvider,
5
5
  resolveControlPolicy
6
- } from "./chunk-EYLQVCME.js";
6
+ } from "./chunk-ECU2Y7D2.js";
7
7
  import {
8
8
  daemonHasRemoteProof,
9
9
  daemonServiceManagerAvailable,
10
10
  hasDaemonServiceDefinition,
11
11
  readDaemonNeedsLogin,
12
12
  readDaemonStatus
13
- } from "./chunk-2QJ6K2SR.js";
13
+ } from "./chunk-7SIZISYH.js";
14
14
  import {
15
15
  readControlMode,
16
16
  readKeySource
17
- } from "./chunk-3VPS7JPH.js";
17
+ } from "./chunk-NMDGIMDV.js";
18
18
  import {
19
19
  getMachineId
20
- } from "./chunk-2NKTEA42.js";
20
+ } from "./chunk-ZVFKNSRX.js";
21
21
  import {
22
22
  getBaseUrl
23
- } from "./chunk-ZC6EVOX6.js";
23
+ } from "./chunk-AJRT3JGE.js";
24
24
  import {
25
25
  getPackageVersion
26
- } from "./chunk-QOBOIFGG.js";
26
+ } from "./chunk-NAROM5IR.js";
27
27
 
28
28
  // src/machines.ts
29
29
  import { hostname } from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-AWD2SLNA.js";
3
+ } from "./chunk-2WWHZTI5.js";
4
4
  import {
5
5
  readJsonSafe,
6
6
  writeFileAtomic
@@ -13,7 +13,7 @@ import {
13
13
  serializeDeclinedAgents,
14
14
  withDeclinedAgent,
15
15
  withoutDeclinedAgent
16
- } from "./chunk-QOBOIFGG.js";
16
+ } from "./chunk-NAROM5IR.js";
17
17
 
18
18
  // src/declined-agents-file.ts
19
19
  import { join } from "path";
@@ -8,10 +8,10 @@ import {
8
8
  codexHooksJsonIn,
9
9
  isPusharyCodexCommand,
10
10
  resolvePathBinary
11
- } from "./chunk-AWD2SLNA.js";
11
+ } from "./chunk-2WWHZTI5.js";
12
12
  import {
13
13
  getPackageVersion
14
- } from "./chunk-QOBOIFGG.js";
14
+ } from "./chunk-NAROM5IR.js";
15
15
 
16
16
  // src/codex-app-server.ts
17
17
  import { existsSync, realpathSync } from "fs";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  openCodeConfigDirFrom
3
- } from "./chunk-Z6VYZSVA.js";
3
+ } from "./chunk-5RONPCMH.js";
4
4
  import {
5
5
  codexHomeFrom,
6
6
  resolvePathBinary
7
- } from "./chunk-AWD2SLNA.js";
7
+ } from "./chunk-2WWHZTI5.js";
8
8
  import {
9
9
  HOOK_COMPATIBLE_PROFILES
10
- } from "./chunk-QOBOIFGG.js";
10
+ } from "./chunk-NAROM5IR.js";
11
11
 
12
12
  // src/hermes-config.ts
13
13
  import { execFileSync } from "child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  configFilePath
3
- } from "./chunk-ZC6EVOX6.js";
3
+ } from "./chunk-AJRT3JGE.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-QOBOIFGG.js";
6
+ } from "./chunk-NAROM5IR.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-AWD2SLNA.js";
3
+ } from "./chunk-2WWHZTI5.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-T7E75EKA.js";
@@ -5,15 +5,15 @@ import {
5
5
  readGlobalUpgradeSubject,
6
6
  upgradeInstalledPackage,
7
7
  withUpgradeLock
8
- } from "./chunk-CKUACXAX.js";
9
- import "./chunk-PNBJAYSL.js";
10
- import "./chunk-J5XCHLP4.js";
8
+ } from "./chunk-MSEUUAJ7.js";
9
+ import "./chunk-LETLRKSY.js";
10
+ import "./chunk-2Z56BRTF.js";
11
11
  import "./chunk-POFBE6ZY.js";
12
12
  import "./chunk-KZERVKTD.js";
13
- import "./chunk-AWD2SLNA.js";
13
+ import "./chunk-2WWHZTI5.js";
14
14
  import "./chunk-T7E75EKA.js";
15
- import "./chunk-RYBAJXV4.js";
16
- import "./chunk-QOBOIFGG.js";
15
+ import "./chunk-FKQMH2DW.js";
16
+ import "./chunk-NAROM5IR.js";
17
17
  export {
18
18
  finishGlobalUpgrade,
19
19
  finishUpgradeWithLock,
@@ -32,8 +32,8 @@ import {
32
32
  pusharyDir,
33
33
  vscodePluginDir,
34
34
  vscodePluginMcp
35
- } from "./chunk-AWD2SLNA.js";
36
- import "./chunk-QOBOIFGG.js";
35
+ } from "./chunk-2WWHZTI5.js";
36
+ import "./chunk-NAROM5IR.js";
37
37
  export {
38
38
  autoUpdateLock,
39
39
  autoUpdateLog,