@pushary/agent-hooks 1.7.3 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +13 -1
  3. package/data/cursor-plugin/scripts/pushary-gate.mjs +2 -21
  4. package/data/cursor-plugin/scripts/redaction.mjs +51 -0
  5. package/data/vscode-plugin/scripts/pushary-gate.mjs +1 -21
  6. package/data/vscode-plugin/scripts/redaction.mjs +51 -0
  7. package/dist/bin/pushary-bell-hook.js +23 -23
  8. package/dist/bin/pushary-bell.js +9 -9
  9. package/dist/bin/pushary-claude.js +26 -26
  10. package/dist/bin/pushary-clean.js +91 -107
  11. package/dist/bin/pushary-codex-bridge.js +18 -18
  12. package/dist/bin/pushary-codex-hook.js +42 -43
  13. package/dist/bin/pushary-codex.js +13 -13
  14. package/dist/bin/pushary-connect.js +13 -13
  15. package/dist/bin/pushary-cowork.js +5 -5
  16. package/dist/bin/pushary-daemon.js +27 -27
  17. package/dist/bin/pushary-disconnect.js +18 -18
  18. package/dist/bin/pushary-doctor.js +85 -79
  19. package/dist/bin/pushary-elicitation-hook.js +25 -25
  20. package/dist/bin/pushary-gemini-bridge.js +12 -12
  21. package/dist/bin/pushary-gemini-hook.js +29 -30
  22. package/dist/bin/pushary-hook.js +32 -32
  23. package/dist/bin/pushary-login.js +12 -12
  24. package/dist/bin/pushary-logout.js +7 -7
  25. package/dist/bin/pushary-mcp.js +85 -28
  26. package/dist/bin/pushary-mode.js +9 -9
  27. package/dist/bin/pushary-notification-hook.js +28 -28
  28. package/dist/bin/pushary-opencode-hook.js +28 -29
  29. package/dist/bin/pushary-permission-denied-hook.js +32 -32
  30. package/dist/bin/pushary-permission-hook.js +31 -31
  31. package/dist/bin/pushary-post-hook.js +28 -28
  32. package/dist/bin/pushary-prompt-hook.js +28 -28
  33. package/dist/bin/pushary-session-end-hook.js +28 -28
  34. package/dist/bin/pushary-session-start-hook.js +32 -32
  35. package/dist/bin/pushary-setup.js +60 -127
  36. package/dist/bin/pushary-stats.js +5 -5
  37. package/dist/bin/pushary-status.js +15 -15
  38. package/dist/bin/pushary-stop-hook.js +28 -28
  39. package/dist/bin/pushary-stopfailure-hook.js +28 -28
  40. package/dist/bin/pushary-suggestions.js +4 -4
  41. package/dist/bin/pushary-transcript-register.js +19 -19
  42. package/dist/bin/pushary-transcripts.js +7 -7
  43. package/dist/bin/pushary-upgrade.js +231 -105
  44. package/dist/bin/pushary-wait.js +9 -9
  45. package/dist/bin/pushary.js +6 -6
  46. package/dist/{chunk-EEEJ2JIL.js → chunk-2ABTSGFT.js} +3 -3
  47. package/dist/{chunk-DUQO4C4I.js → chunk-2OY3ZZ5N.js} +3 -3
  48. package/dist/{chunk-MIXWMA73.js → chunk-3EVPNIBE.js} +3 -3
  49. package/dist/{chunk-WTJM7PSL.js → chunk-6J2JC2RT.js} +3 -3
  50. package/dist/{chunk-EADXTSHE.js → chunk-7Z7Q4GGS.js} +2 -2
  51. package/dist/{chunk-MZBRL5H5.js → chunk-A2A2YTMG.js} +108 -25
  52. package/dist/{chunk-KEL5MXRL.js → chunk-AHV4LNB5.js} +1 -1
  53. package/dist/{chunk-G3OMOTJ4.js → chunk-AXPCESYO.js} +3 -3
  54. package/dist/{chunk-3EUBQARL.js → chunk-C2WCPBF7.js} +1 -1
  55. package/dist/chunk-CJVVKOSR.js +73 -0
  56. package/dist/{chunk-U6RVDUJ5.js → chunk-CULUZTWQ.js} +283 -41
  57. package/dist/{chunk-N5MZH5A6.js → chunk-CVQYGMSR.js} +4 -4
  58. package/dist/{chunk-VKVSRCBO.js → chunk-D2FX3EPW.js} +1 -1
  59. package/dist/{chunk-62CVUUNU.js → chunk-DB3ONZB4.js} +2 -2
  60. package/dist/{chunk-WGMW7OXW.js → chunk-DE4Y6TCC.js} +6 -6
  61. package/dist/{chunk-YYCTF4Q5.js → chunk-E4FJTUH4.js} +1 -1
  62. package/dist/{chunk-EUGNVLMG.js → chunk-EPCXUP3P.js} +3 -1
  63. package/dist/{chunk-PRNFSORD.js → chunk-EX3GAPA4.js} +1 -1
  64. package/dist/{chunk-TCVMK6GI.js → chunk-EYK3GSRH.js} +4 -4
  65. package/dist/{chunk-R6OYCUNK.js → chunk-GPEGOGRJ.js} +1 -1
  66. package/dist/chunk-GU3EJCVV.js +43 -0
  67. package/dist/{chunk-Y4ZH64UK.js → chunk-HQ6G3B5R.js} +2 -2
  68. package/dist/{chunk-5S2VBSJI.js → chunk-HZVVNGEW.js} +2 -2
  69. package/dist/{chunk-IWJKSIB4.js → chunk-IPVKH2ST.js} +1 -1
  70. package/dist/{chunk-UOQRM7JQ.js → chunk-J5TIV3J6.js} +5 -5
  71. package/dist/{chunk-IRZG3HEU.js → chunk-JU6W3XAU.js} +1 -1
  72. package/dist/{chunk-G62JL2NT.js → chunk-JYG4B33G.js} +1 -1
  73. package/dist/{chunk-OTNOANMX.js → chunk-JZTHGAPA.js} +8 -8
  74. package/dist/{chunk-7RUJKCR4.js → chunk-KGDWDSNL.js} +2 -2
  75. package/dist/{chunk-6JQFIHZC.js → chunk-KVQBWI5T.js} +3 -3
  76. package/dist/{chunk-OVC5QXN5.js → chunk-LXQ5FBBD.js} +1 -1
  77. package/dist/{chunk-VE7TXLR4.js → chunk-M5ICYGHT.js} +3 -3
  78. package/dist/{chunk-YPUBA2FL.js → chunk-M5JDZ45W.js} +4 -4
  79. package/dist/{chunk-O3JDWNLU.js → chunk-MDEPU45E.js} +183 -28
  80. package/dist/{chunk-P2VIBGXA.js → chunk-MPWXGONV.js} +1 -1
  81. package/dist/{chunk-YC27PROF.js → chunk-NGDD6TXY.js} +20 -5
  82. package/dist/{chunk-G4GLCLKK.js → chunk-NQTHFF4W.js} +138 -17
  83. package/dist/{chunk-NOI3XTCY.js → chunk-OKXS7WDZ.js} +1 -1
  84. package/dist/{chunk-LPNJLKBQ.js → chunk-OLQRRFBX.js} +1 -1
  85. package/dist/{chunk-D6OODZCM.js → chunk-P7WQEVWA.js} +2 -2
  86. package/dist/{chunk-62VT3BPH.js → chunk-Q7E4I6UA.js} +28 -16
  87. package/dist/{chunk-BIH2Y2HP.js → chunk-R7437YI3.js} +2 -2
  88. package/dist/{chunk-RLW3JWDY.js → chunk-RHR6NARM.js} +2 -2
  89. package/dist/{chunk-WPX67AKT.js → chunk-SAXBC4AZ.js} +1 -1
  90. package/dist/{chunk-IPSRMLCJ.js → chunk-SIFVFP6T.js} +1 -1
  91. package/dist/{chunk-7OA34PNW.js → chunk-SLFABHW3.js} +40 -10
  92. package/dist/{chunk-AWVNAYGD.js → chunk-TY4JT7W3.js} +1 -1
  93. package/dist/{chunk-KJXUIPS4.js → chunk-UI36QSBI.js} +28 -16
  94. package/dist/{chunk-G6RRVJOG.js → chunk-VQKRG3AC.js} +6 -6
  95. package/dist/{chunk-ZKJ34T2F.js → chunk-WE2J62NC.js} +31 -17
  96. package/dist/{chunk-LHC45YUC.js → chunk-ZSZSSJCV.js} +1 -1
  97. package/dist/{chunk-BGBLLHZ4.js → chunk-ZVSKMPBZ.js} +1 -1
  98. package/dist/{reapply-PH5T4BGR.js → reapply-CW3MA66V.js} +9 -9
  99. package/dist/src/index.js +20 -20
  100. package/package.json +1 -1
  101. package/dist/chunk-5GB22QYL.js +0 -255
  102. package/dist/chunk-VYPJHGG6.js +0 -92
