@pushary/agent-hooks 0.97.0 → 0.99.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/bin/pushary-bell-hook.js +20 -19
  3. package/dist/bin/pushary-bell.js +7 -6
  4. package/dist/bin/pushary-claude.js +21 -20
  5. package/dist/bin/pushary-clean.js +19 -18
  6. package/dist/bin/pushary-codex-bridge.js +11 -10
  7. package/dist/bin/pushary-codex-hook.js +33 -23
  8. package/dist/bin/pushary-codex.js +8 -7
  9. package/dist/bin/pushary-connect.js +7 -6
  10. package/dist/bin/pushary-cowork.js +3 -3
  11. package/dist/bin/pushary-daemon.js +24 -23
  12. package/dist/bin/pushary-disconnect.js +6 -6
  13. package/dist/bin/pushary-doctor.js +22 -21
  14. package/dist/bin/pushary-elicitation-hook.js +19 -18
  15. package/dist/bin/pushary-gemini-bridge.js +10 -9
  16. package/dist/bin/pushary-gemini-hook.js +22 -21
  17. package/dist/bin/pushary-hook.js +24 -23
  18. package/dist/bin/pushary-login.js +8 -7
  19. package/dist/bin/pushary-logout.js +5 -4
  20. package/dist/bin/pushary-mode.js +3 -3
  21. package/dist/bin/pushary-notification-hook.js +21 -20
  22. package/dist/bin/pushary-opencode-hook.js +22 -21
  23. package/dist/bin/pushary-permission-denied-hook.js +25 -24
  24. package/dist/bin/pushary-permission-hook.js +24 -23
  25. package/dist/bin/pushary-post-hook.js +21 -20
  26. package/dist/bin/pushary-prompt-hook.js +21 -20
  27. package/dist/bin/pushary-session-end-hook.js +21 -20
  28. package/dist/bin/pushary-session-start-hook.js +24 -23
  29. package/dist/bin/pushary-setup.js +38 -28
  30. package/dist/bin/pushary-stats.js +2 -2
  31. package/dist/bin/pushary-status.js +11 -10
  32. package/dist/bin/pushary-stop-hook.js +21 -20
  33. package/dist/bin/pushary-stopfailure-hook.js +21 -20
  34. package/dist/bin/pushary-transcript-register.js +18 -17
  35. package/dist/bin/pushary-transcripts.js +6 -5
  36. package/dist/bin/pushary-upgrade.js +15 -14
  37. package/dist/bin/pushary-wait.js +3 -3
  38. package/dist/{chunk-SW37HB27.js → chunk-3RVCQDC4.js} +1 -1
  39. package/dist/{chunk-AXSDMDJI.js → chunk-3ZAEUPM4.js} +1 -1
  40. package/dist/{chunk-B3557BDL.js → chunk-4C4XFAGJ.js} +2 -2
  41. package/dist/{chunk-VTUN7WSG.js → chunk-4LL6LG5X.js} +1 -43
  42. package/dist/{chunk-VF7YOT2W.js → chunk-4PBCNVI3.js} +4 -2
  43. package/dist/{chunk-IZKCA35M.js → chunk-562UJ2DA.js} +2 -2
  44. package/dist/{chunk-ROTIPRM4.js → chunk-5KLAETSU.js} +1 -1
  45. package/dist/{chunk-DGUMR5LZ.js → chunk-64WARXGV.js} +5 -5
  46. package/dist/{chunk-VDTC5DEM.js → chunk-6C6MS57P.js} +1 -1
  47. package/dist/{chunk-KDPYXMUI.js → chunk-6IFUXNFX.js} +2 -2
  48. package/dist/{chunk-XDMHLQMH.js → chunk-6KLCP7VF.js} +4 -4
  49. package/dist/{chunk-VCKQ45QA.js → chunk-A76GNRIK.js} +1 -1
  50. package/dist/{chunk-ICUBJNFL.js → chunk-CP34FI4B.js} +2 -2
  51. package/dist/{chunk-LYWTLNMG.js → chunk-CRFLU455.js} +4 -4
  52. package/dist/{chunk-WIKEADOS.js → chunk-EXHXR2X5.js} +1 -1
  53. package/dist/chunk-GCD3SQSV.js +44 -0
  54. package/dist/{chunk-EHQC3GWL.js → chunk-HB2KB7QL.js} +1 -1
  55. package/dist/{chunk-C2FYSFTQ.js → chunk-ID5FDKDZ.js} +1 -1
  56. package/dist/{chunk-BYH75I7Y.js → chunk-IRLTW6KF.js} +1 -1
  57. package/dist/{chunk-67RNDRKL.js → chunk-JBJBVERL.js} +111 -31
  58. package/dist/{chunk-3SNTEHOH.js → chunk-JL33EDN7.js} +4 -4
  59. package/dist/{chunk-FU5SQKAY.js → chunk-JXELRCU5.js} +16 -23
  60. package/dist/{chunk-YRXVC4HL.js → chunk-K4XFCEVI.js} +1 -1
  61. package/dist/{chunk-GGYH6LIE.js → chunk-K6BASBQJ.js} +1 -1
  62. package/dist/{chunk-H4VNAOCG.js → chunk-LBNAGGLV.js} +1 -1
  63. package/dist/{chunk-DOKFLZWL.js → chunk-LWKPMSBB.js} +69 -46
  64. package/dist/{chunk-6VXZKOBB.js → chunk-NSFNEDCT.js} +8 -8
  65. package/dist/{chunk-5ODZEFP3.js → chunk-O3LZQEQP.js} +1 -1
  66. package/dist/{chunk-QFAZ6QCT.js → chunk-OPR2BPD4.js} +1 -1
  67. package/dist/{chunk-HUZW6SEO.js → chunk-OUAE3GKO.js} +2 -2
  68. package/dist/{chunk-IBRX7LRE.js → chunk-PD6JY33P.js} +9 -8
  69. package/dist/{chunk-6WJKYD3Q.js → chunk-QS55LDX4.js} +11 -8
  70. package/dist/{chunk-4AXWBCCO.js → chunk-RALVI7OF.js} +4 -4
  71. package/dist/{chunk-OYTOLQ3N.js → chunk-SI7GYBQP.js} +1 -1
  72. package/dist/{chunk-YX3U2CLP.js → chunk-T3JZZUAR.js} +6 -6
  73. package/dist/{chunk-K7MLXXPY.js → chunk-V262ATS5.js} +3 -3
  74. package/dist/{chunk-DNLFSRCF.js → chunk-WGV3VY7O.js} +2 -2
  75. package/dist/{chunk-VOC55PQV.js → chunk-XOOWC62T.js} +1 -1
  76. package/dist/{chunk-CDSA3NTB.js → chunk-XPPXOKIG.js} +1 -1
  77. package/dist/{chunk-A4AIISZZ.js → chunk-YKLCWWEI.js} +1 -1
  78. package/dist/reapply-HQ264ZTR.js +30 -0
  79. package/dist/src/index.js +11 -10
  80. package/package.json +1 -1
