@pushary/agent-hooks 1.8.3 → 1.9.1

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 (98) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/bin/pushary-bell-hook.js +23 -23
  3. package/dist/bin/pushary-bell.js +9 -9
  4. package/dist/bin/pushary-claude.js +26 -26
  5. package/dist/bin/pushary-clean.js +28 -28
  6. package/dist/bin/pushary-codex-bridge.js +18 -18
  7. package/dist/bin/pushary-codex-hook.js +31 -31
  8. package/dist/bin/pushary-codex.js +13 -13
  9. package/dist/bin/pushary-connect.js +13 -13
  10. package/dist/bin/pushary-cowork.js +5 -5
  11. package/dist/bin/pushary-daemon.js +26 -26
  12. package/dist/bin/pushary-disconnect.js +18 -18
  13. package/dist/bin/pushary-doctor.js +30 -30
  14. package/dist/bin/pushary-elicitation-hook.js +25 -25
  15. package/dist/bin/pushary-gemini-bridge.js +13 -13
  16. package/dist/bin/pushary-gemini-hook.js +28 -28
  17. package/dist/bin/pushary-hook.js +32 -32
  18. package/dist/bin/pushary-login.js +12 -12
  19. package/dist/bin/pushary-logout.js +7 -7
  20. package/dist/bin/pushary-mcp.js +9 -9
  21. package/dist/bin/pushary-mode.js +9 -9
  22. package/dist/bin/pushary-notification-hook.js +28 -28
  23. package/dist/bin/pushary-opencode-hook.js +27 -27
  24. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  25. package/dist/bin/pushary-permission-hook.js +31 -31
  26. package/dist/bin/pushary-post-hook.js +28 -28
  27. package/dist/bin/pushary-prompt-hook.js +28 -28
  28. package/dist/bin/pushary-session-end-hook.js +28 -28
  29. package/dist/bin/pushary-session-start-hook.js +31 -31
  30. package/dist/bin/pushary-setup.js +53 -38
  31. package/dist/bin/pushary-stats.js +5 -5
  32. package/dist/bin/pushary-status.js +15 -15
  33. package/dist/bin/pushary-stop-hook.js +28 -28
  34. package/dist/bin/pushary-stopfailure-hook.js +28 -28
  35. package/dist/bin/pushary-suggestions.js +4 -4
  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 +42 -394
  39. package/dist/bin/pushary-wait.js +9 -9
  40. package/dist/bin/pushary.js +6 -6
  41. package/dist/{chunk-ON5JW2HP.js → chunk-4SB46XLF.js} +1 -1
  42. package/dist/{chunk-HMNR7B2F.js → chunk-4XT4JXMG.js} +1 -1
  43. package/dist/{chunk-YOYSXLUB.js → chunk-5K43TBK4.js} +3 -3
  44. package/dist/{chunk-ZOKXZ3AS.js → chunk-65TOHCXT.js} +4 -4
  45. package/dist/{chunk-4CW5EAOI.js → chunk-6JTTJIKJ.js} +3 -3
  46. package/dist/{chunk-6SS74UHS.js → chunk-6L7TNZ43.js} +1 -1
  47. package/dist/{chunk-EJXEHNB5.js → chunk-6Q4NM2LW.js} +3 -3
  48. package/dist/{chunk-5Y2DY6X4.js → chunk-6QSDNXGM.js} +2 -2
  49. package/dist/{chunk-72WOCX22.js → chunk-7ER66HZH.js} +1 -1
  50. package/dist/{chunk-OLYTGVCC.js → chunk-AKCJ5SNO.js} +6 -6
  51. package/dist/{chunk-N6JJJTPH.js → chunk-C6PPDKVI.js} +3 -3
  52. package/dist/{chunk-VI55VXDH.js → chunk-CE4UH4AP.js} +2 -2
  53. package/dist/{chunk-NOLPURUI.js → chunk-CGRPHFOV.js} +1 -1
  54. package/dist/{chunk-XH7UNEHO.js → chunk-COSADFEH.js} +1 -1
  55. package/dist/{chunk-YLJ26RR2.js → chunk-D3RS57MN.js} +3 -3
  56. package/dist/{chunk-6UDK5TY6.js → chunk-DMA3QUOB.js} +3 -3
  57. package/dist/{chunk-URNXU3FO.js → chunk-FJPC35OW.js} +1 -1
  58. package/dist/{chunk-35X5UDML.js → chunk-FVOCQSBG.js} +1 -1
  59. package/dist/{chunk-FBTUF2PH.js → chunk-GHKNUQYU.js} +2 -2
  60. package/dist/{chunk-DLEKCAQL.js → chunk-HU2LWGEE.js} +1 -1
  61. package/dist/{chunk-SOUJG6UY.js → chunk-IITCMJ4G.js} +2 -2
  62. package/dist/{chunk-MSMKCO4Y.js → chunk-IJXJW2VH.js} +10 -10
  63. package/dist/{chunk-DMU5E6HJ.js → chunk-J7JXA2LX.js} +1 -1
  64. package/dist/{chunk-4DYHBXX4.js → chunk-JCER3Q6P.js} +9 -9
  65. package/dist/{chunk-CB23AO4D.js → chunk-JGQ2ANHQ.js} +2 -2
  66. package/dist/{chunk-AKCE6ZRF.js → chunk-JHZAZAI3.js} +5 -5
  67. package/dist/{chunk-27A7L4DA.js → chunk-KR5JASA4.js} +2 -2
  68. package/dist/{chunk-VF3X4MDB.js → chunk-LJI7U6PM.js} +2 -2
  69. package/dist/{chunk-7U7ZWUTR.js → chunk-LKKYRNJT.js} +1 -1
  70. package/dist/{chunk-MYHG7PX2.js → chunk-LXWUYG7D.js} +1 -1
  71. package/dist/{chunk-VUP5BMOD.js → chunk-LZMH4EGE.js} +1 -1
  72. package/dist/{chunk-CTNLP4A5.js → chunk-NVLXK2I6.js} +5 -5
  73. package/dist/{chunk-7ITOAMCD.js → chunk-P7YDVWLL.js} +1 -1
  74. package/dist/{chunk-IEXWWAJY.js → chunk-PEGKBNGN.js} +5 -5
  75. package/dist/{chunk-UMMCHS6P.js → chunk-PMS3EBD2.js} +1 -1
  76. package/dist/chunk-QQJCDRD3.js +242 -0
  77. package/dist/chunk-QXL27RY6.js +175 -0
  78. package/dist/{chunk-TJMAXQ5Q.js → chunk-RJ7ECJSZ.js} +2 -2
  79. package/dist/{chunk-VFFHQC7W.js → chunk-RNDFGHSQ.js} +1 -1
  80. package/dist/{chunk-4SJIPHR3.js → chunk-RS4ZOFSF.js} +10 -7
  81. package/dist/{chunk-HVDMGDYV.js → chunk-SKEP3M6M.js} +2 -2
  82. package/dist/{chunk-UXKXGRKG.js → chunk-SPB3QRE7.js} +4 -4
  83. package/dist/{chunk-CXYKQAL2.js → chunk-SWGY5WNX.js} +5 -5
  84. package/dist/{chunk-E5JGQGLD.js → chunk-UPTEPARD.js} +2 -2
  85. package/dist/{chunk-CHMOVJ2M.js → chunk-UYHLMBPQ.js} +1 -1
  86. package/dist/{chunk-XNJ4MQF3.js → chunk-V4H33GBM.js} +6 -6
  87. package/dist/{chunk-34EQOFMH.js → chunk-VH6763OR.js} +3 -3
  88. package/dist/{chunk-DXBS2EL7.js → chunk-VQLWYKX7.js} +1 -1
  89. package/dist/{chunk-SD6OLZJX.js → chunk-WWDPULS3.js} +8 -8
  90. package/dist/{chunk-5YY3IJT4.js → chunk-XEIV5QOT.js} +92 -23
  91. package/dist/{chunk-APURTMSW.js → chunk-XW2B4QV2.js} +2 -2
  92. package/dist/{chunk-ZR7LIQKO.js → chunk-ZMKEKWNR.js} +70 -49
  93. package/dist/global-upgrade-ML2RHV4W.js +24 -0
  94. package/dist/paths-LG3IEDDM.js +71 -0
  95. package/dist/{reapply-DYOQAVUP.js → reapply-7PFOITE4.js} +8 -8
  96. package/dist/src/index.js +20 -20
  97. package/dist/upgrade-lock-2A2YUUEU.js +17 -0
  98. package/package.json +1 -1
