@pushary/agent-hooks 1.7.0 → 1.7.2

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 +28 -0
  2. package/dist/bin/pushary-bell-hook.js +23 -23
  3. package/dist/bin/pushary-bell.js +10 -10
  4. package/dist/bin/pushary-claude.js +46 -35
  5. package/dist/bin/pushary-clean.js +194 -102
  6. package/dist/bin/pushary-codex-bridge.js +18 -17
  7. package/dist/bin/pushary-codex-hook.js +53 -39
  8. package/dist/bin/pushary-codex.js +14 -12
  9. package/dist/bin/pushary-connect.js +16 -16
  10. package/dist/bin/pushary-cowork.js +5 -5
  11. package/dist/bin/pushary-daemon.js +27 -27
  12. package/dist/bin/pushary-disconnect.js +19 -17
  13. package/dist/bin/pushary-doctor.js +99 -43
  14. package/dist/bin/pushary-elicitation-hook.js +35 -26
  15. package/dist/bin/pushary-gemini-bridge.js +12 -12
  16. package/dist/bin/pushary-gemini-hook.js +47 -32
  17. package/dist/bin/pushary-hook.js +34 -32
  18. package/dist/bin/pushary-login.js +16 -16
  19. package/dist/bin/pushary-logout.js +8 -8
  20. package/dist/bin/pushary-mcp.js +9 -8
  21. package/dist/bin/pushary-mode.js +10 -10
  22. package/dist/bin/pushary-notification-hook.js +29 -27
  23. package/dist/bin/pushary-opencode-hook.js +46 -32
  24. package/dist/bin/pushary-permission-denied-hook.js +34 -32
  25. package/dist/bin/pushary-permission-hook.js +33 -31
  26. package/dist/bin/pushary-post-hook.js +29 -27
  27. package/dist/bin/pushary-prompt-hook.js +29 -27
  28. package/dist/bin/pushary-session-end-hook.js +29 -27
  29. package/dist/bin/pushary-session-start-hook.js +33 -31
  30. package/dist/bin/pushary-setup.js +143 -105
  31. package/dist/bin/pushary-stats.js +5 -5
  32. package/dist/bin/pushary-status.js +19 -19
  33. package/dist/bin/pushary-stop-hook.js +29 -27
  34. package/dist/bin/pushary-stopfailure-hook.js +29 -27
  35. package/dist/bin/pushary-suggestions.js +5 -5
  36. package/dist/bin/pushary-transcript-register.js +19 -19
  37. package/dist/bin/pushary-transcripts.js +7 -7
  38. package/dist/bin/pushary-upgrade.js +20 -20
  39. package/dist/bin/pushary-wait.js +10 -10
  40. package/dist/bin/pushary.js +6 -6
  41. package/dist/{chunk-IJ6ECPA6.js → chunk-2B4XCMH6.js} +75 -232
  42. package/dist/{chunk-EGKXSQCY.js → chunk-2XOHXZRC.js} +12 -4
  43. package/dist/{chunk-D6BULEJW.js → chunk-3NSRL5E7.js} +2 -2
  44. package/dist/{chunk-UC65FJJT.js → chunk-3RO2UWJQ.js} +2 -2
  45. package/dist/{chunk-73T6MSU5.js → chunk-4S7CCOXB.js} +5 -5
  46. package/dist/{chunk-7OS4IHGI.js → chunk-5GIBNUBD.js} +2 -2
  47. package/dist/chunk-5OP5MQI7.js +45 -0
  48. package/dist/{chunk-B3UXMSMW.js → chunk-65RN6ZCO.js} +1 -1
  49. package/dist/{chunk-2PS6QWDW.js → chunk-6NHXKTQU.js} +2 -2
  50. package/dist/{chunk-V6QRSU2G.js → chunk-6QZK4O36.js} +4 -4
  51. package/dist/{chunk-ZQ7IDOKY.js → chunk-A6WQF7FQ.js} +3 -3
  52. package/dist/{chunk-QXAK5RFU.js → chunk-AWZNDM3B.js} +1 -1
  53. package/dist/{chunk-JNXVOU6Y.js → chunk-D4OGEWLH.js} +19 -2
  54. package/dist/{chunk-R2XCLT6I.js → chunk-E3PLF7YB.js} +4 -4
  55. package/dist/{chunk-2C7CCWVX.js → chunk-F6BMJOSW.js} +1 -1
  56. package/dist/{chunk-XNCMT7YY.js → chunk-HOIGXMI7.js} +1 -1
  57. package/dist/{chunk-CVALVGA7.js → chunk-I7B2DNVU.js} +1 -1
  58. package/dist/{chunk-S3UD4V6W.js → chunk-INR3RVQ3.js} +13 -3
  59. package/dist/{chunk-52NVBNJT.js → chunk-IZVAVXHQ.js} +6 -4
  60. package/dist/{chunk-5HLTWFJ6.js → chunk-JMSB6CJT.js} +1 -1
  61. package/dist/{chunk-KYQXUGH7.js → chunk-KAJT6HPI.js} +3 -3
  62. package/dist/{chunk-VKVIAZQO.js → chunk-KLXYMPTM.js} +1 -1
  63. package/dist/{chunk-PQ4F64M2.js → chunk-L6IF4JOF.js} +3 -3
  64. package/dist/{chunk-ROQK7IN3.js → chunk-LI3C2IQY.js} +2 -2
  65. package/dist/{chunk-B234346F.js → chunk-M2JGLFFS.js} +1 -1
  66. package/dist/chunk-MY3UZO5U.js +99 -0
  67. package/dist/chunk-N6IOSZOE.js +185 -0
  68. package/dist/{chunk-DNJUSFBL.js → chunk-NYBZJ44G.js} +40 -5
  69. package/dist/{chunk-BBKNJJVX.js → chunk-OJRB5QKN.js} +6 -6
  70. package/dist/{chunk-PUDBG3GM.js → chunk-OXEF6JHD.js} +4 -4
  71. package/dist/{chunk-LEZFOTMI.js → chunk-PWNQGITG.js} +1 -1
  72. package/dist/{chunk-B76WVEDX.js → chunk-Q7CDBJXU.js} +1 -1
  73. package/dist/{chunk-KXMZMZD3.js → chunk-QSZ37ROP.js} +1 -1
  74. package/dist/{chunk-BH2SKSSK.js → chunk-R7ZETVNR.js} +1 -1
  75. package/dist/{chunk-DZURML2D.js → chunk-RLRDPZG4.js} +1 -1
  76. package/dist/{chunk-J2355HR7.js → chunk-SEIZQZEE.js} +1 -1
  77. package/dist/{chunk-V4AQBAVG.js → chunk-SJN64NJX.js} +1 -1
  78. package/dist/{chunk-B3YQANFN.js → chunk-SKEW3TQX.js} +1 -1
  79. package/dist/{chunk-L4H2Q2S4.js → chunk-SKMWPXGV.js} +500 -46
  80. package/dist/{chunk-WUNZAE7I.js → chunk-T3PRPFDY.js} +5 -5
  81. package/dist/{chunk-YYINL576.js → chunk-TVJYGZXB.js} +2 -2
  82. package/dist/{chunk-O2LEPIU6.js → chunk-U3MS6D5X.js} +1 -1
  83. package/dist/{chunk-5RUIFDTP.js → chunk-U4TMAANR.js} +33 -2
  84. package/dist/{chunk-KW2RRR7D.js → chunk-UFNBKYWT.js} +3 -3
  85. package/dist/{chunk-DVQDPI3T.js → chunk-UUTWHVSV.js} +35 -35
  86. package/dist/{chunk-X6KDKOV5.js → chunk-VQDJ6KB3.js} +3 -3
  87. package/dist/{chunk-UOAQ6QMP.js → chunk-VSGKQ3HI.js} +2 -2
  88. package/dist/{chunk-YROGUPOZ.js → chunk-WWTLAZQA.js} +25 -8
  89. package/dist/{chunk-SQRWHALT.js → chunk-WXIVUIXA.js} +2 -2
  90. package/dist/{chunk-HDRNWNVP.js → chunk-YLCSKVQQ.js} +9 -28
  91. package/dist/{chunk-JXUAXO74.js → chunk-YNJ2H2FD.js} +2 -2
  92. package/dist/{chunk-BWYJ6AAF.js → chunk-YU4222G2.js} +2 -2
  93. package/dist/{chunk-4F46VIEE.js → chunk-YU54LNC6.js} +6 -6
  94. package/dist/{chunk-EAQMWJPG.js → chunk-ZMWX5SDA.js} +8 -8
  95. package/dist/{chunk-6ADZQFVW.js → chunk-ZUKZJQGR.js} +1 -1
  96. package/dist/{reapply-6PH3FMPX.js → reapply-D6RSDYCK.js} +9 -9
  97. package/dist/src/index.d.ts +1 -0
  98. package/dist/src/index.js +22 -20
  99. package/package.json +2 -1
  100. package/dist/chunk-DANOZVZK.js +0 -307
  101. package/dist/chunk-P32LPT2L.js +0 -6
  102. package/dist/chunk-YHG74UFF.js +0 -12
