@phnx-labs/agents-cli 1.22.42 → 1.22.44
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 +149 -0
- package/README.md +15 -13
- package/dist/bootstrap.js +33 -13
- package/dist/cli/command-registry.d.ts +0 -8
- package/dist/cli/command-registry.js +1 -25
- package/dist/commands/alias.d.ts +7 -4
- package/dist/commands/alias.js +33 -8
- package/dist/commands/apply.d.ts +7 -10
- package/dist/commands/apply.js +15 -35
- package/dist/commands/artifacts.js +4 -5
- package/dist/commands/audit.d.ts +6 -6
- package/dist/commands/audit.js +12 -12
- package/dist/commands/auth.js +14 -6
- package/dist/commands/beta.d.ts +7 -1
- package/dist/commands/beta.js +16 -9
- package/dist/commands/commands.js +1 -1
- package/dist/commands/computer.js +20 -6
- package/dist/commands/daemon.js +1 -1
- package/dist/commands/doctor.d.ts +4 -2
- package/dist/commands/doctor.js +21 -9
- package/dist/commands/events.d.ts +2 -2
- package/dist/commands/events.js +6 -5
- package/dist/commands/exec.d.ts +1 -1
- package/dist/commands/exec.js +11 -6
- package/dist/commands/factory.d.ts +1 -1
- package/dist/commands/feed.js +1 -30
- package/dist/commands/fleet-capture.d.ts +1 -1
- package/dist/commands/fleet-capture.js +4 -5
- package/dist/commands/harness.js +4 -52
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/insights.d.ts +1 -1
- package/dist/commands/insights.js +3 -2
- package/dist/commands/menubar.js +58 -1
- package/dist/commands/monitors.js +1 -1
- package/dist/commands/org.d.ts +5 -0
- package/dist/commands/org.js +83 -29
- package/dist/commands/output.js +2 -2
- package/dist/commands/profiles.js +2 -2
- package/dist/commands/prune.js +5 -4
- package/dist/commands/routines.js +43 -25
- package/dist/commands/routines.test-fixture.d.ts +86 -0
- package/dist/commands/routines.test-fixture.js +345 -0
- package/dist/commands/sessions-picker.js +124 -122
- package/dist/commands/sessions.test-fixture.d.ts +24 -0
- package/dist/commands/sessions.test-fixture.js +224 -0
- package/dist/commands/setup.js +9 -1
- package/dist/commands/share.d.ts +9 -10
- package/dist/commands/share.js +68 -50
- package/dist/commands/skills.js +1 -1
- package/dist/commands/snapshot.d.ts +1 -1
- package/dist/commands/snapshot.js +4 -4
- package/dist/commands/ssh.js +15 -62
- package/dist/commands/status.d.ts +4 -2
- package/dist/commands/status.js +10 -7
- package/dist/commands/subagents.js +1 -1
- package/dist/commands/sync.d.ts +1 -0
- package/dist/commands/sync.js +29 -2
- package/dist/commands/view.js +11 -2
- package/dist/commands/webhook.js +1 -1
- package/dist/lib/accounting/rotate.d.ts +5 -3
- package/dist/lib/accounting/rotate.js +36 -7
- package/dist/lib/accounting/usage.d.ts +18 -4
- package/dist/lib/accounting/usage.js +138 -27
- package/dist/lib/agent-spec/agents.d.ts +7 -7
- package/dist/lib/agent-spec/agents.js +15 -15
- package/dist/lib/analytics/mix-commands.d.ts +6 -28
- package/dist/lib/analytics/mix-commands.js +14 -40
- package/dist/lib/audit/log.d.ts +2 -2
- package/dist/lib/audit/log.js +2 -2
- package/dist/lib/beta.js +1 -1
- package/dist/lib/browser/domain-skills.d.ts +26 -6
- package/dist/lib/browser/domain-skills.js +81 -43
- package/dist/lib/cloud/rush.d.ts +0 -15
- package/dist/lib/cloud/rush.js +0 -35
- package/dist/lib/crabbox/runtimes.d.ts +6 -2
- package/dist/lib/crabbox/runtimes.js +21 -5
- package/dist/lib/daemon/daemon.js +97 -58
- package/dist/lib/daemon/daemon.test-fixture.d.ts +24 -0
- package/dist/lib/daemon/daemon.test-fixture.js +71 -0
- package/dist/lib/daemon/runner.d.ts +18 -1
- package/dist/lib/daemon/runner.js +105 -11
- package/dist/lib/daemon-ticks.d.ts +38 -1
- package/dist/lib/daemon-ticks.js +52 -5
- package/dist/lib/device-config.js +1 -2
- package/dist/lib/devices/discovery-policy.d.ts +3 -3
- package/dist/lib/devices/discovery-policy.js +3 -3
- package/dist/lib/devices/doctor-findings.js +1 -1
- package/dist/lib/devices/fleet.d.ts +4 -8
- package/dist/lib/devices/fleet.js +3 -15
- package/dist/lib/devices/health-report.js +4 -4
- package/dist/lib/devices/pool.d.ts +0 -6
- package/dist/lib/devices/pool.js +0 -6
- package/dist/lib/devices/registry.d.ts +0 -15
- package/dist/lib/devices/registry.js +0 -9
- package/dist/lib/devices/stats-cache.d.ts +12 -0
- package/dist/lib/devices/stats-cache.js +24 -5
- package/dist/lib/drift-sync.d.ts +1 -1
- package/dist/lib/drift-sync.js +2 -2
- package/dist/lib/drift.d.ts +1 -1
- package/dist/lib/exec.js +13 -3
- package/dist/lib/fleet/capture.d.ts +1 -1
- package/dist/lib/fleet/manifest.js +1 -1
- package/dist/lib/fleet/remote-login.d.ts +2 -2
- package/dist/lib/fleet/remote-login.js +3 -4
- package/dist/lib/format.d.ts +9 -0
- package/dist/lib/format.js +16 -0
- package/dist/lib/github/pr-mergeable.d.ts +49 -0
- package/dist/lib/github/pr-mergeable.js +157 -0
- package/dist/lib/github/pr-verdict.d.ts +67 -0
- package/dist/lib/github/pr-verdict.js +72 -0
- package/dist/lib/harness/adapter.d.ts +6 -5
- package/dist/lib/hosts/dispatch.d.ts +2 -0
- package/dist/lib/hosts/dispatch.js +8 -1
- package/dist/lib/hosts/passthrough.d.ts +10 -0
- package/dist/lib/hosts/passthrough.js +28 -7
- package/dist/lib/hosts/providers/devices.js +1 -13
- package/dist/lib/hosts/ready.d.ts +12 -3
- package/dist/lib/hosts/ready.js +27 -12
- package/dist/lib/hosts/registry.d.ts +4 -5
- package/dist/lib/hosts/registry.js +3 -7
- package/dist/lib/hosts/session-index.js +1 -1
- package/dist/lib/installations/shims.js +1 -1
- package/dist/lib/installations/versions.d.ts +40 -0
- package/dist/lib/installations/versions.js +78 -4
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +1 -5
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +2 -15
- package/dist/lib/menubar/install-menubar.d.ts +109 -0
- package/dist/lib/menubar/install-menubar.js +218 -12
- package/dist/lib/monitors/config.d.ts +2 -2
- package/dist/lib/monitors/config.js +3 -2
- package/dist/lib/origin-machine.d.ts +18 -0
- package/dist/lib/origin-machine.js +34 -0
- package/dist/lib/perf/db.js +1 -1
- package/dist/lib/perf/spool.js +1 -1
- package/dist/lib/prix-account.d.ts +2 -1
- package/dist/lib/prix-account.js +2 -1
- package/dist/lib/profiles.d.ts +7 -0
- package/dist/lib/profiles.js +26 -1
- package/dist/lib/remote-agents-json.js +1 -7
- package/dist/lib/routines-placement.d.ts +1 -1
- package/dist/lib/routines-placement.js +1 -1
- package/dist/lib/sandbox.d.ts +24 -0
- package/dist/lib/sandbox.js +101 -0
- package/dist/lib/scheduling/routines.d.ts +18 -9
- package/dist/lib/scheduling/routines.js +16 -8
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -2
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +1 -13
- package/dist/lib/secrets/agent.js +9 -1
- package/dist/lib/secrets/index.js +1 -1
- package/dist/lib/secrets/list-filter.js +1 -1
- package/dist/lib/service-manifest.d.ts +20 -0
- package/dist/lib/service-manifest.js +34 -0
- package/dist/lib/session/active.d.ts +4 -16
- package/dist/lib/session/active.js +2 -6
- package/dist/lib/session/cloud.js +1 -1
- package/dist/lib/session/db.d.ts +13 -98
- package/dist/lib/session/db.js +5 -12
- package/dist/lib/session/discover.d.ts +5 -81
- package/dist/lib/session/discover.js +5 -5
- package/dist/lib/session/fork.js +1 -1
- package/dist/lib/session/live-metadata.js +1 -1
- package/dist/lib/session/origin-machine.d.ts +1 -18
- package/dist/lib/session/origin-machine.js +4 -34
- package/dist/lib/session/relative-time.d.ts +1 -44
- package/dist/lib/session/relative-time.js +4 -120
- package/dist/lib/session/remote/remote-bundle.d.ts +12 -0
- package/dist/lib/session/remote/remote-bundle.js +61 -0
- package/dist/lib/session/remote/remote-list.d.ts +148 -0
- package/dist/lib/session/remote/remote-list.js +607 -0
- package/dist/lib/session/remote/remote.d.ts +132 -0
- package/dist/lib/session/remote/remote.js +314 -0
- package/dist/lib/session/remote/watch.d.ts +101 -0
- package/dist/lib/session/remote/watch.js +241 -0
- package/dist/lib/session/remote-bundle.d.ts +1 -12
- package/dist/lib/session/remote-bundle.js +3 -61
- package/dist/lib/session/remote-list.d.ts +1 -148
- package/dist/lib/session/remote-list.js +3 -607
- package/dist/lib/session/remote.d.ts +1 -132
- package/dist/lib/session/remote.js +3 -314
- package/dist/lib/session/short-id.d.ts +1 -17
- package/dist/lib/session/short-id.js +4 -20
- package/dist/lib/session/watch.d.ts +1 -101
- package/dist/lib/session/watch.js +3 -242
- package/dist/lib/session/width.d.ts +1 -29
- package/dist/lib/session/width.js +4 -101
- package/dist/lib/share/config.d.ts +12 -2
- package/dist/lib/share/config.js +47 -11
- package/dist/lib/share/delete.js +1 -1
- package/dist/lib/share/publish.js +1 -1
- package/dist/lib/share/worker-template.js +2 -2
- package/dist/lib/smart-launch.d.ts +4 -4
- package/dist/lib/smart-launch.js +8 -18
- package/dist/lib/snapshot.d.ts +2 -2
- package/dist/lib/snapshot.js +1 -1
- package/dist/lib/staleness/index.d.ts +3 -1
- package/dist/lib/staleness/index.js +21 -1
- package/dist/lib/staleness/types.d.ts +11 -0
- package/dist/lib/staleness/writers/commands.js +13 -4
- package/dist/lib/staleness/writers/hooks.js +3 -1
- package/dist/lib/staleness/writers/mcp.d.ts +0 -7
- package/dist/lib/staleness/writers/mcp.js +16 -1
- package/dist/lib/staleness/writers/rules.js +1 -1
- package/dist/lib/staleness/writers/skills.js +3 -1
- package/dist/lib/staleness/writers/subagents.d.ts +0 -9
- package/dist/lib/staleness/writers/subagents.js +18 -1
- package/dist/lib/staleness/writers/types.d.ts +10 -0
- package/dist/lib/startup/command-registry.d.ts +10 -1
- package/dist/lib/startup/command-registry.js +26 -7
- package/dist/lib/startup/root-command.d.ts +18 -1
- package/dist/lib/startup/root-command.js +18 -1
- package/dist/lib/state.js +7 -0
- package/dist/lib/teams/placement-probe.js +28 -13
- package/dist/lib/teams/scheduler.d.ts +3 -1
- package/dist/lib/teams/scheduler.js +1 -1
- package/dist/lib/text/relative-time.d.ts +44 -0
- package/dist/lib/text/relative-time.js +120 -0
- package/dist/lib/text/short-id.d.ts +17 -0
- package/dist/lib/text/short-id.js +20 -0
- package/dist/lib/text/width.d.ts +29 -0
- package/dist/lib/text/width.js +101 -0
- package/dist/lib/triggers/handlers.d.ts +7 -0
- package/dist/lib/triggers/handlers.js +8 -0
- package/dist/lib/triggers/webhook.d.ts +1 -0
- package/dist/lib/triggers/webhook.js +2 -1
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/view-types.d.ts +7 -0
- package/package.json +2 -3
- package/dist/bin/agents +0 -0
- package/dist/commands/serve.d.ts +0 -10
- package/dist/commands/serve.js +0 -68
- package/dist/commands/tickets.d.ts +0 -2
- package/dist/commands/tickets.js +0 -43
- package/dist/commands/trends.d.ts +0 -10
- package/dist/commands/trends.js +0 -12
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/observe-aliases.d.ts +0 -30
- package/dist/lib/observe-aliases.js +0 -38
- package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/serve/control.d.ts +0 -95
- package/dist/lib/serve/control.js +0 -260
- package/dist/lib/serve/data.d.ts +0 -81
- package/dist/lib/serve/data.js +0 -91
- package/dist/lib/serve/page.d.ts +0 -7
- package/dist/lib/serve/page.js +0 -140
- package/dist/lib/serve/server.d.ts +0 -80
- package/dist/lib/serve/server.js +0 -145
- package/dist/lib/serve/stream.d.ts +0 -43
- package/dist/lib/serve/stream.js +0 -116
- package/dist/lib/serve/token.d.ts +0 -35
- package/dist/lib/serve/token.js +0 -85
- package/dist/lib/tickets/list.d.ts +0 -53
- package/dist/lib/tickets/list.js +0 -153
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
*
|
|
5
5
|
* - `buildManifest(agent, version, cwd)` — snapshot current state.
|
|
6
6
|
* - `isStale(manifest, agent, version, cwd)` — true when any tracked
|
|
7
|
-
* resource has drifted from its stored fingerprint
|
|
7
|
+
* resource has drifted from its stored fingerprint, or when an artifact
|
|
8
|
+
* the last full sync wrote (`writtenTargets`) has been deleted from the
|
|
9
|
+
* version home (#2398).
|
|
8
10
|
*
|
|
9
11
|
* `loadManifest` / `saveManifest` round-trip the on-disk JSON. The format
|
|
10
12
|
* version stays at 1; new optional fields (workflows, plugins) on old files
|
|
@@ -91,6 +93,12 @@ export function buildManifest(agent, version, cwd, previous) {
|
|
|
91
93
|
subagents: {},
|
|
92
94
|
workflows: {},
|
|
93
95
|
plugins: {},
|
|
96
|
+
// Empty baseline ("nothing recorded to verify"). The full-sync
|
|
97
|
+
// orchestrator (versions.ts) replaces this with the writer-reported
|
|
98
|
+
// artifact paths right before saving; a manifest built outside that path
|
|
99
|
+
// simply verifies nothing. Only an ABSENT field (a pre-upgrade manifest
|
|
100
|
+
// on disk) forces the one-time migration re-sync in isStale.
|
|
101
|
+
writtenTargets: [],
|
|
94
102
|
};
|
|
95
103
|
for (const { checker, field } of STANDARD_CHECKERS) {
|
|
96
104
|
const target = manifest[field];
|
|
@@ -143,5 +151,17 @@ export function isStale(manifest, agent, version, cwd) {
|
|
|
143
151
|
return true;
|
|
144
152
|
if (isRulesStale(manifest.rules, agent, version, cwd))
|
|
145
153
|
return true;
|
|
154
|
+
// Home-side deletion check (#2398): every artifact the last full sync wrote
|
|
155
|
+
// must still exist, or the version home has rotted and needs a re-sync —
|
|
156
|
+
// regardless of source fingerprints. One existsSync per path, no content
|
|
157
|
+
// reads, so the fast-guard budget holds (RUSH-2320). A manifest that
|
|
158
|
+
// predates the field reads as stale once so the next full sync records the
|
|
159
|
+
// baseline (same precedent as the optional workflows/plugins maps).
|
|
160
|
+
if (manifest.writtenTargets === undefined)
|
|
161
|
+
return true;
|
|
162
|
+
for (const target of manifest.writtenTargets) {
|
|
163
|
+
if (!fs.existsSync(target))
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
146
166
|
return false;
|
|
147
167
|
}
|
|
@@ -54,4 +54,15 @@ export interface SyncManifest {
|
|
|
54
54
|
subagents: Record<string, DirEntry>;
|
|
55
55
|
workflows?: Record<string, DirEntry>;
|
|
56
56
|
plugins?: Record<string, PluginEntry>;
|
|
57
|
+
/**
|
|
58
|
+
* Absolute paths of the artifacts the last full sync materialized in the
|
|
59
|
+
* version home (writer-reported — see `WriteResult.paths`). `isStale`
|
|
60
|
+
* treats a missing path as stale so a deleted resource is restored by a
|
|
61
|
+
* plain `agents sync`, not only `--force` (#2398). An absent field means a
|
|
62
|
+
* pre-upgrade manifest: it reads as stale once, and the resulting full sync
|
|
63
|
+
* establishes the baseline — same migration precedent as the optional
|
|
64
|
+
* `workflows`/`plugins` maps above. An empty array is a valid baseline
|
|
65
|
+
* ("nothing recorded to verify"), never a migration trigger.
|
|
66
|
+
*/
|
|
67
|
+
writtenTargets?: string[];
|
|
57
68
|
}
|
|
@@ -25,7 +25,7 @@ import { supports } from '../../capabilities.js';
|
|
|
25
25
|
import { safeJoin } from '../../paths.js';
|
|
26
26
|
import { markdownToToml } from '../../convert.js';
|
|
27
27
|
import { commandAppliesTo, parseCommandMetadata } from '../../commands.js';
|
|
28
|
-
import { installCommandSkillToVersion, listCommandSkillsInVersion, removeCommandSkillFromVersion, shouldAlsoInstallCommandAsSkill, shouldInstallCommandAsSkill, } from '../../command-skills.js';
|
|
28
|
+
import { commandSkillName, installCommandSkillToVersion, listCommandSkillsInVersion, removeCommandSkillFromVersion, shouldAlsoInstallCommandAsSkill, shouldInstallCommandAsSkill, } from '../../command-skills.js';
|
|
29
29
|
import { installGooseCommandToVersion, listGooseCommandsInVersion, removeGooseCommandFromVersion, } from '../../goose-commands.js';
|
|
30
30
|
import { resolveCommandSource, trustedSkillRoots } from './sources.js';
|
|
31
31
|
import { lazyAgentMap } from './lazy-map.js';
|
|
@@ -50,6 +50,7 @@ function buildCommandsWriter(agent) {
|
|
|
50
50
|
fs.mkdirSync(commandsTarget, { recursive: true });
|
|
51
51
|
}
|
|
52
52
|
const synced = [];
|
|
53
|
+
const paths = [];
|
|
53
54
|
for (const cmd of selection) {
|
|
54
55
|
const srcFile = resolveCommandSource(cmd);
|
|
55
56
|
if (!srcFile)
|
|
@@ -63,9 +64,13 @@ function buildCommandsWriter(agent) {
|
|
|
63
64
|
// which is a deliberate no-op, not a failure — the native file is still written.
|
|
64
65
|
if (!installed.success)
|
|
65
66
|
continue;
|
|
67
|
+
if (!installed.skipped) {
|
|
68
|
+
paths.push(safeJoin(path.join(agentDir, 'skills'), commandSkillName(cmd)));
|
|
69
|
+
}
|
|
66
70
|
}
|
|
67
71
|
if (supportsCommands && agent === 'goose') {
|
|
68
72
|
// Goose: recipe YAML + config.yaml slash_commands entry, not a file copy.
|
|
73
|
+
// No artifact path recorded — the recipe layout lives in goose-commands.ts.
|
|
69
74
|
const installed = installGooseCommandToVersion(versionHome, cmd, srcFile);
|
|
70
75
|
if (!installed.success)
|
|
71
76
|
continue;
|
|
@@ -73,14 +78,18 @@ function buildCommandsWriter(agent) {
|
|
|
73
78
|
else if (supportsCommands && agentConfig.format === 'toml') {
|
|
74
79
|
const content = fs.readFileSync(srcFile, 'utf-8');
|
|
75
80
|
const tomlContent = markdownToToml(cmd, content);
|
|
76
|
-
|
|
81
|
+
const dest = safeJoin(commandsTarget, `${cmd}.toml`);
|
|
82
|
+
fs.writeFileSync(dest, tomlContent);
|
|
83
|
+
paths.push(dest);
|
|
77
84
|
}
|
|
78
85
|
else if (supportsCommands) {
|
|
79
|
-
|
|
86
|
+
const dest = safeJoin(commandsTarget, `${cmd}.md`);
|
|
87
|
+
fs.copyFileSync(srcFile, dest);
|
|
88
|
+
paths.push(dest);
|
|
80
89
|
}
|
|
81
90
|
synced.push(cmd);
|
|
82
91
|
}
|
|
83
|
-
return { synced };
|
|
92
|
+
return { synced, paths };
|
|
84
93
|
},
|
|
85
94
|
remove({ versionHome, name }) {
|
|
86
95
|
const agentConfig = AGENTS[agent];
|
|
@@ -75,6 +75,7 @@ function buildHooksWriter(agent) {
|
|
|
75
75
|
const hooksTarget = path.join(agentDir, 'hooks');
|
|
76
76
|
fs.mkdirSync(hooksTarget, { recursive: true });
|
|
77
77
|
const synced = [];
|
|
78
|
+
const paths = [];
|
|
78
79
|
for (const hook of selection) {
|
|
79
80
|
const srcFile = resolveHookSource(hook);
|
|
80
81
|
if (!srcFile)
|
|
@@ -82,6 +83,7 @@ function buildHooksWriter(agent) {
|
|
|
82
83
|
const destFile = safeJoin(hooksTarget, hook);
|
|
83
84
|
if (copyHookSource(srcFile, destFile)) {
|
|
84
85
|
synced.push(hook);
|
|
86
|
+
paths.push(destFile);
|
|
85
87
|
}
|
|
86
88
|
}
|
|
87
89
|
// Native hook registration in settings.json/hooks.json. Grok is included
|
|
@@ -93,7 +95,7 @@ function buildHooksWriter(agent) {
|
|
|
93
95
|
if (agent === 'claude' || agent === 'codex' || agent === 'antigravity' || agent === 'kimi' || agent === 'droid' || agent === 'copilot' || agent === 'kiro' || agent === 'goose' || agent === 'cursor' || agent === 'grok' || agent === 'hermes' || agent === 'muse') {
|
|
94
96
|
registerHooksToSettings(agent, versionHome);
|
|
95
97
|
}
|
|
96
|
-
return { synced };
|
|
98
|
+
return { synced, paths };
|
|
97
99
|
},
|
|
98
100
|
remove({ versionHome, name }) {
|
|
99
101
|
// Delete the copied hook artifact from `{agentDir}/hooks/<name>`. Native
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP writer — thin dispatcher into `installMcpServers` from `lib/mcp.ts`.
|
|
3
|
-
*
|
|
4
|
-
* The per-agent format handling (Claude CLI, Codex TOML, Cursor JSON, etc.)
|
|
5
|
-
* lives in lib/mcp.ts; we keep it there to avoid the import cycle with
|
|
6
|
-
* `versions.ts`. The writer simply hands the selection to that function.
|
|
7
|
-
*/
|
|
8
1
|
import type { AgentId } from '../../types.js';
|
|
9
2
|
import type { ResourceWriter } from './types.js';
|
|
10
3
|
export declare const mcpWriters: Partial<Record<AgentId, ResourceWriter<string[]>>>;
|
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP writer — thin dispatcher into `installMcpServers` from `lib/mcp.ts`.
|
|
3
|
+
*
|
|
4
|
+
* The per-agent format handling (Claude CLI, Codex TOML, Cursor JSON, etc.)
|
|
5
|
+
* lives in lib/mcp.ts; we keep it there to avoid the import cycle with
|
|
6
|
+
* `versions.ts`. The writer simply hands the selection to that function.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs';
|
|
1
9
|
import { capableAgents } from '../../capabilities.js';
|
|
2
10
|
import { installMcpServers } from '../../mcp.js';
|
|
11
|
+
import { getMcpConfigPathForHome } from '../../agents.js';
|
|
3
12
|
import { lazyAgentMap } from './lazy-map.js';
|
|
4
13
|
function buildMcpWriter(agent) {
|
|
5
14
|
return {
|
|
@@ -9,7 +18,13 @@ function buildMcpWriter(agent) {
|
|
|
9
18
|
const r = installMcpServers(agent, version, versionHome, selection, { cwd });
|
|
10
19
|
// Forward r.errors: dropping them is what let a harness with no config
|
|
11
20
|
// writer report a clean sync while writing nothing (RUSH-2677).
|
|
12
|
-
|
|
21
|
+
// All applied servers land in the one canonical config file — that file
|
|
22
|
+
// is the artifact whose deletion must read as stale (#2398). Recorded
|
|
23
|
+
// only when it verifiably exists after the write, so an agent whose CLI
|
|
24
|
+
// wrote elsewhere can never produce a perpetually-stale manifest.
|
|
25
|
+
const configPath = getMcpConfigPathForHome(agent, versionHome);
|
|
26
|
+
const paths = r.applied.length > 0 && fs.existsSync(configPath) ? [configPath] : [];
|
|
27
|
+
return { synced: r.applied, paths, ...(r.errors.length ? { errors: r.errors } : {}) };
|
|
13
28
|
},
|
|
14
29
|
};
|
|
15
30
|
}
|
|
@@ -56,6 +56,7 @@ function buildSkillsWriter(agent) {
|
|
|
56
56
|
catch { /* does not exist yet */ }
|
|
57
57
|
fs.mkdirSync(skillsTarget, { recursive: true });
|
|
58
58
|
const synced = [];
|
|
59
|
+
const paths = [];
|
|
59
60
|
for (const skill of selection) {
|
|
60
61
|
const srcDir = resolveSkillSource(skill, { agent });
|
|
61
62
|
if (!srcDir)
|
|
@@ -64,8 +65,9 @@ function buildSkillsWriter(agent) {
|
|
|
64
65
|
removePath(destDir);
|
|
65
66
|
copyDir(srcDir, destDir);
|
|
66
67
|
synced.push(skill);
|
|
68
|
+
paths.push(destDir);
|
|
67
69
|
}
|
|
68
|
-
return { synced };
|
|
70
|
+
return { synced, paths };
|
|
69
71
|
},
|
|
70
72
|
remove({ versionHome, name }) {
|
|
71
73
|
const agentDir = path.join(versionHome, agentConfigDirName(agent));
|
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Subagents writer. Every agent's on-disk layout (target dir, file/dir shape,
|
|
3
|
-
* transform) is declared once in the subagent registry; this writer is generic
|
|
4
|
-
* and iterates the registry instead of a per-agent `else if` chain.
|
|
5
|
-
*
|
|
6
|
-
* Source-side discovery is `listInstalledSubagents` from lib/subagents.ts —
|
|
7
|
-
* it reads user + system layers only (project layer excluded for the same
|
|
8
|
-
* defense as commands/skills/hooks).
|
|
9
|
-
*/
|
|
10
1
|
import type { AgentId } from '../../types.js';
|
|
11
2
|
import type { ResourceWriter } from './types.js';
|
|
12
3
|
export declare const subagentsWriters: Partial<Record<AgentId, ResourceWriter<string[]>>>;
|
|
@@ -1,3 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subagents writer. Every agent's on-disk layout (target dir, file/dir shape,
|
|
3
|
+
* transform) is declared once in the subagent registry; this writer is generic
|
|
4
|
+
* and iterates the registry instead of a per-agent `else if` chain.
|
|
5
|
+
*
|
|
6
|
+
* Source-side discovery is `listInstalledSubagents` from lib/subagents.ts —
|
|
7
|
+
* it reads user + system layers only (project layer excluded for the same
|
|
8
|
+
* defense as commands/skills/hooks).
|
|
9
|
+
*/
|
|
10
|
+
import * as fs from 'fs';
|
|
1
11
|
import { capableAgents } from '../../capabilities.js';
|
|
2
12
|
import { listInstalledSubagents } from '../../subagents.js';
|
|
3
13
|
import { subagentTarget } from '../../subagents-registry.js';
|
|
@@ -14,6 +24,7 @@ function buildSubagentsWriter(agent) {
|
|
|
14
24
|
const map = new Map(all.map(s => [s.name, s]));
|
|
15
25
|
const dir = target.dir(versionHome);
|
|
16
26
|
const synced = [];
|
|
27
|
+
const paths = [];
|
|
17
28
|
for (const name of selection) {
|
|
18
29
|
const sub = map.get(name);
|
|
19
30
|
if (!sub)
|
|
@@ -21,10 +32,16 @@ function buildSubagentsWriter(agent) {
|
|
|
21
32
|
try {
|
|
22
33
|
target.write(dir, sub);
|
|
23
34
|
synced.push(sub.name);
|
|
35
|
+
// The registry owns the layout — record the artifact paths this
|
|
36
|
+
// write occupies so a later deletion reads as stale (#2398).
|
|
37
|
+
for (const entry of target.occupied(dir, sub.name)) {
|
|
38
|
+
if (fs.existsSync(entry.path))
|
|
39
|
+
paths.push(entry.path);
|
|
40
|
+
}
|
|
24
41
|
}
|
|
25
42
|
catch { /* per-item sync failure: skip */ }
|
|
26
43
|
}
|
|
27
|
-
return { synced };
|
|
44
|
+
return { synced, paths };
|
|
28
45
|
},
|
|
29
46
|
};
|
|
30
47
|
}
|
|
@@ -28,6 +28,16 @@ export interface WriteArgs<Sel> {
|
|
|
28
28
|
export interface WriteResult {
|
|
29
29
|
/** Names actually written. Empty array = write produced nothing (not an error). */
|
|
30
30
|
synced: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Absolute on-disk paths of the artifacts this write materialized (a file or
|
|
33
|
+
* a dir root per resource, per the agent's layout). Recorded into the sync
|
|
34
|
+
* manifest as `writtenTargets` so `isStale` can flag a deleted artifact as
|
|
35
|
+
* stale with one existsSync per path (#2398) — no content reads, keeping the
|
|
36
|
+
* fast-guard budget (RUSH-2320). Optional: a writer whose artifact path is
|
|
37
|
+
* not cheaply known (goose recipe YAML, plugins) may omit entries; absence
|
|
38
|
+
* means "not verified", never a false stale.
|
|
39
|
+
*/
|
|
40
|
+
paths?: string[];
|
|
31
41
|
/**
|
|
32
42
|
* Per-item failures the writer could not complete, as user-facing sentences.
|
|
33
43
|
*
|
|
@@ -21,7 +21,16 @@ export declare const KNOWN_TOP_LEVEL_COMMANDS: ReadonlySet<string>;
|
|
|
21
21
|
* under `agents artifacts share` (RUSH-2580). login/logout/budget/bench/mine/
|
|
22
22
|
* cost/output/profiles/snapshot/cp/resume/roster moved under nested homes
|
|
23
23
|
* (cli-surface-consolidate). `timeline` was removed as a duplicated surface —
|
|
24
|
-
* use `agents feed --filter updates` (RUSH-2692).
|
|
24
|
+
* use `agents feed --filter updates` (RUSH-2692). `status` moved under
|
|
25
|
+
* `agents sync status` (RUSH-2864). `tickets` was removed — use `linear`
|
|
26
|
+
* (linear-cli) (RUSH-2932). `alias` moved under `agents setup alias` (RUSH-2965).
|
|
27
|
+
* `inbox` was a pure alias of `agents feed` (RUSH-2984). `unshare` nested under
|
|
28
|
+
* `agents artifacts unshare` (RUSH-2989). `audit` nested under `agents events audit`.
|
|
29
|
+
* `trends` nested under `agents insights mix` / `insights trends`. `serve` (the
|
|
30
|
+
* read-only local web companion + `--control` anchor) was removed with the
|
|
31
|
+
* unshipped iOS Fleet Cockpit it existed for (RUSH-3001). `apply` nested under
|
|
32
|
+
* `agents fleet apply` / `agents devices apply`. `beta` nested under
|
|
33
|
+
* `agents setup beta` (RUSH-2981).
|
|
25
34
|
*/
|
|
26
35
|
export declare const RETIRED_TOP_LEVEL_COMMANDS: ReadonlySet<string>;
|
|
27
36
|
export declare function isKnownTopLevelCommand(name: string): boolean;
|
|
@@ -3,13 +3,13 @@ const LOADED_COMMAND_NAMES = [
|
|
|
3
3
|
'permissions', 'mcp', 'clis', 'subagents', 'plugins', 'workflows', 'add', 'use', 'list',
|
|
4
4
|
'remove', 'rm', 'purge', 'update', 'prune', 'import', 'registry', 'search', 'install',
|
|
5
5
|
'routines', 'monitors', 'projects', 'run', 'open', 'reconnect', 'fork', 'config',
|
|
6
|
-
'models', 'modes', 'trash', 'restore', 'doctor',
|
|
7
|
-
'route', 'harness', 'harnesses', 'secrets', 'menubar', '
|
|
8
|
-
'refresh-rules', 'factory', 'usage', 'insights', 'perf',
|
|
9
|
-
'
|
|
6
|
+
'models', 'modes', 'trash', 'restore', 'doctor',
|
|
7
|
+
'route', 'harness', 'harnesses', 'secrets', 'menubar', 'sync',
|
|
8
|
+
'refresh-rules', 'factory', 'usage', 'insights', 'perf',
|
|
9
|
+
'pty', 'tmux', 'watchdog', 'browser', 'computer', 'logs', 'events',
|
|
10
10
|
'ssh', 'devices', 'fleet', 'repos', 'repo', 'setup', 'uninstall', 'upgrade', 'sessions',
|
|
11
|
-
'teams', '
|
|
12
|
-
'mailboxes', 'mailbox', '
|
|
11
|
+
'teams', 'cloud', 'message', 'send', 'notify', 'feed',
|
|
12
|
+
'mailboxes', 'mailbox', 'artifacts', 'webhooks',
|
|
13
13
|
'humans', 'daemon',
|
|
14
14
|
];
|
|
15
15
|
const INLINE_COMMAND_NAMES = [
|
|
@@ -41,10 +41,20 @@ export const KNOWN_TOP_LEVEL_COMMANDS = new Set([
|
|
|
41
41
|
* under `agents artifacts share` (RUSH-2580). login/logout/budget/bench/mine/
|
|
42
42
|
* cost/output/profiles/snapshot/cp/resume/roster moved under nested homes
|
|
43
43
|
* (cli-surface-consolidate). `timeline` was removed as a duplicated surface —
|
|
44
|
-
* use `agents feed --filter updates` (RUSH-2692).
|
|
44
|
+
* use `agents feed --filter updates` (RUSH-2692). `status` moved under
|
|
45
|
+
* `agents sync status` (RUSH-2864). `tickets` was removed — use `linear`
|
|
46
|
+
* (linear-cli) (RUSH-2932). `alias` moved under `agents setup alias` (RUSH-2965).
|
|
47
|
+
* `inbox` was a pure alias of `agents feed` (RUSH-2984). `unshare` nested under
|
|
48
|
+
* `agents artifacts unshare` (RUSH-2989). `audit` nested under `agents events audit`.
|
|
49
|
+
* `trends` nested under `agents insights mix` / `insights trends`. `serve` (the
|
|
50
|
+
* read-only local web companion + `--control` anchor) was removed with the
|
|
51
|
+
* unshipped iOS Fleet Cockpit it existed for (RUSH-3001). `apply` nested under
|
|
52
|
+
* `agents fleet apply` / `agents devices apply`. `beta` nested under
|
|
53
|
+
* `agents setup beta` (RUSH-2981).
|
|
45
54
|
*/
|
|
46
55
|
export const RETIRED_TOP_LEVEL_COMMANDS = new Set([
|
|
47
56
|
'webhook',
|
|
57
|
+
'serve',
|
|
48
58
|
'login',
|
|
49
59
|
'logout',
|
|
50
60
|
'budget',
|
|
@@ -60,6 +70,15 @@ export const RETIRED_TOP_LEVEL_COMMANDS = new Set([
|
|
|
60
70
|
'set',
|
|
61
71
|
'share',
|
|
62
72
|
'timeline',
|
|
73
|
+
'status',
|
|
74
|
+
'tickets',
|
|
75
|
+
'alias',
|
|
76
|
+
'inbox',
|
|
77
|
+
'unshare',
|
|
78
|
+
'audit',
|
|
79
|
+
'trends',
|
|
80
|
+
'apply',
|
|
81
|
+
'beta',
|
|
63
82
|
]);
|
|
64
83
|
export function isKnownTopLevelCommand(name) {
|
|
65
84
|
return KNOWN_TOP_LEVEL_COMMANDS.has(name);
|
|
@@ -1,3 +1,20 @@
|
|
|
1
1
|
import type { Command } from 'commander';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Configure the public root surface shared by the live CLI and reference generator.
|
|
4
|
+
*
|
|
5
|
+
* Does NOT call `enablePositionalOptions()` — tried for RUSH-2687 (a subcommand
|
|
6
|
+
* option whose long name collides with an ancestor's is silently dropped at
|
|
7
|
+
* parse time) and reverted. Commander's `copyInheritedSettings()` copies
|
|
8
|
+
* `_enablePositionalOptions` onto every command created via `.command()` from
|
|
9
|
+
* that point on, so setting it here cascades to all ~552 registered commands,
|
|
10
|
+
* not just the root's own scan. That broke a real, load-bearing pattern used
|
|
11
|
+
* elsewhere in the tree: a parent command (e.g. `sessions`, which owns
|
|
12
|
+
* `--since`/`--json`/`--local`) whose LEAF subcommands declare none of their
|
|
13
|
+
* own options and read them back via `command.optsWithGlobals()` (e.g.
|
|
14
|
+
* `sessions backfill tools --since 7d --json --local`) — positional options
|
|
15
|
+
* makes the parent stop scanning at the first subcommand-shaped token, so it
|
|
16
|
+
* never sees the flags typed after it, and the leaf sees `unknown option`
|
|
17
|
+
* instead of a silent drop. RUSH-2687 was fixed per-surface in share.ts
|
|
18
|
+
* instead (renaming the colliding options), not with this global flag.
|
|
19
|
+
*/
|
|
3
20
|
export declare function configureRootCommand(program: Command, name: string, version: string): Command;
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* Configure the public root surface shared by the live CLI and reference generator.
|
|
3
|
+
*
|
|
4
|
+
* Does NOT call `enablePositionalOptions()` — tried for RUSH-2687 (a subcommand
|
|
5
|
+
* option whose long name collides with an ancestor's is silently dropped at
|
|
6
|
+
* parse time) and reverted. Commander's `copyInheritedSettings()` copies
|
|
7
|
+
* `_enablePositionalOptions` onto every command created via `.command()` from
|
|
8
|
+
* that point on, so setting it here cascades to all ~552 registered commands,
|
|
9
|
+
* not just the root's own scan. That broke a real, load-bearing pattern used
|
|
10
|
+
* elsewhere in the tree: a parent command (e.g. `sessions`, which owns
|
|
11
|
+
* `--since`/`--json`/`--local`) whose LEAF subcommands declare none of their
|
|
12
|
+
* own options and read them back via `command.optsWithGlobals()` (e.g.
|
|
13
|
+
* `sessions backfill tools --since 7d --json --local`) — positional options
|
|
14
|
+
* makes the parent stop scanning at the first subcommand-shaped token, so it
|
|
15
|
+
* never sees the flags typed after it, and the leaf sees `unknown option`
|
|
16
|
+
* instead of a silent drop. RUSH-2687 was fixed per-surface in share.ts
|
|
17
|
+
* instead (renaming the colliding options), not with this global flag.
|
|
18
|
+
*/
|
|
2
19
|
export function configureRootCommand(program, name, version) {
|
|
3
20
|
return program
|
|
4
21
|
.name(name)
|
package/dist/lib/state.js
CHANGED
|
@@ -955,6 +955,13 @@ function serializeCentral(central) {
|
|
|
955
955
|
// config data-loss bug). A known device key lingering in the synced file is
|
|
956
956
|
// still removed — it belongs in the per-machine file, not here.
|
|
957
957
|
if (!(k in central) && KNOWN_META_KEYS.has(k)) {
|
|
958
|
+
// RUSH-2837: a partial writeMeta (reconstructed Meta missing `share`)
|
|
959
|
+
// deleted the share endpoint from agents.yaml and synced that deletion
|
|
960
|
+
// fleet-wide. `share` is restored only by setup/join — never drop it
|
|
961
|
+
// just because this write omitted the key. Explicit `share: null` still
|
|
962
|
+
// goes through doc.set above.
|
|
963
|
+
if (k === 'share')
|
|
964
|
+
continue;
|
|
958
965
|
doc.delete(k);
|
|
959
966
|
changed = true;
|
|
960
967
|
}
|
|
@@ -7,9 +7,9 @@
|
|
|
7
7
|
*
|
|
8
8
|
* - reachability + headroom + load ← {@link probeFleetStats} (one parallel
|
|
9
9
|
* SSH fan-out over the pool; the local box is measured directly).
|
|
10
|
-
* - requested agent installed +
|
|
11
|
-
* probe per remote device ({@link buildReadyProbeCommand} →
|
|
12
|
-
* the
|
|
10
|
+
* - requested agent installed + account eligibility (when known) ← a one-shot
|
|
11
|
+
* readiness probe per remote device ({@link buildReadyProbeCommand} →
|
|
12
|
+
* `agents view`), with the same candidate-readiness gate evaluated locally.
|
|
13
13
|
*
|
|
14
14
|
* The result is cached briefly per (pool, agent-or-any) so a `teams start` wave that
|
|
15
15
|
* places N teammates probes the pool ONCE, not N times — the roster-count part
|
|
@@ -25,10 +25,11 @@ import { execFile } from 'child_process';
|
|
|
25
25
|
import { probeFleetStats, headroom } from '../devices/health.js';
|
|
26
26
|
import { loadDevicesSync } from '../devices/registry.js';
|
|
27
27
|
import { buildSshInvocation, writeAskpassShim } from '../devices/connect.js';
|
|
28
|
-
import { buildReadyProbeCommand, parseReadyProbe,
|
|
29
|
-
import {
|
|
28
|
+
import { buildReadyProbeCommand, parseReadyProbe, viewAgentAccountEligibility, viewHasAgent, } from '../hosts/ready.js';
|
|
29
|
+
import { collectRunCandidates, isSignInRecoverable, readinessFromCandidate, } from '../accounting/rotate.js';
|
|
30
|
+
import { localMachineId } from '../origin-machine.js';
|
|
30
31
|
import { normalizeHost } from '../machine-id.js';
|
|
31
|
-
import { checkCliAvailable
|
|
32
|
+
import { checkCliAvailable } from './agents.js';
|
|
32
33
|
/** Per-remote readiness probe budget — matches the health probe's short window
|
|
33
34
|
* (`agents view` on a warm box is sub-second; a wedged one degrades to unknown). */
|
|
34
35
|
export const READY_PROBE_TIMEOUT_MS = 8_000;
|
|
@@ -61,19 +62,22 @@ function probeRemoteReadiness(device, agent) {
|
|
|
61
62
|
({ args, env } = buildSshInvocation(device, [cmd], shim, {}, { agentOnly: true }));
|
|
62
63
|
}
|
|
63
64
|
catch {
|
|
64
|
-
return Promise.resolve({ installed: undefined, signedIn: undefined });
|
|
65
|
+
return Promise.resolve({ installed: undefined, signedIn: undefined, pickerEligible: undefined });
|
|
65
66
|
}
|
|
66
67
|
return new Promise((resolve) => {
|
|
67
68
|
execFile('ssh', args, { encoding: 'utf-8', env: { ...process.env, ...env }, timeout: READY_PROBE_TIMEOUT_MS }, (err, stdout) => {
|
|
68
69
|
if (err || !stdout)
|
|
69
|
-
return resolve({ installed: undefined, signedIn: undefined });
|
|
70
|
+
return resolve({ installed: undefined, signedIn: undefined, pickerEligible: undefined });
|
|
70
71
|
const probe = parseReadyProbe(stdout);
|
|
71
72
|
if (!probe.reachable)
|
|
72
|
-
return resolve({ installed: undefined, signedIn: undefined });
|
|
73
|
+
return resolve({ installed: undefined, signedIn: undefined, pickerEligible: undefined });
|
|
73
74
|
if (!probe.version)
|
|
74
|
-
return resolve({ installed: false, signedIn: false });
|
|
75
|
+
return resolve({ installed: false, signedIn: false, pickerEligible: false });
|
|
75
76
|
const installed = viewHasAgent(probe.view, agent);
|
|
76
|
-
|
|
77
|
+
const eligibility = installed
|
|
78
|
+
? viewAgentAccountEligibility(probe.view, agent)
|
|
79
|
+
: { signedIn: false, pickerEligible: false };
|
|
80
|
+
resolve({ installed, ...eligibility });
|
|
77
81
|
});
|
|
78
82
|
});
|
|
79
83
|
}
|
|
@@ -108,8 +112,18 @@ export async function probePoolSignals(pool, agent, opts = {}) {
|
|
|
108
112
|
const isSelf = normalizeHost(d.name) === self;
|
|
109
113
|
if (isSelf) {
|
|
110
114
|
const inst = checkCliAvailable(agent)[0];
|
|
111
|
-
|
|
112
|
-
|
|
115
|
+
if (!inst)
|
|
116
|
+
return [d.name, { installed: false, signedIn: false, pickerEligible: false }];
|
|
117
|
+
const candidates = await collectRunCandidates(agent).catch(() => null);
|
|
118
|
+
if (!candidates) {
|
|
119
|
+
return [d.name, { installed: true, signedIn: undefined, pickerEligible: undefined }];
|
|
120
|
+
}
|
|
121
|
+
const readiness = candidates.map(readinessFromCandidate);
|
|
122
|
+
return [d.name, {
|
|
123
|
+
installed: true,
|
|
124
|
+
signedIn: readiness.some((candidate) => candidate.ready),
|
|
125
|
+
pickerEligible: readiness.some((candidate) => candidate.ready || isSignInRecoverable(candidate)),
|
|
126
|
+
}];
|
|
113
127
|
}
|
|
114
128
|
return [d.name, await probeRemoteReadiness(d, agent)];
|
|
115
129
|
}))
|
|
@@ -128,6 +142,7 @@ export async function probePoolSignals(pool, agent, opts = {}) {
|
|
|
128
142
|
memPercent: s?.memPercent,
|
|
129
143
|
installed: inst?.installed,
|
|
130
144
|
signedIn: inst?.signedIn,
|
|
145
|
+
pickerEligible: inst?.pickerEligible,
|
|
131
146
|
});
|
|
132
147
|
}
|
|
133
148
|
cache.set(key, { at: now, signals });
|
|
@@ -18,8 +18,10 @@ export interface DevicePlacementSignal {
|
|
|
18
18
|
memPercent?: number;
|
|
19
19
|
/** Requested agent installed on the device. `false` → excluded (can't run). */
|
|
20
20
|
installed?: boolean;
|
|
21
|
-
/** Requested agent
|
|
21
|
+
/** Requested agent has at least one launch-ready account. Ranks a ready device first. */
|
|
22
22
|
signedIn?: boolean;
|
|
23
|
+
/** Requested agent has at least one row the interactive account picker can launch. */
|
|
24
|
+
pickerEligible?: boolean;
|
|
23
25
|
}
|
|
24
26
|
/** Team fields the placement cascade reads (a subset of TeamMeta). */
|
|
25
27
|
export interface PlacementTeam {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
* resolves to a null placement so the existing local spawn path runs unchanged,
|
|
35
35
|
* letting the local machine participate in a pool as just another member.
|
|
36
36
|
*/
|
|
37
|
-
import { machineId } from '../
|
|
37
|
+
import { machineId } from '../machine-id.js';
|
|
38
38
|
/**
|
|
39
39
|
* No device in the pool can host the teammate. Carries the per-device reasons so
|
|
40
40
|
* the caller can print exactly why the pool is unusable instead of silently
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Human-readable "time since" formatting for session timestamps. Lives here (not
|
|
3
|
+
* inline in `sessions.ts`) so both the session list renderer and the remote
|
|
4
|
+
* offline-cache banner (`remote.ts`) share one formatter — `sessions.ts` imports
|
|
5
|
+
* `remote.ts`, so a back-import would cycle.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatRelativeTime(isoTimestamp: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Compact age — `now`, `45m`, `3h`, `2d`, then the calendar date. This is the
|
|
10
|
+
* *creation* half of a session's time cell: it renders right next to the long
|
|
11
|
+
* last-activity label, and one row can afford one long form, not two.
|
|
12
|
+
*/
|
|
13
|
+
export declare function formatCompactAge(isoTimestamp: string): string;
|
|
14
|
+
/** The two time fields a session listing shows for one row. */
|
|
15
|
+
export interface SessionAgeParts {
|
|
16
|
+
/**
|
|
17
|
+
* Compact age of the session's creation, set only when the session ran long
|
|
18
|
+
* enough (>= a minute) for it to say something `last` does not.
|
|
19
|
+
*/
|
|
20
|
+
created?: string;
|
|
21
|
+
/** Last-activity label — the long relative form the listing sorts by. */
|
|
22
|
+
last: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Split a session's timestamps into the two fields a listing renders: when it
|
|
26
|
+
* was created and when it was last active. One last-activity label answers
|
|
27
|
+
* neither "is this the old session I'm looking for" nor "how long did it run" —
|
|
28
|
+
* a session touched an hour ago may have started last week.
|
|
29
|
+
*/
|
|
30
|
+
export declare function sessionAgeParts(createdIso: string, lastActivityIso?: string): SessionAgeParts;
|
|
31
|
+
/**
|
|
32
|
+
* Parse a time filter string (relative like '7d' or an ISO timestamp) into epoch
|
|
33
|
+
* milliseconds. Backs `--since` on `sessions`, `cost`, `teams`, and `output`, and
|
|
34
|
+
* `--unused` on `secrets list`.
|
|
35
|
+
*
|
|
36
|
+
* It lives here, in a module with no imports, rather than in `discover.ts` where
|
|
37
|
+
* it started: `discover.ts` loads `../sqlite.js`, so importing this one function
|
|
38
|
+
* from there pulls `node:sqlite` into the caller's module graph and Node prints
|
|
39
|
+
* `ExperimentalWarning: SQLite …` on stderr. That is invisible in a command that
|
|
40
|
+
* already touches the session DB, and a broken contract in one that doesn't —
|
|
41
|
+
* `monitors --json` asserts a clean stderr. `discover.ts` re-exports it, so
|
|
42
|
+
* existing importers are unaffected.
|
|
43
|
+
*/
|
|
44
|
+
export declare function parseTimeFilter(input: string): number;
|