@phnx-labs/agents-cli 1.22.52 → 1.22.54
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 +336 -0
- package/README.md +42 -9
- package/dist/bootstrap.js +55 -154
- package/dist/cli/command-registry.d.ts +5 -0
- package/dist/cli/command-registry.js +8 -1
- package/dist/commands/accounts.js +220 -174
- package/dist/commands/apply.js +6 -3
- package/dist/commands/auth-mint.d.ts +8 -0
- package/dist/commands/auth-mint.js +96 -0
- package/dist/commands/auth.js +5 -1
- package/dist/commands/browser.js +1 -1
- package/dist/commands/cost.js +8 -2
- package/dist/commands/daemon.js +2 -2
- package/dist/commands/doctor.js +6 -1
- package/dist/commands/exec.js +26 -17
- package/dist/commands/fleet-capture.js +7 -0
- package/dist/commands/focus.d.ts +1 -0
- package/dist/commands/focus.js +4 -2
- package/dist/commands/go.d.ts +5 -4
- package/dist/commands/go.js +8 -7
- package/dist/commands/insights.js +9 -0
- package/dist/commands/monitors.js +85 -30
- package/dist/commands/output.js +8 -2
- package/dist/commands/repo.js +18 -0
- package/dist/commands/secrets.js +33 -14
- package/dist/commands/sessions-inject.js +8 -3
- package/dist/commands/sessions-picker.js +2 -1
- package/dist/commands/sessions.d.ts +20 -12
- package/dist/commands/sessions.js +94 -40
- package/dist/commands/setup-accounts.d.ts +8 -0
- package/dist/commands/setup-accounts.js +47 -0
- package/dist/commands/setup.d.ts +1 -1
- package/dist/commands/setup.js +11 -2
- package/dist/commands/share.d.ts +52 -3
- package/dist/commands/share.js +262 -18
- package/dist/commands/ssh.d.ts +7 -0
- package/dist/commands/ssh.js +53 -14
- package/dist/commands/status.js +14 -0
- package/dist/commands/sync.js +44 -0
- package/dist/commands/view.d.ts +3 -1
- package/dist/commands/view.js +5 -4
- package/dist/lib/account-registry.d.ts +15 -5
- package/dist/lib/account-registry.js +165 -53
- package/dist/lib/accounting/rotate.d.ts +20 -6
- package/dist/lib/accounting/rotate.js +38 -7
- package/dist/lib/accounting/usage.d.ts +37 -1
- package/dist/lib/accounting/usage.js +71 -6
- package/dist/lib/agent-spec/agents.d.ts +5 -2
- package/dist/lib/agent-spec/agents.js +25 -7
- package/dist/lib/analytics/mix-commands.js +12 -6
- package/dist/lib/answer-router.js +2 -1
- package/dist/lib/auth-mint.d.ts +150 -0
- package/dist/lib/auth-mint.js +434 -0
- package/dist/lib/browser/profiles.d.ts +18 -0
- package/dist/lib/browser/profiles.js +26 -1
- package/dist/lib/browser/registry.d.ts +44 -14
- package/dist/lib/browser/registry.js +141 -45
- package/dist/lib/browser/remote-control.d.ts +9 -7
- package/dist/lib/browser/remote-control.js +9 -7
- package/dist/lib/claude-account-token.d.ts +10 -0
- package/dist/lib/claude-account-token.js +14 -4
- package/dist/lib/config-drift.d.ts +37 -0
- package/dist/lib/config-drift.js +72 -0
- package/dist/lib/daemon/auth-sync-service.d.ts +19 -0
- package/dist/lib/daemon/auth-sync-service.js +34 -0
- package/dist/lib/daemon/daemon.js +30 -4
- package/dist/lib/daemon/runner.js +10 -2
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/device-config.d.ts +3 -3
- package/dist/lib/device-config.js +8 -7
- package/dist/lib/devices/config-migration.js +147 -1
- package/dist/lib/devices/connect.d.ts +26 -0
- package/dist/lib/devices/connect.js +48 -1
- package/dist/lib/devices/device-docs.d.ts +35 -0
- package/dist/lib/devices/device-docs.js +163 -0
- package/dist/lib/devices/discovery-policy.d.ts +14 -2
- package/dist/lib/devices/discovery-policy.js +31 -21
- package/dist/lib/devices/doctor-findings.d.ts +5 -1
- package/dist/lib/devices/doctor-findings.js +19 -1
- package/dist/lib/devices/registry.d.ts +11 -5
- package/dist/lib/devices/registry.js +46 -18
- package/dist/lib/exec.d.ts +88 -30
- package/dist/lib/exec.js +138 -34
- package/dist/lib/feed/feed.d.ts +10 -2
- package/dist/lib/feed/feed.js +35 -2
- package/dist/lib/feed-broadcast.js +1 -1
- package/dist/lib/fleet/apply.d.ts +11 -0
- package/dist/lib/fleet/apply.js +23 -3
- package/dist/lib/fleet/auth-sync.js +5 -3
- package/dist/lib/help.d.ts +9 -0
- package/dist/lib/help.js +29 -1
- package/dist/lib/hosts/dispatch.d.ts +4 -3
- package/dist/lib/hosts/dispatch.js +12 -8
- package/dist/lib/hosts/passthrough.d.ts +1 -10
- package/dist/lib/hosts/passthrough.js +1 -13
- package/dist/lib/hosts/providers/local.d.ts +9 -3
- package/dist/lib/hosts/providers/local.js +23 -12
- package/dist/lib/hosts/reconnect.d.ts +7 -4
- package/dist/lib/hosts/reconnect.js +29 -25
- package/dist/lib/hosts/registry.js +4 -1
- package/dist/lib/hosts/remote-os.js +3 -1
- package/dist/lib/installations/versions.js +9 -1
- package/dist/lib/linux-userns.d.ts +58 -0
- package/dist/lib/linux-userns.js +116 -0
- package/dist/lib/memory.d.ts +26 -0
- package/dist/lib/memory.js +80 -1
- package/dist/lib/monitors/config.d.ts +11 -0
- package/dist/lib/monitors/config.js +8 -0
- package/dist/lib/monitors/engine.js +8 -1
- package/dist/lib/monitors/state.d.ts +37 -1
- package/dist/lib/monitors/state.js +79 -4
- package/dist/lib/permissions-registry.d.ts +2 -0
- package/dist/lib/permissions-registry.js +116 -14
- package/dist/lib/permissions.d.ts +5 -3
- package/dist/lib/permissions.js +25 -27
- package/dist/lib/profiles.d.ts +8 -7
- package/dist/lib/profiles.js +12 -0
- package/dist/lib/project-key.d.ts +9 -0
- package/dist/lib/project-key.js +11 -0
- package/dist/lib/secrets/bundles.d.ts +35 -0
- package/dist/lib/secrets/bundles.js +78 -1
- package/dist/lib/secrets/push.d.ts +3 -8
- package/dist/lib/secrets/push.js +18 -14
- package/dist/lib/secrets/remote.d.ts +9 -18
- package/dist/lib/secrets/remote.js +11 -26
- package/dist/lib/secrets/reserved-sync.d.ts +65 -0
- package/dist/lib/secrets/reserved-sync.js +129 -0
- package/dist/lib/self-heal/checks/hook-manifest.d.ts +2 -0
- package/dist/lib/self-heal/checks/hook-manifest.js +56 -0
- package/dist/lib/self-heal/registry.js +4 -0
- package/dist/lib/self-heal/types.d.ts +1 -1
- package/dist/lib/session/active.d.ts +10 -1
- package/dist/lib/session/active.js +8 -5
- package/dist/lib/session/actor-sidecar.d.ts +7 -0
- package/dist/lib/session/actor-sidecar.js +2 -0
- package/dist/lib/session/db.d.ts +39 -4
- package/dist/lib/session/db.js +168 -31
- package/dist/lib/session/discover.d.ts +32 -4
- package/dist/lib/session/discover.js +126 -37
- package/dist/lib/session/insights.d.ts +14 -0
- package/dist/lib/session/insights.js +25 -2
- package/dist/lib/session/linear.js +1 -1
- package/dist/lib/session/live-metadata.js +1 -0
- package/dist/lib/session/pid-registry.d.ts +7 -0
- package/dist/lib/session/prompt.d.ts +15 -0
- package/dist/lib/session/prompt.js +21 -0
- package/dist/lib/session/shell-programs.d.ts +17 -0
- package/dist/lib/session/shell-programs.js +21 -0
- package/dist/lib/session/state.js +2 -1
- package/dist/lib/session/stream-render.js +2 -1
- package/dist/lib/session/tool-calls.js +2 -5
- package/dist/lib/session/trajectory-html.js +2 -1
- package/dist/lib/session/trajectory.js +3 -12
- package/dist/lib/session/types.d.ts +25 -0
- package/dist/lib/session/types.js +10 -0
- package/dist/lib/share/publish.d.ts +53 -5
- package/dist/lib/share/publish.js +99 -17
- package/dist/lib/share/worker-template.js +594 -64
- package/dist/lib/startup/root-command.js +2 -1
- package/dist/lib/state.d.ts +24 -0
- package/dist/lib/state.js +318 -54
- package/dist/lib/sync-status.d.ts +4 -0
- package/dist/lib/sync-status.js +3 -0
- package/dist/lib/terminal/resolve.d.ts +7 -0
- package/dist/lib/terminal/resolve.js +41 -2
- package/dist/lib/traces/classify.js +24 -19
- package/dist/lib/traces/insights.d.ts +67 -0
- package/dist/lib/traces/insights.js +178 -0
- package/dist/lib/traces/phenotype.d.ts +67 -0
- package/dist/lib/traces/phenotype.js +437 -0
- package/dist/lib/traces/segments.d.ts +133 -0
- package/dist/lib/traces/segments.js +301 -0
- package/dist/lib/traces/sync.d.ts +33 -0
- package/dist/lib/traces/sync.js +11 -2
- package/dist/lib/types.d.ts +47 -1
- package/dist/lib/usage-refresh.js +2 -1
- package/dist/lib/view-types.d.ts +2 -0
- package/dist/lib/watchdog/runner.js +18 -4
- package/package.json +2 -1
|
@@ -18,7 +18,7 @@ import { sanitizeForTerminal, redactSecrets } from '../lib/redact.js';
|
|
|
18
18
|
import { resolveProjectKey } from '../lib/project-key.js';
|
|
19
19
|
import { listProjectDefs, resolveProjectNameForCwd } from '../lib/projects.js';
|
|
20
20
|
import ora from 'ora';
|
|
21
|
-
import { SESSION_AGENTS, isAgentTmuxAlias } from '../lib/session/types.js';
|
|
21
|
+
import { SESSION_AGENTS, isAgentTmuxAlias, sessionDisplayAgent } from '../lib/session/types.js';
|
|
22
22
|
import { discoverArtifacts, readArtifact, resolveArtifact } from '../lib/session/artifacts.js';
|
|
23
23
|
import { looksLikePath, toComparablePath, homeDir, needsWindowsShell, composeWin32CommandLine } from '../lib/platform/index.js';
|
|
24
24
|
import { getActiveSessions, describeActiveDiscoveryHealth, sessionProcessIsLocal, backfillActiveRowsFromIndex, isRunningLiveSession, serializeActiveSessionsForJson, serializeSessionsJson, shortIdFromName } from '../lib/session/active.js';
|
|
@@ -233,9 +233,10 @@ async function renderArtifactsForSession(session, listAll, name) {
|
|
|
233
233
|
console.log(chalk.gray('No file-write artifacts found in this session.'));
|
|
234
234
|
return;
|
|
235
235
|
}
|
|
236
|
-
const
|
|
236
|
+
const shown = sessionDisplayAgent(session);
|
|
237
|
+
const agentColor = colorAgent(shown);
|
|
237
238
|
console.log('');
|
|
238
|
-
console.log(agentColor(
|
|
239
|
+
console.log(agentColor(shown) +
|
|
239
240
|
chalk.gray(` · ${session.shortId} · ${formatRelativeTime(session.timestamp)}`));
|
|
240
241
|
console.log(chalk.gray('─'.repeat(72)));
|
|
241
242
|
for (const a of artifacts) {
|
|
@@ -726,7 +727,8 @@ function fitCell(content, room) {
|
|
|
726
727
|
*/
|
|
727
728
|
export function renderActiveRowLines(s, indent, termW) {
|
|
728
729
|
const idCol = chalk.dim(padToWidth((s.sessionId?.slice(0, 8)) ?? '-', ROW_ID_W));
|
|
729
|
-
const
|
|
730
|
+
const shownKind = sessionDisplayAgent({ agent: s.kind, harness: s.harness });
|
|
731
|
+
const kindCol = colorAgent(shownKind)(padToWidth(truncateToWidth(shownKind, ROW_AGENT_W), ROW_AGENT_W + 1));
|
|
730
732
|
const versionCol = chalk.gray(padToWidth(truncateToWidth(s.version ?? '', ROW_VERSION_W), ROW_VERSION_W + 1));
|
|
731
733
|
const statusCol = statusColor(s.status)(padToWidth(truncateToWidth(activityLabel(s), ROW_STATUS_W - 1), ROW_STATUS_W));
|
|
732
734
|
const ownerCol = chalk.cyan(padToWidth(truncateToWidth(ownerLabel(s), ROW_OWNER_W - 1), ROW_OWNER_W));
|
|
@@ -1010,6 +1012,7 @@ export function serializeResolvedSessionsJson(sessions) {
|
|
|
1010
1012
|
id: session.id,
|
|
1011
1013
|
shortId: session.shortId,
|
|
1012
1014
|
agent: session.agent,
|
|
1015
|
+
harness: session.harness,
|
|
1013
1016
|
origin: session.origin,
|
|
1014
1017
|
timestamp: session.timestamp,
|
|
1015
1018
|
lastActivity: session.lastActivity,
|
|
@@ -1805,7 +1808,8 @@ function runOutcomeDetail(meta) {
|
|
|
1805
1808
|
/** Compact per-session metadata line under a linked session row. */
|
|
1806
1809
|
function linkedSessionMeta(session) {
|
|
1807
1810
|
const parts = [];
|
|
1808
|
-
|
|
1811
|
+
const shown = sessionDisplayAgent(session);
|
|
1812
|
+
parts.push(session.version ? `${shown} v${session.version}` : shown);
|
|
1809
1813
|
if (session.account)
|
|
1810
1814
|
parts.push(session.account);
|
|
1811
1815
|
if (session.model)
|
|
@@ -1974,7 +1978,7 @@ export async function renderSessionPreview(query, scope) {
|
|
|
1974
1978
|
if (outcome.kind !== 'resolved'
|
|
1975
1979
|
&& (!scope.hosts?.length || shouldIncludeLocal(scope.hosts, machineId()))) {
|
|
1976
1980
|
const discovered = applyScopeFilters(await discoverSessions({ all: true, cwd: process.cwd(), limit: 5000, waitForScan: true }), scope);
|
|
1977
|
-
const localMatches = resolveSessionQuery(discovered, query, { indexFallback: false }).matches
|
|
1981
|
+
const localMatches = resolveSessionQuery(discovered, query, { indexFallback: false, scope }).matches
|
|
1978
1982
|
.map(session => ({ ...session, machine: session.machine || machineId() }));
|
|
1979
1983
|
const exact = localMatches.find(session => selectorAllowsEarlyExit(query)
|
|
1980
1984
|
&& session.id.toLowerCase() === query.trim().toLowerCase());
|
|
@@ -2670,7 +2674,11 @@ limitSource) {
|
|
|
2670
2674
|
if (toolEvidenceMode) {
|
|
2671
2675
|
const self = toolSelf;
|
|
2672
2676
|
const selectedSessions = searchQuery
|
|
2673
|
-
? filterSessionsByQuery(sessions, searchQuery
|
|
2677
|
+
? filterSessionsByQuery(sessions, searchQuery, {
|
|
2678
|
+
agent: options.agent,
|
|
2679
|
+
project: options.project,
|
|
2680
|
+
routine: options.routine,
|
|
2681
|
+
})
|
|
2674
2682
|
: sessions;
|
|
2675
2683
|
const localSessions = selectedSessions;
|
|
2676
2684
|
const mayFanOut = options.local !== true && process.env[NO_FANOUT_ENV] !== '1';
|
|
@@ -2767,7 +2775,9 @@ limitSource) {
|
|
|
2767
2775
|
// that merely MENTIONS the id, defeating exact remote resolution. A genuine
|
|
2768
2776
|
// search phrase keeps the ranked metadata+content path.
|
|
2769
2777
|
const filtered = searchQuery
|
|
2770
|
-
? resolveSessionQuery(sessions, searchQuery
|
|
2778
|
+
? resolveSessionQuery(sessions, searchQuery, {
|
|
2779
|
+
scope: { agent: options.agent, project: options.project, routine: options.routine },
|
|
2780
|
+
}).matches
|
|
2771
2781
|
: sessions;
|
|
2772
2782
|
// JSON is the canonical picker contract: enrich the durable rows once
|
|
2773
2783
|
// from the shared live cache so every consumer gets lifecycle/recovery
|
|
@@ -2876,7 +2886,7 @@ limitSource) {
|
|
|
2876
2886
|
const message = pathFilter
|
|
2877
2887
|
? `Search sessions (${path.basename(pathFilter)}):`
|
|
2878
2888
|
: formatSearchMessage(options);
|
|
2879
|
-
const picked = await pickSessionInteractive(sessions, message, searchQuery, hiddenCount);
|
|
2889
|
+
const picked = await pickSessionInteractive(sessions, message, searchQuery, hiddenCount, undefined, { agent: options.agent, project: options.project, routine: options.routine });
|
|
2880
2890
|
if (picked) {
|
|
2881
2891
|
await handlePickedSession(picked);
|
|
2882
2892
|
return;
|
|
@@ -2884,7 +2894,13 @@ limitSource) {
|
|
|
2884
2894
|
return;
|
|
2885
2895
|
}
|
|
2886
2896
|
// Non-interactive fallback (piped output) or --flat/--tree.
|
|
2887
|
-
const filtered = searchQuery
|
|
2897
|
+
const filtered = searchQuery
|
|
2898
|
+
? filterSessionsByQuery(sessions, searchQuery, {
|
|
2899
|
+
agent: options.agent,
|
|
2900
|
+
project: options.project,
|
|
2901
|
+
routine: options.routine,
|
|
2902
|
+
})
|
|
2903
|
+
: sessions;
|
|
2888
2904
|
const liveIndex = await maybeLiveIndex(options);
|
|
2889
2905
|
printSessionTable(filtered, hiddenCount, options.tree === true, liveIndex);
|
|
2890
2906
|
// Every listing path must say what it dropped — a hidden default that stays
|
|
@@ -2996,7 +3012,8 @@ function timeCell(age, topicSlack) {
|
|
|
2996
3012
|
* when `showTicket` — otherwise a listing with no refs would waste a column of
|
|
2997
3013
|
* dashes and needlessly truncate the topic. Worktree stays a trailing badge. */
|
|
2998
3014
|
export function flatSessionRow(session, live, showTicket = false, cols = {}, bookmarked = false) {
|
|
2999
|
-
const
|
|
3015
|
+
const shown = sessionDisplayAgent(session);
|
|
3016
|
+
const agentColor = colorAgent(shown);
|
|
3000
3017
|
const age = sessionAgeParts(session.timestamp, session.lastActivity);
|
|
3001
3018
|
const project = session.project || '-';
|
|
3002
3019
|
const tag = originTag(session) || teamTag(session);
|
|
@@ -3045,7 +3062,7 @@ export function flatSessionRow(session, live, showTicket = false, cols = {}, boo
|
|
|
3045
3062
|
const topicW = Math.max(MIN_TOPIC_W, width - fixedW - modelW - when.extraW);
|
|
3046
3063
|
return (bookmarkCell +
|
|
3047
3064
|
chalk.white(padToWidth(truncateToWidth(session.shortId, 9), 10)) +
|
|
3048
|
-
agentColor(padToWidth(truncateToWidth(
|
|
3065
|
+
agentColor(padToWidth(truncateToWidth(shown, 8), 9)) +
|
|
3049
3066
|
chalk.yellow(padToWidth(truncateToWidth(session.version || '-', 7), 8)) +
|
|
3050
3067
|
(modelW ? chalk.yellow(padToWidth(truncateToWidth(modelLabel(session.model), modelW - 1), modelW)) : '') +
|
|
3051
3068
|
machineCell +
|
|
@@ -3060,7 +3077,8 @@ export function flatSessionRow(session, live, showTicket = false, cols = {}, boo
|
|
|
3060
3077
|
}
|
|
3061
3078
|
/** One tree-mode row (grouped under a dir header): id · agent · badges · topic · time. No version/project column. */
|
|
3062
3079
|
function treeSessionRow(session, live) {
|
|
3063
|
-
const
|
|
3080
|
+
const shown = sessionDisplayAgent(session);
|
|
3081
|
+
const agentColor = colorAgent(shown);
|
|
3064
3082
|
const age = sessionAgeParts(session.timestamp, session.lastActivity);
|
|
3065
3083
|
const tag = originTag(session) || teamTag(session);
|
|
3066
3084
|
const label = session.label;
|
|
@@ -3082,7 +3100,7 @@ function treeSessionRow(session, live) {
|
|
|
3082
3100
|
const topicW = Math.max(12, baseTopicW - when.extraW);
|
|
3083
3101
|
return (' ' +
|
|
3084
3102
|
chalk.dim(padToWidth(session.shortId, 9)) +
|
|
3085
|
-
agentColor(padToWidth(truncateToWidth(
|
|
3103
|
+
agentColor(padToWidth(truncateToWidth(shown, 7), 8)) +
|
|
3086
3104
|
(badges ? badges + ' ' : '') +
|
|
3087
3105
|
(glyph ? glyph + ' ' : '') +
|
|
3088
3106
|
statusCell +
|
|
@@ -3246,7 +3264,8 @@ const TEAM_HANDLE_W = 16;
|
|
|
3246
3264
|
* identity the `--teams` view exists to show (RUSH-1997).
|
|
3247
3265
|
*/
|
|
3248
3266
|
function teamMemberRow(session, live) {
|
|
3249
|
-
const
|
|
3267
|
+
const shown = sessionDisplayAgent(session);
|
|
3268
|
+
const agentColor = colorAgent(shown);
|
|
3250
3269
|
const origin = session.teamOrigin;
|
|
3251
3270
|
const age = sessionAgeParts(session.timestamp, session.lastActivity);
|
|
3252
3271
|
const handle = safeTeamText(origin?.handle) ?? session.shortId;
|
|
@@ -3267,7 +3286,7 @@ function teamMemberRow(session, live) {
|
|
|
3267
3286
|
const topicW = Math.max(12, baseTopicW - when.extraW);
|
|
3268
3287
|
return (' ' +
|
|
3269
3288
|
chalk.dim(padToWidth(session.shortId, 9)) +
|
|
3270
|
-
agentColor(padToWidth(truncateToWidth(
|
|
3289
|
+
agentColor(padToWidth(truncateToWidth(shown, 7), 8)) +
|
|
3271
3290
|
chalk.yellow(padToWidth(truncateToWidth(mode || '-', TEAM_MODE_W), TEAM_MODE_W + 1)) +
|
|
3272
3291
|
(badges ? badges + ' ' : '') +
|
|
3273
3292
|
(glyph ? glyph + ' ' : '') +
|
|
@@ -3444,13 +3463,14 @@ function renderArchivedSession(session, mode, options = {}) {
|
|
|
3444
3463
|
}, null, 2));
|
|
3445
3464
|
return;
|
|
3446
3465
|
}
|
|
3447
|
-
const
|
|
3466
|
+
const shown = sessionDisplayAgent(session);
|
|
3467
|
+
const agentColor = colorAgent(shown);
|
|
3448
3468
|
const absTime = formatAbsoluteTime(session.timestamp);
|
|
3449
3469
|
const title = session.label || session.topic;
|
|
3450
3470
|
console.log('');
|
|
3451
3471
|
if (title)
|
|
3452
3472
|
console.log(chalk.bold.white(title));
|
|
3453
|
-
console.log(agentColor(
|
|
3473
|
+
console.log(agentColor(shown) +
|
|
3454
3474
|
(session.version ? chalk.yellow(` ${session.version}`) : '') +
|
|
3455
3475
|
(session.project ? chalk.cyan(` ${session.project}`) : '') +
|
|
3456
3476
|
chalk.gray(` ${absTime} (${formatRelativeTime(session.timestamp)})`) +
|
|
@@ -3481,7 +3501,7 @@ async function renderSession(session, mode, filters, options = {}) {
|
|
|
3481
3501
|
console.log(chalk.yellow('Session transcript not available (file no longer exists).'));
|
|
3482
3502
|
console.log(chalk.gray(`Path: ${session.filePath}`));
|
|
3483
3503
|
if (session.version)
|
|
3484
|
-
console.log(chalk.gray(`Version: ${session
|
|
3504
|
+
console.log(chalk.gray(`Version: ${sessionDisplayAgent(session)} ${session.version}`));
|
|
3485
3505
|
if (session.project)
|
|
3486
3506
|
console.log(chalk.gray(`Project: ${session.project}`));
|
|
3487
3507
|
if (session.account)
|
|
@@ -3489,11 +3509,12 @@ async function renderSession(session, mode, filters, options = {}) {
|
|
|
3489
3509
|
console.log(chalk.gray(`Time: ${session.timestamp}`));
|
|
3490
3510
|
return;
|
|
3491
3511
|
}
|
|
3492
|
-
const spinner = ora(`Parsing ${session
|
|
3512
|
+
const spinner = ora(`Parsing ${sessionDisplayAgent(session)} session...`).start();
|
|
3493
3513
|
const parsedEvents = parseSession(session.filePath, session.agent);
|
|
3494
3514
|
spinner.stop();
|
|
3495
3515
|
let events = filterEvents(parsedEvents, filters);
|
|
3496
|
-
const
|
|
3516
|
+
const shown = sessionDisplayAgent(session);
|
|
3517
|
+
const agentColor = colorAgent(shown);
|
|
3497
3518
|
console.log('');
|
|
3498
3519
|
if (mode === 'summary') {
|
|
3499
3520
|
const stats = computeSummaryStats(events);
|
|
@@ -3507,7 +3528,7 @@ async function renderSession(session, mode, filters, options = {}) {
|
|
|
3507
3528
|
const badges = signalBadges(metaSignals(session));
|
|
3508
3529
|
console.log(chalk.bold.white(title) + (badges ? ' ' + badges : ''));
|
|
3509
3530
|
}
|
|
3510
|
-
console.log(agentColor(
|
|
3531
|
+
console.log(agentColor(shown) +
|
|
3511
3532
|
(session.version ? chalk.yellow(` ${session.version}`) : '') +
|
|
3512
3533
|
modelStr +
|
|
3513
3534
|
(session.project ? chalk.cyan(` ${session.project}`) + branchStr : branchStr) +
|
|
@@ -3521,7 +3542,7 @@ async function renderSession(session, mode, filters, options = {}) {
|
|
|
3521
3542
|
return;
|
|
3522
3543
|
}
|
|
3523
3544
|
if (mode === 'markdown') {
|
|
3524
|
-
console.log(agentColor(
|
|
3545
|
+
console.log(agentColor(shown) +
|
|
3525
3546
|
(session.version ? chalk.yellow(` ${session.version}`) : '') +
|
|
3526
3547
|
(session.project ? chalk.cyan(` ${session.project}`) : '') +
|
|
3527
3548
|
chalk.gray(` ${formatRelativeTime(session.timestamp)}`) +
|
|
@@ -3662,7 +3683,8 @@ export function liveHostLabel(a) {
|
|
|
3662
3683
|
return viewer && viewer !== a.host ? `${a.host}→${viewer}` : a.host;
|
|
3663
3684
|
}
|
|
3664
3685
|
export function formatPickerLabel(s, query, cols = {}, ssh, host = '', bookmarked = false, live) {
|
|
3665
|
-
const
|
|
3686
|
+
const shown = sessionDisplayAgent(s);
|
|
3687
|
+
const agentColor = colorAgent(shown);
|
|
3666
3688
|
const age = sessionAgeParts(s.timestamp, s.lastActivity);
|
|
3667
3689
|
const project = s.project || '-';
|
|
3668
3690
|
// SSH-launch origin (live rows only): mirrors the flat listing's `ssh←<device>`
|
|
@@ -3727,7 +3749,7 @@ export function formatPickerLabel(s, query, cols = {}, ssh, host = '', bookmarke
|
|
|
3727
3749
|
// live row with no session id is named by its pid or cloud task, which can
|
|
3728
3750
|
// run past the column and shunt every later column out of alignment.
|
|
3729
3751
|
chalk.white(padRight(truncate(s.shortId, 9), 10)) +
|
|
3730
|
-
agentColor(padRight(truncate(
|
|
3752
|
+
agentColor(padRight(truncate(shown, 8), 9)) +
|
|
3731
3753
|
chalk.yellow(padRight(truncate(versionStr, 7), 8)) +
|
|
3732
3754
|
machineCell +
|
|
3733
3755
|
hostCell +
|
|
@@ -3754,7 +3776,7 @@ const PICKER_TIPS = [
|
|
|
3754
3776
|
export function formatPickerTip(sessions) {
|
|
3755
3777
|
return chalk.gray(PICKER_TIPS[sessions.length % PICKER_TIPS.length]);
|
|
3756
3778
|
}
|
|
3757
|
-
export async function pickSessionInteractive(sessions, message = 'Search sessions:', initialSearch, hiddenCount = 0, enterHint) {
|
|
3779
|
+
export async function pickSessionInteractive(sessions, message = 'Search sessions:', initialSearch, hiddenCount = 0, enterHint, scope) {
|
|
3758
3780
|
// The hidden-session footer is console.log'd above the Inquirer prompt, so it
|
|
3759
3781
|
// scrolls the viewport the picker can't measure; tell the picker to reserve for
|
|
3760
3782
|
// it (see pickerPageSize) so the preview and the footer stay on screen together.
|
|
@@ -3774,7 +3796,7 @@ export async function pickSessionInteractive(sessions, message = 'Search session
|
|
|
3774
3796
|
// Typing: search the full pool.
|
|
3775
3797
|
if (!query.trim())
|
|
3776
3798
|
return sessions;
|
|
3777
|
-
return filterSessionsByQuery(sessions, query);
|
|
3799
|
+
return filterSessionsByQuery(sessions, query, scope);
|
|
3778
3800
|
},
|
|
3779
3801
|
labelFor: (s, query) => formatPickerLabel(s, query, cols),
|
|
3780
3802
|
pageSize: PICKER_RECENT_COUNT,
|
|
@@ -4169,7 +4191,7 @@ export function resolveSessionQuery(pool, query, options = {}) {
|
|
|
4169
4191
|
const matches = options.indexFallback === false ? [] : findSessionsById(normalized);
|
|
4170
4192
|
return { matches, byId: true, completeId };
|
|
4171
4193
|
}
|
|
4172
|
-
return { matches: filterSessionsByQuery(pool, normalized), byId: false, completeId };
|
|
4194
|
+
return { matches: filterSessionsByQuery(pool, normalized, options.scope), byId: false, completeId };
|
|
4173
4195
|
}
|
|
4174
4196
|
/** Explain an ambiguous resolution. Only a short id can be lengthened: a complete
|
|
4175
4197
|
* id is already maximal, and a search phrase was never an id to begin with. */
|
|
@@ -4208,7 +4230,7 @@ export function fleetNotFoundMessage(query, deviceCount, unreachable) {
|
|
|
4208
4230
|
return lines;
|
|
4209
4231
|
}
|
|
4210
4232
|
/** Filter and rank sessions by a multi-term search query across metadata and content. */
|
|
4211
|
-
export function filterSessionsByQuery(sessions, query) {
|
|
4233
|
+
export function filterSessionsByQuery(sessions, query, scope) {
|
|
4212
4234
|
const trimmed = query?.trim().toLowerCase() || '';
|
|
4213
4235
|
if (!trimmed)
|
|
4214
4236
|
return sessions;
|
|
@@ -4218,7 +4240,9 @@ export function filterSessionsByQuery(sessions, query) {
|
|
|
4218
4240
|
return sessions.filter((session) => session.agent === agent && session.version === version);
|
|
4219
4241
|
}
|
|
4220
4242
|
const terms = trimmed.split(/\s+/).filter(Boolean);
|
|
4221
|
-
|
|
4243
|
+
// Hydrate FTS hits missing from the pool (PHNX-2767), then drop hits that
|
|
4244
|
+
// fail --project/--agent/--routine so those flags are not undone by the union.
|
|
4245
|
+
const contentIndex = scopedContentIndex(sessions, trimmed, scope);
|
|
4222
4246
|
// If the query exactly matches a session label, short-circuit the structural
|
|
4223
4247
|
// scorer (which would otherwise surface every session whose topic happens to
|
|
4224
4248
|
// contain the same words) and return only the label hits.
|
|
@@ -4227,7 +4251,15 @@ export function filterSessionsByQuery(sessions, query) {
|
|
|
4227
4251
|
if (exactLabelHits.length > 0) {
|
|
4228
4252
|
return exactLabelHits.sort((a, b) => (b._bm25Score ?? 0) - (a._bm25Score ?? 0));
|
|
4229
4253
|
}
|
|
4230
|
-
|
|
4254
|
+
// The listing pool is a page of the index. FTS hits the whole index. Union
|
|
4255
|
+
// so a grep-visible transcript is returned even when it missed the page
|
|
4256
|
+
// (PHNX-2767).
|
|
4257
|
+
const poolById = new Map(sessions.map(s => [s.id, s]));
|
|
4258
|
+
for (const [id, hit] of contentIndex) {
|
|
4259
|
+
if (!poolById.has(id))
|
|
4260
|
+
poolById.set(id, hit);
|
|
4261
|
+
}
|
|
4262
|
+
return [...poolById.values()]
|
|
4231
4263
|
.map(session => ({ session, score: scoreSessionQuery(session, terms) }))
|
|
4232
4264
|
.filter(entry => {
|
|
4233
4265
|
// Include if scored by topic/project/etc, or matched by content search
|
|
@@ -4304,6 +4336,11 @@ function scoreSessionQuery(session, terms) {
|
|
|
4304
4336
|
* Without this, a query like "scoped search" could match sessions in BOTH
|
|
4305
4337
|
* the project you specified AND elsewhere, producing an ambiguity error
|
|
4306
4338
|
* even though the user already pointed at the correct scope.
|
|
4339
|
+
*
|
|
4340
|
+
* PHNX-2767 hydrates FTS hits missing from the listing pool *after* this
|
|
4341
|
+
* runs, so callers that search must also pass the same scope into
|
|
4342
|
+
* `filterSessionsByQuery` / `scopedContentIndex` or the union
|
|
4343
|
+
* reintroduces the rows this function just dropped.
|
|
4307
4344
|
*/
|
|
4308
4345
|
export function applyScopeFilters(sessions, scope) {
|
|
4309
4346
|
let filtered = sessions;
|
|
@@ -4340,6 +4377,23 @@ export function applyScopeFilters(sessions, scope) {
|
|
|
4340
4377
|
}
|
|
4341
4378
|
return filtered;
|
|
4342
4379
|
}
|
|
4380
|
+
/**
|
|
4381
|
+
* PHNX-2767 hydrates FTS hits missing from the listing pool. That union is
|
|
4382
|
+
* unscoped on purpose (cwd/limit are a page of the index, not a filter).
|
|
4383
|
+
* `--project` / `--agent` / `--routine` ARE filters: drop hydrated hits that
|
|
4384
|
+
* fail them so content search cannot undo a scope the user already set.
|
|
4385
|
+
*/
|
|
4386
|
+
function scopedContentIndex(sessions, query, scope) {
|
|
4387
|
+
const hits = searchContentIndex(sessions, query);
|
|
4388
|
+
if (!scope || (!scope.agent && !scope.project && !scope.routine))
|
|
4389
|
+
return hits;
|
|
4390
|
+
const kept = new Map();
|
|
4391
|
+
for (const [id, session] of hits) {
|
|
4392
|
+
if (applyScopeFilters([session], scope).length > 0)
|
|
4393
|
+
kept.set(id, session);
|
|
4394
|
+
}
|
|
4395
|
+
return kept;
|
|
4396
|
+
}
|
|
4343
4397
|
export function artifactLookupScope(agent, project, routine) {
|
|
4344
4398
|
return { agent, project, routine };
|
|
4345
4399
|
}
|
|
@@ -4355,7 +4409,7 @@ async function renderArtifactsGlobal(query, listAll, name, scope) {
|
|
|
4355
4409
|
});
|
|
4356
4410
|
tracker.stop();
|
|
4357
4411
|
const allSessions = applyScopeFilters(discovered, scope);
|
|
4358
|
-
const { matches: queryMatches, byId, completeId } = resolveSessionQuery(allSessions, query);
|
|
4412
|
+
const { matches: queryMatches, byId, completeId } = resolveSessionQuery(allSessions, query, { scope });
|
|
4359
4413
|
if (queryMatches.length === 0) {
|
|
4360
4414
|
spinner.stop();
|
|
4361
4415
|
if (byId)
|
|
@@ -4452,7 +4506,7 @@ async function renderOneSession(query, mode, scope) {
|
|
|
4452
4506
|
tracker.stop();
|
|
4453
4507
|
const allSessions = applyScopeFilters(discovered, scope);
|
|
4454
4508
|
let session;
|
|
4455
|
-
const resolution = resolveSessionQuery(allSessions, query);
|
|
4509
|
+
const resolution = resolveSessionQuery(allSessions, query, { scope });
|
|
4456
4510
|
let queryMatches = resolution.matches;
|
|
4457
4511
|
let byId = resolution.byId;
|
|
4458
4512
|
const completeId = resolution.completeId;
|
|
@@ -4464,7 +4518,7 @@ async function renderOneSession(query, mode, scope) {
|
|
|
4464
4518
|
// echoes the id in a resume prompt. Gate on looksLikeSessionId, not just
|
|
4465
4519
|
// completeId, so a short id resolves to "no match" rather than fuzzy content.
|
|
4466
4520
|
if (queryMatches.length === 0 && !looksLikeSessionId(query)) {
|
|
4467
|
-
const contentResults =
|
|
4521
|
+
const contentResults = scopedContentIndex(allSessions, query, scope);
|
|
4468
4522
|
if (contentResults.size > 0) {
|
|
4469
4523
|
const matchedSessions = Array.from(contentResults.values())
|
|
4470
4524
|
.sort((a, b) => (b._bm25Score ?? 0) - (a._bm25Score ?? 0));
|
|
@@ -4659,16 +4713,16 @@ export function fleetCandidatesByQuery(rows, query, trustResolvedRows = false) {
|
|
|
4659
4713
|
});
|
|
4660
4714
|
}
|
|
4661
4715
|
/** Resolve through the canonical metadata+content union used by keyword search. */
|
|
4662
|
-
function resolveIndexedMetadataRows(indexed, selector) {
|
|
4716
|
+
function resolveIndexedMetadataRows(indexed, selector, scope) {
|
|
4663
4717
|
const alias = resolveSessionAlias(selector);
|
|
4664
4718
|
if (alias.kind === 'resolved') {
|
|
4665
|
-
return resolveSessionQuery(indexed, alias.sessionId, { indexFallback: false }).matches;
|
|
4719
|
+
return resolveSessionQuery(indexed, alias.sessionId, { indexFallback: false, scope }).matches;
|
|
4666
4720
|
}
|
|
4667
4721
|
if (alias.kind === 'ambiguous') {
|
|
4668
4722
|
const ids = new Set(alias.sessionIds.map(id => id.toLowerCase()));
|
|
4669
4723
|
return indexed.filter(session => ids.has(session.id.toLowerCase()));
|
|
4670
4724
|
}
|
|
4671
|
-
return resolveSessionQuery(indexed, selector, { indexFallback: false }).matches;
|
|
4725
|
+
return resolveSessionQuery(indexed, selector, { indexFallback: false, scope }).matches;
|
|
4672
4726
|
}
|
|
4673
4727
|
/**
|
|
4674
4728
|
* ID-shaped selectors go straight to SQLite's primary-key/short-id lookup.
|
|
@@ -4779,7 +4833,7 @@ export async function computeLocalMetadataMatches(selector, scope, deps = {}) {
|
|
|
4779
4833
|
const includeLocal = !scope.hosts?.length || shouldIncludeLocal(scope.hosts, localMachine);
|
|
4780
4834
|
if (!includeLocal)
|
|
4781
4835
|
return [];
|
|
4782
|
-
const indexed = resolveIndexedMetadataRows(indexedRowsForSelector(selector, scope), selector);
|
|
4836
|
+
const indexed = resolveIndexedMetadataRows(indexedRowsForSelector(selector, scope), selector, scope);
|
|
4783
4837
|
if (indexed.length > 0 || !looksLikeSessionId(selector)) {
|
|
4784
4838
|
return indexed.map(session => ({ ...session, machine: session.machine || localMachine }));
|
|
4785
4839
|
}
|
|
@@ -4796,7 +4850,7 @@ export async function computeLocalMetadataMatches(selector, scope, deps = {}) {
|
|
|
4796
4850
|
*/
|
|
4797
4851
|
export async function liveMetadataMatches(selector, scope, self, deps = {}) {
|
|
4798
4852
|
const load = deps.loadActive ?? loadLocalActiveSessions;
|
|
4799
|
-
const match = (metas) => resolveIndexedMetadataRows(applyScopeFilters(metas, scope), selector);
|
|
4853
|
+
const match = (metas) => resolveIndexedMetadataRows(applyScopeFilters(metas, scope), selector, scope);
|
|
4800
4854
|
try {
|
|
4801
4855
|
const cached = liveSessionMetas((await load()).sessions, self, Date.now());
|
|
4802
4856
|
const hit = match(cached);
|
|
@@ -5013,7 +5067,7 @@ export function registerSessionsCommands(program) {
|
|
|
5013
5067
|
.option('--preview', 'With a session id/query: print a compact preview and exit (no pager)');
|
|
5014
5068
|
setHelpSections(sessionsCmd, {
|
|
5015
5069
|
examples: `
|
|
5016
|
-
# Search
|
|
5070
|
+
# Search indexed transcripts by topic, file path, or command
|
|
5017
5071
|
agents sessions "add auth middleware"
|
|
5018
5072
|
|
|
5019
5073
|
# Read a session as markdown (user + assistant + thinking + tools)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `agents setup accounts` — mint a Claude setup-token so unattended usage/probe
|
|
3
|
+
* is not stuck on "usage pending". Delegates to the same mint engine as
|
|
4
|
+
* `agents accounts mint` / `agents auth mint`.
|
|
5
|
+
*/
|
|
6
|
+
import type { Command } from 'commander';
|
|
7
|
+
export declare function runAccountsSetupWizard(): Promise<void>;
|
|
8
|
+
export declare function registerSetupAccountsCommand(setupCmd: Command): void;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { confirm } from '@inquirer/prompts';
|
|
3
|
+
import { isInteractiveTerminal, isPromptCancelled } from './utils.js';
|
|
4
|
+
import { hasMintedSetupToken, mintAndSeed } from '../lib/auth-mint.js';
|
|
5
|
+
export async function runAccountsSetupWizard() {
|
|
6
|
+
const status = hasMintedSetupToken();
|
|
7
|
+
if (status.ready) {
|
|
8
|
+
console.log(chalk.green(`Setup-token already minted (${status.detail}).`));
|
|
9
|
+
console.log(chalk.gray('Re-mint with: agents accounts mint claude'));
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!isInteractiveTerminal()) {
|
|
13
|
+
console.log(chalk.yellow('No Claude setup-token on this machine.'));
|
|
14
|
+
console.log(chalk.gray('Mint one with: agents accounts mint claude'));
|
|
15
|
+
console.log(chalk.gray('Already have a token: agents accounts mint claude --token-stdin'));
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
const proceed = await confirm({
|
|
20
|
+
message: 'Mint a Claude setup-token now? (opens a browser; seeds a named account + the reserved auth bundle)',
|
|
21
|
+
default: true,
|
|
22
|
+
});
|
|
23
|
+
if (!proceed) {
|
|
24
|
+
console.log(chalk.gray('Skipped. Run `agents accounts mint claude` when ready.'));
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const result = await mintAndSeed({ harness: 'claude' });
|
|
28
|
+
console.log(chalk.green(`Minted account '${result.account}' for ${result.email}.`));
|
|
29
|
+
}
|
|
30
|
+
export function registerSetupAccountsCommand(setupCmd) {
|
|
31
|
+
setupCmd
|
|
32
|
+
.command('accounts')
|
|
33
|
+
.description('Mint a Claude setup-token into a named account (unattended usage/probe).')
|
|
34
|
+
.action(async () => {
|
|
35
|
+
try {
|
|
36
|
+
await runAccountsSetupWizard();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
if (isPromptCancelled(err)) {
|
|
40
|
+
console.log(chalk.yellow('\nCancelled'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
console.error(chalk.red(err instanceof Error ? err.message : String(err)));
|
|
44
|
+
process.exitCode = 1;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
package/dist/commands/setup.d.ts
CHANGED
|
@@ -31,7 +31,7 @@ export declare function ensureInitialized(program: Command): Promise<void>;
|
|
|
31
31
|
* wizard. Never throws — a cancel or an optional wizard's error just skips the
|
|
32
32
|
* rest and lets core setup complete.
|
|
33
33
|
*/
|
|
34
|
-
export type SetupPhase = 'browser' | 'computer' | 'share' | 'secrets' | 'fleet' | 'watchdog' | 'preferences';
|
|
34
|
+
export type SetupPhase = 'browser' | 'computer' | 'share' | 'secrets' | 'accounts' | 'fleet' | 'watchdog' | 'preferences';
|
|
35
35
|
export type SetupStatusState = 'ready' | 'missing' | 'n/a';
|
|
36
36
|
export interface SetupStatusRow {
|
|
37
37
|
phase: 'core' | SetupPhase;
|
package/dist/commands/setup.js
CHANGED
|
@@ -24,7 +24,9 @@ import { runShareWizard } from './artifacts-setup.js';
|
|
|
24
24
|
import { registerSetupMineCommand } from './setup-mine.js';
|
|
25
25
|
import { registerSetupSecretsCommand } from './setup-secrets.js';
|
|
26
26
|
import { registerSetupFleetCommand } from './setup-fleet.js';
|
|
27
|
+
import { registerSetupAccountsCommand, runAccountsSetupWizard } from './setup-accounts.js';
|
|
27
28
|
import { registerSetupWatchdogCommand, runWatchdogSetupWizard } from './setup-watchdog.js';
|
|
29
|
+
import { hasMintedSetupToken } from '../lib/auth-mint.js';
|
|
28
30
|
import { registerAliasCommand } from './alias.js';
|
|
29
31
|
import { registerBetaCommands } from './beta.js';
|
|
30
32
|
import { runPreferencesStep } from './setup-preferences.js';
|
|
@@ -276,6 +278,7 @@ export async function getSetupStatus() {
|
|
|
276
278
|
const devices = await loadDevices();
|
|
277
279
|
const coreReady = isGitRepo(getAgentsDir());
|
|
278
280
|
const secretsReady = fs.existsSync(setupSecretsPrefsPath());
|
|
281
|
+
const minted = hasMintedSetupToken();
|
|
279
282
|
const shareConfig = readShareConfig();
|
|
280
283
|
const watchdogEnabled = getConfigValue('watchdog.enabled').value === true;
|
|
281
284
|
const interactiveHost = getConfigValue('interactive.host').value;
|
|
@@ -285,6 +288,7 @@ export async function getSetupStatus() {
|
|
|
285
288
|
{ phase: 'browser', state: browserReady ? 'ready' : 'missing', detail: browserReady ? `profile ${browserProfile.name}` : browserProfile ? `profile ${browserProfile.name} cannot launch here` : installedBrowsers.length ? 'no default profile' : 'no supported browser found' },
|
|
286
289
|
{ phase: 'computer', state: computerState, detail: computerState === 'ready' ? 'helper trusted' : computerState === 'n/a' ? 'macOS local setup only' : 'helper not running or not trusted' },
|
|
287
290
|
{ phase: 'secrets', state: secretsReady ? 'ready' : 'missing', detail: secretsReady ? 'defaults chosen' : 'defaults not chosen' },
|
|
291
|
+
{ phase: 'accounts', state: minted.ready ? 'ready' : 'missing', detail: minted.detail },
|
|
288
292
|
{ phase: 'fleet', state: Object.keys(devices).length ? 'ready' : 'missing', detail: Object.keys(devices).length ? `${Object.keys(devices).length} device${Object.keys(devices).length === 1 ? '' : 's'} registered` : 'no devices registered' },
|
|
289
293
|
{ phase: 'share', state: shareConfig ? 'ready' : 'missing', detail: shareConfig?.baseUrl ?? 'endpoint not configured' },
|
|
290
294
|
{ phase: 'watchdog', state: watchdogEnabled ? 'ready' : 'missing', detail: watchdogEnabled ? 'enabled on this device' : 'disabled on this device' },
|
|
@@ -308,6 +312,8 @@ async function runSetupPhase(phase) {
|
|
|
308
312
|
await runShareWizard();
|
|
309
313
|
else if (phase === 'secrets')
|
|
310
314
|
await import('./setup-secrets.js').then((m) => m.runSecretsSetupWizard());
|
|
315
|
+
else if (phase === 'accounts')
|
|
316
|
+
await runAccountsSetupWizard();
|
|
311
317
|
else if (phase === 'fleet')
|
|
312
318
|
await import('./setup-fleet.js').then((m) => m.runFleetSetupWizard());
|
|
313
319
|
else if (phase === 'watchdog')
|
|
@@ -364,19 +370,20 @@ export function registerSetupCommand(program) {
|
|
|
364
370
|
.description('Set up agents-cli, or re-open the capability onboarding hub.')
|
|
365
371
|
.option('-f, --force', 'Re-run setup even if ~/.agents/.system/ already exists (use with caution)')
|
|
366
372
|
.option('--no-system-repo', 'Skip cloning the system repo (you must populate ~/.agents/.system/ yourself)');
|
|
367
|
-
// Capability subcommands: `agents setup browser|computer|mine|secrets|fleet|alias|beta`.
|
|
373
|
+
// Capability subcommands: `agents setup browser|computer|mine|secrets|accounts|fleet|alias|beta`.
|
|
368
374
|
// Share/artifact publishing is set up by `agents artifacts setup` (RUSH-2580);
|
|
369
375
|
// the hub below still offers it as a phase via runShareWizard.
|
|
370
376
|
registerSetupBrowserCommand(setupCmd);
|
|
371
377
|
registerSetupComputerCommand(setupCmd);
|
|
372
378
|
registerSetupMineCommand(setupCmd);
|
|
373
379
|
registerSetupSecretsCommand(setupCmd);
|
|
380
|
+
registerSetupAccountsCommand(setupCmd);
|
|
374
381
|
registerSetupFleetCommand(setupCmd);
|
|
375
382
|
registerSetupWatchdogCommand(setupCmd);
|
|
376
383
|
registerAliasCommand(setupCmd);
|
|
377
384
|
registerBetaCommands(setupCmd);
|
|
378
385
|
setupCmd.command('status')
|
|
379
|
-
.description('Show setup readiness for core, browser, computer, secrets, fleet, share, watchdog, and preferences.')
|
|
386
|
+
.description('Show setup readiness for core, browser, computer, secrets, accounts, fleet, share, watchdog, and preferences.')
|
|
380
387
|
.option('--json', 'print machine-readable JSON')
|
|
381
388
|
.action(async (options) => {
|
|
382
389
|
const rows = await getSetupStatus();
|
|
@@ -399,6 +406,7 @@ export function registerSetupCommand(program) {
|
|
|
399
406
|
agents setup browser
|
|
400
407
|
agents setup computer
|
|
401
408
|
agents setup secrets
|
|
409
|
+
agents setup accounts
|
|
402
410
|
agents setup fleet
|
|
403
411
|
agents setup watchdog
|
|
404
412
|
agents setup alias add teams
|
|
@@ -416,6 +424,7 @@ export function registerSetupCommand(program) {
|
|
|
416
424
|
agents setup computer # install the signed macOS helper + grant permissions
|
|
417
425
|
agents artifacts setup # provision or join a Cloudflare share endpoint
|
|
418
426
|
agents setup secrets # choose secrets backend/policy defaults + import
|
|
427
|
+
agents setup accounts # mint a Claude setup-token for unattended usage/probe
|
|
419
428
|
agents setup fleet # discover Tailscale devices + configure SSH access
|
|
420
429
|
agents setup watchdog # choose which devices run the daemon watchdog pass
|
|
421
430
|
agents setup alias add teams # PATH shorthand: teams runs agents teams
|
package/dist/commands/share.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
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
|
-
import { type PublishResult } from '../lib/share/publish.js';
|
|
4
|
+
import { type PublishResult, type ShareVisibility } from '../lib/share/publish.js';
|
|
5
5
|
import { deleteShare, type DeleteShareResult } from '../lib/share/delete.js';
|
|
6
6
|
import type { PhoenixSession } from '../lib/identity/client.js';
|
|
7
7
|
export declare function formatSharePublishResult(result: PublishResult, json?: boolean): string;
|
|
@@ -36,6 +36,9 @@ export interface ShareListItem {
|
|
|
36
36
|
repo: string | null;
|
|
37
37
|
/** Count of retained prior versions under this slug (see `share revisions`). */
|
|
38
38
|
revisionCount: number;
|
|
39
|
+
/** The visibility stamped at publish time: public | unlisted | me | org.
|
|
40
|
+
* Missing on Workers that predate this field → treated as public. */
|
|
41
|
+
visibility: ShareVisibility;
|
|
39
42
|
/** Arbitrary `--meta key=value` entries attached at publish time (RUSH-2683)
|
|
40
43
|
* — everything that isn't a reserved provenance/label key. `{}` when none
|
|
41
44
|
* were set, or when the deployed Worker predates this field. */
|
|
@@ -47,12 +50,41 @@ export interface ShareListResult {
|
|
|
47
50
|
count: number;
|
|
48
51
|
objects: ShareListItem[];
|
|
49
52
|
}
|
|
50
|
-
/** DI seam for tests — override the real HTTP GET of the JSON listing route.
|
|
51
|
-
|
|
53
|
+
/** DI seam for tests — override the real HTTP GET of the JSON listing route.
|
|
54
|
+
* The optional `headers` carry the owner bearer for hidden-visibility listings. */
|
|
55
|
+
export type ListingFetchFn = (url: string, headers?: Record<string, string>) => Promise<{
|
|
52
56
|
status: number;
|
|
53
57
|
contentType: string;
|
|
54
58
|
body: string;
|
|
55
59
|
}>;
|
|
60
|
+
export interface ShareEditResult {
|
|
61
|
+
ok: true;
|
|
62
|
+
url: string;
|
|
63
|
+
label: string | null;
|
|
64
|
+
meta: Record<string, string>;
|
|
65
|
+
/** The visibility the page now carries (present on Workers that support the
|
|
66
|
+
* visibility edit; absent from an older deployed template). */
|
|
67
|
+
visibility?: ShareVisibility;
|
|
68
|
+
/** The visibility the page had before this edit, when the Worker reports it. */
|
|
69
|
+
previousVisibility?: ShareVisibility;
|
|
70
|
+
}
|
|
71
|
+
export declare function runShareEdit(target: string, opts: {
|
|
72
|
+
githubUser?: string;
|
|
73
|
+
config?: ShareConfig;
|
|
74
|
+
writeToken?: string;
|
|
75
|
+
byo?: boolean;
|
|
76
|
+
session?: PhoenixSession | null;
|
|
77
|
+
label?: string | null;
|
|
78
|
+
meta?: Record<string, string>;
|
|
79
|
+
metaMode?: 'merge' | 'replace';
|
|
80
|
+
removeMeta?: string[];
|
|
81
|
+
/** Change the page's visibility in place (public | unlisted | me | org).
|
|
82
|
+
* A metadata-only rewrite like label/meta — the body is untouched, so no
|
|
83
|
+
* revision is created. me/org require a Phoenix session. */
|
|
84
|
+
visibility?: ShareVisibility;
|
|
85
|
+
force?: boolean;
|
|
86
|
+
fetchEdit?: typeof fetch;
|
|
87
|
+
}): Promise<ShareEditResult>;
|
|
56
88
|
/** Parse the Worker's listing JSON into a validated result, failing loud (with the
|
|
57
89
|
* outdated-template hint) on any body that isn't the expected shape — an old Worker
|
|
58
90
|
* serves the HTML gallery for a non-empty namespace, which must not be silently
|
|
@@ -79,7 +111,24 @@ export declare function runShareList(opts?: {
|
|
|
79
111
|
session?: string;
|
|
80
112
|
/** Only shares whose label contains this text (case-insensitive substring). */
|
|
81
113
|
label?: string;
|
|
114
|
+
/** Only shares matching every provided `--meta key=value` entry. */
|
|
115
|
+
meta?: Record<string, string>;
|
|
116
|
+
/** Visibility filter. `public` (default) lists only public gallery pages;
|
|
117
|
+
* `unlisted`/`me`/`org` include that owner's hidden pages; `all` includes
|
|
118
|
+
* every active page. Hidden scopes send the owner's bearer and `scope=mine`. */
|
|
119
|
+
scope?: 'public' | 'unlisted' | 'me' | 'org' | 'all';
|
|
82
120
|
}): Promise<ShareListResult>;
|
|
121
|
+
/** Client-side filtering over an already-fetched listing (RUSH-2683) — the
|
|
122
|
+
* Worker has no query surface for this, so it narrows the fetched set instead
|
|
123
|
+
* of a second round trip. `count` reflects the FILTERED set, matching what the
|
|
124
|
+
* caller actually sees. */
|
|
125
|
+
export declare function applyShareListFilters(result: ShareListResult, filters: {
|
|
126
|
+
agent?: string;
|
|
127
|
+
session?: string;
|
|
128
|
+
label?: string;
|
|
129
|
+
meta?: Record<string, string>;
|
|
130
|
+
scope?: 'public' | 'unlisted' | 'me' | 'org' | 'all';
|
|
131
|
+
}): ShareListResult;
|
|
83
132
|
export declare function formatShareList(result: ShareListResult, json?: boolean): string;
|
|
84
133
|
/** One retained prior version of a slug, as reported by the Worker's
|
|
85
134
|
* `?revisions=json` route. */
|