@@ -6,38 +6,38 @@ import {
6
6
  } from "./chunk-SGZJ5LYH.js";
7
7
  import {
8
8
  hookOwnerOf
9
- } from "./chunk-ZOKXZ3AS.js";
9
+ } from "./chunk-65TOHCXT.js";
10
10
  import {
11
11
  ensureDaemonRunning
12
- } from "./chunk-IEXWWAJY.js";
12
+ } from "./chunk-PEGKBNGN.js";
13
13
  import {
14
14
  buildTranscriptRecords,
15
15
  decodePublicKey,
16
16
  generateSessionKey,
17
17
  wrapSessionKey
18
- } from "./chunk-URNXU3FO.js";
18
+ } from "./chunk-FJPC35OW.js";
19
19
  import {
20
20
  fetchTranscriptRecipients,
21
21
  uploadTranscriptRecords
22
- } from "./chunk-UMMCHS6P.js";
22
+ } from "./chunk-PMS3EBD2.js";
23
23
  import {
24
24
  transcriptEnvironmentPreference,
25
25
  transcriptsEnabled
26
- } from "./chunk-72WOCX22.js";
26
+ } from "./chunk-7ER66HZH.js";
27
27
  import {
28
28
  readTranscriptPreference
29
- } from "./chunk-TJMAXQ5Q.js";
29
+ } from "./chunk-RJ7ECJSZ.js";
30
30
  import {
31
31
  codexHome,
32
32
  pusharyDir
33
- } from "./chunk-ZR7LIQKO.js";
33
+ } from "./chunk-ZMKEKWNR.js";
34
34
  import {
35
35
  writeJsonAtomic
36
36
  } from "./chunk-T7E75EKA.js";
