@smithers-orchestrator/cli 0.20.3 → 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 +16 -16
- 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 +65 -15
- 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 +8 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smithers-orchestrator/cli",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.4",
|
|
4
4
|
"description": "Smithers command-line interface, MCP server, and local workflow tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -32,21 +32,21 @@
|
|
|
32
32
|
"picocolors": "^1.1.1",
|
|
33
33
|
"react": "^19.2.5",
|
|
34
34
|
"zod": "^4.3.6",
|
|
35
|
-
"@smithers-orchestrator/accounts": "0.20.
|
|
36
|
-
"@smithers-orchestrator/agents": "0.20.
|
|
37
|
-
"@smithers-orchestrator/components": "0.20.
|
|
38
|
-
"@smithers-orchestrator/db": "0.20.
|
|
39
|
-
"@smithers-orchestrator/devtools": "0.20.
|
|
40
|
-
"@smithers-orchestrator/driver": "0.20.
|
|
41
|
-
"@smithers-orchestrator/
|
|
42
|
-
"@smithers-orchestrator/
|
|
43
|
-
"@smithers-orchestrator/
|
|
44
|
-
"@smithers-orchestrator/
|
|
45
|
-
"@smithers-orchestrator/
|
|
46
|
-
"@smithers-orchestrator/
|
|
47
|
-
"@smithers-orchestrator/
|
|
48
|
-
"@smithers-orchestrator/
|
|
49
|
-
"@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"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
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
|
@@ -2301,10 +2301,10 @@ let lastDevtoolsCommandOutcome;
|
|
|
2301
2301
|
* friendly typed error the helper already wrote to stderr (finding #2).
|
|
2302
2302
|
*
|
|
2303
2303
|
* @param {"tree"|"diff"|"output"|"rewind"} cmd
|
|
2304
|
-
* @param {{ args: any; options: any
|
|
2304
|
+
* @param {{ args: any; options: any }} c
|
|
2305
2305
|
* @param {() => Promise<number>} handler
|
|
2306
2306
|
*/
|
|
2307
|
-
async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
2307
|
+
async function* runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
2308
2308
|
const startedAt = Date.now();
|
|
2309
2309
|
let exitCode = 0;
|
|
2310
2310
|
try {
|
|
@@ -2362,9 +2362,8 @@ async function runDevtoolsCommandWithTelemetry(cmd, c, handler) {
|
|
|
2362
2362
|
// best-effort metrics.
|
|
2363
2363
|
}
|
|
2364
2364
|
}
|
|
2365
|
-
//
|
|
2366
|
-
//
|
|
2367
|
-
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.
|
|
2368
2367
|
}
|
|
2369
2368
|
|
|
2370
2369
|
/**
|
|
@@ -3429,8 +3428,8 @@ const cli = Cli.create({
|
|
|
3429
3428
|
// =========================================================================
|
|
3430
3429
|
// smithers inspect <run_id>
|
|
3431
3430
|
// =========================================================================
|
|
3432
|
-
|
|
3433
|
-
description: "Output detailed state
|
|
3431
|
+
.command("inspect", {
|
|
3432
|
+
description: "Output detailed run state, including steps, agents, approvals, and outputs.",
|
|
3434
3433
|
args: inspectArgs,
|
|
3435
3434
|
options: inspectOptions,
|
|
3436
3435
|
alias: { watch: "w", interval: "i" },
|
|
@@ -4356,8 +4355,8 @@ const cli = Cli.create({
|
|
|
4356
4355
|
// =========================================================================
|
|
4357
4356
|
// smithers timetravel <workflow>
|
|
4358
4357
|
// =========================================================================
|
|
4359
|
-
|
|
4360
|
-
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.",
|
|
4361
4360
|
args: workflowArgs,
|
|
4362
4361
|
options: z.object({
|
|
4363
4362
|
runId: z.string().describe("Run ID"),
|
|
@@ -4641,7 +4640,7 @@ const cli = Cli.create({
|
|
|
4641
4640
|
// rewrites raw `--json` → `-j` for these commands so it lands as a
|
|
4642
4641
|
// command option, not a format directive.
|
|
4643
4642
|
alias: { json: "j" },
|
|
4644
|
-
|
|
4643
|
+
run(c) {
|
|
4645
4644
|
return runDevtoolsCommandWithTelemetry("tree", c, async () => {
|
|
4646
4645
|
const { runTreeOnce, runTreeWatch } = await import("./tree.js");
|
|
4647
4646
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4707,7 +4706,7 @@ const cli = Cli.create({
|
|
|
4707
4706
|
color: z.enum(["auto", "always", "never"]).default("auto").describe("Colorize output"),
|
|
4708
4707
|
}),
|
|
4709
4708
|
alias: { json: "j" },
|
|
4710
|
-
|
|
4709
|
+
run(c) {
|
|
4711
4710
|
return runDevtoolsCommandWithTelemetry("diff", c, async () => {
|
|
4712
4711
|
const { runDiffOnce } = await import("./diff.js");
|
|
4713
4712
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4746,7 +4745,7 @@ const cli = Cli.create({
|
|
|
4746
4745
|
pretty: z.boolean().default(false).describe("Schema-ordered render"),
|
|
4747
4746
|
}),
|
|
4748
4747
|
alias: { json: "j" },
|
|
4749
|
-
|
|
4748
|
+
run(c) {
|
|
4750
4749
|
return runDevtoolsCommandWithTelemetry("output", c, async () => {
|
|
4751
4750
|
const { runOutputOnce } = await import("./output.js");
|
|
4752
4751
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -4782,7 +4781,7 @@ const cli = Cli.create({
|
|
|
4782
4781
|
json: z.boolean().default(false).describe("Emit JumpResult JSON"),
|
|
4783
4782
|
}),
|
|
4784
4783
|
alias: { json: "j" },
|
|
4785
|
-
|
|
4784
|
+
run(c) {
|
|
4786
4785
|
return runDevtoolsCommandWithTelemetry("rewind", c, async () => {
|
|
4787
4786
|
const { runRewindOnce } = await import("./rewind.js");
|
|
4788
4787
|
const { adapter, cleanup } = await findAndOpenDb();
|
|
@@ -5193,6 +5192,54 @@ function argvRequestsJsonMode(argv) {
|
|
|
5193
5192
|
}
|
|
5194
5193
|
return false;
|
|
5195
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
|
+
}
|
|
5196
5243
|
/**
|
|
5197
5244
|
* @param {string[]} argv
|
|
5198
5245
|
*/
|
|
@@ -5276,7 +5323,7 @@ function normalizeResumeOption(value) {
|
|
|
5276
5323
|
const CHAT_CREATE_PROMPT = [
|
|
5277
5324
|
"Start an interactive chat session with the user and help them directly.",
|
|
5278
5325
|
"Stay in this conversation until the user is done.",
|
|
5279
|
-
'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: {}.',
|
|
5280
5327
|
].join("\n\n");
|
|
5281
5328
|
/**
|
|
5282
5329
|
* @param {"claude-code" | "codex" | "gemini"} agentId
|
|
@@ -5288,7 +5335,7 @@ async function createChatAgent(agentId, cwd) {
|
|
|
5288
5335
|
const { ClaudeCodeAgent } = await import("@smithers-orchestrator/agents/ClaudeCodeAgent");
|
|
5289
5336
|
return new ClaudeCodeAgent({
|
|
5290
5337
|
cwd,
|
|
5291
|
-
model: "claude-opus-4-
|
|
5338
|
+
model: "claude-opus-4-7",
|
|
5292
5339
|
});
|
|
5293
5340
|
}
|
|
5294
5341
|
case "codex": {
|
|
@@ -5395,6 +5442,9 @@ async function main() {
|
|
|
5395
5442
|
if (argvRequestsJsonMode(argv)) {
|
|
5396
5443
|
setJsonMode(true);
|
|
5397
5444
|
}
|
|
5445
|
+
if (runRawJsonAgentCommandIfMatched(argv)) {
|
|
5446
|
+
return;
|
|
5447
|
+
}
|
|
5398
5448
|
// Finding #1: pre-validate argv for devtools commands so missing-args
|
|
5399
5449
|
// / invalid-flag errors go to stderr with exit 1 (not incur's
|
|
5400
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
|
@@ -183,7 +183,7 @@ function renderAgentScaffoldFiles() {
|
|
|
183
183
|
'// Built-in Claude Code CLI agent (cliEngine: "claude-code").',
|
|
184
184
|
"// Tweak `model`, `cwd`, or uncomment extra options below to match your setup.",
|
|
185
185
|
"export const ClaudeCodeAgent = new SmithersClaudeCodeAgent({",
|
|
186
|
-
' model: "claude-opus-4-
|
|
186
|
+
' model: "claude-opus-4-7",',
|
|
187
187
|
" cwd: process.cwd(),",
|
|
188
188
|
' // systemPrompt: "Add shared instructions for every Claude run.",',
|
|
189
189
|
" // timeoutMs: 10 * 60 * 1000,",
|
|
@@ -279,9 +279,10 @@ function renderPrompts() {
|
|
|
279
279
|
"",
|
|
280
280
|
"Reviewer: {props.reviewer}",
|
|
281
281
|
"",
|
|
282
|
-
"Review the following request and
|
|
283
|
-
"
|
|
284
|
-
"
|
|
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.",
|
|
285
286
|
"",
|
|
286
287
|
"REQUEST:",
|
|
287
288
|
"{props.prompt}",
|
|
@@ -289,6 +290,8 @@ function renderPrompts() {
|
|
|
289
290
|
"REQUIRED OUTPUT:",
|
|
290
291
|
"{props.schema}",
|
|
291
292
|
"",
|
|
293
|
+
"Return ONLY raw JSON matching the required output schema.",
|
|
294
|
+
"",
|
|
292
295
|
].join("\n"),
|
|
293
296
|
},
|
|
294
297
|
{
|
|
@@ -3221,7 +3224,7 @@ function renderWorkflows() {
|
|
|
3221
3224
|
" return (",
|
|
3222
3225
|
" <Worktree",
|
|
3223
3226
|
" key={ticket.slug}",
|
|
3224
|
-
|
|
3227
|
+
' path={resolve(process.cwd(), ".worktrees", ticket.slug)}',
|
|
3225
3228
|
" branch={`ticket/${ticket.slug}`}",
|
|
3226
3229
|
" >",
|
|
3227
3230
|
" <Sequence>",
|