@pushary/agent-hooks 1.9.1 → 1.9.3

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 (105) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/data/cursor-plugin/.cursor-plugin/plugin.json +1 -1
  3. package/data/cursor-plugin/CHANGELOG.md +4 -0
  4. package/data/cursor-plugin/scripts/pushary-gate.mjs +1 -1
  5. package/data/vscode-plugin/.claude-plugin/plugin.json +1 -1
  6. package/data/vscode-plugin/CHANGELOG.md +4 -0
  7. package/data/vscode-plugin/scripts/pushary-gate.mjs +1 -1
  8. package/dist/bin/pushary-bell-hook.js +23 -23
  9. package/dist/bin/pushary-bell.js +9 -9
  10. package/dist/bin/pushary-claude.js +26 -26
  11. package/dist/bin/pushary-clean.js +28 -28
  12. package/dist/bin/pushary-codex-bridge.js +18 -18
  13. package/dist/bin/pushary-codex-hook.js +31 -31
  14. package/dist/bin/pushary-codex.js +13 -13
  15. package/dist/bin/pushary-connect.js +13 -13
  16. package/dist/bin/pushary-cowork.js +5 -5
  17. package/dist/bin/pushary-daemon.js +26 -26
  18. package/dist/bin/pushary-disconnect.js +18 -18
  19. package/dist/bin/pushary-doctor.js +99 -48
  20. package/dist/bin/pushary-elicitation-hook.js +25 -25
  21. package/dist/bin/pushary-gemini-bridge.js +13 -13
  22. package/dist/bin/pushary-gemini-hook.js +28 -28
  23. package/dist/bin/pushary-hook.js +32 -32
  24. package/dist/bin/pushary-login.js +26 -23
  25. package/dist/bin/pushary-logout.js +7 -7
  26. package/dist/bin/pushary-mcp.js +9 -9
  27. package/dist/bin/pushary-mode.js +9 -9
  28. package/dist/bin/pushary-notification-hook.js +28 -28
  29. package/dist/bin/pushary-opencode-hook.js +27 -27
  30. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  31. package/dist/bin/pushary-permission-hook.js +31 -31
  32. package/dist/bin/pushary-post-hook.js +28 -28
  33. package/dist/bin/pushary-prompt-hook.js +28 -28
  34. package/dist/bin/pushary-session-end-hook.js +28 -28
  35. package/dist/bin/pushary-session-start-hook.js +31 -31
  36. package/dist/bin/pushary-setup.js +69 -52
  37. package/dist/bin/pushary-stats.js +5 -5
  38. package/dist/bin/pushary-status.js +15 -15
  39. package/dist/bin/pushary-stop-hook.js +28 -28
  40. package/dist/bin/pushary-stopfailure-hook.js +28 -28
  41. package/dist/bin/pushary-suggestions.js +4 -4
  42. package/dist/bin/pushary-transcript-register.js +19 -19
  43. package/dist/bin/pushary-transcripts.js +7 -7
  44. package/dist/bin/pushary-upgrade.js +21 -21
  45. package/dist/bin/pushary-wait.js +9 -9
  46. package/dist/bin/pushary.js +6 -6
  47. package/dist/{chunk-COSADFEH.js → chunk-2UWD2WZC.js} +1 -1
  48. package/dist/{chunk-7ER66HZH.js → chunk-34JHGOYO.js} +1 -1
  49. package/dist/{chunk-4SB46XLF.js → chunk-4GTXFYQ7.js} +1 -1
  50. package/dist/{chunk-P7YDVWLL.js → chunk-552AGATI.js} +1 -1
  51. package/dist/{chunk-ZMKEKWNR.js → chunk-5IIAUWEJ.js} +18 -5
  52. package/dist/{chunk-AKCJ5SNO.js → chunk-7FVC3RGF.js} +17 -12
  53. package/dist/{chunk-DMA3QUOB.js → chunk-7MO3CNBX.js} +3 -3
  54. package/dist/{chunk-IITCMJ4G.js → chunk-AGW7PMMO.js} +2 -2
  55. package/dist/{chunk-WWDPULS3.js → chunk-AMFNJPJ5.js} +8 -8
  56. package/dist/{chunk-LJI7U6PM.js → chunk-AUS3LY4N.js} +2 -2
  57. package/dist/{chunk-RS4ZOFSF.js → chunk-BPGATW2F.js} +7 -6
  58. package/dist/{chunk-JCER3Q6P.js → chunk-CJFVYYKM.js} +10 -9
  59. package/dist/{chunk-D3RS57MN.js → chunk-CVVPUVBD.js} +3 -3
  60. package/dist/{chunk-JGQ2ANHQ.js → chunk-DEWCUHOY.js} +2 -2
  61. package/dist/chunk-EO23EUOK.js +14 -0
  62. package/dist/{chunk-FVOCQSBG.js → chunk-EZFE4PC3.js} +1 -1
  63. package/dist/{chunk-LXWUYG7D.js → chunk-FANGHYW5.js} +1 -1
  64. package/dist/{chunk-SKEP3M6M.js → chunk-FLUECSUC.js} +2 -2
  65. package/dist/{chunk-J7JXA2LX.js → chunk-FSFI2PQL.js} +1 -1
  66. package/dist/{chunk-UPTEPARD.js → chunk-G2YXIZZS.js} +2 -2
  67. package/dist/{chunk-65TOHCXT.js → chunk-GB2U4QVF.js} +4 -4
  68. package/dist/{chunk-CE4UH4AP.js → chunk-GOWCPJTP.js} +7 -5
  69. package/dist/{chunk-RNDFGHSQ.js → chunk-HBUQ2EQD.js} +1 -1
  70. package/dist/{chunk-GHKNUQYU.js → chunk-HIQNUBWO.js} +2 -2
  71. package/dist/{chunk-QXL27RY6.js → chunk-HPXFPXW7.js} +1 -1
  72. package/dist/{chunk-CGRPHFOV.js → chunk-IVF3OVR2.js} +1 -1
  73. package/dist/{chunk-XEIV5QOT.js → chunk-JDUWMJDP.js} +118 -170
  74. package/dist/{chunk-V4H33GBM.js → chunk-JM2MCYRZ.js} +6 -6
  75. package/dist/{chunk-LZMH4EGE.js → chunk-KA2GI53J.js} +1 -1
  76. package/dist/{chunk-SWGY5WNX.js → chunk-KO7UOTLD.js} +5 -5
  77. package/dist/{chunk-HU2LWGEE.js → chunk-MH6SJHUE.js} +1 -1
  78. package/dist/{chunk-XW2B4QV2.js → chunk-NGD7H3GZ.js} +2 -2
  79. package/dist/{chunk-UYHLMBPQ.js → chunk-NP5RJL34.js} +1 -1
  80. package/dist/{chunk-IJXJW2VH.js → chunk-NZJ5LFMX.js} +10 -10
  81. package/dist/{chunk-QQJCDRD3.js → chunk-OEMF3KJ3.js} +5 -5
  82. package/dist/{chunk-6L7TNZ43.js → chunk-OXJRUMZT.js} +1 -1
  83. package/dist/{chunk-C6PPDKVI.js → chunk-P3REVSM5.js} +3 -3
  84. package/dist/{chunk-SPB3QRE7.js → chunk-PPC4FZKJ.js} +4 -4
  85. package/dist/{chunk-FJPC35OW.js → chunk-Q4RF7EEP.js} +1 -1
  86. package/dist/{chunk-4XT4JXMG.js → chunk-Q7FLA4N3.js} +1 -1
  87. package/dist/{chunk-LKKYRNJT.js → chunk-Q7KSRRQ4.js} +1 -1
  88. package/dist/{chunk-KR5JASA4.js → chunk-QVUOPB32.js} +44 -16
  89. package/dist/{chunk-VH6763OR.js → chunk-SJC5TXK7.js} +3 -3
  90. package/dist/{chunk-6QSDNXGM.js → chunk-U3DBAX7P.js} +2 -2
  91. package/dist/{chunk-JHZAZAI3.js → chunk-UWMEY4RS.js} +5 -5
  92. package/dist/{chunk-NVLXK2I6.js → chunk-VRPNTJX3.js} +5 -5
  93. package/dist/{chunk-5K43TBK4.js → chunk-VRYOALHQ.js} +3 -3
  94. package/dist/{chunk-VQLWYKX7.js → chunk-WEK6US33.js} +1 -1
  95. package/dist/{chunk-PEGKBNGN.js → chunk-WL4YO6CO.js} +5 -5
  96. package/dist/{chunk-6JTTJIKJ.js → chunk-WRDMCP4G.js} +3 -3
  97. package/dist/{chunk-RJ7ECJSZ.js → chunk-ZPTSEJMD.js} +4 -2
  98. package/dist/{chunk-6Q4NM2LW.js → chunk-ZUZKHTPJ.js} +3 -3
  99. package/dist/{chunk-PMS3EBD2.js → chunk-ZV32QRBR.js} +1 -1
  100. package/dist/{global-upgrade-ML2RHV4W.js → global-upgrade-VEQ4KQEW.js} +6 -6
  101. package/dist/{paths-LG3IEDDM.js → paths-QTOUBV2V.js} +2 -2
  102. package/dist/{reapply-7PFOITE4.js → reapply-T5PLCAGP.js} +8 -8
  103. package/dist/src/index.js +20 -20
  104. package/dist/{upgrade-lock-2A2YUUEU.js → upgrade-lock-KFZBAPNU.js} +3 -3
  105. package/package.json +1 -1
