@smithers-orchestrator/cli 0.20.1 → 0.20.4
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/package.json +17 -19
- package/src/agent-detection.js +2 -2
- package/src/event-categories.js +5 -0
- package/src/find-db.js +6 -6
- package/src/index.js +117 -59
- package/src/mcp/semantic-tools.js +1 -2
- package/src/node-detail.js +1 -6
- package/src/watch.js +1 -2
- package/src/why-diagnosis.js +1 -2
- package/src/workflow-pack.js +23 -11
- package/src/tui/app.jsx +0 -139
- package/src/tui/app.tsx +0 -5
- package/src/tui/components/AskModal.jsx +0 -109
- package/src/tui/components/AskModal.tsx +0 -3
- package/src/tui/components/AttentionPane.jsx +0 -112
- package/src/tui/components/AttentionPane.tsx +0 -6
- package/src/tui/components/ChatPane.jsx +0 -57
- package/src/tui/components/ChatPane.tsx +0 -7
- package/src/tui/components/CronList.jsx +0 -87
- package/src/tui/components/CronList.tsx +0 -5
- package/src/tui/components/DetailsPane.jsx +0 -96
- package/src/tui/components/DetailsPane.tsx +0 -7
- package/src/tui/components/FramesPane.jsx +0 -147
- package/src/tui/components/FramesPane.tsx +0 -8
- package/src/tui/components/LogsPane.jsx +0 -46
- package/src/tui/components/LogsPane.tsx +0 -6
- package/src/tui/components/MetricsPane.jsx +0 -108
- package/src/tui/components/MetricsPane.tsx +0 -5
- package/src/tui/components/NodeDetailView.jsx +0 -284
- package/src/tui/components/NodeDetailView.tsx +0 -7
- package/src/tui/components/NodeInspector.jsx +0 -51
- package/src/tui/components/NodeInspector.tsx +0 -7
- package/src/tui/components/RunDetailView.jsx +0 -190
- package/src/tui/components/RunDetailView.tsx +0 -7
- package/src/tui/components/RunsList.jsx +0 -184
- package/src/tui/components/RunsList.tsx +0 -7
- package/src/tui/components/SqliteBrowser.jsx +0 -131
- package/src/tui/components/SqliteBrowser.tsx +0 -5
- package/src/tui/components/WorkflowLauncher.jsx +0 -63
- package/src/tui/components/WorkflowLauncher.tsx +0 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithers-orchestrator/cli",
|
|
3
|
-
"version": "0.20.
|
|
4
|
-
"description": "Smithers command-line interface,
|
|
3
|
+
"version": "0.20.4",
|
|
4
|
+
"description": "Smithers command-line interface, MCP server, and local workflow tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"exports": {
|
|
@@ -25,8 +25,6 @@
|
|
|
25
25
|
"@effect/workflow": "^0.18.0",
|
|
26
26
|
"@clack/prompts": "^0.10.1",
|
|
27
27
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
28
|
-
"@opentui/core": "^0.1.100",
|
|
29
|
-
"@opentui/react": "^0.1.100",
|
|
30
28
|
"cron-parser": "^5.5.0",
|
|
31
29
|
"drizzle-orm": "^0.45.2",
|
|
32
30
|
"effect": "^3.21.1",
|
|
@@ -34,21 +32,21 @@
|
|
|
34
32
|
"picocolors": "^1.1.1",
|
|
35
33
|
"react": "^19.2.5",
|
|
36
34
|
"zod": "^4.3.6",
|
|
37
|
-
"@smithers-orchestrator/accounts": "0.20.
|
|
38
|
-
"@smithers-orchestrator/agents": "0.20.
|
|
39
|
-
"@smithers-orchestrator/components": "0.20.
|
|
40
|
-
"@smithers-orchestrator/db": "0.20.
|
|
41
|
-
"@smithers-orchestrator/devtools": "0.20.
|
|
42
|
-
"@smithers-orchestrator/driver": "0.20.
|
|
43
|
-
"@smithers-orchestrator/
|
|
44
|
-
"@smithers-orchestrator/
|
|
45
|
-
"@smithers-orchestrator/
|
|
46
|
-
"@smithers-orchestrator/
|
|
47
|
-
"@smithers-orchestrator/
|
|
48
|
-
"@smithers-orchestrator/
|
|
49
|
-
"@smithers-orchestrator/
|
|
50
|
-
"@smithers-orchestrator/
|
|
51
|
-
"@smithers-orchestrator/
|
|
35
|
+
"@smithers-orchestrator/accounts": "0.20.4",
|
|
36
|
+
"@smithers-orchestrator/agents": "0.20.4",
|
|
37
|
+
"@smithers-orchestrator/components": "0.20.4",
|
|
38
|
+
"@smithers-orchestrator/db": "0.20.4",
|
|
39
|
+
"@smithers-orchestrator/devtools": "0.20.4",
|
|
40
|
+
"@smithers-orchestrator/driver": "0.20.4",
|
|
41
|
+
"@smithers-orchestrator/errors": "0.20.4",
|
|
42
|
+
"@smithers-orchestrator/observability": "0.20.4",
|
|
43
|
+
"@smithers-orchestrator/protocol": "0.20.4",
|
|
44
|
+
"@smithers-orchestrator/scheduler": "0.20.4",
|
|
45
|
+
"@smithers-orchestrator/engine": "0.20.4",
|
|
46
|
+
"@smithers-orchestrator/server": "0.20.4",
|
|
47
|
+
"@smithers-orchestrator/time-travel": "0.20.4",
|
|
48
|
+
"@smithers-orchestrator/memory": "0.20.4",
|
|
49
|
+
"@smithers-orchestrator/openapi": "0.20.4"
|
|
52
50
|
},
|
|
53
51
|
"devDependencies": {
|
|
54
52
|
"@types/bun": "latest",
|
package/src/agent-detection.js
CHANGED
|
@@ -91,7 +91,7 @@ const AGENT_VARIANTS = [
|
|
|
91
91
|
displayName: "Claude Sonnet",
|
|
92
92
|
constructor: {
|
|
93
93
|
importName: "ClaudeCodeAgent",
|
|
94
|
-
expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-
|
|
94
|
+
expr: 'new SmithersClaudeCodeAgent({ model: "claude-sonnet-4-7", cwd: process.cwd() })',
|
|
95
95
|
},
|
|
96
96
|
},
|
|
97
97
|
];
|
|
@@ -108,7 +108,7 @@ const TIER_PREFERENCES = {
|
|
|
108
108
|
const CONSTRUCTORS = {
|
|
109
109
|
claude: {
|
|
110
110
|
importName: "ClaudeCodeAgent",
|
|
111
|
-
expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-
|
|
111
|
+
expr: 'new SmithersClaudeCodeAgent({ model: "claude-opus-4-7", cwd: process.cwd() })',
|
|
112
112
|
},
|
|
113
113
|
codex: {
|
|
114
114
|
importName: "CodexAgent",
|
package/src/event-categories.js
CHANGED
|
@@ -8,6 +8,7 @@ const EVENT_CATEGORY_BY_TYPE = {
|
|
|
8
8
|
RunAutoResumeSkipped: "run",
|
|
9
9
|
RunStarted: "run",
|
|
10
10
|
RunStatusChanged: "run",
|
|
11
|
+
RunStateChanged: "run",
|
|
11
12
|
RunFinished: "run",
|
|
12
13
|
RunFailed: "run",
|
|
13
14
|
RunCancelled: "run",
|
|
@@ -49,6 +50,7 @@ const EVENT_CATEGORY_BY_TYPE = {
|
|
|
49
50
|
RevertFinished: "revert",
|
|
50
51
|
TimeTravelStarted: "revert",
|
|
51
52
|
TimeTravelFinished: "revert",
|
|
53
|
+
TimeTravelJumped: "revert",
|
|
52
54
|
WorkflowReloadDetected: "workflow",
|
|
53
55
|
WorkflowReloaded: "workflow",
|
|
54
56
|
WorkflowReloadFailed: "workflow",
|
|
@@ -67,6 +69,9 @@ const EVENT_CATEGORY_BY_TYPE = {
|
|
|
67
69
|
TimerCreated: "timer",
|
|
68
70
|
TimerFired: "timer",
|
|
69
71
|
TimerCancelled: "timer",
|
|
72
|
+
AgentTraceEvent: "agent",
|
|
73
|
+
AgentTraceSummary: "agent",
|
|
74
|
+
AgentSessionEvent: "agent",
|
|
70
75
|
};
|
|
71
76
|
const CATEGORY_ALIASES = {
|
|
72
77
|
agent: "agent",
|
package/src/find-db.js
CHANGED
|
@@ -15,16 +15,16 @@ import { SmithersError } from "@smithers-orchestrator/errors";
|
|
|
15
15
|
export function findSmithersDb(from) {
|
|
16
16
|
let dir = resolve(from ?? process.cwd());
|
|
17
17
|
const root = resolve("/");
|
|
18
|
-
while (
|
|
18
|
+
while (dir !== root) {
|
|
19
19
|
const candidate = resolve(dir, "smithers.db");
|
|
20
20
|
if (existsSync(candidate))
|
|
21
21
|
return candidate;
|
|
22
|
-
|
|
23
|
-
if (parent === dir || dir === root) {
|
|
24
|
-
throw new SmithersError("CLI_DB_NOT_FOUND", "No smithers.db found. Run this command from a directory containing a smithers.db, or use 'smithers up <workflow>' to start a run first.");
|
|
25
|
-
}
|
|
26
|
-
dir = parent;
|
|
22
|
+
dir = dirname(dir);
|
|
27
23
|
}
|
|
24
|
+
const rootCandidate = resolve(root, "smithers.db");
|
|
25
|
+
if (existsSync(rootCandidate))
|
|
26
|
+
return rootCandidate;
|
|
27
|
+
throw new SmithersError("CLI_DB_NOT_FOUND", "No smithers.db found. Run this command from a directory containing a smithers.db, or use 'smithers up <workflow>' to start a run first.");
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
30
|
* @param {number} ms
|
package/src/index.js
CHANGED
|
@@ -484,6 +484,41 @@ function isRunStatusTerminal(status) {
|
|
|
484
484
|
status !== "waiting-timer" &&
|
|
485
485
|
status !== "waiting-event");
|
|
486
486
|
}
|
|
487
|
+
/**
|
|
488
|
+
* Fetch a docs file from smithers.sh and write it to stdout.
|
|
489
|
+
* Honors --json (global) by emitting `{ url, content }`.
|
|
490
|
+
*
|
|
491
|
+
* @param {{ error: Function; ok: Function; format?: string; options?: { json?: boolean } }} c
|
|
492
|
+
* @param {string} url
|
|
493
|
+
* @param {string} errorCode
|
|
494
|
+
*/
|
|
495
|
+
async function printSmithersDocs(c, url, errorCode) {
|
|
496
|
+
let body;
|
|
497
|
+
try {
|
|
498
|
+
const res = await fetch(url);
|
|
499
|
+
if (!res.ok) {
|
|
500
|
+
return c.error({
|
|
501
|
+
code: errorCode,
|
|
502
|
+
message: `Failed to fetch ${url}: HTTP ${res.status}`,
|
|
503
|
+
exitCode: 1,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
body = await res.text();
|
|
507
|
+
}
|
|
508
|
+
catch (err) {
|
|
509
|
+
return c.error({
|
|
510
|
+
code: errorCode,
|
|
511
|
+
message: `Failed to fetch ${url}: ${err?.message ?? String(err)}`,
|
|
512
|
+
exitCode: 1,
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
const wantsJson = Boolean(c.options?.json) || c.format === "json";
|
|
516
|
+
if (wantsJson) {
|
|
517
|
+
return c.ok({ url, content: body });
|
|
518
|
+
}
|
|
519
|
+
process.stdout.write(body.endsWith("\n") ? body : `${body}\n`);
|
|
520
|
+
return c.ok(undefined);
|
|
521
|
+
}
|
|
487
522
|
/**
|
|
488
523
|
* @param {string | undefined} format
|
|
489
524
|
* @param {unknown} payload
|
|
@@ -2266,10 +2301,10 @@ let lastDevtoolsCommandOutcome;
|
|
|
2266
2301
|
* friendly typed error the helper already wrote to stderr (finding #2).
|
|
2267
2302
|
*
|
|
2268
2303
|
* @param {"tree"|"diff"|"output"|"rewind"} cmd
|
|
2269
|
-
* @param {{ args: any; options: any
|
|
2304
|
+
* @param {{ args: any; options: any }} c
|
|
2270
2305
|
* @param {() => Promise<number>} handler
|
|
2271
2306
|
*/
|
|
2272
|
-
async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
2307
|
+
async function* runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
2273
2308
|
const startedAt = Date.now();
|
|
2274
2309
|
let exitCode = 0;
|
|
2275
2310
|
try {
|
|
@@ -2327,9 +2362,8 @@ async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
|
2327
2362
|
// best-effort metrics.
|
|
2328
2363
|
}
|
|
2329
2364
|
}
|
|
2330
|
-
//
|
|
2331
|
-
//
|
|
2332
|
-
return c.ok(undefined);
|
|
2365
|
+
// This is an empty stream so Incur does not emit an additional envelope
|
|
2366
|
+
// or framework CTA on stdout after the helper has already written output.
|
|
2333
2367
|
}
|
|
2334
2368
|
|
|
2335
2369
|
/**
|
|
@@ -2551,8 +2585,8 @@ const cli = Cli.create({
|
|
|
2551
2585
|
{ command: "workflow run implement", description: "Run the implementation workflow" },
|
|
2552
2586
|
]
|
|
2553
2587
|
: [
|
|
2554
|
-
{ command: "tui", description: "Open the interactive dashboard" },
|
|
2555
2588
|
{ command: "workflow list", description: "View all available workflows" },
|
|
2589
|
+
{ command: "workflow run implement", description: "Run the implementation workflow" },
|
|
2556
2590
|
],
|
|
2557
2591
|
},
|
|
2558
2592
|
});
|
|
@@ -2641,49 +2675,6 @@ const cli = Cli.create({
|
|
|
2641
2675
|
cleanup();
|
|
2642
2676
|
}
|
|
2643
2677
|
},
|
|
2644
|
-
})
|
|
2645
|
-
// =========================================================================
|
|
2646
|
-
// smithers tui
|
|
2647
|
-
// =========================================================================
|
|
2648
|
-
.command("tui", {
|
|
2649
|
-
description: "Open the interactive Smithers observability dashboard",
|
|
2650
|
-
async run(c) {
|
|
2651
|
-
const fail = (opts) => {
|
|
2652
|
-
commandExitOverride = opts.exitCode ?? 1;
|
|
2653
|
-
return c.error(opts);
|
|
2654
|
-
};
|
|
2655
|
-
let cleanup;
|
|
2656
|
-
let renderer;
|
|
2657
|
-
try {
|
|
2658
|
-
const db = await findAndOpenDb(undefined, {
|
|
2659
|
-
timeoutMs: 5000,
|
|
2660
|
-
intervalMs: 100,
|
|
2661
|
-
});
|
|
2662
|
-
const adapter = db.adapter;
|
|
2663
|
-
cleanup = db.cleanup;
|
|
2664
|
-
const { createCliRenderer } = await import("@opentui/core");
|
|
2665
|
-
const { createRoot } = await import("@opentui/react");
|
|
2666
|
-
const { TuiApp } = await import("./tui/app.jsx");
|
|
2667
|
-
const React = await import("react");
|
|
2668
|
-
renderer = await createCliRenderer({ exitOnCtrlC: false });
|
|
2669
|
-
const root = createRoot(renderer);
|
|
2670
|
-
await new Promise((resolve) => {
|
|
2671
|
-
root.render(React.createElement(TuiApp, {
|
|
2672
|
-
adapter,
|
|
2673
|
-
onExit: () => resolve(true),
|
|
2674
|
-
}));
|
|
2675
|
-
});
|
|
2676
|
-
return c.ok(undefined);
|
|
2677
|
-
}
|
|
2678
|
-
catch (err) {
|
|
2679
|
-
return fail({ code: "TUI_FAILED", message: err?.message ?? String(err), exitCode: 1 });
|
|
2680
|
-
}
|
|
2681
|
-
finally {
|
|
2682
|
-
if (renderer)
|
|
2683
|
-
renderer.destroy();
|
|
2684
|
-
cleanup?.();
|
|
2685
|
-
}
|
|
2686
|
-
}
|
|
2687
2678
|
})
|
|
2688
2679
|
// =========================================================================
|
|
2689
2680
|
// smithers ps
|
|
@@ -3437,8 +3428,8 @@ const cli = Cli.create({
|
|
|
3437
3428
|
// =========================================================================
|
|
3438
3429
|
// smithers inspect <run_id>
|
|
3439
3430
|
// =========================================================================
|
|
3440
|
-
|
|
3441
|
-
description: "Output detailed state
|
|
3431
|
+
.command("inspect", {
|
|
3432
|
+
description: "Output detailed run state, including steps, agents, approvals, and outputs.",
|
|
3442
3433
|
args: inspectArgs,
|
|
3443
3434
|
options: inspectOptions,
|
|
3444
3435
|
alias: { watch: "w", interval: "i" },
|
|
@@ -4364,8 +4355,8 @@ const cli = Cli.create({
|
|
|
4364
4355
|
// =========================================================================
|
|
4365
4356
|
// smithers timetravel <workflow>
|
|
4366
4357
|
// =========================================================================
|
|
4367
|
-
|
|
4368
|
-
description: "Time-travel to a previous task state
|
|
4358
|
+
.command("timetravel", {
|
|
4359
|
+
description: "Time-travel to a previous task state by reverting filesystem state, resetting DB state, and optionally resuming.",
|
|
4369
4360
|
args: workflowArgs,
|
|
4370
4361
|
options: z.object({
|
|
4371
4362
|
runId: z.string().describe("Run ID"),
|
|
@@ -4649,7 +4640,7 @@ const cli = Cli.create({
|
|
|
4649
4640
|
// rewrites raw `--json` → `-j` for these commands so it lands as a
|
|
4650
4641
|
// command option, not a format directive.
|
|
4651
4642
|
alias: { json: "j" },
|
|
4652
|
-
|
|
4643
|
+
run(c) {
|
|
4653
4644
|
return runDevtoolsCommandWithTelemetry("tree", c, async () => {
|
|
4654
4645
|
const { runTreeOnce, runTreeWatch } = await import("./tree.js");
|
|
4655
4646
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4715,7 +4706,7 @@ const cli = Cli.create({
|
|
|
4715
4706
|
color: z.enum(["auto", "always", "never"]).default("auto").describe("Colorize output"),
|
|
4716
4707
|
}),
|
|
4717
4708
|
alias: { json: "j" },
|
|
4718
|
-
|
|
4709
|
+
run(c) {
|
|
4719
4710
|
return runDevtoolsCommandWithTelemetry("diff", c, async () => {
|
|
4720
4711
|
const { runDiffOnce } = await import("./diff.js");
|
|
4721
4712
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4754,7 +4745,7 @@ const cli = Cli.create({
|
|
|
4754
4745
|
pretty: z.boolean().default(false).describe("Schema-ordered render"),
|
|
4755
4746
|
}),
|
|
4756
4747
|
alias: { json: "j" },
|
|
4757
|
-
|
|
4748
|
+
run(c) {
|
|
4758
4749
|
return runDevtoolsCommandWithTelemetry("output", c, async () => {
|
|
4759
4750
|
const { runOutputOnce } = await import("./output.js");
|
|
4760
4751
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4790,7 +4781,7 @@ const cli = Cli.create({
|
|
|
4790
4781
|
json: z.boolean().default(false).describe("Emit JumpResult JSON"),
|
|
4791
4782
|
}),
|
|
4792
4783
|
alias: { json: "j" },
|
|
4793
|
-
|
|
4784
|
+
run(c) {
|
|
4794
4785
|
return runDevtoolsCommandWithTelemetry("rewind", c, async () => {
|
|
4795
4786
|
const { runRewindOnce } = await import("./rewind.js");
|
|
4796
4787
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4966,6 +4957,22 @@ const cli = Cli.create({
|
|
|
4966
4957
|
return c.error({ code: "GUI_LAUNCH_FAILED", message: err?.message ?? String(err), exitCode: 1 });
|
|
4967
4958
|
}
|
|
4968
4959
|
},
|
|
4960
|
+
})
|
|
4961
|
+
// =========================================================================
|
|
4962
|
+
// smithers docs / smithers docs-full
|
|
4963
|
+
// Print the published llms.txt / llms-full.txt from smithers.sh.
|
|
4964
|
+
// =========================================================================
|
|
4965
|
+
.command("docs", {
|
|
4966
|
+
description: "Print llms.txt (concise docs index for LLMs) from smithers.sh.",
|
|
4967
|
+
async run(c) {
|
|
4968
|
+
return printSmithersDocs(c, "https://smithers.sh/llms.txt", "DOCS_FETCH_FAILED");
|
|
4969
|
+
},
|
|
4970
|
+
})
|
|
4971
|
+
.command("docs-full", {
|
|
4972
|
+
description: "Print llms-full.txt (full docs bundle for LLMs) from smithers.sh.",
|
|
4973
|
+
async run(c) {
|
|
4974
|
+
return printSmithersDocs(c, "https://smithers.sh/llms-full.txt", "DOCS_FULL_FETCH_FAILED");
|
|
4975
|
+
},
|
|
4969
4976
|
})
|
|
4970
4977
|
.command(workflowCli)
|
|
4971
4978
|
.command(cronCli)
|
|
@@ -5185,6 +5192,54 @@ function argvRequestsJsonMode(argv) {
|
|
|
5185
5192
|
}
|
|
5186
5193
|
return false;
|
|
5187
5194
|
}
|
|
5195
|
+
/**
|
|
5196
|
+
* Some commands own stdout completely and promise a raw JSON document even
|
|
5197
|
+
* without `--format json`. Run those before Incur can append framework CTAs
|
|
5198
|
+
* such as the stale-skills reminder, which would make stdout unparsable.
|
|
5199
|
+
*
|
|
5200
|
+
* @param {string[]} argv
|
|
5201
|
+
* @returns {boolean}
|
|
5202
|
+
*/
|
|
5203
|
+
function runRawJsonAgentCommandIfMatched(argv) {
|
|
5204
|
+
const positionals = [];
|
|
5205
|
+
let jsonOutput = false;
|
|
5206
|
+
for (let index = 0; index < argv.length; index++) {
|
|
5207
|
+
const arg = argv[index];
|
|
5208
|
+
if (arg === "--json") {
|
|
5209
|
+
jsonOutput = true;
|
|
5210
|
+
continue;
|
|
5211
|
+
}
|
|
5212
|
+
if (arg === "--format") {
|
|
5213
|
+
if (argv[index + 1] !== "json") {
|
|
5214
|
+
return false;
|
|
5215
|
+
}
|
|
5216
|
+
jsonOutput = true;
|
|
5217
|
+
index += 1;
|
|
5218
|
+
continue;
|
|
5219
|
+
}
|
|
5220
|
+
if (arg === "--format=json") {
|
|
5221
|
+
jsonOutput = true;
|
|
5222
|
+
continue;
|
|
5223
|
+
}
|
|
5224
|
+
if (arg.startsWith("-")) {
|
|
5225
|
+
return false;
|
|
5226
|
+
}
|
|
5227
|
+
positionals.push(arg);
|
|
5228
|
+
}
|
|
5229
|
+
if (positionals.length !== 2 || positionals[0] !== "agents") {
|
|
5230
|
+
return false;
|
|
5231
|
+
}
|
|
5232
|
+
if (positionals[1] === "capabilities") {
|
|
5233
|
+
process.stdout.write(`${JSON.stringify(getCliAgentCapabilityReport(), null, 2)}\n`);
|
|
5234
|
+
process.exit(0);
|
|
5235
|
+
}
|
|
5236
|
+
if (positionals[1] === "doctor" && jsonOutput) {
|
|
5237
|
+
const report = getCliAgentCapabilityDoctorReport();
|
|
5238
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
5239
|
+
process.exit(report.ok ? 0 : 1);
|
|
5240
|
+
}
|
|
5241
|
+
return false;
|
|
5242
|
+
}
|
|
5188
5243
|
/**
|
|
5189
5244
|
* @param {string[]} argv
|
|
5190
5245
|
*/
|
|
@@ -5268,7 +5323,7 @@ function normalizeResumeOption(value) {
|
|
|
5268
5323
|
const CHAT_CREATE_PROMPT = [
|
|
5269
5324
|
"Start an interactive chat session with the user and help them directly.",
|
|
5270
5325
|
"Stay in this conversation until the user is done.",
|
|
5271
|
-
'When you are completely finished and want to hand control back to Smithers,
|
|
5326
|
+
'When you are completely finished and want to hand control back to Smithers, return ONLY this raw JSON object with no prose, markdown, or code fence: {}.',
|
|
5272
5327
|
].join("\n\n");
|
|
5273
5328
|
/**
|
|
5274
5329
|
* @param {"claude-code" | "codex" | "gemini"} agentId
|
|
@@ -5280,7 +5335,7 @@ async function createChatAgent(agentId, cwd) {
|
|
|
5280
5335
|
const { ClaudeCodeAgent } = await import("@smithers-orchestrator/agents/ClaudeCodeAgent");
|
|
5281
5336
|
return new ClaudeCodeAgent({
|
|
5282
5337
|
cwd,
|
|
5283
|
-
model: "claude-opus-4-
|
|
5338
|
+
model: "claude-opus-4-7",
|
|
5284
5339
|
});
|
|
5285
5340
|
}
|
|
5286
5341
|
case "codex": {
|
|
@@ -5387,6 +5442,9 @@ async function main() {
|
|
|
5387
5442
|
if (argvRequestsJsonMode(argv)) {
|
|
5388
5443
|
setJsonMode(true);
|
|
5389
5444
|
}
|
|
5445
|
+
if (runRawJsonAgentCommandIfMatched(argv)) {
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5390
5448
|
// Finding #1: pre-validate argv for devtools commands so missing-args
|
|
5391
5449
|
// / invalid-flag errors go to stderr with exit 1 (not incur's
|
|
5392
5450
|
// remap-to-4 VALIDATION_ERROR envelope on stdout).
|
package/src/node-detail.js
CHANGED
|
@@ -89,12 +89,7 @@ function parseErrorSummary(raw) {
|
|
|
89
89
|
if (message) {
|
|
90
90
|
return { message, detail: parsed };
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
return { message: JSON.stringify(parsed), detail: parsed };
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
return { message: String(parsed), detail: parsed };
|
|
97
|
-
}
|
|
92
|
+
return { message: JSON.stringify(parsed), detail: parsed };
|
|
98
93
|
}
|
|
99
94
|
return { message: String(parsed), detail: parsed };
|
|
100
95
|
}
|
package/src/watch.js
CHANGED
|
@@ -110,7 +110,7 @@ export async function runWatchLoop(options) {
|
|
|
110
110
|
tickCount += 1;
|
|
111
111
|
latest = await options.fetch();
|
|
112
112
|
await renderSnapshot(latest, false);
|
|
113
|
-
if (options.isTerminal?.(latest))
|
|
113
|
+
if (options.isTerminal?.(latest))
|
|
114
114
|
return {
|
|
115
115
|
intervalMs,
|
|
116
116
|
tickCount,
|
|
@@ -118,7 +118,6 @@ export async function runWatchLoop(options) {
|
|
|
118
118
|
reachedTerminal: true,
|
|
119
119
|
lastData: latest,
|
|
120
120
|
};
|
|
121
|
-
}
|
|
122
121
|
}
|
|
123
122
|
}
|
|
124
123
|
finally {
|
package/src/why-diagnosis.js
CHANGED
|
@@ -461,8 +461,7 @@ function computeSignalName(node, descriptor, attempts, events) {
|
|
|
461
461
|
correlationId ??
|
|
462
462
|
parseString(payload.correlationId) ??
|
|
463
463
|
null;
|
|
464
|
-
if (signalName && correlationId)
|
|
465
|
-
break;
|
|
464
|
+
if (signalName && correlationId) break;
|
|
466
465
|
}
|
|
467
466
|
return { signalName, correlationId };
|
|
468
467
|
}
|
package/src/workflow-pack.js
CHANGED
|
@@ -133,7 +133,6 @@ function renderPackageJson(versions) {
|
|
|
133
133
|
dependencies: {
|
|
134
134
|
react: versions.reactVersion,
|
|
135
135
|
"react-dom": versions.reactDomVersion,
|
|
136
|
-
skills: "github:mattpocock/skills",
|
|
137
136
|
"smithers-orchestrator": smithersSpec,
|
|
138
137
|
zod: versions.zodVersion,
|
|
139
138
|
},
|
|
@@ -184,7 +183,7 @@ function renderAgentScaffoldFiles() {
|
|
|
184
183
|
'// Built-in Claude Code CLI agent (cliEngine: "claude-code").',
|
|
185
184
|
"// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
|
|
186
185
|
"export const ClaudeCodeAgent = new SmithersClaudeCodeAgent({",
|
|
187
|
-
' model: "claude-opus-4-
|
|
186
|
+
' model: "claude-opus-4-7",',
|
|
188
187
|
" cwd: process.cwd(),",
|
|
189
188
|
' // systemPrompt: "Add shared instructions for every Claude run.",',
|
|
190
189
|
" // timeoutMs: 10 * 60 * 1000,",
|
|
@@ -280,9 +279,10 @@ function renderPrompts() {
|
|
|
280
279
|
"",
|
|
281
280
|
"Reviewer: {props.reviewer}",
|
|
282
281
|
"",
|
|
283
|
-
"Review the following request and
|
|
284
|
-
"
|
|
285
|
-
"
|
|
282
|
+
"Review the following request and return ONLY the required JSON object.",
|
|
283
|
+
"Do not include prose, markdown, headings, commentary, or code fences.",
|
|
284
|
+
"The first character of your response must be `{` and the last character must be `}`.",
|
|
285
|
+
"Be a very thorough reviewer who only accepts production ready tested code.",
|
|
286
286
|
"",
|
|
287
287
|
"REQUEST:",
|
|
288
288
|
"{props.prompt}",
|
|
@@ -290,6 +290,8 @@ function renderPrompts() {
|
|
|
290
290
|
"REQUIRED OUTPUT:",
|
|
291
291
|
"{props.schema}",
|
|
292
292
|
"",
|
|
293
|
+
"Return ONLY raw JSON matching the required output schema.",
|
|
294
|
+
"",
|
|
293
295
|
].join("\n"),
|
|
294
296
|
},
|
|
295
297
|
{
|
|
@@ -413,6 +415,17 @@ function renderPrompts() {
|
|
|
413
415
|
"",
|
|
414
416
|
].join("\n"),
|
|
415
417
|
},
|
|
418
|
+
{
|
|
419
|
+
path: ".smithers/prompts/grill-me.mdx",
|
|
420
|
+
contents: [
|
|
421
|
+
"Interview me relentlessly about every aspect of this plan until we reach a shared understanding. Walk down each branch of the design tree, resolving dependencies between decisions one-by-one. For each question, provide your recommended answer.",
|
|
422
|
+
"",
|
|
423
|
+
"Ask the questions one at a time.",
|
|
424
|
+
"",
|
|
425
|
+
"If a question can be answered by exploring the codebase, explore the codebase instead.",
|
|
426
|
+
"",
|
|
427
|
+
].join("\n"),
|
|
428
|
+
},
|
|
416
429
|
{
|
|
417
430
|
path: ".smithers/prompts/write-a-prd.mdx",
|
|
418
431
|
contents: [
|
|
@@ -1185,7 +1198,7 @@ function renderComponents() {
|
|
|
1185
1198
|
"/** @jsxImportSource smithers-orchestrator */",
|
|
1186
1199
|
'import { Loop, Sequence, Task, type AgentLike, type OutputTarget } from "smithers-orchestrator";',
|
|
1187
1200
|
'import { z } from "zod/v4";',
|
|
1188
|
-
'import GrillMeSkill from "
|
|
1201
|
+
'import GrillMeSkill from "../prompts/grill-me.mdx";',
|
|
1189
1202
|
'import AskUserInstructions from "../prompts/ask-user-instructions.mdx";',
|
|
1190
1203
|
"",
|
|
1191
1204
|
"export const grillOutputSchema = z.looseObject({",
|
|
@@ -3211,7 +3224,7 @@ function renderWorkflows() {
|
|
|
3211
3224
|
" return (",
|
|
3212
3225
|
" <Worktree",
|
|
3213
3226
|
" key={ticket.slug}",
|
|
3214
|
-
|
|
3227
|
+
' path={resolve(process.cwd(), ".worktrees", ticket.slug)}',
|
|
3215
3228
|
" branch={`ticket/${ticket.slug}`}",
|
|
3216
3229
|
" >",
|
|
3217
3230
|
" <Sequence>",
|
|
@@ -3417,10 +3430,9 @@ export function initWorkflowPack(options = {}) {
|
|
|
3417
3430
|
};
|
|
3418
3431
|
}
|
|
3419
3432
|
/**
|
|
3420
|
-
* Install `.smithers/` workspace deps so
|
|
3421
|
-
*
|
|
3422
|
-
*
|
|
3423
|
-
* the scaffold is on disk, the user can always re-run `bun install` by hand.
|
|
3433
|
+
* Install `.smithers/` workspace deps so the first workflow run isn't blocked
|
|
3434
|
+
* on a cold install. Failures here don't fail init: the scaffold is on disk,
|
|
3435
|
+
* the user can always re-run `bun install` by hand.
|
|
3424
3436
|
*
|
|
3425
3437
|
* @param {string} rootDir
|
|
3426
3438
|
* @param {boolean} skip
|