pushary 1.9.111 → 1.9.113

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 (129) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/dist/{api-AESRTYYT.js → api-PCAXOVGM.js} +11 -11
  3. package/dist/bin/pushary-audit.js +3 -3
  4. package/dist/bin/pushary-bell-hook.js +27 -27
  5. package/dist/bin/pushary-bell.js +10 -10
  6. package/dist/bin/pushary-claude.js +25 -25
  7. package/dist/bin/pushary-clean.js +34 -34
  8. package/dist/bin/pushary-codex-bridge.js +21 -21
  9. package/dist/bin/pushary-codex-hook.js +32 -32
  10. package/dist/bin/pushary-codex-session.js +8 -8
  11. package/dist/bin/pushary-codex.js +15 -15
  12. package/dist/bin/pushary-connect.js +28 -28
  13. package/dist/bin/pushary-cowork.js +5 -5
  14. package/dist/bin/pushary-daemon.js +66 -484
  15. package/dist/bin/pushary-disconnect.js +27 -27
  16. package/dist/bin/pushary-display-hook.js +17 -17
  17. package/dist/bin/pushary-doctor.js +42 -42
  18. package/dist/bin/pushary-elicitation-hook.js +27 -27
  19. package/dist/bin/pushary-gemini-bridge.js +15 -15
  20. package/dist/bin/pushary-gemini-hook.js +29 -29
  21. package/dist/bin/pushary-hook.js +32 -32
  22. package/dist/bin/pushary-login.js +21 -21
  23. package/dist/bin/pushary-logout.js +26 -26
  24. package/dist/bin/pushary-mcp.js +12 -12
  25. package/dist/bin/pushary-mode.js +15 -15
  26. package/dist/bin/pushary-notification-hook.js +26 -26
  27. package/dist/bin/pushary-opencode-hook.js +28 -28
  28. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  29. package/dist/bin/pushary-permission-hook.js +32 -32
  30. package/dist/bin/pushary-post-hook.js +26 -26
  31. package/dist/bin/pushary-prompt-hook.js +26 -26
  32. package/dist/bin/pushary-session-end-hook.js +26 -26
  33. package/dist/bin/pushary-session-start-hook.js +35 -35
  34. package/dist/bin/pushary-setup.js +61 -47
  35. package/dist/bin/pushary-stats.js +5 -5
  36. package/dist/bin/pushary-status.js +32 -32
  37. package/dist/bin/pushary-stop-hook.js +26 -26
  38. package/dist/bin/pushary-stopfailure-hook.js +26 -26
  39. package/dist/bin/pushary-suggestions.js +15 -15
  40. package/dist/bin/pushary-transcript-register.js +17 -17
  41. package/dist/bin/pushary-transcripts.js +25 -25
  42. package/dist/bin/pushary-upgrade.js +40 -40
  43. package/dist/bin/pushary-wait.js +15 -15
  44. package/dist/bin/pushary.js +7 -7
  45. package/dist/{chunk-NUU2JVOG.js → chunk-22OATDEL.js} +3 -3
  46. package/dist/{chunk-YBQF7DCL.js → chunk-233KC6DP.js} +1 -1
  47. package/dist/{chunk-2MOWY5QL.js → chunk-24M7PB2Y.js} +5 -5
  48. package/dist/{chunk-NHDTSA7V.js → chunk-3D2J3T2M.js} +1 -1
  49. package/dist/{chunk-KLCT2YQD.js → chunk-3LJWADU2.js} +6 -6
  50. package/dist/{chunk-SSW4QRGU.js → chunk-3ZU77DJH.js} +6 -6
  51. package/dist/{chunk-RFFIAX33.js → chunk-44HW5T6P.js} +2 -2
  52. package/dist/{chunk-TILEGY4M.js → chunk-44O6GG4I.js} +6 -6
  53. package/dist/{chunk-YNTB3MIQ.js → chunk-4EFZANH3.js} +1 -1
  54. package/dist/{chunk-NVPCETJ3.js → chunk-4I6FWGZ5.js} +1 -1
  55. package/dist/{chunk-O2MZQPP4.js → chunk-53ROMSOB.js} +3 -3
  56. package/dist/{chunk-G42VQNBC.js → chunk-5J2OGCUA.js} +1 -1
  57. package/dist/{chunk-54DPX27B.js → chunk-5SUTYXCT.js} +1 -1
  58. package/dist/{chunk-M73Q37LC.js → chunk-6E2D22Y5.js} +2 -2
  59. package/dist/{chunk-G2TTGQ5A.js → chunk-AR3VX4UQ.js} +10 -10
  60. package/dist/{chunk-5EEW4WIS.js → chunk-B5NKPU2E.js} +5 -5
  61. package/dist/{chunk-DEHWKUKF.js → chunk-BMZFL3HF.js} +4 -4
  62. package/dist/{chunk-VA4OGALQ.js → chunk-BWSXWX6T.js} +2 -2
  63. package/dist/{chunk-YI5I2TF3.js → chunk-BYL7RNOM.js} +3 -3
  64. package/dist/{chunk-XJ4PMNCR.js → chunk-CG5SK6NF.js} +1 -1
  65. package/dist/{chunk-YILMWIZN.js → chunk-D3XNQAQO.js} +2 -2
  66. package/dist/{chunk-BM32JPXJ.js → chunk-DLCECUKY.js} +7 -7
  67. package/dist/{chunk-PTBWLU4G.js → chunk-DSXBMC2N.js} +5 -5
  68. package/dist/{chunk-76ATPJN2.js → chunk-E3A77P52.js} +4 -4
  69. package/dist/{chunk-SDQQ43FT.js → chunk-F5TQ6TCH.js} +1 -1
  70. package/dist/{chunk-WO46WX65.js → chunk-FLRVTAV4.js} +2 -2
  71. package/dist/{chunk-FYVRA5GN.js → chunk-FQSFN5ZE.js} +1 -1
  72. package/dist/{chunk-3AX5BKYN.js → chunk-GBT74TNN.js} +2 -2
  73. package/dist/chunk-GGBGKQIZ.js +454 -0
  74. package/dist/{chunk-YXFLZ2LO.js → chunk-GI3266RE.js} +2 -2
  75. package/dist/{chunk-X5P3IO37.js → chunk-GNP6I5XM.js} +2 -2
  76. package/dist/{chunk-R3KDA7JB.js → chunk-GQFT3QTC.js} +15 -3
  77. package/dist/{chunk-O76PTPKP.js → chunk-GSJUGW3A.js} +1 -1
  78. package/dist/{chunk-OECCPPO6.js → chunk-HJ566HEV.js} +3 -3
  79. package/dist/{chunk-7HDO5W4C.js → chunk-I7HSE5LD.js} +11 -11
  80. package/dist/{chunk-QVGE26SZ.js → chunk-IWUYKDDW.js} +4 -4
  81. package/dist/{chunk-KHWNW4AS.js → chunk-JCHF4VR3.js} +1 -1
  82. package/dist/{chunk-LTVILMEZ.js → chunk-JRW5HK32.js} +2 -2
  83. package/dist/{chunk-KICQRZAT.js → chunk-JXN4SH6M.js} +1 -1
  84. package/dist/{chunk-GXTW3W45.js → chunk-JXNDO7FB.js} +1 -1
  85. package/dist/{chunk-UN2QALQO.js → chunk-KB2EEK5T.js} +5 -5
  86. package/dist/{chunk-262UYDKT.js → chunk-KDTTCR3E.js} +3 -3
  87. package/dist/{chunk-DZE26BID.js → chunk-KPCVIH52.js} +22 -1
  88. package/dist/{chunk-RBM2ROSY.js → chunk-LUBECFXJ.js} +1 -1
  89. package/dist/{chunk-4M6VUUTX.js → chunk-MDEXA6JD.js} +3 -3
  90. package/dist/{chunk-Y3N7LIFV.js → chunk-MPG4HYQ6.js} +3 -3
  91. package/dist/{chunk-75UJ7W6H.js → chunk-NG2EWF32.js} +2 -2
  92. package/dist/{chunk-NZZFIIH6.js → chunk-NK5XT4RS.js} +4 -4
  93. package/dist/{chunk-PYAPWXVP.js → chunk-NPG4WCIM.js} +1 -1
  94. package/dist/{chunk-AW7IJ56H.js → chunk-O5VJGP6H.js} +4 -4
  95. package/dist/{chunk-RUORT3DE.js → chunk-OJGHJIFQ.js} +5 -5
  96. package/dist/{chunk-56ANL3UO.js → chunk-OR5SWH44.js} +10 -10
  97. package/dist/{chunk-FE7HSLTK.js → chunk-P4PLDBZK.js} +5 -5
  98. package/dist/{chunk-4AKZALX4.js → chunk-PU2KHDRD.js} +22 -19
  99. package/dist/{chunk-YQMARTNQ.js → chunk-Q4VB3DIL.js} +2 -2
  100. package/dist/{chunk-QQMT2JIC.js → chunk-RIBCPWOB.js} +3 -3
  101. package/dist/{chunk-PCFIYMK4.js → chunk-RLBTKTOK.js} +2 -2
  102. package/dist/{chunk-CIT4NO5H.js → chunk-SI7EFQEU.js} +34 -13
  103. package/dist/{chunk-X2XXKXC5.js → chunk-T2N7MEO3.js} +3 -3
  104. package/dist/{chunk-Q63L3VBY.js → chunk-T5GJK54S.js} +4 -4
  105. package/dist/{chunk-37F75NBN.js → chunk-TAGLGMA6.js} +2 -2
  106. package/dist/{chunk-N2VH44GL.js → chunk-U35OB2HQ.js} +6 -6
  107. package/dist/{chunk-LUFKWK7N.js → chunk-UMR6UQZ4.js} +3 -3
  108. package/dist/{chunk-LDE7L7XO.js → chunk-WGK2BIX6.js} +4 -4
  109. package/dist/{chunk-EPMIBLCE.js → chunk-WUREJCUJ.js} +5 -5
  110. package/dist/{chunk-BH5WEDQ4.js → chunk-XL6DDWWT.js} +1 -1
  111. package/dist/{chunk-5RVL2CQK.js → chunk-XQFHB2EK.js} +3 -3
  112. package/dist/{chunk-ZLLQO4RU.js → chunk-YM5OM2CI.js} +6 -6
  113. package/dist/{chunk-LMECI62A.js → chunk-Z2QWM27R.js} +6 -6
  114. package/dist/{chunk-YHHWO4IU.js → chunk-ZUZ4RXM7.js} +1 -1
  115. package/dist/{codex-app-cards-switch-SXY732CY.js → codex-app-cards-switch-UI2LQQ6C.js} +11 -11
  116. package/dist/{codex-card-routing-K5FNOTBK.js → codex-card-routing-IOVURY45.js} +2 -2
  117. package/dist/{codex-desktop-launch-SMWGCLWW.js → codex-desktop-launch-GAXMK6IM.js} +1 -1
  118. package/dist/{codex-session-launch-MDMNYCCG.js → codex-session-launch-FYXRCD3I.js} +18 -18
  119. package/dist/{config-3R7UVC67.js → config-WOATWPOD.js} +3 -3
  120. package/dist/{global-upgrade-2BXXJQHR.js → global-upgrade-LDIMKAPF.js} +9 -9
  121. package/dist/{identity-N45XKYBA.js → identity-GCRCIP45.js} +4 -4
  122. package/dist/{live-capabilities-YT7CENI2.js → live-capabilities-DPMIMA3P.js} +4 -4
  123. package/dist/{paths-A2TITMY3.js → paths-H5LP5HJB.js} +3 -3
  124. package/dist/{reapply-O4TGPUVZ.js → reapply-FBNJRZLQ.js} +28 -28
  125. package/dist/src/index.d.ts +2 -1
  126. package/dist/src/index.js +31 -31
  127. package/dist/{upgrade-lock-HYD3MFFS.js → upgrade-lock-76Z2YLIV.js} +4 -4
  128. package/dist/{usage-PTPB2XF6.js → usage-SIELH6XD.js} +3 -3
  129. package/package.json +1 -1