@@ -3,10 +3,10 @@ import {
3
3
  } from "./chunk-KZERVKTD.js";
4
4
  import {
5
5
  renderCommandHelp
6
- } from "./chunk-FVOCQSBG.js";
6
+ } from "./chunk-EZFE4PC3.js";
7
7
  import {
8
8
  getPackageVersion
9
- } from "./chunk-XEIV5QOT.js";
9
+ } from "./chunk-JDUWMJDP.js";
10
10
 
11
11
  // src/cli/usage.ts
12
12
  var exitOnHelpFlag = (command) => {
@@ -0,0 +1,14 @@
1
+ // src/cli/json.ts
2
+ var writeStdoutFully = (text) => new Promise((resolve, reject) => {
3
+ const settle = (error) => {
4
+ if (!error) process.stdout.off("error", settle);
5
+ if (error && (!("code" in error) || error.code !== "EPIPE")) reject(error);
6
+ else resolve();
7
+ };
8
+ process.stdout.once("error", settle);
9
+ process.stdout.write(text, settle);
10
+ });
11
+
12
+ export {
13
+ writeStdoutFully
14
+ };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SETUP_AGENT_CHOICES
3
- } from "./chunk-XEIV5QOT.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/cli/commands.ts
6
6
  var NPX_LATEST_COMMAND = "npx pushary@latest";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  HOOK_LOCATOR_BINARY
