@pushary/agent-hooks 1.7.3 → 1.8.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 (108) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +39 -19
  3. package/data/SKILL.md +8 -8
  4. package/data/cowork/SKILL.md +2 -2
  5. package/data/cursor-plugin/README.md +2 -2
  6. package/data/cursor-plugin/scripts/pushary-gate.mjs +2 -21
  7. package/data/cursor-plugin/scripts/redaction.mjs +53 -0
  8. package/data/cursor-plugin/skills/pushary/SKILL.md +7 -7
  9. package/data/vscode-plugin/README.md +4 -4
  10. package/data/vscode-plugin/scripts/pushary-gate.mjs +3 -23
  11. package/data/vscode-plugin/scripts/redaction.mjs +53 -0
  12. package/data/vscode-plugin/skills/pushary/SKILL.md +7 -7
  13. package/dist/bin/pushary-bell-hook.js +23 -23
  14. package/dist/bin/pushary-bell.js +9 -9
  15. package/dist/bin/pushary-claude.js +26 -26
  16. package/dist/bin/pushary-clean.js +97 -111
  17. package/dist/bin/pushary-codex-bridge.js +18 -18
  18. package/dist/bin/pushary-codex-hook.js +42 -43
  19. package/dist/bin/pushary-codex.js +13 -13
  20. package/dist/bin/pushary-connect.js +13 -13
  21. package/dist/bin/pushary-cowork.js +5 -5
  22. package/dist/bin/pushary-daemon.js +27 -27
  23. package/dist/bin/pushary-disconnect.js +18 -18
  24. package/dist/bin/pushary-doctor.js +92 -86
  25. package/dist/bin/pushary-elicitation-hook.js +25 -25
  26. package/dist/bin/pushary-gemini-bridge.js +12 -12
  27. package/dist/bin/pushary-gemini-hook.js +29 -30
  28. package/dist/bin/pushary-hook.js +32 -32
  29. package/dist/bin/pushary-login.js +12 -12
  30. package/dist/bin/pushary-logout.js +7 -7
  31. package/dist/bin/pushary-mcp.js +85 -28
  32. package/dist/bin/pushary-mode.js +9 -9
  33. package/dist/bin/pushary-notification-hook.js +28 -28
  34. package/dist/bin/pushary-opencode-hook.js +28 -29
  35. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  36. package/dist/bin/pushary-permission-hook.js +31 -31
  37. package/dist/bin/pushary-post-hook.js +28 -28
  38. package/dist/bin/pushary-prompt-hook.js +28 -28
  39. package/dist/bin/pushary-session-end-hook.js +28 -28
  40. package/dist/bin/pushary-session-start-hook.js +32 -32
  41. package/dist/bin/pushary-setup.js +62 -129
  42. package/dist/bin/pushary-stats.js +5 -5
  43. package/dist/bin/pushary-status.js +15 -15
  44. package/dist/bin/pushary-stop-hook.js +28 -28
  45. package/dist/bin/pushary-stopfailure-hook.js +28 -28
  46. package/dist/bin/pushary-suggestions.js +4 -4
  47. package/dist/bin/pushary-transcript-register.js +19 -19
  48. package/dist/bin/pushary-transcripts.js +7 -7
  49. package/dist/bin/pushary-upgrade.js +236 -110
  50. package/dist/bin/pushary-wait.js +9 -9
  51. package/dist/bin/pushary.js +6 -6
  52. package/dist/{chunk-DUQO4C4I.js → chunk-2SLCHCVN.js} +3 -3
  53. package/dist/{chunk-YYCTF4Q5.js → chunk-35X5UDML.js} +7 -7
  54. package/dist/{chunk-OVC5QXN5.js → chunk-4A3UQERT.js} +1 -1
  55. package/dist/chunk-5DGNEUXK.js +73 -0
  56. package/dist/{chunk-62CVUUNU.js → chunk-5Y2DY6X4.js} +2 -2
  57. package/dist/{chunk-G4GLCLKK.js → chunk-5YY3IJT4.js} +159 -36
  58. package/dist/{chunk-KJXUIPS4.js → chunk-64H5IZZD.js} +28 -16
  59. package/dist/{chunk-OTNOANMX.js → chunk-6TK4IY3A.js} +8 -8
  60. package/dist/{chunk-LPNJLKBQ.js → chunk-72WOCX22.js} +1 -1
  61. package/dist/{chunk-IRZG3HEU.js → chunk-7ITOAMCD.js} +1 -1
  62. package/dist/{chunk-G62JL2NT.js → chunk-7U7ZWUTR.js} +1 -1
  63. package/dist/{chunk-IPSRMLCJ.js → chunk-ASWRMBOM.js} +1 -1
  64. package/dist/{chunk-5S2VBSJI.js → chunk-CB23AO4D.js} +2 -2
  65. package/dist/{chunk-VKVSRCBO.js → chunk-CHMOVJ2M.js} +1 -1
  66. package/dist/{chunk-BGBLLHZ4.js → chunk-DLEKCAQL.js} +1 -1
  67. package/dist/{chunk-EEEJ2JIL.js → chunk-DVW2MYCM.js} +3 -3
  68. package/dist/{chunk-AWVNAYGD.js → chunk-DXBS2EL7.js} +1 -1
  69. package/dist/{chunk-ZKJ34T2F.js → chunk-EIGJYCOE.js} +31 -17
  70. package/dist/{chunk-U6RVDUJ5.js → chunk-F6NTWZZC.js} +283 -41
  71. package/dist/{chunk-7RUJKCR4.js → chunk-FLQPM2GQ.js} +2 -2
  72. package/dist/{chunk-TCVMK6GI.js → chunk-GBNQXYN4.js} +4 -4
  73. package/dist/{chunk-G6RRVJOG.js → chunk-GH6KGWMC.js} +6 -6
  74. package/dist/chunk-GU3EJCVV.js +43 -0
  75. package/dist/{chunk-6JQFIHZC.js → chunk-HBWC3JVZ.js} +3 -3
  76. package/dist/{chunk-IWJKSIB4.js → chunk-HMNR7B2F.js} +1 -1
  77. package/dist/{chunk-NOI3XTCY.js → chunk-HOEB6AKG.js} +1 -1
  78. package/dist/{chunk-62VT3BPH.js → chunk-HQRCVEI2.js} +32 -17
  79. package/dist/{chunk-MIXWMA73.js → chunk-HTEGMMT3.js} +3 -3
  80. package/dist/{chunk-BIH2Y2HP.js → chunk-HVDMGDYV.js} +2 -2
  81. package/dist/{chunk-VE7TXLR4.js → chunk-I4HKMUZQ.js} +3 -3
  82. package/dist/{chunk-YPUBA2FL.js → chunk-INSMZNS7.js} +5 -5
  83. package/dist/{chunk-G3OMOTJ4.js → chunk-JRQRNNGA.js} +3 -3
  84. package/dist/{chunk-N5MZH5A6.js → chunk-KB2FTO4O.js} +4 -4
  85. package/dist/{chunk-O3JDWNLU.js → chunk-LK2S5XIV.js} +183 -28
  86. package/dist/{chunk-YC27PROF.js → chunk-MMVCI6DT.js} +20 -5
  87. package/dist/{chunk-3EUBQARL.js → chunk-MYHG7PX2.js} +1 -1
  88. package/dist/{chunk-EADXTSHE.js → chunk-N6JJJTPH.js} +6 -3
  89. package/dist/{chunk-PRNFSORD.js → chunk-NHCUXTEM.js} +1 -1
  90. package/dist/{chunk-KEL5MXRL.js → chunk-NOLPURUI.js} +1 -1
  91. package/dist/{chunk-WTJM7PSL.js → chunk-OCVVSRDA.js} +3 -3
  92. package/dist/{chunk-R6OYCUNK.js → chunk-ON5JW2HP.js} +1 -1
  93. package/dist/{chunk-UOQRM7JQ.js → chunk-QB6QYZ6B.js} +5 -5
  94. package/dist/{chunk-7OA34PNW.js → chunk-T55H6YEP.js} +40 -10
  95. package/dist/{chunk-D6OODZCM.js → chunk-TJMAXQ5Q.js} +2 -2
  96. package/dist/{chunk-WGMW7OXW.js → chunk-TKQ6LZQZ.js} +6 -6
  97. package/dist/{chunk-WPX67AKT.js → chunk-UMMCHS6P.js} +1 -1
  98. package/dist/{chunk-MZBRL5H5.js → chunk-UPLV5AJF.js} +108 -25
  99. package/dist/{chunk-P2VIBGXA.js → chunk-URNXU3FO.js} +1 -1
  100. package/dist/{chunk-EUGNVLMG.js → chunk-VFFHQC7W.js} +3 -1
  101. package/dist/{chunk-Y4ZH64UK.js → chunk-VZMIHERK.js} +2 -2
  102. package/dist/{chunk-RLW3JWDY.js → chunk-W2LJ4O3A.js} +2 -2
  103. package/dist/{chunk-LHC45YUC.js → chunk-ZJYJAD52.js} +1 -1
  104. package/dist/{reapply-PH5T4BGR.js → reapply-ICGTBHVE.js} +9 -9
  105. package/dist/src/index.js +20 -20
  106. package/package.json +1 -1
  107. package/dist/chunk-5GB22QYL.js +0 -255
  108. package/dist/chunk-VYPJHGG6.js +0 -92
