@pushary/agent-hooks 1.8.1 → 1.8.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.
- package/CHANGELOG.md +13 -0
- package/dist/bin/pushary-bell-hook.js +12 -11
- package/dist/bin/pushary-bell.js +2 -2
- package/dist/bin/pushary-claude.js +16 -15
- package/dist/bin/pushary-clean.js +19 -18
- package/dist/bin/pushary-codex-bridge.js +14 -12
- package/dist/bin/pushary-codex-hook.js +19 -18
- package/dist/bin/pushary-codex.js +8 -8
- package/dist/bin/pushary-connect.js +7 -7
- package/dist/bin/pushary-daemon.js +92 -25
- package/dist/bin/pushary-disconnect.js +12 -11
- package/dist/bin/pushary-doctor.js +24 -21
- package/dist/bin/pushary-elicitation-hook.js +15 -14
- package/dist/bin/pushary-gemini-bridge.js +9 -6
- package/dist/bin/pushary-gemini-hook.js +17 -16
- package/dist/bin/pushary-hook.js +20 -19
- package/dist/bin/pushary-login.js +5 -5
- package/dist/bin/pushary-logout.js +1 -1
- package/dist/bin/pushary-mcp.js +6 -6
- package/dist/bin/pushary-mode.js +5 -5
- package/dist/bin/pushary-notification-hook.js +18 -17
- package/dist/bin/pushary-opencode-hook.js +16 -15
- package/dist/bin/pushary-permission-denied-hook.js +20 -19
- package/dist/bin/pushary-permission-hook.js +20 -19
- package/dist/bin/pushary-post-hook.js +18 -17
- package/dist/bin/pushary-prompt-hook.js +18 -17
- package/dist/bin/pushary-session-end-hook.js +18 -17
- package/dist/bin/pushary-session-start-hook.js +22 -21
- package/dist/bin/pushary-setup.js +37 -93
- package/dist/bin/pushary-status.js +11 -9
- package/dist/bin/pushary-stop-hook.js +18 -17
- package/dist/bin/pushary-stopfailure-hook.js +18 -17
- package/dist/bin/pushary-transcript-register.js +9 -8
- package/dist/bin/pushary-upgrade.js +219 -141
- package/dist/bin/pushary-wait.js +5 -5
- package/dist/bin/pushary.js +3 -3
- package/dist/{chunk-W2LJ4O3A.js → chunk-27A7L4DA.js} +1 -1
- package/dist/{chunk-I4HKMUZQ.js → chunk-34EQOFMH.js} +2 -2
- package/dist/{chunk-2SLCHCVN.js → chunk-4CW5EAOI.js} +1 -1
- package/dist/{chunk-F6NTWZZC.js → chunk-4DYHBXX4.js} +5 -5
- package/dist/{chunk-INSMZNS7.js → chunk-4SJIPHR3.js} +1 -1
- package/dist/chunk-6ICPEJY5.js +20 -0
- package/dist/{chunk-ZJYJAD52.js → chunk-6SS74UHS.js} +1 -1
- package/dist/{chunk-DVW2MYCM.js → chunk-6UDK5TY6.js} +1 -1
- package/dist/{chunk-MMVCI6DT.js → chunk-AKCE6ZRF.js} +3 -3
- package/dist/{chunk-HBWC3JVZ.js → chunk-APURTMSW.js} +2 -2
- package/dist/{chunk-QB6QYZ6B.js → chunk-CTNLP4A5.js} +4 -4
- package/dist/{chunk-GH6KGWMC.js → chunk-CXYKQAL2.js} +11 -9
- package/dist/{chunk-4A3UQERT.js → chunk-DMU5E6HJ.js} +1 -1
- package/dist/{chunk-FLQPM2GQ.js → chunk-E5JGQGLD.js} +2 -2
- package/dist/{chunk-JRQRNNGA.js → chunk-EJXEHNB5.js} +2 -2
- package/dist/{chunk-5DGNEUXK.js → chunk-FBTUF2PH.js} +1 -1
- package/dist/{chunk-EIGJYCOE.js → chunk-IEXWWAJY.js} +2 -2
- package/dist/{chunk-HQRCVEI2.js → chunk-MSMKCO4Y.js} +6 -6
- package/dist/{chunk-TKQ6LZQZ.js → chunk-OLYTGVCC.js} +5 -4
- package/dist/{chunk-ASWRMBOM.js → chunk-RIVNNBEK.js} +2 -1
- package/dist/{chunk-6TK4IY3A.js → chunk-SD6OLZJX.js} +3 -3
- package/dist/chunk-SOUJG6UY.js +198 -0
- package/dist/{chunk-KB2FTO4O.js → chunk-UXKXGRKG.js} +2 -2
- package/dist/{chunk-T55H6YEP.js → chunk-VF3X4MDB.js} +1 -1
- package/dist/{chunk-64H5IZZD.js → chunk-VI55VXDH.js} +1 -1
- package/dist/{chunk-NHCUXTEM.js → chunk-VUP5BMOD.js} +1 -1
- package/dist/{chunk-HOEB6AKG.js → chunk-XH7UNEHO.js} +1 -1
- package/dist/{chunk-LK2S5XIV.js → chunk-XNJ4MQF3.js} +2 -2
- package/dist/{chunk-HTEGMMT3.js → chunk-YLJ26RR2.js} +5 -18
- package/dist/{chunk-OCVVSRDA.js → chunk-YOYSXLUB.js} +2 -2
- package/dist/{chunk-GBNQXYN4.js → chunk-ZOKXZ3AS.js} +2 -2
- package/dist/{chunk-UPLV5AJF.js → chunk-ZR7LIQKO.js} +57 -5
- package/dist/{reapply-ICGTBHVE.js → reapply-DYOQAVUP.js} +8 -7
- package/dist/src/index.js +14 -13
- package/package.json +1 -1
- package/dist/chunk-VZMIHERK.js +0 -59
|
@@ -5,18 +5,19 @@ import {
|
|
|
5
5
|
import {
|
|
6
6
|
ensureCodexTrustAfterReapply,
|
|
7
7
|
reapplyAllAgents
|
|
8
|
-
} from "../chunk-
|
|
9
|
-
import "../chunk-
|
|
10
|
-
import "../chunk-W2LJ4O3A.js";
|
|
8
|
+
} from "../chunk-CXYKQAL2.js";
|
|
9
|
+
import "../chunk-27A7L4DA.js";
|
|
11
10
|
import {
|
|
12
11
|
waitForMachineReadiness
|
|
13
|
-
} from "../chunk-
|
|
14
|
-
import "../chunk-
|
|
12
|
+
} from "../chunk-OLYTGVCC.js";
|
|
13
|
+
import "../chunk-EJXEHNB5.js";
|
|
15
14
|
import {
|
|
16
15
|
detectProviderLiveCapabilities,
|
|
16
|
+
expectedLaunchCapabilities,
|
|
17
17
|
hasSpawnProvider,
|
|
18
18
|
resolveControlPolicy
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-SOUJG6UY.js";
|
|
20
|
+
import "../chunk-RIVNNBEK.js";
|
|
20
21
|
import {
|
|
21
22
|
AUTO_UPDATE_DISABLE_ENV,
|
|
22
23
|
describeAutoUpdateCheck,
|
|
@@ -27,8 +28,8 @@ import {
|
|
|
27
28
|
readAutoUpdateState,
|
|
28
29
|
updateAutoUpdateState,
|
|
29
30
|
upgradeEntryFor
|
|
30
|
-
} from "../chunk-
|
|
31
|
-
import "../chunk-
|
|
31
|
+
} from "../chunk-VI55VXDH.js";
|
|
32
|
+
import "../chunk-YOYSXLUB.js";
|
|
32
33
|
import {
|
|
33
34
|
daemonHasRemoteProof,
|
|
34
35
|
daemonServiceManagerAvailable,
|
|
@@ -39,9 +40,10 @@ import {
|
|
|
39
40
|
replaceDaemonService,
|
|
40
41
|
stopDaemonService,
|
|
41
42
|
waitForDaemonRemoteProof
|
|
42
|
-
} from "../chunk-
|
|
43
|
-
import "../chunk-
|
|
43
|
+
} from "../chunk-IEXWWAJY.js";
|
|
44
|
+
import "../chunk-YLJ26RR2.js";
|
|
44
45
|
import "../chunk-XHKBHWLX.js";
|
|
46
|
+
import "../chunk-6ICPEJY5.js";
|
|
45
47
|
import "../chunk-VFFHQC7W.js";
|
|
46
48
|
import "../chunk-POFBE6ZY.js";
|
|
47
49
|
import {
|
|
@@ -50,7 +52,7 @@ import {
|
|
|
50
52
|
import {
|
|
51
53
|
readControlMode
|
|
52
54
|
} from "../chunk-TJMAXQ5Q.js";
|
|
53
|
-
import "../chunk-
|
|
55
|
+
import "../chunk-DMU5E6HJ.js";
|
|
54
56
|
import {
|
|
55
57
|
EXIT
|
|
56
58
|
} from "../chunk-KZERVKTD.js";
|
|
@@ -71,8 +73,10 @@ import {
|
|
|
71
73
|
readGlobalCliInstallAt,
|
|
72
74
|
readGlobalPrefix,
|
|
73
75
|
vscodePluginDir
|
|
74
|
-
} from "../chunk-
|
|
75
|
-
import
|
|
76
|
+
} from "../chunk-ZR7LIQKO.js";
|
|
77
|
+
import {
|
|
78
|
+
writeJsonAtomic
|
|
79
|
+
} from "../chunk-T7E75EKA.js";
|
|
76
80
|
import {
|
|
77
81
|
getApiKey
|
|
78
82
|
} from "../chunk-ON5JW2HP.js";
|
|
@@ -83,6 +87,7 @@ import {
|
|
|
83
87
|
CANONICAL_PACKAGE,
|
|
84
88
|
LEGACY_PACKAGE,
|
|
85
89
|
commandsPackage,
|
|
90
|
+
getPackageVersion,
|
|
86
91
|
globalUpgradeEntry,
|
|
87
92
|
isNewerVersion,
|
|
88
93
|
isReleaseVersion,
|
|
@@ -91,66 +96,38 @@ import {
|
|
|
91
96
|
packageVersionAt
|
|
92
97
|
} from "../chunk-5YY3IJT4.js";
|
|
93
98
|
|
|
94
|
-
//
|
|
95
|
-
import {
|
|
96
|
-
import {
|
|
97
|
-
import {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
var FINISH_UPGRADE_FLAG = "--finish-upgrade";
|
|
108
|
-
var LOCK_STALE_MS = 10 * 60 * 1e3;
|
|
109
|
-
var INSTALL_TIMEOUT_MS = 12e4;
|
|
99
|
+
// src/upgrade-lock.ts
|
|
100
|
+
import { fork } from "child_process";
|
|
101
|
+
import { createHash } from "crypto";
|
|
102
|
+
import { existsSync, mkdirSync, readFileSync, realpathSync, unlinkSync } from "fs";
|
|
103
|
+
import { createServer, Server } from "net";
|
|
104
|
+
import { basename, dirname, join } from "path";
|
|
105
|
+
var LOCK_HOST = "127.0.0.1";
|
|
106
|
+
var LOCK_PORT_START = 49152;
|
|
107
|
+
var LOCK_PORT_COUNT = 16384;
|
|
108
|
+
var INHERITED_LOCK_ENV = "PUSHARY_UPGRADE_LOCK";
|
|
109
|
+
var LOCK_READY = "pushary-upgrade-lock-ready";
|
|
110
|
+
var LOCK_HANDLE = "pushary-upgrade-lock-handle";
|
|
111
|
+
var HANDOFF_TIMEOUT_MS = 1e4;
|
|
110
112
|
var FINISH_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
111
|
-
var
|
|
112
|
-
var
|
|
113
|
-
var
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
writeSync(handle, `${JSON.stringify({ pid: process.pid, at: new Date(now).toISOString() })}
|
|
120
|
-
`);
|
|
121
|
-
} finally {
|
|
122
|
-
closeSync(handle);
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
var tryCreateLock = (lockPath, now) => {
|
|
113
|
+
var KERNEL_LOCK_FORMAT = "kernel-v1";
|
|
114
|
+
var heldLocks = /* @__PURE__ */ new Map();
|
|
115
|
+
var canonicalLockPath = (path) => {
|
|
116
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
117
|
+
return join(realpathSync(dirname(path)), basename(path));
|
|
118
|
+
};
|
|
119
|
+
var lockPort = (path) => LOCK_PORT_START + createHash("sha256").update(path).digest().readUInt32BE(0) % LOCK_PORT_COUNT;
|
|
120
|
+
var readLockRecord = (path) => {
|
|
126
121
|
try {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
};
|
|
134
|
-
var isStaleLock = (lockPath, now) => {
|
|
135
|
-
const modifiedAt = statSync(lockPath, { throwIfNoEntry: false })?.mtimeMs;
|
|
136
|
-
return modifiedAt !== void 0 && now - modifiedAt > LOCK_STALE_MS;
|
|
137
|
-
};
|
|
138
|
-
var takeOverLock = (lockPath, now) => {
|
|
139
|
-
try {
|
|
140
|
-
unlinkSync(lockPath);
|
|
122
|
+
const value = JSON.parse(readFileSync(path, "utf8"));
|
|
123
|
+
const pid = value && typeof value === "object" && "pid" in value ? value.pid : void 0;
|
|
124
|
+
return {
|
|
125
|
+
pid: typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : void 0,
|
|
126
|
+
installationPending: value !== null && typeof value === "object" && "installationPending" in value && value.installationPending === true,
|
|
127
|
+
usesKernelLock: value !== null && typeof value === "object" && "format" in value && value.format === KERNEL_LOCK_FORMAT
|
|
128
|
+
};
|
|
141
129
|
} catch {
|
|
142
|
-
return
|
|
143
|
-
}
|
|
144
|
-
return tryCreateLock(lockPath, now);
|
|
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;
|
|
130
|
+
return { pid: void 0, usesKernelLock: false, installationPending: false };
|
|
154
131
|
}
|
|
155
132
|
};
|
|
156
133
|
var isProcessAlive = (pid) => {
|
|
@@ -158,54 +135,138 @@ var isProcessAlive = (pid) => {
|
|
|
158
135
|
process.kill(pid, 0);
|
|
159
136
|
return true;
|
|
160
137
|
} catch (error) {
|
|
161
|
-
return error instanceof Error && "code" in error && error.code === "
|
|
138
|
+
return !(error instanceof Error && "code" in error && error.code === "ESRCH");
|
|
162
139
|
}
|
|
163
140
|
};
|
|
164
|
-
var
|
|
165
|
-
|
|
166
|
-
return {
|
|
167
|
-
holderPid,
|
|
168
|
-
holderAlive: holderPid !== void 0 && isAlive(holderPid),
|
|
169
|
-
stale: isStaleLock(lockPath, now)
|
|
170
|
-
};
|
|
141
|
+
var rejectConnection = (socket) => {
|
|
142
|
+
socket.destroy();
|
|
171
143
|
};
|
|
172
|
-
var
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
144
|
+
var inheritLock = (path) => new Promise((resolve) => {
|
|
145
|
+
const done = (claim) => {
|
|
146
|
+
clearTimeout(timer);
|
|
147
|
+
process.off("message", receive);
|
|
148
|
+
process.off("disconnect", disconnected);
|
|
149
|
+
resolve(claim);
|
|
150
|
+
};
|
|
151
|
+
const disconnected = () => done({ kind: "unavailable", reason: "Upgrade parent disconnected before transferring its lock" });
|
|
152
|
+
const receive = (message, handle) => {
|
|
153
|
+
if (message !== LOCK_HANDLE || !(handle instanceof Server)) return;
|
|
154
|
+
const address = handle.address();
|
|
155
|
+
if (address === null || typeof address === "string" || address.port !== lockPort(path) || address.address !== LOCK_HOST) {
|
|
156
|
+
handle.close();
|
|
157
|
+
done({ kind: "unavailable", reason: "Invalid inherited upgrade lock" });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
handle.on("connection", rejectConnection);
|
|
161
|
+
heldLocks.set(path, handle);
|
|
162
|
+
done({ kind: "inherited" });
|
|
163
|
+
process.disconnect?.();
|
|
164
|
+
};
|
|
165
|
+
const timer = setTimeout(() => done({ kind: "unavailable", reason: "Upgrade lock handoff timed out" }), HANDOFF_TIMEOUT_MS);
|
|
166
|
+
process.on("message", receive);
|
|
167
|
+
process.once("disconnect", disconnected);
|
|
168
|
+
if (!process.send || !process.connected) return disconnected();
|
|
169
|
+
process.send(LOCK_READY, (error) => {
|
|
170
|
+
if (error) disconnected();
|
|
171
|
+
});
|
|
172
|
+
});
|
|
173
|
+
var claimUpgradeLock = async (request = {}) => {
|
|
174
|
+
let server;
|
|
179
175
|
try {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
const path = canonicalLockPath(request.lockPath ?? autoUpdateLock());
|
|
177
|
+
const inheritedPath = process.env[INHERITED_LOCK_ENV];
|
|
178
|
+
delete process.env[INHERITED_LOCK_ENV];
|
|
179
|
+
if (inheritedPath === path && !heldLocks.has(path)) return await inheritLock(path);
|
|
180
|
+
server = createServer(rejectConnection);
|
|
181
|
+
const listener = server;
|
|
182
|
+
await new Promise((resolve, reject) => {
|
|
183
|
+
listener.once("error", reject);
|
|
184
|
+
listener.listen({ host: LOCK_HOST, port: lockPort(path), exclusive: true }, resolve);
|
|
185
|
+
});
|
|
186
|
+
const record = readLockRecord(path);
|
|
187
|
+
if (record.installationPending) {
|
|
188
|
+
server.close();
|
|
189
|
+
return { kind: "unavailable", reason: `An earlier installation did not finish safely. Stop its npm processes (or restart the computer), then remove ${path} and retry the upgrade.` };
|
|
190
|
+
}
|
|
191
|
+
if (existsSync(path) && !record.usesKernelLock && (record.pid === void 0 || (request.isAlive ?? isProcessAlive)(record.pid))) {
|
|
192
|
+
server.close();
|
|
193
|
+
return { kind: "held", holderPid: record.pid };
|
|
194
|
+
}
|
|
195
|
+
writeJsonAtomic(path, { pid: process.pid, format: KERNEL_LOCK_FORMAT }, 384);
|
|
196
|
+
heldLocks.set(path, server);
|
|
197
|
+
return { kind: "acquired" };
|
|
198
|
+
} catch (error) {
|
|
199
|
+
server?.close();
|
|
200
|
+
if (error instanceof Error && "code" in error && error.code === "EADDRINUSE") {
|
|
201
|
+
return { kind: "held", holderPid: readLockRecord(request.lockPath ?? autoUpdateLock()).pid };
|
|
202
|
+
}
|
|
203
|
+
return { kind: "unavailable", reason: npmErrorMessage(error) };
|
|
183
204
|
}
|
|
184
205
|
};
|
|
185
|
-
var
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
return
|
|
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 = {}) => {
|
|
206
|
+
var releaseAutoUpdateLock = (lockPath) => {
|
|
207
|
+
const path = canonicalLockPath(lockPath);
|
|
208
|
+
const server = heldLocks.get(path);
|
|
209
|
+
if (!server) return;
|
|
210
|
+
heldLocks.delete(path);
|
|
201
211
|
try {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
212
|
+
const record = readLockRecord(path);
|
|
213
|
+
if (record.pid === process.pid && !record.installationPending) unlinkSync(path);
|
|
214
|
+
} finally {
|
|
215
|
+
server.close();
|
|
205
216
|
}
|
|
206
217
|
};
|
|
218
|
+
var finishWithUpgradeLock = (request) => new Promise((resolve, reject) => {
|
|
219
|
+
const path = canonicalLockPath(request.lockPath ?? autoUpdateLock());
|
|
220
|
+
const server = heldLocks.get(path);
|
|
221
|
+
if (!server) return reject(new Error("Cannot finish an upgrade without its lock"));
|
|
222
|
+
const child = fork(request.entry, [...request.args], {
|
|
223
|
+
execArgv: [],
|
|
224
|
+
stdio: request.stdio ?? ["inherit", "inherit", "inherit", "ipc"],
|
|
225
|
+
env: { ...process.env, ...request.env, [INHERITED_LOCK_ENV]: path }
|
|
226
|
+
});
|
|
227
|
+
const timer = setTimeout(() => child.kill("SIGKILL"), FINISH_TIMEOUT_MS);
|
|
228
|
+
child.on("message", (message) => {
|
|
229
|
+
if (message === LOCK_READY) child.send(LOCK_HANDLE, server, (error) => {
|
|
230
|
+
if (error) child.kill();
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
child.once("error", (error) => {
|
|
234
|
+
clearTimeout(timer);
|
|
235
|
+
reject(error);
|
|
236
|
+
});
|
|
237
|
+
child.once("exit", (code, signal) => {
|
|
238
|
+
clearTimeout(timer);
|
|
239
|
+
if (code === 0) resolve();
|
|
240
|
+
else reject(new Error(`Upgrade finish exited with ${signal ?? code}`));
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
var installWithUpgradeLock = (request, lockPath = autoUpdateLock(), runNpm) => {
|
|
244
|
+
const path = canonicalLockPath(lockPath);
|
|
245
|
+
if (!heldLocks.has(path)) throw new Error("Cannot install an upgrade without its lock");
|
|
246
|
+
writeJsonAtomic(path, { pid: process.pid, format: KERNEL_LOCK_FORMAT, installationPending: true }, 384);
|
|
247
|
+
installPackageGlobally(request, runNpm);
|
|
248
|
+
writeJsonAtomic(path, { pid: process.pid, format: KERNEL_LOCK_FORMAT }, 384);
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// bin/pushary-upgrade.ts
|
|
252
|
+
import { existsSync as existsSync3 } from "fs";
|
|
253
|
+
import { homedir } from "os";
|
|
254
|
+
import { join as join2 } from "path";
|
|
255
|
+
|
|
256
|
+
// src/global-upgrade.ts
|
|
257
|
+
import { existsSync as existsSync2 } from "fs";
|
|
258
|
+
|
|
259
|
+
// src/auto-update-run.ts
|
|
260
|
+
import { closeSync, mkdirSync as mkdirSync2, openSync, statSync, writeSync } from "fs";
|
|
261
|
+
import { dirname as dirname2 } from "path";
|
|
262
|
+
var FINISH_UPGRADE_FLAG = "--finish-upgrade";
|
|
263
|
+
var INSTALL_TIMEOUT_MS = 12e4;
|
|
264
|
+
var LOG_LIMIT_BYTES = 256 * 1024;
|
|
265
|
+
var UNREADABLE_INSTALLED_VERSION = "could not read the installed version";
|
|
266
|
+
var UNREACHABLE_REGISTRY = "could not read the latest version from the npm registry";
|
|
267
|
+
var MANUAL_UPGRADE_COMMAND = `${NPX_LATEST_COMMAND} upgrade`;
|
|
207
268
|
var openAutoUpdateLog = (logPath) => {
|
|
208
|
-
|
|
269
|
+
mkdirSync2(dirname2(logPath), { recursive: true });
|
|
209
270
|
const size = statSync(logPath, { throwIfNoEntry: false })?.size ?? 0;
|
|
210
271
|
return openSync(logPath, size > LOG_LIMIT_BYTES ? "w" : "a");
|
|
211
272
|
};
|
|
@@ -222,13 +283,15 @@ var appendAutoUpdateLog = (logPath, line) => {
|
|
|
222
283
|
return;
|
|
223
284
|
}
|
|
224
285
|
};
|
|
225
|
-
var finishInNewInstall = (request) => {
|
|
286
|
+
var finishInNewInstall = async (request) => {
|
|
226
287
|
const handle = openAutoUpdateLog(request.logPath);
|
|
227
288
|
try {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
289
|
+
await finishWithUpgradeLock({
|
|
290
|
+
entry: request.entry,
|
|
291
|
+
args: [FINISH_UPGRADE_FLAG],
|
|
292
|
+
lockPath: request.lockPath,
|
|
293
|
+
stdio: ["ignore", handle, handle, "ipc"],
|
|
294
|
+
env: { npm_config_prefix: request.prefix }
|
|
232
295
|
});
|
|
233
296
|
} finally {
|
|
234
297
|
closeSync(handle);
|
|
@@ -236,11 +299,11 @@ var finishInNewInstall = (request) => {
|
|
|
236
299
|
};
|
|
237
300
|
var incompleteFinishDetail = (logPath) => `installed, but refreshing the agent configs did not finish cleanly; see ${logPath}`;
|
|
238
301
|
var newMajorDetail = (latest) => `${latest} is a new major version; run ${MANUAL_UPGRADE_COMMAND}`;
|
|
239
|
-
var finishInstalledUpgrade = (context, from, to) => {
|
|
302
|
+
var finishInstalledUpgrade = async (context, from, to) => {
|
|
240
303
|
const pending = { result: "finish_pending", from, to, detail: incompleteFinishDetail(context.logPath) };
|
|
241
304
|
recordAutoUpdateCheck(context.statePath, pending, new Date(context.now()).toISOString());
|
|
242
305
|
try {
|
|
243
|
-
context.finish({ entry: upgradeEntryFor(context.location), prefix: context.location.prefix, logPath: context.logPath });
|
|
306
|
+
await context.finish({ lockPath: context.lockPath, entry: upgradeEntryFor(context.location), prefix: context.location.prefix, logPath: context.logPath });
|
|
244
307
|
return { result: "updated", from, to };
|
|
245
308
|
} catch {
|
|
246
309
|
return pending;
|
|
@@ -263,14 +326,13 @@ var checkAndInstall = async (context) => {
|
|
|
263
326
|
}
|
|
264
327
|
appendAutoUpdateLog(context.logPath, `${new Date(context.now()).toISOString()} installing ${context.location.packageName}@${latest} into ${context.location.prefix}`);
|
|
265
328
|
try {
|
|
266
|
-
|
|
329
|
+
installWithUpgradeLock({
|
|
267
330
|
packageName: context.location.packageName,
|
|
268
331
|
version: latest,
|
|
269
332
|
prefix: context.location.prefix,
|
|
270
333
|
timeoutMs: INSTALL_TIMEOUT_MS
|
|
271
|
-
}, context.runNpm);
|
|
334
|
+
}, context.lockPath, context.runNpm);
|
|
272
335
|
} catch (error) {
|
|
273
|
-
if (pendingFinish) return finishInstalledUpgrade(context, previous.from, installed);
|
|
274
336
|
return { result: "failed", from: installed, to: latest, detail: npmErrorMessage(error) };
|
|
275
337
|
}
|
|
276
338
|
return finishInstalledUpgrade(context, installed, latest);
|
|
@@ -292,9 +354,17 @@ var runAutoUpdate = async (run = {}) => {
|
|
|
292
354
|
const now = run.now ?? Date.now;
|
|
293
355
|
const lockPath = run.lockPath ?? autoUpdateLock();
|
|
294
356
|
const logPath = run.logPath ?? autoUpdateLog();
|
|
295
|
-
|
|
357
|
+
const claim = await claimUpgradeLock({ lockPath });
|
|
358
|
+
if (claim.kind === "unavailable") {
|
|
359
|
+
const at = new Date(now()).toISOString();
|
|
360
|
+
const state = recordAutoUpdateCheck(run.statePath ?? autoUpdateState(), { result: "failed", detail: claim.reason }, at);
|
|
361
|
+
appendAutoUpdateLog(logPath, `${at} ${describeAutoUpdateCheck(state)}`);
|
|
362
|
+
return { kind: "recorded", state };
|
|
363
|
+
}
|
|
364
|
+
if (claim.kind !== "acquired") return { kind: "locked" };
|
|
296
365
|
try {
|
|
297
366
|
const check = await checkAndInstall({
|
|
367
|
+
lockPath,
|
|
298
368
|
packageRoot,
|
|
299
369
|
statePath: run.statePath ?? autoUpdateState(),
|
|
300
370
|
location,
|
|
@@ -325,14 +395,12 @@ var readGlobalUpgradeSubject = (platform = process.platform) => {
|
|
|
325
395
|
const prefix = readGlobalPrefix();
|
|
326
396
|
return globalUpgradeSubject(prefix, prefix === void 0 ? { kind: "unavailable" } : readGlobalCliInstallAt(prefix, platform));
|
|
327
397
|
};
|
|
328
|
-
var finishWithThisNode = (entry) => {
|
|
329
|
-
|
|
330
|
-
};
|
|
331
|
-
var finishGlobalUpgrade = (subject, platform = process.platform, runFinish = finishWithThisNode) => {
|
|
398
|
+
var finishWithThisNode = (entry) => finishWithUpgradeLock({ entry, args: [FINISH_UPGRADE_FLAG] });
|
|
399
|
+
var finishGlobalUpgrade = async (subject, platform = process.platform, runFinish = finishWithThisNode) => {
|
|
332
400
|
const entry = globalUpgradeEntry(subject.prefix, subject.name, platform);
|
|
333
|
-
if (!
|
|
401
|
+
if (!existsSync2(entry)) return { kind: "entry_missing", entry };
|
|
334
402
|
try {
|
|
335
|
-
runFinish(entry);
|
|
403
|
+
await runFinish(entry);
|
|
336
404
|
return { kind: "finished" };
|
|
337
405
|
} catch {
|
|
338
406
|
return { kind: "failed" };
|
|
@@ -340,22 +408,30 @@ var finishGlobalUpgrade = (subject, platform = process.platform, runFinish = fin
|
|
|
340
408
|
};
|
|
341
409
|
var describeHeldUpgradeLock = (holderPid) => `Another Pushary upgrade is already running${holderPid === void 0 ? "" : ` (pid ${holderPid})`}. Try again when it has finished.`;
|
|
342
410
|
var withUpgradeLock = async (run, request = {}) => {
|
|
343
|
-
const claim = claimUpgradeLock(request);
|
|
411
|
+
const claim = await claimUpgradeLock(request);
|
|
412
|
+
if (claim.kind === "unavailable") return { kind: "refused", exitCode: EXIT.FAILED, message: `Could not lock the Pushary upgrade: ${claim.reason}` };
|
|
344
413
|
if (claim.kind === "held") return { kind: "refused", exitCode: EXIT.FAILED, message: describeHeldUpgradeLock(claim.holderPid) };
|
|
345
414
|
try {
|
|
346
415
|
await run();
|
|
347
416
|
} finally {
|
|
348
|
-
|
|
417
|
+
releaseAutoUpdateLock(request.lockPath ?? autoUpdateLock());
|
|
349
418
|
}
|
|
350
419
|
return { kind: "ran" };
|
|
351
420
|
};
|
|
421
|
+
var finishUpgradeWithLock = async (run, request) => {
|
|
422
|
+
const outcome = await withUpgradeLock(run, request);
|
|
423
|
+
if (outcome.kind === "refused") {
|
|
424
|
+
updateAutoUpdateState(request.statePath, { lastResult: "finish_pending", to: request.installedVersion, detail: outcome.message });
|
|
425
|
+
}
|
|
426
|
+
return outcome;
|
|
427
|
+
};
|
|
352
428
|
var describeUpgradeStart = (subject, latest) => `Upgrading ${subject.name} ${subject.version} -> ${latest ?? "latest"}`;
|
|
353
429
|
var upgradeInstalledPackage = async (subject, effects) => {
|
|
354
430
|
const pendingFinish = effects.hasPendingFinish(subject.version);
|
|
355
431
|
const latest = await effects.fetchLatest(subject.name);
|
|
356
432
|
const newerPublished = latest !== void 0 && isNewerVersion(latest, subject.version);
|
|
357
433
|
if (pendingFinish && !newerPublished) {
|
|
358
|
-
const finish = effects.finish(subject);
|
|
434
|
+
const finish = await effects.finish(subject);
|
|
359
435
|
if (finish.kind !== "finished") return { kind: "pending_finish_failed", finish };
|
|
360
436
|
effects.recordFinished();
|
|
361
437
|
}
|
|
@@ -366,7 +442,7 @@ var upgradeInstalledPackage = async (subject, effects) => {
|
|
|
366
442
|
} catch (error) {
|
|
367
443
|
return { kind: "install_failed", detail: npmErrorMessage(error) };
|
|
368
444
|
}
|
|
369
|
-
return { kind: "installed", finish: effects.finish(subject) };
|
|
445
|
+
return { kind: "installed", finish: await effects.finish(subject) };
|
|
370
446
|
};
|
|
371
447
|
|
|
372
448
|
// bin/pushary-upgrade.ts
|
|
@@ -376,32 +452,32 @@ var detectInstallModes = () => {
|
|
|
376
452
|
{
|
|
377
453
|
label: "Cursor plugin",
|
|
378
454
|
upgrade: "updates itself through Cursor",
|
|
379
|
-
present:
|
|
455
|
+
present: existsSync3(cursorPluginDir())
|
|
380
456
|
},
|
|
381
457
|
{
|
|
382
458
|
label: "VS Code plugin",
|
|
383
459
|
upgrade: `${NPX_LATEST_COMMAND} setup --agents vscode`,
|
|
384
|
-
present:
|
|
460
|
+
present: existsSync3(vscodePluginDir())
|
|
385
461
|
},
|
|
386
462
|
{
|
|
387
463
|
label: "Codex config",
|
|
388
464
|
upgrade: `${NPX_LATEST_COMMAND} setup --agents codex`,
|
|
389
|
-
present:
|
|
465
|
+
present: existsSync3(codexConfigToml())
|
|
390
466
|
},
|
|
391
467
|
{
|
|
392
468
|
label: "Claude Code config",
|
|
393
469
|
upgrade: `${NPX_LATEST_COMMAND} setup --agents claude_code`,
|
|
394
|
-
present:
|
|
470
|
+
present: existsSync3(claudeJson())
|
|
395
471
|
},
|
|
396
472
|
{
|
|
397
473
|
label: "Gemini config",
|
|
398
474
|
upgrade: `${NPX_LATEST_COMMAND} setup --agents gemini_cli`,
|
|
399
|
-
present:
|
|
475
|
+
present: existsSync3(geminiSettings())
|
|
400
476
|
},
|
|
401
477
|
{
|
|
402
478
|
label: "Hermes plugin (pip)",
|
|
403
479
|
upgrade: `${NPX_LATEST_COMMAND} setup --agents hermes`,
|
|
404
|
-
present:
|
|
480
|
+
present: existsSync3(join2(homedir(), ".hermes"))
|
|
405
481
|
}
|
|
406
482
|
];
|
|
407
483
|
return candidates.filter((candidate) => candidate.present).map(({ label, upgrade }) => ({ label, upgrade }));
|
|
@@ -444,7 +520,7 @@ var finishUpgrade = async () => {
|
|
|
444
520
|
const daemon = service.kind === "ok" ? await ensureDaemonRunning({ spawnDaemon: () => {
|
|
445
521
|
} }) : null;
|
|
446
522
|
const localProof = daemon?.kind === "running" || daemon?.kind === "started" ? await waitForDaemonRemoteProof() : null;
|
|
447
|
-
const serverProof = localProof && daemonHasRemoteProof(localProof) ? await waitForMachineReadiness(apiKey,
|
|
523
|
+
const serverProof = localProof && daemonHasRemoteProof(localProof) ? await waitForMachineReadiness(apiKey, expectedLaunchCapabilities(configuredControlProviders)) : null;
|
|
448
524
|
daemonReady = service.kind === "ok" && localProof !== null && daemonHasRemoteProof(localProof) && (serverProof?.kind === "ready" || serverProof?.kind === "unsupported");
|
|
449
525
|
}
|
|
450
526
|
} else if (controlMode === "on" && controlPolicy === "unsupported") {
|
|
@@ -551,7 +627,7 @@ var upgradeSubject = async (subject) => {
|
|
|
551
627
|
updateAutoUpdateState(autoUpdateState(), { lastResult: "updated", detail: void 0, announced: false });
|
|
552
628
|
},
|
|
553
629
|
announce: (line) => console.log(line),
|
|
554
|
-
install: (packageName) =>
|
|
630
|
+
install: (packageName) => installWithUpgradeLock({ packageName, version: LATEST_TAG, timeoutMs: 12e4 }),
|
|
555
631
|
finish: (installedSubject) => finishGlobalUpgrade(installedSubject)
|
|
556
632
|
});
|
|
557
633
|
reportGlobalUpgrade(outcome);
|
|
@@ -569,15 +645,17 @@ var upgradeGlobalInstall = async () => {
|
|
|
569
645
|
}
|
|
570
646
|
await upgradeSubject(subject);
|
|
571
647
|
};
|
|
572
|
-
var
|
|
573
|
-
const locked = await withUpgradeLock(run);
|
|
648
|
+
var reportUpgradeLock = (locked) => {
|
|
574
649
|
if (locked.kind === "ran") return;
|
|
575
650
|
console.error(locked.message);
|
|
576
651
|
process.exitCode = locked.exitCode;
|
|
577
652
|
};
|
|
578
653
|
var main = async () => {
|
|
579
654
|
if (process.argv.includes(FINISH_UPGRADE_FLAG)) {
|
|
580
|
-
await
|
|
655
|
+
reportUpgradeLock(await finishUpgradeWithLock(finishUpgrade, {
|
|
656
|
+
installedVersion: getPackageVersion(),
|
|
657
|
+
statePath: autoUpdateState()
|
|
658
|
+
}));
|
|
581
659
|
return;
|
|
582
660
|
}
|
|
583
661
|
const autoFlag = parseAutoUpdateFlag(process.argv.slice(2));
|
|
@@ -594,6 +672,6 @@ var main = async () => {
|
|
|
594
672
|
await runAutomaticUpdate();
|
|
595
673
|
return;
|
|
596
674
|
}
|
|
597
|
-
await
|
|
675
|
+
reportUpgradeLock(await withUpgradeLock(upgradeGlobalInstall));
|
|
598
676
|
};
|
|
599
677
|
main();
|
package/dist/bin/pushary-wait.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "../chunk-CVWG2N3Y.js";
|
|
5
5
|
import {
|
|
6
6
|
exitOnFailedResponse
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-VUP5BMOD.js";
|
|
8
8
|
import {
|
|
9
9
|
createIo
|
|
10
10
|
} from "../chunk-U4TMAANR.js";
|
|
@@ -14,16 +14,16 @@ import {
|
|
|
14
14
|
import {
|
|
15
15
|
rejectUnknownFlags
|
|
16
16
|
} from "../chunk-GMXKITVA.js";
|
|
17
|
-
import "../chunk-
|
|
18
|
-
import "../chunk-
|
|
19
|
-
import "../chunk-
|
|
17
|
+
import "../chunk-6UDK5TY6.js";
|
|
18
|
+
import "../chunk-4CW5EAOI.js";
|
|
19
|
+
import "../chunk-DMU5E6HJ.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-
|
|
26
|
+
import "../chunk-ZR7LIQKO.js";
|
|
27
27
|
import "../chunk-T7E75EKA.js";
|
|
28
28
|
import {
|
|
29
29
|
getApiKey,
|
package/dist/bin/pushary.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
installNetworkDefaults
|
|
4
|
-
} from "../chunk-
|
|
5
|
-
import "../chunk-
|
|
4
|
+
} from "../chunk-4CW5EAOI.js";
|
|
5
|
+
import "../chunk-DMU5E6HJ.js";
|
|
6
6
|
import "../chunk-7QLSKOSU.js";
|
|
7
7
|
import {
|
|
8
8
|
EXIT
|
|
9
9
|
} from "../chunk-KZERVKTD.js";
|
|
10
|
-
import "../chunk-
|
|
10
|
+
import "../chunk-ZR7LIQKO.js";
|
|
11
11
|
import "../chunk-T7E75EKA.js";
|
|
12
12
|
import "../chunk-ON5JW2HP.js";
|
|
13
13
|
import {
|