3
- } from "./chunk-XEIV5QOT.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/diagnostics/bridge.ts
6
6
  import { execFileSync } from "child_process";
@@ -3,11 +3,11 @@ import {
3
3
  decodePublicKey,
4
4
  generateSessionKey,
5
5
  wrapSessionKey
6
- } from "./chunk-FJPC35OW.js";
6
+ } from "./chunk-Q4RF7EEP.js";
7
7
  import {
8
8
  fetchTranscriptRecipients,
9
9
  uploadTranscriptRecords
10
- } from "./chunk-PMS3EBD2.js";
10
+ } from "./chunk-ZV32QRBR.js";
11
11
 
12
12
  // src/live-session.ts
13
13
  var MAX_TRANSCRIPT_QUEUE = 100;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-ZMKEKWNR.js";
3
+ } from "./chunk-5IIAUWEJ.js";
4
4
  import {
5
5
  writeFileAtomic
6
6
  } from "./chunk-T7E75EKA.js";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  registerTranscript
3
- } from "./chunk-WWDPULS3.js";
3
+ } from "./chunk-AMFNJPJ5.js";
4
4
  import {
5
5
  writeDegraded
6
- } from "./chunk-SPB3QRE7.js";
6
+ } from "./chunk-PPC4FZKJ.js";
7
7
 
8
8
  // src/tool-hook-input.ts
9
9
  var OPTIONAL_TEXT_FIELDS = ["hook_event_name", "session_id", "cwd", "transcript_path", "tool_use_id", "permission_mode"];
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  AGENT_CHOICES
3
- } from "./chunk-HU2LWGEE.js";
3
+ } from "./chunk-MH6SJHUE.js";
4
4
  import {
5
5
  isBridgeLocator
6
- } from "./chunk-LXWUYG7D.js";
6
+ } from "./chunk-FANGHYW5.js";
7
7
  import {
8
8
  pusharyHookExecutable
9
- } from "./chunk-5K43TBK4.js";
9
+ } from "./chunk-VRYOALHQ.js";
10
10
  import {
11
11
  BELL_HOOK_BINARY
12
- } from "./chunk-COSADFEH.js";
12
+ } from "./chunk-2UWD2WZC.js";
13
13
 
14
14
  // src/setup/hook-ownership.ts
15
15
  var commandsIn = (value) => {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-POFBE6ZY.js";
4
4
  import {
5
5
  autoUpdateState
6
- } from "./chunk-ZMKEKWNR.js";
6
+ } from "./chunk-5IIAUWEJ.js";
7
7
  import {
8
8
  readJsonSafe,
9
9
  writeJsonAtomic
@@ -14,13 +14,14 @@ import {
14
14
  cliPackagePathSegments,
15
15
  globalUpgradeEntry,
16
16
  ownPackageRoot
17
- } from "./chunk-XEIV5QOT.js";
17
+ } from "./chunk-JDUWMJDP.js";
18
18
 
19
19
  // src/auto-update.ts
20
20
  import { spawn } from "child_process";
21
21
  import { dirname } from "path";
22
22
  var AUTO_UPDATE_DISABLE_ENV = "PUSHARY_DISABLE_AUTOUPDATE";
23
23
  var AUTO_UPDATE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
24
+ var PENDING_FINISH_RETRY_MS = 5 * 60 * 1e3;
24
25
  var AUTO_UPDATE_FLAG = "--auto";
25
26
  var NON_GLOBAL_INSTALL_SEGMENTS = ["/_npx/", "/.volta/"];
26
27
  var AUTO_UPDATE_RESULTS = ["updated", "current", "needs_manual", "failed", "finish_pending"];
@@ -75,11 +76,11 @@ var globalInstallLocation = (packageRoot) => {
75
76
  return null;
76
77
  };
77
78
  var upgradeEntryFor = (location, platform = process.platform) => globalUpgradeEntry(location.prefix, location.packageName, platform);
78
- var checkedWithinInterval = (lastCheckAt, now) => {
79
+ var checkedWithinInterval = (lastCheckAt, now, interval) => {
79
80
  const last = lastCheckAt === void 0 ? Number.NaN : Date.parse(lastCheckAt);
80
81
  if (Number.isNaN(last)) return false;
81
82
  const elapsed = now - last;
82
- return elapsed >= 0 && elapsed < AUTO_UPDATE_INTERVAL_MS;
83
+ return elapsed >= 0 && elapsed < interval;
83
84
  };
84
85
  var autoUpdateDecision = (input) => {
85
86
  if (input.isSubagentStart) return { kind: "skip", reason: "subagent_start" };
@@ -87,7 +88,8 @@ var autoUpdateDecision = (input) => {
87
88
  if (offReason !== null) return { kind: "skip", reason: offReason };
88
89
  const location = input.packageRoot === void 0 ? null : globalInstallLocation(input.packageRoot);
89
90
  if (location === null) return { kind: "skip", reason: "not_global_install" };
90
- if (checkedWithinInterval(input.state.lastCheckAt, input.now)) return { kind: "skip", reason: "checked_recently" };
91
+ const interval = input.state.lastResult === "finish_pending" ? PENDING_FINISH_RETRY_MS : AUTO_UPDATE_INTERVAL_MS;
92
+ if (checkedWithinInterval(input.state.lastCheckAt, input.now, interval)) return { kind: "skip", reason: "checked_recently" };
91
93
  return { kind: "check", ...location };
92
94
  };
93
95
  var parseAutoUpdateFlag = (args) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  PRETOOLUSE_GATED_TOOLS
3
- } from "./chunk-XEIV5QOT.js";
3
+ } from "./chunk-JDUWMJDP.js";
4
4
 