@@ -2,17 +2,17 @@ import {
2
2
  CLAUDE_HOOK_EVENTS,
3
3
  GEMINI_HOOK_EVENTS,
4
4
  hasGeminiHooks
5
- } from "./chunk-MIXWMA73.js";
5
+ } from "./chunk-HTEGMMT3.js";
6
6
  import {
7
7
  CODEX_HOOK_EVENTS,
8
8
  hasCodexHooks,
9
9
  holdBudgetOf
10
- } from "./chunk-MZBRL5H5.js";
10
+ } from "./chunk-UPLV5AJF.js";
11
11
  import {
12
12
  CURSOR_GATE_EVENTS,
13
13
  HOOK_LOCATOR_BINARY,
14
14
  hookCommandHoldBudget
15
- } from "./chunk-G4GLCLKK.js";
15
+ } from "./chunk-5YY3IJT4.js";
16
16
 
17
17
  // src/diagnostics/wiring.ts
18
18
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  NPX_LATEST_COMMAND
3
- } from "./chunk-YYCTF4Q5.js";
3
+ } from "./chunk-35X5UDML.js";
4
4
 
5
5
  // src/config.ts
6
6
  import { readFileSync } from "fs";
@@ -3,28 +3,28 @@ import {
3
3
  addPusharyToolPermissions,
4
4
  isPusharyHook,
5
5
  removeClaudeMcpServers
6
- } from "./chunk-G3OMOTJ4.js";
6
+ } from "./chunk-JRQRNNGA.js";
7
7
  import {
8
8
  CLAUDE_HOOK_EVENTS,
9
9
  addGeminiMcpServer,
10
10
  removeGeminiMcpServer
11
- } from "./chunk-MIXWMA73.js";
11
+ } from "./chunk-HTEGMMT3.js";
12
12
  import {
13
13
  CLAUDE_CODE_AGENT,
14
14
  parseApplyPatchFiles
15
- } from "./chunk-U6RVDUJ5.js";
15
+ } from "./chunk-F6NTWZZC.js";
16
16
  import {
17
17
  guardBinary,
18
18
  holdBudgetOf,
19
19
  registerHookEntry
20
- } from "./chunk-MZBRL5H5.js";
20
+ } from "./chunk-UPLV5AJF.js";
21
21
  import {
22
22
  PHONE_ANSWERED_TOOLS,
23
23
  hookCompatibleProfile,
24
24
  hookCompatibleProfileBySource,
25
25
  toToolLookup,
26
26
  withHookHoldBudget
27
- } from "./chunk-G4GLCLKK.js";
27
+ } from "./chunk-5YY3IJT4.js";
28
28
 