@@ -1,34 +1,34 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  describeCodexTrustConfirmation
4
- } from "../chunk-AWVNAYGD.js";
4
+ } from "../chunk-TY4JT7W3.js";
5
5
  import {
6
6
  ensureCodexTrustAfterReapply,
7
7
  reapplyAllAgents
8
- } from "../chunk-G6RRVJOG.js";
9
- import "../chunk-IPSRMLCJ.js";
10
- import "../chunk-RLW3JWDY.js";
8
+ } from "../chunk-VQKRG3AC.js";
9
+ import "../chunk-SIFVFP6T.js";
10
+ import "../chunk-RHR6NARM.js";
11
11
  import {
12
12
  waitForMachineReadiness
13
- } from "../chunk-WGMW7OXW.js";
14
- import "../chunk-G3OMOTJ4.js";
13
+ } from "../chunk-DE4Y6TCC.js";
14
+ import "../chunk-AXPCESYO.js";
15
15
  import {
16
16
  detectProviderLiveCapabilities,
17
17
  hasSpawnProvider,
18
18
  resolveControlPolicy
19
- } from "../chunk-Y4ZH64UK.js";
19
+ } from "../chunk-HQ6G3B5R.js";
20
20
  import {
21
21
  AUTO_UPDATE_DISABLE_ENV,
22
22
  describeAutoUpdateCheck,
23
- globalInstallPrefix,
23
+ globalInstallLocation,
24
24
  hasPendingUpgradeFinish,
25
25
  isAutoUpdateDisabledByEnv,
26
26
  parseAutoUpdateFlag,
27
27
  readAutoUpdateState,
28
28
  updateAutoUpdateState,
29
29
  upgradeEntryFor
30
- } from "../chunk-KJXUIPS4.js";
31
- import "../chunk-WTJM7PSL.js";
30
+ } from "../chunk-UI36QSBI.js";
31
+ import "../chunk-6J2JC2RT.js";
32
32
  import {
33
33
  daemonHasRemoteProof,
34
34
  daemonServiceManagerAvailable,
@@ -39,24 +39,22 @@ import {
39
39
  replaceDaemonService,
40
40
  stopDaemonService,
41
41
  waitForDaemonRemoteProof
42
- } from "../chunk-ZKJ34T2F.js";
43
- import "../chunk-MIXWMA73.js";
44
- import {
45
- needsShell
46
- } from "../chunk-XHKBHWLX.js";
47
- import "../chunk-EUGNVLMG.js";
42
+ } from "../chunk-WE2J62NC.js";
43
+ import "../chunk-3EVPNIBE.js";
44
+ import "../chunk-XHKBHWLX.js";
45
+ import "../chunk-EPCXUP3P.js";
48
46
  import "../chunk-POFBE6ZY.js";