@@ -6,27 +6,30 @@ import {
6
6
  readServiceExecPath,
7
7
  retryAgentCommand,
8
8
  versionManagerOf
9
- } from "../chunk-S3UD4V6W.js";
9
+ } from "../chunk-INR3RVQ3.js";
10
10
  import {
11
11
  assessCodexHookTrust,
12
12
  readCodexTrustForPusharyHooks
13
- } from "../chunk-7OS4IHGI.js";
13
+ } from "../chunk-5GIBNUBD.js";
14
14
  import {
15
15
  readMachineReadiness,
16
16
  readManagedControlEvidence
17
- } from "../chunk-4F46VIEE.js";
18
- import {
19
- CURSOR_GATE_SCRIPT
20
- } from "../chunk-P32LPT2L.js";
17
+ } from "../chunk-YU54LNC6.js";
21
18
  import {
22
19
  FX_PROFILE_REFUSALS,
23
20
  FX_PUSHARY_TOOLS_RULE,
21
+ FX_QUESTION_TOOL,
22
+ FX_SETTINGS_REFUSALS,
23
+ HERMES_PIP_PACKAGE,
24
+ HERMES_PLUGIN_NAME,
24
25
  agentProbes,
25
26
  detectAgent,
26
27
  detectAllAgents,
27
28
  fxBridgeTargetOf,
28
29
  fxPusharyEntryOf,
30
+ fxQuestionRouting,
29
31
  hasInstructionBlock,
32
+ hermesWiredByPushary,
30
33
  isDetected,
31
34
  isFxPusharyEntry,
32
35
  isPluginRegistered,
@@ -34,29 +37,32 @@ import {
34
37
  readFxFile,
35
38
  readFxProfile,
36
39
  readFxSettings,
40
+ readHermesStatus,
41
+ resolveHermesPython,
37
42
  shortenHome,
38
- vscodeSettingsTargets
39
- } from "../chunk-L4H2Q2S4.js";
40
- import "../chunk-YYINL576.js";
43
+ vscodeSettingsTargets,
44
+ workspacesShowingQuestionTool
45
+ } from "../chunk-SKMWPXGV.js";
46
+ import "../chunk-TVJYGZXB.js";
41
47
  import {
42
48
  OPENCODE_PLUGIN_PLACEHOLDER,
43
49
  openCodePluginDir,
44
50
  openCodePluginFile,
45
51
  openCodeWired
46
- } from "../chunk-B3YQANFN.js";
52
+ } from "../chunk-SKEW3TQX.js";
47
53
  import {
48
54
  compatibleConfigFile,
49
55
  compatibleInstructionsFile,
50
56
  compatibleMcpFile,
51
57
  hasCompatibleHooks,
52
58
  missingCompatibleHookEvents
53
- } from "../chunk-WUNZAE7I.js";
54
- import "../chunk-KYQXUGH7.js";
59
+ } from "../chunk-T3PRPFDY.js";
60
+ import "../chunk-KAJT6HPI.js";
55
61
  import {
56
62
  detectProviderLiveCapabilities,
57
63
  hasSpawnProvider,
58
64
  resolveControlPolicy
59
- } from "../chunk-JXUAXO74.js";
65
+ } from "../chunk-YNJ2H2FD.js";
60
66
  import {
61
67
  AUTO_UPDATE_DISABLE_ENV,
62
68
  autoUpdateOffReason,
@@ -64,16 +70,16 @@ import {
64
70
  describeAutoUpdateCheck,
65
71
  readAutoUpdateState,
66
72
  takeAutoUpdateAnnouncement
67
- } from "../chunk-BWYJ6AAF.js";
73
+ } from "../chunk-YU4222G2.js";
68
74
  import {
69
75
  readLedgerSummary
70
- } from "../chunk-2C7CCWVX.js";
76
+ } from "../chunk-F6BMJOSW.js";
71
77
  import {
72
78
  describeBridgeResolution,
73
79
  isBridgeLocator,
74
80
  liveBridgeProbe,
75
81
  resolveBridgeStub
76
- } from "../chunk-5HLTWFJ6.js";
82
+ } from "../chunk-JMSB6CJT.js";
77
83
  import {
78
84
  claudeOtherHolders,
79
85
  claudeUnprovenHolds,
@@ -90,7 +96,7 @@ import {
90
96
  geminiWired,
91
97
  holdsLong,
92
98
  pusharyHookExecutable
93
- } from "../chunk-PQ4F64M2.js";
99
+ } from "../chunk-L6IF4JOF.js";
94
100
  import {
95
101
  daemonHasRemoteProof,
96
102
  daemonServiceManagerAvailable,
@@ -99,17 +105,18 @@ import {
99
105
  readDaemonNeedsLogin,
100
106
  readDaemonStatus,
101
107
  readInstalledDaemonService
102
- } from "../chunk-73T6MSU5.js";
108
+ } from "../chunk-4S7CCOXB.js";
103
109
  import {
104
110
  GEMINI_HOOK_BINARY,
105
111
  hasGeminiHooks,
106
112
  missingGeminiHookEvents
107
- } from "../chunk-ZQ7IDOKY.js";
113
+ } from "../chunk-A6WQF7FQ.js";
108
114
  import "../chunk-XHKBHWLX.js";