29
29
  // src/compatible-config.ts
30
30
  import { homedir } from "os";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  parseSseMessages
3
- } from "./chunk-VE7TXLR4.js";
3
+ } from "./chunk-I4HKMUZQ.js";
4
4
  import {
5
5
  NPX_LATEST_COMMAND
6
- } from "./chunk-YYCTF4Q5.js";
6
+ } from "./chunk-35X5UDML.js";
7
7
 
8
8
  // src/mcp-stdio-bridge.ts
9
9
  var MCP_BRIDGE_BINARY = "pushary-mcp";
@@ -11,6 +11,7 @@ var MCP_BRIDGE_PATH = "/api/mcp/mcp";
11
11
  var MCP_BRIDGE_REQUEST_TIMEOUT_MS = 9e4;
12
12
  var JSON_RPC_PARSE_ERROR = -32700;
13
13
  var MCP_BRIDGE_ERROR = -32e3;
14
+ var MCP_MAX_RESPONSE_BYTES = 1024 * 1024;
14
15
  var MCP_SESSION_HEADER = "mcp-session-id";
15
16
  var MCP_PROTOCOL_HEADER = "mcp-protocol-version";
16
17
  var INITIALIZE_METHOD = "initialize";
@@ -63,6 +64,25 @@ var negotiatedProtocolOf = (messages, initializeIds) => {
63
64
  }
64
65
  return void 0;
65
66
  };
67
+ var readBoundedResponse = async (response) => {
68
+ if (!response.body) return "";
69
+ const reader = response.body.getReader();
70
+ const chunks = [];
71
+ let size = 0;
72
+ try {
73
+ for (; ; ) {
74
+ const { done, value } = await reader.read();
75
+ if (done) break;
76
+ size += value.byteLength;
77
+ if (size > MCP_MAX_RESPONSE_BYTES) throw new Error("MCP response exceeds the 1 MiB limit.");
78
+ chunks.push(value);
79
+ }
80
+ return Buffer.concat(chunks).toString("utf8");
81
+ } finally {
82
+ await reader.cancel().catch(() => void 0);
83
+ reader.releaseLock();
84
+ }
85
+ };
66
86
  var createMcpStdioBridge = (deps) => {
67
87
  let sessionId = null;
68
88
  let protocolVersion = null;
@@ -73,9 +93,9 @@ var createMcpStdioBridge = (deps) => {
73
93
  ...sessionId ? { [MCP_SESSION_HEADER]: sessionId } : {},
74
94
  ...protocolVersion ? { [MCP_PROTOCOL_HEADER]: protocolVersion } : {}
75
95
  });