37
37
  import {
38
38
  getApiKey,
39
39
  getBaseUrl
40
- } from "./chunk-ON5JW2HP.js";
40
+ } from "./chunk-4SB46XLF.js";
41
41
 
42
42
  // src/transcript-registration.ts
43
43
  import { createHash } from "crypto";
@@ -532,6 +532,18 @@ var degradedLine = (subsystem, report) => `${DEGRADED_PREFIX} ${JSON.stringify(d
532
532
 
533
533
  // ../contracts/src/setup-wire.ts
534
534
  var PAIR_TTL_SECONDS = 900;
535
+ var computerOsOfPlatform = (platform) => {
536
+ switch (platform) {
537
+ case "darwin":
538
+ return "mac";
539
+ case "win32":
540
+ return "windows";
541
+ case "linux":
542
+ return "linux";
543
+ default:
544
+ return null;
545
+ }
546
+ };
535
547
  var SETUP_AGENT_CHOICES = [
536
548
  "claude_code",
537
549
  "codex",
@@ -544,6 +556,8 @@ var SETUP_AGENT_CHOICES = [
544
556
  ...COMPATIBLE_AGENT_TYPES,
545
557
  "custom"
546
558
  ];
559
+ var isComputerAgent = (agent) => agent !== "custom";
560
+ var NO_PAIRING_COMPUTER = { computerName: null, os: null, agents: null };
547
561
  var SETUP_CONNECT_MODES = ["app", "browser", "web", "none"];
548
562
  var isSetupConnectMode = (value) => typeof value === "string" && SETUP_CONNECT_MODES.includes(value);
549
563
 
@@ -1172,6 +1186,7 @@ var isSafeSimpleCommand = (segment) => {
1172
1186
  if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(first) || first.includes("$")) return false;
1173
1187
  if (!isTrustedExecutable(first)) return false;
1174
1188
  const exe = basenameOf(first);
1189
+ if (INSPECTED_ARGUMENT_COMMANDS.has(exe) && argumentsMayExpand(segment)) return false;
1175
1190
  if (exe === "git") {
1176
1191
  const sub = tokens[1];
1177
1192
  if (!sub || sub.startsWith("-")) return false;
@@ -1186,25 +1201,73 @@ var isSafeSimpleCommand = (segment) => {
1186
1201
  }
1187
1202
  return true;
1188
1203
  }
1204
+ if (exe === "sed") return isPrintOnlySed(tokens.slice(1));
1205
+ if (exe === "date") return isReadOnlyDate(tokens.slice(1));
1189
1206
  return SAFE_SHELL_COMMANDS.has(exe);
1190
1207
  };
1208
+ var SED_PRINT_ONLY_SCRIPT = /^(?:\d+|\$)(?:,(?:\d+|\$))?p$/;
1209
+ var SED_QUIET_FLAG = "-n";
1210
+ var DATE_FORMAT_PREFIX = "+";
1211
+ var DATE_UTC_FLAG = "-u";
1212
+ var isFlagToken = (token) => token.startsWith("-");
1213
+ var isPrintOnlySed = (args) => args[0] === SED_QUIET_FLAG && SED_PRINT_ONLY_SCRIPT.test(args[1] ?? "") && !args.slice(2).some(isFlagToken);
1214
+ var isReadOnlyDate = (args) => args.every((arg) => arg.startsWith(DATE_FORMAT_PREFIX) || arg === DATE_UTC_FLAG);
1215
+ var SINGLE_QUOTE = "'";
1216
+ var QUOTED_LITERAL = "_";
1217
+ var LITERAL_IN_DOUBLE_QUOTES = /* @__PURE__ */ new Set([";", "|", "&", "<", ">", "*", "?", "[", SHELL_ESCAPE]);
1218
+ var READ_ONLY_SEGMENT_SEPARATOR = /&&|\|\||[;|]/g;
1219
+ var PIPELINE_CHAIN_SEPARATOR = /&&|\|\||;/g;
1220
+ var shellVisibleText = (command) => {
1221
+ let visible = "";
1222
+ let quote = null;
1223
+ for (let index = 0; index < command.length; index += 1) {
1224
+ const char = command[index];
1225
+ if (quote === SINGLE_QUOTE) {
1226
+ quote = char === SINGLE_QUOTE ? null : quote;
1227
+ visible += quote === null ? char : QUOTED_LITERAL;
1228
+ continue;
1229
+ }
1230
+ if (quote === SHELL_DOUBLE_QUOTE) {
1231
+ if (char === SHELL_ESCAPE && DOUBLE_QUOTE_ESCAPABLE.has(command[index + 1] ?? "")) return null;
1232
+ quote = char === SHELL_DOUBLE_QUOTE ? null : quote;
1233
+ visible += quote !== null && LITERAL_IN_DOUBLE_QUOTES.has(char) ? QUOTED_LITERAL : char;
1234
+ continue;
1235
+ }
1236
+ if (SHELL_QUOTES.has(char)) quote = char;
1237
+ visible += char;
1238
+ }
1239
+ return quote === null ? visible : null;
1240
+ };
1241
+ var EXPANSION_THAT_CAN_BECOME_A_FLAG = /\$|(?:^|\s)[*?[]/;
1242
+ var SHELL_QUOTE_CHARACTERS = /['"]/g;
1243
+ var INSPECTED_ARGUMENT_COMMANDS = /* @__PURE__ */ new Set(["git", "find", "sed", "date"]);
1244
+ var argumentsMayExpand = (segment) => {
1245
+ const visible = shellVisibleText(segment);
1246
+ return visible === null || EXPANSION_THAT_CAN_BECOME_A_FLAG.test(visible.replace(SHELL_QUOTE_CHARACTERS, ""));
1247
+ };
1248
+ var blankedSafeRedirections = (text) => text.replace(SAFE_REDIRECTION, (redirection) => " ".repeat(redirection.length));
1249
+ var segmentsSplitWhereVisible = (command, visible, separators) => {
1250
+ const segments = [];
1251
+ let start = 0;
1252
+ for (const separator of visible.matchAll(separators)) {
1253
+ segments.push(command.slice(start, separator.index));
1254
+ start = separator.index + separator[0].length;
1255
+ }
1256
+ segments.push(command.slice(start));
1257
+ return segments;
1258
+ };
1191
1259
  var isSafeReadOnlyCommand = (command) => {
1192
1260
  const trimmed = command.trim();
1193
1261
  if (!trimmed || trimmed.length > 2e3) return false;
1194
- if (/[`\n\r{}]/.test(trimmed)) return false;
1195
- if (/;|\|\|/.test(trimmed)) return false;
1196
- if (/\\(?![()!])/.test(trimmed)) return false;
1197
- if (/(?<!\\)[()]/.test(trimmed)) return false;
1198
- const noRedir = trimmed.replace(SAFE_REDIRECTION, " ");
1199
- if (/[<>]/.test(noRedir)) return false;
1200
- if (noRedir.replace(/&&/g, " ").includes("&")) return false;
1201
- for (const andPart of noRedir.split("&&")) {
1202
- if (!andPart.trim()) return false;
1203
- for (const segment of andPart.split("|")) {
1204
- if (!isSafeSimpleCommand(segment)) return false;
1205
- }
1206
- }
1207
- return true;
1262
+ if (/[\n\r]/.test(trimmed)) return false;
1263
+ const visible = shellVisibleText(trimmed);
1264
+ if (visible === null || /[`{}]|\$'/.test(visible)) return false;
1265
+ if (/\\(?![()!])/.test(visible)) return false;
1266
+ if (/(?<!\\)[()]/.test(visible)) return false;
1267
+ const visibleWithoutRedirection = blankedSafeRedirections(visible);
1268
+ if (/[<>]/.test(visibleWithoutRedirection)) return false;
1269
+ if (visibleWithoutRedirection.replace(/&&/g, " ").includes("&")) return false;
1270
+ return segmentsSplitWhereVisible(blankedSafeRedirections(trimmed), visibleWithoutRedirection, READ_ONLY_SEGMENT_SEPARATOR).every((segment) => segment.trim().length > 0 && isSafeSimpleCommand(segment));
1208
1271
  };
1209
1272
  var isAutoApprove = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "approve";
1210
1273
  var isAutoDeny = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "deny";
@@ -1528,6 +1591,7 @@ var segmentNeedsAPerson = (toolName, segment) => {
1528
1591
  return invocationHidesItsEffect(invocation) || subcommandDestroys(invocation) || classifyDecisionRisk(toolName, normalized) !== "standard" || isCoveredByPolicy(CAPABILITY_PATTERNS.destructive, toolName, normalized) || isCoveredByPolicy(CAPABILITY_PATTERNS.network, toolName, normalized) || isCoveredByPolicy(DATA_LOSS_COMMAND_PATTERNS, toolName, normalized);
1529
1592
  };
1530
1593
  var commandNeedsAPerson = (toolName, command) => {
1594
+ if (toolName === "Bash" && isSafeReadOnlyCommand(command)) return false;
1531
1595
  const segments = readableCommandSegments(command);
1532
1596
  return segments === null || classifyDecisionRisk(toolName, command) !== "standard" || segments.some((segment) => segmentNeedsAPerson(toolName, segment));
1533
1597
  };
@@ -1605,11 +1669,7 @@ ${body}`;
1605
1669
  const highConsequence = HIGH_CONSEQUENCE_PATTERNS.some((re) => re.test(scanText));
1606
1670
  return { isCommand: command, commandText, path, highConsequence };
1607
1671
  };
1608
- var isDestructive = (toolName, commandText) => {
1609
- const haystack = `${toolName ?? ""}
1610
- ${commandText}`;
1611
- return APPROVAL_FATIGUE_FLAG_PATTERNS.some((re) => re.test(haystack));
1612
- };
1672
+ var isDestructive = (toolName, commandText) => namesADestructiveAction(toolName ?? "", commandText);
1613
1673
  var addAlnumTokens = (source, set) => {
1614
1674
  for (const raw of source.toLowerCase().split(/[^a-z0-9]+/)) {
1615
1675
  if (raw) set.add(raw);
@@ -1762,11 +1822,17 @@ var SETTLED_OUTCOME = {
1762
1822
  deny: "deny"
1763
1823
  };
1764
1824
  var isSettledOutcome = (value) => typeof value === "string" && SETTLED_OUTCOMES.includes(value);
1825
+ var commandTextThatCanAct = (command) => {
1826
+ const visible = shellVisibleText(command);
1827
+ return visible === null ? command : segmentsSplitWhereVisible(command, visible, PIPELINE_CHAIN_SEPARATOR).filter((pipeline) => !isSafeReadOnlyCommand(pipeline)).join("\n");
1828
+ };
1829
+ var destructiveKeywordTarget = (toolName, toolTarget) => toolName === "Bash" ? commandTextThatCanAct(toolTarget) : toolTarget;
1830
+ var matchesAnyPattern = (patterns, parts) => parts.some((part) => patterns.some((re) => re.test(part)));
1831
+ var namesADestructiveAction = (toolName, toolTarget) => matchesAnyPattern(APPROVAL_FATIGUE_FLAG_PATTERNS, [toolName, destructiveKeywordTarget(toolName, toolTarget)]);
1765
1832
  var classifyDecisionRisk = (toolName, toolTarget) => {
1766
- const parts = [toolName, toolTarget ?? ""];
1767
- const matchesAny = (patterns) => parts.some((part) => patterns.some((re) => re.test(part)));
1768
- if (matchesAny(APPROVAL_FATIGUE_FLAG_PATTERNS)) return "destructive";
1769
- if (matchesAny(HIGH_CONSEQUENCE_PATTERNS)) return "elevated";
1833
+ const target = toolTarget ?? "";
1834
+ if (namesADestructiveAction(toolName, target)) return "destructive";
1835
+ if (matchesAnyPattern(HIGH_CONSEQUENCE_PATTERNS, [toolName, target])) return "elevated";
1770
1836
  return "standard";
1771
1837
  };
1772
1838
  var POLICY_CAPABILITIES = ["read", "edit", "shell", "network", "destructive"];
@@ -2727,7 +2793,10 @@ export {
2727
2793
  isHookActivationReport,
2728
2794
  hookActivationResult,
2729
2795
  PAIR_TTL_SECONDS,
2796
+ computerOsOfPlatform,
2730
2797
  SETUP_AGENT_CHOICES,
2798
+ isComputerAgent,
2799
+ NO_PAIRING_COMPUTER,
2731
2800
  SETUP_CONNECT_MODES,
2732
2801
  isSetupConnectMode,
2733
2802
  CLIENT_REPORT_PATH,
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  pusharyHookExecutable
3
- } from "./chunk-YOYSXLUB.js";
3
+ } from "./chunk-5K43TBK4.js";
4
4
  import {
5
5
  isProtectedByScope,
6
6
  registerHookEntry
7
- } from "./chunk-ZR7LIQKO.js";
7
+ } from "./chunk-ZMKEKWNR.js";
8
8
 
9
9
  // src/skills-cli.ts
10
10
  import { execSync } from "child_process";
@@ -13,7 +13,45 @@ import {
13
13
  isReleaseVersion,
14
14
  ownPackageName,
15
15
  withHookHoldBudget
16
- } from "./chunk-5YY3IJT4.js";
16
+ } from "./chunk-XEIV5QOT.js";
17
+
18
+ // src/setup/paths.ts
19
+ import { homedir as homedir2 } from "os";
20
+ import { join as join3 } from "path";
21
+
22
+ // src/codex-config.ts
23
+ import { createHash } from "crypto";
24
+ import { homedir } from "os";
25
+ import { join as join2 } from "path";
26
+
27
+ // src/registration-holder.ts
28
+ var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
29
+ var registeredCommands = (document) => {
30
+ const hooks = asRecord(document?.hooks);
31
+ if (!hooks) return [];
32
+ const found = [];
33
+ for (const [event, value] of Object.entries(hooks)) {
34
+ if (!Array.isArray(value)) continue;
35
+ for (const item of value) {
36
+ const inner = asRecord(item)?.hooks;
37
+ if (!Array.isArray(inner)) continue;
38
+ for (const hook of inner) {
39
+ const command = asRecord(hook)?.command;
40
+ if (typeof command === "string") found.push({ event, command });
41
+ }
42
+ }
43
+ }
44
+ return found;
45
+ };
46
+ var wholeSegments = (command) => command.split(/[\s/\\"']+/).map((segment) => segment.replace(/\.(cmd|exe)$/i, ""));
47
+ var namesLocator = (command) => wholeSegments(command).includes(HOOK_LOCATOR_BINARY);
48
+ var namesCliBinary = (command, cliBinaries) => wholeSegments(command).some((segment) => cliBinaries.has(segment));
49
+ var namesOurBinary = (command, cliBinaries) => namesLocator(command) || namesCliBinary(command, cliBinaries);
50
+ var registrationHolderOf = (document, cliBinaries) => {
51
+ const commands = registeredCommands(document);
52
+ if (commands.some(({ command }) => namesLocator(command))) return "app";
53
+ return commands.some(({ command }) => namesCliBinary(command, cliBinaries)) ? "cli" : "none";
54
+ };
17
55
 
18
56
  // src/npm.ts
19
57
  import { promisify } from "util";
@@ -327,19 +365,32 @@ var installGlobally = (options) => {
327
365
  }
328
366
  const started = (async () => {
329
367
  if (!npmIsOnPath()) throw new NpmMissingError();
330
- const platform = process.platform;
331
- const { prefix, packageName } = planGlobalInstall(platform);
332
- const pinned = process.env.PUSHARY_PIN_GLOBAL_VERSION !== "0";
333
- if (pinned && prefix !== void 0 && !needsGlobalInstall(
334
- options.version,
335
- installedVersionOf(prefix, packageName, platform),
336
- globalPackageBinsPresent(packageName, prefix, platform)
337
- )) {
338
- return "skipped";
368
+ const { withUpgradeLock } = await import("./global-upgrade-ML2RHV4W.js");
369
+ const { installWithUpgradeLock, ownsUpgradeLock } = await import("./upgrade-lock-2A2YUUEU.js");
370
+ const { autoUpdateLock: autoUpdateLock2 } = await import("./paths-LG3IEDDM.js");
371
+ let result = "skipped";
372
+ const install = async () => {
373
+ const platform = process.platform;
374
+ const { prefix, packageName } = planGlobalInstall(platform);
375
+ const pinned = process.env.PUSHARY_PIN_GLOBAL_VERSION !== "0";
376
+ if (pinned && prefix !== void 0 && !needsGlobalInstall(
377
+ options.version,
378
+ installedVersionOf(prefix, packageName, platform),
379
+ globalPackageBinsPresent(packageName, prefix, platform)
380
+ )) {
381
+ return;
382
+ }
383
+ const version = pinned && options.version && options.version !== "0.0.0" ? options.version : LATEST_TAG;
384
+ installWithUpgradeLock({ packageName, version, timeoutMs: options.timeoutMs ?? 12e4 }, options.lockPath);
385
+ result = "installed";
386
+ };
387
+ if (ownsUpgradeLock(options.lockPath ?? autoUpdateLock2())) {
388
+ await install();
389
+ } else {
390
+ const lock = await withUpgradeLock(install, options);
391
+ if (lock.kind === "refused") throw new Error(lock.message);
339
392
  }
340
- const version = pinned && options.version && options.version !== "0.0.0" ? options.version : LATEST_TAG;
341
- installPackageGlobally({ packageName, version, timeoutMs: options.timeoutMs ?? 12e4 });
342
- return "installed";
393
+ return result;
343
394
  })();
344
395
  installState = started;
345
396
  started.catch(() => {
@@ -397,40 +448,6 @@ var guardedArgv = (target, args = [], platform = process.platform) => {
397
448
  return [shell, ...shellArgs, HOOK_GUARD_SCRIPTS[guardKindOf(target)], path, ...args];
398
449
  };
399
450
 
400
- // src/codex-config.ts
401
- import { createHash } from "crypto";
402
- import { homedir } from "os";
403
- import { join as join2 } from "path";
404
-
405
- // src/registration-holder.ts
406
- var asRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
407
- var registeredCommands = (document) => {
408
- const hooks = asRecord(document?.hooks);
409
- if (!hooks) return [];
410
- const found = [];
411
- for (const [event, value] of Object.entries(hooks)) {
412
- if (!Array.isArray(value)) continue;
413
- for (const item of value) {
414
- const inner = asRecord(item)?.hooks;
415
- if (!Array.isArray(inner)) continue;
416
- for (const hook of inner) {
417
- const command = asRecord(hook)?.command;
418
- if (typeof command === "string") found.push({ event, command });
419
- }
420
- }
421
- }
422
- return found;
423
- };
424
- var wholeSegments = (command) => command.split(/[\s/\\"']+/).map((segment) => segment.replace(/\.(cmd|exe)$/i, ""));
425
- var namesLocator = (command) => wholeSegments(command).includes(HOOK_LOCATOR_BINARY);
426
- var namesCliBinary = (command, cliBinaries) => wholeSegments(command).some((segment) => cliBinaries.has(segment));
427
- var namesOurBinary = (command, cliBinaries) => namesLocator(command) || namesCliBinary(command, cliBinaries);
428
- var registrationHolderOf = (document, cliBinaries) => {
429
- const commands = registeredCommands(document);
430
- if (commands.some(({ command }) => namesLocator(command))) return "app";
431
- return commands.some(({ command }) => namesCliBinary(command, cliBinaries)) ? "cli" : "none";
432
- };
433
-
434
451
  // src/hook-entries.ts
435
452
  var registerHookEntry = (existing, isOurs, entry) => {
436
453
  const rewritten = [];
@@ -759,13 +776,14 @@ var staleTrustKeys = (state, hooksJsonPath, event, currentKey, ourHash) => {
759
776
  };
760
777
 
761
778
  // src/setup/paths.ts
762
- import { homedir as homedir2 } from "os";
763
- import { join as join3 } from "path";
764
779
  var claudeSettings = () => join3(homedir2(), ".claude", "settings.json");
765
780
  var claudeJson = () => join3(homedir2(), ".claude.json");
766
781
  var claudeSkillDir = () => join3(homedir2(), ".claude", "skills", "pushary");
767
782
  var cursorPluginDir = () => join3(homedir2(), ".cursor", "plugins", "local", "pushary");
768
783
  var cursorUserHooks = () => join3(homedir2(), ".cursor", "hooks.json");
784
+ var cursorPluginMcp = () => join3(cursorPluginDir(), "mcp.json");
785
+ var cursorPluginManifest = () => join3(cursorPluginDir(), ".cursor-plugin", "plugin.json");
786
+ var cursorPluginRule = () => join3(cursorPluginDir(), "rules", "pushary.mdc");
769
787
  var cursorUserMcp = () => join3(homedir2(), ".cursor", "mcp.json");
770
788
  var vscodePluginDir = () => join3(homedir2(), ".pushary", "plugins", "vscode");
771
789
  var vscodePluginMcp = () => join3(vscodePluginDir(), ".mcp.json");
@@ -859,6 +877,9 @@ export {
859
877
  claudeSkillDir,
860
878
  cursorPluginDir,
861
879
  cursorUserHooks,
880
+ cursorPluginMcp,
881
+ cursorPluginManifest,
882
+ cursorPluginRule,
862
883
  cursorUserMcp,
863
884
  vscodePluginDir,
864
885
  vscodePluginMcp,
@@ -0,0 +1,24 @@
1
+ import {
2
+ finishGlobalUpgrade,
3
+ finishUpgradeWithLock,
4
+ globalUpgradeSubject,
5
+ readGlobalUpgradeSubject,
6
+ upgradeInstalledPackage,
7
+ withUpgradeLock
8
+ } from "./chunk-QQJCDRD3.js";
9
+ import "./chunk-QXL27RY6.js";
10
+ import "./chunk-CE4UH4AP.js";
11
+ import "./chunk-POFBE6ZY.js";
12
+ import "./chunk-KZERVKTD.js";
13
+ import "./chunk-ZMKEKWNR.js";
14
+ import "./chunk-T7E75EKA.js";
15
+ import "./chunk-FVOCQSBG.js";
16
+ import "./chunk-XEIV5QOT.js";
17
+ export {
18
+ finishGlobalUpgrade,
19
+ finishUpgradeWithLock,
20
+ globalUpgradeSubject,
21
+ readGlobalUpgradeSubject,
22
+ upgradeInstalledPackage,
23
+ withUpgradeLock
24
+ };
@@ -0,0 +1,71 @@
1
+ import {
2
+ autoUpdateLock,
3
+ autoUpdateLog,
4
+ autoUpdateState,
5
+ bridgeAgentKey,
6
+ claudeJson,
7
+ claudeMcpReceipt,
8
+ claudeRegistrationReceipt,
9
+ claudeSettings,
10
+ claudeSettingsLocal,
11
+ claudeSkillDir,
12
+ clientReportClaims,
13
+ codexAgentsMd2 as codexAgentsMd,
14
+ codexSkillDir2 as codexSkillDir,
15
+ cursorPluginDir,
16
+ cursorPluginManifest,
17
+ cursorPluginMcp,
18
+ cursorPluginRule,
19
+ cursorUserHooks,
20
+ cursorUserMcp,
21
+ fxAgentsMd,
22
+ fxConfigDir,
23
+ fxMcpProfile,
24
+ fxQuestionRuleReceipt,
25
+ fxSettings,
26
+ geminiMd,
27
+ geminiSettings,
28
+ hermesConfig,
29
+ hermesConfigReceipt,
30
+ hookTakeoverReceipt,
31
+ pusharyConfigFile,
32
+ pusharyDir,
33
+ vscodePluginDir,
34
+ vscodePluginMcp
35
+ } from "./chunk-ZMKEKWNR.js";
36
+ import "./chunk-XEIV5QOT.js";
37
+ export {
38
+ autoUpdateLock,
39
+ autoUpdateLog,
40
+ autoUpdateState,
41
+ bridgeAgentKey,
42
+ claudeJson,
43
+ claudeMcpReceipt,
44
+ claudeRegistrationReceipt,
45
+ claudeSettings,
46
+ claudeSettingsLocal,
47
+ claudeSkillDir,
48
+ clientReportClaims,
49
+ codexAgentsMd,
50
+ codexSkillDir,
51
+ cursorPluginDir,
52
+ cursorPluginManifest,
53
+ cursorPluginMcp,
54
+ cursorPluginRule,
55
+ cursorUserHooks,
56
+ cursorUserMcp,
57
+ fxAgentsMd,
58
+ fxConfigDir,
59
+ fxMcpProfile,
60
+ fxQuestionRuleReceipt,
61
+ fxSettings,
62
+ geminiMd,
63
+ geminiSettings,
64
+ hermesConfig,
65
+ hermesConfigReceipt,
66
+ hookTakeoverReceipt,
67
+ pusharyConfigFile,
68
+ pusharyDir,
69
+ vscodePluginDir,
70
+ vscodePluginMcp
71
+ };
@@ -9,18 +9,18 @@ import {
9
9
  reapplyGeminiSettings,
10
10
  reapplyVsCodePlugin,
11
11
  repairCodexHolds
12
- } from "./chunk-CXYKQAL2.js";
13
- import "./chunk-27A7L4DA.js";
14
- import "./chunk-EJXEHNB5.js";
12
+ } from "./chunk-SWGY5WNX.js";
13
+ import "./chunk-KR5JASA4.js";
14
+ import "./chunk-6Q4NM2LW.js";
15
15
  import "./chunk-RIVNNBEK.js";
16
- import "./chunk-YOYSXLUB.js";
17
- import "./chunk-YLJ26RR2.js";
16
+ import "./chunk-5K43TBK4.js";
17
+ import "./chunk-D3RS57MN.js";
18
18
  import "./chunk-XHKBHWLX.js";
19
19
  import "./chunk-6ICPEJY5.js";
20
- import "./chunk-VFFHQC7W.js";
21
- import "./chunk-ZR7LIQKO.js";
20
+ import "./chunk-RNDFGHSQ.js";
21
+ import "./chunk-ZMKEKWNR.js";
22
22
  import "./chunk-T7E75EKA.js";
23
- import "./chunk-5YY3IJT4.js";
23
+ import "./chunk-XEIV5QOT.js";
24
24
  export {
25
25
  ensureCodexTrustAfterReapply,
26
26
  inspectConfiguredManagedProviders,
package/dist/src/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  handlePreToolUse
3
- } from "../chunk-MSMKCO4Y.js";
4
- import "../chunk-CTNLP4A5.js";
5
- import "../chunk-EJXEHNB5.js";
6
- import "../chunk-FBTUF2PH.js";
7
- import "../chunk-7ITOAMCD.js";
3
+ } from "../chunk-IJXJW2VH.js";
4
+ import "../chunk-NVLXK2I6.js";
5
+ import "../chunk-6Q4NM2LW.js";
6
+ import "../chunk-GHKNUQYU.js";
7
+ import "../chunk-P7YDVWLL.js";
8
8
  import "../chunk-5OP5MQI7.js";
9
- import "../chunk-YLJ26RR2.js";
9
+ import "../chunk-D3RS57MN.js";
10
10
  import {
11
11
  fetchAccountPublicKey
12
- } from "../chunk-UMMCHS6P.js";
12
+ } from "../chunk-PMS3EBD2.js";
13
13
  import "../chunk-6ICPEJY5.js";
14
14
  import {
15
15
  fetchModeOverride,
@@ -19,33 +19,33 @@ import {
19
19
  handlePostToolUse,
20
20
  handleStop,
21
21
  reportEvent
22
- } from "../chunk-4DYHBXX4.js";
22
+ } from "../chunk-JCER3Q6P.js";
23
23
  import "../chunk-N6IOSZOE.js";
24
- import "../chunk-VFFHQC7W.js";
24
+ import "../chunk-RNDFGHSQ.js";
25
25
  import {
26
26
  askUser,
27
27
  cancelQuestion,
28
28
  waitForAnswer
29
- } from "../chunk-AKCE6ZRF.js";
30
- import "../chunk-UXKXGRKG.js";
29
+ } from "../chunk-JHZAZAI3.js";
30
+ import "../chunk-SPB3QRE7.js";
31
31
  import "../chunk-POFBE6ZY.js";
32
- import "../chunk-34EQOFMH.js";
33
- import "../chunk-6UDK5TY6.js";
34
- import "../chunk-4CW5EAOI.js";
35
- import "../chunk-DMU5E6HJ.js";
32
+ import "../chunk-VH6763OR.js";
33
+ import "../chunk-DMA3QUOB.js";
34
+ import "../chunk-6JTTJIKJ.js";
35
+ import "../chunk-J7JXA2LX.js";
36
36
  import "../chunk-7QLSKOSU.js";
37
37
  import "../chunk-KZERVKTD.js";
38
- import "../chunk-5Y2DY6X4.js";
39
- import "../chunk-ZR7LIQKO.js";
38
+ import "../chunk-6QSDNXGM.js";
39
+ import "../chunk-ZMKEKWNR.js";
40
40
  import "../chunk-T7E75EKA.js";
41
41
  import {
42
42
  getApiKey,
43
43
  getBaseUrl
44
- } from "../chunk-ON5JW2HP.js";
45
- import "../chunk-35X5UDML.js";
44
+ } from "../chunk-4SB46XLF.js";
45
+ import "../chunk-FVOCQSBG.js";
46
46
  import {
47
47
  resolvePolicy
48
- } from "../chunk-5YY3IJT4.js";
48
+ } from "../chunk-XEIV5QOT.js";
49
49
  export {
50
50
  askUser,
51
51
  cancelQuestion,
@@ -0,0 +1,17 @@
1
+ import {
2
+ claimUpgradeLock,
3
+ finishWithUpgradeLock,
4
+ installWithUpgradeLock,
5
+ ownsUpgradeLock,
6
+ releaseAutoUpdateLock
7
+ } from "./chunk-QXL27RY6.js";
8
+ import "./chunk-ZMKEKWNR.js";
9
+ import "./chunk-T7E75EKA.js";
10
+ import "./chunk-XEIV5QOT.js";
11
+ export {
12
+ claimUpgradeLock,
13
+ finishWithUpgradeLock,
14
+ installWithUpgradeLock,
15
+ ownsUpgradeLock,
16
+ releaseAutoUpdateLock
17
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "1.8.3",
3
+ "version": "1.9.1",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",