@phnx-labs/agents-cli 1.22.56 → 1.22.58
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 +70 -0
- package/README.md +4 -4
- package/dist/bootstrap.js +11 -2
- package/dist/cli/command-registry.d.ts +0 -1
- package/dist/cli/command-registry.js +0 -3
- package/dist/commands/accounts.js +7 -3
- package/dist/commands/apply.js +10 -2
- package/dist/commands/exec.js +1 -1
- package/dist/commands/fork.d.ts +23 -10
- package/dist/commands/fork.js +115 -58
- package/dist/commands/hooks.js +4 -4
- package/dist/commands/insights.d.ts +7 -5
- package/dist/commands/insights.js +16 -9
- package/dist/commands/monitors.js +11 -0
- package/dist/commands/perf.d.ts +16 -7
- package/dist/commands/perf.js +29 -20
- package/dist/commands/prune.js +5 -3
- package/dist/commands/routines.d.ts +8 -0
- package/dist/commands/routines.js +57 -3
- package/dist/commands/rules.js +1 -1
- package/dist/commands/sessions-picker.d.ts +11 -0
- package/dist/commands/sessions-picker.js +16 -0
- package/dist/commands/sessions.js +1 -0
- package/dist/commands/share.d.ts +14 -0
- package/dist/commands/share.js +43 -2
- package/dist/commands/ssh.js +24 -14
- package/dist/commands/status.js +1 -1
- package/dist/commands/sync.js +83 -7
- package/dist/commands/traces.js +7 -0
- package/dist/commands/trash.d.ts +2 -2
- package/dist/commands/trash.js +2 -6
- package/dist/commands/versions.d.ts +2 -2
- package/dist/commands/versions.js +1 -10
- package/dist/commands/view.d.ts +2 -2
- package/dist/commands/view.js +7 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.js +14 -0
- package/dist/lib/account-registry.d.ts +5 -1
- package/dist/lib/account-registry.js +47 -14
- package/dist/lib/accounting/capacity.d.ts +18 -7
- package/dist/lib/accounting/capacity.js +19 -8
- package/dist/lib/accounting/usage-ingest.d.ts +1 -0
- package/dist/lib/accounting/usage-ingest.js +75 -0
- package/dist/lib/accounting/usage-sync.d.ts +97 -0
- package/dist/lib/accounting/usage-sync.js +203 -0
- package/dist/lib/accounting/usage.d.ts +48 -2
- package/dist/lib/accounting/usage.js +79 -2
- package/dist/lib/agent-spec/agents.js +1 -1
- package/dist/lib/analytics/mix-commands.d.ts +8 -7
- package/dist/lib/analytics/mix-commands.js +50 -73
- package/dist/lib/auth-mint.d.ts +11 -1
- package/dist/lib/auth-mint.js +21 -6
- package/dist/lib/browser/ipc.d.ts +8 -0
- package/dist/lib/browser/ipc.js +87 -0
- package/dist/lib/browser/service.d.ts +19 -0
- package/dist/lib/browser/service.js +96 -11
- package/dist/lib/browser/sessions-list.js +10 -1
- package/dist/lib/daemon/daemon.js +5 -0
- package/dist/lib/daemon/runner.d.ts +3 -0
- package/dist/lib/daemon/runner.js +95 -53
- package/dist/lib/daemon/usage-sync-service.d.ts +21 -0
- package/dist/lib/daemon/usage-sync-service.js +42 -0
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +5 -0
- package/dist/lib/device-config.d.ts +17 -6
- package/dist/lib/device-config.js +25 -11
- package/dist/lib/devices/connect.d.ts +17 -8
- package/dist/lib/devices/connect.js +31 -14
- package/dist/lib/devices/pool.d.ts +4 -3
- package/dist/lib/devices/pool.js +13 -5
- package/dist/lib/doctor-diff.js +77 -7
- package/dist/lib/exec.d.ts +6 -41
- package/dist/lib/exec.js +6 -41
- package/dist/lib/fleet/manifest.d.ts +17 -0
- package/dist/lib/fleet/manifest.js +26 -0
- package/dist/lib/git.d.ts +13 -1
- package/dist/lib/git.js +36 -7
- package/dist/lib/harness/adapter.d.ts +7 -7
- package/dist/lib/harness/adapters/claude.js +3 -2
- package/dist/lib/hooks/install.d.ts +27 -11
- package/dist/lib/hooks/install.js +42 -17
- package/dist/lib/hosts/reconnect.d.ts +52 -203
- package/dist/lib/hosts/reconnect.js +64 -284
- package/dist/lib/hosts/remote-cmd.d.ts +9 -0
- package/dist/lib/hosts/remote-cmd.js +22 -0
- package/dist/lib/installations/migrate.d.ts +6 -120
- package/dist/lib/installations/migrate.js +27 -259
- package/dist/lib/installations/shims.d.ts +13 -95
- package/dist/lib/installations/shims.js +22 -139
- package/dist/lib/installations/store.js +1 -1
- package/dist/lib/installations/versions.d.ts +26 -133
- package/dist/lib/installations/versions.js +41 -204
- package/dist/lib/perf/db.d.ts +1 -1
- package/dist/lib/perf/db.js +1 -1
- package/dist/lib/plugins/skills.d.ts +8 -1
- package/dist/lib/plugins/skills.js +18 -2
- package/dist/lib/refresh.d.ts +9 -0
- package/dist/lib/refresh.js +3 -1
- package/dist/lib/routine-readiness.d.ts +15 -1
- package/dist/lib/routine-readiness.js +41 -0
- package/dist/lib/sandbox.d.ts +4 -1
- package/dist/lib/sandbox.js +30 -1
- package/dist/lib/secrets/agent.d.ts +80 -225
- package/dist/lib/secrets/agent.js +139 -401
- package/dist/lib/secrets/bundles.d.ts +73 -222
- package/dist/lib/secrets/bundles.js +168 -467
- package/dist/lib/secrets/reaper.d.ts +28 -70
- package/dist/lib/secrets/reaper.js +30 -85
- package/dist/lib/secrets/remote.d.ts +42 -129
- package/dist/lib/secrets/remote.js +55 -173
- package/dist/lib/self-heal/checks/install-staging.d.ts +4 -0
- package/dist/lib/self-heal/checks/install-staging.js +96 -0
- package/dist/lib/self-heal/registry.js +2 -0
- package/dist/lib/self-heal/types.d.ts +1 -1
- package/dist/lib/self-update.d.ts +23 -0
- package/dist/lib/self-update.js +50 -0
- package/dist/lib/session/active.d.ts +16 -32
- package/dist/lib/session/active.js +10 -68
- package/dist/lib/session/db.d.ts +24 -36
- package/dist/lib/session/db.js +143 -44
- package/dist/lib/session/discover.d.ts +6 -58
- package/dist/lib/session/discover.js +5 -43
- package/dist/lib/session/fork.d.ts +45 -26
- package/dist/lib/session/fork.js +32 -95
- package/dist/lib/session/parse.d.ts +1 -19
- package/dist/lib/session/parse.js +2 -15
- package/dist/lib/session/tool-calls.d.ts +43 -1
- package/dist/lib/session/tool-calls.js +74 -44
- package/dist/lib/session/tool-store.d.ts +33 -2
- package/dist/lib/session/tool-store.js +56 -3
- package/dist/lib/staleness/writers/sources.d.ts +5 -0
- package/dist/lib/staleness/writers/sources.js +2 -1
- package/dist/lib/startup/command-registry.d.ts +8 -2
- package/dist/lib/startup/command-registry.js +12 -4
- package/dist/lib/sync-status.d.ts +22 -0
- package/dist/lib/sync-status.js +27 -0
- package/dist/lib/sync-umbrella.d.ts +9 -0
- package/dist/lib/sync-umbrella.js +21 -2
- package/dist/lib/traces/insights.d.ts +47 -14
- package/dist/lib/traces/insights.js +92 -21
- package/dist/lib/traces/phenotype.d.ts +23 -3
- package/dist/lib/traces/phenotype.js +72 -24
- package/dist/lib/traces/sync.d.ts +15 -0
- package/dist/lib/traces/sync.js +104 -19
- package/dist/lib/traces/worker-template.js +154 -1
- package/package.json +1 -1
|
@@ -7,20 +7,21 @@
|
|
|
7
7
|
* rhythm, edits) — split by Claude account by default
|
|
8
8
|
* agents insights mix COUNTERS (sessions index + usage.db recipes:
|
|
9
9
|
* harness/model mix, token ratios, secrets, browser)
|
|
10
|
-
* agents insights <recipe>
|
|
10
|
+
* agents insights mix <recipe> One baked mix recipe (harness-mix, tools-per-session, …)
|
|
11
11
|
* agents insights query Raw usage.db rows
|
|
12
12
|
*
|
|
13
|
-
* Sibling observe verbs
|
|
13
|
+
* Sibling observe verbs under this same group (different questions):
|
|
14
14
|
*
|
|
15
15
|
* agents insights cost what you spent ($ and duration)
|
|
16
16
|
* agents insights output what shipped (burn vs PRs and commits)
|
|
17
|
+
* agents insights perf latency (hooks, CLI commands, agent.run) — not popularity
|
|
17
18
|
* agents view live quota headroom (per account, with auth state)
|
|
18
|
-
* agents perf latency (hooks, CLI commands, agent.run) — not popularity
|
|
19
19
|
* agents sessions stats which skills/slash-commands were explicitly invoked
|
|
20
20
|
*
|
|
21
21
|
* Why mix lives here (not a second top-level `trends`): two abstract "analytics"
|
|
22
22
|
* nouns taught agents and humans to guess. One verb, two engines — cheap SQL mix
|
|
23
|
-
* vs transcript facets.
|
|
23
|
+
* vs transcript facets. `perf` (latency) is also nested here now (PHNX-3391) —
|
|
24
|
+
* performance is an insight, kept a distinct sub-verb so it is never confused with mix.
|
|
24
25
|
*
|
|
25
26
|
* Modelled on Claude Code's `/insights`, with the difference that motivated it: that
|
|
26
27
|
* command reads one account's directory, while `balanced` rotation sprays sessions
|
|
@@ -31,7 +32,8 @@
|
|
|
31
32
|
* the coaching prose by piping the AGGREGATE (never raw transcripts) through a headless
|
|
32
33
|
* `claude -p`.
|
|
33
34
|
*
|
|
34
|
-
* Former top-level `agents trends` is `agents insights mix`
|
|
35
|
+
* Former top-level `agents trends` is `agents insights mix` (one section:
|
|
36
|
+
* `agents insights mix <recipe>`; `--list` names them).
|
|
35
37
|
*/
|
|
36
38
|
import type { Command } from 'commander';
|
|
37
39
|
export declare function registerInsightsCommand(program: Command): void;
|
|
@@ -7,20 +7,21 @@
|
|
|
7
7
|
* rhythm, edits) — split by Claude account by default
|
|
8
8
|
* agents insights mix COUNTERS (sessions index + usage.db recipes:
|
|
9
9
|
* harness/model mix, token ratios, secrets, browser)
|
|
10
|
-
* agents insights <recipe>
|
|
10
|
+
* agents insights mix <recipe> One baked mix recipe (harness-mix, tools-per-session, …)
|
|
11
11
|
* agents insights query Raw usage.db rows
|
|
12
12
|
*
|
|
13
|
-
* Sibling observe verbs
|
|
13
|
+
* Sibling observe verbs under this same group (different questions):
|
|
14
14
|
*
|
|
15
15
|
* agents insights cost what you spent ($ and duration)
|
|
16
16
|
* agents insights output what shipped (burn vs PRs and commits)
|
|
17
|
+
* agents insights perf latency (hooks, CLI commands, agent.run) — not popularity
|
|
17
18
|
* agents view live quota headroom (per account, with auth state)
|
|
18
|
-
* agents perf latency (hooks, CLI commands, agent.run) — not popularity
|
|
19
19
|
* agents sessions stats which skills/slash-commands were explicitly invoked
|
|
20
20
|
*
|
|
21
21
|
* Why mix lives here (not a second top-level `trends`): two abstract "analytics"
|
|
22
22
|
* nouns taught agents and humans to guess. One verb, two engines — cheap SQL mix
|
|
23
|
-
* vs transcript facets.
|
|
23
|
+
* vs transcript facets. `perf` (latency) is also nested here now (PHNX-3391) —
|
|
24
|
+
* performance is an insight, kept a distinct sub-verb so it is never confused with mix.
|
|
24
25
|
*
|
|
25
26
|
* Modelled on Claude Code's `/insights`, with the difference that motivated it: that
|
|
26
27
|
* command reads one account's directory, while `balanced` rotation sprays sessions
|
|
@@ -31,7 +32,8 @@
|
|
|
31
32
|
* the coaching prose by piping the AGGREGATE (never raw transcripts) through a headless
|
|
32
33
|
* `claude -p`.
|
|
33
34
|
*
|
|
34
|
-
* Former top-level `agents trends` is `agents insights mix`
|
|
35
|
+
* Former top-level `agents trends` is `agents insights mix` (one section:
|
|
36
|
+
* `agents insights mix <recipe>`; `--list` names them).
|
|
35
37
|
*/
|
|
36
38
|
import * as fs from 'fs';
|
|
37
39
|
import chalk from 'chalk';
|
|
@@ -47,6 +49,7 @@ import { formatUsd } from '../lib/pricing/index.js';
|
|
|
47
49
|
import { formatDuration } from '../lib/session/render.js';
|
|
48
50
|
import { terminalWidth, truncateToWidth, stringWidth, padToWidth } from '../lib/session/width.js';
|
|
49
51
|
import { registerMixCommands } from '../lib/analytics/mix-commands.js';
|
|
52
|
+
import { registerPerfSubcommand } from './perf.js';
|
|
50
53
|
import { registerCostCommand } from './cost.js';
|
|
51
54
|
import { registerOutputCommand } from './output.js';
|
|
52
55
|
const execFileAsync = promisify(execFile);
|
|
@@ -570,7 +573,7 @@ function configureInsightsCommand(cmd) {
|
|
|
570
573
|
# Counter mix board (harness/model/token/secrets recipes) — former agents trends
|
|
571
574
|
agents insights mix
|
|
572
575
|
agents insights mix --days 30
|
|
573
|
-
agents insights harness-mix --json
|
|
576
|
+
agents insights mix harness-mix --json
|
|
574
577
|
agents insights query --kind secret --days 7
|
|
575
578
|
|
|
576
579
|
# One account only, all of its history
|
|
@@ -586,10 +589,10 @@ function configureInsightsCommand(cmd) {
|
|
|
586
589
|
Two paths under one verb:
|
|
587
590
|
bare \`agents insights\` — transcript behaviour (tools, friction, rhythm, by account)
|
|
588
591
|
\`agents insights mix\` — cheap counters from sessions.db + usage.db
|
|
589
|
-
Latency is \`agents perf\` (not mix). Quota is \`agents view\`. Spend is
|
|
592
|
+
Latency is \`agents insights perf\` (not mix). Quota is \`agents view\`. Spend is
|
|
590
593
|
\`agents insights cost\`; shipped output is \`agents insights output\`. Skill/slash popularity
|
|
591
|
-
is \`agents sessions stats\`. Former top-level \`agents trends\` is \`agents insights mix
|
|
592
|
-
|
|
594
|
+
is \`agents sessions stats\`. Former top-level \`agents trends\` is \`agents insights mix\`.
|
|
595
|
+
One recipe is \`agents insights mix <recipe>\` (e.g. \`harness-mix\`); \`--list\` names them.
|
|
593
596
|
|
|
594
597
|
The behavioural report parses in-scope transcripts once and caches facets; later runs
|
|
595
598
|
re-read only files that changed. \`--refresh\` forces a full re-read.
|
|
@@ -606,6 +609,10 @@ export function registerInsightsCommand(program) {
|
|
|
606
609
|
configureInsightsCommand(cmd);
|
|
607
610
|
registerCostCommand(cmd);
|
|
608
611
|
registerOutputCommand(cmd);
|
|
612
|
+
// Latency rollups (former top-level `agents perf` → `agents insights perf`,
|
|
613
|
+
// PHNX-3391). A sibling observe verb of cost/output, so it lives on the
|
|
614
|
+
// top-level insights group beside them, not under `sessions insights`.
|
|
615
|
+
registerPerfSubcommand(cmd);
|
|
609
616
|
}
|
|
610
617
|
export function registerSessionsInsightsCommand(sessions) {
|
|
611
618
|
configureInsightsCommand(sessions.command('insights'));
|
|
@@ -139,6 +139,13 @@ function livenessLabel(monitor, state, liveness) {
|
|
|
139
139
|
if (liveness.lastError) {
|
|
140
140
|
return chalk.red(`checked ${liveness.checkCount}x · error: ${liveness.lastError.replace(/\s+/g, ' ').slice(0, 60)}`);
|
|
141
141
|
}
|
|
142
|
+
const latestFire = listFires(monitor.name).at(-1);
|
|
143
|
+
if (latestFire) {
|
|
144
|
+
const outcome = resolveFireOutcome(monitor.name, latestFire);
|
|
145
|
+
if (!outcome.ok) {
|
|
146
|
+
return chalk.red(`ACTION FAILED ${formatRelativeTime(latestFire.firedAt)}`) + chalk.gray(` · checked ${liveness.checkCount}x`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
142
149
|
if (state?.lastFiredAt) {
|
|
143
150
|
return chalk.green(`fired ${formatRelativeTime(state.lastFiredAt)}`) + chalk.gray(` · checked ${liveness.checkCount}x`);
|
|
144
151
|
}
|
|
@@ -629,6 +636,8 @@ export function registerMonitorsCommands(program) {
|
|
|
629
636
|
const payload = monitors.map((m) => {
|
|
630
637
|
const state = readState(m.name);
|
|
631
638
|
const liveness = readLiveness(m.name);
|
|
639
|
+
const latestFire = listFires(m.name).at(-1);
|
|
640
|
+
const latestOutcome = latestFire ? resolveFireOutcome(m.name, latestFire) : null;
|
|
632
641
|
return {
|
|
633
642
|
name: m.name,
|
|
634
643
|
enabled: m.enabled,
|
|
@@ -650,6 +659,8 @@ export function registerMonitorsCommands(program) {
|
|
|
650
659
|
lastError: liveness?.lastError ?? null,
|
|
651
660
|
consecutiveErrors: liveness?.consecutiveErrors ?? 0,
|
|
652
661
|
stalled: isStalled(m, liveness),
|
|
662
|
+
lastActionStatus: latestOutcome?.runStatus ?? null,
|
|
663
|
+
lastActionFailed: latestOutcome ? !latestOutcome.ok : false,
|
|
653
664
|
};
|
|
654
665
|
});
|
|
655
666
|
stdoutJson(payload);
|
package/dist/commands/perf.d.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `agents perf` — latency rollups over the disposable perf SQLite
|
|
2
|
+
* `agents insights perf` — latency rollups over the disposable perf SQLite
|
|
3
|
+
* warehouse (former top-level `agents perf`, moved under insights in PHNX-3391).
|
|
3
4
|
*
|
|
4
5
|
* Subcommands:
|
|
5
|
-
* agents perf multi-section summary (commands + hooks + runs)
|
|
6
|
-
* agents perf hooks per-hook p50/p99 + cache hit rates
|
|
7
|
-
* agents perf commands slowest CLI command paths (from command.end)
|
|
8
|
-
* agents perf run agent.run / perf.timing labels
|
|
9
|
-
* agents perf friction sessions stuck repeatedly hitting the same guard
|
|
6
|
+
* agents insights perf multi-section summary (commands + hooks + runs)
|
|
7
|
+
* agents insights perf hooks per-hook p50/p99 + cache hit rates
|
|
8
|
+
* agents insights perf commands slowest CLI command paths (from command.end)
|
|
9
|
+
* agents insights perf run agent.run / perf.timing labels
|
|
10
|
+
* agents insights perf friction sessions stuck repeatedly hitting the same guard
|
|
10
11
|
*
|
|
11
12
|
* Soft-joins sessions.db via shared string keys (session_id, agent, machine) —
|
|
12
13
|
* no foreign keys. Warehouse lives at ~/.agents/.cache/perf/perf.db (safe to wipe).
|
|
@@ -49,5 +50,13 @@ export declare function loadHookProfile(days: number, project?: string): HookPro
|
|
|
49
50
|
* exit 2 — see lib/friction-heuristics.ts for the grouping.
|
|
50
51
|
*/
|
|
51
52
|
export declare function frictionAction(opts: PerfGlobalOpts): void;
|
|
52
|
-
|
|
53
|
+
/**
|
|
54
|
+
* Attach the `perf` latency-rollup command under a parent (the top-level
|
|
55
|
+
* `insights` group). Performance is an insight, not a top-level noun — `agents
|
|
56
|
+
* perf` was retired in favour of `agents insights perf` (PHNX-3391). It is a
|
|
57
|
+
* sibling of `agents insights cost` / `output`, registered in
|
|
58
|
+
* `registerInsightsCommand` beside them (top-level insights only, not
|
|
59
|
+
* `sessions insights`).
|
|
60
|
+
*/
|
|
61
|
+
export declare function registerPerfSubcommand(parent: Command): void;
|
|
53
62
|
export {};
|
package/dist/commands/perf.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `agents perf` — latency rollups over the disposable perf SQLite
|
|
2
|
+
* `agents insights perf` — latency rollups over the disposable perf SQLite
|
|
3
|
+
* warehouse (former top-level `agents perf`, moved under insights in PHNX-3391).
|
|
3
4
|
*
|
|
4
5
|
* Subcommands:
|
|
5
|
-
* agents perf multi-section summary (commands + hooks + runs)
|
|
6
|
-
* agents perf hooks per-hook p50/p99 + cache hit rates
|
|
7
|
-
* agents perf commands slowest CLI command paths (from command.end)
|
|
8
|
-
* agents perf run agent.run / perf.timing labels
|
|
9
|
-
* agents perf friction sessions stuck repeatedly hitting the same guard
|
|
6
|
+
* agents insights perf multi-section summary (commands + hooks + runs)
|
|
7
|
+
* agents insights perf hooks per-hook p50/p99 + cache hit rates
|
|
8
|
+
* agents insights perf commands slowest CLI command paths (from command.end)
|
|
9
|
+
* agents insights perf run agent.run / perf.timing labels
|
|
10
|
+
* agents insights perf friction sessions stuck repeatedly hitting the same guard
|
|
10
11
|
*
|
|
11
12
|
* Soft-joins sessions.db via shared string keys (session_id, agent, machine) —
|
|
12
13
|
* no foreign keys. Warehouse lives at ~/.agents/.cache/perf/perf.db (safe to wipe).
|
|
@@ -190,7 +191,7 @@ export function frictionAction(opts) {
|
|
|
190
191
|
// --cwd flag — so silently accepting the flag here would look like it
|
|
191
192
|
// filtered when it did nothing. Fail loud instead of no-op.
|
|
192
193
|
if (opts.project) {
|
|
193
|
-
console.error(chalk.red("agents perf friction does not support --project yet — friction events carry no cwd to filter on."));
|
|
194
|
+
console.error(chalk.red("agents insights perf friction does not support --project yet — friction events carry no cwd to filter on."));
|
|
194
195
|
process.exitCode = 1;
|
|
195
196
|
return;
|
|
196
197
|
}
|
|
@@ -224,7 +225,7 @@ function summaryAction(opts) {
|
|
|
224
225
|
}, null, 2));
|
|
225
226
|
return;
|
|
226
227
|
}
|
|
227
|
-
console.log(chalk.bold(`agents perf — last ${days} day${days === 1 ? '' : 's'}${project ? ` — project ${project}` : ''}`));
|
|
228
|
+
console.log(chalk.bold(`agents insights perf — last ${days} day${days === 1 ? '' : 's'}${project ? ` — project ${project}` : ''}`));
|
|
228
229
|
console.log(chalk.gray(`warehouse: ${perfDbPath()} (disposable; soft-join sessions via session_id/agent/machine)`));
|
|
229
230
|
console.log('');
|
|
230
231
|
console.log(chalk.bold('Commands (slowest by p99)'));
|
|
@@ -246,7 +247,7 @@ function attachSharedOptions(cmd) {
|
|
|
246
247
|
}
|
|
247
248
|
/**
|
|
248
249
|
* Commander binds a flag declared on both parent and child to the *parent*.
|
|
249
|
-
* Merge so `agents perf commands --json` still sees json:true on the leaf.
|
|
250
|
+
* Merge so `agents insights perf commands --json` still sees json:true on the leaf.
|
|
250
251
|
*/
|
|
251
252
|
function leafOpts(cmd) {
|
|
252
253
|
const parent = cmd.parent && typeof cmd.parent.opts === 'function'
|
|
@@ -254,8 +255,16 @@ function leafOpts(cmd) {
|
|
|
254
255
|
: {};
|
|
255
256
|
return { ...parent, ...cmd.opts() };
|
|
256
257
|
}
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
/**
|
|
259
|
+
* Attach the `perf` latency-rollup command under a parent (the top-level
|
|
260
|
+
* `insights` group). Performance is an insight, not a top-level noun — `agents
|
|
261
|
+
* perf` was retired in favour of `agents insights perf` (PHNX-3391). It is a
|
|
262
|
+
* sibling of `agents insights cost` / `output`, registered in
|
|
263
|
+
* `registerInsightsCommand` beside them (top-level insights only, not
|
|
264
|
+
* `sessions insights`).
|
|
265
|
+
*/
|
|
266
|
+
export function registerPerfSubcommand(parent) {
|
|
267
|
+
const perf = parent
|
|
259
268
|
.command('perf')
|
|
260
269
|
.description('Latency rollups from the disposable perf warehouse (hooks, commands, runs)')
|
|
261
270
|
.addHelpText('after', `
|
|
@@ -264,16 +273,16 @@ Identity columns reuse sessions/events string shapes (session_id, agent, machine
|
|
|
264
273
|
for soft cross-reference; there are no foreign keys.
|
|
265
274
|
|
|
266
275
|
Examples:
|
|
267
|
-
agents perf # summary: commands + hooks + runs
|
|
268
|
-
agents perf hooks # per-hook p50/p95/p99 + cache hit rate
|
|
269
|
-
agents perf commands --days 30 # slowest CLI entrypoints
|
|
270
|
-
agents perf run --json # agent.run timings as JSON
|
|
271
|
-
agents perf hooks --warn-ms 500
|
|
272
|
-
agents perf hooks --project agents-cli # scope to one repo's samples
|
|
273
|
-
agents perf friction # sessions stuck retrying the same guard block
|
|
276
|
+
agents insights perf # summary: commands + hooks + runs
|
|
277
|
+
agents insights perf hooks # per-hook p50/p95/p99 + cache hit rate
|
|
278
|
+
agents insights perf commands --days 30 # slowest CLI entrypoints
|
|
279
|
+
agents insights perf run --json # agent.run timings as JSON
|
|
280
|
+
agents insights perf hooks --warn-ms 500
|
|
281
|
+
agents insights perf hooks --project agents-cli # scope to one repo's samples
|
|
282
|
+
agents insights perf friction # sessions stuck retrying the same guard block
|
|
274
283
|
`);
|
|
275
|
-
// Options live on the parent so `agents perf --json` and
|
|
276
|
-
// `agents perf commands --json` both work (see leafOpts).
|
|
284
|
+
// Options live on the parent so `agents insights perf --json` and
|
|
285
|
+
// `agents insights perf commands --json` both work (see leafOpts).
|
|
277
286
|
attachSharedOptions(perf).action(function summary() {
|
|
278
287
|
summaryAction(this.opts());
|
|
279
288
|
});
|
package/dist/commands/prune.js
CHANGED
|
@@ -66,9 +66,11 @@ function collectOrphans(types, all) {
|
|
|
66
66
|
}
|
|
67
67
|
if (types.includes('hooks')) {
|
|
68
68
|
for (const { agent, version } of scopePairs(iterHooksCapableVersions(), all)) {
|
|
69
|
-
// Orphan hooks = scripts present in the version home
|
|
70
|
-
//
|
|
71
|
-
//
|
|
69
|
+
// Orphan hooks = scripts present in the version home but absent from
|
|
70
|
+
// every configured source (user + system + extras) — genuinely dead
|
|
71
|
+
// files, not merely unregistered ones (sync copies helper/test scripts
|
|
72
|
+
// that no manifest entry declares). Same definition the doctor overview
|
|
73
|
+
// reports (PHNX-2693).
|
|
72
74
|
const orphans = listUnmanagedHooksInVersionHome(agent, version);
|
|
73
75
|
if (orphans.length > 0) {
|
|
74
76
|
groups.push({ type: 'hooks', agent, version, orphans });
|
|
@@ -46,5 +46,13 @@ export declare function groupRoutineJobsByDevice(jobs: JobConfig[], registry: De
|
|
|
46
46
|
*/
|
|
47
47
|
export declare function groupRoutineJobsByProject(jobs: JobConfig[], knownProjectNames: Set<string>): RoutineListGroup[];
|
|
48
48
|
export declare function buildRunsJson(runs: RunMeta[]): Record<string, unknown>[];
|
|
49
|
+
/**
|
|
50
|
+
* The short, human reason a run did not simply complete — for inline display in
|
|
51
|
+
* the list/detail so "why did it fail" needs no dig into the run dir. Prefers the
|
|
52
|
+
* concrete `errorMessage` (which carries `auth_failed: …`, OAuth-revoked, timeouts),
|
|
53
|
+
* then the readiness block for a `blocked` run, then the mapped skip reason. Returns
|
|
54
|
+
* null for a healthy (`completed`/`running`) run, which needs no annotation.
|
|
55
|
+
*/
|
|
56
|
+
export declare function runFailureReason(run: RunMeta): string | null;
|
|
49
57
|
/** Register the `agents routines` command tree. */
|
|
50
58
|
export declare function registerRoutinesCommands(program: Command): void;
|
|
@@ -245,12 +245,17 @@ function renderRoutineRows({ jobs, scheduler, overdueSet, link, now, local = tru
|
|
|
245
245
|
: lastStatus === 'missed' ? chalk.magenta
|
|
246
246
|
: chalk.gray;
|
|
247
247
|
const overdueTag = overdueSet.has(job.name) ? chalk.yellow(' (overdue)') : '';
|
|
248
|
+
// Append the concrete reason a routine did not complete (auth_failed, wedged,
|
|
249
|
+
// blocked, missed) right in the Last Status cell, so the list answers "why"
|
|
250
|
+
// without a drill-in. Only for non-completed local runs; peer rows stay blank.
|
|
251
|
+
const reason = latestRun ? runFailureReason(latestRun) : null;
|
|
252
|
+
const reasonTag = reason ? chalk.gray(` — ${reason}`) : '';
|
|
248
253
|
const agentLabelPadded = job.command
|
|
249
254
|
? chalk.magenta('command'.padEnd(10))
|
|
250
255
|
: job.workflow
|
|
251
256
|
? chalk.magenta(`wf:${job.workflow}`.padEnd(10))
|
|
252
257
|
: (job.agent || '').padEnd(10);
|
|
253
|
-
console.log(` ${chalk.cyan(job.name.padEnd(NAME_W))} ${agentLabelPadded} ${repoCell}${' '.repeat(repoPadding)} ${deviceCell}${' '.repeat(devicePad)} ${schedStr.padEnd(SCHED_W)} ${enabledStr}${' '.repeat(enabledPad)} ${chalk.gray(nextStr.padEnd(NEXT_W))} ${statusColor(lastStatus)}${overdueTag}`);
|
|
258
|
+
console.log(` ${chalk.cyan(job.name.padEnd(NAME_W))} ${agentLabelPadded} ${repoCell}${' '.repeat(repoPadding)} ${deviceCell}${' '.repeat(devicePad)} ${schedStr.padEnd(SCHED_W)} ${enabledStr}${' '.repeat(enabledPad)} ${chalk.gray(nextStr.padEnd(NEXT_W))} ${statusColor(lastStatus)}${overdueTag}${reasonTag}`);
|
|
254
259
|
}
|
|
255
260
|
}
|
|
256
261
|
function parseRoutineTrigger(options) {
|
|
@@ -622,6 +627,43 @@ function routineMatchesQuery(job, q) {
|
|
|
622
627
|
.toLowerCase()
|
|
623
628
|
.includes(q);
|
|
624
629
|
}
|
|
630
|
+
/** Friendly one-liners for the claim a `skipped` run lost. */
|
|
631
|
+
const SKIP_REASON_LABEL = {
|
|
632
|
+
active_run: 'wedged: a prior run is still active',
|
|
633
|
+
duplicate_slot: 'duplicate slot (already fired)',
|
|
634
|
+
wrong_owner: 'pinned to another device',
|
|
635
|
+
};
|
|
636
|
+
/**
|
|
637
|
+
* The short, human reason a run did not simply complete — for inline display in
|
|
638
|
+
* the list/detail so "why did it fail" needs no dig into the run dir. Prefers the
|
|
639
|
+
* concrete `errorMessage` (which carries `auth_failed: …`, OAuth-revoked, timeouts),
|
|
640
|
+
* then the readiness block for a `blocked` run, then the mapped skip reason. Returns
|
|
641
|
+
* null for a healthy (`completed`/`running`) run, which needs no annotation.
|
|
642
|
+
*/
|
|
643
|
+
export function runFailureReason(run) {
|
|
644
|
+
if (run.status === 'completed' || run.status === 'running')
|
|
645
|
+
return null;
|
|
646
|
+
const compact = (s) => {
|
|
647
|
+
const one = s.replace(/\s+/g, ' ').trim();
|
|
648
|
+
return one.length > 80 ? one.slice(0, 79) + '…' : one;
|
|
649
|
+
};
|
|
650
|
+
if (run.errorMessage)
|
|
651
|
+
return compact(run.errorMessage);
|
|
652
|
+
if (run.status === 'blocked' && run.readiness) {
|
|
653
|
+
return compact(run.readiness.message || run.readiness.code);
|
|
654
|
+
}
|
|
655
|
+
if (run.skipReason)
|
|
656
|
+
return SKIP_REASON_LABEL[run.skipReason];
|
|
657
|
+
if (run.status === 'missed')
|
|
658
|
+
return 'scheduler was not running when it came due';
|
|
659
|
+
// The most common failure shape: a command/agent body that exited nonzero with
|
|
660
|
+
// no structured errorMessage (the cause is in stdout). Naming the exit code is
|
|
661
|
+
// still more than the bare status word, and tells the reader it ran and threw.
|
|
662
|
+
if ((run.status === 'failed' || run.status === 'timeout') && run.exitCode !== null && run.exitCode !== undefined) {
|
|
663
|
+
return `exit ${run.exitCode}`;
|
|
664
|
+
}
|
|
665
|
+
return null;
|
|
666
|
+
}
|
|
625
667
|
/** One compact routine row for the browser list: name · kind · schedule · next · last. */
|
|
626
668
|
function routineBrowserRow(job, scheduler, overdueSet, now) {
|
|
627
669
|
const kind = job.command ? 'command' : job.workflow ? `wf:${job.workflow}` : job.agent ?? '?';
|
|
@@ -685,7 +727,12 @@ function buildRoutineDetail(job, scheduler, now) {
|
|
|
685
727
|
? chalk.red(run.status)
|
|
686
728
|
: chalk.yellow(run.status);
|
|
687
729
|
const dur = run.completedAt ? ` ${formatRunDuration(run.startedAt, run.completedAt)}` : '';
|
|
688
|
-
|
|
730
|
+
// Surface WHY a run did not complete, inline, so "looking at status" does not
|
|
731
|
+
// require digging into the run dir. auth_failed / OAuth-revoked, a wedged
|
|
732
|
+
// active-run skip, or a readiness block all live on the RunMeta already.
|
|
733
|
+
const reason = runFailureReason(run);
|
|
734
|
+
const why = reason ? chalk.gray(` — ${reason}`) : '';
|
|
735
|
+
lines.push(` ${run.startedAt} ${status}${dur}${why}`);
|
|
689
736
|
}
|
|
690
737
|
}
|
|
691
738
|
// 4. Stats
|
|
@@ -1533,7 +1580,9 @@ export function registerRoutinesCommands(program) {
|
|
|
1533
1580
|
: run.status === 'failed'
|
|
1534
1581
|
? chalk.red(run.status)
|
|
1535
1582
|
: chalk.yellow(run.status);
|
|
1536
|
-
|
|
1583
|
+
const reason = runFailureReason(run);
|
|
1584
|
+
const why = reason ? chalk.gray(` — ${reason}`) : '';
|
|
1585
|
+
console.log(` ${run.runId} ${status} ${run.startedAt}${why}`);
|
|
1537
1586
|
}
|
|
1538
1587
|
});
|
|
1539
1588
|
routinesCmd
|
|
@@ -1856,6 +1905,11 @@ export function registerRoutinesCommands(program) {
|
|
|
1856
1905
|
chalk.gray(` ${run.startedAt}`) +
|
|
1857
1906
|
chalk.gray(formatRunDuration(run.startedAt, run.completedAt)) +
|
|
1858
1907
|
(run.exitCode !== null && run.exitCode !== undefined ? chalk.gray(` exit ${run.exitCode}`) : ''));
|
|
1908
|
+
// The structured reason (auth_failed, blocked readiness, wedged skip) — the
|
|
1909
|
+
// report/stdout tail below often buries or omits it, so name it up front.
|
|
1910
|
+
const logsReason = runFailureReason(run);
|
|
1911
|
+
if (logsReason)
|
|
1912
|
+
console.log(chalk.red('reason: ') + chalk.gray(logsReason));
|
|
1859
1913
|
console.log(chalk.gray('─'.repeat(60)));
|
|
1860
1914
|
const reportPath = path.join(getRunDir(name, runId), 'report.md');
|
|
1861
1915
|
if (fs.existsSync(reportPath)) {
|
package/dist/commands/rules.js
CHANGED
|
@@ -538,7 +538,7 @@ Examples:
|
|
|
538
538
|
}
|
|
539
539
|
const version = resolveVersionAlias(agentId, rawVersion);
|
|
540
540
|
if (!version) {
|
|
541
|
-
console.log(chalk.red(`Pass a version: ${agentId}@<version>. Try 'default' or 'agents
|
|
541
|
+
console.log(chalk.red(`Pass a version: ${agentId}@<version>. Try 'default' or 'agents view ${agentId}'.`));
|
|
542
542
|
process.exit(1);
|
|
543
543
|
}
|
|
544
544
|
const installed = listInstalledVersions(agentId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { SessionEvent, SessionMeta, TodoProgress } from '../lib/session/types.js';
|
|
2
2
|
import { fetchPeerPreviewDigest } from '../lib/session/remote-list.js';
|
|
3
3
|
import { classifyFileChanges, changeCounts, toolHistogram, detectTestResult } from '../lib/session/digest.js';
|
|
4
|
+
import type { FileChange } from '../lib/session/digest.js';
|
|
4
5
|
import { extractArtifacts, extractHooks, extractLinks, extractSkills } from '../lib/session/highlights.js';
|
|
5
6
|
/**
|
|
6
7
|
* Compact checklist tally for list rows and previews (RUSH-2045).
|
|
@@ -118,6 +119,16 @@ export interface SessionPreviewDigest {
|
|
|
118
119
|
backgroundShellCount?: number;
|
|
119
120
|
toolTags: string[];
|
|
120
121
|
changes: ReturnType<typeof changeCounts>;
|
|
122
|
+
/**
|
|
123
|
+
* The per-file source paths behind `changes`. `changes` keeps the roll-up
|
|
124
|
+
* counts every existing consumer already reads; `changedFiles` carries the
|
|
125
|
+
* real path + op the CLI computed at scan time (via classifyFileChanges) and
|
|
126
|
+
* used to discard — kept so a consumer that renders a per-file diff list (the
|
|
127
|
+
* AGI EXT Fleet detail panel, PHNX-2973) has the paths, not just the totals.
|
|
128
|
+
* Capped so a session that rewrote thousands of files can't bloat the cached
|
|
129
|
+
* digest / JSON payload; the `changes` counts stay the true totals.
|
|
130
|
+
*/
|
|
131
|
+
changedFiles: FileChange[];
|
|
121
132
|
dirs: string[];
|
|
122
133
|
repos: string[];
|
|
123
134
|
artifacts: ReturnType<typeof extractArtifacts>;
|
|
@@ -229,6 +229,14 @@ export function sanitizeRemoteDigest(raw) {
|
|
|
229
229
|
backgroundShellCount: optNum(d.backgroundShellCount),
|
|
230
230
|
toolTags: strList(d.toolTags),
|
|
231
231
|
changes,
|
|
232
|
+
// Per-file paths from an untrusted peer: keep only well-formed {path, op}
|
|
233
|
+
// entries (path scrubbed of terminal escapes, op a known FileOp), bounded
|
|
234
|
+
// like the local build so a hostile peer can't flood the pane.
|
|
235
|
+
changedFiles: objList(d.changedFiles, (f) => {
|
|
236
|
+
const path = str(f.path);
|
|
237
|
+
const op = f.op === 'created' || f.op === 'modified' || f.op === 'deleted' ? f.op : undefined;
|
|
238
|
+
return path && op ? { path, op } : undefined;
|
|
239
|
+
}).slice(0, CHANGED_FILES_MAX),
|
|
232
240
|
dirs: strList(d.dirs),
|
|
233
241
|
repos: strList(d.repos),
|
|
234
242
|
artifacts: objList(d.artifacts, (a) => {
|
|
@@ -655,6 +663,10 @@ const LAST_RESPONSE_MAX_LINES = 15;
|
|
|
655
663
|
const LAST_RESPONSE_MAX_LINES_WITH_TODOS = 8;
|
|
656
664
|
const TODOS_MAX_ITEMS = 5;
|
|
657
665
|
const DIRS_TOUCHED_MAX = 5;
|
|
666
|
+
// Upper bound on the per-file `changedFiles` list carried on the digest. High
|
|
667
|
+
// enough to cover any real session's edits, low enough that a runaway rewrite
|
|
668
|
+
// can't bloat the cached JSON. The `changes` counts stay the true totals.
|
|
669
|
+
const CHANGED_FILES_MAX = 200;
|
|
658
670
|
/** Fold a harness-normalized event stream into the stable preview data model. */
|
|
659
671
|
export function buildSessionPreviewDigest(events, session) {
|
|
660
672
|
let firstUser = '';
|
|
@@ -747,6 +759,10 @@ export function buildSessionPreviewDigest(events, session) {
|
|
|
747
759
|
backgroundShellCount,
|
|
748
760
|
toolTags: [...toolTags],
|
|
749
761
|
changes: chg,
|
|
762
|
+
// Full per-file list the picker used to collapse to `chg` and throw away.
|
|
763
|
+
// Bounded so a mass-rewrite session can't blow up the cached digest; the
|
|
764
|
+
// counts above remain the true totals.
|
|
765
|
+
changedFiles: changes.slice(0, CHANGED_FILES_MAX),
|
|
750
766
|
dirs: directoriesTouched(session, events, changes),
|
|
751
767
|
repos: extractRepos(events, session.cwd),
|
|
752
768
|
artifacts: extractArtifacts(changes),
|
|
@@ -2061,6 +2061,7 @@ export async function renderSessionPreview(query, scope) {
|
|
|
2061
2061
|
tokenCount: session.tokenCount,
|
|
2062
2062
|
costUsd: session.costUsd,
|
|
2063
2063
|
label: session.label,
|
|
2064
|
+
topic: session.topic,
|
|
2064
2065
|
ticketId: session.ticketId,
|
|
2065
2066
|
prUrl: session.prUrl,
|
|
2066
2067
|
},
|
package/dist/commands/share.d.ts
CHANGED
|
@@ -250,6 +250,17 @@ export interface ShareUpdateResult {
|
|
|
250
250
|
templateHash: string;
|
|
251
251
|
baseUrl: string;
|
|
252
252
|
workerName: string;
|
|
253
|
+
/** True when this was a `--check` run: nothing was deployed, the fields below
|
|
254
|
+
* just report whether a deploy WOULD be needed. Used by the release train to
|
|
255
|
+
* decide during preflight — before it verifies deploy creds — whether this
|
|
256
|
+
* release even changes the Worker. */
|
|
257
|
+
checked?: boolean;
|
|
258
|
+
/** Whether the current `worker-template.ts` render differs from what the
|
|
259
|
+
* endpoint last deployed (or `--force`/an endpoint with no recorded hash). */
|
|
260
|
+
deployNeeded?: boolean;
|
|
261
|
+
/** The template hash the endpoint last deployed, per local config. Undefined
|
|
262
|
+
* on an endpoint provisioned before the hash field existed. */
|
|
263
|
+
deployedHash?: string;
|
|
253
264
|
}
|
|
254
265
|
/** Re-deploy the Worker script on an ALREADY-provisioned endpoint to match the
|
|
255
266
|
* current `worker-template.ts`. Reuses the existing account/worker/bucket and
|
|
@@ -264,6 +275,9 @@ export declare function runShareUpdate(opts?: {
|
|
|
264
275
|
account?: string;
|
|
265
276
|
token?: string;
|
|
266
277
|
force?: boolean;
|
|
278
|
+
/** Report whether a deploy is needed and return without deploying. Needs no
|
|
279
|
+
* Cloudflare credentials — change detection is a pure local render+hash. */
|
|
280
|
+
check?: boolean;
|
|
267
281
|
request?: CloudflareRequester;
|
|
268
282
|
/** Bind PHOENIX_ID_BASE even when the configured hostname is not the managed domain. */
|
|
269
283
|
managed?: boolean;
|
package/dist/commands/share.js
CHANGED
|
@@ -820,6 +820,7 @@ Prefer to change visibility without a browser? Use 'agents artifacts share visib
|
|
|
820
820
|
.option('--account <id>', 'Cloudflare account id override (default: the configured endpoint\'s account)')
|
|
821
821
|
.option('--token <t>', 'Cloudflare API token (else read from --bundle)')
|
|
822
822
|
.option('--force', 're-deploy even if the deployed template already matches')
|
|
823
|
+
.option('--check', 'report whether a deploy is needed and exit without deploying (needs no Cloudflare credentials)')
|
|
823
824
|
// Named --update-json, not --json: `share <file>` (the parent) already
|
|
824
825
|
// owns --json for its own publish-time result. Commander resolves an
|
|
825
826
|
// option's long name against the WHOLE ancestor chain, so a same-named
|
|
@@ -832,6 +833,12 @@ Prefer to change visibility without a browser? Use 'agents artifacts share visib
|
|
|
832
833
|
console.log(JSON.stringify(result, null, 2));
|
|
833
834
|
return;
|
|
834
835
|
}
|
|
836
|
+
if (result.checked) {
|
|
837
|
+
console.log(result.deployNeeded
|
|
838
|
+
? chalk.yellow(`Worker '${result.workerName}' template is outdated — deploy needed (current render ${result.templateHash.slice(0, 12)}…).`)
|
|
839
|
+
: chalk.dim(`Worker '${result.workerName}' already matches the current template — no deploy needed.`));
|
|
840
|
+
return;
|
|
841
|
+
}
|
|
835
842
|
if (result.updated) {
|
|
836
843
|
console.log(chalk.green(`Worker '${result.workerName}' updated → template ${result.templateHash.slice(0, 12)}…`));
|
|
837
844
|
}
|
|
@@ -851,11 +858,18 @@ Prefer to change visibility without a browser? Use 'agents artifacts share visib
|
|
|
851
858
|
|
|
852
859
|
# Force a re-deploy even though the template hash already matches
|
|
853
860
|
agents artifacts share update --force
|
|
861
|
+
|
|
862
|
+
# Report whether a deploy is due without deploying (no Cloudflare creds needed)
|
|
863
|
+
agents artifacts share update --check --update-json
|
|
854
864
|
`,
|
|
855
865
|
notes: `
|
|
856
866
|
Reuses the existing account/worker/bucket from 'agents artifacts share status' and the
|
|
857
867
|
existing write token — it never re-provisions a bucket, touches routes, or
|
|
858
868
|
regenerates the token. See 'agents artifacts share status' for whether an update is due.
|
|
869
|
+
|
|
870
|
+
--check renders the current template and compares its hash to what the endpoint last
|
|
871
|
+
deployed, then exits — deploying nothing and reading no Cloudflare credentials. The
|
|
872
|
+
release train uses it to decide, before publish, whether a release changes the Worker.
|
|
859
873
|
`,
|
|
860
874
|
});
|
|
861
875
|
shareCmd
|
|
@@ -1222,6 +1236,27 @@ export async function runShareUpdate(opts = {}) {
|
|
|
1222
1236
|
if (!cfg) {
|
|
1223
1237
|
throw new Error("Not configured. Run 'agents artifacts setup' (to provision) or 'agents artifacts share join' first.");
|
|
1224
1238
|
}
|
|
1239
|
+
// Change detection is a pure local computation (render + sha256), so it needs
|
|
1240
|
+
// no Cloudflare credentials. The release train calls this in `--check` mode
|
|
1241
|
+
// during preflight — BEFORE it has verified the deploy creds — to decide
|
|
1242
|
+
// whether this release changes the Worker at all. `shareTemplateStatus` is the
|
|
1243
|
+
// same comparator `agents artifacts share status` uses; 'unknown' (an endpoint
|
|
1244
|
+
// with no recorded hash) deploys, mirroring `updateWorker`'s undefined-previous
|
|
1245
|
+
// behavior.
|
|
1246
|
+
const worker = renderWorkerBundle();
|
|
1247
|
+
const templateHash = hashWorkerScript(worker.script);
|
|
1248
|
+
const deployNeeded = opts.force === true || shareTemplateStatus(cfg) !== 'current';
|
|
1249
|
+
if (opts.check) {
|
|
1250
|
+
return {
|
|
1251
|
+
updated: false,
|
|
1252
|
+
checked: true,
|
|
1253
|
+
deployNeeded,
|
|
1254
|
+
templateHash,
|
|
1255
|
+
deployedHash: cfg.templateHash,
|
|
1256
|
+
baseUrl: cfg.baseUrl,
|
|
1257
|
+
workerName: cfg.workerName,
|
|
1258
|
+
};
|
|
1259
|
+
}
|
|
1225
1260
|
const { apiToken, accountId: acctFromBundle } = readCloudflareCreds(opts.bundle ?? DEFAULT_CF_BUNDLE, {
|
|
1226
1261
|
apiToken: opts.token,
|
|
1227
1262
|
accountId: opts.account,
|
|
@@ -1231,7 +1266,6 @@ export async function runShareUpdate(opts = {}) {
|
|
|
1231
1266
|
throw new Error("Share endpoint has no Cloudflare account id — `agents artifacts share update` cannot call the API. Pass --account <id>, or re-run 'agents artifacts share join'.");
|
|
1232
1267
|
}
|
|
1233
1268
|
const writeToken = readWriteToken();
|
|
1234
|
-
const worker = renderWorkerBundle();
|
|
1235
1269
|
const phoenixIdBase = phoenixIdBaseForDeploy({ managed: opts.managed }, cfg);
|
|
1236
1270
|
const provisionOpts = {
|
|
1237
1271
|
...(opts.request ? { request: opts.request } : {}),
|
|
@@ -1242,7 +1276,14 @@ export async function runShareUpdate(opts = {}) {
|
|
|
1242
1276
|
if (!result.skipped) {
|
|
1243
1277
|
writeShareConfig({ ...cfg, accountId, templateHash: result.templateHash });
|
|
1244
1278
|
}
|
|
1245
|
-
return {
|
|
1279
|
+
return {
|
|
1280
|
+
updated: !result.skipped,
|
|
1281
|
+
templateHash: result.templateHash,
|
|
1282
|
+
deployNeeded,
|
|
1283
|
+
deployedHash: cfg.templateHash,
|
|
1284
|
+
baseUrl: cfg.baseUrl,
|
|
1285
|
+
workerName: cfg.workerName,
|
|
1286
|
+
};
|
|
1246
1287
|
}
|
|
1247
1288
|
function cleanHostname(domain) {
|
|
1248
1289
|
const raw = domain?.trim().replace(/\/+$/, '');
|