76
- const failRequests = (requests, message, answered = /* @__PURE__ */ new Set()) => {
96
+ const failRequests = async (requests, message, answered = /* @__PURE__ */ new Set()) => {
77
97
  for (const request of requests) {
78
- if (!answered.has(request.id)) deps.emit(bridgeError(request.id, message));
98
+ if (!answered.has(request.id)) await deps.emit(bridgeError(request.id, message));
79
99
  }
80
100
  };
81
101
  const post = async (line, apiKey) => deps.fetchImpl(deps.endpoint, {
@@ -87,7 +107,7 @@ var createMcpStdioBridge = (deps) => {
87
107
  const forward = async (line) => {
88
108
  const parsed = parseBridgeLine(line);
89
109
  if (!parsed.ok) {
90
- deps.emit(bridgeError(null, PARSE_ERROR_MESSAGE, JSON_RPC_PARSE_ERROR));
110
+ await deps.emit(bridgeError(null, PARSE_ERROR_MESSAGE, JSON_RPC_PARSE_ERROR));
91
111
  return;
92
112
  }
93
113
  const requests = requestsIn(parsed.payload);
@@ -96,25 +116,35 @@ var createMcpStdioBridge = (deps) => {
96
116
  let body;
97
117
  try {
98
118
  response = await post(line, apiKey);
99
- body = await response.text();
119
+ body = await readBoundedResponse(response);
100
120
  } catch (err) {
101
- failRequests(requests, unreachableMessage(err));
121
+ await failRequests(requests, unreachableMessage(err));
102
122
  return;
103
123
  }
104
124
  sessionId = response.headers.get(MCP_SESSION_HEADER) ?? sessionId;
105
125
  const messages = parseMcpMessages(body, response.headers.get("content-type")).filter(isJsonRpcMessage);
106
126
  const initializeIds = new Set(requests.filter((request) => request.method === INITIALIZE_METHOD).map((request) => request.id));
107
127
  protocolVersion = negotiatedProtocolOf(messages, initializeIds) ?? protocolVersion;
108
- for (const message of messages) deps.emit(message);
128
+ for (const message of messages) await deps.emit(message);
109
129
  const answered = new Set(messages.map(responseIdOf).filter(isJsonRpcId));
110
130
  const failure = response.ok ? NO_RESPONSE_MESSAGE : httpFailureMessage(response.status, apiKey !== null, body);
111
- failRequests(requests, failure, answered);
131
+ await failRequests(requests, failure, answered);
132
+ };
133
+ const reject = async (line, message) => {
134
+ const parsed = parseBridgeLine(line);
135
+ if (!parsed.ok) {
136
+ await deps.emit(bridgeError(null, PARSE_ERROR_MESSAGE, JSON_RPC_PARSE_ERROR));
137
+ return;
138
+ }
139
+ await failRequests(requestsIn(parsed.payload), message);
112
140
  };
113
- return { forward };
141
+ return { forward, reject };
114
142
  };
115
143
 
116
144
  export {
117
145
  MCP_BRIDGE_BINARY,
118
146
  MCP_BRIDGE_PATH,
147
+ bridgeError,
148
+ parseBridgeLine,
119
149
  createMcpStdioBridge
120
150
  };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  resolveInstallSourceFor
3
- } from "./chunk-62CVUUNU.js";
3
+ } from "./chunk-5Y2DY6X4.js";
4
4
  import {
5
5
  backupFile,
6
6
  readJsonSafe,
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-T7E75EKA.js";
10
10
  import {
11
11
  configFilePath
12
- } from "./chunk-R6OYCUNK.js";
12
+ } from "./chunk-ON5JW2HP.js";
13
13
 
14
14
  // src/shell-alias.ts
15
15
  import { homedir } from "os";
@@ -2,27 +2,27 @@ import {
2
2
  detectProviderLiveCapabilities,
3
3
  hasSpawnProvider,
4
4
  resolveControlPolicy
5
- } from "./chunk-Y4ZH64UK.js";
5
+ } from "./chunk-VZMIHERK.js";
6
6
  import {
7
7
  daemonHasRemoteProof,
8
8
  daemonServiceManagerAvailable,
9
9
  hasDaemonServiceDefinition,
10
10
  readDaemonNeedsLogin,
11
11
  readDaemonStatus
12
- } from "./chunk-ZKJ34T2F.js";
12
+ } from "./chunk-EIGJYCOE.js";
13
13
  import {
14
14
  readControlMode,
15
15
  readKeySource
16
- } from "./chunk-D6OODZCM.js";
16
+ } from "./chunk-TJMAXQ5Q.js";
17
17
  import {
18
18
  getMachineId
19
- } from "./chunk-OVC5QXN5.js";
19
+ } from "./chunk-4A3UQERT.js";
20
20
  import {
21
21
  getBaseUrl
22
- } from "./chunk-R6OYCUNK.js";
22
+ } from "./chunk-ON5JW2HP.js";
23
23
  import {
24
24
  getPackageVersion
25
- } from "./chunk-G4GLCLKK.js";
25
+ } from "./chunk-5YY3IJT4.js";
26
26
 
27
27
  // src/machines.ts
28
28
  import { hostname } from "os";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getBaseUrl
3
- } from "./chunk-R6OYCUNK.js";
3
+ } from "./chunk-ON5JW2HP.js";
4
4
 
5
5
  // src/transcript-api.ts
6
6
  var fetchTranscriptRecipients = async (apiKey, baseUrl = getBaseUrl()) => {
@@ -1,16 +1,25 @@
1
1
  import {
2
+ CLI_PACKAGE_NAMES,
2
3
  HOOK_BUDGETS,
3
4
  HOOK_LOCATOR_BINARY,
5
+ OWNERSHIP_PROBE_COMMAND,
6
+ classifyGlobalFolder,
7
+ classifyGlobalInstall,
8
+ cmdShimTarget,
9
+ decideCommandOwner,
10
+ globalInstallTarget,
11
+ globalPackageFolder,
12
+ globalRootFor,
4
13
  isReleaseVersion,
14
+ ownPackageName,
5
15
  withHookHoldBudget
6
- } from "./chunk-G4GLCLKK.js";
16
+ } from "./chunk-5YY3IJT4.js";
7
17
 
8
18
  // src/npm.ts
9
19
  import { execFileSync, execSync } from "child_process";
