@phnx-labs/agents-cli 1.22.88 → 1.22.90
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 +159 -0
- package/dist/lib/accounts/migrate.js +99 -0
- package/dist/lib/answer-router.d.ts +8 -0
- package/dist/lib/answer-router.js +13 -1
- package/dist/lib/auth-mint.d.ts +22 -1
- package/dist/lib/auth-mint.js +85 -10
- package/dist/lib/daemon/attention-notify-service.d.ts +66 -0
- package/dist/lib/daemon/attention-notify-service.js +185 -0
- package/dist/lib/daemon/auth-sync-service.js +10 -0
- package/dist/lib/daemon/daemon.js +9 -0
- package/dist/lib/daemon/self-update-service.d.ts +9 -0
- package/dist/lib/daemon/self-update-service.js +51 -6
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/feed/answer.js +1 -1
- package/dist/lib/feed/attention.d.ts +2 -0
- package/dist/lib/feed/attention.js +0 -0
- package/dist/lib/fs-atomic.d.ts +7 -0
- package/dist/lib/fs-atomic.js +20 -0
- package/dist/lib/menubar/notify-desktop.d.ts +27 -0
- package/dist/lib/menubar/notify-desktop.js +11 -0
- package/dist/lib/run-notify.d.ts +4 -0
- package/dist/lib/run-notify.js +21 -2
- package/dist/lib/secrets-policy.d.ts +17 -0
- package/dist/lib/secrets-policy.js +14 -1
- package/dist/lib/self-update.d.ts +37 -11
- package/dist/lib/self-update.js +77 -20
- package/package.json +1 -1
|
@@ -104,18 +104,22 @@ export declare function resolveMultiInstallInventory(runningRoot: string, runnin
|
|
|
104
104
|
/**
|
|
105
105
|
* The on-disk package root of the copy that is currently running.
|
|
106
106
|
*
|
|
107
|
-
* For a plain JS install
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
107
|
+
* For a plain JS install, walk up from the CALLING module's directory to the
|
|
108
|
+
* directory whose package.json names this package. Never assume a fixed depth:
|
|
109
|
+
* `<__dirname>/..` is the root only for a module directly under `dist/`, and
|
|
110
|
+
* from `dist/lib/daemon/self-update-service.js` it answered `dist/lib`, which
|
|
111
|
+
* deriveGlobalPrefix rejected as "not an npm-managed install" on every daemon
|
|
112
|
+
* self-update tick (2026-09-07 fleet incident).
|
|
113
113
|
*
|
|
114
|
-
*
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
114
|
+
* Under the compiled standalone binary (shipped since 1.20.53) `__dirname` is
|
|
115
|
+
* Bun's embedded virtual FS, so walking up from it yields `/$bunfs` — a path
|
|
116
|
+
* that exists nowhere. That phantom value was reported as a second install by
|
|
117
|
+
* the multi-install check and rejected by deriveGlobalPrefix, so every
|
|
118
|
+
* self-upgrade from a compiled copy failed. The physical executable is
|
|
119
|
+
* `process.execPath`, which ships inside the package
|
|
120
|
+
* (`<packageRoot>/dist/bin/agents`); walk up from it instead. Either way a
|
|
121
|
+
* change to the dist layout surfaces as a clear throw here rather than a wrong
|
|
122
|
+
* prefix that npm would happily install into.
|
|
119
123
|
*/
|
|
120
124
|
export declare function resolveRunningPackageRoot(dirname: string, execPath?: string): string;
|
|
121
125
|
/**
|
|
@@ -175,8 +179,30 @@ export declare function installPackageIntoPrefix(spec: string, prefix: string, s
|
|
|
175
179
|
* alias shims afterwards via refreshAliasShims() rather than relying on the
|
|
176
180
|
* package's postinstall hook.
|
|
177
181
|
*
|
|
182
|
+
* Unlike npm's arborist (see {@link sweepStaleInstallStaging}: retire-rename,
|
|
183
|
+
* then one final rename), bun's write into the package directory is NOT known
|
|
184
|
+
* to be atomic — files may land incrementally. Anything that trusts a version
|
|
185
|
+
* bump on disk written by ANOTHER process (the daemon's stale-install relaunch
|
|
186
|
+
* in `daemon/self-update-service.ts`) must therefore gate on
|
|
187
|
+
* {@link installLooksSettled} rather than on the version alone.
|
|
188
|
+
*
|
|
178
189
|
* `signal` behaves exactly as documented on {@link installPackageIntoPrefix}.
|
|
179
190
|
*/
|
|
191
|
+
/** How long an install's package.json must have been at rest before a foreign version bump is trusted. */
|
|
192
|
+
export declare const INSTALL_SETTLE_MS = 60000;
|
|
193
|
+
/**
|
|
194
|
+
* True when the install at `packageRoot` looks complete: its package.json has
|
|
195
|
+
* not been modified for at least `settleMs`, and every `bin` entry it declares
|
|
196
|
+
* exists on disk. This is the guard for trusting a version bump that a
|
|
197
|
+
* DIFFERENT process wrote (an operator's `agents` auto-update, `agents
|
|
198
|
+
* upgrade`, the installer) without re-running that process's own verification:
|
|
199
|
+
* npm's reify is an atomic rename, but bun's is not (see
|
|
200
|
+
* {@link installPackageWithBun}), so a reader can catch bun mid-extraction —
|
|
201
|
+
* package.json present, `dist/` still landing. An install finishes in seconds;
|
|
202
|
+
* a minute of quiet plus the bin entry present rules that window out. Any
|
|
203
|
+
* read error means "not settled".
|
|
204
|
+
*/
|
|
205
|
+
export declare function installLooksSettled(packageRoot: string, settleMs?: number, now?: number): boolean;
|
|
180
206
|
export declare function installPackageWithBun(spec: string, signal?: AbortSignal): Promise<void>;
|
|
181
207
|
/**
|
|
182
208
|
* Verify a downloaded tarball's bytes against a Subresource Integrity (SRI)
|
package/dist/lib/self-update.js
CHANGED
|
@@ -240,37 +240,59 @@ function isPackageRoot(dir) {
|
|
|
240
240
|
/**
|
|
241
241
|
* The on-disk package root of the copy that is currently running.
|
|
242
242
|
*
|
|
243
|
-
* For a plain JS install
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
243
|
+
* For a plain JS install, walk up from the CALLING module's directory to the
|
|
244
|
+
* directory whose package.json names this package. Never assume a fixed depth:
|
|
245
|
+
* `<__dirname>/..` is the root only for a module directly under `dist/`, and
|
|
246
|
+
* from `dist/lib/daemon/self-update-service.js` it answered `dist/lib`, which
|
|
247
|
+
* deriveGlobalPrefix rejected as "not an npm-managed install" on every daemon
|
|
248
|
+
* self-update tick (2026-09-07 fleet incident).
|
|
249
249
|
*
|
|
250
|
-
*
|
|
251
|
-
*
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
*
|
|
250
|
+
* Under the compiled standalone binary (shipped since 1.20.53) `__dirname` is
|
|
251
|
+
* Bun's embedded virtual FS, so walking up from it yields `/$bunfs` — a path
|
|
252
|
+
* that exists nowhere. That phantom value was reported as a second install by
|
|
253
|
+
* the multi-install check and rejected by deriveGlobalPrefix, so every
|
|
254
|
+
* self-upgrade from a compiled copy failed. The physical executable is
|
|
255
|
+
* `process.execPath`, which ships inside the package
|
|
256
|
+
* (`<packageRoot>/dist/bin/agents`); walk up from it instead. Either way a
|
|
257
|
+
* change to the dist layout surfaces as a clear throw here rather than a wrong
|
|
258
|
+
* prefix that npm would happily install into.
|
|
255
259
|
*/
|
|
256
260
|
export function resolveRunningPackageRoot(dirname, execPath = process.execPath) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
261
|
+
if (!isBunVirtualPath(dirname)) {
|
|
262
|
+
// Walk up from the CALLING module's directory to the package.json that
|
|
263
|
+
// names this package. The previous `path.resolve(dirname, '..')` was only
|
|
264
|
+
// right for a module one level below the root (dist/bootstrap.js); from
|
|
265
|
+
// dist/lib/daemon/self-update-service.js it answered `dist/lib`, so
|
|
266
|
+
// `deriveGlobalPrefix` threw "not an npm-managed install" on every daemon
|
|
267
|
+
// self-update tick, fleet-wide, and no daemon ever relaunched onto a
|
|
268
|
+
// release (2026-09-07: eight workers still running 1.22.79 code four
|
|
269
|
+
// releases later).
|
|
270
|
+
const found = findPackageRootAbove(dirname);
|
|
271
|
+
if (found)
|
|
272
|
+
return found;
|
|
273
|
+
throw new Error(`Cannot locate the running agents-cli install: no ${NPM_PACKAGE_NAME} package.json above ` +
|
|
274
|
+
`${dirname}. Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
275
|
+
}
|
|
260
276
|
if (!execPath || isBunVirtualPath(execPath)) {
|
|
261
|
-
throw new Error(`Cannot locate the running agents-cli install: __dirname is the Bun virtual path ${
|
|
277
|
+
throw new Error(`Cannot locate the running agents-cli install: __dirname is the Bun virtual path ${dirname} ` +
|
|
262
278
|
`and process.execPath (${execPath || '(empty)'}) is not a real file. ` +
|
|
263
279
|
`Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
264
280
|
}
|
|
265
|
-
|
|
281
|
+
const found = findPackageRootAbove(path.dirname(path.resolve(execPath)));
|
|
282
|
+
if (found)
|
|
283
|
+
return found;
|
|
284
|
+
throw new Error(`Cannot locate the running agents-cli install: no ${NPM_PACKAGE_NAME} package.json above ` +
|
|
285
|
+
`${execPath}. Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
286
|
+
}
|
|
287
|
+
/** Nearest ancestor of `start` (inclusive) whose package.json names this package, or null. */
|
|
288
|
+
function findPackageRootAbove(start) {
|
|
289
|
+
let dir = path.resolve(start);
|
|
266
290
|
for (;;) {
|
|
267
291
|
if (isPackageRoot(dir))
|
|
268
292
|
return dir;
|
|
269
293
|
const parent = path.dirname(dir);
|
|
270
|
-
if (parent === dir)
|
|
271
|
-
|
|
272
|
-
`${execPath}. Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
273
|
-
}
|
|
294
|
+
if (parent === dir)
|
|
295
|
+
return null;
|
|
274
296
|
dir = parent;
|
|
275
297
|
}
|
|
276
298
|
}
|
|
@@ -376,8 +398,43 @@ export async function installPackageIntoPrefix(spec, prefix, signal) {
|
|
|
376
398
|
* alias shims afterwards via refreshAliasShims() rather than relying on the
|
|
377
399
|
* package's postinstall hook.
|
|
378
400
|
*
|
|
401
|
+
* Unlike npm's arborist (see {@link sweepStaleInstallStaging}: retire-rename,
|
|
402
|
+
* then one final rename), bun's write into the package directory is NOT known
|
|
403
|
+
* to be atomic — files may land incrementally. Anything that trusts a version
|
|
404
|
+
* bump on disk written by ANOTHER process (the daemon's stale-install relaunch
|
|
405
|
+
* in `daemon/self-update-service.ts`) must therefore gate on
|
|
406
|
+
* {@link installLooksSettled} rather than on the version alone.
|
|
407
|
+
*
|
|
379
408
|
* `signal` behaves exactly as documented on {@link installPackageIntoPrefix}.
|
|
380
409
|
*/
|
|
410
|
+
/** How long an install's package.json must have been at rest before a foreign version bump is trusted. */
|
|
411
|
+
export const INSTALL_SETTLE_MS = 60_000;
|
|
412
|
+
/**
|
|
413
|
+
* True when the install at `packageRoot` looks complete: its package.json has
|
|
414
|
+
* not been modified for at least `settleMs`, and every `bin` entry it declares
|
|
415
|
+
* exists on disk. This is the guard for trusting a version bump that a
|
|
416
|
+
* DIFFERENT process wrote (an operator's `agents` auto-update, `agents
|
|
417
|
+
* upgrade`, the installer) without re-running that process's own verification:
|
|
418
|
+
* npm's reify is an atomic rename, but bun's is not (see
|
|
419
|
+
* {@link installPackageWithBun}), so a reader can catch bun mid-extraction —
|
|
420
|
+
* package.json present, `dist/` still landing. An install finishes in seconds;
|
|
421
|
+
* a minute of quiet plus the bin entry present rules that window out. Any
|
|
422
|
+
* read error means "not settled".
|
|
423
|
+
*/
|
|
424
|
+
export function installLooksSettled(packageRoot, settleMs = INSTALL_SETTLE_MS, now = Date.now()) {
|
|
425
|
+
try {
|
|
426
|
+
const pkgJsonPath = path.join(packageRoot, 'package.json');
|
|
427
|
+
const stat = fs.statSync(pkgJsonPath);
|
|
428
|
+
if (now - stat.mtimeMs < settleMs)
|
|
429
|
+
return false;
|
|
430
|
+
const pkg = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8'));
|
|
431
|
+
const bins = typeof pkg.bin === 'string' ? [pkg.bin] : Object.values(pkg.bin ?? {});
|
|
432
|
+
return bins.every((rel) => fs.existsSync(path.join(packageRoot, rel)));
|
|
433
|
+
}
|
|
434
|
+
catch {
|
|
435
|
+
return false;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
381
438
|
export async function installPackageWithBun(spec, signal) {
|
|
382
439
|
const { execFile } = await import('child_process');
|
|
383
440
|
const { promisify } = await import('util');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phnx-labs/agents-cli",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.90",
|
|
4
4
|
"description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|