49
47
  import {
50
48
  exitOnHelpFlag
51
- } from "../chunk-5S2VBSJI.js";
49
+ } from "../chunk-HZVVNGEW.js";
52
50
  import {
53
51
  readControlMode
54
- } from "../chunk-D6OODZCM.js";
55
- import "../chunk-OVC5QXN5.js";
52
+ } from "../chunk-P7WQEVWA.js";
53
+ import "../chunk-LXQ5FBBD.js";
56
54
  import {
57
55
  EXIT
58
56
  } from "../chunk-KZERVKTD.js";
59
- import "../chunk-62CVUUNU.js";
57
+ import "../chunk-DB3ONZB4.js";
60
58
  import {
61
59
  LATEST_TAG,
62
60
  autoUpdateLock,
@@ -68,35 +66,43 @@ import {
68
66
  execNpm,
69
67
  fetchLatestPublishedVersion,
70
68
  geminiSettings,
71
- installAgentHooksGlobally,
69
+ installPackageGlobally,
72
70
  npmErrorMessage,
73
- resolveGlobalBinary,
71
+ readGlobalCliInstallAt,
72
+ readGlobalPrefix,
74
73
  vscodePluginDir
75
- } from "../chunk-MZBRL5H5.js";
74
+ } from "../chunk-A2A2YTMG.js";
76
75
  import "../chunk-T7E75EKA.js";
77
76
  import {
78
77
  getApiKey
79
- } from "../chunk-R6OYCUNK.js";
78
+ } from "../chunk-GPEGOGRJ.js";
80
79
  import {
81
80
  NPX_LATEST_COMMAND
82
- } from "../chunk-YYCTF4Q5.js";
81
+ } from "../chunk-E4FJTUH4.js";
83
82
  import {
83
+ CANONICAL_PACKAGE,
84
+ LEGACY_PACKAGE,
85
+ commandsPackage,
86
+ globalUpgradeEntry,
84
87
  isNewerVersion,
85
88
  isReleaseVersion,
86
89
  isSameMajorVersion,
87
90
  ownPackageRoot,
88
91
  packageVersionAt
89
- } from "../chunk-G4GLCLKK.js";
92
+ } from "../chunk-NQTHFF4W.js";
90
93
 
91
94
  // bin/pushary-upgrade.ts
92
- import { existsSync } from "fs";
95
+ import { existsSync as existsSync2 } from "fs";
93
96
  import { homedir } from "os";
94
97
  import { join } from "path";
98
+
99
+ // src/global-upgrade.ts
95
100
  import { execFileSync as execFileSync2 } from "child_process";
101
+ import { existsSync } from "fs";
96
102
 
97
103
  // src/auto-update-run.ts
98
104
  import { execFileSync } from "child_process";
99
- import { closeSync, mkdirSync, openSync, statSync, unlinkSync, writeSync } from "fs";
105
+ import { closeSync, mkdirSync, openSync, readFileSync, statSync, unlinkSync, writeSync } from "fs";
100
106
  import { dirname } from "path";
101
107
  var FINISH_UPGRADE_FLAG = "--finish-upgrade";
102
108
  var LOCK_STALE_MS = 10 * 60 * 1e3;
@@ -129,10 +135,7 @@ var isStaleLock = (lockPath, now) => {
129
135
  const modifiedAt = statSync(lockPath, { throwIfNoEntry: false })?.mtimeMs;
130
136
  return modifiedAt !== void 0 && now - modifiedAt > LOCK_STALE_MS;
131
137
  };