@@ -0,0 +1,454 @@
1
+ import {
2
+ MANAGED_CLAUDE_SETTINGS_BY_PLATFORM
3
+ } from "./chunk-6E2D22Y5.js";
4
+ import {
5
+ declinedAgentsFile,
6
+ readDeclinedAgents
7
+ } from "./chunk-BWSXWX6T.js";
8
+ import {
9
+ OPENCODE_HOOK_BINARY,
10
+ openCodeConfigDir,
11
+ openCodePluginArgv,
12
+ openCodePluginFile
13
+ } from "./chunk-KB2EEK5T.js";
14
+ import {
15
+ liveCursorGateCoverage
16
+ } from "./chunk-IWUYKDDW.js";
17
+ import {
18
+ compatibleConfigFile,
19
+ compatibleHookEvents,
20
+ grokHome,
21
+ parseConfigDocument
22
+ } from "./chunk-OJGHJIFQ.js";
23
+ import {
24
+ DEFAULT_HOOKS_KEY_PATH,
25
+ GEMINI_HOOK_BINARY,
26
+ GEMINI_HOOK_EVENTS,
27
+ hooksAt
28
+ } from "./chunk-NK5XT4RS.js";
29
+ import {
30
+ CODEX_EARLIER_APPROVAL_MATCHERS,
31
+ CODEX_HOOK_BINARY,
32
+ CODEX_HOOK_EVENTS,
33
+ NO_SPOTLIGHT,
34
+ bridgeCache,
35
+ bridgeStub,
36
+ claudeConfigDir,
37
+ claudeSettings,
38
+ claudeSettingsLocal,
39
+ codexConfigToml,
40
+ codexHome,
41
+ codexHookPositions,
42
+ codexHooksFeatureDisabled,
43
+ codexHooksJson,
44
+ codexTrustGaps,
45
+ cursorUserHooks,
46
+ geminiSettings,
47
+ hookBinaryNameOf,
48
+ hookExecutableName,
49
+ installedBridgeBundleRoots,
50
+ isBridgeLocator,
51
+ liveBridgeProbe,
52
+ macAppBridgeIsInstalled,
53
+ parseHookArgv,
54
+ parseHookCommand,
55
+ supportedClaudeEvents
56
+ } from "./chunk-RLBTKTOK.js";
57
+ import {
58
+ readRegularJsonFile,
59
+ readRegularTextFile
60
+ } from "./chunk-T5I4PKOQ.js";
61
+ import {
62
+ CURSOR_GATE_EVENTS,
63
+ CURSOR_GATE_SCRIPT,
64
+ HOOK_COMPATIBLE_PROFILES,
65
+ HOOK_WIRING_PROFILE_LENGTH,
66
+ HOOK_WIRING_REPORT_VERSION,
67
+ OPENCODE_APPROVAL_EVENT,
68
+ isRecord,
69
+ matcherMatchesEveryCall
70
+ } from "./chunk-KPCVIH52.js";
71
+
72
+ // src/hook-wiring.ts
73
+ import { createHash } from "crypto";
74
+ import { realpathSync, statSync } from "fs";
75
+ import { homedir } from "os";
76
+ import { dirname, isAbsolute, resolve } from "path";
77
+ var HOOK_WIRING_MAX_FILE_BYTES = 16 * 1024 * 1024;
78
+ var COMMAND_HOOK_TYPE = "command";
79
+ var CODEX_TRUST_GAPS_THAT_SWITCH_OFF = /* @__PURE__ */ new Set(["disabled", "asynchronous"]);
80
+ var CODEX_TRUST_GAP_UNTRUSTED = "untrusted";
81
+ var MATCHER_ALTERNATIVE_SEPARATOR = "|";
82
+ var SIMPLE_CLAUDE_CODE_MATCHER = /^[a-zA-Z0-9_|]+$/;
83
+ var TABLE_PATTERN_WILDCARD = ".*";
84
+ var TABLE_PATTERN_SAMPLE = "probe";
85
+ var UNRESTRICTED_MATCHER_PROBES = ["Bash", "Write", "Edit", "Read", "apply_patch", "run_shell_command", "mcp__probe__tool", "probe"];
86
+ var EXECUTE_BITS = 73;
87
+ var WINDOWS_PLATFORM = "win32";
88
+ var NO_EVENTS = /* @__PURE__ */ new Set();
89
+ var NO_HANDLERS = /* @__PURE__ */ new Map();
90
+ var NO_EARLIER_MATCHERS = {};
91
+ var approvalEventsOf = (definitions, binaryOf, earlierMatchers = NO_EARLIER_MATCHERS) => definitions.filter((definition) => definition.delivery === "approval").map((definition) => ({
92
+ event: definition.event,
93
+ binary: binaryOf(definition),
94
+ matcher: definition.matcher ?? null,
95
+ earlierMatchers: earlierMatchers[definition.event] ?? [],
96
+ cliOnly: definition.cliOnly === true
97
+ }));
98
+ var eventsWithBinary = (events, binary) => events.map((event) => ({ event, binary, matcher: null, earlierMatchers: [], cliOnly: false }));
99
+ var CODEX_APPROVAL_EVENTS = approvalEventsOf(CODEX_HOOK_EVENTS, () => CODEX_HOOK_BINARY, CODEX_EARLIER_APPROVAL_MATCHERS);
100
+ var hookWiringAgentOf = (target) => {
101
+ switch (target.kind) {
102
+ case "claude":
103
+ return "claude";
104
+ case "codex":
105
+ return "codex";
106
+ case "gemini":
107
+ return "gemini";
108
+ case "cursor":
109
+ return "cursor";
110
+ case "opencode":
111
+ return "opencode";
112
+ case "compatible":
113
+ return target.profile.source;
114
+ }
115
+ };
116
+ var hookWiringApprovalEvents = (target) => {
117
+ switch (target.kind) {
118
+ case "claude":
119
+ return approvalEventsOf(supportedClaudeEvents(null), (hook) => hook.binary);
120
+ case "codex":
121
+ return CODEX_APPROVAL_EVENTS;
122
+ case "gemini":
123
+ return approvalEventsOf(GEMINI_HOOK_EVENTS, () => GEMINI_HOOK_BINARY);
124
+ case "cursor":
125
+ return eventsWithBinary(CURSOR_GATE_EVENTS, hookBinaryNameOf(CURSOR_GATE_SCRIPT));
126
+ case "opencode":
127
+ return eventsWithBinary([OPENCODE_APPROVAL_EVENT], OPENCODE_HOOK_BINARY);
128
+ case "compatible":
129
+ return approvalEventsOf(compatibleHookEvents(target.profile), (hook) => hook.binary);
130
+ }
131
+ };
132
+ var configFileOf = (target) => {
133
+ switch (target.kind) {
134
+ case "claude":
135
+ case "gemini":
136
+ return target.settingsFile;
137
+ case "opencode":
138
+ return target.pluginFile;
139
+ case "codex":
140
+ case "cursor":
141
+ case "compatible":
142
+ return target.hooksFile;
143
+ }
144
+ };
145
+ var hooksKeyPathOf = (target) => target.kind === "compatible" ? target.profile.hooksKeyPath : DEFAULT_HOOKS_KEY_PATH;
146
+ var handlerTypeOf = (target) => target.kind === "cursor" ? "optional" : "required";
147
+ var hookWiringProfileOf = (machineId, configFile) => createHash("sha256").update(`${machineId}\0${resolve(configFile)}`, "utf8").digest("hex").slice(0, HOOK_WIRING_PROFILE_LENGTH);
148
+ var requiredApprovalEvents = (events, owner) => events.filter((event) => !(event.cliOnly && owner === "app")).map((event) => event.event);
149
+ var isSwitchedOff = (reading, required) => reading.switchedOff || reading.trustGaps.some((gap) => CODEX_TRUST_GAPS_THAT_SWITCH_OFF.has(gap.kind) && required.has(gap.event));
150
+ var isUntrusted = (reading, required) => reading.trustGaps.some((gap) => gap.kind === CODEX_TRUST_GAP_UNTRUSTED && required.has(gap.event));
151
+ var weakeningOf = (switchedOff, wiring) => {
152
+ if (switchedOff) return "switched_off";
153
+ if (wiring.missing.length > 0) return "events_missing";
154
+ return wiring.narrowed.length > 0 ? "matcher_narrowed" : null;
155
+ };
156
+ var guardedStateOf = (reading, required) => isUntrusted(reading, required) ? "untrusted" : "wired";
157
+ var requiredEventWiringOf = (required, wiredEvents, narrowedEvents) => ({
158
+ missing: required.filter((event) => !wiredEvents.has(event) && !narrowedEvents.has(event)),
159
+ narrowed: required.filter((event) => !wiredEvents.has(event) && narrowedEvents.has(event))
160
+ });
161
+ var hookWiringOf = (reading) => {
162
+ if (!reading.configDirExists) return null;
163
+ const base = { agent: reading.agent, profile: reading.profile };
164
+ if (reading.hooks.kind === "unreadable") {
165
+ return { ...base, state: reading.declined ? "disconnected" : "unreadable", owner: null };
166
+ }
167
+ const owner = reading.hooks.kind === "read" ? reading.hooks.owner : null;
168
+ if (reading.declined) return { ...base, state: "disconnected", owner };
169
+ const required = requiredApprovalEvents(reading.approvalEvents, owner);
170
+ const wiring = reading.hooks.kind === "read" ? requiredEventWiringOf(required, reading.hooks.wiredEvents, reading.hooks.narrowedEvents) : requiredEventWiringOf(required, NO_EVENTS, NO_EVENTS);
171
+ if (wiring.missing.length === required.length) return { ...base, state: "missing", owner };
172
+ const requiredSet = new Set(required);
173
+ const weakenedBy = weakeningOf(isSwitchedOff(reading, requiredSet), wiring);
174
+ if (weakenedBy) {
175
+ return { ...base, state: "weakened", owner, weakenedBy, ...wiring.missing.length > 0 ? { missing: wiring.missing } : {} };
176
+ }
177
+ return { ...base, state: guardedStateOf(reading, requiredSet), owner };
178
+ };
179
+ var isCommandHandler = (handler, handlerType) => handler.type === COMMAND_HOOK_TYPE || handlerType === "optional" && handler.type === void 0;
180
+ var handlerOf = (handler, matcher, handlerType) => {
181
+ if (!isCommandHandler(handler, handlerType) || typeof handler.command !== "string") return [];
182
+ const command = parseHookCommand(handler.command);
183
+ return command ? [{ raw: handler.command, command, matcher }] : [];
184
+ };
185
+ var handlersInEntry = (entry, handlerType) => {
186
+ if (!isRecord(entry)) return [];
187
+ if (!Array.isArray(entry.hooks)) return handlerOf(entry, entry.matcher, handlerType);
188
+ return entry.hooks.filter(isRecord).flatMap((handler) => handlerOf(handler, entry.matcher, handlerType));
189
+ };
190
+ var handlersOnEvent = (entries, handlerType) => Array.isArray(entries) ? entries.flatMap((entry) => handlersInEntry(entry, handlerType)) : [];
191
+ var handlersByEventIn = (hooks, handlerType) => new Map(isRecord(hooks) ? Object.entries(hooks).map(([event, entries]) => [event, handlersOnEvent(entries, handlerType)]) : []);
192
+ var matcherAlternatives = (matcher) => matcher.split(MATCHER_ALTERNATIVE_SEPARATOR);
193
+ var compiledMatcher = (matcher) => {
194
+ try {
195
+ return new RegExp(matcher);
196
+ } catch {
197
+ return null;
198
+ }
199
+ };
200
+ var regexToolMatch = (matcher) => {
201
+ const pattern = compiledMatcher(matcher);
202
+ return (tool) => pattern !== null && pattern.test(tool);
203
+ };
204
+ var toolMatchOf = (semantics, matcher) => {
205
+ if (semantics === "regex" || !SIMPLE_CLAUDE_CODE_MATCHER.test(matcher)) return regexToolMatch(matcher);
206
+ const names = new Set(matcherAlternatives(matcher));
207
+ return (tool) => names.has(tool);
208
+ };
209
+ var tableToolSamples = (tableMatcher) => matcherAlternatives(tableMatcher).map((alternative) => alternative.replaceAll(TABLE_PATTERN_WILDCARD, TABLE_PATTERN_SAMPLE));
210
+ var coverageOfSamples = (samples, matches) => {
211
+ const matched = samples.filter(matches).length;
212
+ if (matched === samples.length) return "covers";
213
+ return matched > 0 ? "narrows" : "misses";
214
+ };
215
+ var unrestrictedEventCoverage = (matcher, matches, event) => {
216
+ if (UNRESTRICTED_MATCHER_PROBES.every(matches)) return "covers";
217
+ return event.earlierMatchers.includes(matcher) ? "narrows" : "misses";
218
+ };
219
+ var tableMatcherCoverage = (semantics) => (matcher, event) => {
220
+ if (matcherMatchesEveryCall(matcher)) return "covers";
221
+ if (typeof matcher !== "string") return "misses";
222
+ const matches = toolMatchOf(semantics, matcher);
223
+ if (event.matcher === null) return unrestrictedEventCoverage(matcher, matches, event);
224
+ return coverageOfSamples(tableToolSamples(event.matcher), matches);
225
+ };
226
+ var matcherSemanticsOf = (target) => target.kind === "codex" || target.kind === "gemini" ? "regex" : "claude_code";
227
+ var coverageDecidedElsewhere = () => "covers";
228
+ var runsBinary = (command, binary, context) => {
229
+ if (!command.runsExecutable) return false;
230
+ if (isBridgeLocator(command.executable)) return context.isLiveBridge(command.executable);
231
+ return hookExecutableName(command.executable) === binary && context.isRunnableBinary(command);
232
+ };
233
+ var coveredHandlerOf = (handler, event, coverageOf) => {
234
+ const coverage = coverageOf(handler.matcher, event);
235
+ return coverage === "misses" ? [] : [{ handler, coverage }];
236
+ };
237
+ var approvalHandlersOn = (handlersByEvent, event, context, coverageOf) => ({
238
+ event,
239
+ handlers: (handlersByEvent.get(event.event) ?? []).filter((handler) => runsBinary(handler.command, event.binary, context)).flatMap((handler) => coveredHandlerOf(handler, event, coverageOf))
240
+ });
241
+ var coversTableMatcher = (approval) => approval.handlers.some((covered) => covered.coverage === "covers");
242
+ var isBridgeHandler = (handler) => isBridgeLocator(handler.command.executable);
243
+ var hasLiveBridgeAnywhere = (handlersByEvent, isLiveBridge) => [...handlersByEvent.values()].flat().some((handler) => handler.command.runsExecutable && isBridgeHandler(handler) && isLiveBridge(handler.command.executable));
244
+ var approvalOwnerOf = (running, liveBridgeAnywhere) => {
245
+ const covering = running.flatMap((approval) => approval.handlers.filter((covered) => covered.coverage === "covers").map((covered) => covered.handler));
246
+ if (covering.length > 0) return covering.some(isBridgeHandler) ? "app" : "cli";
247
+ if (running.some((approval) => approval.handlers.some((covered) => !isBridgeHandler(covered.handler)))) return "cli";
248
+ return liveBridgeAnywhere ? "app" : null;
249
+ };
250
+ var eventNamesOf = (approvals) => new Set(approvals.map((approval) => approval.event.event));
251
+ var approvalWiringOf = (handlersByEvent, events, context, coverageOf) => {
252
+ const running = events.map((event) => approvalHandlersOn(handlersByEvent, event, context, coverageOf)).filter((approval) => approval.handlers.length > 0);
253
+ return {
254
+ owner: approvalOwnerOf(running, hasLiveBridgeAnywhere(handlersByEvent, context.isLiveBridge)),
255
+ wiredEvents: eventNamesOf(running.filter(coversTableMatcher)),
256
+ narrowedEvents: eventNamesOf(running.filter((approval) => !coversTableMatcher(approval)))
257
+ };
258
+ };
259
+ var readJsonDocument = (path) => {
260
+ const result = readRegularJsonFile(path, HOOK_WIRING_MAX_FILE_BYTES);
261
+ if (result.kind === "missing") return { kind: "missing" };
262
+ if (result.kind === "ok" && isRecord(result.value)) return { kind: "read", document: result.value };
263
+ return { kind: "unreadable" };
264
+ };
265
+ var jsonDocumentOrEmpty = (path) => {
266
+ if (path === null) return {};
267
+ const reading = readJsonDocument(path);
268
+ return reading.kind === "read" ? reading.document : {};
269
+ };
270
+ var textOrNull = (path) => {
271
+ const result = readRegularTextFile(path, HOOK_WIRING_MAX_FILE_BYTES);
272
+ return result.kind === "ok" ? result.value : null;
273
+ };
274
+ var tomlDocumentOrEmpty = (path) => {
275
+ const document = parseConfigDocument(textOrNull(path), "toml");
276
+ return document.kind === "parsed" ? document.value : {};
277
+ };
278
+ var handlersIn = (document, target) => handlersByEventIn(hooksAt(document, hooksKeyPathOf(target)), handlerTypeOf(target));
279
+ var tableFileReading = (reading, target, context) => reading.kind === "read" ? { kind: "read", ...approvalWiringOf(handlersIn(reading.document, target), hookWiringApprovalEvents(target), context, tableMatcherCoverage(matcherSemanticsOf(target))) } : reading;
280
+ var cursorFileReading = (target, context) => {
281
+ const reading = readJsonDocument(target.hooksFile);
282
+ if (reading.kind !== "read") return reading;
283
+ const wiring = approvalWiringOf(handlersIn(reading.document, target), hookWiringApprovalEvents(target), context, coverageDecidedElsewhere);
284
+ const coverage = liveCursorGateCoverage(reading.document, { hooksFile: target.hooksFile, probe: context.probe });
285
+ const runsPushary = (event) => wiring.wiredEvents.has(event);
286
+ return {
287
+ kind: "read",
288
+ owner: wiring.owner,
289
+ wiredEvents: new Set(coverage.full.filter(runsPushary)),
290
+ narrowedEvents: new Set(coverage.partial.filter(runsPushary))
291
+ };
292
+ };
293
+ var openCodeHandlers = (argv) => {
294
+ const command = parseHookArgv(argv);
295
+ return command ? /* @__PURE__ */ new Map([[OPENCODE_APPROVAL_EVENT, [{ raw: argv.join(" "), command, matcher: void 0 }]]]) : NO_HANDLERS;
296
+ };
297
+ var openCodeFileReading = (target, context) => {
298
+ const result = readRegularTextFile(target.pluginFile, HOOK_WIRING_MAX_FILE_BYTES);
299
+ if (result.kind === "missing") return { kind: "missing" };
300
+ if (result.kind !== "ok") return { kind: "unreadable" };
301
+ const handlersByEvent = openCodeHandlers(openCodePluginArgv(result.value) ?? []);
302
+ return { kind: "read", ...approvalWiringOf(handlersByEvent, hookWiringApprovalEvents(target), context, tableMatcherCoverage(matcherSemanticsOf(target))) };
303
+ };
304
+ var isDirectory = (path) => {
305
+ try {
306
+ return statSync(path).isDirectory();
307
+ } catch {
308
+ return false;
309
+ }
310
+ };
311
+ var claudeHooksSwitchedOff = (user, local, managed) => [user, local, managed].some((settings) => settings.disableAllHooks === true) || managed.allowManagedHooksOnly === true;
312
+ var codexTrustCommandIn = (document) => {
313
+ const handlersByEvent = handlersByEventIn(hooksAt(document, DEFAULT_HOOKS_KEY_PATH), "required");
314
+ const handlers = CODEX_APPROVAL_EVENTS.flatMap((event) => handlersByEvent.get(event.event) ?? []);
315
+ return handlers.find((handler) => hookExecutableName(handler.command.executable) === CODEX_HOOK_BINARY)?.raw ?? "";
316
+ };
317
+ var codexHookTrustGapsIn = (config, document, hooksFile) => codexTrustGaps(config, document, hooksFile, codexTrustCommandIn(document), codexHookPositions(document));
318
+ var CODEX_HOOKS_UNREADABLE = { kind: "unreadable" };
319
+ var readCodexHooksOnDisk = (configFile, hooksFile) => {
320
+ const config = parseConfigDocument(textOrNull(configFile), "toml");
321
+ const hooks = readJsonDocument(hooksFile);
322
+ if (config.kind !== "parsed" || hooks.kind !== "read") return CODEX_HOOKS_UNREADABLE;
323
+ return {
324
+ kind: "read",
325
+ hooksFeatureOff: codexHooksFeatureDisabled(config.value),
326
+ gaps: codexHookTrustGapsIn(config.value, hooks.document, hooksFile)
327
+ };
328
+ };
329
+ var UNSWITCHED = { switchedOff: false, trustGaps: [] };
330
+ var readClaudeTarget = (target, context) => {
331
+ const settings = readJsonDocument(target.settingsFile);
332
+ return {
333
+ hooks: tableFileReading(settings, target, context),
334
+ switchedOff: claudeHooksSwitchedOff(
335
+ settings.kind === "read" ? settings.document : {},
336
+ jsonDocumentOrEmpty(target.localSettingsFile),
337
+ jsonDocumentOrEmpty(target.managedSettingsFile)
338
+ ),
339
+ trustGaps: []
340
+ };
341
+ };
342
+ var readCodexTarget = (target, context) => {
343
+ const hooksDocument = readJsonDocument(target.hooksFile);
344
+ const hooks = tableFileReading(hooksDocument, target, context);
345
+ if (hooksDocument.kind !== "read") return { hooks, ...UNSWITCHED };
346
+ const config = tomlDocumentOrEmpty(target.configFile);
347
+ return {
348
+ hooks,
349
+ switchedOff: codexHooksFeatureDisabled(config),
350
+ trustGaps: codexHookTrustGapsIn(config, hooksDocument.document, target.hooksFile)
351
+ };
352
+ };
353
+ var readAgentSpecific = (target, context) => {
354
+ switch (target.kind) {
355
+ case "claude":
356
+ return readClaudeTarget(target, context);
357
+ case "codex":
358
+ return readCodexTarget(target, context);
359
+ case "opencode":
360
+ return { hooks: openCodeFileReading(target, context), ...UNSWITCHED };
361
+ case "cursor":
362
+ return { hooks: cursorFileReading(target, context), ...UNSWITCHED };
363
+ case "gemini":
364
+ case "compatible":
365
+ return { hooks: tableFileReading(readJsonDocument(configFileOf(target)), target, context), ...UNSWITCHED };
366
+ }
367
+ };
368
+ var readHookWiringTarget = (target, machineId, declined, context) => {
369
+ const agent = hookWiringAgentOf(target);
370
+ return {
371
+ agent,
372
+ profile: hookWiringProfileOf(machineId, configFileOf(target)),
373
+ configDirExists: isDirectory(target.configDir),
374
+ declined: declined.has(agent),
375
+ approvalEvents: hookWiringApprovalEvents(target),
376
+ ...readAgentSpecific(target, context)
377
+ };
378
+ };
379
+ var realpathOrNull = (path) => {
380
+ try {
381
+ return realpathSync(path);
382
+ } catch {
383
+ return null;
384
+ }
385
+ };
386
+ var canonicalLiveBridge = (location, probe) => {
387
+ const stub = realpathOrNull(location.stub);
388
+ if (stub === null || !macAppBridgeIsInstalled(location, probe)) return () => false;
389
+ return (executable) => isAbsolute(executable) && isBridgeLocator(executable) && realpathOrNull(executable) === stub;
390
+ };
391
+ var regularFileMode = (path) => {
392
+ try {
393
+ const stats = statSync(path);
394
+ return stats.isFile() ? stats.mode : null;
395
+ } catch {
396
+ return null;
397
+ }
398
+ };
399
+ var runnableBinaryCheck = (platform) => (command) => {
400
+ if (!isAbsolute(command.executable)) return false;
401
+ const mode = regularFileMode(command.executable);
402
+ if (mode === null) return false;
403
+ return command.runsThroughNode || platform === WINDOWS_PLATFORM || (mode & EXECUTE_BITS) !== 0;
404
+ };
405
+ var hookWiringReadContext = (bridge, platform) => {
406
+ const probe = { ...liveBridgeProbe(), readFile: textOrNull, mdfind: NO_SPOTLIGHT };
407
+ return { probe, isLiveBridge: canonicalLiveBridge(bridge, probe), isRunnableBinary: runnableBinaryCheck(platform) };
408
+ };
409
+ var compatibleConfigDirOf = (profile, hooksFile) => profile.configFile.root === "grok_home" ? grokHome() : dirname(hooksFile);
410
+ var compatibleTarget = (profile) => {
411
+ const hooksFile = compatibleConfigFile(profile);
412
+ return { kind: "compatible", profile, configDir: compatibleConfigDirOf(profile, hooksFile), hooksFile };
413
+ };
414
+ var hookWiringLocations = (platform = process.platform) => ({
415
+ declinedAgentsFile: declinedAgentsFile(),
416
+ bridge: { stub: bridgeStub(), cache: bridgeCache(), bundleRoots: installedBridgeBundleRoots(homedir()) },
417
+ targets: [
418
+ {
419
+ kind: "claude",
420
+ configDir: claudeConfigDir(),
421
+ settingsFile: claudeSettings(),
422
+ localSettingsFile: claudeSettingsLocal(),
423
+ managedSettingsFile: MANAGED_CLAUDE_SETTINGS_BY_PLATFORM[platform] ?? null
424
+ },
425
+ { kind: "codex", configDir: codexHome(), hooksFile: codexHooksJson(), configFile: codexConfigToml() },
426
+ { kind: "gemini", configDir: dirname(geminiSettings()), settingsFile: geminiSettings() },
427
+ { kind: "cursor", configDir: dirname(cursorUserHooks()), hooksFile: cursorUserHooks() },
428
+ { kind: "opencode", configDir: openCodeConfigDir(), pluginFile: openCodePluginFile() },
429
+ ...HOOK_COMPATIBLE_PROFILES.map(compatibleTarget)
430
+ ]
431
+ });
432
+ var readHookWiring = (machineId, locations = hookWiringLocations()) => {
433
+ const declined = new Set(readDeclinedAgents(locations.declinedAgentsFile));
434
+ const context = hookWiringReadContext(locations.bridge, process.platform);
435
+ const agents = locations.targets.flatMap((target) => {
436
+ const entry = hookWiringOf(readHookWiringTarget(target, machineId, declined, context));
437
+ return entry ? [entry] : [];
438
+ });
439
+ return { version: HOOK_WIRING_REPORT_VERSION, agents };
440
+ };
441
+ var readHookWiringSafely = (read, reportFailure) => {
442
+ try {
443
+ return read();
444
+ } catch (error) {
445
+ reportFailure(error);
446
+ return null;
447
+ }
448
+ };
449
+
450
+ export {
451
+ readCodexHooksOnDisk,
452
+ readHookWiring,
453
+ readHookWiringSafely
454
+ };
@@ -4,10 +4,10 @@ import {
4
4
  keyPrefix,
5
5
  readConfigFileKey,
6
6
  readMacAppKeyPrefix
7
- } from "./chunk-NUU2JVOG.js";
7
+ } from "./chunk-22OATDEL.js";
8
8
  import {
9
9
  NPX_LATEST_COMMAND
10
- } from "./chunk-KHWNW4AS.js";
10
+ } from "./chunk-JCHF4VR3.js";
11
11
 