109
- import "../chunk-IJ6ECPA6.js";
110
- import "../chunk-DZURML2D.js";
111
- import "../chunk-EGKXSQCY.js";
112
- import "../chunk-V6QRSU2G.js";
115
+ import "../chunk-2B4XCMH6.js";
116
+ import "../chunk-N6IOSZOE.js";
117
+ import "../chunk-RLRDPZG4.js";
118
+ import "../chunk-2XOHXZRC.js";
119
+ import "../chunk-6QZK4O36.js";
113
120
  import "../chunk-POFBE6ZY.js";
114
121
  import {
115
122
  describeReach,
@@ -118,19 +125,15 @@ import {
118
125
  reachVerdict,
119
126
  roundTripEvidence,
120
127
  verifyRoundTrip
121
- } from "../chunk-HDRNWNVP.js";
128
+ } from "../chunk-YLCSKVQQ.js";
122
129
  import "../chunk-3EGEA4KH.js";
123
- import {
124
- checkApiKey,
125
- describeKeyCheck
126
- } from "../chunk-X6KDKOV5.js";
127
130
  import "../chunk-QCGNGEGE.js";
128
131
  import {
129
132
  createIo
130
- } from "../chunk-5RUIFDTP.js";
133
+ } from "../chunk-U4TMAANR.js";
131
134
  import {
132
135
  exitOnHelpFlag
133
- } from "../chunk-2PS6QWDW.js";
136
+ } from "../chunk-6NHXKTQU.js";
134
137
  import {
135
138
  parseFlags
136
139
  } from "../chunk-GMXKITVA.js";