@@ -1,10 +1,3 @@
1
- import {
2
- configFilePath
3
- } from "./chunk-2UMNXADU.js";
4
- import {
5
- normalizeInstallSource
6
- } from "./chunk-HUZW6SEO.js";
7
-
8
1
  // src/cli/fsx.ts
9
2
  import { copyFileSync, existsSync, fsyncSync, mkdirSync, openSync, closeSync, readFileSync, renameSync, unlinkSync, writeFileSync } from "fs";
10
3
  import { dirname, join } from "path";
@@ -64,45 +57,10 @@ var writeJsonAtomicDurable = (filePath, data, mode) => {
64
57
  }
65
58
  };
66
59
 
67
- // src/install-source.ts
68
- import { readFileSync as readFileSync2 } from "fs";
69
- var ENV_OVERRIDE = "PUSHARY_INSTALL_SOURCE";
70
- var PLUGIN_ROOT = "CLAUDE_PLUGIN_ROOT";
71
- var EDITOR_PLUGIN_MARKERS = ["cursor-plugin", "vscode-plugin"];
72
- var detectInstallSource = (env = process.env, argv = process.argv) => {
73
- const declared = env[ENV_OVERRIDE]?.trim();
74
- if (declared) return normalizeInstallSource(declared);
75
- const pluginRoot = env[PLUGIN_ROOT]?.trim();
76
- if (pluginRoot) {
77
- return EDITOR_PLUGIN_MARKERS.some((marker) => pluginRoot.includes(marker)) ? "editor_plugin" : "claude_plugin";
78
- }
79
- const entry = argv[1] ?? "";
80
- if (entry.includes("_npx")) return "npx";
81
- if (entry) return "npm";
82
- return "unknown";
83
- };
84
- var storedInstallSource = () => {
85
- try {
86
- const parsed = JSON.parse(readFileSync2(configFilePath(), "utf-8"));
87
- const stored = parsed.installSource;
88
- return typeof stored === "string" && stored ? normalizeInstallSource(stored) : void 0;
89
- } catch {
90
- return void 0;
91
- }
92
- };
93
- var resolveInstallSourceFor = (config) => {
94
- const stored = config.installSource;
95
- if (typeof stored === "string" && stored) return normalizeInstallSource(stored);
96
- return detectInstallSource();
97
- };
98
- var reportedInstallSource = () => storedInstallSource() ?? detectInstallSource();
99
-
100
60
  export {
101
61
  readJsonSafe,
102
62
  backupFile,
103
63
  writeFileAtomic,
104
64
  writeJsonAtomic,
105
- writeJsonAtomicDurable,
106
- resolveInstallSourceFor,
107
- reportedInstallSource
65
+ writeJsonAtomicDurable
108
66
  };