12
12
  // src/key-signed-out.ts
13
13
  var VERDICT_BY_CHECK = {
@@ -9,13 +9,13 @@ import {
9
9
  installedCodexApp,
10
10
  readCodexAppRuntime,
11
11
  shellQuoted
12
- } from "./chunk-YI5I2TF3.js";
12
+ } from "./chunk-BYL7RNOM.js";
13
13
  import {
14
14
  writeHuman
15
15
  } from "./chunk-QCGNGEGE.js";
16
16
  import {
17
17
  xml
18
- } from "./chunk-SSW4QRGU.js";
18
+ } from "./chunk-3ZU77DJH.js";
19
19
  import {
20
20
  writeFileAtomic
21
21
  } from "./chunk-T5I4PKOQ.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  CODEX_HOOK_STATUS
3
- } from "./chunk-3AX5BKYN.js";
3
+ } from "./chunk-GBT74TNN.js";
4
4
  import {
5
5
  retryAgentCommand
6
- } from "./chunk-Y3N7LIFV.js";
6
+ } from "./chunk-MPG4HYQ6.js";
7
7
  import {
8
8
  NPX_LATEST_COMMAND
9
- } from "./chunk-KHWNW4AS.js";
9
+ } from "./chunk-JCHF4VR3.js";
10
10
 