@@ -138,22 +141,26 @@ import {
138
141
  keyPrefix,
139
142
  readControlMode,
140
143
  readKeySource
141
- } from "../chunk-UOAQ6QMP.js";
144
+ } from "../chunk-VSGKQ3HI.js";
142
145
  import {
143
146
  callMcpTool,
144
147
  sendMcpRequest
145
- } from "../chunk-JNXVOU6Y.js";
146
- import "../chunk-KW2RRR7D.js";
148
+ } from "../chunk-D4OGEWLH.js";
149
+ import {
150
+ checkApiKey,
151
+ describeKeyCheck
152
+ } from "../chunk-VQDJ6KB3.js";
153
+ import "../chunk-UFNBKYWT.js";
147
154
  import {
148
155
  getMachineId
149
- } from "../chunk-XNCMT7YY.js";
156
+ } from "../chunk-HOIGXMI7.js";
150
157
  import {
151
158
  UsageError
152
159
  } from "../chunk-7QLSKOSU.js";
153
160
  import {
154
161
  EXIT
155
162
  } from "../chunk-KZERVKTD.js";
156
- import "../chunk-ROQK7IN3.js";
163
+ import "../chunk-LI3C2IQY.js";
157
164
  import {
158
165
  CODEX_HOOK_EVENTS,
159
166
  autoUpdateState,
@@ -176,19 +183,21 @@ import {
176
183
  geminiMd,
177
184
  geminiSettings,
178
185
  hasCodexHooks,
186
+ hermesConfig,
187
+ hermesConfigReceipt,
179
188
  missingCodexHookEvents,
180
189
  pusharyConfigFile,
181
190
  readCodexMcpAuth,
182
191
  resolvePathBinary,
183
192
  vscodePluginDir
184
- } from "../chunk-DNJUSFBL.js";
193
+ } from "../chunk-NYBZJ44G.js";
185
194
  import "../chunk-T7E75EKA.js";
186
195
  import {
187
196
  getBaseUrl
188
- } from "../chunk-V4AQBAVG.js";
197
+ } from "../chunk-SJN64NJX.js";
189
198
  import {
190
199
  NPX_LATEST_COMMAND
191
- } from "../chunk-B3UXMSMW.js";
200
+ } from "../chunk-65RN6ZCO.js";
192
201
  import {
193
202
  AGENTS,
194
203
  CURSOR_GATE_EVENTS,
@@ -202,7 +211,7 @@ import {
202
211
  hookCompatibleProfile,
203
212
  isHookActivationReport,
204
213
  isNewerVersion
205
- } from "../chunk-YROGUPOZ.js";
214
+ } from "../chunk-WWTLAZQA.js";
206
215
 
207
216
  // bin/pushary-doctor.ts
208
217
  import { existsSync, readFileSync, writeFileSync } from "fs";