5
5
  // src/claude-tools.ts
6
6
  var POSTTOOLUSE_MIRROR_ONLY_TOOLS = ["TodoWrite", "Task", "WebFetch", "WebSearch"];
@@ -5,7 +5,7 @@ import {
5
5
  permissionDeniedAction,
6
6
  releaseThrottle,
7
7
  reportEvent
8
- } from "./chunk-JCER3Q6P.js";
8
+ } from "./chunk-CJFVYYKM.js";
9
9
  import {
10
10
  DEFAULT_SESSION
11
11
  } from "./chunk-N6IOSZOE.js";
@@ -13,7 +13,7 @@ import {
13
13
  machineDecisionFor,
14
14
  shouldDeferToNativeMode,
15
15
  wireVerdictFor
16
- } from "./chunk-XEIV5QOT.js";
16
+ } from "./chunk-JDUWMJDP.js";
17
17
 
18
18
  // src/machine-decision-audit.ts
19
19
  import { basename } from "path";
@@ -2,7 +2,7 @@ import {
2
2
  autoUpdateLock,
3
3
  installPackageGlobally,
4
4
  npmErrorMessage
5
- } from "./chunk-ZMKEKWNR.js";
5
+ } from "./chunk-5IIAUWEJ.js";
6
6
  import {
7
7
  writeJsonAtomic
8
8
  } from "./chunk-T7E75EKA.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HOOK_BUDGETS,
3
3
  OPENCODE_APPROVAL_EVENT
4
- } from "./chunk-XEIV5QOT.js";
4
+ } from "./chunk-JDUWMJDP.js";
5
5
 
6
6
  // src/opencode-plugin.ts
7
7
  var OPENCODE_PLUGIN_MARKER = "pushary-opencode-plugin w1";
@@ -518,6 +518,106 @@ var redactSecrets = (text) => applyRedactionRules(SECRET_REDACTION_RULES, text);
518
518
  var redactSecretsFromContent = (text) => applyRedactionRules(CUT_OFF_TEXT_REDACTION_RULES, text);
519
519
  var redactSecretsDeep = (text) => redactSecrets(text).replace(HIGH_ENTROPY_RULE.pattern, HIGH_ENTROPY_RULE.replacement);
520
520
 