11
11
  // src/setup/codex-trust.ts
12
12
  var CODEX_TRUST_TELEMETRY = {
@@ -18,6 +18,16 @@ var CODEX_TRUST_TELEMETRY = {
18
18
  };
19
19
  var isUnanswered = (confirmation) => confirmation.kind === "skipped" || confirmation.kind === "unavailable";
20
20
  var codexTrustOutcome = (confirmation, portedTrustWritten) => isUnanswered(confirmation) && !portedTrustWritten ? "manual" : CODEX_TRUST_TELEMETRY[confirmation.kind];
21
+ var CODEX_APPROVALS_BY_TRUST = {
22
+ verified: "on",
23
+ pretrusted: "on",
24
+ unverified: "on",
25
+ manual: "hooks_not_running"
26
+ };
27
+ var GAPS_THAT_STOP_A_HOOK = /* @__PURE__ */ new Set(["untrusted", "disabled", "asynchronous"]);
28
+ var CODEX_SETTINGS_STOP_A_HOOK = "Codex's own settings stop a Pushary hook from running: hooks are turned off in config.toml, or a hook is turned off or not trusted in Codex's hooks list (/hooks, or Settings then Hooks in the ChatGPT app). Run pushary doctor to see which, and how to fix it.";
29
+ var codexSettingsStopAHook = (onDisk) => onDisk.kind === "read" && (onDisk.hooksFeatureOff || onDisk.gaps.some((gap) => GAPS_THAT_STOP_A_HOOK.has(gap.kind)));
30
+ var codexApprovalsWithHooks = (trust, onDisk) => trust === "unverified" && codexSettingsStopAHook(onDisk) ? "hooks_not_running" : CODEX_APPROVALS_BY_TRUST[trust];
21
31
  var CODEX_TRUST_REFUSED = "Codex did not accept the trust Pushary asked for, so its hooks are not trusted yet. Open Codex, run /hooks, and choose Trust for the Pushary hooks.";
22
32
  var CODEX_HOOK_REMEDY = {
23
33
  asynchronous: "re-run setup to restore blocking permission hooks",
@@ -110,6 +120,8 @@ var describeHermesState = (state) => {
110
120
 
111
121
  export {
112
122
  codexTrustOutcome,
123
+ CODEX_SETTINGS_STOP_A_HOOK,
124
+ codexApprovalsWithHooks,
113
125
  CODEX_HOOK_REMEDY,
114
126
  needsCodexTrustStep,
115
127
  describeCodexTrustConfirmation,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-KHWNW4AS.js";
3
+ } from "./chunk-JCHF4VR3.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyFetch
3
- } from "./chunk-5RVL2CQK.js";
3
+ } from "./chunk-XQFHB2EK.js";
4
4
  import {
5
5
  getBaseUrl
6
- } from "./chunk-O76PTPKP.js";
6
+ } from "./chunk-GSJUGW3A.js";
7
7
  import {
8
8
  NetworkError
9
9
  } from "./chunk-YU2EUD7O.js";