@@ -1,10 +1,12 @@
1
+ import {
2
+ resolveInstallSourceFor
3
+ } from "./chunk-GCD3SQSV.js";
1
4
  import {
2
5
  backupFile,
3
6
  readJsonSafe,
4
- resolveInstallSourceFor,
5
7
  writeFileAtomic,
6
8
  writeJsonAtomic
7
- } from "./chunk-VTUN7WSG.js";
9
+ } from "./chunk-4LL6LG5X.js";
8
10
  import {
9
11
  configFilePath
10
12
  } from "./chunk-2UMNXADU.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-67RNDRKL.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
  import {
5
5
  writeFileAtomic
6
- } from "./chunk-VTUN7WSG.js";
6
+ } from "./chunk-4LL6LG5X.js";
7
7
 
8
8
  // src/identity.ts
9
9
  import { randomUUID } from "crypto";
@@ -3,7 +3,7 @@ import {
3
3
  decodePublicKey,
4
4
  generateSessionKey,
5
5
  wrapSessionKey
6
- } from "./chunk-CDSA3NTB.js";
6
+ } from "./chunk-XPPXOKIG.js";
7
7
  import {
8
8
  fetchTranscriptRecipients,
9
9
  uploadTranscriptRecords
@@ -18,11 +18,11 @@ import {
18
18
  summarizeStop,
19
19
  taskTitleFrom,
20
20
  toolResultErrorText
21
- } from "./chunk-VCKQ45QA.js";
21
+ } from "./chunk-A76GNRIK.js";
22
22
  import {
23
23
  NOTIFICATION_PUSH_TYPES,
24
24
  POSTTOOLUSE_MIRROR_ONLY_TOOLS
25
- } from "./chunk-QFAZ6QCT.js";
25
+ } from "./chunk-OPR2BPD4.js";
26
26
  import {
27
27
  cancelQuestion,
28
28
  isPolicyConfig,
@@ -31,13 +31,13 @@ import {
31
31
  } from "./chunk-LGXUGYUH.js";
32
32
  import {
33
33
  getMachineId
34
- } from "./chunk-IZKCA35M.js";
34
+ } from "./chunk-562UJ2DA.js";
35
35
  import {
36
36
  withRetry
37
37
  } from "./chunk-EYRGBYZG.js";
38
38
  import {
39
39
  reportedInstallSource
40
- } from "./chunk-VTUN7WSG.js";
40
+ } from "./chunk-GCD3SQSV.js";
41
41
  import {
42
42
  getApiKey,
43
43
  getBaseUrl
@@ -54,7 +54,7 @@ import {
54
54
  pendingCommandEvents,
55
55
  resolveAutoResolveOrigin,
56
56
  resolvePolicy
57
- } from "./chunk-HUZW6SEO.js";
57
+ } from "./chunk-OUAE3GKO.js";
58
58
 
59
59
  // src/policy.ts
60
60
  import { createHash } from "crypto";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  describeKeyCheck,
3
3
  keyCheckFromResponse
4
- } from "./chunk-SW37HB27.js";
4
+ } from "./chunk-3RVCQDC4.js";
5
5
  import {
6
6
  createIo
7
7
  } from "./chunk-5RUIFDTP.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-67RNDRKL.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
  import {
5
5
  readJsonSafe
6
- } from "./chunk-VTUN7WSG.js";
6
+ } from "./chunk-4LL6LG5X.js";
7
7
 
8
8
  // src/process-ownership.ts
9
9
  import { createHash, randomUUID } from "crypto";
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  canonicalGateInputs
3
- } from "./chunk-VCKQ45QA.js";
3
+ } from "./chunk-A76GNRIK.js";
4
4
  import {
5
5
  canonicalJson
6
- } from "./chunk-67RNDRKL.js";
6
+ } from "./chunk-JBJBVERL.js";
7
7
  import {
8
8
  writeFileAtomic
9
- } from "./chunk-VTUN7WSG.js";
9
+ } from "./chunk-4LL6LG5X.js";
10
10
  import {
11
11
  BLOCKED_ACTION_GRANT_TTL_SECONDS,
12
12
  blockedActionIdentity,
13
13
  shouldDeferToNativeMode
14
- } from "./chunk-HUZW6SEO.js";
14
+ } from "./chunk-OUAE3GKO.js";
15
15
 
16
16
  // src/native-defer.ts
17
17
  var nativeDeferOptions = () => {
@@ -6,7 +6,7 @@ import {
6
6
  GATE_MAX_TOOL_INPUTS,
7
7
  redactSecrets,
8
8
  redactSecretsDeep
9
- } from "./chunk-HUZW6SEO.js";
9
+ } from "./chunk-OUAE3GKO.js";
10
10
 
11
11
  // ../hook-mapping/src/describe.ts
12
12
  import { isAbsolute, relative, resolve } from "path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SETUP_FLAGS
3
- } from "./chunk-H4VNAOCG.js";
3
+ } from "./chunk-LBNAGGLV.js";
4
4
  import {
5
5
  parseFlags
6
6
  } from "./chunk-GMXKITVA.js";