521
+ // ../contracts/src/shell-analysis.ts
522
+ var SHELL_WORD_SEPARATOR = /[ \t\n]/;
523
+ var trimShellWhitespace = (command) => command.replace(/^[ \t\n]+|[ \t\n]+$/g, "");
524
+ var DOUBLE_QUOTE_ESCAPABLE = /* @__PURE__ */ new Set(['"', "\\", "$", "`"]);
525
+ var SEGMENT_SEPARATORS = /* @__PURE__ */ new Set([";", "\n", "&", "|"]);
526
+ var DOUBLED_SEPARATORS = /* @__PURE__ */ new Set(["&", "|"]);
527
+ var UNDECOMPOSABLE = /* @__PURE__ */ new Set(["`", "<", ">"]);
528
+ var LITERAL_IN_DOUBLE_QUOTES = /* @__PURE__ */ new Set([";", "|", "&", "<", ">", "*", "?", "[", "\\"]);
529
+ var scanShell = (command) => {
530
+ const lexemes = [];
531
+ let quote = null;
532
+ for (let index = 0; index < command.length; index += 1) {
533
+ const char = command.charAt(index);
534
+ const next = command.charAt(index + 1);
535
+ if (char === "\\" && next && quote !== "'" && (quote === null || DOUBLE_QUOTE_ESCAPABLE.has(next))) {
536
+ lexemes.push({ index, text: char + next, quote, kind: "escape" });
537
+ index += 1;
538
+ } else if ((char === "'" || char === '"') && (quote === null || quote === char)) {
539
+ lexemes.push({ index, text: char, quote, kind: "quote" });
540
+ quote = quote === null ? char : null;
541
+ } else {
542
+ lexemes.push({ index, text: char, quote, kind: "text" });
543
+ }
544
+ }
545
+ return quote === null ? lexemes : null;
546
+ };
547
+ var shellCommandSegments = (command) => {
548
+ const lexemes = scanShell(command);
549
+ if (lexemes === null) return null;
550
+ const segments = [];
551
+ let start = 0;
552
+ let consumed = -1;
553
+ for (const lexeme of lexemes) {
554
+ const { index, text, quote, kind } = lexeme;
555
+ if (index <= consumed || kind !== "text" || quote === "'") continue;
556
+ if (text === "`" || text === "$" && command[index + 1] === "(") return null;
557
+ if (quote !== null) continue;
558
+ if (UNDECOMPOSABLE.has(text)) return null;
559
+ if (!SEGMENT_SEPARATORS.has(text)) continue;
560
+ consumed = index + (DOUBLED_SEPARATORS.has(text) && command[index + 1] === text ? 1 : 0);
561
+ segments.push(trimShellWhitespace(command.slice(start, index)));
562
+ start = consumed + 1;
563
+ }
564
+ segments.push(trimShellWhitespace(command.slice(start)));
565
+ const present = segments.filter((segment) => segment.length > 0);
566
+ return present.length > 0 ? present : null;
567
+ };
568
+ var shellVisibleText = (command) => {
569
+ const lexemes = scanShell(command);
570
+ if (lexemes === null) return null;
571
+ let visible = "";
572
+ for (const { text, quote, kind } of lexemes) {
573
+ if (kind === "escape" && quote === '"') return null;
574
+ const literal = kind === "text" && (quote === "'" || quote === '"' && LITERAL_IN_DOUBLE_QUOTES.has(text));
575
+ visible += literal ? "_".repeat(text.length) : text;
576
+ }
577
+ return visible;
578
+ };
579
+ var shellWordsOf = (command) => {
580
+ const lexemes = scanShell(command);
581
+ if (lexemes === null) return null;
582
+ const words = [];
583
+ let text = "";
584
+ let plain = true;
585
+ let expands = false;
586
+ let comment = false;
587
+ let started = false;
588
+ const finishWord = () => {
589
+ if (started) words.push({ text, plain, expands, comment });
590
+ text = "";
591
+ plain = true;
592
+ expands = false;
593
+ comment = false;
594
+ started = false;
595
+ };
596
+ for (const lexeme of lexemes) {
597
+ if (lexeme.kind === "quote") {
598
+ plain = false;
599
+ started = true;
600
+ continue;
601
+ }
602
+ if (lexeme.kind === "escape") {
603
+ text += lexeme.text.slice(1);
604
+ plain = false;
605
+ started = true;
606
+ continue;
607
+ }
608
+ if (lexeme.quote === null && SHELL_WORD_SEPARATOR.test(lexeme.text)) {
609
+ finishWord();
610
+ continue;
611
+ }
612
+ comment ||= lexeme.quote === null && !started && lexeme.text === "#";
613
+ expands ||= lexeme.quote !== "'" && lexeme.text === "$";
614
+ text += lexeme.text;
615
+ started = true;
616
+ }
617
+ finishWord();
618
+ return words;
619
+ };
620
+
521
621
  // ../contracts/src/degraded.ts
522
622
  var DEGRADED_PREFIX = "[degraded]";