@@ -13,7 +13,7 @@ import {
13
13
  import {
14
14
  isValidApiKey,
15
15
  normalizeKeyScope
16
- } from "./chunk-DZE26BID.js";
16
+ } from "./chunk-KPCVIH52.js";
17
17
 
18
18
  // src/session.ts
19
19
  var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
@@ -27,11 +27,11 @@ import {
27
27
  toolResultErrorText,
28
28
  transcriptTokensIn,
29
29
  transcriptUsageRequest
30
- } from "./chunk-FYVRA5GN.js";
30
+ } from "./chunk-FQSFN5ZE.js";
31
31
  import {
32
32
  branchFor,
33
33
  repoKeyFor
34
- } from "./chunk-NVPCETJ3.js";
34
+ } from "./chunk-4I6FWGZ5.js";
35
35
  import {
36
36
  cancelQuestion,
37
37
  clientErrorKindOf,
@@ -39,34 +39,34 @@ import {
39
39
  reportClientError,
40
40
  sendNotification,
41
41
  waitForAnswer
42
- } from "./chunk-TILEGY4M.js";
42
+ } from "./chunk-44O6GG4I.js";
43
43
  import {
44
44
  withRetry
45
- } from "./chunk-EPMIBLCE.js";
45
+ } from "./chunk-WUREJCUJ.js";
46
46
  import {
47
47
  fetchAsCredential
48
- } from "./chunk-PYAPWXVP.js";
48
+ } from "./chunk-NPG4WCIM.js";
49
49
  import {
50
50
  getMachineId
51
- } from "./chunk-SDQQ43FT.js";
51
+ } from "./chunk-F5TQ6TCH.js";
52
52
  import {
53
53
  reportedInstallSource
54
- } from "./chunk-LTVILMEZ.js";
54
+ } from "./chunk-JRW5HK32.js";
55
55
  import {
56
56
  IDLE_PROMPT_NOTIFICATION,
57
57
  NOTIFICATION_PUSH_TYPES,
58
58
  POSTTOOLUSE_MIRROR_ONLY_TOOLS,
59
59
  canonicalJson,
60
60
  claudeConfigDir
61
- } from "./chunk-PCFIYMK4.js";
61
+ } from "./chunk-RLBTKTOK.js";
62
62
  import {
63
63
  compareVersion,
64
64
  parseVersion
65
- } from "./chunk-QQMT2JIC.js";
65
+ } from "./chunk-RIBCPWOB.js";
66
66
  import {
67
67
  getApiKey,
68
68
  getBaseUrl
69
- } from "./chunk-O76PTPKP.js";
69
+ } from "./chunk-GSJUGW3A.js";
70
70
  import {
71
71
  writeFileAtomic,
72
72
  writeJsonAtomicDurable
@@ -94,7 +94,7 @@ import {
94
94
  resolveAutoResolveOrigin,
95
95
  resolvePolicy,
96
96
  unansweredRefusalReason
97
- } from "./chunk-DZE26BID.js";
97
+ } from "./chunk-KPCVIH52.js";
98
98
 