@@ -367,6 +376,9 @@ function inertRegistrations(configs, resolves) {
367
376
  var describeInertRegistration = ({ named }) => `hooks here are registered for "${named}", which this CLI has no profile for, so every one of them stands aside`;
368
377
  var inertRegistrationRemedy = () => "Upgrade with npx @pushary/agent-hooks@latest upgrade, or re-run setup to rewrite them for an agent this version knows";
369
378
 
379
+ // src/hooks-spec.ts
380
+ var CURSOR_GATE_SCRIPT = "pushary-gate.mjs";
381
+
370
382
  // src/diagnostics/activation.ts
371
383
  var readHookActivation = async (apiKey, agentType, target, deps = {}) => {
372
384
  const machineId = deps.machineId ?? getMachineId();
@@ -455,9 +467,31 @@ var CLAUDE_SETTINGS = claudeSettings();
455
467
  var registeredConfigs = () => [CLAUDE_SETTINGS, codexHooksJson(), ...HOOK_COMPATIBLE_PROFILES.map((profile) => compatibleConfigFile(profile))].filter(existsSync).map((file) => ({ file, contents: readFileSync(file, "utf-8") }));
456
468
  var SKILL_PATH = join(claudeSkillDir(), "SKILL.md");
457
469
  var SHELL_FILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile"].map((f) => join(homedir2(), f));
458
- var fxAllowsPusharyTools = () => {
459
- const read = readFxFile(fxSettings(), readFxSettings);
460
- return read.kind === "settings" && pusharyToolsAllowed(read.settings);
470
+ var reportFxQuestionRouting = (routing) => {
471
+ if (routing === "routed") {
472
+ check(true, "fx: questions go through Pushary", `${FX_QUESTION_TOOL} is off in ${fxSettings()}`);
473
+ return;
474
+ }
475
+ console.log(` ${warn} fx: questions can still stop in the terminal ${dim(`(${FX_QUESTION_ROUTING_WARNINGS[routing]})`)}`);
476
+ };
477
+ var reportHermesStatus = (status) => {
478
+ const config = hermesConfig();
479
+ check(status.pluginInstalled, "Hermes: plugin installed", status.pluginInstalled ? HERMES_PIP_PACKAGE : `${HERMES_PIP_PACKAGE} is not installed in Hermes' Python \u2014 run ${retryAgentCommand("hermes")}`);
480
+ check(status.pluginEnabled, "Hermes: plugin enabled", status.pluginEnabled ? config : `"${HERMES_PLUGIN_NAME}" is missing from plugins.enabled in ${config} \u2014 run ${retryAgentCommand("hermes")}`);
481
+ if (status.approvalsRouted) check(true, "Hermes: approvals go through Pushary", `security.approval.transport in ${config}`);
482
+ else console.log(` ${warn} Hermes: approvals stay in the terminal ${dim(`(security.approval.transport is not "pushary" in ${config})`)}`);
483
+ if (status.questionsRouted) check(true, "Hermes: questions go through Pushary", `clarify is off in ${config}`);
484
+ else console.log(` ${warn} Hermes: questions can stop in the terminal ${dim(`(clarify is not in agent.disabled_toolsets in ${config})`)}`);
485
+ };
486
+ var fxSettingsProblem = (read) => {
487
+ if (read.kind === "missing") return `${fxSettings()} is missing, so fx runs with no Pushary rules; re-run ${retryAgentCommand("fx")}`;
488
+ if (read.kind === "unreadable") return `${fxSettings()} could not be read`;
489
+ if (read.kind === "refused") return `${fxSettings()} ${FX_SETTINGS_REFUSALS[read.reason]}`;
490
+ return null;
491
+ };
492
+ var FX_QUESTION_ROUTING_WARNINGS = {
493
+ "full-access": "full-access mode ignores permission rules, so fx's terminal question tool stays on; its instructions ask it to use Pushary instead",
494
+ overridden: `a rule in ${fxSettings()} keeps ${FX_QUESTION_TOOL} on; make "${FX_QUESTION_TOOL}": "deny" the last rule that matches it`
461
495
  };
462
496
  var fxBridgeFound = (target) => target.includes("/") ? existsSync(target) : resolvePathBinary(target) !== void 0;
463
497
  var readJson = (path) => {
@@ -1088,14 +1122,36 @@ var main = async () => {
1088
1122
  const found = fxBridgeFound(bridge);
1089
1123
  check(found, "fx: bridge binary resolves", found ? bridge : `${bridge} is not installed or not on PATH \u2014 re-run ${retryAgentCommand("fx")}`);
1090
1124
  }
1091
- if (!fxAllowsPusharyTools()) {
1125
+ const fxSettingsRead = readFxFile(fxSettings(), readFxSettings);
1126
+ const settingsProblem = fxSettingsProblem(fxSettingsRead);
1127
+ const fxSettings2 = fxSettingsRead.kind === "settings" ? fxSettingsRead.settings : {};
1128
+ if (settingsProblem) {
1129
+ console.log(` ${warn} fx: Pushary tools are not auto-allowed and questions can still stop in the terminal ${dim(`(${settingsProblem})`)}`);
1130
+ } else if (!pusharyToolsAllowed(fxSettings2)) {
1092
1131
  console.log(` ${warn} fx: Pushary tools are not auto-allowed ${dim(`(fx will review or prompt for each call; add "${FX_PUSHARY_TOOLS_RULE}": "allow" to permission in ${fxSettings()})`)}`);
1093
1132
  }
1133
+ const questionRouting = fxQuestionRouting(fxSettings2, process.env);
1134
+ if (settingsProblem === null) reportFxQuestionRouting(questionRouting);
1135
+ const workspacesShowingQuestions = workspacesShowingQuestionTool(fxSettings2);
1136
+ if (workspacesShowingQuestions.length > 0) {
1137
+ console.log(` ${warn} fx: ${workspacesShowingQuestions.length} workspace(s) replace the global rules and keep ${FX_QUESTION_TOOL} on ${dim(`(add "${FX_QUESTION_TOOL}": "deny" to their permission rules in ${fxSettings()})`)}`);
1138
+ }
1094
1139
  } else if (fxProfile.kind === "refused" && installed("fx")) {
1095
1140
  check(false, "fx: MCP profile", `${fxMcpProfile()} ${FX_PROFILE_REFUSALS[fxProfile.reason]} \u2014 fix it, then run ${retryAgentCommand("fx")}`);
1096
1141
  } else {
1097
1142
  skipped("fx", installed("fx") ? "installed, but Pushary is not set up for it" : "not installed");
1098
1143
  }
1144
+ const hermesPython = resolveHermesPython();
1145
+ const hermesStatus = hermesPython ? readHermesStatus(hermesPython) : null;
1146
+ const hermesSetupRecorded = existsSync(hermesConfigReceipt());
1147
+ if (hermesStatus && hermesWiredByPushary(hermesStatus, hermesSetupRecorded)) {
1148
+ checking("Hermes");
1149
+ reportHermesStatus(hermesStatus);
1150
+ } else if (hermesPython && hermesStatus === null && hermesSetupRecorded) {
1151
+ check(false, "Hermes: config readable", `${hermesConfig()} could not be read with Hermes' Python \u2014 run ${retryAgentCommand("hermes")}`);
1152
+ } else {
1153
+ skipped("Hermes", installed("hermes") ? "installed, but Pushary is not set up for it" : "not installed");
1154
+ }
1099
1155
  if (bridgeStub) {
1100
1156
  const resolution = resolveBridgeStub(bridgeStub, liveBridgeProbe());
1101
1157
  check(resolution.kind === "bundle", "Mac app behind pushary-bridge", describeBridgeResolution(resolution));
@@ -1,47 +1,52 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  readHookInput
4
- } from "../chunk-UC65FJJT.js";
4
+ } from "../chunk-3RO2UWJQ.js";
5
5
  import {
6
+ announceSubscriptionRequired,
6
7
  isDeferAnswer
7
- } from "../chunk-YHG74UFF.js";
8
- import "../chunk-EAQMWJPG.js";
8
+ } from "../chunk-5OP5MQI7.js";
9
+ import "../chunk-ZMWX5SDA.js";
9
10
  import "../chunk-SGZJ5LYH.js";
10
- import "../chunk-R2XCLT6I.js";
11
- import "../chunk-CVALVGA7.js";
12
- import "../chunk-5HLTWFJ6.js";
13
- import "../chunk-PQ4F64M2.js";
14
- import "../chunk-73T6MSU5.js";
15
- import "../chunk-ZQ7IDOKY.js";
16
- import "../chunk-VKVIAZQO.js";
17
- import "../chunk-BH2SKSSK.js";
18
- import "../chunk-KXMZMZD3.js";
19
- import "../chunk-B76WVEDX.js";
11
+ import "../chunk-E3PLF7YB.js";
12
+ import "../chunk-I7B2DNVU.js";
13
+ import "../chunk-JMSB6CJT.js";
14
+ import "../chunk-L6IF4JOF.js";
15
+ import "../chunk-4S7CCOXB.js";
16
+ import "../chunk-A6WQF7FQ.js";
17
+ import "../chunk-KLXYMPTM.js";
18
+ import "../chunk-R7ZETVNR.js";
19
+ import "../chunk-QSZ37ROP.js";
20
+ import "../chunk-Q7CDBJXU.js";
20
21
  import "../chunk-XHKBHWLX.js";
21
- import "../chunk-DZURML2D.js";
22
+ import "../chunk-N6IOSZOE.js";
23
+ import "../chunk-RLRDPZG4.js";
22
24
  import {
23
25
  askUser,
24
26
  isDecisionStopped,
25
27
  waitForQuestion
26
- } from "../chunk-EGKXSQCY.js";
27
- import "../chunk-V6QRSU2G.js";
28
+ } from "../chunk-2XOHXZRC.js";
29
+ import "../chunk-6QZK4O36.js";
28
30
  import "../chunk-POFBE6ZY.js";
29
31
  import "../chunk-GMXKITVA.js";
30
- import "../chunk-UOAQ6QMP.js";
31
- import "../chunk-JNXVOU6Y.js";
32
- import "../chunk-KW2RRR7D.js";
32
+ import "../chunk-VSGKQ3HI.js";
33
+ import {
34
+ SubscriptionRequiredError
35
+ } from "../chunk-D4OGEWLH.js";
36
+ import "../chunk-VQDJ6KB3.js";
37
+ import "../chunk-UFNBKYWT.js";
33
38
  import {
34
39
  getMachineId
35
- } from "../chunk-XNCMT7YY.js";
40
+ } from "../chunk-HOIGXMI7.js";
36
41
  import "../chunk-7QLSKOSU.js";