10
- import { existsSync, readFileSync, realpathSync } from "fs";
20
+ import { existsSync, readFileSync, readlinkSync, realpathSync } from "fs";
11
21
  import { dirname, isAbsolute, join, relative, resolve } from "path";
12
- var AGENT_HOOKS_PACKAGE = "@pushary/agent-hooks";
13
- var LATEST_RELEASE_URL = `https://registry.npmjs.org/${AGENT_HOOKS_PACKAGE}/latest`;
22
+ var latestReleaseUrl = (packageName) => `https://registry.npmjs.org/${packageName}/latest`;
14
23
  var REGISTRY_TIMEOUT_MS = 5e3;
15
24
  var LATEST_TAG = "latest";
16
25
  var cleanNpmEnv = () => {
@@ -36,15 +45,21 @@ var execNpm = (args, options = {}) => {
36
45
  env: { ...cleanNpmEnv(), ...options.env ?? {} }
37
46
  });
38
47
  };
39
- var resolveGlobalBinary = (name) => {
48
+ var GLOBAL_PREFIX_TIMEOUT_MS = 5e3;
49
+ var readGlobalPrefix = () => {
40
50
  try {
41
- const prefix = execNpm("prefix -g --no-workspaces", { timeout: 5e3 }).toString().trim();
42
- const candidates = process.platform === "win32" ? [join(prefix, `${name}.cmd`), join(prefix, name)] : [join(prefix, "bin", name)];
43
- return candidates.find(existsSync);
51
+ const prefix = execNpm("prefix -g --no-workspaces", { timeout: GLOBAL_PREFIX_TIMEOUT_MS }).toString().trim();
52
+ return prefix === "" ? void 0 : prefix;
44
53
  } catch {
45
54
  return void 0;
46
55
  }
47
56
  };
57
+ var resolveGlobalBinary = (name) => {
58
+ const prefix = readGlobalPrefix();
59
+ if (prefix === void 0) return void 0;
60
+ const candidates = process.platform === "win32" ? [join(prefix, `${name}.cmd`), join(prefix, name)] : [join(prefix, "bin", name)];
61
+ return candidates.find(existsSync);
62
+ };
48
63
  var resolvePathBinary = (name, platform = process.platform) => {
49
64
  try {
50
65
  return execFileSync(platform === "win32" ? "where" : "which", [name], {
@@ -155,29 +170,79 @@ var AGENT_HOOKS_RUNTIME_FILES = [
155
170
  "data/cursor-plugin/hooks/hooks.json",
156
171
  "data/cursor-plugin/mcp.json",
157
172
  "data/cursor-plugin/scripts/pushary-gate.mjs",
173
+ "data/cursor-plugin/scripts/redaction.mjs",
158
174
  "data/vscode-plugin/.claude-plugin/plugin.json",
159
175
  "data/vscode-plugin/hooks/hooks.json",
160
176
  "data/vscode-plugin/.mcp.json",
161
- "data/vscode-plugin/scripts/pushary-gate.mjs"
177
+ "data/vscode-plugin/scripts/pushary-gate.mjs",
178
+ "data/vscode-plugin/scripts/redaction.mjs"
162
179
  ];
163
- var globalPackageBinsPresent = (name) => {
180
+ var globalPackageBinsPresent = (name, prefix, platform) => packageBinsPresent(globalPackageFolder(globalRootFor(prefix, platform), name, platform), prefix, platform, AGENT_HOOKS_RUNTIME_FILES);
181
+ var errorCode = (error) => typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
182
+ var realpathOrUndefined = (path) => {
164
183
  try {
165
- const root = execNpm("root -g --no-workspaces", { timeout: 5e3 }).toString().trim();
166
- const prefix = execNpm("prefix -g --no-workspaces", { timeout: 5e3 }).toString().trim();
167
- return packageBinsPresent(join(root, ...name.split("/")), prefix, process.platform, AGENT_HOOKS_RUNTIME_FILES);
184
+ return realpathSync(path);
168
185
  } catch {
169
- return false;
186
+ return void 0;
187
+ }
188
+ };
189
+ var definedPaths = (paths) => paths.filter((path) => path !== void 0);
190
+ var readPosixCommandLink = (prefix) => {
191
+ const command = join(prefix, "bin", OWNERSHIP_PROBE_COMMAND);
192
+ try {
193
+ const target = resolve(dirname(command), readlinkSync(command));
194
+ return { kind: "resolved", targets: definedPaths([target, realpathOrUndefined(command)]) };
195
+ } catch (error) {
196
+ if (errorCode(error) === "ENOENT") return { kind: "absent" };
197
+ const real = realpathOrUndefined(command);
198
+ return real === void 0 ? { kind: "unreadable" } : { kind: "resolved", targets: [real] };
199
+ }
200
+ };
201
+ var readWindowsCommandLink = (prefix) => {
202
+ const shim = join(prefix, `${OWNERSHIP_PROBE_COMMAND}.cmd`);
203
+ try {
204
+ const target = cmdShimTarget(prefix, readFileSync(shim, "utf8"));
205
+ return target === void 0 ? { kind: "unreadable" } : { kind: "resolved", targets: [target] };
206
+ } catch (error) {
207
+ return errorCode(error) === "ENOENT" ? { kind: "absent" } : { kind: "unreadable" };
170
208
  }
171
209
  };
210
+ var readCommandLink = (prefix, platform) => platform === "win32" ? readWindowsCommandLink(prefix) : readPosixCommandLink(prefix);
211
+ var readFolderManifest = (folder) => {
212
+ try {
213
+ return { kind: "read", manifest: JSON.parse(readFileSync(join(folder, "package.json"), "utf8")) };
214
+ } catch {
215
+ return { kind: "unreadable" };
216
+ }
217
+ };
218
+ var readGlobalFolder = (root, name, platform = process.platform) => classifyGlobalFolder(name, readFolderManifest(globalPackageFolder(root, name, platform)));
219
+ var installedIfOurs = (folder) => folder.kind === "ours" ? [folder.installed] : [];
220
+ var readInstalledCliPackages = (root, platform = process.platform) => CLI_PACKAGE_NAMES.flatMap((name) => installedIfOurs(readGlobalFolder(root, name, platform)));
221
+ var globalRootsFor = (prefix, platform) => {
222
+ const root = globalRootFor(prefix, platform);
223
+ return definedPaths([root, realpathOrUndefined(root)]);
224
+ };
225
+ var readCommandOwner = (prefix, platform = process.platform) => decideCommandOwner({
226
+ platform,
227
+ globalRoots: globalRootsFor(prefix, platform),
228
+ link: readCommandLink(prefix, platform),
229
+ installed: readInstalledCliPackages(globalRootFor(prefix, platform), platform).map((installed) => installed.name)
230
+ });
231
+ var NPM_UNAVAILABLE_OWNER = { kind: "unknown", reason: "npm_unavailable" };
232
+ var readGlobalCliInstallAt = (prefix, platform = process.platform) => classifyGlobalInstall(readInstalledCliPackages(globalRootFor(prefix, platform), platform), readCommandOwner(prefix, platform));
233
+ var readGlobalCliInstall = (platform = process.platform) => {
234
+ const prefix = readGlobalPrefix();
235
+ return prefix === void 0 ? { kind: "unavailable" } : readGlobalCliInstallAt(prefix, platform);
236
+ };
172
237
  var resolveGlobalBinDir = (probe) => {
173
238
  if (process.platform === "win32") return void 0;
174
239
  const resolved = resolveGlobalBinary(probe);
175
240
  return resolved ? resolved.slice(0, resolved.length - probe.length - 1) : void 0;
176
241
  };
177
242
  var quoteIfNeeded = (path) => /\s/.test(path) ? `"${path}"` : path;
178
- var fetchLatestPublishedVersion = async (request = {}) => {
243
+ var fetchLatestPublishedVersion = async (request) => {
179
244
  try {
180
- const response = await (request.fetchImpl ?? fetch)(LATEST_RELEASE_URL, {
245
+ const response = await (request.fetchImpl ?? fetch)(latestReleaseUrl(request.packageName), {
181
246
  signal: AbortSignal.timeout(request.timeoutMs ?? REGISTRY_TIMEOUT_MS)
182
247
  });
183
248
  if (!response.ok) return void 0;
@@ -190,29 +255,42 @@ var fetchLatestPublishedVersion = async (request = {}) => {
190
255
  };
191
256
  var POSIX_SHELL_WORD = /^[\w@%+=:,./-]+$/;
192
257
  var quoteForPosixShell = (value) => POSIX_SHELL_WORD.test(value) ? value : `'${value.replaceAll("'", `'\\''`)}'`;
193
- var installAgentHooksGlobally = (request, runNpm = execNpm) => {
258
+ var installPackageGlobally = (request, runNpm = execNpm) => {
194
259
  const prefixFlag = request.prefix === void 0 ? "" : ` --prefix ${quoteForPosixShell(request.prefix)}`;
195
- const spec = quoteForPosixShell(`${AGENT_HOOKS_PACKAGE}@${request.version}`);
260
+ const spec = quoteForPosixShell(`${request.packageName}@${request.version}`);
196
261
  runNpm(`install -g --no-workspaces${prefixFlag} ${spec}`, { timeout: request.timeoutMs });
197
262
  };
198
263
  var needsGlobalInstall = (requested, installed, binaryPresent) => requested !== installed || !binaryPresent;
264
+ var planGlobalInstall = (platform) => {
265
+ const prefix = readGlobalPrefix();
266
+ const owner = prefix === void 0 ? NPM_UNAVAILABLE_OWNER : readCommandOwner(prefix, platform);
267
+ return { prefix, packageName: globalInstallTarget(owner, ownPackageName()) };
268
+ };
269
+ var plannedGlobalPackage = () => planGlobalInstall(process.platform).packageName;
270
+ var installedVersionOf = (prefix, name, platform) => {
271
+ const folder = readGlobalFolder(globalRootFor(prefix, platform), name, platform);
272
+ return folder.kind === "ours" ? folder.installed.version : void 0;
273
+ };
274
+ var asCachedResult = (result) => result === "installed" ? "cached" : result;
199
275
  var installState;
200
276
  var installGlobally = (options) => {
201
277
  if (installState) {
202
- return installState.then((result) => result === "installed" ? "cached" : result);
278
+ return installState.then(asCachedResult);
203
279
  }
204
280
  const started = (async () => {
205
281
  if (!npmIsOnPath()) throw new NpmMissingError();
282
+ const platform = process.platform;
283
+ const { prefix, packageName } = planGlobalInstall(platform);
206
284
  const pinned = process.env.PUSHARY_PIN_GLOBAL_VERSION !== "0";
207
- if (pinned && !needsGlobalInstall(
285
+ if (pinned && prefix !== void 0 && !needsGlobalInstall(
208
286
  options.version,
209
- resolveGlobalPackageVersion(AGENT_HOOKS_PACKAGE),
210
- globalPackageBinsPresent(AGENT_HOOKS_PACKAGE)
287
+ installedVersionOf(prefix, packageName, platform),
288
+ globalPackageBinsPresent(packageName, prefix, platform)
211
289
  )) {
212
290
  return "skipped";
213
291
  }
214
292
  const version = pinned && options.version && options.version !== "0.0.0" ? options.version : LATEST_TAG;
215
- installAgentHooksGlobally({ version, timeoutMs: options.timeoutMs ?? 12e4 });
293
+ installPackageGlobally({ packageName, version, timeoutMs: options.timeoutMs ?? 12e4 });
216
294
  return "installed";
217
295
  })();
218
296
  installState = started;
@@ -670,10 +748,11 @@ export {
670
748
  registeredCommands,
671
749
  namesOurBinary,
672
750
  registrationHolderOf,
673
- AGENT_HOOKS_PACKAGE,
674
751
  LATEST_TAG,
752
+ cleanNpmEnv,
675
753
  npmErrorMessage,
676
754
  execNpm,
755
+ readGlobalPrefix,
677
756
  resolveGlobalBinary,
678
757
  resolvePathBinary,
679
758
  npmIsOnPath,
@@ -682,9 +761,13 @@ export {
682
761
  resolveBinary,
683
762
  resolvePackageVersionFromBinary,
684
763
  resolveGlobalPackageVersion,
764
+ readGlobalFolder,
765
+ readGlobalCliInstallAt,
766
+ readGlobalCliInstall,
685
767
  resolveGlobalBinDir,
686
768
  fetchLatestPublishedVersion,
687
- installAgentHooksGlobally,
769
+ installPackageGlobally,
770
+ plannedGlobalPackage,
688
771
  installGlobally,
689
772
  holdBudgetOf,
690
773
  guardBinary,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  redactSecretsFromContent
3
- } from "./chunk-G4GLCLKK.js";
3
+ } from "./chunk-5YY3IJT4.js";
4
4
 
5
5
  // src/crypto.ts
6
6
  import nacl from "tweetnacl";
@@ -1,12 +1,13 @@
1
1
  import {
2
2
  PRETOOLUSE_GATED_TOOLS
3
- } from "./chunk-G4GLCLKK.js";
3
+ } from "./chunk-5YY3IJT4.js";
4
4
 
5
5
  // src/claude-tools.ts
6
6
  var POSTTOOLUSE_MIRROR_ONLY_TOOLS = ["TodoWrite", "Task", "WebFetch", "WebSearch"];
7
7
  var POSTTOOLUSE_MIRRORED_TOOLS = [...PRETOOLUSE_GATED_TOOLS, ...POSTTOOLUSE_MIRROR_ONLY_TOOLS];
8
8
 
9
9
  // src/claude-notifications.ts
10
+ var IDLE_PROMPT_NOTIFICATION = "idle_prompt";
10
11
  var NOTIFICATION_MATCHED_TYPES = [
11
12
  // Blocks. The agent, or one of its workers, is waiting on a person.
12
13
  "permission_prompt",
@@ -34,6 +35,7 @@ var NOTIFICATION_PUSH_TYPES = /* @__PURE__ */ new Set([
34
35
  export {
35
36
  POSTTOOLUSE_MIRROR_ONLY_TOOLS,
36
37
  POSTTOOLUSE_MIRRORED_TOOLS,
38
+ IDLE_PROMPT_NOTIFICATION,
37
39
  NOTIFICATION_MATCHED_TYPES,
38
40
  NOTIFICATION_PUSH_TYPES
39
41
  };
@@ -2,10 +2,10 @@ import {
2
2
  resolveBinary,
3
3
  resolveGlobalPackageVersion,
4
4
  resolvePackageVersionFromBinary
5
- } from "./chunk-MZBRL5H5.js";
5
+ } from "./chunk-UPLV5AJF.js";
6
6
  import {
7
7
  MANAGED_PROVIDERS
8
- } from "./chunk-G4GLCLKK.js";
8
+ } from "./chunk-5YY3IJT4.js";
9
9
 
10
10
  // src/live-capabilities.ts
11
11
  var CLAUDE_BRIDGE_CAPABILITY = "claude-bridge";
@@ -6,10 +6,10 @@ import {
6
6
  codexHooksJsonIn,
7
7
  isPusharyCodexCommand,
8
8
  resolvePathBinary
9
- } from "./chunk-MZBRL5H5.js";
9
+ } from "./chunk-UPLV5AJF.js";
10
10
  import {
11
11
  getPackageVersion
12
- } from "./chunk-G4GLCLKK.js";
12
+ } from "./chunk-5YY3IJT4.js";
13
13
 
14
14
  // src/codex-app-server.ts
15
15
  import { existsSync, realpathSync } from "fs";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyDir
3
- } from "./chunk-MZBRL5H5.js";
3
+ } from "./chunk-UPLV5AJF.js";
4
4
  import {
5
5
  readJsonSafe
6
6
  } from "./chunk-T7E75EKA.js";
@@ -9,17 +9,17 @@ import {
9
9
  reapplyGeminiSettings,
10
10
  reapplyVsCodePlugin,
11
11
  repairCodexHolds
12
- } from "./chunk-G6RRVJOG.js";
13
- import "./chunk-IPSRMLCJ.js";
14
- import "./chunk-RLW3JWDY.js";
15
- import "./chunk-G3OMOTJ4.js";
16
- import "./chunk-WTJM7PSL.js";
17
- import "./chunk-MIXWMA73.js";
12
+ } from "./chunk-GH6KGWMC.js";
13
+ import "./chunk-ASWRMBOM.js";
14
+ import "./chunk-W2LJ4O3A.js";
15
+ import "./chunk-JRQRNNGA.js";
16
+ import "./chunk-OCVVSRDA.js";
17
+ import "./chunk-HTEGMMT3.js";
18
18
  import "./chunk-XHKBHWLX.js";
19
- import "./chunk-EUGNVLMG.js";
20
- import "./chunk-MZBRL5H5.js";
19
+ import "./chunk-VFFHQC7W.js";
20
+ import "./chunk-UPLV5AJF.js";
21
21
  import "./chunk-T7E75EKA.js";
22
- import "./chunk-G4GLCLKK.js";
22
+ import "./chunk-5YY3IJT4.js";
23
23
  export {
24
24
  ensureCodexTrustAfterReapply,
25
25
  inspectConfiguredManagedProviders,
package/dist/src/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  handlePreToolUse
3
- } from "../chunk-62VT3BPH.js";
4
- import "../chunk-UOQRM7JQ.js";
5
- import "../chunk-G3OMOTJ4.js";
6
- import "../chunk-5GB22QYL.js";
7
- import "../chunk-IRZG3HEU.js";
3
+ } from "../chunk-HQRCVEI2.js";
4
+ import "../chunk-QB6QYZ6B.js";
5
+ import "../chunk-JRQRNNGA.js";
6
+ import "../chunk-5DGNEUXK.js";
7
+ import "../chunk-7ITOAMCD.js";
8
8
  import "../chunk-5OP5MQI7.js";
9
- import "../chunk-MIXWMA73.js";
9
+ import "../chunk-HTEGMMT3.js";
10
10
  import {
11
11
  fetchAccountPublicKey
12
- } from "../chunk-WPX67AKT.js";
12
+ } from "../chunk-UMMCHS6P.js";
13
13
  import {
14
14
  fetchModeOverride,
15
15
  fetchModeState,
@@ -18,33 +18,33 @@ import {
18
18
  handlePostToolUse,
19
19
  handleStop,
20
20
  reportEvent
21
- } from "../chunk-U6RVDUJ5.js";
21
+ } from "../chunk-F6NTWZZC.js";
22
22
  import "../chunk-N6IOSZOE.js";
23
- import "../chunk-EUGNVLMG.js";
23
+ import "../chunk-VFFHQC7W.js";
24
24
  import {
25
25
  askUser,
26
26
  cancelQuestion,
27
27
  waitForAnswer
28
- } from "../chunk-YC27PROF.js";
29
- import "../chunk-N5MZH5A6.js";
28
+ } from "../chunk-MMVCI6DT.js";
29
+ import "../chunk-KB2FTO4O.js";
30
30
  import "../chunk-POFBE6ZY.js";
31
- import "../chunk-VE7TXLR4.js";
32
- import "../chunk-EEEJ2JIL.js";
33
- import "../chunk-DUQO4C4I.js";
34
- import "../chunk-OVC5QXN5.js";
31
+ import "../chunk-I4HKMUZQ.js";
32
+ import "../chunk-DVW2MYCM.js";
33
+ import "../chunk-2SLCHCVN.js";
34
+ import "../chunk-4A3UQERT.js";
35
35
  import "../chunk-7QLSKOSU.js";
36
36
  import "../chunk-KZERVKTD.js";
37
- import "../chunk-62CVUUNU.js";
38
- import "../chunk-MZBRL5H5.js";
37
+ import "../chunk-5Y2DY6X4.js";
38
+ import "../chunk-UPLV5AJF.js";
39
39
  import "../chunk-T7E75EKA.js";
40
40
  import {
41
41
  getApiKey,
42
42
  getBaseUrl
43
- } from "../chunk-R6OYCUNK.js";
44
- import "../chunk-YYCTF4Q5.js";
43
+ } from "../chunk-ON5JW2HP.js";
44
+ import "../chunk-35X5UDML.js";
45
45
  import {
46
46
  resolvePolicy
47
- } from "../chunk-G4GLCLKK.js";
47
+ } from "../chunk-5YY3IJT4.js";
48
48
  export {
49
49
  askUser,
50
50
  cancelQuestion,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pushary/agent-hooks",
3
- "version": "1.7.3",
3
+ "version": "1.8.1",
4
4
  "description": "Permission hooks for AI coding agents: route tool approvals through Pushary push notifications",
5
5
  "keywords": [
6
6
  "pushary",