99
99
  // src/pending.ts
100
100
  import { join } from "path";
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  pusharyHookExecutable
3
- } from "./chunk-NZZFIIH6.js";
3
+ } from "./chunk-NK5XT4RS.js";
4
4
  import {
5
5
  bridgeResolvesToApp,
6
6
  cursorUserHooks,
7
7
  executableFileName,
8
8
  isBridgeLocator,
9
9
  liveBridgeProbe
10
- } from "./chunk-PCFIYMK4.js";
10
+ } from "./chunk-RLBTKTOK.js";
11
11
  import {
12
12
  atLeast,
13
13
  parseVersion
14
- } from "./chunk-QQMT2JIC.js";
14
+ } from "./chunk-RIBCPWOB.js";
15
15
  import {
16
16
  CURSOR_GATE_COVERAGE,
17
17
  CURSOR_GATE_SCRIPT,
@@ -21,7 +21,7 @@ import {
21
21
  isCursorHookPayload,
22
22
  isRecord,
23
23
  toolsCoveredByGateEntry
24
- } from "./chunk-DZE26BID.js";
24
+ } from "./chunk-KPCVIH52.js";
25
25
 
26
26
  // src/cursor-gate-registration.ts
27
27
  import { dirname, isAbsolute, join, resolve } from "path";
@@ -2,7 +2,7 @@ import {
2
2
  DISCONNECT_AGENT_IDS,
3
3
  SETUP_AGENT_CHOICES,
4
4
  isApprovalMode
5
- } from "./chunk-DZE26BID.js";
5
+ } from "./chunk-KPCVIH52.js";
6
6
 
7
7
  // src/cli/mode-request.ts
8
8
  var parseDuration = (value) => {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  configFilePath
3
- } from "./chunk-O76PTPKP.js";
3
+ } from "./chunk-GSJUGW3A.js";
4
4
  import {
5
5
  normalizeInstallSource
6
- } from "./chunk-DZE26BID.js";
6
+ } from "./chunk-KPCVIH52.js";
7
7
 
8
8
  // src/install-source.ts
9
9
  import { readFileSync } from "fs";