@@ -14,7 +14,7 @@ import {
14
14
  CLAUDE_CONNECTOR_URL,
15
15
  COWORK_CONNECTOR_LIMIT,
16
16
  COWORK_STANDING_INSTRUCTIONS
17
- } from "./chunk-HUZW6SEO.js";
17
+ } from "./chunk-OUAE3GKO.js";
18
18
 
19
19
  // src/cli/cowork.ts
20
20
  import { readFileSync } from "fs";
@@ -4,23 +4,23 @@ import {
4
4
  } from "./chunk-XHKBHWLX.js";
5
5
  import {
6
6
  getMachineId
7
- } from "./chunk-IZKCA35M.js";
7
+ } from "./chunk-562UJ2DA.js";
8
8
  import {
9
9
  pusharyDir,
10
10
  resolveGlobalBinary
11
- } from "./chunk-67RNDRKL.js";
11
+ } from "./chunk-JBJBVERL.js";
12
12
  import {
13
13
  getPackageVersion
14
14
  } from "./chunk-DINDL2CF.js";
15
15
  import {
16
16
  readControlMode
17
- } from "./chunk-VF7YOT2W.js";
17
+ } from "./chunk-4PBCNVI3.js";
18
18
  import {
19
19
  readJsonSafe,
20
20
  writeFileAtomic,
21
21
  writeJsonAtomic,
22
22
  writeJsonAtomicDurable
23
- } from "./chunk-VTUN7WSG.js";
23
+ } from "./chunk-4LL6LG5X.js";
24
24
  import {
25
25
  getApiKey
26
26
  } from "./chunk-2UMNXADU.js";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  guardBinary
3
- } from "./chunk-67RNDRKL.js";
3
+ } from "./chunk-JBJBVERL.js";
4
4
 
5
5
  // src/bell/install.ts
6
6
  import { join } from "path";
@@ -0,0 +1,44 @@
1
+ import {
2
+ configFilePath
3
+ } from "./chunk-2UMNXADU.js";
4
+ import {
5
+ normalizeInstallSource
6
+ } from "./chunk-OUAE3GKO.js";
7
+
8
+ // src/install-source.ts
9
+ import { readFileSync } from "fs";
10
+ var ENV_OVERRIDE = "PUSHARY_INSTALL_SOURCE";
11
+ var PLUGIN_ROOT = "CLAUDE_PLUGIN_ROOT";
12
+ var EDITOR_PLUGIN_MARKERS = ["cursor-plugin", "vscode-plugin"];
13
+ var detectInstallSource = (env = process.env, argv = process.argv) => {
14
+ const declared = env[ENV_OVERRIDE]?.trim();
15
+ if (declared) return normalizeInstallSource(declared);
16
+ const pluginRoot = env[PLUGIN_ROOT]?.trim();
17
+ if (pluginRoot) {
18
+ return EDITOR_PLUGIN_MARKERS.some((marker) => pluginRoot.includes(marker)) ? "editor_plugin" : "claude_plugin";
19
+ }
20
+ const entry = argv[1] ?? "";
21
+ if (entry.includes("_npx")) return "npx";
22
+ if (entry) return "npm";
23
+ return "unknown";
24
+ };
25
+ var storedInstallSource = () => {
26
+ try {
27
+ const parsed = JSON.parse(readFileSync(configFilePath(), "utf-8"));
28
+ const stored = parsed.installSource;
29
+ return typeof stored === "string" && stored ? normalizeInstallSource(stored) : void 0;
30
+ } catch {
31
+ return void 0;
32
+ }
33
+ };
34
+ var resolveInstallSourceFor = (config) => {
35
+ const stored = config.installSource;
36
+ if (typeof stored === "string" && stored) return normalizeInstallSource(stored);
37
+ return detectInstallSource();
38
+ };
39
+ var reportedInstallSource = () => storedInstallSource() ?? detectInstallSource();
40
+
41
+ export {
42
+ resolveInstallSourceFor,
43
+ reportedInstallSource
44
+ };
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_BUDGETS,
3
3
  OPENCODE_APPROVAL_EVENT
4
- } from "./chunk-HUZW6SEO.js";
4
+ } from "./chunk-OUAE3GKO.js";
5
5
 
6
6
  // src/opencode-plugin.ts
7
7
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  readTranscriptPreference
3
- } from "./chunk-VF7YOT2W.js";
3
+ } from "./chunk-4PBCNVI3.js";
4
4
 
5
5
  // src/transcript-setting.ts
6
6
  var transcriptEnvironmentPreference = () => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HOOK_LOCATOR_BINARY
3
- } from "./chunk-HUZW6SEO.js";
3
+ } from "./chunk-OUAE3GKO.js";
4
4
 
5
5
  // src/diagnostics/bridge.ts
6
6
  import { execFileSync } from "child_process";
