@phnx-labs/agents-cli 1.20.74 → 1.20.77
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 +1055 -0
- package/README.md +36 -10
- package/dist/bin/agents +0 -0
- package/dist/commands/apply.js +21 -3
- package/dist/commands/attach.d.ts +10 -0
- package/dist/commands/attach.js +41 -0
- package/dist/commands/computer.js +3 -3
- package/dist/commands/detach-core.d.ts +46 -0
- package/dist/commands/detach-core.js +61 -0
- package/dist/commands/detach.d.ts +5 -0
- package/dist/commands/detach.js +171 -0
- package/dist/commands/doctor.js +18 -0
- package/dist/commands/exec.js +83 -13
- package/dist/commands/feed.d.ts +7 -1
- package/dist/commands/feed.js +47 -4
- package/dist/commands/go.d.ts +9 -2
- package/dist/commands/go.js +16 -6
- package/dist/commands/harness.d.ts +14 -0
- package/dist/commands/harness.js +145 -0
- package/dist/commands/import.js +38 -8
- package/dist/commands/inspect.js +5 -2
- package/dist/commands/profiles.d.ts +20 -0
- package/dist/commands/profiles.js +68 -21
- package/dist/commands/repo.js +14 -0
- package/dist/commands/routines.js +286 -15
- package/dist/commands/secrets.js +102 -37
- package/dist/commands/sessions-browser.js +12 -2
- package/dist/commands/sessions-export.js +19 -5
- package/dist/commands/sessions-migrate.d.ts +29 -0
- package/dist/commands/sessions-migrate.js +596 -0
- package/dist/commands/sessions-picker.d.ts +14 -1
- package/dist/commands/sessions-picker.js +184 -16
- package/dist/commands/sessions.d.ts +56 -14
- package/dist/commands/sessions.js +322 -62
- package/dist/commands/setup-computer.js +2 -2
- package/dist/commands/ssh.d.ts +13 -0
- package/dist/commands/ssh.js +110 -37
- package/dist/commands/status.js +10 -2
- package/dist/commands/versions.js +15 -6
- package/dist/commands/view.d.ts +5 -0
- package/dist/commands/view.js +24 -4
- package/dist/commands/watchdog.d.ts +7 -2
- package/dist/commands/watchdog.js +73 -57
- package/dist/index.js +59 -7
- package/dist/lib/activity.d.ts +17 -6
- package/dist/lib/activity.js +466 -40
- package/dist/lib/actor.d.ts +50 -0
- package/dist/lib/actor.js +166 -0
- package/dist/lib/agent-spec/provider.js +2 -1
- package/dist/lib/agent-spec/resolve.js +19 -5
- package/dist/lib/agent-spec/types.d.ts +9 -1
- package/dist/lib/agents.d.ts +21 -0
- package/dist/lib/agents.js +70 -6
- package/dist/lib/cloud/codex.d.ts +2 -0
- package/dist/lib/cloud/codex.js +14 -3
- package/dist/lib/cloud/session-index.d.ts +32 -0
- package/dist/lib/cloud/session-index.js +58 -0
- package/dist/lib/cloud/store.d.ts +7 -0
- package/dist/lib/cloud/store.js +25 -0
- package/dist/lib/config-transfer.js +4 -0
- package/dist/lib/daemon.d.ts +10 -1
- package/dist/lib/daemon.js +114 -11
- package/dist/lib/devices/connect.d.ts +15 -1
- package/dist/lib/devices/connect.js +15 -1
- package/dist/lib/devices/fleet.d.ts +37 -1
- package/dist/lib/devices/fleet.js +36 -2
- package/dist/lib/devices/health-report.d.ts +38 -0
- package/dist/lib/devices/health-report.js +214 -0
- package/dist/lib/devices/health.js +4 -1
- package/dist/lib/devices/reachability.d.ts +31 -0
- package/dist/lib/devices/reachability.js +40 -0
- package/dist/lib/devices/registry.d.ts +33 -0
- package/dist/lib/devices/registry.js +37 -0
- package/dist/lib/devices/resolve-target.d.ts +15 -27
- package/dist/lib/devices/resolve-target.js +63 -102
- package/dist/lib/devices/sync.d.ts +18 -0
- package/dist/lib/devices/sync.js +23 -1
- package/dist/lib/devices/tailscale.d.ts +3 -0
- package/dist/lib/devices/tailscale.js +1 -0
- package/dist/lib/events.d.ts +1 -1
- package/dist/lib/exec.d.ts +82 -0
- package/dist/lib/exec.js +218 -6
- package/dist/lib/feed-post.d.ts +63 -0
- package/dist/lib/feed-post.js +204 -0
- package/dist/lib/feed.d.ts +7 -1
- package/dist/lib/feed.js +96 -6
- package/dist/lib/fleet/apply.d.ts +32 -2
- package/dist/lib/fleet/apply.js +97 -10
- package/dist/lib/fleet/types.d.ts +11 -0
- package/dist/lib/fs-walk.d.ts +13 -0
- package/dist/lib/fs-walk.js +16 -7
- package/dist/lib/heal.d.ts +7 -4
- package/dist/lib/heal.js +10 -22
- package/dist/lib/hooks.d.ts +1 -0
- package/dist/lib/hooks.js +156 -0
- package/dist/lib/hosts/dispatch.d.ts +16 -0
- package/dist/lib/hosts/dispatch.js +26 -4
- package/dist/lib/hosts/passthrough.js +9 -2
- package/dist/lib/hosts/reconnect.d.ts +78 -0
- package/dist/lib/hosts/reconnect.js +127 -0
- package/dist/lib/hosts/registry.d.ts +75 -14
- package/dist/lib/hosts/registry.js +205 -30
- package/dist/lib/hosts/remote-cmd.d.ts +11 -0
- package/dist/lib/hosts/remote-cmd.js +32 -8
- package/dist/lib/hosts/remote-session-id.d.ts +45 -0
- package/dist/lib/hosts/remote-session-id.js +84 -0
- package/dist/lib/hosts/run-target.d.ts +17 -5
- package/dist/lib/hosts/run-target.js +30 -10
- package/dist/lib/hosts/session-index.d.ts +18 -1
- package/dist/lib/hosts/session-index.js +40 -5
- package/dist/lib/hosts/session-marker.d.ts +33 -0
- package/dist/lib/hosts/session-marker.js +51 -0
- package/dist/lib/hosts/tasks.d.ts +8 -4
- package/dist/lib/import.d.ts +2 -0
- package/dist/lib/import.js +35 -2
- package/dist/lib/menubar/install-menubar.d.ts +29 -0
- package/dist/lib/menubar/install-menubar.js +59 -1
- package/dist/lib/menubar/notify-desktop.d.ts +44 -0
- package/dist/lib/menubar/notify-desktop.js +78 -0
- package/dist/lib/migrate.d.ts +16 -0
- package/dist/lib/migrate.js +36 -0
- package/dist/lib/models.d.ts +27 -0
- package/dist/lib/models.js +54 -1
- package/dist/lib/overdue.d.ts +6 -2
- package/dist/lib/overdue.js +10 -36
- package/dist/lib/picker.js +4 -1
- package/dist/lib/platform/process.d.ts +17 -0
- package/dist/lib/platform/process.js +70 -0
- package/dist/lib/profiles-presets.js +9 -7
- package/dist/lib/profiles.d.ts +31 -0
- package/dist/lib/profiles.js +70 -0
- package/dist/lib/pty-server.d.ts +2 -10
- package/dist/lib/pty-server.js +4 -38
- package/dist/lib/registry.d.ts +1 -1
- package/dist/lib/registry.js +48 -8
- package/dist/lib/rotate.d.ts +18 -0
- package/dist/lib/rotate.js +28 -0
- package/dist/lib/routine-notify.d.ts +76 -0
- package/dist/lib/routine-notify.js +190 -0
- package/dist/lib/routines-placement.d.ts +38 -0
- package/dist/lib/routines-placement.js +79 -0
- package/dist/lib/routines-project.d.ts +97 -0
- package/dist/lib/routines-project.js +349 -0
- package/dist/lib/routines.d.ts +94 -0
- package/dist/lib/routines.js +93 -9
- package/dist/lib/runner.d.ts +12 -2
- package/dist/lib/runner.js +242 -20
- package/dist/lib/sandbox.js +10 -0
- package/dist/lib/secrets/account-token.d.ts +20 -0
- package/dist/lib/secrets/account-token.js +64 -0
- package/dist/lib/secrets/agent.d.ts +74 -4
- package/dist/lib/secrets/agent.js +181 -107
- package/dist/lib/secrets/bundles.d.ts +54 -6
- package/dist/lib/secrets/bundles.js +230 -34
- package/dist/lib/secrets/index.d.ts +26 -3
- package/dist/lib/secrets/index.js +42 -12
- package/dist/lib/secrets/rc-hygiene.d.ts +55 -0
- package/dist/lib/secrets/rc-hygiene.js +154 -0
- package/dist/lib/secrets/remote.d.ts +7 -4
- package/dist/lib/secrets/remote.js +7 -4
- package/dist/lib/secrets/session-store.d.ts +6 -2
- package/dist/lib/secrets/session-store.js +65 -15
- package/dist/lib/secrets/sync-commands.d.ts +21 -0
- package/dist/lib/secrets/sync-commands.js +21 -0
- package/dist/lib/secrets/unlock-hints.d.ts +27 -0
- package/dist/lib/secrets/unlock-hints.js +36 -0
- package/dist/lib/self-update.d.ts +23 -2
- package/dist/lib/self-update.js +86 -5
- package/dist/lib/session/active.d.ts +124 -7
- package/dist/lib/session/active.js +390 -56
- package/dist/lib/session/cloud.js +2 -1
- package/dist/lib/session/db.d.ts +54 -0
- package/dist/lib/session/db.js +320 -19
- package/dist/lib/session/detached.d.ts +30 -0
- package/dist/lib/session/detached.js +92 -0
- package/dist/lib/session/discover.d.ts +478 -3
- package/dist/lib/session/discover.js +1740 -472
- package/dist/lib/session/fork.js +2 -1
- package/dist/lib/session/hook-sessions.d.ts +43 -0
- package/dist/lib/session/hook-sessions.js +135 -0
- package/dist/lib/session/linear.d.ts +6 -0
- package/dist/lib/session/linear.js +55 -0
- package/dist/lib/session/migrate-targets.d.ts +65 -0
- package/dist/lib/session/migrate-targets.js +94 -0
- package/dist/lib/session/migrations.d.ts +37 -0
- package/dist/lib/session/migrations.js +60 -0
- package/dist/lib/session/parse.d.ts +18 -0
- package/dist/lib/session/parse.js +141 -32
- package/dist/lib/session/pid-registry.d.ts +34 -2
- package/dist/lib/session/pid-registry.js +49 -2
- package/dist/lib/session/prompt.d.ts +7 -0
- package/dist/lib/session/prompt.js +37 -0
- package/dist/lib/session/provenance.d.ts +7 -0
- package/dist/lib/session/render.d.ts +7 -2
- package/dist/lib/session/render.js +40 -26
- package/dist/lib/session/short-id.d.ts +17 -0
- package/dist/lib/session/short-id.js +20 -0
- package/dist/lib/session/state.d.ts +4 -0
- package/dist/lib/session/state.js +99 -13
- package/dist/lib/session/types.d.ts +25 -1
- package/dist/lib/session/types.js +8 -0
- package/dist/lib/shims.d.ts +1 -1
- package/dist/lib/shims.js +20 -6
- package/dist/lib/sqlite.d.ts +3 -2
- package/dist/lib/sqlite.js +27 -4
- package/dist/lib/staleness/detectors/commands.js +1 -1
- package/dist/lib/staleness/detectors/workflows.js +13 -2
- package/dist/lib/staleness/writers/commands.js +7 -7
- package/dist/lib/staleness/writers/workflows.d.ts +4 -2
- package/dist/lib/startup/command-registry.d.ts +1 -0
- package/dist/lib/startup/command-registry.js +3 -0
- package/dist/lib/state.d.ts +8 -4
- package/dist/lib/state.js +21 -37
- package/dist/lib/teams/agents.d.ts +19 -10
- package/dist/lib/teams/agents.js +40 -39
- package/dist/lib/types.d.ts +47 -2
- package/dist/lib/usage.d.ts +33 -1
- package/dist/lib/usage.js +172 -12
- package/dist/lib/versions.d.ts +9 -2
- package/dist/lib/versions.js +37 -8
- package/dist/lib/watchdog/log.d.ts +43 -0
- package/dist/lib/watchdog/log.js +69 -0
- package/dist/lib/watchdog/routine.d.ts +44 -0
- package/dist/lib/watchdog/routine.js +69 -0
- package/dist/lib/watchdog/runner.d.ts +51 -7
- package/dist/lib/watchdog/runner.js +239 -64
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdog.js +31 -16
- package/dist/lib/workflows.d.ts +16 -0
- package/dist/lib/workflows.js +110 -1
- package/package.json +1 -1
package/dist/lib/self-update.js
CHANGED
|
@@ -116,6 +116,66 @@ export function shouldPromptUpgrade(cache, currentVersion) {
|
|
|
116
116
|
compareVersions(cache.latestVersion, currentVersion) > 0 &&
|
|
117
117
|
cache.latestVersion !== cache.dismissed);
|
|
118
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Whether `p` is Bun's embedded virtual filesystem — where a standalone
|
|
121
|
+
* executable exposes its bundled sources. Nothing there exists on disk: it
|
|
122
|
+
* cannot be stat'd, installed into, or compared against a real install path.
|
|
123
|
+
*
|
|
124
|
+
* Matches the root itself (`/$bunfs`) as well as paths under it, because
|
|
125
|
+
* `<__dirname>/..` from the embedded entry produces exactly that bare root.
|
|
126
|
+
* daemon.ts carries a narrower under-the-root-only guard for deciding what may
|
|
127
|
+
* be supervised; the two are deliberately not shared.
|
|
128
|
+
*/
|
|
129
|
+
function isBunVirtualPath(p) {
|
|
130
|
+
return /(^|[/\\])\$bunfs([/\\]|$)/.test(p);
|
|
131
|
+
}
|
|
132
|
+
/** Whether `dir` is the root of an installed copy of this package. */
|
|
133
|
+
function isPackageRoot(dir) {
|
|
134
|
+
try {
|
|
135
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8'));
|
|
136
|
+
return pkg.name === NPM_PACKAGE_NAME;
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The on-disk package root of the copy that is currently running.
|
|
144
|
+
*
|
|
145
|
+
* For a plain JS install this is just `<__dirname>/..`. Under the compiled
|
|
146
|
+
* standalone binary (shipped since 1.20.53) it is not: Bun sets `__dirname` to
|
|
147
|
+
* its embedded virtual FS, so `<__dirname>/..` yields `/$bunfs` — a path that
|
|
148
|
+
* exists nowhere. That phantom value was reported as a second install by the
|
|
149
|
+
* multi-install check, and rejected by deriveGlobalPrefix as "not an
|
|
150
|
+
* npm-managed install", so every self-upgrade from a compiled copy failed.
|
|
151
|
+
*
|
|
152
|
+
* The physical executable is `process.execPath`, which ships inside the
|
|
153
|
+
* package (`<packageRoot>/dist/bin/agents`). Walk up from it to the directory
|
|
154
|
+
* whose package.json actually names this package rather than assuming a fixed
|
|
155
|
+
* depth, so a change to the dist layout surfaces as a clear throw here instead
|
|
156
|
+
* of a wrong prefix that npm would happily install into.
|
|
157
|
+
*/
|
|
158
|
+
export function resolveRunningPackageRoot(dirname, execPath = process.execPath) {
|
|
159
|
+
const fromDirname = path.resolve(dirname, '..');
|
|
160
|
+
if (!isBunVirtualPath(fromDirname))
|
|
161
|
+
return fromDirname;
|
|
162
|
+
if (!execPath || isBunVirtualPath(execPath)) {
|
|
163
|
+
throw new Error(`Cannot locate the running agents-cli install: __dirname is the Bun virtual path ${fromDirname} ` +
|
|
164
|
+
`and process.execPath (${execPath || '(empty)'}) is not a real file. ` +
|
|
165
|
+
`Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
166
|
+
}
|
|
167
|
+
let dir = path.dirname(path.resolve(execPath));
|
|
168
|
+
for (;;) {
|
|
169
|
+
if (isPackageRoot(dir))
|
|
170
|
+
return dir;
|
|
171
|
+
const parent = path.dirname(dir);
|
|
172
|
+
if (parent === dir) {
|
|
173
|
+
throw new Error(`Cannot locate the running agents-cli install: no ${NPM_PACKAGE_NAME} package.json above ` +
|
|
174
|
+
`${execPath}. Reinstall with: npm install -g ${NPM_PACKAGE_NAME}`);
|
|
175
|
+
}
|
|
176
|
+
dir = parent;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
119
179
|
/**
|
|
120
180
|
* Derive the npm global prefix that owns the install at `packageRoot`.
|
|
121
181
|
*
|
|
@@ -249,6 +309,24 @@ export function refreshAliasShims(packageRoot) {
|
|
|
249
309
|
stdio: 'ignore',
|
|
250
310
|
});
|
|
251
311
|
}
|
|
312
|
+
/**
|
|
313
|
+
* The package root a resolved `agents` entrypoint belongs to, or null when the
|
|
314
|
+
* path is not an agents-cli entry at all. Two shipped shapes:
|
|
315
|
+
* <packageRoot>/dist/index.js — the JS entry npm links as `agents`
|
|
316
|
+
* <packageRoot>/dist/bin/agents — the compiled standalone executable
|
|
317
|
+
*/
|
|
318
|
+
function packageRootForEntry(real) {
|
|
319
|
+
const distDir = path.dirname(real);
|
|
320
|
+
if (path.basename(real) === 'index.js' && path.basename(distDir) === 'dist') {
|
|
321
|
+
return path.dirname(distDir);
|
|
322
|
+
}
|
|
323
|
+
if (path.basename(real) === 'agents' &&
|
|
324
|
+
path.basename(distDir) === 'bin' &&
|
|
325
|
+
path.basename(path.dirname(distDir)) === 'dist') {
|
|
326
|
+
return path.dirname(path.dirname(distDir));
|
|
327
|
+
}
|
|
328
|
+
return null;
|
|
329
|
+
}
|
|
252
330
|
/**
|
|
253
331
|
* Scan PATH for `agents` entrypoints and resolve each to the agents-cli
|
|
254
332
|
* package root it executes. More than one distinct root means upgrades,
|
|
@@ -257,8 +335,12 @@ export function refreshAliasShims(packageRoot) {
|
|
|
257
335
|
*
|
|
258
336
|
* npm bin entries are symlinks that resolve to `<packageRoot>/dist/index.js`
|
|
259
337
|
* (the dev install's `~/.local/bin/agents` chains through the dev prefix to
|
|
260
|
-
* the same shape).
|
|
261
|
-
*
|
|
338
|
+
* the same shape). A shim pointed at the compiled standalone binary resolves
|
|
339
|
+
* to `<packageRoot>/dist/bin/agents` instead; that shape counts too, otherwise
|
|
340
|
+
* the copy that actually runs — the compiled one is typically first on PATH —
|
|
341
|
+
* is invisible to this scan and its root looks like a separate install.
|
|
342
|
+
* Anything that resolves to neither shape inside a package named
|
|
343
|
+
* @phnx-labs/agents-cli is some other tool and is skipped.
|
|
262
344
|
* POSIX-only: Windows npm bins are .cmd wrappers, not symlinks.
|
|
263
345
|
*/
|
|
264
346
|
export function findAgentsCliInstalls(pathEnv) {
|
|
@@ -275,10 +357,9 @@ export function findAgentsCliInstalls(pathEnv) {
|
|
|
275
357
|
catch {
|
|
276
358
|
continue; // missing or dangling symlink
|
|
277
359
|
}
|
|
278
|
-
|
|
360
|
+
const packageRoot = packageRootForEntry(real);
|
|
361
|
+
if (!packageRoot)
|
|
279
362
|
continue;
|
|
280
|
-
}
|
|
281
|
-
const packageRoot = path.dirname(path.dirname(real));
|
|
282
363
|
if (seenRoots.has(packageRoot))
|
|
283
364
|
continue;
|
|
284
365
|
let pkg;
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import type { CloudTaskStatus } from '../cloud/types.js';
|
|
2
2
|
import { type PidSessionEntry } from './pid-registry.js';
|
|
3
|
+
import { type HookSessionIndex } from './hook-sessions.js';
|
|
3
4
|
import { type SessionActivity, type AwaitingReason, type StructuredQuestion, type TodoProgress, type DetectedPr, type DetectedWorktree, type DetectedTicket } from './state.js';
|
|
4
5
|
import type { SessionAttachment } from './types.js';
|
|
5
6
|
import { type SessionProvenance } from './provenance.js';
|
|
7
|
+
import { type DeviceRegistry } from '../devices/registry.js';
|
|
8
|
+
import { type Presence } from './detached.js';
|
|
6
9
|
/**
|
|
7
10
|
* Per-PID `lsof` probes run bounded and staggered rather than as one parallel
|
|
8
11
|
* fan-out: a simultaneous system-wide `lsof` burst reads to behavioral EDR
|
|
@@ -11,7 +14,15 @@ import { type SessionProvenance } from './provenance.js';
|
|
|
11
14
|
*/
|
|
12
15
|
export declare const LSOF_CONCURRENCY = 4;
|
|
13
16
|
export type ActiveContext = 'terminal' | 'teams' | 'cloud' | 'headless';
|
|
14
|
-
|
|
17
|
+
/**
|
|
18
|
+
* `unknown` = the process is alive but we cannot introspect what it is doing —
|
|
19
|
+
* a live harness whose transcript format we do not parse (everything but
|
|
20
|
+
* claude/codex), or a resolvable transcript whose `stat` momentarily failed. It
|
|
21
|
+
* is NOT a synonym for idle: idle is a positive "not mid-turn, not waiting on
|
|
22
|
+
* you" conclusion drawn from a readable transcript; unknown is the honest "we
|
|
23
|
+
* can't tell", which we refuse to fake as idle.
|
|
24
|
+
*/
|
|
25
|
+
export type ActiveStatus = 'running' | 'idle' | 'queued' | 'input_required' | 'unknown';
|
|
15
26
|
export interface ActiveSession {
|
|
16
27
|
context: ActiveContext;
|
|
17
28
|
kind: string;
|
|
@@ -71,7 +82,24 @@ export interface ActiveSession {
|
|
|
71
82
|
attachments?: SessionAttachment[];
|
|
72
83
|
sessionFile?: string;
|
|
73
84
|
startedAtMs?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Last-activity epoch — the transcript's last write (mtime). Distinct from
|
|
87
|
+
* {@link startedAtMs} (session START): a session begun 3h ago but last touched
|
|
88
|
+
* 20s ago has an old start and a fresh last-activity. The Floor renders "Xs ago"
|
|
89
|
+
* off this so an idle-but-old session doesn't read as freshly active.
|
|
90
|
+
*/
|
|
91
|
+
lastActivityMs?: number;
|
|
74
92
|
status: ActiveStatus;
|
|
93
|
+
/**
|
|
94
|
+
* Foreground/background presence for the detach/attach model:
|
|
95
|
+
* `attached` — live interactive TUI you're watching;
|
|
96
|
+
* `background` — detached: running headless, unattended (via `agents sessions detach`);
|
|
97
|
+
* `parked` — the headless continuation has exited; the transcript is durable.
|
|
98
|
+
* Absent for ad-hoc headless runs and cloud/team rows, which aren't on the
|
|
99
|
+
* foreground/background axis. Folded on at the end of {@link getActiveSessions}
|
|
100
|
+
* from the detach store — never asserted by a source.
|
|
101
|
+
*/
|
|
102
|
+
presence?: Presence;
|
|
75
103
|
/** How many live PIDs resolve to this same session (subagents/forks). 1 unless collapsed. */
|
|
76
104
|
pidCount?: number;
|
|
77
105
|
/**
|
|
@@ -150,6 +178,17 @@ export declare const ACTIVE_SESSION_STALE_MS: number;
|
|
|
150
178
|
* `.exe` suffix (`claude.exe`), so basename + suffix-strip before the lookup.
|
|
151
179
|
*/
|
|
152
180
|
export declare function agentKindFromComm(commRaw: string): string | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* True when `pid` names a live process AND — when a session's recorded
|
|
183
|
+
* `startedAtMs` is supplied — that process is plausibly the SAME one, not a later
|
|
184
|
+
* process that recycled the pid. The OS reuses pids, so a bare
|
|
185
|
+
* `process.kill(pid, 0)` existence check reports a dead session as alive (a
|
|
186
|
+
* "zombie") once its pid is handed to an unrelated process. A genuine session
|
|
187
|
+
* process starts at or before its own recorded start, so a process that began
|
|
188
|
+
* meaningfully AFTER `startedAtMs` is a reused pid and the session is dead. When
|
|
189
|
+
* the start time can't be read, we keep the existence answer.
|
|
190
|
+
*/
|
|
191
|
+
export declare function isPidAlive(pid: number, startedAtMs?: number): boolean;
|
|
153
192
|
/**
|
|
154
193
|
* Pick a Claude transcript file within a project dir.
|
|
155
194
|
*
|
|
@@ -163,6 +202,34 @@ export declare function agentKindFromComm(commRaw: string): string | undefined;
|
|
|
163
202
|
* heuristic for a directly-launched agent with no registry entry).
|
|
164
203
|
*/
|
|
165
204
|
export declare function pickSessionFile(projectDir: string, sessionId?: string): string | undefined;
|
|
205
|
+
/**
|
|
206
|
+
* One `stat` → the transcript's creation (≈ session start) and last-write (≈ last
|
|
207
|
+
* activity) epochs. Both `undefined` when the file can't be stat'd (vanished /
|
|
208
|
+
* unresolved). `birthtimeMs` can be 0 on filesystems without creation time — coerce
|
|
209
|
+
* that to `undefined` so callers fall through to a real signal instead of epoch 0.
|
|
210
|
+
*/
|
|
211
|
+
export declare function sessionFileTimes(sessionFile: string | undefined): {
|
|
212
|
+
birthtimeMs?: number;
|
|
213
|
+
mtimeMs?: number;
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* The ONE place a fallback status is decided when no rich transcript state is
|
|
217
|
+
* available — a non-Claude/Codex kind we cannot parse, or a Claude/Codex tail
|
|
218
|
+
* that was empty or unreadable. Honest by construction: it never asserts a status
|
|
219
|
+
* it cannot justify from a measured signal.
|
|
220
|
+
*
|
|
221
|
+
* - Resolvable transcript, readable mtime → the MEASURED freshness signal:
|
|
222
|
+
* written within ACTIVE_MTIME_WINDOW_MS ⇒ `running`, else `idle`.
|
|
223
|
+
* - Resolvable transcript whose `stat` throws (file vanished / permission) → we
|
|
224
|
+
* genuinely cannot tell ⇒ `unknown`. (This branch previously returned
|
|
225
|
+
* `running`, which contradicted the `idle` default one branch up.)
|
|
226
|
+
* - No resolvable transcript but the process is alive → alive-but-opaque ⇒
|
|
227
|
+
* `unknown`. This is the truthful answer for a live gemini / droid / cursor /
|
|
228
|
+
* opencode whose format we don't parse — NOT a fabricated `idle` (which the
|
|
229
|
+
* UI reads as "done and waiting"), and it never lies as `running` either.
|
|
230
|
+
* - No transcript and the process is not known alive → nothing to report ⇒ `idle`.
|
|
231
|
+
*/
|
|
232
|
+
export declare function resolveFallbackStatus(sessionFile: string | undefined, pidAlive: boolean): ActiveStatus;
|
|
166
233
|
/**
|
|
167
234
|
* Locate the live transcript for an agent process. Claude files are keyed by
|
|
168
235
|
* cwd (+ optional session uuid); Codex files are date-partitioned, so we resolve
|
|
@@ -236,14 +303,47 @@ export declare function foldSubordinateAgents(candidates: AgentCandidate[], ppid
|
|
|
236
303
|
* sort means `headless` (daemon, launchd-spawned, orphan).
|
|
237
304
|
*/
|
|
238
305
|
export declare function listUnattributedActive(attributed: Set<number>): Promise<ActiveSession[]>;
|
|
306
|
+
/** One tmux pane's resolved agent identity for the authoritative source. */
|
|
307
|
+
export interface PaneIdentity {
|
|
308
|
+
agent: string;
|
|
309
|
+
/** Exact session id when resolvable (launch registry, or the hook join). */
|
|
310
|
+
sessionId?: string;
|
|
311
|
+
/** The agent's OS pid from the launch registry (may differ from `pane_pid`). */
|
|
312
|
+
pid?: number;
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Attribute a single tmux pane to the agent actually running in it.
|
|
316
|
+
*
|
|
317
|
+
* The launch registry — written per bare-spawn AND per wrap, each stamped with the
|
|
318
|
+
* `tmuxPane` it targeted (see src/lib/exec.ts) — is the EXACT, per-pane source of
|
|
319
|
+
* truth. So an agent spawned into an EXISTING pane (a split, where `$TMUX` is
|
|
320
|
+
* already set so no new session meta is stamped) is attributed to its OWN launch,
|
|
321
|
+
* not the session's original agent — closing the gap where such an agent was
|
|
322
|
+
* dropped by this source and left to the weaker ps-scan fallback. Session-meta
|
|
323
|
+
* labels remain the fallback for the wrapped origin pane of a session whose
|
|
324
|
+
* registry entry is absent (a failed best-effort write, or a legacy session that
|
|
325
|
+
* predates the registry's `tmuxPane` field) — and ONLY for that origin pane
|
|
326
|
+
* (`meta.pane`), so a split shell pane of a labeled session isn't mis-attributed
|
|
327
|
+
* the wrapped agent. When `meta.pane` is unknown (attach-existing sessions), any
|
|
328
|
+
* labeled pane is accepted and the caller's per-session dedupe keeps one.
|
|
329
|
+
* `source: 'teams'` panes are skipped — teammates are surfaced by listTeamsActive.
|
|
330
|
+
* Pure so it is unit-tested without tmux.
|
|
331
|
+
*/
|
|
332
|
+
export declare function resolvePaneIdentity(pane: string, meta: {
|
|
333
|
+
labels?: Record<string, string>;
|
|
334
|
+
source?: string;
|
|
335
|
+
pane?: string;
|
|
336
|
+
} | null, liveEntry: PidSessionEntry | undefined, getHookIndex: () => HookSessionIndex): PaneIdentity | undefined;
|
|
239
337
|
/**
|
|
240
338
|
* Agents hosted in the shared-socket tmux server — the authoritative source for
|
|
241
|
-
* tmux-
|
|
242
|
-
* every pane on the shared socket and
|
|
243
|
-
*
|
|
244
|
-
*
|
|
245
|
-
*
|
|
246
|
-
*
|
|
339
|
+
* tmux-hosted interactive spawns (see src/lib/exec.ts `runInTmux`). Enumerates
|
|
340
|
+
* every pane on the shared socket and attributes each to the agent running in it
|
|
341
|
+
* via {@link resolvePaneIdentity}: the per-pane launch registry (exact) first, the
|
|
342
|
+
* session-meta labels as fallback. Because tmux (not a per-window
|
|
343
|
+
* `live-terminals.json`) is the source of truth, a tmux-hosted agent is captured
|
|
344
|
+
* with its exact `%pane` even when the extension registry is stale — INCLUDING an
|
|
345
|
+
* agent bare-spawned into a split of an existing session, which older logic dropped
|
|
346
|
+
* (it kept only the first pane per session meta). `source: 'teams'` is skipped.
|
|
247
347
|
*/
|
|
248
348
|
export declare function listTmuxAgentSessions(): Promise<ActiveSession[]>;
|
|
249
349
|
/**
|
|
@@ -254,4 +354,21 @@ export declare function listTmuxAgentSessions(): Promise<ActiveSession[]>;
|
|
|
254
354
|
* terminal/headless row for the same session id.
|
|
255
355
|
*/
|
|
256
356
|
export declare function getActiveSessions(opts?: ActiveQueryOptions): Promise<ActiveSession[]>;
|
|
357
|
+
/**
|
|
358
|
+
* Match an SSH client IP to a registered device (pure — testable with a plain
|
|
359
|
+
* registry object). Returns the device name + ssh login user when the IP is a
|
|
360
|
+
* known device address.
|
|
361
|
+
*/
|
|
362
|
+
export declare function matchOriginDevice(clientIp: string, reg: DeviceRegistry): {
|
|
363
|
+
device: string;
|
|
364
|
+
user?: string;
|
|
365
|
+
} | undefined;
|
|
366
|
+
/**
|
|
367
|
+
* Collapse rows that resolve to the *same* session — a session with many
|
|
368
|
+
* subagent/fork PIDs (all matched to one transcript file) would otherwise print
|
|
369
|
+
* dozens of identical rows. Keyed by session id, falling back to the transcript
|
|
370
|
+
* file, then the cloud/run handle, then {@link anonymousWorkerKey}. The first row
|
|
371
|
+
* wins and carries a `pidCount`.
|
|
372
|
+
*/
|
|
373
|
+
export declare function dedupeBySession(sessions: ActiveSession[]): ActiveSession[];
|
|
257
374
|
export {};
|