523
623
  var degradedPayload = (subsystem, report) => ({
@@ -857,57 +957,6 @@ var PATTERN_INTENT = {
857
957
  grant: "grant",
858
958
  restrict: "restrict"
859
959
  };
860
- var SHELL_ESCAPE = "\\";
861
- var SHELL_DOUBLE_QUOTE = '"';
862
- var SHELL_SUBSTITUTION_SIGIL = "$";
863
- var SHELL_GROUP_OPEN = "(";
864
- var SHELL_QUOTES = /* @__PURE__ */ new Set(["'", SHELL_DOUBLE_QUOTE]);
865
- var SHELL_SEGMENT_SEPARATORS = /* @__PURE__ */ new Set([";", "\n", "&", "|"]);
866
- var SHELL_DOUBLED_SEPARATORS = /* @__PURE__ */ new Set(["&", "|"]);
867
- var SHELL_UNDECOMPOSABLE = /* @__PURE__ */ new Set(["`", "<", ">"]);
868
- var shellCommandSegments = (command) => {
869
- const segments = [];
870
- let current = "";
871
- let quote = null;
872
- for (let index = 0; index < command.length; index += 1) {
873
- const char = command[index];
874
- const next = command[index + 1];
875
- if (quote !== null) {
876
- if (char === SHELL_ESCAPE && quote === SHELL_DOUBLE_QUOTE && next !== void 0) {
877
- current += char + next;
878
- index += 1;
879
- continue;
880
- }
881
- if (quote === SHELL_DOUBLE_QUOTE && (char === "`" || char === SHELL_SUBSTITUTION_SIGIL && next === SHELL_GROUP_OPEN)) return null;
882
- if (char === quote) quote = null;
883
- current += char;
884
- continue;
885
- }
886
- if (char === SHELL_ESCAPE && next !== void 0) {
887
- current += char + next;
888
- index += 1;
889
- continue;
890
- }
891
- if (SHELL_QUOTES.has(char)) {
892
- quote = char;
893
- current += char;
894
- continue;
895
- }
896
- if (SHELL_UNDECOMPOSABLE.has(char)) return null;
897
- if (char === SHELL_SUBSTITUTION_SIGIL && next === SHELL_GROUP_OPEN) return null;
898
- if (SHELL_SEGMENT_SEPARATORS.has(char)) {
899
- if (next === char && SHELL_DOUBLED_SEPARATORS.has(char)) index += 1;
900
- segments.push(current);
901
- current = "";
902
- continue;
903
- }
904
- current += char;
905
- }
906
- if (quote !== null) return null;
907
- segments.push(current);
908
- const present = segments.map((segment) => segment.trim()).filter((segment) => segment.length > 0);
909
- return present.length > 0 ? present : null;
910
- };
911
960
  var everySegmentMatches = (command, matches) => {
912
961
  const segments = shellCommandSegments(command);
913
962
  return segments !== null && segments.every(matches);
@@ -1147,40 +1196,8 @@ var isTrustedExecutable = (first) => {
1147
1196
  if (first.includes("..")) return false;
1148
1197
  return TRUSTED_EXE_PREFIXES.some((prefix) => first.startsWith(prefix));
1149
1198
  };
1150
- var tokenizeShellCommand = (command) => {
1151
- const tokens = [];
1152
- let current = "";
1153
- let quote = null;
1154
- let started = false;
1155
- for (const ch of command) {
1156
- if (quote) {
1157
- if (ch === quote) quote = null;
1158
- else current += ch;
1159
- started = true;
1160
- continue;
1161
- }
1162
- if (ch === '"' || ch === "'") {
1163
- quote = ch;
1164
- started = true;
1165
- continue;
1166
- }
1167
- if (ch === " " || ch === " ") {
1168
- if (started) {
1169
- tokens.push(current);
1170
- current = "";
1171
- started = false;
1172
- }
1173
- continue;
1174
- }
1175
- current += ch;
1176
- started = true;
1177
- }
1178
- if (quote) return null;
1179
- if (started) tokens.push(current);
1180
- return tokens;
1181
- };
1182
1199
  var isSafeSimpleCommand = (segment) => {
1183
- const tokens = tokenizeShellCommand(segment.trim());
1200
+ const tokens = shellWordsOf(segment)?.map((word) => word.text);
1184
1201
  if (!tokens || tokens.length === 0) return false;
1185
1202
  const first = tokens[0];
1186
1203
  if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(first) || first.includes("$")) return false;
@@ -1212,32 +1229,8 @@ var DATE_UTC_FLAG = "-u";
1212
1229
  var isFlagToken = (token) => token.startsWith("-");
1213
1230
  var isPrintOnlySed = (args) => args[0] === SED_QUIET_FLAG && SED_PRINT_ONLY_SCRIPT.test(args[1] ?? "") && !args.slice(2).some(isFlagToken);
1214
1231
  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
1232
  var READ_ONLY_SEGMENT_SEPARATOR = /&&|\|\||[;|]/g;
1219
1233
  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
1234
  var EXPANSION_THAT_CAN_BECOME_A_FLAG = /\$|(?:^|\s)[*?[]/;
1242
1235
  var SHELL_QUOTE_CHARACTERS = /['"]/g;
1243
1236
  var INSPECTED_ARGUMENT_COMMANDS = /* @__PURE__ */ new Set(["git", "find", "sed", "date"]);
@@ -1257,7 +1250,7 @@ var segmentsSplitWhereVisible = (command, visible, separators) => {
1257
1250
  return segments;
1258
1251
  };
1259
1252
  var isSafeReadOnlyCommand = (command) => {
1260
- const trimmed = command.trim();
1253
+ const trimmed = trimShellWhitespace(command);
1261
1254
  if (!trimmed || trimmed.length > 2e3) return false;
1262
1255
  if (/[\n\r]/.test(trimmed)) return false;
1263
1256
  const visible = shellVisibleText(trimmed);
@@ -1267,7 +1260,7 @@ var isSafeReadOnlyCommand = (command) => {
1267
1260
  const visibleWithoutRedirection = blankedSafeRedirections(visible);
1268
1261
  if (/[<>]/.test(visibleWithoutRedirection)) return false;
1269
1262
  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));
1263
+ return segmentsSplitWhereVisible(blankedSafeRedirections(trimmed), visibleWithoutRedirection, READ_ONLY_SEGMENT_SEPARATOR).every((segment) => trimShellWhitespace(segment).length > 0 && isSafeSimpleCommand(segment));
1271
1264
  };
1272
1265
  var isAutoApprove = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "approve";
1273
1266
  var isAutoDeny = (policy) => policy.timeoutSeconds === 0 && policy.timeoutAction === "deny";
@@ -1481,67 +1474,9 @@ var SHELL_RESERVED_WORDS = /* @__PURE__ */ new Set([
1481
1474
  var HARMLESS_GLOBAL_FLAGS = /* @__PURE__ */ new Set(["--no-pager", "--version", "-v", "-V", "--help", "-h"]);
1482
1475
  var END_OF_OPTIONS = "--";
1483
1476
  var SUBCOMMAND_DEPTH = 3;
1484
- var SHELL_COMMENT_MARK = "#";
1485
1477
  var SHELL_LINE_CONTINUATION = /\\\n/g;
1486
- var SHELL_WORD_BREAK = /\s/;
1487
- var DOUBLE_QUOTE_ESCAPABLE = /* @__PURE__ */ new Set([SHELL_DOUBLE_QUOTE, SHELL_ESCAPE, SHELL_SUBSTITUTION_SIGIL, "`"]);
1488
- var shellWordsOf = (segment) => {
1489
- const words = [];
1490
- let text = "";
1491
- let plain = true;
1492
- let expands = false;
1493
- let comment = false;
1494
- let started = false;
1495
- let quote = null;
1496
- const finishWord = () => {
1497
- if (started) words.push({ text, plain, expands, comment });
1498
- text = "";
1499
- plain = true;
1500
- expands = false;
1501
- comment = false;
1502
- started = false;
1503
- };
1504
- for (let index = 0; index < segment.length; index += 1) {
1505
- const char = segment[index];
1506
- const next = segment[index + 1];
1507
- if (quote === "'") {
1508
- if (char === quote) quote = null;
1509
- else text += char;
1510
- continue;
1511
- }
1512
- if (char === SHELL_ESCAPE && next !== void 0 && (quote === null || DOUBLE_QUOTE_ESCAPABLE.has(next))) {
1513
- text += next;
1514
- plain = false;
1515
- started = true;
1516
- index += 1;
1517
- continue;
1518
- }
1519
- if (quote === SHELL_DOUBLE_QUOTE) {
1520
- if (char === quote) quote = null;
1521
- else text += char;
1522
- expands ||= char === SHELL_SUBSTITUTION_SIGIL;
1523
- continue;
1524
- }
1525
- if (SHELL_QUOTES.has(char)) {
1526
- quote = char;
1527
- plain = false;
1528
- started = true;
1529
- continue;
1530
- }
1531
- if (SHELL_WORD_BREAK.test(char)) {
1532
- finishWord();
1533
- continue;
1534
- }
1535
- comment ||= !started && char === SHELL_COMMENT_MARK;
1536
- expands ||= char === SHELL_SUBSTITUTION_SIGIL;
1537
- text += char;
1538
- started = true;
1539
- }
1540
- finishWord();
1541
- return words;
1542
- };
1543
1478
  var invocationOf = (segment) => {
1544
- const [program, ...args] = shellWordsOf(segment);
1479
+ const [program, ...args] = shellWordsOf(segment) ?? [];
1545
1480
  return { program, args };
1546
1481
  };
1547
1482
  var argsAfterHarmlessGlobalFlags = (args) => {
@@ -1822,6 +1757,16 @@ var SETTLED_OUTCOME = {
1822
1757
  deny: "deny"
1823
1758
  };
1824
1759
  var isSettledOutcome = (value) => typeof value === "string" && SETTLED_OUTCOMES.includes(value);
1760
+ var APPROVE_RESPONSES = /* @__PURE__ */ new Set(["yes", "approve", "approved"]);
1761
+ var DENY_RESPONSES = /* @__PURE__ */ new Set(["no", "deny", "denied", "reject", "rejected"]);
1762
+ var DEFER_RESPONSES = /* @__PURE__ */ new Set(["defer"]);
1763
+ var classifyConfirmResponse = (response) => {
1764
+ const normalized = (response ?? "").trim().toLowerCase();
1765
+ if (APPROVE_RESPONSES.has(normalized)) return "approve";
1766
+ if (DENY_RESPONSES.has(normalized)) return "deny";
1767
+ if (DEFER_RESPONSES.has(normalized)) return "defer";
1768
+ return null;
1769
+ };
1825
1770
  var commandTextThatCanAct = (command) => {
1826
1771
  const visible = shellVisibleText(command);
1827
1772
  return visible === null ? command : segmentsSplitWhereVisible(command, visible, PIPELINE_CHAIN_SEPARATOR).filter((pipeline) => !isSafeReadOnlyCommand(pipeline)).join("\n");
@@ -2607,10 +2552,11 @@ var elicitationContentFromAnswers = (ask, answers) => {
2607
2552
  // ../contracts/src/hook-activation.ts
2608
2553
  var hookWritePath = (toolName, input) => toolName === "Write" && typeof input.file_path === "string" && input.file_path.startsWith("/") && input.file_path.length <= 4096 ? input.file_path : void 0;
2609
2554
  var HOOK_ACTIVATION_RESULTS = ["unverified", "approved_executed", "denied_observed", "unexpected_execution", "tool_failed"];
2555
+ var MAX_HOOK_ACTIVATION_EVIDENCE_ROWS = 20;
2610
2556
  var isHookActivationReport = (value) => {
2611
2557
  if (!value || typeof value !== "object") return false;
2612
2558
  const report = value;
2613
- return typeof report.agentType === "string" && typeof report.machineId === "string" && typeof report.target === "string" && report.target.length > 0 && report.target.length <= 4096 && typeof report.truncated === "boolean" && Array.isArray(report.evidence) && report.evidence.length <= 20 && (!report.truncated || report.evidence.length === 0) && report.evidence.every((item) => {
2559
+ return typeof report.agentType === "string" && typeof report.machineId === "string" && typeof report.target === "string" && report.target.length > 0 && report.target.length <= 4096 && typeof report.truncated === "boolean" && Array.isArray(report.evidence) && report.evidence.length <= MAX_HOOK_ACTIVATION_EVIDENCE_ROWS && (!report.truncated || report.evidence.length === 0) && report.evidence.every((item) => {
2614
2560
  if (!item || typeof item !== "object") return false;
2615
2561
  const row = item;
2616
2562
  return ["correlationId", "sessionId", "toolUseId", "toolName", "createdAt"].every((key) => typeof row[key] === "string" && row[key].length > 0 && row[key].length <= 256) && (row.answerSource === null || isAnswerSource(row.answerSource)) && HOOK_ACTIVATION_RESULTS.includes(row.result) && Number.isFinite(Date.parse(row.createdAt)) && (row.occurredAt === null || typeof row.occurredAt === "string" && Number.isFinite(Date.parse(row.occurredAt))) && (row.observedAt === null || typeof row.observedAt === "string" && Number.isFinite(Date.parse(row.observedAt))) && (row.result === "unverified" || row.occurredAt !== null && row.observedAt !== null && row.producer !== null && isAnswerSource(row.answerSource) && row.answerSource !== "sandbox") && (row.producer === null || row.producer === "hook" || row.producer === "uplink");
@@ -2790,6 +2736,7 @@ export {
2790
2736
  redactSecretsDeep,
2791
2737
  degradedLine,
2792
2738
  hookWritePath,
2739
+ MAX_HOOK_ACTIVATION_EVIDENCE_ROWS,
2793
2740
  isHookActivationReport,
2794
2741
  hookActivationResult,
2795
2742
  PAIR_TTL_SECONDS,
@@ -2832,6 +2779,7 @@ export {
2832
2779
  ASK_AGENT_NAME_MAX,
2833
2780
  truncateLine,
2834
2781
  isAnswerSource,
2782
+ classifyConfirmResponse,
2835
2783
  buildDecisionEpisodeFeatures,
2836
2784
  resolveAutoResolveOrigin,
2837
2785
  resolvePolicy,
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  MCP_BRIDGE_BINARY
3
- } from "./chunk-LJI7U6PM.js";
3
+ } from "./chunk-AUS3LY4N.js";
4
4
  import {
5
5
  openCodeConfigDirFrom
6
- } from "./chunk-CGRPHFOV.js";
6
+ } from "./chunk-IVF3OVR2.js";
7
7
  import {
8
8
  KEY_FILE_MODE
9
- } from "./chunk-RJ7ECJSZ.js";
9
+ } from "./chunk-ZPTSEJMD.js";
10
10
  import {
11
11
  NpmMissingError,
12
12
  codexHomeFrom,
13
13
  resolvePathBinary
14
- } from "./chunk-ZMKEKWNR.js";
14
+ } from "./chunk-5IIAUWEJ.js";
15
15
  import {
16
16
  readJsonSafe,
17
17
  writeFileAtomic,
@@ -19,10 +19,10 @@ import {
19
19
  } from "./chunk-T7E75EKA.js";
20
20
  import {
21
21
  NPX_LATEST_COMMAND
22
- } from "./chunk-FVOCQSBG.js";
22
+ } from "./chunk-EZFE4PC3.js";
23
23
  import {
24
24
  HOOK_COMPATIBLE_PROFILES
25
- } from "./chunk-XEIV5QOT.js";
25
+ } from "./chunk-JDUWMJDP.js";
26
26
 
27
27
  // src/hermes-config.ts
28
28
  import { execFileSync } from "child_process";
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  describeKeyCheck,
6
6
  keyCheckFromResponse
7
- } from "./chunk-DMA3QUOB.js";
7
+ } from "./chunk-7MO3CNBX.js";
8
8
  import {
9
9
  EXIT
10
10
  } from "./chunk-KZERVKTD.js";
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  ensureCodexTrustsPusharyHooks
3
- } from "./chunk-KR5JASA4.js";
3
+ } from "./chunk-QVUOPB32.js";
4
4
  import {
5
5
  addClaudeMcpServer,
6
6
  addPusharyHooks,
7
7
  addPusharyToolPermissions
8
- } from "./chunk-6Q4NM2LW.js";
8
+ } from "./chunk-ZUZKHTPJ.js";
9
9
  import {
10
10
  detectClaudeVersion
11
11
  } from "./chunk-RIVNNBEK.js";
@@ -15,7 +15,7 @@ import {
15
15
  codexUnprovenHolds,
16
16
  codexWired,
17
17
  geminiWired
18
- } from "./chunk-5K43TBK4.js";
18
+ } from "./chunk-VRYOALHQ.js";
19
19
  import {
20
20
  CLAUDE_HOOK_BINARY,
21
21
  CLAUDE_HOOK_EVENTS,
@@ -26,7 +26,7 @@ import {
26
26
  needsReregistration,
27
27
  registrationSignatures,
28
28
  supportedClaudeEvents
29
- } from "./chunk-D3RS57MN.js";
29
+ } from "./chunk-CVVPUVBD.js";
30
30
  import {
31
31
  formatVersion
32
32
  } from "./chunk-6ICPEJY5.js";
@@ -49,7 +49,7 @@ import {
49
49
  registrationHolderOf,
50
50
  resolveGlobalBinary,
51
51
  vscodePluginMcp
52
- } from "./chunk-ZMKEKWNR.js";
52
+ } from "./chunk-5IIAUWEJ.js";
53
53
  import {
54
54
  readJsonSafe,
55
55
  writeFileAtomic,
@@ -9,7 +9,7 @@ import {
9
9
  SETUP_CONNECT_MODES,
10
10
  isSetupConnectMode,
11
11
  isValidApiKey
12
- } from "./chunk-XEIV5QOT.js";
12
+ } from "./chunk-JDUWMJDP.js";
13
13
 
14
14
  // src/setup/options.ts
15
15
  var AGENT_CHOICES = SETUP_AGENT_CHOICES;