@phnx-labs/agents-cli 1.22.46 → 1.22.49
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 +663 -0
- package/LICENSE +102 -182
- package/README.md +96 -49
- package/dist/bootstrap.js +4 -2
- package/dist/cli/command-registry.d.ts +2 -1
- package/dist/cli/command-registry.js +6 -2
- package/dist/commands/accounts.d.ts +58 -0
- package/dist/commands/accounts.js +243 -25
- package/dist/commands/artifacts.js +7 -6
- package/dist/commands/attach.js +1 -1
- package/dist/commands/auth.js +7 -5
- package/dist/commands/browser-sessions-picker.js +9 -7
- package/dist/commands/browser.js +711 -62
- package/dist/commands/config.d.ts +0 -1
- package/dist/commands/config.js +26 -24
- package/dist/commands/cost.d.ts +1 -1
- package/dist/commands/daemon.d.ts +21 -0
- package/dist/commands/daemon.js +147 -12
- package/dist/commands/detach.d.ts +13 -0
- package/dist/commands/detach.js +11 -8
- package/dist/commands/exec.js +107 -53
- package/dist/commands/feed-watch.d.ts +2 -0
- package/dist/commands/feed-watch.js +28 -0
- package/dist/commands/feed.js +27 -0
- package/dist/commands/feedback.js +3 -19
- package/dist/commands/focus.d.ts +14 -0
- package/dist/commands/focus.js +48 -5
- package/dist/commands/go.d.ts +3 -0
- package/dist/commands/go.js +16 -3
- package/dist/commands/insights.d.ts +1 -1
- package/dist/commands/insights.js +2 -2
- package/dist/commands/inspect.js +2 -2
- package/dist/commands/lease.d.ts +1 -1
- package/dist/commands/lease.js +7 -6
- package/dist/commands/mailboxes.js +4 -3
- package/dist/commands/menubar.js +11 -4
- package/dist/commands/projects.d.ts +16 -1
- package/dist/commands/projects.js +58 -64
- package/dist/commands/resume.js +1 -1
- package/dist/commands/route.js +4 -4
- package/dist/commands/routines.js +4 -3
- package/dist/commands/run-broadcast.d.ts +1 -1
- package/dist/commands/run-broadcast.js +1 -1
- package/dist/commands/sessions-picker-factory.d.ts +2 -1
- package/dist/commands/sessions-picker-factory.js +1 -1
- package/dist/commands/sessions-picker.d.ts +22 -0
- package/dist/commands/sessions-picker.js +48 -9
- package/dist/commands/sessions-stop.d.ts +24 -0
- package/dist/commands/sessions-stop.js +66 -0
- package/dist/commands/sessions-trace.d.ts +82 -0
- package/dist/commands/sessions-trace.js +387 -0
- package/dist/commands/sessions.js +5 -0
- package/dist/commands/setup-secrets.js +23 -0
- package/dist/commands/share.d.ts +20 -5
- package/dist/commands/share.js +152 -52
- package/dist/commands/ssh.d.ts +15 -0
- package/dist/commands/ssh.js +243 -18
- package/dist/commands/teams.js +34 -2
- package/dist/commands/traces.d.ts +2 -0
- package/dist/commands/traces.js +184 -0
- package/dist/commands/view.d.ts +2 -0
- package/dist/commands/view.js +32 -62
- package/dist/commands/watchdog.js +9 -14
- package/dist/index.d.ts +1 -0
- package/dist/index.js +5 -0
- package/dist/lib/account-capabilities.d.ts +4 -0
- package/dist/lib/account-capabilities.js +13 -9
- package/dist/lib/account-registry.d.ts +2 -0
- package/dist/lib/account-registry.js +30 -2
- package/dist/lib/accounting/rotate.d.ts +9 -0
- package/dist/lib/accounting/rotate.js +12 -2
- package/dist/lib/accounting/usage.d.ts +84 -6
- package/dist/lib/accounting/usage.js +293 -75
- package/dist/lib/agent-modes.js +29 -1
- package/dist/lib/agent-spec/agents.d.ts +4 -3
- package/dist/lib/agent-spec/agents.js +25 -15
- package/dist/lib/analytics/mix-commands.d.ts +1 -1
- package/dist/lib/analytics/mix-commands.js +2 -2
- package/dist/lib/auth-health.d.ts +13 -3
- package/dist/lib/auth-health.js +50 -8
- package/dist/lib/browser/devices.d.ts +19 -0
- package/dist/lib/browser/devices.js +23 -0
- package/dist/lib/browser/drivers/ssh.d.ts +16 -2
- package/dist/lib/browser/drivers/ssh.js +36 -9
- package/dist/lib/browser/ipc.d.ts +1 -1
- package/dist/lib/browser/ipc.js +40 -9
- package/dist/lib/browser/profiles.d.ts +104 -65
- package/dist/lib/browser/profiles.js +277 -165
- package/dist/lib/browser/registry.d.ts +39 -0
- package/dist/lib/browser/registry.js +149 -0
- package/dist/lib/browser/remote-control.d.ts +28 -2
- package/dist/lib/browser/remote-control.js +35 -3
- package/dist/lib/browser/resolve-target.d.ts +68 -0
- package/dist/lib/browser/resolve-target.js +250 -0
- package/dist/lib/browser/runtime-state.d.ts +44 -11
- package/dist/lib/browser/runtime-state.js +98 -15
- package/dist/lib/browser/service.d.ts +65 -9
- package/dist/lib/browser/service.js +196 -61
- package/dist/lib/browser/sessions-list.d.ts +1 -3
- package/dist/lib/browser/sessions-list.js +3 -16
- package/dist/lib/browser/task-index.d.ts +70 -0
- package/dist/lib/browser/task-index.js +180 -0
- package/dist/lib/browser/types.d.ts +12 -1
- package/dist/lib/byok-usage.js +2 -2
- package/dist/lib/claude-statusline.d.ts +29 -0
- package/dist/lib/claude-statusline.js +139 -0
- package/dist/lib/cloud/host.d.ts +1 -1
- package/dist/lib/cloud/host.js +1 -1
- package/dist/lib/cloud/rush.js +1 -1
- package/dist/lib/codex-policy.d.ts +11 -1
- package/dist/lib/codex-policy.js +20 -5
- package/dist/lib/computer/computer-rpc.js +2 -2
- package/dist/lib/computer/download.d.ts +15 -15
- package/dist/lib/computer/download.js +35 -98
- package/dist/lib/computer/ssh-tunnel.d.ts +0 -3
- package/dist/lib/computer/ssh-tunnel.js +12 -22
- package/dist/lib/config-keys.d.ts +6 -11
- package/dist/lib/config-keys.js +18 -19
- package/dist/lib/crabbox/cli.d.ts +1 -1
- package/dist/lib/crabbox/cli.js +2 -2
- package/dist/lib/crabbox/lease.d.ts +9 -0
- package/dist/lib/crabbox/lease.js +70 -15
- package/dist/lib/crabbox/runtimes.js +1 -1
- package/dist/lib/daemon/account-state-daemon-service.d.ts +16 -0
- package/dist/lib/daemon/account-state-daemon-service.js +26 -0
- package/dist/lib/daemon/browser-ipc-service.d.ts +20 -0
- package/dist/lib/daemon/browser-ipc-service.js +46 -0
- package/dist/lib/daemon/daemon.d.ts +3 -0
- package/dist/lib/daemon/daemon.js +212 -444
- package/dist/lib/daemon/device-probe-service.d.ts +26 -0
- package/dist/lib/daemon/device-probe-service.js +47 -0
- package/dist/lib/daemon/keychain-reap-service.d.ts +17 -0
- package/dist/lib/daemon/keychain-reap-service.js +32 -0
- package/dist/lib/daemon/monitor-engine-service.d.ts +22 -0
- package/dist/lib/daemon/monitor-engine-service.js +29 -0
- package/dist/lib/daemon/runner.js +15 -2
- package/dist/lib/daemon/secrets-broker-service.d.ts +20 -0
- package/dist/lib/daemon/secrets-broker-service.js +66 -0
- package/dist/lib/daemon/self-heal-service.d.ts +27 -0
- package/dist/lib/daemon/self-heal-service.js +48 -0
- package/dist/lib/daemon/service.d.ts +102 -0
- package/dist/lib/daemon/service.js +98 -0
- package/dist/lib/daemon/session-index-service.d.ts +22 -0
- package/dist/lib/daemon/session-index-service.js +40 -0
- package/dist/lib/daemon/state-dir-check-service.d.ts +43 -0
- package/dist/lib/daemon/state-dir-check-service.js +63 -0
- package/dist/lib/daemon/supervisor.d.ts +87 -0
- package/dist/lib/daemon/supervisor.js +298 -0
- package/dist/lib/daemon/watchdog-service.d.ts +19 -0
- package/dist/lib/daemon/watchdog-service.js +40 -0
- package/dist/lib/daemon-health.d.ts +15 -0
- package/dist/lib/daemon-health.js +29 -5
- package/dist/lib/daemon-services.d.ts +8 -1
- package/dist/lib/daemon-services.js +55 -0
- package/dist/lib/daemon-ticks.d.ts +13 -2
- package/dist/lib/daemon-ticks.js +22 -20
- package/dist/lib/device-config.d.ts +25 -10
- package/dist/lib/device-config.js +90 -39
- package/dist/lib/devices/config-migration.d.ts +7 -0
- package/dist/lib/devices/config-migration.js +67 -3
- package/dist/lib/devices/health.d.ts +27 -2
- package/dist/lib/devices/health.js +39 -9
- package/dist/lib/devices/interactive-host.d.ts +15 -0
- package/dist/lib/devices/interactive-host.js +53 -0
- package/dist/lib/devices/registry.d.ts +61 -4
- package/dist/lib/devices/registry.js +94 -38
- package/dist/lib/devices/stats-cache.d.ts +26 -0
- package/dist/lib/devices/stats-cache.js +59 -7
- package/dist/lib/devices/worker-pick.d.ts +48 -0
- package/dist/lib/devices/worker-pick.js +113 -0
- package/dist/lib/exec.d.ts +70 -14
- package/dist/lib/exec.js +110 -38
- package/dist/lib/feed/answer.d.ts +29 -0
- package/dist/lib/feed/answer.js +145 -0
- package/dist/lib/feed/attention.d.ts +83 -0
- package/dist/lib/feed/attention.js +0 -0
- package/dist/lib/feed/feed.d.ts +109 -0
- package/dist/lib/feed/feed.js +154 -3
- package/dist/lib/feed/pr-status.d.ts +14 -0
- package/dist/lib/feed/pr-status.js +47 -0
- package/dist/lib/feed/watch.d.ts +59 -0
- package/dist/lib/feed/watch.js +180 -0
- package/dist/lib/fleet/capture.js +6 -0
- package/dist/lib/fleet/remote-login.js +8 -3
- package/dist/lib/fleet/types.d.ts +17 -0
- package/dist/lib/harness/adapter.d.ts +11 -0
- package/dist/lib/harness/adapters/claude.js +38 -24
- package/dist/lib/harness/adapters/codex.js +2 -4
- package/dist/lib/harness/adapters/cursor.js +8 -11
- package/dist/lib/helper-download.d.ts +108 -0
- package/dist/lib/helper-download.js +194 -0
- package/dist/lib/helper-versions.d.ts +52 -0
- package/dist/lib/helper-versions.js +58 -0
- package/dist/lib/hooks/cache.js +19 -0
- package/dist/lib/hooks/install.js +2 -2
- package/dist/lib/hooks/match.d.ts +3 -0
- package/dist/lib/hooks/match.js +25 -0
- package/dist/lib/hosts/credentials.d.ts +1 -1
- package/dist/lib/hosts/credentials.js +1 -1
- package/dist/lib/hosts/dispatch.d.ts +7 -1
- package/dist/lib/hosts/dispatch.js +24 -5
- package/dist/lib/hosts/passthrough.d.ts +8 -15
- package/dist/lib/hosts/passthrough.js +35 -16
- package/dist/lib/hosts/providers/devices.d.ts +1 -1
- package/dist/lib/hosts/providers/devices.js +1 -1
- package/dist/lib/hosts/reconnect.d.ts +179 -21
- package/dist/lib/hosts/reconnect.js +266 -45
- package/dist/lib/hosts/registry.js +7 -0
- package/dist/lib/installations/migrate.d.ts +4 -5
- package/dist/lib/installations/migrate.js +6 -7
- package/dist/lib/installations/shims.d.ts +1 -1
- package/dist/lib/installations/shims.js +23 -13
- package/dist/lib/installations/versions.js +25 -2
- package/dist/lib/linear-autoclose.d.ts +1 -1
- package/dist/lib/linear-autoclose.js +1 -1
- package/dist/lib/loop.d.ts +2 -2
- package/dist/lib/loop.js +1 -1
- package/dist/lib/menubar/download-menubar.d.ts +47 -0
- package/dist/lib/menubar/download-menubar.js +60 -0
- package/dist/lib/menubar/install-menubar.d.ts +44 -7
- package/dist/lib/menubar/install-menubar.js +105 -23
- package/dist/lib/menubar/notify-desktop.d.ts +3 -3
- package/dist/lib/menubar/notify-desktop.js +6 -6
- package/dist/lib/model-tiers.d.ts +1 -1
- package/dist/lib/open-url.d.ts +60 -2
- package/dist/lib/open-url.js +167 -12
- package/dist/lib/project-probe.d.ts +1 -1
- package/dist/lib/project-probe.js +1 -1
- package/dist/lib/project-pull.d.ts +1 -1
- package/dist/lib/project-pull.js +2 -2
- package/dist/lib/projects.d.ts +1 -1
- package/dist/lib/projects.js +1 -1
- package/dist/lib/refresh-coordinator.d.ts +1 -1
- package/dist/lib/refresh-coordinator.js +1 -1
- package/dist/lib/sandbox.js +6 -7
- package/dist/lib/secrets/download-keychain.d.ts +47 -0
- package/dist/lib/secrets/download-keychain.js +70 -0
- package/dist/lib/secrets/install-helper.d.ts +20 -1
- package/dist/lib/secrets/install-helper.js +44 -3
- package/dist/lib/session/active.d.ts +67 -0
- package/dist/lib/session/active.js +86 -2
- package/dist/lib/session/db.d.ts +11 -1
- package/dist/lib/session/db.js +142 -8
- package/dist/lib/session/discover.d.ts +23 -1
- package/dist/lib/session/discover.js +44 -10
- package/dist/lib/session/highlights.d.ts +49 -1
- package/dist/lib/session/highlights.js +95 -0
- package/dist/lib/session/host-link.d.ts +16 -2
- package/dist/lib/session/host-link.js +7 -1
- package/dist/lib/session/parse.js +33 -1
- package/dist/lib/session/prompt.d.ts +35 -0
- package/dist/lib/session/prompt.js +56 -0
- package/dist/lib/session/remote/remote-list.d.ts +9 -0
- package/dist/lib/session/remote/remote-list.js +19 -2
- package/dist/lib/session/remote/watch.d.ts +1 -1
- package/dist/lib/session/remote/watch.js +17 -3
- package/dist/lib/session/render.js +7 -3
- package/dist/lib/session/session-cache.d.ts +53 -0
- package/dist/lib/session/session-cache.js +93 -1
- package/dist/lib/session/state.js +1 -1
- package/dist/lib/session/tool-calls.d.ts +2 -0
- package/dist/lib/session/tool-calls.js +1 -1
- package/dist/lib/session/trajectory-compare.d.ts +47 -0
- package/dist/lib/session/trajectory-compare.js +116 -0
- package/dist/lib/session/trajectory-html.d.ts +19 -0
- package/dist/lib/session/trajectory-html.js +770 -0
- package/dist/lib/session/trajectory-lineage.d.ts +92 -0
- package/dist/lib/session/trajectory-lineage.js +195 -0
- package/dist/lib/session/trajectory-text.d.ts +37 -0
- package/dist/lib/session/trajectory-text.js +284 -0
- package/dist/lib/session/trajectory.d.ts +102 -0
- package/dist/lib/session/trajectory.js +384 -0
- package/dist/lib/session/types.d.ts +15 -0
- package/dist/lib/sha256-asset.d.ts +26 -0
- package/dist/lib/sha256-asset.js +41 -0
- package/dist/lib/share/backend.d.ts +95 -0
- package/dist/lib/share/backend.js +139 -0
- package/dist/lib/share/delete.d.ts +6 -2
- package/dist/lib/share/delete.js +8 -9
- package/dist/lib/share/html.d.ts +22 -0
- package/dist/lib/share/html.js +88 -0
- package/dist/lib/share/provision.d.ts +18 -4
- package/dist/lib/share/provision.js +38 -4
- package/dist/lib/share/publish.d.ts +39 -15
- package/dist/lib/share/publish.js +55 -26
- package/dist/lib/share/worker-template.js +171 -11
- package/dist/lib/sqlite.js +16 -3
- package/dist/lib/ssh-exec.d.ts +65 -0
- package/dist/lib/ssh-exec.js +120 -4
- package/dist/lib/startup/command-registry.d.ts +3 -1
- package/dist/lib/startup/command-registry.js +6 -3
- package/dist/lib/startup/dev-build.js +3 -3
- package/dist/lib/state.d.ts +2 -2
- package/dist/lib/state.js +11 -5
- package/dist/lib/subagents-registry.js +1 -1
- package/dist/lib/teams/agents.js +9 -0
- package/dist/lib/terminal/index.d.ts +1 -1
- package/dist/lib/terminal/inject.d.ts +19 -0
- package/dist/lib/terminal/inject.js +19 -9
- package/dist/lib/terminal/types.d.ts +1 -1
- package/dist/lib/terminal/types.js +1 -1
- package/dist/lib/tmux/orphan-reap.js +1 -1
- package/dist/lib/tmux/session.d.ts +46 -13
- package/dist/lib/tmux/session.js +204 -27
- package/dist/lib/traces/backend.d.ts +29 -0
- package/dist/lib/traces/backend.js +46 -0
- package/dist/lib/traces/classify.d.ts +52 -0
- package/dist/lib/traces/classify.js +72 -0
- package/dist/lib/traces/config.d.ts +10 -0
- package/dist/lib/traces/config.js +2 -0
- package/dist/lib/traces/provision.d.ts +19 -0
- package/dist/lib/traces/provision.js +30 -0
- package/dist/lib/traces/sync.d.ts +150 -0
- package/dist/lib/traces/sync.js +447 -0
- package/dist/lib/traces/worker-template.d.ts +4 -0
- package/dist/lib/traces/worker-template.js +159 -0
- package/dist/lib/types.d.ts +34 -19
- package/dist/lib/types.js +14 -0
- package/dist/lib/usage-backoff.d.ts +2 -1
- package/dist/lib/usage-backoff.js +60 -19
- package/dist/lib/usage-refresh.d.ts +18 -4
- package/dist/lib/usage-refresh.js +68 -19
- package/dist/lib/watchdog/log.d.ts +1 -1
- package/dist/lib/watchdog/log.js +1 -1
- package/dist/lib/watchdog/runner.d.ts +36 -45
- package/dist/lib/watchdog/runner.js +150 -119
- package/dist/lib/watchdog/service.d.ts +0 -1
- package/dist/lib/watchdog/service.js +0 -1
- package/dist/lib/watchdog/watchdog-agent.d.ts +38 -0
- package/dist/lib/watchdog/watchdog-agent.js +59 -0
- package/dist/lib/watchdog/watchdog.d.ts +11 -2
- package/dist/lib/watchdog/watchdog.js +37 -104
- package/dist/lib/workflows.d.ts +1 -1
- package/package.json +5 -7
- package/dist/commands/usage.d.ts +0 -27
- package/dist/commands/usage.js +0 -96
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +0 -24
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +0 -128
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +0 -24
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +0 -123
- package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/usage-fleet.d.ts +0 -32
- package/dist/lib/usage-fleet.js +0 -125
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agents sessions trace <selectors...>` (alias: `agents trace <selectors...>`) —
|
|
3
|
+
* render one session as a derived trajectory, or two as a compare.
|
|
4
|
+
*
|
|
5
|
+
* One model (`buildTrajectory`), three renderings, audience auto-selected: a
|
|
6
|
+
* person at a TTY gets the self-contained HTML opened in a browser; a piped or
|
|
7
|
+
* headless caller (an agent) gets the compact text trajectory; `--json` emits the
|
|
8
|
+
* versioned envelope the AGI EXT Fleet panel and triaging agents consume. Explicit
|
|
9
|
+
* `--html/--text/--json` always win.
|
|
10
|
+
*
|
|
11
|
+
* Exactly two resolved selectors turn the single trajectory into a **compare**
|
|
12
|
+
* (`diffTrajectories`, PR2/3) — the same three renderings, laid on a shared axis
|
|
13
|
+
* with a divergence marker. `--tree` turns one selector into a **lineage**
|
|
14
|
+
* (`buildLineage`, PR3/3): the orchestrator and every session it spawned, edges
|
|
15
|
+
* read from the team records. Three or more selectors still fail loud.
|
|
16
|
+
*/
|
|
17
|
+
import * as fs from 'fs';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import chalk from 'chalk';
|
|
20
|
+
import { setHelpSections } from '../lib/help.js';
|
|
21
|
+
import { showFile } from '../lib/open-url.js';
|
|
22
|
+
import { knownSecretValuesFromEnv } from '../lib/redact.js';
|
|
23
|
+
import { getCacheDir } from '../lib/state.js';
|
|
24
|
+
import { discoverSessions } from '../lib/session/discover.js';
|
|
25
|
+
import { parseSession } from '../lib/session/parse.js';
|
|
26
|
+
import { buildTrajectory } from '../lib/session/trajectory.js';
|
|
27
|
+
import { diffTrajectories } from '../lib/session/trajectory-compare.js';
|
|
28
|
+
import { buildLineage } from '../lib/session/trajectory-lineage.js';
|
|
29
|
+
import { renderTrajectoryHtml, renderTrajectoryCompareHtml, renderLineageHtml } from '../lib/session/trajectory-html.js';
|
|
30
|
+
import { renderTrajectoryText, renderTrajectoryCompareText, renderLineageText } from '../lib/session/trajectory-text.js';
|
|
31
|
+
import { parseAgentFilter } from './sessions.js';
|
|
32
|
+
import { selectSessions } from './sessions-export.js';
|
|
33
|
+
/** Versioned envelope emitted by `--json` — the stable contract for consumers. */
|
|
34
|
+
export const SESSIONS_TRACE_SCHEMA_VERSION = 1;
|
|
35
|
+
/** Build the versioned `--json` envelope for a single-session trajectory. */
|
|
36
|
+
export function buildTraceEnvelope(models) {
|
|
37
|
+
return {
|
|
38
|
+
schemaVersion: SESSIONS_TRACE_SCHEMA_VERSION,
|
|
39
|
+
kind: 'sessions-trace',
|
|
40
|
+
layout: 'single',
|
|
41
|
+
sessions: models,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Build the versioned `--json` envelope for a two-session compare. */
|
|
45
|
+
export function buildCompareTraceEnvelope(cmp) {
|
|
46
|
+
return {
|
|
47
|
+
schemaVersion: SESSIONS_TRACE_SCHEMA_VERSION,
|
|
48
|
+
kind: 'sessions-trace',
|
|
49
|
+
layout: 'compare',
|
|
50
|
+
sessions: [cmp.a, cmp.b],
|
|
51
|
+
diff: {
|
|
52
|
+
divergence: cmp.divergence,
|
|
53
|
+
added: cmp.added,
|
|
54
|
+
removed: cmp.removed,
|
|
55
|
+
summaryA: cmp.summaryA,
|
|
56
|
+
summaryB: cmp.summaryB,
|
|
57
|
+
truncatedA: cmp.truncatedA,
|
|
58
|
+
truncatedB: cmp.truncatedB,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build the versioned `--json` envelope for a lineage. `sessions` carries the
|
|
64
|
+
* ROOT's trajectory only: the graph's own numbers come from the indexed session
|
|
65
|
+
* rows, so a consumer pays one transcript parse instead of one per teammate —
|
|
66
|
+
* `agents sessions trace <child>` is how you get a child's full trajectory.
|
|
67
|
+
*/
|
|
68
|
+
export function buildLineageTraceEnvelope(lineage, rootTrajectory) {
|
|
69
|
+
return {
|
|
70
|
+
schemaVersion: SESSIONS_TRACE_SCHEMA_VERSION,
|
|
71
|
+
kind: 'sessions-trace',
|
|
72
|
+
layout: 'lineage',
|
|
73
|
+
sessions: [rootTrajectory],
|
|
74
|
+
lineage: {
|
|
75
|
+
rootId: lineage.rootId,
|
|
76
|
+
nodes: lineage.nodes,
|
|
77
|
+
edges: lineage.edges,
|
|
78
|
+
teams: lineage.teams,
|
|
79
|
+
unresolvedParentIds: lineage.unresolvedParentIds,
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Pick the rendering by audience: explicit `--html/--text/--json` win; otherwise
|
|
85
|
+
* a person at a TTY gets the visual HTML and a piped/headless caller (an agent)
|
|
86
|
+
* gets the compact text trajectory.
|
|
87
|
+
*/
|
|
88
|
+
export function chooseFormat(options, isTTY) {
|
|
89
|
+
if (options.json)
|
|
90
|
+
return 'json';
|
|
91
|
+
if (options.html)
|
|
92
|
+
return 'html';
|
|
93
|
+
if (options.text)
|
|
94
|
+
return 'text';
|
|
95
|
+
return isTTY ? 'html' : 'text';
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Decide the trace layout from what the user TYPED (`selectorCount`) vs what
|
|
99
|
+
* those selectors RESOLVED to (`resolvedCount`). Keyed on selector count so a
|
|
100
|
+
* single content-search selector that happens to match two sessions never
|
|
101
|
+
* silently becomes a compare — every unsupported combination fails loud with a
|
|
102
|
+
* clear message. Pure, so the boundaries are unit-tested without the command.
|
|
103
|
+
*/
|
|
104
|
+
export function decideTraceLayout(options, selectorCount, resolvedCount) {
|
|
105
|
+
if (options.tree) {
|
|
106
|
+
if (options.compare) {
|
|
107
|
+
throw new Error('`--tree` (lineage) and `--compare` are different layouts — pass one or the other.');
|
|
108
|
+
}
|
|
109
|
+
if (selectorCount !== 1) {
|
|
110
|
+
throw new Error(`Lineage roots at ONE session; you passed ${selectorCount} selectors. ` +
|
|
111
|
+
'Pass the orchestrator session whose team you want to see.');
|
|
112
|
+
}
|
|
113
|
+
if (resolvedCount !== 1) {
|
|
114
|
+
throw new Error(`The selector must match exactly one session to root a lineage; it matched ${resolvedCount}. ` +
|
|
115
|
+
'Use a more specific selector (e.g. the full session id).');
|
|
116
|
+
}
|
|
117
|
+
return 'lineage';
|
|
118
|
+
}
|
|
119
|
+
const wantCompare = options.compare === true || selectorCount >= 2;
|
|
120
|
+
if (wantCompare) {
|
|
121
|
+
if (selectorCount !== 2) {
|
|
122
|
+
throw new Error(`Comparing needs exactly two selectors; you passed ${selectorCount}. ` +
|
|
123
|
+
'Pass two session selectors (ids or queries), each matching one session.');
|
|
124
|
+
}
|
|
125
|
+
if (resolvedCount !== 2) {
|
|
126
|
+
throw new Error(`Each selector must match exactly one session to compare; the two selectors matched ${resolvedCount}. ` +
|
|
127
|
+
'Use more specific selectors (e.g. full session ids).');
|
|
128
|
+
}
|
|
129
|
+
return 'compare';
|
|
130
|
+
}
|
|
131
|
+
if (resolvedCount > 1) {
|
|
132
|
+
throw new Error(`${resolvedCount} sessions matched — pass a more specific selector for one trajectory, ` +
|
|
133
|
+
'or two selectors to compare them.');
|
|
134
|
+
}
|
|
135
|
+
return 'single';
|
|
136
|
+
}
|
|
137
|
+
/** Attach the trace behaviour to a command node (canonical or top-level alias). */
|
|
138
|
+
export function configureTraceCommand(cmd) {
|
|
139
|
+
cmd
|
|
140
|
+
.description('Visualize a session as a trajectory — a tool-call timeline you can read at a glance. Opens a visual for a person; prints a compact trajectory for an agent.')
|
|
141
|
+
.option('--html', 'Force the HTML rendering (opens in a browser)')
|
|
142
|
+
.option('--text', 'Force the compact text trajectory')
|
|
143
|
+
.option('--json', 'Emit the versioned sessions-trace JSON envelope')
|
|
144
|
+
.option('-o, --output <path>', 'Write the rendering to a path instead of opening/printing')
|
|
145
|
+
.option('--no-open', 'Do not open the HTML; print its path instead')
|
|
146
|
+
.option('--errors-only', 'Collapse the text trajectory to error steps and their neighbours')
|
|
147
|
+
.option('--compare', 'Force the compare layout for exactly two selectors (this is also the default for two)')
|
|
148
|
+
.option('--tree', 'Render the lineage of one session — it and every session it spawned')
|
|
149
|
+
.option('--no-redact', 'Local-only: skip secret redaction of derived labels (never for a shared file)')
|
|
150
|
+
.option('--all', 'Search every directory and all time, not just this project')
|
|
151
|
+
.option('--since <time>', 'Only sessions newer than this (7d, 4w, an ISO date)')
|
|
152
|
+
.option('--limit <n>', 'Max sessions to scan when resolving the selector (default 100)')
|
|
153
|
+
.option('-a, --agent <agent>', 'Filter by agent type (e.g. claude, codex)');
|
|
154
|
+
setHelpSections(cmd, {
|
|
155
|
+
examples: `# Open one session's trajectory in a browser (a person at a terminal)
|
|
156
|
+
agents sessions trace a1b2c3d4
|
|
157
|
+
|
|
158
|
+
# The compact text trajectory an agent reads in-context
|
|
159
|
+
agents sessions trace a1b2c3d4 --text
|
|
160
|
+
|
|
161
|
+
# Just the failures and their neighbours — for a triaging agent
|
|
162
|
+
agents sessions trace a1b2c3d4 --text --errors-only
|
|
163
|
+
|
|
164
|
+
# The stable JSON envelope for the AGI EXT Fleet panel or a tool
|
|
165
|
+
agents sessions trace a1b2c3d4 --json
|
|
166
|
+
|
|
167
|
+
# Write the self-contained HTML to a file without opening it
|
|
168
|
+
agents sessions trace a1b2c3d4 --html -o trace.html --no-open
|
|
169
|
+
|
|
170
|
+
# Two selectors — compare where a passing run and a failing one diverge
|
|
171
|
+
agents sessions trace a1b2c3d4 e5f6a7b8
|
|
172
|
+
|
|
173
|
+
# The compare, as text — for a triaging agent comparing harnesses
|
|
174
|
+
agents sessions trace a1b2c3d4 e5f6a7b8 --text
|
|
175
|
+
|
|
176
|
+
# The team an orchestrator spawned, as a graph (one selector + --tree)
|
|
177
|
+
agents sessions trace a1b2c3d4 --tree
|
|
178
|
+
|
|
179
|
+
# The same lineage as an indented tree an agent can read
|
|
180
|
+
agents sessions trace a1b2c3d4 --tree --text`,
|
|
181
|
+
notes: `Audience auto-select: with no --html/--text/--json, HTML opens on a TTY (a person) and
|
|
182
|
+
the compact text trajectory prints when piped or headless (an agent). The HTML is self-contained
|
|
183
|
+
(no CDN, no external asset) and redacted by default, as safe to share as an 'agents sessions share' page.
|
|
184
|
+
|
|
185
|
+
One selector renders the single trajectory; exactly two selectors compare them (a shared time axis,
|
|
186
|
+
the first divergence point, and the step-level diff); one selector with --tree renders its lineage —
|
|
187
|
+
the session and every session it spawned, with the edges read from the teams records
|
|
188
|
+
(teamOrigin.parentSessionId), never from an inline Task sub-agent, which is a step inside one transcript
|
|
189
|
+
and has no session of its own. --json emits { schemaVersion, kind: 'sessions-trace',
|
|
190
|
+
layout: 'single' | 'compare' | 'lineage', sessions: [SessionTrajectory], diff?, lineage? } — the contract
|
|
191
|
+
consumers read so nothing re-parses a transcript.
|
|
192
|
+
|
|
193
|
+
Lineage resolves children from the scanned pool, so a very old team may need a wider --limit or --since.
|
|
194
|
+
Three or more selectors, and --tree with more than one selector, fail loud.`,
|
|
195
|
+
});
|
|
196
|
+
cmd.action(async (selectors, _options, command) => {
|
|
197
|
+
// Merge parent globals: under `agents sessions trace`, the `sessions` command
|
|
198
|
+
// owns `--json`/`--no-redact`/`--all`/`--agent`/`--since` and captures them, so
|
|
199
|
+
// read the merged view (as `render`/`insights` do) — the top-level `agents
|
|
200
|
+
// trace` alias has no such parent and its own options fill the same fields.
|
|
201
|
+
const options = command.optsWithGlobals();
|
|
202
|
+
// Lineage resolves its children FROM the scanned pool, and a teammate can sit
|
|
203
|
+
// well below the orchestrator in recency order, so --tree scans wider by
|
|
204
|
+
// default than the single/compare layouts. An explicit --limit still wins.
|
|
205
|
+
const defaultLimit = options.tree ? 500 : 100;
|
|
206
|
+
const limit = Math.max(1, Number.parseInt(options.limit || String(defaultLimit), 10) || defaultLimit);
|
|
207
|
+
const agent = parseAgentFilter(options.agent).agent;
|
|
208
|
+
const pool = await discoverSessions({
|
|
209
|
+
// Default to every directory so an id from any project resolves, matching
|
|
210
|
+
// `agents sessions render` (sessions-render.ts:126).
|
|
211
|
+
all: options.all !== false,
|
|
212
|
+
since: options.since,
|
|
213
|
+
limit,
|
|
214
|
+
agent: agent ?? undefined,
|
|
215
|
+
});
|
|
216
|
+
const sessions = selectSessions(pool, selectors);
|
|
217
|
+
if (sessions.length === 0) {
|
|
218
|
+
process.stderr.write(chalk.yellow('No sessions matched the selection.\n'));
|
|
219
|
+
process.exitCode = 1;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
// Layout is keyed on what the USER TYPED (selector count), not the resolved
|
|
223
|
+
// count — a single content-search selector matching two sessions must NOT
|
|
224
|
+
// silently become a compare. All the fail-loud boundaries live in the pure
|
|
225
|
+
// decideTraceLayout so they are unit-tested (see sessions-trace.test.ts).
|
|
226
|
+
const layout = decideTraceLayout(options, selectors.length, sessions.length);
|
|
227
|
+
const redact = options.redact !== false;
|
|
228
|
+
const knownSecrets = redact ? knownSecretValuesFromEnv() : undefined;
|
|
229
|
+
const format = chooseFormat(options, Boolean(process.stdout.isTTY));
|
|
230
|
+
const buildOne = (session) => {
|
|
231
|
+
const events = parseSession(session.filePath, session.agent);
|
|
232
|
+
return buildTrajectory(events, session, { redact, knownSecrets });
|
|
233
|
+
};
|
|
234
|
+
if (layout === 'lineage') {
|
|
235
|
+
// The pool must keep team-origin rows: they are hidden from the ordinary
|
|
236
|
+
// listing by default (AGENTS.md invariant 7), and they ARE the children.
|
|
237
|
+
// discoverSessions does not apply that presentation filter, so `pool` is
|
|
238
|
+
// already the teams-included set the graph needs.
|
|
239
|
+
const root = sessions[0];
|
|
240
|
+
// An id-shaped selector resolves through the session INDEX, which reaches
|
|
241
|
+
// rows the scanned pool does not hold (selectSessions -> findSessionsById,
|
|
242
|
+
// sessions-export.ts:386). Seed the pool with the resolved root so the
|
|
243
|
+
// graph always roots where the user pointed.
|
|
244
|
+
const pooled = pool.some((s) => s.id === root.id) ? pool : [root, ...pool];
|
|
245
|
+
const lineage = buildLineage(pooled, { rootId: root.id });
|
|
246
|
+
const idPart = root.shortId || root.id;
|
|
247
|
+
if (format === 'json') {
|
|
248
|
+
const out = JSON.stringify(buildLineageTraceEnvelope(lineage, buildOne(root)), null, 2) + '\n';
|
|
249
|
+
if (options.output) {
|
|
250
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
251
|
+
process.stderr.write(chalk.green(`Wrote lineage JSON to ${options.output}\n`));
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
process.stdout.write(out);
|
|
255
|
+
}
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
if (format === 'text') {
|
|
259
|
+
const out = renderLineageText(lineage);
|
|
260
|
+
if (options.output) {
|
|
261
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
262
|
+
process.stderr.write(chalk.green(`Wrote lineage text to ${options.output}\n`));
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
process.stdout.write(out);
|
|
266
|
+
}
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// HTML.
|
|
270
|
+
const html = renderLineageHtml(lineage, redact);
|
|
271
|
+
if (options.output) {
|
|
272
|
+
fs.writeFileSync(options.output, html, { mode: 0o600 });
|
|
273
|
+
process.stdout.write(`${path.resolve(options.output)}\n`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const dir = path.join(getCacheDir(), 'traces');
|
|
277
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
278
|
+
const file = path.join(dir, `${idPart}-lineage-${Date.now()}.html`);
|
|
279
|
+
fs.writeFileSync(file, html, { mode: 0o600 });
|
|
280
|
+
if (options.open === false) {
|
|
281
|
+
process.stdout.write(`${file}\n`);
|
|
282
|
+
}
|
|
283
|
+
else {
|
|
284
|
+
await showFile(file);
|
|
285
|
+
process.stderr.write(chalk.green(`Opened lineage for ${idPart}: ${file}\n`));
|
|
286
|
+
}
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
if (layout === 'compare') {
|
|
290
|
+
const cmp = diffTrajectories(buildOne(sessions[0]), buildOne(sessions[1]));
|
|
291
|
+
const idPart = `${sessions[0].shortId || sessions[0].id}-vs-${sessions[1].shortId || sessions[1].id}`;
|
|
292
|
+
if (format === 'json') {
|
|
293
|
+
const out = JSON.stringify(buildCompareTraceEnvelope(cmp), null, 2) + '\n';
|
|
294
|
+
if (options.output) {
|
|
295
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
296
|
+
process.stderr.write(chalk.green(`Wrote compare JSON to ${options.output}\n`));
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
process.stdout.write(out);
|
|
300
|
+
}
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
303
|
+
if (format === 'text') {
|
|
304
|
+
const out = renderTrajectoryCompareText(cmp);
|
|
305
|
+
if (options.output) {
|
|
306
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
307
|
+
process.stderr.write(chalk.green(`Wrote compare text to ${options.output}\n`));
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
process.stdout.write(out);
|
|
311
|
+
}
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
// HTML.
|
|
315
|
+
const html = renderTrajectoryCompareHtml(cmp);
|
|
316
|
+
if (options.output) {
|
|
317
|
+
fs.writeFileSync(options.output, html, { mode: 0o600 });
|
|
318
|
+
process.stdout.write(`${path.resolve(options.output)}\n`);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const dir = path.join(getCacheDir(), 'traces');
|
|
322
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
323
|
+
const file = path.join(dir, `${idPart}-${Date.now()}.html`);
|
|
324
|
+
fs.writeFileSync(file, html, { mode: 0o600 });
|
|
325
|
+
if (options.open === false) {
|
|
326
|
+
process.stdout.write(`${file}\n`);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
await showFile(file);
|
|
330
|
+
process.stderr.write(chalk.green(`Opened compare for ${idPart}: ${file}\n`));
|
|
331
|
+
}
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
// One selector — the single-session trajectory.
|
|
335
|
+
const session = sessions[0];
|
|
336
|
+
const model = buildOne(session);
|
|
337
|
+
if (format === 'json') {
|
|
338
|
+
const out = JSON.stringify(buildTraceEnvelope([model]), null, 2) + '\n';
|
|
339
|
+
if (options.output) {
|
|
340
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
341
|
+
process.stderr.write(chalk.green(`Wrote trajectory JSON to ${options.output}\n`));
|
|
342
|
+
}
|
|
343
|
+
else {
|
|
344
|
+
process.stdout.write(out);
|
|
345
|
+
}
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
if (format === 'text') {
|
|
349
|
+
const out = renderTrajectoryText(model, { errorsOnly: options.errorsOnly === true });
|
|
350
|
+
if (options.output) {
|
|
351
|
+
fs.writeFileSync(options.output, out, { mode: 0o600 });
|
|
352
|
+
process.stderr.write(chalk.green(`Wrote text trajectory to ${options.output}\n`));
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
process.stdout.write(out);
|
|
356
|
+
}
|
|
357
|
+
return;
|
|
358
|
+
}
|
|
359
|
+
// HTML.
|
|
360
|
+
const html = renderTrajectoryHtml(model);
|
|
361
|
+
if (options.output) {
|
|
362
|
+
fs.writeFileSync(options.output, html, { mode: 0o600 });
|
|
363
|
+
process.stdout.write(`${path.resolve(options.output)}\n`);
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
const dir = path.join(getCacheDir(), 'traces');
|
|
367
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
368
|
+
const file = path.join(dir, `${session.shortId || session.id}-${Date.now()}.html`);
|
|
369
|
+
fs.writeFileSync(file, html, { mode: 0o600 });
|
|
370
|
+
if (options.open === false) {
|
|
371
|
+
process.stdout.write(`${file}\n`);
|
|
372
|
+
}
|
|
373
|
+
else {
|
|
374
|
+
await showFile(file);
|
|
375
|
+
process.stderr.write(chalk.green(`Opened trajectory for ${session.shortId || session.id}: ${file}\n`));
|
|
376
|
+
}
|
|
377
|
+
});
|
|
378
|
+
return cmd;
|
|
379
|
+
}
|
|
380
|
+
/** Canonical `agents sessions trace <selectors...>`. */
|
|
381
|
+
export function registerSessionsTraceCommand(sessionsCmd) {
|
|
382
|
+
configureTraceCommand(sessionsCmd.command('trace <selectors...>'));
|
|
383
|
+
}
|
|
384
|
+
/** Top-level alias `agents trace <selectors...>` (mirrors `agents insights`). */
|
|
385
|
+
export function registerTraceCommand(program) {
|
|
386
|
+
configureTraceCommand(program.command('trace <selectors...>'));
|
|
387
|
+
}
|
|
@@ -66,10 +66,12 @@ import { registerGoCommand } from './go.js';
|
|
|
66
66
|
import { registerFocusCommand } from './focus.js';
|
|
67
67
|
import { registerReconnectCommand } from './reconnect.js';
|
|
68
68
|
import { registerDetachCommand } from './detach.js';
|
|
69
|
+
import { registerSessionsStopCommand } from './sessions-stop.js';
|
|
69
70
|
import { registerAttachCommand } from './attach.js';
|
|
70
71
|
import { registerSessionsInjectCommand } from './sessions-inject.js';
|
|
71
72
|
import { registerSessionsExportCommand } from './sessions-export.js';
|
|
72
73
|
import { registerSessionsRenderCommand } from './sessions-render.js';
|
|
74
|
+
import { registerSessionsTraceCommand } from './sessions-trace.js';
|
|
73
75
|
import { registerSessionsShareCommand } from './sessions-share.js';
|
|
74
76
|
import { registerSessionsImportCommand } from './sessions-import.js';
|
|
75
77
|
import { registerSessionsMigrateCommand, registerSessionsMigrationsCommand } from './sessions-migrate.js';
|
|
@@ -3851,6 +3853,7 @@ export async function resumeOnOwnerIfRemote(session) {
|
|
|
3851
3853
|
const rc = await runOnPeer(['sessions', 'resume', session.id], owner, {
|
|
3852
3854
|
tty: true,
|
|
3853
3855
|
env: { [RESUME_PINNED_ENV]: '1' },
|
|
3856
|
+
sessionId: session.id,
|
|
3854
3857
|
});
|
|
3855
3858
|
if (rc === 'no-target')
|
|
3856
3859
|
warnNoPeerTarget(owner, session);
|
|
@@ -5170,10 +5173,12 @@ export function registerSessionsCommands(program) {
|
|
|
5170
5173
|
registerFocusCommand(sessionsCmd);
|
|
5171
5174
|
registerReconnectCommand(sessionsCmd);
|
|
5172
5175
|
registerDetachCommand(sessionsCmd);
|
|
5176
|
+
registerSessionsStopCommand(sessionsCmd);
|
|
5173
5177
|
registerAttachCommand(sessionsCmd);
|
|
5174
5178
|
registerSessionsInjectCommand(sessionsCmd);
|
|
5175
5179
|
registerSessionsExportCommand(sessionsCmd);
|
|
5176
5180
|
registerSessionsRenderCommand(sessionsCmd);
|
|
5181
|
+
registerSessionsTraceCommand(sessionsCmd);
|
|
5177
5182
|
registerSessionsShareCommand(sessionsCmd);
|
|
5178
5183
|
registerSessionsImportCommand(sessionsCmd);
|
|
5179
5184
|
registerSessionsMigrateCommand(sessionsCmd);
|
|
@@ -61,6 +61,27 @@ function applySecretsDefaults(backend, policy) {
|
|
|
61
61
|
function backendArgs(backend) {
|
|
62
62
|
return backend === 'vault' ? ['--synced'] : ['--backend', backend];
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Provision the signed macOS keychain broker on the explicit onboarding path.
|
|
66
|
+
* This is the async, download-capable trigger the hot sync `getKeychainHelperPath()`
|
|
67
|
+
* fails loud toward: with a bundled `.app` it is a local copy (no network); on a
|
|
68
|
+
* tarball that lacks the bundle it fetches the verified release asset. Best-effort
|
|
69
|
+
* — the wizard's saved prefs must survive an offline provision failure; the next
|
|
70
|
+
* secret op re-points here.
|
|
71
|
+
*/
|
|
72
|
+
async function maybeProvisionKeychainHelper(backend) {
|
|
73
|
+
if (backend !== 'keychain' || process.platform !== 'darwin')
|
|
74
|
+
return;
|
|
75
|
+
const { ensureKeychainHelperInstalledAsync } = await import('../lib/secrets/install-helper.js');
|
|
76
|
+
try {
|
|
77
|
+
await ensureKeychainHelperInstalledAsync();
|
|
78
|
+
console.log(chalk.gray('keychain helper: installed the signed broker for this version.'));
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
console.error(chalk.yellow(`keychain helper not installed: ${err.message}\n` +
|
|
82
|
+
'Re-run `agents setup secrets` once online, or reinstall agents-cli.'));
|
|
83
|
+
}
|
|
84
|
+
}
|
|
64
85
|
function printBackendNotes(backend) {
|
|
65
86
|
if (backend === 'keychain') {
|
|
66
87
|
console.log(chalk.gray('backend: keychain — macOS reads may ask for Touch ID or the device password.'));
|
|
@@ -189,6 +210,8 @@ export async function runSecretsSetupWizard(opts = {}) {
|
|
|
189
210
|
defaultPolicy: policy,
|
|
190
211
|
updatedAt: new Date().toISOString(),
|
|
191
212
|
});
|
|
213
|
+
// Provision the signed keychain broker before any import subprocess reads it.
|
|
214
|
+
await maybeProvisionKeychainHelper(backend);
|
|
192
215
|
await maybeImportSecrets(importSource, {
|
|
193
216
|
bundle: opts.bundle,
|
|
194
217
|
vault: opts.vault,
|
package/dist/commands/share.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type Command } from 'commander';
|
|
2
2
|
import { type ShareConfig } from '../lib/share/config.js';
|
|
3
3
|
import { type CloudflareRequester } from '../lib/share/provision.js';
|
|
4
4
|
import { type PublishResult } from '../lib/share/publish.js';
|
|
5
5
|
import { deleteShare, type DeleteShareResult } from '../lib/share/delete.js';
|
|
6
|
+
import type { PhoenixSession } from '../lib/identity/client.js';
|
|
6
7
|
export declare function formatSharePublishResult(result: PublishResult, json?: boolean): string;
|
|
7
8
|
/** Compare the configured endpoint's last-deployed template hash against the
|
|
8
9
|
* hash of the CURRENT `worker-template.ts` render. A config with no recorded
|
|
@@ -61,10 +62,16 @@ export declare function parseShareListing(user: string, body: string): ShareList
|
|
|
61
62
|
* Worker's `?format=json` route. Fails loud when share was never configured, when
|
|
62
63
|
* the deployed template is known-outdated (RUSH-2449 templateHash), or when the
|
|
63
64
|
* live response proves the route is absent (404 or a non-JSON 200 = the old HTML
|
|
64
|
-
* gallery) — never a silent empty/wrong result.
|
|
65
|
+
* gallery) — never a silent empty/wrong result. Signed-in users hit the managed
|
|
66
|
+
* endpoint; BYO still uses `readShareConfig()`. */
|
|
65
67
|
export declare function runShareList(opts?: {
|
|
66
68
|
githubUser?: string;
|
|
67
69
|
config?: ShareConfig;
|
|
70
|
+
writeToken?: string;
|
|
71
|
+
byo?: boolean;
|
|
72
|
+
/** DI seam — override `readSession()`. Named `phoenixSession` because
|
|
73
|
+
* `session` is already the listing filter (session id). */
|
|
74
|
+
phoenixSession?: PhoenixSession | null;
|
|
68
75
|
fetchListing?: ListingFetchFn;
|
|
69
76
|
/** Only shares published by this agent/harness (case-insensitive, exact). */
|
|
70
77
|
agent?: string;
|
|
@@ -111,6 +118,9 @@ export declare function parseShareRevisions(key: string, body: string): ShareRev
|
|
|
111
118
|
export declare function runShareRevisions(target: string, opts?: {
|
|
112
119
|
githubUser?: string;
|
|
113
120
|
config?: ShareConfig;
|
|
121
|
+
writeToken?: string;
|
|
122
|
+
byo?: boolean;
|
|
123
|
+
session?: PhoenixSession | null;
|
|
114
124
|
fetchListing?: ListingFetchFn;
|
|
115
125
|
}): Promise<ShareRevisionsResult>;
|
|
116
126
|
export declare function formatShareRevisions(result: ShareRevisionsResult, json?: boolean): string;
|
|
@@ -156,6 +166,8 @@ export declare function runShareProvision(opts: {
|
|
|
156
166
|
domain?: string;
|
|
157
167
|
analyticsToken?: string;
|
|
158
168
|
request?: CloudflareRequester;
|
|
169
|
+
/** Bind PHOENIX_ID_BASE even when the mapped hostname is not the managed domain. */
|
|
170
|
+
managed?: boolean;
|
|
159
171
|
}): Promise<void>;
|
|
160
172
|
export interface ShareUpdateResult {
|
|
161
173
|
updated: boolean;
|
|
@@ -167,15 +179,18 @@ export interface ShareUpdateResult {
|
|
|
167
179
|
* current `worker-template.ts`. Reuses the existing account/worker/bucket and
|
|
168
180
|
* write token from `readShareConfig()`/the `share` bundle — never creates a
|
|
169
181
|
* bucket, touches routes/domains, or regenerates the token (see
|
|
170
|
-
* `updateWorker` in `lib/share/provision.ts` for how the token
|
|
171
|
-
* re-upload). Idempotent:
|
|
172
|
-
*
|
|
182
|
+
* `updateWorker` in `lib/share/provision.ts` for how the token — and, on a
|
|
183
|
+
* managed endpoint, `PHOENIX_ID_BASE` — survives the re-upload). Idempotent:
|
|
184
|
+
* no-ops the script upload when the deployed hash already matches unless
|
|
185
|
+
* `force`; a managed endpoint still re-applies `PHOENIX_ID_BASE`. */
|
|
173
186
|
export declare function runShareUpdate(opts?: {
|
|
174
187
|
bundle?: string;
|
|
175
188
|
account?: string;
|
|
176
189
|
token?: string;
|
|
177
190
|
force?: boolean;
|
|
178
191
|
request?: CloudflareRequester;
|
|
192
|
+
/** Bind PHOENIX_ID_BASE even when the configured hostname is not the managed domain. */
|
|
193
|
+
managed?: boolean;
|
|
179
194
|
}): Promise<ShareUpdateResult>;
|
|
180
195
|
/** Join an existing share endpoint (no provisioning): prompt for the endpoint
|
|
181
196
|
* details + write token and persist them. Shared by `agents artifacts share join`
|