37
42
  import "../chunk-KZERVKTD.js";
38
- import "../chunk-ROQK7IN3.js";
39
- import "../chunk-DNJUSFBL.js";
43
+ import "../chunk-LI3C2IQY.js";
44
+ import "../chunk-NYBZJ44G.js";
40
45
  import "../chunk-T7E75EKA.js";
41
46
  import {
42
47
  getApiKey
43
- } from "../chunk-V4AQBAVG.js";
44
- import "../chunk-B3UXMSMW.js";
48
+ } from "../chunk-SJN64NJX.js";
49
+ import "../chunk-65RN6ZCO.js";
45
50
  import {
46
51
  ELICITATION_ANSWERABLE_MODE,
47
52
  effectiveWaitSeconds,
@@ -52,7 +57,7 @@ import {
52
57
  planElicitationAsk,
53
58
  readElicitationFields,
54
59
  renderElicitationOutput
55
- } from "../chunk-YROGUPOZ.js";
60
+ } from "../chunk-WWTLAZQA.js";
56
61
 
57
62
  // bin/pushary-elicitation-hook.ts
58
63
  import { basename } from "path";
@@ -105,7 +110,11 @@ var main = async () => {
105
110
  let created;
106
111
  try {
107
112
  created = await askUser(apiKey, { ...common, ...prompt });
108
- } catch {
113
+ } catch (error) {
114
+ if (error instanceof SubscriptionRequiredError) {
115
+ announceSubscriptionRequired(error.upgradeUrl, input.session_id);
116
+ return;
117
+ }
109
118
  process.stdout.write(renderElicitationOutput(input.hook_event_name ?? "Elicitation", "cancel") ?? "");
110
119
  return;
111
120
  }
@@ -5,37 +5,37 @@ import {
5
5
  postLiveSession,
6
6
  postLiveSessionUntilAccepted,
7
7
  startLiveSessionHeartbeat
8
- } from "../chunk-SQRWHALT.js";
8
+ } from "../chunk-WXIVUIXA.js";
9
9
  import {
10
10
  SESSION_IDLE_TIMEOUT_MS,
11
11
  describeIdleWindow,
12
12
  idleDeadlinePassed,
13
13
  startProcessOwnership,
14
14
  withSpawnProcessOwnership
15
- } from "../chunk-LEZFOTMI.js";
16
- import "../chunk-BH2SKSSK.js";
17
- import "../chunk-KXMZMZD3.js";
15
+ } from "../chunk-PWNQGITG.js";
16
+ import "../chunk-R7ZETVNR.js";
17
+ import "../chunk-QSZ37ROP.js";
18
18
  import {
19
19
  transcriptsEnabled
20
- } from "../chunk-B76WVEDX.js";
20
+ } from "../chunk-Q7CDBJXU.js";
21
21
  import {
22
22
  spawnClaude
23
23
  } from "../chunk-XHKBHWLX.js";
