@phnx-labs/agents-cli 1.22.57 → 1.22.59
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 +294 -0
- package/README.md +29 -0
- package/dist/bootstrap.js +39 -1
- package/dist/commands/accounts.js +7 -3
- package/dist/commands/apply.js +10 -2
- package/dist/commands/fork.d.ts +23 -10
- package/dist/commands/fork.js +115 -58
- package/dist/commands/monitors.js +198 -23
- package/dist/commands/prune.js +5 -3
- package/dist/commands/routines.d.ts +8 -0
- package/dist/commands/routines.js +57 -3
- package/dist/commands/routines.test-fixture.js +5 -0
- package/dist/commands/send.d.ts +2 -1
- package/dist/commands/send.js +7 -5
- package/dist/commands/sessions-picker.d.ts +11 -0
- package/dist/commands/sessions-picker.js +16 -0
- package/dist/commands/sessions-stats.js +37 -5
- package/dist/commands/sessions.js +40 -5
- package/dist/commands/share.d.ts +14 -0
- package/dist/commands/share.js +43 -2
- package/dist/commands/ssh.js +12 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/sync.js +83 -7
- package/dist/commands/traces.js +7 -0
- package/dist/commands/versions.js +12 -4
- package/dist/commands/view.js +7 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +6 -1
- package/dist/lib/account-registry.d.ts +5 -1
- package/dist/lib/account-registry.js +47 -14
- package/dist/lib/accounting/capacity.d.ts +18 -7
- package/dist/lib/accounting/capacity.js +19 -8
- package/dist/lib/accounting/usage-sync.d.ts +29 -1
- package/dist/lib/accounting/usage-sync.js +76 -2
- package/dist/lib/accounting/usage.js +7 -1
- package/dist/lib/auth-mint.d.ts +11 -1
- package/dist/lib/auth-mint.js +21 -6
- package/dist/lib/auto-pull-worker.js +7 -2
- package/dist/lib/browser/ipc.d.ts +8 -0
- package/dist/lib/browser/ipc.js +87 -0
- package/dist/lib/browser/service.d.ts +19 -0
- package/dist/lib/browser/service.js +96 -11
- package/dist/lib/browser/sessions-list.js +10 -1
- package/dist/lib/cloud/rush.d.ts +7 -0
- package/dist/lib/cloud/rush.js +29 -1
- package/dist/lib/daemon/daemon.d.ts +22 -0
- package/dist/lib/daemon/daemon.js +39 -0
- package/dist/lib/daemon/runner.d.ts +3 -0
- package/dist/lib/daemon/runner.js +86 -45
- package/dist/lib/daemon/session-index-service.js +9 -1
- package/dist/lib/daemon/usage-sync-service.d.ts +3 -3
- package/dist/lib/daemon/usage-sync-service.js +14 -8
- package/dist/lib/daemon-services.js +1 -1
- package/dist/lib/daemon-ticks.d.ts +15 -0
- package/dist/lib/daemon-ticks.js +26 -0
- package/dist/lib/device-config.d.ts +5 -1
- package/dist/lib/device-config.js +2 -2
- package/dist/lib/devices/connect.d.ts +17 -8
- package/dist/lib/devices/connect.js +31 -14
- package/dist/lib/devices/health.js +5 -1
- package/dist/lib/devices/pool.d.ts +25 -2
- package/dist/lib/devices/pool.js +32 -2
- package/dist/lib/devices/stats-cache.d.ts +0 -6
- package/dist/lib/devices/stats-cache.js +2 -9
- package/dist/lib/doctor-diff.d.ts +14 -0
- package/dist/lib/doctor-diff.js +120 -9
- package/dist/lib/fleet/manifest.d.ts +17 -0
- package/dist/lib/fleet/manifest.js +26 -0
- package/dist/lib/git.d.ts +38 -0
- package/dist/lib/git.js +58 -0
- package/dist/lib/hooks/install.d.ts +27 -11
- package/dist/lib/hooks/install.js +42 -17
- package/dist/lib/hosts/ready.d.ts +8 -0
- package/dist/lib/hosts/ready.js +13 -2
- package/dist/lib/hosts/reconnect.d.ts +52 -203
- package/dist/lib/hosts/reconnect.js +64 -284
- package/dist/lib/installations/migrate.d.ts +6 -120
- package/dist/lib/installations/migrate.js +27 -259
- package/dist/lib/installations/shims.d.ts +13 -95
- package/dist/lib/installations/shims.js +22 -139
- package/dist/lib/installations/store.js +1 -1
- package/dist/lib/installations/versions.d.ts +43 -133
- package/dist/lib/installations/versions.js +94 -206
- package/dist/lib/monitors/config.d.ts +71 -3
- package/dist/lib/monitors/config.js +100 -12
- package/dist/lib/monitors/pid-watch.d.ts +35 -0
- package/dist/lib/monitors/pid-watch.js +45 -0
- package/dist/lib/monitors/remote.d.ts +18 -0
- package/dist/lib/monitors/remote.js +11 -0
- package/dist/lib/permissions.js +7 -2
- package/dist/lib/plugins/plugins.d.ts +17 -3
- package/dist/lib/plugins/plugins.js +84 -9
- package/dist/lib/plugins/skills.d.ts +8 -1
- package/dist/lib/plugins/skills.js +18 -2
- package/dist/lib/pty-server.d.ts +14 -0
- package/dist/lib/pty-server.js +49 -5
- package/dist/lib/refresh.d.ts +9 -0
- package/dist/lib/refresh.js +3 -1
- package/dist/lib/routine-readiness.d.ts +15 -1
- package/dist/lib/routine-readiness.js +41 -0
- package/dist/lib/sandbox.d.ts +4 -1
- package/dist/lib/sandbox.js +30 -1
- package/dist/lib/secrets/agent.d.ts +80 -225
- package/dist/lib/secrets/agent.js +139 -401
- package/dist/lib/secrets/bundles.d.ts +73 -222
- package/dist/lib/secrets/bundles.js +168 -467
- package/dist/lib/secrets/drivers/rush.js +5 -0
- package/dist/lib/secrets/reaper.d.ts +28 -70
- package/dist/lib/secrets/reaper.js +30 -85
- package/dist/lib/secrets/remote.d.ts +42 -129
- package/dist/lib/secrets/remote.js +55 -173
- package/dist/lib/self-heal/checks/install-staging.d.ts +4 -0
- package/dist/lib/self-heal/checks/install-staging.js +96 -0
- package/dist/lib/self-heal/registry.js +2 -0
- package/dist/lib/self-heal/types.d.ts +1 -1
- package/dist/lib/self-update.d.ts +65 -0
- package/dist/lib/self-update.js +138 -0
- package/dist/lib/session/active.d.ts +13 -1
- package/dist/lib/session/active.js +2 -0
- package/dist/lib/session/cloud.js +5 -0
- package/dist/lib/session/db.d.ts +51 -6
- package/dist/lib/session/db.js +266 -20
- package/dist/lib/session/fork.d.ts +45 -26
- package/dist/lib/session/fork.js +32 -95
- package/dist/lib/session/tool-calls.d.ts +43 -1
- package/dist/lib/session/tool-calls.js +74 -44
- package/dist/lib/session/tool-store.d.ts +33 -2
- package/dist/lib/session/tool-store.js +56 -3
- package/dist/lib/smart-launch.d.ts +6 -0
- package/dist/lib/smart-launch.js +5 -2
- package/dist/lib/staleness/writers/plugins.js +5 -2
- package/dist/lib/staleness/writers/sources.d.ts +5 -0
- package/dist/lib/staleness/writers/sources.js +2 -1
- package/dist/lib/staleness/writers/subagents.js +13 -3
- package/dist/lib/state.d.ts +7 -4
- package/dist/lib/state.js +7 -4
- package/dist/lib/subagents.js +8 -2
- package/dist/lib/sync-status.d.ts +22 -0
- package/dist/lib/sync-status.js +27 -0
- package/dist/lib/sync-umbrella.d.ts +9 -0
- package/dist/lib/sync-umbrella.js +21 -2
- package/dist/lib/teams/scheduler.d.ts +10 -0
- package/dist/lib/teams/scheduler.js +8 -0
- package/dist/lib/traces/insights.d.ts +47 -14
- package/dist/lib/traces/insights.js +92 -21
- package/dist/lib/traces/phenotype.d.ts +23 -3
- package/dist/lib/traces/phenotype.js +72 -24
- package/dist/lib/traces/sync.d.ts +128 -6
- package/dist/lib/traces/sync.js +294 -35
- package/dist/lib/traces/worker-template.js +154 -1
- package/dist/lib/view-types.d.ts +12 -0
- package/package.json +2 -2
package/dist/lib/self-update.js
CHANGED
|
@@ -292,6 +292,56 @@ export function deriveGlobalPrefix(packageRoot) {
|
|
|
292
292
|
const parent = path.dirname(nodeModulesDir);
|
|
293
293
|
return path.basename(parent) === 'lib' ? path.dirname(parent) : parent;
|
|
294
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Sweep npm arborist's "retired" staging dir for `packageRoot` before a
|
|
297
|
+
* reify (PHNX-3393).
|
|
298
|
+
*
|
|
299
|
+
* npm (@npmcli/arborist) reifies an install by first renaming the tree it is
|
|
300
|
+
* about to replace out of the way into a sibling directory —
|
|
301
|
+
* `retirePath(from)` in arborist's own source names it
|
|
302
|
+
* `.<basename>-<8-char sha1 hash of the full path>`, sibling to `from` — then
|
|
303
|
+
* stages the new tree and renames it into place. Because the hash is a pure
|
|
304
|
+
* function of `packageRoot`'s path, that staging path is IDENTICAL on every
|
|
305
|
+
* reify of this install. A crash between the retire-rename and the final
|
|
306
|
+
* rename (SIGKILL, a killed terminal, a box that lost power mid-upgrade)
|
|
307
|
+
* leaves that exact directory behind, non-empty. `rename(2)` cannot replace a
|
|
308
|
+
* non-empty directory, so every subsequent upgrade's reify fails ENOTEMPTY at
|
|
309
|
+
* the same path forever — nothing about a plain retry ever clears it.
|
|
310
|
+
*
|
|
311
|
+
* Removing any stale `.<basename>-*` sibling before install self-heals this:
|
|
312
|
+
* npm re-stages cleanly once the collision is gone. Matches only the
|
|
313
|
+
* retire-path shape (a dot-prefixed sibling starting with the package's own
|
|
314
|
+
* basename), so an unrelated dotfile in the same directory is left alone.
|
|
315
|
+
* Best-effort per entry: one unremovable sibling must not block the rest.
|
|
316
|
+
*/
|
|
317
|
+
export function sweepStaleInstallStaging(packageRoot) {
|
|
318
|
+
const resolved = path.resolve(packageRoot);
|
|
319
|
+
const dir = path.dirname(resolved);
|
|
320
|
+
const base = path.basename(resolved);
|
|
321
|
+
const escapedBase = base.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
322
|
+
const stagingPattern = new RegExp(`^\\.${escapedBase}-[a-zA-Z0-9]+$`);
|
|
323
|
+
let entries;
|
|
324
|
+
try {
|
|
325
|
+
entries = fs.readdirSync(dir);
|
|
326
|
+
}
|
|
327
|
+
catch {
|
|
328
|
+
return [];
|
|
329
|
+
}
|
|
330
|
+
const swept = [];
|
|
331
|
+
for (const entry of entries) {
|
|
332
|
+
if (!stagingPattern.test(entry))
|
|
333
|
+
continue;
|
|
334
|
+
const full = path.join(dir, entry);
|
|
335
|
+
try {
|
|
336
|
+
fs.rmSync(full, { recursive: true, force: true });
|
|
337
|
+
swept.push(full);
|
|
338
|
+
}
|
|
339
|
+
catch {
|
|
340
|
+
/* best-effort — one unremovable stager must not block the rest */
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
return swept;
|
|
344
|
+
}
|
|
295
345
|
/**
|
|
296
346
|
* Install `spec` into an explicit global prefix. `--prefix` pins the
|
|
297
347
|
* destination no matter which npm binary PATH resolves. `--ignore-scripts`
|
|
@@ -404,6 +454,94 @@ export function refreshAliasShims(packageRoot) {
|
|
|
404
454
|
stdio: 'ignore',
|
|
405
455
|
});
|
|
406
456
|
}
|
|
457
|
+
/** Resolve `p` through symlinks, or null when it does not resolve (missing/dangling). */
|
|
458
|
+
function realpathOrNull(p) {
|
|
459
|
+
try {
|
|
460
|
+
return fs.realpathSync(p);
|
|
461
|
+
}
|
|
462
|
+
catch {
|
|
463
|
+
return null;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Reconcile one `<binDir>/<name>` link to `target`. A link that already resolves
|
|
468
|
+
* to `target` is left untouched (`ok`); anything else — absent, dangling, or
|
|
469
|
+
* pointing at a stale/foreign path — is replaced with a fresh **relative**
|
|
470
|
+
* symlink (`../lib/node_modules/@phnx-labs/agents-cli/dist/index.js`), the exact
|
|
471
|
+
* shape npm and the by-hand zion repair both produced, then re-verified. A
|
|
472
|
+
* repair that still does not resolve (target missing, unwritable bin dir) is
|
|
473
|
+
* reported `failed` with the reason rather than silently swallowed.
|
|
474
|
+
*/
|
|
475
|
+
function reconcileBinLink(name, linkPath, target) {
|
|
476
|
+
const wanted = realpathOrNull(target);
|
|
477
|
+
if (wanted !== null && realpathOrNull(linkPath) === wanted) {
|
|
478
|
+
return { name, linkPath, target, action: 'ok' };
|
|
479
|
+
}
|
|
480
|
+
try {
|
|
481
|
+
fs.mkdirSync(path.dirname(linkPath), { recursive: true });
|
|
482
|
+
// Replace whatever is there (a dangling link, a stale link, or nothing).
|
|
483
|
+
fs.rmSync(linkPath, { force: true });
|
|
484
|
+
fs.symlinkSync(path.relative(path.dirname(linkPath), target), linkPath);
|
|
485
|
+
const resolved = realpathOrNull(linkPath);
|
|
486
|
+
if (resolved !== null && resolved === realpathOrNull(target)) {
|
|
487
|
+
return { name, linkPath, target, action: 'repaired' };
|
|
488
|
+
}
|
|
489
|
+
return {
|
|
490
|
+
name,
|
|
491
|
+
linkPath,
|
|
492
|
+
target,
|
|
493
|
+
action: 'failed',
|
|
494
|
+
error: resolved === null
|
|
495
|
+
? `link created but still does not resolve (is ${target} present?)`
|
|
496
|
+
: `link resolves to ${resolved}, not ${target}`,
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
catch (err) {
|
|
500
|
+
return { name, linkPath, target, action: 'failed', error: err instanceof Error ? err.message : String(err) };
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
/**
|
|
504
|
+
* The global bin links the upgrade OWNS: `<prefix>/bin/<name>` for every
|
|
505
|
+
* `package.json#bin` entry (`agents`, `ag`, `browser`, `computer`).
|
|
506
|
+
*
|
|
507
|
+
* npm creates these on a normal `install -g`, but a box with several installs
|
|
508
|
+
* (or a reify interrupted after the old links were retired) can end an upgrade
|
|
509
|
+
* with the package at the new version and these links **missing** — the state
|
|
510
|
+
* that stranded zion (PHNX-2768): `/opt/homebrew/lib/node_modules/...` at
|
|
511
|
+
* 1.22.40 but `/opt/homebrew/bin/{agents,ag,browser,computer}` gone, so every
|
|
512
|
+
* `agents` invocation was "command not found" until the links were relinked by
|
|
513
|
+
* hand. The rollout probe reported it `unverified`; the box was left broken.
|
|
514
|
+
*
|
|
515
|
+
* So the upgrade verifies these links right after installing and **restores any
|
|
516
|
+
* that are wrong** — covering the sibling entrypoints, not just `agents`, since
|
|
517
|
+
* `ag`/`browser`/`computer` share the same failure. Each link is reconciled
|
|
518
|
+
* independently; a link that cannot be made to resolve is reported `failed` so
|
|
519
|
+
* the caller can fail loud (the rollout then marks the box failed, not merely
|
|
520
|
+
* unverified) instead of returning a box the package upgraded but cannot run.
|
|
521
|
+
*
|
|
522
|
+
* POSIX only — Windows npm bins are `.cmd`/`.ps1` shims, not symlinks, so this
|
|
523
|
+
* relink shape does not apply and the caller skips it there. `prefix` is the
|
|
524
|
+
* npm global prefix from {@link deriveGlobalPrefix}; the bun path uses its own
|
|
525
|
+
* bin layout and is out of scope.
|
|
526
|
+
*/
|
|
527
|
+
export function ensureGlobalBinLinks(packageRoot, prefix) {
|
|
528
|
+
let bin;
|
|
529
|
+
try {
|
|
530
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(packageRoot, 'package.json'), 'utf-8'));
|
|
531
|
+
bin = pkg && typeof pkg.bin === 'object' && pkg.bin !== null ? pkg.bin : {};
|
|
532
|
+
}
|
|
533
|
+
catch (err) {
|
|
534
|
+
throw new Error(`could not read bin entries from ${path.join(packageRoot, 'package.json')}: ${err instanceof Error ? err.message : String(err)}`);
|
|
535
|
+
}
|
|
536
|
+
const binDir = path.join(prefix, 'bin');
|
|
537
|
+
const repairs = [];
|
|
538
|
+
for (const [name, rel] of Object.entries(bin)) {
|
|
539
|
+
if (typeof rel !== 'string' || !rel)
|
|
540
|
+
continue;
|
|
541
|
+
repairs.push(reconcileBinLink(name, path.join(binDir, name), path.resolve(packageRoot, rel)));
|
|
542
|
+
}
|
|
543
|
+
return repairs;
|
|
544
|
+
}
|
|
407
545
|
/**
|
|
408
546
|
* The package root a resolved `agents` entrypoint belongs to, or null when the
|
|
409
547
|
* path is not an agents-cli entry at all. Two shipped shapes:
|
|
@@ -55,7 +55,7 @@ export declare function attributedSetLostPids(prev: Set<number>, next: Set<numbe
|
|
|
55
55
|
export declare function filterCachedUnattributed(sessions: ActiveSession[], attributed: Set<number>, alive: (pid: number, startedAtMs?: number) => boolean): ActiveSession[];
|
|
56
56
|
type ActiveContext = 'terminal' | 'teams' | 'cloud' | 'headless';
|
|
57
57
|
/** The SessionMeta fields the live-row backfill reads — the enrichment a running process cannot report. */
|
|
58
|
-
export type BackfillMeta = Pick<SessionMeta, 'version' | 'timestamp' | 'label' | 'ticketId' | 'prUrl' | 'prNumber' | 'origin' | 'routineName' | 'harness'>;
|
|
58
|
+
export type BackfillMeta = Pick<SessionMeta, 'version' | 'account' | 'timestamp' | 'label' | 'ticketId' | 'prUrl' | 'prNumber' | 'origin' | 'routineName' | 'harness'>;
|
|
59
59
|
export declare function backfillActiveRowsFromMeta(sessions: ActiveSession[], metaById: Map<string, BackfillMeta>): void;
|
|
60
60
|
export declare function backfillActiveRowsFromIndex(sessions: ActiveSession[]): void;
|
|
61
61
|
export declare function isRunningLiveSession(s: ActiveSession): boolean;
|
|
@@ -201,6 +201,18 @@ export interface ActiveSession {
|
|
|
201
201
|
* id (RUSH-2205), never asserted by a source.
|
|
202
202
|
*/
|
|
203
203
|
version?: string;
|
|
204
|
+
/**
|
|
205
|
+
* Email of the account that produced the session (display-only). Like
|
|
206
|
+
* {@link version}, a running process does not report which account a
|
|
207
|
+
* `--strategy balanced` launch selected, so it is backfilled at render time
|
|
208
|
+
* from the indexed {@link SessionMeta} by session id (PHNX-3184). This is what
|
|
209
|
+
* the AGI EXT status bar renders as the session's account — it reads it off the
|
|
210
|
+
* `sessions watch --json` row instead of spawning a per-tab `agents sessions
|
|
211
|
+
* <id> --device <host> --json` (the 2026-08-25 CPU incident, agi-cli#3019).
|
|
212
|
+
* Never group on this — two orgs can share one email; group on the index's
|
|
213
|
+
* `accountKey`.
|
|
214
|
+
*/
|
|
215
|
+
account?: string;
|
|
204
216
|
/**
|
|
205
217
|
* Last-activity epoch — the transcript's last write (mtime). Distinct from
|
|
206
218
|
* {@link startedAtMs} (session START): a session begun 3h ago but last touched
|
|
@@ -145,6 +145,8 @@ export function backfillActiveRowsFromMeta(sessions, metaById) {
|
|
|
145
145
|
continue;
|
|
146
146
|
if (!s.version && m.version)
|
|
147
147
|
s.version = m.version;
|
|
148
|
+
if (!s.account && m.account)
|
|
149
|
+
s.account = m.account;
|
|
148
150
|
if (!s.label && m.label)
|
|
149
151
|
s.label = m.label;
|
|
150
152
|
if (!s.ticket && m.ticketId)
|
|
@@ -29,6 +29,11 @@ function readToken() {
|
|
|
29
29
|
if (!token) {
|
|
30
30
|
throw new Error('No session token in ~/.rush/user.yaml. Run `rush login` first.');
|
|
31
31
|
}
|
|
32
|
+
const expiresAt = data.session?.expires_at;
|
|
33
|
+
if (typeof expiresAt === 'number' && expiresAt <= Date.now() / 1000) {
|
|
34
|
+
const expiredAt = new Date(expiresAt * 1000).toISOString();
|
|
35
|
+
throw new Error(`Rush session expired at ${expiredAt}. Run \`rush login\` to refresh.`);
|
|
36
|
+
}
|
|
32
37
|
return token;
|
|
33
38
|
}
|
|
34
39
|
async function api(method, endpoint, token) {
|
package/dist/lib/session/db.d.ts
CHANGED
|
@@ -9,10 +9,11 @@
|
|
|
9
9
|
import Database from '../sqlite.js';
|
|
10
10
|
import type { SessionAgentId, SessionEvent, SessionMeta } from './types.js';
|
|
11
11
|
import { type IndexedToolCall } from './tool-calls.js';
|
|
12
|
+
import { type ToolScanResumePoint } from './tool-store.js';
|
|
12
13
|
/** Current schema version; bumped when migrations are added. Exported so tests
|
|
13
14
|
* assert against the constant instead of hardcoding a number that every bump
|
|
14
15
|
* then has to chase (docs/sessions.md calls the constant the source of truth). */
|
|
15
|
-
export declare const SCHEMA_VERSION =
|
|
16
|
+
export declare const SCHEMA_VERSION = 44;
|
|
16
17
|
/**
|
|
17
18
|
* Bump to force the content extractor (assistant-answer text, alongside the
|
|
18
19
|
* user-prompt text every harness already accumulates) to re-derive on every
|
|
@@ -35,6 +36,8 @@ export declare const CONTENT_INDEX_VERSION = 1;
|
|
|
35
36
|
export declare const INSIGHTS_EXTRACTOR_VERSION = 7;
|
|
36
37
|
/** Bump when classifyTopic's output changes so cached topics recompute (human task taxonomy v2). */
|
|
37
38
|
export declare const SESSION_TOPIC_EXTRACTOR_VERSION = 2;
|
|
39
|
+
/** Bump when classifyPhenotype's output changes so cached phenotypes recompute (PHNX-3327 v1). */
|
|
40
|
+
export declare const SESSION_PHENOTYPE_EXTRACTOR_VERSION = 1;
|
|
38
41
|
/** File stat snapshot used to detect changes between scan runs. */
|
|
39
42
|
export interface ScanStamp {
|
|
40
43
|
fileMtimeMs: number;
|
|
@@ -249,6 +252,13 @@ export declare function upsertSessionsBatch(entries: Array<{
|
|
|
249
252
|
toolCalls?: IndexedToolCall[];
|
|
250
253
|
toolScan?: ScanStamp;
|
|
251
254
|
toolIndexMode?: 'replace' | 'append';
|
|
255
|
+
/**
|
|
256
|
+
* Where the NEXT scan of this full-file-harness session may resume its tool
|
|
257
|
+
* index (PHNX-3411). Computed internally in the enrichment map below; not
|
|
258
|
+
* supplied by callers. Persisted alongside the tool ledger so an active
|
|
259
|
+
* session re-derives only its newly appended tool calls next tick.
|
|
260
|
+
*/
|
|
261
|
+
toolResume?: ToolScanResumePoint | null;
|
|
252
262
|
}>): void;
|
|
253
263
|
/**
|
|
254
264
|
* Sync labels for a set of sessions. For each id in the map, if the stored
|
|
@@ -307,6 +317,16 @@ export declare function getSessionExistenceCacheStats(): {
|
|
|
307
317
|
};
|
|
308
318
|
/** Query sessions from the database, applying filters and ordering by last-activity descending (default). */
|
|
309
319
|
export declare function querySessions(options?: QueryOptions): SessionMeta[];
|
|
320
|
+
/**
|
|
321
|
+
* Cheap query for the daemon's deferred tool-index pass (PHNX-3411).
|
|
322
|
+
*
|
|
323
|
+
* Returns the most-recently-active sessions whose parseSession reads a large
|
|
324
|
+
* flat transcript (kimi: wire.jsonl, grok: chat_history.jsonl). Their scanners
|
|
325
|
+
* produce no events, so upsertSessionsBatch skips them in the warm tick to
|
|
326
|
+
* avoid wedging the event loop. ensureToolIndex uses tool_scan_ledger stamps
|
|
327
|
+
* to skip already-current rows and applies byte/file budget caps.
|
|
328
|
+
*/
|
|
329
|
+
export declare function querySessionsForDeferredToolIndex(limit: number): SessionMeta[];
|
|
310
330
|
/** Count sessions matching the given filter options. */
|
|
311
331
|
export declare function countSessions(options?: QueryOptions): number;
|
|
312
332
|
/** One grouped row in a cost/duration rollup. */
|
|
@@ -377,6 +397,15 @@ export declare function writeSessionTopics<T>(entries: Array<{
|
|
|
377
397
|
fileSize: number | null;
|
|
378
398
|
topic: T;
|
|
379
399
|
}>): void;
|
|
400
|
+
/** Read cached failure phenotypes only when their transcript byte stamps still match. */
|
|
401
|
+
export declare function readSessionPhenotypes<T>(ids: string[]): Map<string, T>;
|
|
402
|
+
/** Persist failure phenotypes against the exact transcript bytes used to classify them. */
|
|
403
|
+
export declare function writeSessionPhenotypes<T>(entries: Array<{
|
|
404
|
+
id: string;
|
|
405
|
+
fileMtimeMs: number | null;
|
|
406
|
+
fileSize: number | null;
|
|
407
|
+
phenotype: T;
|
|
408
|
+
}>): void;
|
|
380
409
|
/** Read one derived preview only when it matches the transcript bytes on disk. */
|
|
381
410
|
export declare function readSessionPreviewCache<T>(id: string, sourceStamp: {
|
|
382
411
|
fileMtimeMs: number | null;
|
|
@@ -500,14 +529,30 @@ export declare function queryResourceUsageStats(options: QueryOptions & {
|
|
|
500
529
|
limit?: number;
|
|
501
530
|
}): ResourceStatRow[];
|
|
502
531
|
/**
|
|
503
|
-
* Coverage of the resource-usage signal
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
*
|
|
507
|
-
*
|
|
532
|
+
* Coverage of the resource-usage signal, as three honest facts:
|
|
533
|
+
*
|
|
534
|
+
* - `scanned` — sessions the resource extractor has actually processed, i.e.
|
|
535
|
+
* those carrying a `resource_scan_ledger` row at the current
|
|
536
|
+
* `RESOURCE_INDEX_VERSION`. This is the true "has the historical backfill run"
|
|
537
|
+
* signal: the ledger is stamped for EVERY scanned session, including ones that
|
|
538
|
+
* invoked nothing (`resource_count = 0`), so `scanned/total` rises to ~1 after
|
|
539
|
+
* `agents sessions backfill resources` regardless of how sparse explicit
|
|
540
|
+
* invocations are.
|
|
541
|
+
* - `covered` — distinct sessions that carry AT LEAST ONE row in
|
|
542
|
+
* `session_resource_usage`, i.e. that actually recorded an explicit invocation.
|
|
543
|
+
* This is an ABSOLUTE signal count, not a coverage ratio: it stays small even
|
|
544
|
+
* at full scan coverage because most sessions invoke no skill/command, and a
|
|
545
|
+
* non-recording harness contributes none by construction.
|
|
546
|
+
* - `total` — sessions indexed.
|
|
547
|
+
*
|
|
548
|
+
* The two were previously conflated: `covered/total` was framed as coverage and
|
|
549
|
+
* read ~1.2% even after a full backfill (most sessions genuinely invoke nothing),
|
|
550
|
+
* so the "run the backfill" hint never cleared. Keying the hint on `scanned/total`
|
|
551
|
+
* fixes that — see `commands/sessions-stats.ts` (PHNX-2301).
|
|
508
552
|
*/
|
|
509
553
|
export declare function resourceUsageCoverage(): {
|
|
510
554
|
covered: number;
|
|
555
|
+
scanned: number;
|
|
511
556
|
total: number;
|
|
512
557
|
};
|
|
513
558
|
/** Outcome of a resource-usage backfill run. */
|