@@ -2,7 +2,7 @@ import {
2
2
  HOOK_BUDGETS,
3
3
  HOOK_LOCATOR_BINARY,
4
4
  withHookHoldBudget
5
- } from "./chunk-HUZW6SEO.js";
5
+ } from "./chunk-OUAE3GKO.js";
6
6
 
7
7
  // src/npm.ts
8
8
  import { execFileSync, execSync } from "child_process";
@@ -227,6 +227,52 @@ import { createHash } from "crypto";
227
227
  import { homedir } from "os";
228
228
  import { join as join2 } from "path";
229
229
 
230
+ // src/registration-holder.ts
231
+ var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
232
+ var registeredCommands = (document) => {
233
+ const hooks = asRecord(document?.hooks);
234
+ if (!hooks) return [];
235
+ const found = [];
236
+ for (const [event, value] of Object.entries(hooks)) {
237
+ if (!Array.isArray(value)) continue;
238
+ for (const item of value) {
239
+ const inner = asRecord(item)?.hooks;
240
+ if (!Array.isArray(inner)) continue;
241
+ for (const hook of inner) {
242
+ const command = asRecord(hook)?.command;
243
+ if (typeof command === "string") found.push({ event, command });
244
+ }
245
+ }
246
+ }
247
+ return found;
248
+ };
249
+ var wholeSegments = (command) => command.split(/[\s/\\"']+/).map((segment) => segment.replace(/\.(cmd|exe)$/i, ""));
250
+ var namesLocator = (command) => wholeSegments(command).includes(HOOK_LOCATOR_BINARY);
251
+ var namesCliBinary = (command, cliBinaries) => wholeSegments(command).some((segment) => cliBinaries.has(segment));
252
+ var namesOurBinary = (command, cliBinaries) => namesLocator(command) || namesCliBinary(command, cliBinaries);
253
+ var registrationHolderOf = (document, cliBinaries) => {
254
+ const commands = registeredCommands(document);
255
+ if (commands.some(({ command }) => namesLocator(command))) return "app";
256
+ return commands.some(({ command }) => namesCliBinary(command, cliBinaries)) ? "cli" : "none";
257
+ };
258
+
259
+ // src/hook-entries.ts
260
+ var registerHookEntry = (existing, isOurs, entry) => {
261
+ const rewritten = [];
262
+ let placed = false;
263
+ for (const item of existing) {
264
+ if (!isOurs(item)) {
265
+ rewritten.push(item);
266
+ continue;
267
+ }
268
+ if (placed) continue;
269
+ rewritten.push(entry);
270
+ placed = true;
271
+ }
272
+ if (!placed) rewritten.push(entry);
273
+ return rewritten;
274
+ };
275
+
230
276
  // src/canonical-json.ts
231
277
  var canonicalJson = (value) => {
232
278
  if (value === null || typeof value !== "object") return JSON.stringify(value);
@@ -281,9 +327,9 @@ var CODEX_EVENT_KEY = {
281
327
  PostCompact: "post_compact"
282
328
  };
283
329
  var codexEventKeyOf = (event) => event.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
284
- var asRecord = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
330
+ var asRecord2 = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
285
331
  var ensureRecord = (target, key) => {
286
- const existing = asRecord(target[key]);
332
+ const existing = asRecord2(target[key]);
287
333
  if (existing) return existing;
288
334
  const created = {};
289
335
  target[key] = created;
@@ -300,9 +346,9 @@ var addCodexMcpServer = (config, apiKey) => {
300
346
  delete pushary.tools;
301
347
  };
302
348
  var readCodexMcpAuth = (config) => {
303
- const pushary = asRecord(asRecord(config.mcp_servers)?.pushary);
349
+ const pushary = asRecord2(asRecord2(config.mcp_servers)?.pushary);
304
350
  if (!pushary) return void 0;
305
- const authorization = asRecord(pushary.http_headers)?.Authorization;
351
+ const authorization = asRecord2(pushary.http_headers)?.Authorization;
306
352
  if (typeof authorization === "string" && authorization.startsWith("Bearer ")) {
307
353
  return { method: "embedded", key: authorization.slice("Bearer ".length).trim() };
308
354
  }
@@ -313,20 +359,21 @@ var readCodexMcpAuth = (config) => {
313
359
  return void 0;
314
360
  };
315
361
  var isPusharyCommand = (hook, scope) => {
316
- const command = String(asRecord(hook)?.command ?? "");
362
+ const command = String(asRecord2(hook)?.command ?? "");
317
363
  if (isProtectedByScope(command, scope)) return false;
318
364
  return command.includes(CODEX_HOOK_BINARY) || command.includes(HOOK_LOCATOR_BINARY);
319
365
  };
320
366
  var isPusharyCodexHook = (entry, scope) => {
321
- const hooks = asRecord(entry)?.hooks;
367
+ const hooks = asRecord2(entry)?.hooks;
322
368
  return Array.isArray(hooks) && hooks.some((hook) => isPusharyCommand(hook, scope));
323
369
  };
370
+ var CODEX_CLI_BINARIES = /* @__PURE__ */ new Set([CODEX_HOOK_BINARY]);
371
+ var codexRegistrationHolder = (hooksConfig) => registrationHolderOf(hooksConfig, CODEX_CLI_BINARIES);
324
372
  var addCodexHooks = (config, command) => {
325
373
  const hooks = ensureRecord(config, "hooks");
326
374
  for (const definition of CODEX_HOOK_EVENTS) {
327
375
  const existing = Array.isArray(hooks[definition.event]) ? hooks[definition.event] : [];
328
- const entries = existing.filter((entry) => !isPusharyCodexHook(entry));
329
- entries.push({
376
+ hooks[definition.event] = registerHookEntry(existing, isPusharyCodexHook, {
330
377
  ...definition.matcher ? { matcher: definition.matcher } : {},
331
378
  hooks: [{
332
379
  type: "command",
@@ -335,11 +382,10 @@ var addCodexHooks = (config, command) => {
335
382
  ...definition.statusMessage ? { statusMessage: definition.statusMessage } : {}
336
383
  }]
337
384
  });
338
- hooks[definition.event] = entries;
339
385
  }
340
386
  };
341
387
  var removeCodexHooks = (config, scope) => {
342
- const hooks = asRecord(config.hooks);
388
+ const hooks = asRecord2(config.hooks);
343
389
  if (!hooks) return false;
344
390
  let changed = false;
345
391
  for (const definition of CODEX_HOOK_EVENTS) {
@@ -359,7 +405,7 @@ var removeCodexHooks = (config, scope) => {
359
405
  return changed;
360
406
  };
361
407
  var hasCodexHooks = (config) => {
362
- const hooks = asRecord(config.hooks);
408
+ const hooks = asRecord2(config.hooks);
363
409
  if (!hooks) return false;
364
410
  return CODEX_HOOK_EVENTS.some((definition) => {
365
411
  const entries = hooks[definition.event];
@@ -367,7 +413,7 @@ var hasCodexHooks = (config) => {
367
413
  });
368
414
  };
369
415
  var missingCodexHookEvents = (config) => {
370
- const hooks = asRecord(config.hooks);
416
+ const hooks = asRecord2(config.hooks);
371
417
  return CODEX_HOOK_EVENTS.filter((definition) => {
372
418
  const entries = hooks?.[definition.event];
373
419
  return !Array.isArray(entries) || !entries.some((entry) => isPusharyCodexHook(entry));
@@ -384,22 +430,22 @@ var codexEntryTrustHash = (eventKey, entry) => {
384
430
  const hooks = Array.isArray(entry.hooks) ? entry.hooks : [];
385
431
  const identity = {
386
432
  event_name: eventKey,
387
- hooks: hooks.map((hook) => ({ async: false, ...asRecord(hook) }))
433
+ hooks: hooks.map((hook) => ({ async: false, ...asRecord2(hook) }))
388
434
  };
389
435
  if (typeof entry.matcher === "string") identity.matcher = entry.matcher;
390
436
  return "sha256:" + createHash("sha256").update(canonicalJson(identity), "utf8").digest("hex");
391
437
  };
392
438
  var codexTrustSchemeAgrees = (hooksConfig, config, hooksJsonPath) => {
393
- const hooks = asRecord(hooksConfig?.hooks);
394
- const state = asRecord(asRecord(config.hooks)?.state);
439
+ const hooks = asRecord2(hooksConfig?.hooks);
440
+ const state = asRecord2(asRecord2(config.hooks)?.state);
395
441
  if (!hooks || !state) return false;
396
442
  for (const [event, entries] of Object.entries(hooks)) {
397
443
  if (!Array.isArray(entries)) continue;
398
444
  const eventKey = CODEX_EVENT_KEY[event] ?? codexEventKeyOf(event);
399
445
  for (const [index, entry] of entries.entries()) {
400
- const record = asRecord(entry);
446
+ const record = asRecord2(entry);
401
447
  if (!record) continue;
402
- const stored = asRecord(state[`${hooksJsonPath}:${eventKey}:${index}:0`])?.trusted_hash;
448
+ const stored = asRecord2(state[`${hooksJsonPath}:${eventKey}:${index}:0`])?.trusted_hash;
403
449
  if (typeof stored !== "string") continue;
404
450
  if (stored === codexEntryTrustHash(eventKey, record)) return true;
405
451
  }
@@ -407,22 +453,49 @@ var codexTrustSchemeAgrees = (hooksConfig, config, hooksJsonPath) => {
407
453
  return false;
408
454
  };
409
455
  var codexHookPositions = (hooksConfig) => {
410
- const hooks = asRecord(hooksConfig?.hooks);
456
+ const hooks = asRecord2(hooksConfig?.hooks);
411
457
  const positions = {};
412
458
  for (const definition of CODEX_HOOK_EVENTS) {
413
459
  const entries = hooks?.[definition.event];
414
460
  if (!Array.isArray(entries)) continue;
415
461
  const entryIndex = entries.findIndex((entry) => isPusharyCodexHook(entry));
416
462
  if (entryIndex < 0) continue;
417
- const inner = asRecord(entries[entryIndex])?.hooks;
463
+ const inner = asRecord2(entries[entryIndex])?.hooks;
418
464
  const hookIndex = Array.isArray(inner) ? inner.findIndex((hook) => isPusharyCommand(hook)) : -1;
419
465
  positions[definition.event] = [entryIndex, Math.max(hookIndex, 0)];
420
466
  }
421
467
  return positions;
422
468
  };
423
469
  var codexHookStateKey = (hooksJsonPath, event, position) => `${hooksJsonPath}:${CODEX_EVENT_KEY[event]}:${position[0]}:${position[1]}`;
470
+ var codexVacatedIndexes = (hooksConfig) => {
471
+ const hooks = asRecord2(hooksConfig?.hooks);
472
+ const vacated = {};
473
+ for (const definition of CODEX_HOOK_EVENTS) {
474
+ const entries = hooks?.[definition.event];
475
+ if (!Array.isArray(entries)) continue;
476
+ const ours = entries.flatMap((entry, index) => isPusharyCodexHook(entry) ? [index] : []);
477
+ if (ours.length > 1) vacated[definition.event] = ours[1];
478
+ }
479
+ return vacated;
480
+ };
481
+ var dropVacatedCodexHookTrust = (config, hooksJsonPath, vacated) => {
482
+ const state = asRecord2(asRecord2(config.hooks)?.state);
483
+ if (!state) return false;
484
+ let changed = false;
485
+ for (const [event, from] of Object.entries(vacated)) {
486
+ const prefix = `${hooksJsonPath}:${CODEX_EVENT_KEY[event] ?? codexEventKeyOf(event)}:`;
487
+ for (const key of Object.keys(state)) {
488
+ if (!key.startsWith(prefix)) continue;
489
+ const entryIndex = Number(key.slice(prefix.length).split(":")[0]);
490
+ if (!Number.isInteger(entryIndex) || entryIndex < from) continue;
491
+ delete state[key];
492
+ changed = true;
493
+ }
494
+ }
495
+ return changed;
496
+ };
424
497
  var captureCodexHookTrust = (config, hooksJsonPath, positions) => {
425
- const state = asRecord(asRecord(config.hooks)?.state);
498
+ const state = asRecord2(asRecord2(config.hooks)?.state);
426
499
  if (!state) return {};
427
500
  const snapshot = {};
428
501
  for (const [event, position] of Object.entries(positions)) {
@@ -441,16 +514,16 @@ var restoreCodexHookTrust = (config, hooksJsonPath, positions, snapshot) => {
441
514
  return true;
442
515
  };
443
516
  var codexTrustGaps = (config, hooksConfig, hooksJsonPath, command, positions) => {
444
- const state = asRecord(asRecord(config.hooks)?.state);
445
- const hooks = asRecord(hooksConfig?.hooks);
517
+ const state = asRecord2(asRecord2(config.hooks)?.state);
518
+ const hooks = asRecord2(hooksConfig?.hooks);
446
519
  const gaps = [];
447
520
  for (const definition of CODEX_HOOK_EVENTS) {
448
521
  const position = positions[definition.event];
449
522
  if (!position) continue;
450
- const stored = asRecord(state?.[codexHookStateKey(hooksJsonPath, definition.event, position)])?.trusted_hash;
523
+ const stored = asRecord2(state?.[codexHookStateKey(hooksJsonPath, definition.event, position)])?.trusted_hash;
451
524
  const eventKey = CODEX_EVENT_KEY[definition.event] ?? definition.event;
452
- const onDisk = asRecord(
453
- asRecord(hooks?.[definition.event]) ?? (Array.isArray(hooks?.[definition.event]) ? hooks[definition.event][position[0]] : void 0)
525
+ const onDisk = asRecord2(
526
+ asRecord2(hooks?.[definition.event]) ?? (Array.isArray(hooks?.[definition.event]) ? hooks[definition.event][position[0]] : void 0)
454
527
  );
455
528
  const diskHash = onDisk ? codexEntryTrustHash(eventKey, onDisk) : void 0;
456
529
  if (stored !== void 0 && diskHash !== void 0 && stored === diskHash) {
@@ -466,14 +539,14 @@ var codexTrustGaps = (config, hooksConfig, hooksJsonPath, command, positions) =>
466
539
  return gaps;
467
540
  };
468
541
  var removeCodexMcpServer = (config) => {
469
- const servers = asRecord(config.mcp_servers);
542
+ const servers = asRecord2(config.mcp_servers);
470
543
  if (!servers?.pushary) return false;
471
544
  delete servers.pushary;
472
545
  if (Object.keys(servers).length === 0) delete config.mcp_servers;
473
546
  return true;
474
547
  };
475
548
  var removeCodexHookTrust = (config, hooksJsonPath, positions) => {
476
- const state = asRecord(asRecord(config.hooks)?.state);
549
+ const state = asRecord2(asRecord2(config.hooks)?.state);
477
550
  if (!state) return false;
478
551
  let changed = false;
479
552
  for (const definition of CODEX_HOOK_EVENTS) {
@@ -486,7 +559,7 @@ var removeCodexHookTrust = (config, hooksJsonPath, positions) => {
486
559
  }
487
560
  }
488
561
  if (changed && Object.keys(state).length === 0) {
489
- const hooks = asRecord(config.hooks);
562
+ const hooks = asRecord2(config.hooks);
490
563
  if (hooks) {
491
564
  delete hooks.state;
492
565
  if (Object.keys(hooks).length === 0) delete config.hooks;
@@ -507,7 +580,7 @@ var addCodexHookTrust = (config, hooksJsonPath, command, positions) => {
507
580
  if (!position) continue;
508
581
  const key = codexHookStateKey(hooksJsonPath, definition.event, position);
509
582
  const ours = codexHookTrustHash(definition, command);
510
- const existing = asRecord(state[key]) ?? {};
583
+ const existing = asRecord2(state[key]) ?? {};
511
584
  state[key] = { ...existing, trusted_hash: ours };
512
585
  for (const stale of staleTrustKeys(state, hooksJsonPath, definition.event, key, ours)) {
513
586
  delete state[stale];
@@ -517,7 +590,7 @@ var addCodexHookTrust = (config, hooksJsonPath, command, positions) => {
517
590
  var staleTrustKeys = (state, hooksJsonPath, event, currentKey, ourHash) => {
518
591
  const prefix = `${hooksJsonPath}:${CODEX_EVENT_KEY[event]}:`;
519
592
  return Object.keys(state).filter(
520
- (key) => key !== currentKey && key.startsWith(prefix) && asRecord(state[key])?.trusted_hash === ourHash
593
+ (key) => key !== currentKey && key.startsWith(prefix) && asRecord2(state[key])?.trusted_hash === ourHash
521
594
  );
522
595
  };
523
596
 
@@ -546,6 +619,9 @@ var geminiMd = () => join3(homedir2(), ".gemini", "GEMINI.md");
546
619
  var pusharyConfigFile = () => join3(homedir2(), ".pushary", "config.json");
547
620
 
548
621
  export {
622
+ registeredCommands,
623
+ namesOurBinary,
624
+ registrationHolderOf,
549
625
  npmErrorMessage,
550
626
  execNpm,
551
627
  resolveGlobalBinary,
@@ -559,6 +635,7 @@ export {
559
635
  guardBinary,
560
636
  guardCursorGate,
561
637
  guardedArgv,
638
+ registerHookEntry,
562
639
  isProtectedByScope,
563
640
  canonicalJson,
564
641
  CODEX_HOOK_BINARY,
@@ -571,12 +648,15 @@ export {
571
648
  CODEX_HOOK_EVENTS,
572
649
  addCodexMcpServer,
573
650
  readCodexMcpAuth,
651
+ codexRegistrationHolder,
574
652
  addCodexHooks,
575
653
  removeCodexHooks,
576
654
  hasCodexHooks,
577
655
  missingCodexHookEvents,
578
656
  codexTrustSchemeAgrees,
579
657
  codexHookPositions,
658
+ codexVacatedIndexes,
659
+ dropVacatedCodexHookTrust,
580
660
  captureCodexHookTrust,
581
661
  restoreCodexHookTrust,
582
662
  codexTrustGaps,
@@ -2,24 +2,24 @@ import {
2
2
  detectProviderLiveCapabilities,
3
3
  hasSpawnProvider,
4
4
  resolveControlPolicy
5
- } from "./chunk-DNLFSRCF.js";
5
+ } from "./chunk-WGV3VY7O.js";
6
6
  import {
7
7
  daemonHasRemoteProof,
8
8
  daemonServiceManagerAvailable,
9
9
  hasDaemonServiceDefinition,
10
10
  readDaemonNeedsLogin,
11
11
  readDaemonStatus
12
- } from "./chunk-LYWTLNMG.js";
12
+ } from "./chunk-CRFLU455.js";
13
13
  import {
14
14
  getMachineId
15
- } from "./chunk-IZKCA35M.js";
15
+ } from "./chunk-562UJ2DA.js";
16
16
  import {
17
17
  getPackageVersion
18
18
  } from "./chunk-DINDL2CF.js";
19
19
  import {
20
20
  readControlMode,
21
21
  readKeySource
22
- } from "./chunk-VF7YOT2W.js";
22
+ } from "./chunk-4PBCNVI3.js";
23
23
  import {
24
24
  getBaseUrl
25
25
  } from "./chunk-2UMNXADU.js";