24
- import "../chunk-UOAQ6QMP.js";
24
+ import "../chunk-VSGKQ3HI.js";
25
25
  import {
26
26
  getMachineId
27
- } from "../chunk-XNCMT7YY.js";
28
- import "../chunk-ROQK7IN3.js";
27
+ } from "../chunk-HOIGXMI7.js";
28
+ import "../chunk-LI3C2IQY.js";
29
29
  import {
30
30
  resolveBinary
31
- } from "../chunk-DNJUSFBL.js";
31
+ } from "../chunk-NYBZJ44G.js";
32
32
  import "../chunk-T7E75EKA.js";
33
33
  import {
34
34
  getApiKey,
35
35
  getBaseUrl
36
- } from "../chunk-V4AQBAVG.js";
37
- import "../chunk-B3UXMSMW.js";
38
- import "../chunk-YROGUPOZ.js";
36
+ } from "../chunk-SJN64NJX.js";
37
+ import "../chunk-65RN6ZCO.js";
38
+ import "../chunk-WWTLAZQA.js";
39
39
 
40
40
  // bin/pushary-gemini-bridge.ts
41
41
  import { existsSync } from "fs";
@@ -1,33 +1,33 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  triggerAutoUpdate
4
- } from "../chunk-BWYJ6AAF.js";
4
+ } from "../chunk-YU4222G2.js";
5
5
  import {
6
6
  isGatingMoment,
7
7
  recordKeylessMoment
8
- } from "../chunk-2C7CCWVX.js";
8
+ } from "../chunk-F6BMJOSW.js";
9
9
  import {
10
10
  readHookInput
11
- } from "../chunk-UC65FJJT.js";
11
+ } from "../chunk-3RO2UWJQ.js";
12
12
  import {
13
+ announceSubscriptionRequired,
13
14
  denyReasonFrom,
14
15
  isDeferAnswer
15
- } from "../chunk-YHG74UFF.js";
16
- import "../chunk-EAQMWJPG.js";
16
+ } from "../chunk-5OP5MQI7.js";
17
+ import "../chunk-ZMWX5SDA.js";
17
18
  import "../chunk-SGZJ5LYH.js";
18
- import "../chunk-R2XCLT6I.js";
19
- import "../chunk-CVALVGA7.js";
20
- import "../chunk-5HLTWFJ6.js";
21
- import "../chunk-PQ4F64M2.js";
22
- import "../chunk-73T6MSU5.js";
23
- import "../chunk-ZQ7IDOKY.js";
24
- import "../chunk-VKVIAZQO.js";
25
- import "../chunk-BH2SKSSK.js";
26
- import "../chunk-KXMZMZD3.js";
27
- import "../chunk-B76WVEDX.js";
19
+ import "../chunk-E3PLF7YB.js";
20
+ import "../chunk-I7B2DNVU.js";
21
+ import "../chunk-JMSB6CJT.js";
22
+ import "../chunk-L6IF4JOF.js";
23
+ import "../chunk-4S7CCOXB.js";
24
+ import "../chunk-A6WQF7FQ.js";
25
+ import "../chunk-KLXYMPTM.js";
26
+ import "../chunk-R7ZETVNR.js";
27
+ import "../chunk-QSZ37ROP.js";
28
+ import "../chunk-Q7CDBJXU.js";
28
29
  import "../chunk-XHKBHWLX.js";
29
30
  import {
30
- DEFAULT_SESSION,
31
31
  UNNAMED_ACTION,
32
32
  deriveActionBody,
33
33
  deriveBlocker,
@@ -45,38 +45,45 @@ import {
45
45
  repoKeyFor,
46
46
  reportEvent,
47
47
  scopePathFor
48
- } from "../chunk-IJ6ECPA6.js";
49
- import "../chunk-DZURML2D.js";
48
+ } from "../chunk-2B4XCMH6.js";
49
+ import {
50
+ DEFAULT_SESSION
51
+ } from "../chunk-N6IOSZOE.js";
52
+ import "../chunk-RLRDPZG4.js";
50
53
  import {
51
54
  DECISION_STOP_REASON,
55
+ UNVERIFIABLE_APPROVAL_REASON,
52
56
  askUser,
53
57
  isDecisionStopped,
54
58
  isLocalQuestionHandoff,
55
59
  sendNotification,
56
60
  waitForQuestion
57
- } from "../chunk-EGKXSQCY.js";
61
+ } from "../chunk-2XOHXZRC.js";
58
62
  import {
59
63
  exitAfterClientReports
60
- } from "../chunk-V6QRSU2G.js";
64
+ } from "../chunk-6QZK4O36.js";
61
65
  import "../chunk-POFBE6ZY.js";
62
66
  import "../chunk-GMXKITVA.js";
63
- import "../chunk-UOAQ6QMP.js";
64
- import "../chunk-JNXVOU6Y.js";
65
- import "../chunk-KW2RRR7D.js";
67
+ import "../chunk-VSGKQ3HI.js";
68
+ import {
69
+ SubscriptionRequiredError
70
+ } from "../chunk-D4OGEWLH.js";
71
+ import "../chunk-VQDJ6KB3.js";
72
+ import "../chunk-UFNBKYWT.js";
66
73
  import {
67
74
  getMachineId
68
- } from "../chunk-XNCMT7YY.js";
75
+ } from "../chunk-HOIGXMI7.js";
69
76
  import "../chunk-7QLSKOSU.js";