132
- var acquireAutoUpdateLock = (lockPath, now) => {
133
- mkdirSync(dirname(lockPath), { recursive: true });
134
- if (tryCreateLock(lockPath, now) === "acquired") return "acquired";
135
- if (!isStaleLock(lockPath, now)) return "held";
138
+ var takeOverLock = (lockPath, now) => {
136
139
  try {
137
140
  unlinkSync(lockPath);
138
141
  } catch {
@@ -140,6 +143,38 @@ var acquireAutoUpdateLock = (lockPath, now) => {
140
143
  }
141
144
  return tryCreateLock(lockPath, now);
142
145
  };
146
+ var isAbandonedLock = (evidence) => evidence.stale || evidence.holderPid !== void 0 && !evidence.holderAlive;
147
+ var lockHolderPid = (lockPath) => {
148
+ try {
149
+ const holder = JSON.parse(readFileSync(lockPath, "utf8"));
150
+ const pid = holder && typeof holder === "object" && "pid" in holder ? holder.pid : void 0;
151
+ return typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : void 0;
152
+ } catch {
153
+ return void 0;
154
+ }
155
+ };
156
+ var isProcessAlive = (pid) => {
157
+ try {
158
+ process.kill(pid, 0);
159
+ return true;
160
+ } catch (error) {
161
+ return error instanceof Error && "code" in error && error.code === "EPERM";
162
+ }
163
+ };
164
+ var readLockHolder = (lockPath, now, isAlive) => {
165
+ const holderPid = lockHolderPid(lockPath);
166
+ return {
167
+ holderPid,
168
+ holderAlive: holderPid !== void 0 && isAlive(holderPid),
169
+ stale: isStaleLock(lockPath, now)
170
+ };
171
+ };
172
+ var acquireAutoUpdateLock = (lockPath, now) => {
173
+ mkdirSync(dirname(lockPath), { recursive: true });
174
+ if (tryCreateLock(lockPath, now) === "acquired") return "acquired";
175
+ if (!isStaleLock(lockPath, now)) return "held";
176
+ return takeOverLock(lockPath, now);
177
+ };
143
178
  var releaseAutoUpdateLock = (lockPath) => {
144
179
  try {
145
180
  unlinkSync(lockPath);
@@ -147,6 +182,28 @@ var releaseAutoUpdateLock = (lockPath) => {
147
182
  return;
148
183
  }
149
184
  };
185
+ var upgradeLockVerdict = (evidence) => {
186
+ if (evidence.holderPid !== void 0 && evidence.holderPid === evidence.parentPid) return "inherited";
187
+ if (isAbandonedLock(evidence)) return "take_over";
188
+ return "held";
189
+ };
190
+ var claimUpgradeLockAt = (lockPath, request) => {
191
+ const now = request.now ?? Date.now();
192
+ mkdirSync(dirname(lockPath), { recursive: true });
193
+ if (tryCreateLock(lockPath, now) === "acquired") return { kind: "acquired" };
194
+ const holder = readLockHolder(lockPath, now, request.isAlive ?? isProcessAlive);
195
+ const verdict = upgradeLockVerdict({ ...holder, parentPid: request.parentPid ?? process.ppid });
196
+ if (verdict === "inherited") return { kind: "inherited" };
197
+ if (verdict === "take_over" && takeOverLock(lockPath, now) === "acquired") return { kind: "acquired" };
198
+ return { kind: "held", holderPid: holder.holderPid };
199
+ };
200
+ var claimUpgradeLock = (request = {}) => {
201
+ try {
202
+ return claimUpgradeLockAt(request.lockPath ?? autoUpdateLock(), request);
203
+ } catch {
204
+ return { kind: "unavailable" };
205
+ }
206
+ };
150
207
  var openAutoUpdateLog = (logPath) => {
151
208
  mkdirSync(dirname(logPath), { recursive: true });
152
209
  const size = statSync(logPath, { throwIfNoEntry: false })?.size ?? 0;
@@ -183,7 +240,7 @@ var finishInstalledUpgrade = (context, from, to) => {
183
240
  const pending = { result: "finish_pending", from, to, detail: incompleteFinishDetail(context.logPath) };
184
241
  recordAutoUpdateCheck(context.statePath, pending, new Date(context.now()).toISOString());
185
242
  try {
186
- context.finish({ entry: upgradeEntryFor(context.prefix), prefix: context.prefix, logPath: context.logPath });
243
+ context.finish({ entry: upgradeEntryFor(context.location), prefix: context.location.prefix, logPath: context.logPath });
187
244
  return { result: "updated", from, to };
188
245
  } catch {
189
246
  return pending;
@@ -197,16 +254,21 @@ var checkAndInstall = async (context) => {
197
254
  }
198
255
  const previous = readAutoUpdateState(context.statePath);
199
256
  const pendingFinish = hasPendingUpgradeFinish(previous, installed);
200
- const latest = await fetchLatestPublishedVersion({ fetchImpl: context.fetchImpl });
257
+ const latest = await fetchLatestPublishedVersion({ packageName: context.location.packageName, fetchImpl: context.fetchImpl });
201
258
  if (pendingFinish && !isInstallableRelease(latest, installed)) return finishInstalledUpgrade(context, previous.from, installed);
202
259
  if (latest === void 0) return { result: "failed", from: installed, detail: UNREACHABLE_REGISTRY };
203
260
  if (!isNewerVersion(latest, installed)) return { result: "current", from: installed };
204
261
  if (!isSameMajorVersion(latest, installed)) {
205
262
  return { result: "needs_manual", from: installed, to: latest, detail: newMajorDetail(latest) };
206
263
  }
207
- appendAutoUpdateLog(context.logPath, `${new Date(context.now()).toISOString()} installing ${latest} into ${context.prefix}`);
264
+ appendAutoUpdateLog(context.logPath, `${new Date(context.now()).toISOString()} installing ${context.location.packageName}@${latest} into ${context.location.prefix}`);
208
265
  try {
209
- installAgentHooksGlobally({ version: latest, prefix: context.prefix, timeoutMs: INSTALL_TIMEOUT_MS }, context.runNpm);
266
+ installPackageGlobally({
267
+ packageName: context.location.packageName,
268
+ version: latest,
269
+ prefix: context.location.prefix,
270
+ timeoutMs: INSTALL_TIMEOUT_MS
271
+ }, context.runNpm);
210
272
  } catch (error) {
211
273
  if (pendingFinish) return finishInstalledUpgrade(context, previous.from, installed);
212
274
  return { result: "failed", from: installed, to: latest, detail: npmErrorMessage(error) };
@@ -225,8 +287,8 @@ var recordAutoUpdateCheck = (statePath, check, at) => updateAutoUpdateState(stat
225
287
  var runAutoUpdate = async (run = {}) => {
226
288
  if ((run.platform ?? process.platform) === "linux") return { kind: "linux" };
227
289
  const packageRoot = run.packageRoot ?? ownPackageRoot();
228
- const prefix = packageRoot === void 0 ? null : globalInstallPrefix(packageRoot);
229
- if (packageRoot === void 0 || prefix === null) return { kind: "not_global_install" };
290
+ const location = packageRoot === void 0 ? null : globalInstallLocation(packageRoot);
291
+ if (packageRoot === void 0 || location === null) return { kind: "not_global_install" };
230
292
  const now = run.now ?? Date.now;
231
293
  const lockPath = run.lockPath ?? autoUpdateLock();
232
294
  const logPath = run.logPath ?? autoUpdateLog();
@@ -235,7 +297,7 @@ var runAutoUpdate = async (run = {}) => {
235
297
  const check = await checkAndInstall({
236
298
  packageRoot,
237
299
  statePath: run.statePath ?? autoUpdateState(),
238
- prefix,
300
+ location,
239
301
  logPath,
240
302
  now,
241
303
  fetchImpl: run.fetchImpl ?? fetch,
@@ -251,6 +313,62 @@ var runAutoUpdate = async (run = {}) => {
251
313
  }
252
314
  };
253
315
 
316
+ // src/global-upgrade.ts
317
+ var NOT_INSTALLED = { kind: "not_installed" };
318
+ var globalUpgradeSubject = (prefix, install) => {
319
+ if (prefix === void 0) return NOT_INSTALLED;
320
+ const commands = commandsPackage(install);
321
+ if (commands?.version !== void 0) return { kind: "installed", prefix, name: commands.name, version: commands.version };
322
+ return install.kind === "both" ? { kind: "both_installed" } : NOT_INSTALLED;
323
+ };
324
+ var readGlobalUpgradeSubject = (platform = process.platform) => {
325
+ const prefix = readGlobalPrefix();
326
+ return globalUpgradeSubject(prefix, prefix === void 0 ? { kind: "unavailable" } : readGlobalCliInstallAt(prefix, platform));
327
+ };
328
+ var finishWithThisNode = (entry) => {
329
+ execFileSync2(process.execPath, [entry, FINISH_UPGRADE_FLAG], { stdio: "inherit" });
330
+ };
331
+ var finishGlobalUpgrade = (subject, platform = process.platform, runFinish = finishWithThisNode) => {
332
+ const entry = globalUpgradeEntry(subject.prefix, subject.name, platform);
333
+ if (!existsSync(entry)) return { kind: "entry_missing", entry };
334
+ try {
335
+ runFinish(entry);
336
+ return { kind: "finished" };
337
+ } catch {
338
+ return { kind: "failed" };
339
+ }
340
+ };
341
+ var describeHeldUpgradeLock = (holderPid) => `Another Pushary upgrade is already running${holderPid === void 0 ? "" : ` (pid ${holderPid})`}. Try again when it has finished.`;
342
+ var withUpgradeLock = async (run, request = {}) => {
343
+ const claim = claimUpgradeLock(request);
344
+ if (claim.kind === "held") return { kind: "refused", exitCode: EXIT.FAILED, message: describeHeldUpgradeLock(claim.holderPid) };
345
+ try {
346
+ await run();
347
+ } finally {
348
+ if (claim.kind === "acquired") releaseAutoUpdateLock(request.lockPath ?? autoUpdateLock());
349
+ }
350
+ return { kind: "ran" };
351
+ };
352
+ var describeUpgradeStart = (subject, latest) => `Upgrading ${subject.name} ${subject.version} -> ${latest ?? "latest"}`;
353
+ var upgradeInstalledPackage = async (subject, effects) => {
354
+ const pendingFinish = effects.hasPendingFinish(subject.version);
355
+ const latest = await effects.fetchLatest(subject.name);
356
+ const newerPublished = latest !== void 0 && isNewerVersion(latest, subject.version);
357
+ if (pendingFinish && !newerPublished) {
358
+ const finish = effects.finish(subject);
359
+ if (finish.kind !== "finished") return { kind: "pending_finish_failed", finish };
360
+ effects.recordFinished();
361
+ }
362
+ if (latest !== void 0 && !newerPublished) return { kind: "current", version: subject.version };
363
+ effects.announce(describeUpgradeStart(subject, latest));
364
+ try {
365
+ effects.install(subject.name);
366
+ } catch (error) {
367
+ return { kind: "install_failed", detail: npmErrorMessage(error) };
368
+ }
369
+ return { kind: "installed", finish: effects.finish(subject) };
370
+ };
371
+
254
372
  // bin/pushary-upgrade.ts
255
373
  exitOnHelpFlag("upgrade");
256
374
  var detectInstallModes = () => {
@@ -258,43 +376,36 @@ var detectInstallModes = () => {
258
376
  {
259
377
  label: "Cursor plugin",
260
378
  upgrade: "updates itself through Cursor",
261
- present: existsSync(cursorPluginDir())
379
+ present: existsSync2(cursorPluginDir())
262
380
  },
263
381
  {
264
382
  label: "VS Code plugin",
265
383
  upgrade: "npx @pushary/agent-hooks@latest setup --agents vscode",
266
- present: existsSync(vscodePluginDir())
384
+ present: existsSync2(vscodePluginDir())
267
385
  },
268
386
  {
269
387
  label: "Codex config",
270
388
  upgrade: "npx @pushary/agent-hooks@latest setup --agents codex",
271
- present: existsSync(codexConfigToml())
389
+ present: existsSync2(codexConfigToml())
272
390
  },
273
391
  {
274
392
  label: "Claude Code config",
275
393
  upgrade: "npx @pushary/agent-hooks@latest setup --agents claude_code",
276
- present: existsSync(claudeJson())
394
+ present: existsSync2(claudeJson())
277
395
  },
278
396
  {
279
397
  label: "Gemini config",
280
398
  upgrade: "npx @pushary/agent-hooks@latest setup --agents gemini_cli",
281
- present: existsSync(geminiSettings())
399
+ present: existsSync2(geminiSettings())
282
400
  },
283
401
  {
284
402
  label: "Hermes plugin (pip)",
285
403
  upgrade: "npx @pushary/agent-hooks@latest setup --agents hermes",
286
- present: existsSync(join(homedir(), ".hermes"))
404
+ present: existsSync2(join(homedir(), ".hermes"))
287
405
  }
288
406
  ];
289
407
  return candidates.filter((candidate) => candidate.present).map(({ label, upgrade }) => ({ label, upgrade }));
290
408
  };
291
- var getInstalledVersion = () => {
292
- try {
293
- return execNpm("list -g --no-workspaces @pushary/agent-hooks --depth=0", { timeout: 1e4 }).toString().match(/@pushary\/agent-hooks@([\d.]+)/)?.[1] ?? "";
294
- } catch {
295
- return "";
296
- }
297
- };
298
409
  var finishUpgrade = async () => {
299
410
  let apiKey;
300
411
  try {
@@ -395,27 +506,78 @@ var runAutomaticUpdate = async () => {
395
506
  if (outcome.state.lastResult === "failed" || outcome.state.lastResult === "finish_pending") process.exitCode = 1;
396
507
  };
397
508
  var FINISH_FAILED_MESSAGE = "Upgrade installed, but refreshing the agent configs did not finish. Fix the problem printed above, then run pushary upgrade again.";
398
- var finishGlobalUpgrade = () => {
399
- const upgradedBinary = resolveGlobalBinary("pushary-upgrade");
400
- if (!upgradedBinary) {
401
- console.error("Upgrade installed, but the new pushary-upgrade binary could not be found on PATH.");
402
- process.exit(1);
509
+ var describeFinishFailure = (finish) => finish.kind === "entry_missing" ? `Upgrade installed, but the new pushary-upgrade entry was not found at ${finish.entry}.` : FINISH_FAILED_MESSAGE;
510
+ var reportFinish = (finish) => {
511
+ if (finish.kind === "finished") return;
512
+ console.error(describeFinishFailure(finish));
513
+ process.exitCode = EXIT.FAILED;
514
+ };
515
+ var reportGlobalUpgrade = (outcome) => {
516
+ switch (outcome.kind) {
517
+ case "current":
518
+ console.log(`Already on the latest version (${outcome.version}).`);
519
+ return;
520
+ case "install_failed":
521
+ console.error(`Upgrade failed: ${outcome.detail}`);
522
+ process.exitCode = EXIT.FAILED;
523
+ return;
524
+ case "pending_finish_failed":
525
+ case "installed":
526
+ reportFinish(outcome.finish);
403
527
  }
404
- try {
405
- execFileSync2(upgradedBinary, [FINISH_UPGRADE_FLAG], {
406
- stdio: "inherit",
407
- shell: needsShell(upgradedBinary)
408
- });
409
- return true;
410
- } catch {
411
- console.error(FINISH_FAILED_MESSAGE);
412
- process.exitCode = 1;
413
- return false;
528
+ };
529
+ var BOTH_INSTALLED_MESSAGE = `Both ${CANONICAL_PACKAGE} and ${LEGACY_PACKAGE} are installed globally, and which one runs the Pushary commands could not be read, so nothing was upgraded. Check with: ${NPX_LATEST_COMMAND} doctor`;
530
+ var reportNoGlobalInstall = () => {
531
+ const found = detectInstallModes();
532
+ console.log(`No global install of ${CANONICAL_PACKAGE} or ${LEGACY_PACKAGE} found, so there is nothing to upgrade here.`);
533
+ console.log();
534
+ if (found.length === 0) {
535
+ console.log("Nothing on this machine looks Pushary-configured either.");
536
+ console.log(" Set it up with: npx @pushary/agent-hooks@latest setup");
537
+ } else {
538
+ console.log("What this machine does have:");
539
+ for (const mode of found) {
540
+ console.log(` ${mode.label.padEnd(22)} ${mode.upgrade}`);
541
+ }
414
542
  }
543
+ console.log();
544
+ console.log("Check the result with: pushary doctor");
545
+ };
546
+ var upgradeSubject = async (subject) => {
547
+ const outcome = await upgradeInstalledPackage(subject, {
548
+ fetchLatest: (packageName) => fetchLatestPublishedVersion({ packageName }),
549
+ hasPendingFinish: (installed) => hasPendingUpgradeFinish(readAutoUpdateState(autoUpdateState()), installed),
550
+ recordFinished: () => {
551
+ updateAutoUpdateState(autoUpdateState(), { lastResult: "updated", detail: void 0, announced: false });
552
+ },
553
+ announce: (line) => console.log(line),
554
+ install: (packageName) => installPackageGlobally({ packageName, version: LATEST_TAG, timeoutMs: 12e4 }),
555
+ finish: (installedSubject) => finishGlobalUpgrade(installedSubject)
556
+ });
557
+ reportGlobalUpgrade(outcome);
558
+ };
559
+ var upgradeGlobalInstall = async () => {
560
+ const subject = readGlobalUpgradeSubject();
561
+ if (subject.kind === "not_installed") {
562
+ reportNoGlobalInstall();
563
+ return;
564
+ }
565
+ if (subject.kind === "both_installed") {
566
+ console.error(BOTH_INSTALLED_MESSAGE);
567
+ process.exitCode = EXIT.FAILED;
568
+ return;
569
+ }
570
+ await upgradeSubject(subject);
571
+ };
572
+ var runUnderUpgradeLock = async (run) => {
573
+ const locked = await withUpgradeLock(run);
574
+ if (locked.kind === "ran") return;
575
+ console.error(locked.message);
576
+ process.exitCode = locked.exitCode;
415
577
  };
416
578
  var main = async () => {
417
579
  if (process.argv.includes(FINISH_UPGRADE_FLAG)) {
418
- await finishUpgrade();
580
+ await runUnderUpgradeLock(finishUpgrade);
419
581
  return;
420
582
  }
421
583
  const autoFlag = parseAutoUpdateFlag(process.argv.slice(2));
@@ -432,42 +594,6 @@ var main = async () => {
432
594
  await runAutomaticUpdate();
433
595
  return;
434
596
  }
435
- const installed = getInstalledVersion();
436
- if (!installed) {
437
- const found = detectInstallModes();
438
- console.log("No global install of @pushary/agent-hooks found, so there is nothing to upgrade here.");
439
- console.log();
440
- if (found.length === 0) {
441
- console.log("Nothing on this machine looks Pushary-configured either.");
442
- console.log(" Set it up with: npx @pushary/agent-hooks@latest setup");
443
- } else {
444
- console.log("What this machine does have:");
445
- for (const mode of found) {
446
- console.log(` ${mode.label.padEnd(22)} ${mode.upgrade}`);
447
- }
448
- }
449
- console.log();
450
- console.log("Check the result with: pushary doctor");
451
- return;
452
- }
453
- const pendingFinish = hasPendingUpgradeFinish(readAutoUpdateState(autoUpdateState()), installed);
454
- const latest = await fetchLatestPublishedVersion();
455
- const newerPublished = latest !== void 0 && isNewerVersion(latest, installed);
456
- if (pendingFinish && !newerPublished) {
457
- if (!finishGlobalUpgrade()) return;
458
- updateAutoUpdateState(autoUpdateState(), { lastResult: "updated", detail: void 0, announced: false });
459
- }
460
- if (latest && !isNewerVersion(latest, installed)) {
461
- console.log(`Already on the latest version (${installed}).`);
462
- return;
463
- }
464
- console.log(`Upgrading @pushary/agent-hooks ${installed} -> ${latest ?? "latest"}`);
465
- try {
466
- installAgentHooksGlobally({ version: LATEST_TAG, timeoutMs: 12e4 });
467
- } catch (err) {
468
- console.error(`Upgrade failed: ${npmErrorMessage(err)}`);
469
- process.exit(1);
470
- }
471
- finishGlobalUpgrade();
597
+ await runUnderUpgradeLock(upgradeGlobalInstall);
472
598
  };
473
599
  main();
@@ -4,33 +4,33 @@ import {
4
4
  } from "../chunk-CVWG2N3Y.js";
5
5
  import {
6
6
  exitOnFailedResponse
7
- } from "../chunk-PRNFSORD.js";
7
+ } from "../chunk-EX3GAPA4.js";
8
8
  import {
9
9
  createIo
10
10
  } from "../chunk-U4TMAANR.js";
11
11
  import {
12
12
  exitOnHelpFlag
13
- } from "../chunk-5S2VBSJI.js";
13
+ } from "../chunk-HZVVNGEW.js";
14
14
  import {
15
15
  rejectUnknownFlags
16
16
  } from "../chunk-GMXKITVA.js";
17
- import "../chunk-EEEJ2JIL.js";
18
- import "../chunk-DUQO4C4I.js";
19
- import "../chunk-OVC5QXN5.js";
17
+ import "../chunk-2ABTSGFT.js";
18
+ import "../chunk-2OY3ZZ5N.js";
19
+ import "../chunk-LXQ5FBBD.js";
20
20
  import {
21
21
  UsageError
22
22
  } from "../chunk-7QLSKOSU.js";
23
23
  import {
24
24
  EXIT
25
25
  } from "../chunk-KZERVKTD.js";
26
- import "../chunk-MZBRL5H5.js";
26
+ import "../chunk-A2A2YTMG.js";
27
27
  import "../chunk-T7E75EKA.js";
28
28
  import {
29
29
  getApiKey,
30
30
  getBaseUrl
31
- } from "../chunk-R6OYCUNK.js";
32
- import "../chunk-YYCTF4Q5.js";
33
- import "../chunk-G4GLCLKK.js";
31
+ } from "../chunk-GPEGOGRJ.js";
32
+ import "../chunk-E4FJTUH4.js";
33
+ import "../chunk-NQTHFF4W.js";
34
34
 
35
35
  // bin/pushary-wait.ts
36
36
  exitOnHelpFlag("wait");
@@ -1,23 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  installNetworkDefaults
4
- } from "../chunk-DUQO4C4I.js";
5
- import "../chunk-OVC5QXN5.js";
4
+ } from "../chunk-2OY3ZZ5N.js";
5
+ import "../chunk-LXQ5FBBD.js";
6
6
  import "../chunk-7QLSKOSU.js";
7
7
  import {
8
8
  EXIT
9
9
  } from "../chunk-KZERVKTD.js";
10
- import "../chunk-MZBRL5H5.js";
10
+ import "../chunk-A2A2YTMG.js";
11
11
  import "../chunk-T7E75EKA.js";
12
- import "../chunk-R6OYCUNK.js";
12
+ import "../chunk-GPEGOGRJ.js";
13
13
  import {
14
14
  COMMANDS,
15
15
  isCommandName,
16
16
  renderHelp
17
- } from "../chunk-YYCTF4Q5.js";
17
+ } from "../chunk-E4FJTUH4.js";
18
18
  import {
19
19
  getPackageVersion
20
- } from "../chunk-G4GLCLKK.js";
20
+ } from "../chunk-NQTHFF4W.js";
21
21
 
22
22
  // src/cli/runtime.ts
23
23
  var supportsRuntime = (version) => {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  pusharyFetch
3
- } from "./chunk-DUQO4C4I.js";
3
+ } from "./chunk-2OY3ZZ5N.js";
4
4
  import {
5
5
  NetworkError
6
6
  } from "./chunk-7QLSKOSU.js";
@@ -9,11 +9,11 @@ import {
9
9
  } from "./chunk-KZERVKTD.js";
10
10
  import {
11
11
  getBaseUrl
12
- } from "./chunk-R6OYCUNK.js";
12
+ } from "./chunk-GPEGOGRJ.js";
13
13
  import {
14
14
  isValidApiKey,
15
15
  normalizeKeyScope
16
- } from "./chunk-G4GLCLKK.js";
16
+ } from "./chunk-NQTHFF4W.js";
17
17
 
18
18
  // src/session.ts
19
19
  var samePusharyAccount = (left, right) => left.kind === "ok" && right.kind === "ok" && left.identity.workspaceId !== "" && left.identity.workspaceId === right.identity.workspaceId && left.identity.siteId === right.identity.siteId;
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  readExistingMachineId
3
- } from "./chunk-OVC5QXN5.js";
3
+ } from "./chunk-LXQ5FBBD.js";
4
4
  import {
5
5
  NetworkError
6
6
  } from "./chunk-7QLSKOSU.js";
7
7
  import {
8
8
  getBaseUrl
9
- } from "./chunk-R6OYCUNK.js";
9
+ } from "./chunk-GPEGOGRJ.js";
10
10
  import {
11
11
  clientContextHeaders,
12
12
  getPackageVersion
13
- } from "./chunk-G4GLCLKK.js";
13
+ } from "./chunk-NQTHFF4W.js";
14
14
 
15
15
  // src/cli/net.ts
16
16
  import { createRequire } from "module";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  NOTIFICATION_MATCHED_TYPES,
3
3
  POSTTOOLUSE_MIRRORED_TOOLS
4
- } from "./chunk-EUGNVLMG.js";
4
+ } from "./chunk-EPCXUP3P.js";
5
5
  import {
6
6
  isProtectedByScope,
7
7
  registerHookEntry
8
- } from "./chunk-MZBRL5H5.js";
8
+ } from "./chunk-A2A2YTMG.js";
9
9
  import {
10
10
  CLAUDE_PRETOOLUSE_MATCHER,
11
11
  HOOK_BUDGETS,
12
12
  HOOK_LOCATOR_BINARY
13
- } from "./chunk-G4GLCLKK.js";
13
+ } from "./chunk-NQTHFF4W.js";
14
14
 
15
15
  // src/gemini-config.ts
16
16
  var GEMINI_HOOK_BINARY = "pushary-gemini-hook";
@@ -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-3EVPNIBE.js";
6
6
  import {
7
7
  CODEX_HOOK_EVENTS,
8
8
  hasCodexHooks,
9
9
  holdBudgetOf
10
- } from "./chunk-MZBRL5H5.js";
10
+ } from "./chunk-A2A2YTMG.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-NQTHFF4W.js";
16
16
 
17
17
  // src/diagnostics/wiring.ts
18
18
  var record = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : null;