70
77
  import {
71
78
  EXIT
72
79
  } from "../chunk-KZERVKTD.js";
73
- import "../chunk-ROQK7IN3.js";
74
- import "../chunk-DNJUSFBL.js";
80
+ import "../chunk-LI3C2IQY.js";
81
+ import "../chunk-NYBZJ44G.js";
75
82
  import "../chunk-T7E75EKA.js";
76
83
  import {
77
84
  getApiKey
78
- } from "../chunk-V4AQBAVG.js";
79
- import "../chunk-B3UXMSMW.js";
85
+ } from "../chunk-SJN64NJX.js";
86
+ import "../chunk-65RN6ZCO.js";
80
87
  import {
81
88
  DECISION_LINE_MAX,
82
89
  KILL_REASON,
@@ -85,7 +92,7 @@ import {
85
92
  hookWaitClamped,
86
93
  hookWaitDeadline,
87
94
  resolveGate
88
- } from "../chunk-YROGUPOZ.js";
95
+ } from "../chunk-WWTLAZQA.js";
89
96
 
90
97
  // bin/pushary-gemini-hook.ts
91
98
  import { basename } from "path";
@@ -125,7 +132,9 @@ var NO_LOCAL_INPUT = "This unattended Gemini session has no local approval input
125
132
  var NO_ANSWER_IN_TIME = "No answer from your phone in time, and this unattended Gemini session has no local approval input. Retry when you can answer on your phone.";
126
133
  var HANDLED_ON_MACHINE = "You chose to handle this on your machine, but this unattended Gemini session has no local approval input. Use an interactive session.";
127
134
  var NO_DEVICE = "No phone or other notification channel is connected to Pushary, and this unattended Gemini session has no local approval input. Connect one in Pushary, then retry.";
135
+ var SUBSCRIPTION_REQUIRED = "Your Pushary workspace has no active subscription, so approvals cannot reach your phone, and this unattended Gemini session has no local approval input. Renew Pushary, then retry.";
128
136
  var geminiLocalHandoff = (bridge, reason = NO_LOCAL_INPUT) => geminiOwnsLifecycle(bridge) ? geminiPass() : geminiDeny(reason);
137
+ var geminiSubscriptionRequiredDecision = (bridge) => geminiLocalHandoff(bridge, SUBSCRIPTION_REQUIRED);
129
138
  var geminiPushOnlyHandoff = (askStatus, bridge) => askStatus === "notified" || askStatus === "terminal" ? geminiLocalHandoff(bridge) : geminiPass();
130
139
  var fromPhoneAnswer = (answer) => answer.value === "yes" ? geminiAllow() : geminiDeny(denyReasonFrom(answer.value, answer.note));
131
140
  var geminiPushFirstDecision = (pushed, bridge) => {
@@ -137,7 +146,7 @@ var geminiPushFirstDecision = (pushed, bridge) => {
137
146
  return geminiLocalHandoff(bridge, NO_ANSWER_IN_TIME);
138
147
  };
139
148
  var geminiPushOnlyDecision = (pushed, timeoutAction, bridge) => {
140
- if (!pushed) return geminiDeny("Pushary could not create a verifiable approval. Retry the action.");
149
+ if (!pushed) return geminiDeny(UNVERIFIABLE_APPROVAL_REASON);
141
150
  const { answer, localHandoff, clampCut, askStatus } = pushed;
142
151
  if (isDecisionStopped(answer)) return geminiDeny(DECISION_STOP_REASON);
143
152
  if (localHandoff) return geminiPushOnlyHandoff(askStatus, bridge);
@@ -205,11 +214,16 @@ var notifyApprovalNeeded = async (apiKey, input, lookup) => {
205
214
  } catch {
206
215
  }
207
216
  };
217
+ var geminiStepsAside = (error, input) => {
218
+ announceSubscriptionRequired(error.upgradeUrl, input.session_id);
219
+ return geminiSubscriptionRequiredDecision(process.env.PUSHARY_GEMINI_BRIDGE);
220
+ };
208
221
  var handlePushOnly = async (apiKey, input, lookup, timeoutSeconds, timeoutAction) => {
209
222
  let pushed;
210
223
  try {
211
224
  pushed = await pushQuestion(apiKey, input, lookup, effectiveWaitSeconds(timeoutAction, timeoutSeconds, "gemini"), "push_only");
212
- } catch {
225
+ } catch (error) {
226
+ if (error instanceof SubscriptionRequiredError) return geminiStepsAside(error, input);
213
227
  pushed = void 0;
214
228
  }
215
229
  return geminiPushOnlyDecision(pushed, timeoutAction, process.env.PUSHARY_GEMINI_BRIDGE);
@@ -218,7 +232,8 @@ var handlePushFirst = async (apiKey, input, lookup, pushFirstSeconds) => {
218
232
  let pushed;
219
233
  try {
220
234
  pushed = await pushQuestion(apiKey, input, lookup, pushFirstSeconds, "push_first", 1500);
221
- } catch {
235
+ } catch (error) {
236
+ if (error instanceof SubscriptionRequiredError) return geminiStepsAside(error, input);
222
237
  pushed = void 0;
223
238
  }
224
239
  return geminiPushFirstDecision(pushed, process.env.PUSHARY_GEMINI_BRIDGE);