@united-workforce/cli 0.6.1 → 0.8.1
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/README.md +120 -5
- package/dist/.build-fingerprint +1 -1
- package/dist/__tests__/agent-resolution-llm-free.test.js +9 -2
- package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -1
- package/dist/__tests__/broker-prompt.test.d.ts +10 -0
- package/dist/__tests__/broker-prompt.test.d.ts.map +1 -0
- package/dist/__tests__/broker-prompt.test.js +129 -0
- package/dist/__tests__/broker-prompt.test.js.map +1 -0
- package/dist/__tests__/broker-step-active-turns.test.d.ts +20 -0
- package/dist/__tests__/broker-step-active-turns.test.d.ts.map +1 -0
- package/dist/__tests__/broker-step-active-turns.test.js +428 -0
- package/dist/__tests__/broker-step-active-turns.test.js.map +1 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts +13 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts.map +1 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.js +429 -0
- package/dist/__tests__/broker-step-turn-chain-phase2.test.js.map +1 -0
- package/dist/__tests__/config.test.js +33 -37
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/e2e-broker-step-suspend.test.d.ts +18 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.js +313 -0
- package/dist/__tests__/e2e-broker-step-suspend.test.js.map +1 -0
- package/dist/__tests__/e2e-broker-step.test.d.ts +13 -0
- package/dist/__tests__/e2e-broker-step.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-broker-step.test.js +278 -0
- package/dist/__tests__/e2e-broker-step.test.js.map +1 -0
- package/dist/__tests__/e2e-mock-agent.test.js +1 -1
- package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts +28 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js +322 -0
- package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js.map +1 -0
- package/dist/__tests__/log-tag-validity.test.d.ts +2 -0
- package/dist/__tests__/log-tag-validity.test.d.ts.map +1 -0
- package/dist/__tests__/log-tag-validity.test.js +110 -0
- package/dist/__tests__/log-tag-validity.test.js.map +1 -0
- package/dist/__tests__/setup-agent-discovery.test.js +35 -23
- package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
- package/dist/__tests__/setup-no-llm.test.js +5 -2
- package/dist/__tests__/setup-no-llm.test.js.map +1 -1
- package/dist/__tests__/step-ask.test.js +9 -6
- package/dist/__tests__/step-ask.test.js.map +1 -1
- package/dist/__tests__/step-show-json.test.js +5 -5
- package/dist/__tests__/step-show-json.test.js.map +1 -1
- package/dist/__tests__/step-show-text.test.d.ts +2 -0
- package/dist/__tests__/step-show-text.test.d.ts.map +1 -0
- package/dist/__tests__/step-show-text.test.js +192 -0
- package/dist/__tests__/step-show-text.test.js.map +1 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.d.ts +21 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.js +356 -0
- package/dist/__tests__/step-turns-cli-subprocess.test.js.map +1 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.d.ts +21 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.js +476 -0
- package/dist/__tests__/step-turns-panorama-phase3.test.js.map +1 -0
- package/dist/__tests__/step-turns.test.d.ts +24 -0
- package/dist/__tests__/step-turns.test.d.ts.map +1 -0
- package/dist/__tests__/step-turns.test.js +646 -0
- package/dist/__tests__/step-turns.test.js.map +1 -0
- package/dist/__tests__/store-turn-chain.test.d.ts +2 -0
- package/dist/__tests__/store-turn-chain.test.d.ts.map +1 -0
- package/dist/__tests__/store-turn-chain.test.js +341 -0
- package/dist/__tests__/store-turn-chain.test.js.map +1 -0
- package/dist/__tests__/thread-agent-failure-suspended.test.js +3 -3
- package/dist/__tests__/thread-agent-failure-suspended.test.js.map +1 -1
- package/dist/__tests__/thread-list-limit-offset.test.d.ts +24 -0
- package/dist/__tests__/thread-list-limit-offset.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-limit-offset.test.js +254 -0
- package/dist/__tests__/thread-list-limit-offset.test.js.map +1 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js +7 -2
- package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -1
- package/dist/__tests__/thread-poke.test.js +6 -6
- package/dist/__tests__/thread-poke.test.js.map +1 -1
- package/dist/__tests__/thread-resume.test.js +2 -2
- package/dist/__tests__/thread-resume.test.js.map +1 -1
- package/dist/__tests__/thread-suspend-step.test.js +1 -1
- package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
- package/dist/__tests__/thread.test.js +28 -14
- package/dist/__tests__/thread.test.js.map +1 -1
- package/dist/cli.js +910 -344
- package/dist/cli.js.map +1 -1
- package/dist/commands/broker-step.d.ts +117 -0
- package/dist/commands/broker-step.d.ts.map +1 -0
- package/dist/commands/broker-step.js +654 -0
- package/dist/commands/broker-step.js.map +1 -0
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +2 -23
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/prompt.d.ts.map +1 -1
- package/dist/commands/prompt.js +43 -51
- package/dist/commands/prompt.js.map +1 -1
- package/dist/commands/setup.d.ts +6 -4
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +24 -27
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/step.d.ts +54 -6
- package/dist/commands/step.d.ts.map +1 -1
- package/dist/commands/step.js +484 -134
- package/dist/commands/step.js.map +1 -1
- package/dist/commands/thread.d.ts +4 -0
- package/dist/commands/thread.d.ts.map +1 -1
- package/dist/commands/thread.js +77 -151
- package/dist/commands/thread.js.map +1 -1
- package/dist/output-mappers.d.ts +8 -0
- package/dist/output-mappers.d.ts.map +1 -1
- package/dist/output-mappers.js +72 -18
- package/dist/output-mappers.js.map +1 -1
- package/dist/schemas.d.ts +3 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +17 -3
- package/dist/schemas.js.map +1 -1
- package/dist/store.d.ts +147 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +254 -1
- package/dist/store.js.map +1 -1
- package/dist/text-renderers.d.ts.map +1 -1
- package/dist/text-renderers.js +27 -2
- package/dist/text-renderers.js.map +1 -1
- package/package.json +7 -5
- package/src/__tests__/agent-resolution-llm-free.test.ts +14 -2
- package/src/__tests__/broker-prompt.test.ts +142 -0
- package/src/__tests__/broker-step-active-turns.test.ts +509 -0
- package/src/__tests__/broker-step-turn-chain-phase2.test.ts +525 -0
- package/src/__tests__/config.test.ts +35 -39
- package/src/__tests__/e2e-broker-step-suspend.test.ts +351 -0
- package/src/__tests__/e2e-broker-step.test.ts +320 -0
- package/src/__tests__/e2e-mock-agent.test.ts +1 -1
- package/src/__tests__/e2e-thread-resume-timeout-suspend.test.ts +360 -0
- package/src/__tests__/log-tag-validity.test.ts +124 -0
- package/src/__tests__/setup-agent-discovery.test.ts +35 -23
- package/src/__tests__/setup-no-llm.test.ts +5 -2
- package/src/__tests__/step-ask.test.ts +9 -6
- package/src/__tests__/step-show-json.test.ts +5 -5
- package/src/__tests__/step-show-text.test.ts +236 -0
- package/src/__tests__/step-turns-cli-subprocess.test.ts +411 -0
- package/src/__tests__/step-turns-panorama-phase3.test.ts +579 -0
- package/src/__tests__/step-turns.test.ts +734 -0
- package/src/__tests__/store-turn-chain.test.ts +386 -0
- package/src/__tests__/thread-agent-failure-suspended.test.ts +3 -3
- package/src/__tests__/thread-list-limit-offset.test.ts +305 -0
- package/src/__tests__/thread-list-template-ms-date.test.ts +7 -2
- package/src/__tests__/thread-poke.test.ts +6 -6
- package/src/__tests__/thread-resume.test.ts +2 -2
- package/src/__tests__/thread-suspend-step.test.ts +1 -1
- package/src/__tests__/thread.test.ts +29 -15
- package/src/cli.ts +1056 -483
- package/src/commands/broker-step.ts +913 -0
- package/src/commands/config.ts +2 -24
- package/src/commands/prompt.ts +43 -51
- package/src/commands/setup.ts +25 -29
- package/src/commands/step.ts +645 -176
- package/src/commands/thread.ts +87 -192
- package/src/output-mappers.ts +99 -21
- package/src/schemas.ts +32 -2
- package/src/store.ts +297 -2
- package/src/text-renderers.ts +35 -2
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts +0 -2
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts.map +0 -1
- package/dist/__tests__/adapter-json-roundtrip.test.js +0 -160
- package/dist/__tests__/adapter-json-roundtrip.test.js.map +0 -1
- package/dist/__tests__/spawn-agent-json.test.d.ts +0 -2
- package/dist/__tests__/spawn-agent-json.test.d.ts.map +0 -1
- package/dist/__tests__/spawn-agent-json.test.js +0 -79
- package/dist/__tests__/spawn-agent-json.test.js.map +0 -1
- package/src/__tests__/adapter-json-roundtrip.test.ts +0 -193
- package/src/__tests__/spawn-agent-json.test.ts +0 -100
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env -S node --disable-warning=ExperimentalWarning
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { createCLI } from "@ocas/cli-kit";
|
|
6
|
+
import { z } from "zod";
|
|
3
7
|
import { cmdConfigGet, cmdConfigList, cmdConfigSet } from "./commands/config.js";
|
|
4
8
|
import { cmdLogClean, cmdLogList, cmdLogShow } from "./commands/log.js";
|
|
5
9
|
import { cmdPromptAdapterDeveloping, cmdPromptBootstrap, cmdPromptList, cmdPromptUsage, cmdPromptWorkflowAuthoring, } from "./commands/prompt.js";
|
|
6
10
|
import { cmdSetup, cmdSetupInteractive } from "./commands/setup.js";
|
|
7
|
-
import { cmdStepAsk, cmdStepFork, cmdStepList, cmdStepRead, cmdStepShow } from "./commands/step.js";
|
|
11
|
+
import { cmdStepAsk, cmdStepFork, cmdStepList, cmdStepRead, cmdStepShow, cmdStepTurns, } from "./commands/step.js";
|
|
8
12
|
import { cmdThreadCancel, cmdThreadExec, cmdThreadJoin, cmdThreadList, cmdThreadPoke, cmdThreadRead, cmdThreadResume, cmdThreadShow, cmdThreadStart, cmdThreadStop, THREAD_READ_DEFAULT_QUOTA, } from "./commands/thread.js";
|
|
9
13
|
import { parseTimeInput } from "./commands/thread-time-parser.js";
|
|
10
14
|
import { cmdWorkflowAdd, cmdWorkflowList, cmdWorkflowShow, cmdWorkflowValidate, } from "./commands/workflow.js";
|
|
11
15
|
import { formatOutput, isOutputFormat, SUPPORTED_FORMATS, writeEnvelope, } from "./format.js";
|
|
12
16
|
import { toStepDetailPayload, toStepListPayload, toThreadExecPayload, toThreadListPayload, toThreadStartPayload, toThreadStatusPayload, toValidateResultPayload, toWorkflowAddPayload, toWorkflowDetailPayload, toWorkflowListPayload, } from "./output-mappers.js";
|
|
13
17
|
import { createUwfStore, resolveStorageRoot } from "./store.js";
|
|
18
|
+
// --- Package version (readFileSync replaces dynamic import) ---
|
|
19
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
21
|
+
const VERSION = pkg.version;
|
|
22
|
+
// --- Module-level state (cli-kit v0.2.1 workaround: no global --format) ---
|
|
23
|
+
// Parsed from argv early, before cli-kit sees it.
|
|
24
|
+
let formatOverride = null;
|
|
25
|
+
// Parsed from argv early — cli-kit rejects values starting with `-`.
|
|
26
|
+
let countOverride = null;
|
|
14
27
|
function getFormat() {
|
|
15
|
-
const raw =
|
|
28
|
+
const raw = formatOverride ?? "text";
|
|
16
29
|
if (!isOutputFormat(raw)) {
|
|
17
30
|
process.stderr.write(`Invalid --format: ${raw}. Must be one of: ${SUPPORTED_FORMATS.join(", ")}\n`);
|
|
18
31
|
process.exit(1);
|
|
@@ -34,121 +47,18 @@ async function writeOutput(payload, schemaName, storageRoot) {
|
|
|
34
47
|
* (the default) it renders via the per-command registry when available
|
|
35
48
|
* and falls back to JSON.
|
|
36
49
|
*/
|
|
37
|
-
function writeRawOutput(data, commandPath) {
|
|
50
|
+
function writeRawOutput(data, commandPath = null) {
|
|
38
51
|
const fmt = getFormat();
|
|
39
|
-
process.stdout.write(`${formatOutput(data, fmt, commandPath)}\n`);
|
|
52
|
+
process.stdout.write(`${formatOutput(data, fmt, commandPath ?? undefined)}\n`);
|
|
40
53
|
}
|
|
41
54
|
function runAction(action) {
|
|
42
|
-
action().catch((e) => {
|
|
55
|
+
return action().catch((e) => {
|
|
43
56
|
const message = e instanceof Error ? e.message : String(e);
|
|
44
57
|
process.stderr.write(`${message}\n`);
|
|
45
58
|
process.exit(1);
|
|
46
59
|
});
|
|
47
60
|
}
|
|
48
|
-
|
|
49
|
-
// eslint-disable-next-line -- dynamic import for version
|
|
50
|
-
const pkg = await import("../package.json", { with: { type: "json" } });
|
|
51
|
-
program
|
|
52
|
-
.name("uwf")
|
|
53
|
-
.description("Stateless workflow CLI\n\n" +
|
|
54
|
-
"Four-layer architecture:\n" +
|
|
55
|
-
" workflow → thread → step → turn")
|
|
56
|
-
.version(pkg.default.version, "-V, --version");
|
|
57
|
-
program.option("--format <fmt>", "Output format: text (default), json, yaml, raw-json, raw-yaml", "text");
|
|
58
|
-
const workflow = program
|
|
59
|
-
.command("workflow")
|
|
60
|
-
.description("Workflow definitions (layer 1: templates)");
|
|
61
|
-
workflow
|
|
62
|
-
.command("add")
|
|
63
|
-
.description("Register a workflow from YAML")
|
|
64
|
-
.argument("<file>", "Workflow YAML file")
|
|
65
|
-
.action((file) => {
|
|
66
|
-
const storageRoot = resolveStorageRoot();
|
|
67
|
-
runAction(async () => {
|
|
68
|
-
const result = await cmdWorkflowAdd(storageRoot, file);
|
|
69
|
-
await writeOutput(toWorkflowAddPayload(result), "workflow-add", storageRoot);
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
workflow
|
|
73
|
-
.command("validate")
|
|
74
|
-
.description("Validate a workflow YAML without registering it (CI-friendly)")
|
|
75
|
-
.argument("<file>", "Workflow YAML file")
|
|
76
|
-
.action((file) => {
|
|
77
|
-
const storageRoot = resolveStorageRoot();
|
|
78
|
-
runAction(async () => {
|
|
79
|
-
const errors = await cmdWorkflowValidate(file);
|
|
80
|
-
await writeOutput(toValidateResultPayload(errors), "validate-result", storageRoot);
|
|
81
|
-
if (errors.length > 0) {
|
|
82
|
-
process.exit(1);
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
workflow
|
|
87
|
-
.command("show")
|
|
88
|
-
.description("Show a workflow by name or CAS hash")
|
|
89
|
-
.argument("<id>", "Workflow name or hash")
|
|
90
|
-
.action((id) => {
|
|
91
|
-
const storageRoot = resolveStorageRoot();
|
|
92
|
-
runAction(async () => {
|
|
93
|
-
const result = await cmdWorkflowShow(storageRoot, id, process.cwd());
|
|
94
|
-
await writeOutput(toWorkflowDetailPayload(result), "workflow-detail", storageRoot);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
workflow
|
|
98
|
-
.command("list")
|
|
99
|
-
.description("List registered workflows")
|
|
100
|
-
.action(() => {
|
|
101
|
-
const storageRoot = resolveStorageRoot();
|
|
102
|
-
runAction(async () => {
|
|
103
|
-
const result = await cmdWorkflowList(storageRoot, process.cwd());
|
|
104
|
-
await writeOutput(toWorkflowListPayload(result), "workflow-list", storageRoot);
|
|
105
|
-
});
|
|
106
|
-
});
|
|
107
|
-
const thread = program.command("thread").description("Thread execution (layer 2: instances)");
|
|
108
|
-
thread
|
|
109
|
-
.command("start")
|
|
110
|
-
.description("Create a thread without executing")
|
|
111
|
-
.argument("<workflow>", "Workflow name or hash")
|
|
112
|
-
.requiredOption("-p, --prompt <text>", "User prompt")
|
|
113
|
-
.option("--cwd <path>", "Working directory for thread execution (default: process.cwd())")
|
|
114
|
-
.action((workflow, opts) => {
|
|
115
|
-
const storageRoot = resolveStorageRoot();
|
|
116
|
-
runAction(async () => {
|
|
117
|
-
const result = await cmdThreadStart(storageRoot, workflow, opts.prompt, process.cwd(), opts.cwd ?? process.cwd());
|
|
118
|
-
await writeOutput(toThreadStartPayload(result), "thread-start", storageRoot);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
121
|
-
thread
|
|
122
|
-
.command("exec")
|
|
123
|
-
.description("Execute one or more steps")
|
|
124
|
-
.argument("<thread-id>", "Thread ULID")
|
|
125
|
-
.option("--agent <cmd>", "Override agent command")
|
|
126
|
-
.option("-c, --count <number>", "Number of steps to run (default: 1)")
|
|
127
|
-
.option("--background", "Run in background and return immediately")
|
|
128
|
-
.option("--_background-worker", "Internal flag for background worker process", false)
|
|
129
|
-
.action((threadId, opts) => {
|
|
130
|
-
const storageRoot = resolveStorageRoot();
|
|
131
|
-
runAction(async () => {
|
|
132
|
-
const agentOverride = opts.agent ?? null;
|
|
133
|
-
const count = opts.count !== undefined ? Number(opts.count) : 1;
|
|
134
|
-
const background = opts.background ?? false;
|
|
135
|
-
const backgroundWorker = opts._backgroundWorker ?? false;
|
|
136
|
-
const results = await cmdThreadExec(storageRoot, threadId, agentOverride, count, background, backgroundWorker);
|
|
137
|
-
await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
thread
|
|
141
|
-
.command("show")
|
|
142
|
-
.description("Show thread head pointer")
|
|
143
|
-
.argument("<thread-id>", "Thread ULID")
|
|
144
|
-
.action((threadId) => {
|
|
145
|
-
const storageRoot = resolveStorageRoot();
|
|
146
|
-
runAction(async () => {
|
|
147
|
-
const result = await cmdThreadShow(storageRoot, threadId);
|
|
148
|
-
await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
// Helper functions for thread list command parsing
|
|
61
|
+
// --- Helper functions for thread list / step turns parsing (unchanged) ---
|
|
152
62
|
function parseStatusFilter(status) {
|
|
153
63
|
if (status === undefined)
|
|
154
64
|
return null;
|
|
@@ -203,87 +113,755 @@ function parsePaginationOptions(skip, take) {
|
|
|
203
113
|
}
|
|
204
114
|
return { skip: skipVal, take: takeVal };
|
|
205
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Parse a `step turns` `--limit`/`--offset` value into a non-negative integer, or
|
|
118
|
+
* `null` when the flag is absent (the OCAS `ListOptions` "no limit" / offset-0
|
|
119
|
+
* convention). `--limit 0` is a legal value (renders no turns); negative or
|
|
120
|
+
* non-numeric values are a CLI usage error (exit non-zero). The `flag` label is
|
|
121
|
+
* used verbatim in the error message.
|
|
122
|
+
*/
|
|
123
|
+
function parseTurnsPageOption(flag, value) {
|
|
124
|
+
if (value === undefined) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
const trimmed = value.trim();
|
|
128
|
+
if (!/^\d+$/.test(trimmed)) {
|
|
129
|
+
process.stderr.write(`${flag} must be a non-negative integer\n`);
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
|
132
|
+
return Number.parseInt(trimmed, 10);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Resolve `thread list` pagination from both the canonical repo-wide
|
|
136
|
+
* `ListOptions` vocabulary (`--limit`/`--offset`, as used by `step turns`) and
|
|
137
|
+
* the backward-compatible legacy aliases (`--skip`/`--take`). The canonical
|
|
138
|
+
* flags map onto the existing `cmdThreadList` parameters: `--limit` → `take`
|
|
139
|
+
* (max items), `--offset` → `skip` (items skipped from the front of the
|
|
140
|
+
* newest-first list). When both a canonical flag and its legacy alias are
|
|
141
|
+
* supplied, the canonical flag wins and the alias is the fallback.
|
|
142
|
+
* `--limit`/`--offset` are validated via `parseTurnsPageOption` (same
|
|
143
|
+
* non-negative-integer rule and flag-named error as `step turns`); `--limit 0`
|
|
144
|
+
* is legal and yields no items (the `ListOptions` "no limit" convention treats
|
|
145
|
+
* an absent flag, not 0, as "all items").
|
|
146
|
+
*/
|
|
147
|
+
function resolveThreadListPagination(flags) {
|
|
148
|
+
const legacy = parsePaginationOptions(flags.skip, flags.take);
|
|
149
|
+
const limit = parseTurnsPageOption("--limit", flags.limit);
|
|
150
|
+
const offset = parseTurnsPageOption("--offset", flags.offset);
|
|
151
|
+
return {
|
|
152
|
+
skip: offset ?? legacy.skip,
|
|
153
|
+
take: limit ?? legacy.take,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
// --- Positional arg helper (cli-kit workaround: custom missing-arg message) ---
|
|
157
|
+
// cli-kit emits "Missing positional arguments" as NDJSON; tests expect a
|
|
158
|
+
// plain "missing required argument" message on stderr. We don't declare
|
|
159
|
+
// .arg() on commands and read positionals from the _positionals field that
|
|
160
|
+
// cli-kit injects into the flags object.
|
|
161
|
+
function getPositionals(flags) {
|
|
162
|
+
const p = flags._positionals;
|
|
163
|
+
return Array.isArray(p) ? p : [];
|
|
164
|
+
}
|
|
165
|
+
function requirePositional(flags, index, name) {
|
|
166
|
+
const positionals = getPositionals(flags);
|
|
167
|
+
const value = positionals[index];
|
|
168
|
+
if (value === undefined) {
|
|
169
|
+
process.stderr.write(`Error: missing required argument: ${name}\n`);
|
|
170
|
+
process.exit(1);
|
|
171
|
+
}
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
// --- Help text (cli-kit v0.2.1 workaround: no per-command --help) ---
|
|
175
|
+
const TOP_LEVEL_HELP = `Usage: uwf <command> [options]
|
|
176
|
+
|
|
177
|
+
Stateless workflow CLI
|
|
178
|
+
|
|
179
|
+
Four-layer architecture:
|
|
180
|
+
workflow → thread → step → turn
|
|
181
|
+
|
|
182
|
+
Commands:
|
|
183
|
+
workflow Workflow definitions (layer 1: templates)
|
|
184
|
+
thread Thread execution (layer 2: instances)
|
|
185
|
+
step Step results (layer 3: single cycle)
|
|
186
|
+
prompt Built-in prompt references for agents
|
|
187
|
+
setup Configure the default agent
|
|
188
|
+
log Process-level debug logs
|
|
189
|
+
config Configuration management
|
|
190
|
+
|
|
191
|
+
Standard flags:
|
|
192
|
+
--format <fmt> Output format: text (default), json, yaml, raw-json, raw-yaml
|
|
193
|
+
-V, --version Show version
|
|
194
|
+
-h, --help Show this help
|
|
195
|
+
`;
|
|
196
|
+
const PROMPT_HELP = `Usage: uwf prompt <command>
|
|
197
|
+
|
|
198
|
+
Built-in prompt references for agents
|
|
199
|
+
|
|
200
|
+
Commands:
|
|
201
|
+
usage Print the usage reference (CLI guide + typical workflows)
|
|
202
|
+
bootstrap Print setup instructions for installing uwf skills
|
|
203
|
+
workflow-authoring Print the workflow authoring reference (YAML design guide)
|
|
204
|
+
adapter-developing Print the adapter developing reference (building agent adapters)
|
|
205
|
+
list List all available prompt names
|
|
206
|
+
`;
|
|
207
|
+
const WORKFLOW_HELP = `Usage: uwf workflow <command>
|
|
208
|
+
|
|
209
|
+
Workflow definitions (layer 1: templates)
|
|
210
|
+
|
|
211
|
+
Commands:
|
|
212
|
+
add Register a workflow from YAML
|
|
213
|
+
validate Validate a workflow YAML without registering it (CI-friendly)
|
|
214
|
+
show Show a workflow by name or CAS hash
|
|
215
|
+
list List registered workflows
|
|
216
|
+
`;
|
|
217
|
+
const WORKFLOW_ADD_HELP = `Usage: uwf workflow add <file>
|
|
218
|
+
|
|
219
|
+
Register a workflow from YAML
|
|
220
|
+
|
|
221
|
+
Arguments:
|
|
222
|
+
file Workflow YAML file
|
|
223
|
+
`;
|
|
224
|
+
const WORKFLOW_VALIDATE_HELP = `Usage: uwf workflow validate <file>
|
|
225
|
+
|
|
226
|
+
Validate a workflow YAML without registering it (CI-friendly)
|
|
227
|
+
|
|
228
|
+
Arguments:
|
|
229
|
+
file Workflow YAML file
|
|
230
|
+
`;
|
|
231
|
+
const WORKFLOW_SHOW_HELP = `Usage: uwf workflow show <id>
|
|
232
|
+
|
|
233
|
+
Show a workflow by name or CAS hash
|
|
234
|
+
|
|
235
|
+
Arguments:
|
|
236
|
+
id Workflow name or hash
|
|
237
|
+
`;
|
|
238
|
+
const WORKFLOW_LIST_HELP = `Usage: uwf workflow list
|
|
239
|
+
|
|
240
|
+
List registered workflows
|
|
241
|
+
`;
|
|
242
|
+
const THREAD_HELP = `Usage: uwf thread <command>
|
|
243
|
+
|
|
244
|
+
Thread execution (layer 2: instances)
|
|
245
|
+
|
|
246
|
+
Commands:
|
|
247
|
+
start Create a thread without executing
|
|
248
|
+
exec Execute one or more steps
|
|
249
|
+
show Show thread head pointer
|
|
250
|
+
list List threads (defaults to active: idle + running + corrupt)
|
|
251
|
+
resume Resume a suspended thread and re-run the suspended role
|
|
252
|
+
poke Re-run the head step's agent with a supplementary prompt
|
|
253
|
+
stop Stop background execution of a thread (keep thread active)
|
|
254
|
+
cancel Cancel a thread (stop execution and move to history)
|
|
255
|
+
join Block until a running thread finishes, then return the final result
|
|
256
|
+
read Read thread context as human-readable markdown
|
|
257
|
+
`;
|
|
258
|
+
const THREAD_START_HELP = `Usage: uwf thread start <workflow> [options]
|
|
259
|
+
|
|
260
|
+
Create a thread without executing
|
|
261
|
+
|
|
262
|
+
Arguments:
|
|
263
|
+
workflow Workflow name or hash
|
|
264
|
+
|
|
265
|
+
Options:
|
|
266
|
+
-p, --prompt <text> User prompt (required)
|
|
267
|
+
--cwd <path> Working directory for thread execution (default: process.cwd())
|
|
268
|
+
`;
|
|
269
|
+
const THREAD_EXEC_HELP = `Usage: uwf thread exec <thread-id> [options]
|
|
270
|
+
|
|
271
|
+
Execute one or more steps
|
|
272
|
+
|
|
273
|
+
Arguments:
|
|
274
|
+
thread-id Thread ULID
|
|
275
|
+
|
|
276
|
+
Options:
|
|
277
|
+
--agent <cmd> Override agent command
|
|
278
|
+
-c, --count <number> Number of steps to run (default: 1)
|
|
279
|
+
--background Run in background and return immediately
|
|
280
|
+
`;
|
|
281
|
+
const THREAD_SHOW_HELP = `Usage: uwf thread show <thread-id>
|
|
282
|
+
|
|
283
|
+
Show thread head pointer
|
|
284
|
+
|
|
285
|
+
Arguments:
|
|
286
|
+
thread-id Thread ULID
|
|
287
|
+
`;
|
|
288
|
+
const THREAD_LIST_HELP = `Usage: uwf thread list [options]
|
|
289
|
+
|
|
290
|
+
List threads (defaults to active: idle + running + corrupt)
|
|
291
|
+
|
|
292
|
+
Options:
|
|
293
|
+
--status <status> Filter by status: idle, running, end, cancelled, active, or comma-separated
|
|
294
|
+
--all Show all threads regardless of status
|
|
295
|
+
--after <date> Filter threads created after this date
|
|
296
|
+
--before <date> Filter threads created before this date
|
|
297
|
+
--limit <n> Return at most n threads (newest first)
|
|
298
|
+
--offset <m> Skip the first m threads (newest first)
|
|
299
|
+
--take <n> Alias for --limit
|
|
300
|
+
--skip <n> Alias for --offset
|
|
301
|
+
`;
|
|
302
|
+
const THREAD_RESUME_HELP = `Usage: uwf thread resume <thread-id> [options]
|
|
303
|
+
|
|
304
|
+
Resume a suspended thread and re-run the suspended role
|
|
305
|
+
|
|
306
|
+
Arguments:
|
|
307
|
+
thread-id Thread ULID
|
|
308
|
+
|
|
309
|
+
Options:
|
|
310
|
+
-p, --prompt <text> Supplementary info to append to the resume prompt
|
|
311
|
+
--agent <cmd> Override agent command
|
|
312
|
+
`;
|
|
313
|
+
const THREAD_POKE_HELP = `Usage: uwf thread poke <thread-id> [options]
|
|
314
|
+
|
|
315
|
+
Re-run the head step's agent with a supplementary prompt (replaces head step)
|
|
316
|
+
|
|
317
|
+
Arguments:
|
|
318
|
+
thread-id Thread ULID
|
|
319
|
+
|
|
320
|
+
Options:
|
|
321
|
+
-p, --prompt <text> Supplementary prompt for the agent (required)
|
|
322
|
+
--agent <cmd> Override agent command (defaults to head step's agent)
|
|
323
|
+
`;
|
|
324
|
+
const THREAD_STOP_HELP = `Usage: uwf thread stop <thread-id>
|
|
325
|
+
|
|
326
|
+
Stop background execution of a thread (keep thread active)
|
|
327
|
+
|
|
328
|
+
Arguments:
|
|
329
|
+
thread-id Thread ULID
|
|
330
|
+
`;
|
|
331
|
+
const THREAD_CANCEL_HELP = `Usage: uwf thread cancel <thread-id>
|
|
332
|
+
|
|
333
|
+
Cancel a thread (stop execution and move to history)
|
|
334
|
+
|
|
335
|
+
Arguments:
|
|
336
|
+
thread-id Thread ULID
|
|
337
|
+
`;
|
|
338
|
+
const THREAD_JOIN_HELP = `Usage: uwf thread join <thread-id> [options]
|
|
339
|
+
|
|
340
|
+
Block until a running thread finishes, then return the final result
|
|
341
|
+
|
|
342
|
+
Arguments:
|
|
343
|
+
thread-id Thread ULID
|
|
344
|
+
|
|
345
|
+
Options:
|
|
346
|
+
--timeout <seconds> Max seconds to wait before giving up
|
|
347
|
+
`;
|
|
348
|
+
const THREAD_READ_HELP = `Usage: uwf thread read <thread-id> [options]
|
|
349
|
+
|
|
350
|
+
Read thread context as human-readable markdown
|
|
351
|
+
|
|
352
|
+
Arguments:
|
|
353
|
+
thread-id Thread ULID
|
|
354
|
+
|
|
355
|
+
Options:
|
|
356
|
+
--quota <chars> Max output characters
|
|
357
|
+
--before <step-hash> Load steps before this hash (exclusive)
|
|
358
|
+
--start Include start step in output
|
|
359
|
+
`;
|
|
360
|
+
const STEP_HELP = `Usage: uwf step <command>
|
|
361
|
+
|
|
362
|
+
Step results (layer 3: single cycle)
|
|
363
|
+
|
|
364
|
+
Commands:
|
|
365
|
+
list List all steps in a thread
|
|
366
|
+
show Show details of a specific step
|
|
367
|
+
ask Ask a follow-up question to a historical step's agent
|
|
368
|
+
read Read a step's turns as human-readable markdown
|
|
369
|
+
turns Show all turns across a thread's steps
|
|
370
|
+
fork Fork a thread from a specific step
|
|
371
|
+
`;
|
|
372
|
+
const STEP_LIST_HELP = `Usage: uwf step list <thread-id>
|
|
373
|
+
|
|
374
|
+
List all steps in a thread
|
|
375
|
+
|
|
376
|
+
Arguments:
|
|
377
|
+
thread-id Thread ULID
|
|
378
|
+
`;
|
|
379
|
+
const STEP_SHOW_HELP = `Usage: uwf step show <step-hash>
|
|
380
|
+
|
|
381
|
+
Show details of a specific step
|
|
382
|
+
|
|
383
|
+
Arguments:
|
|
384
|
+
step-hash CAS hash of the StepNode
|
|
385
|
+
`;
|
|
386
|
+
const STEP_ASK_HELP = `Usage: uwf step ask <step-hash> [options]
|
|
387
|
+
|
|
388
|
+
Ask a follow-up question to a historical step's agent (read-only; no thread mutation)
|
|
389
|
+
|
|
390
|
+
Arguments:
|
|
391
|
+
step-hash CAS hash of the StepNode to query
|
|
392
|
+
|
|
393
|
+
Options:
|
|
394
|
+
-p, --prompt <text> Question to ask the step's agent (required)
|
|
395
|
+
--agent <cmd> Override agent command
|
|
396
|
+
--no-fork Skip session-fork; spawn fresh ask session
|
|
397
|
+
`;
|
|
398
|
+
const STEP_READ_HELP = `Usage: uwf step read <step-hash> [options]
|
|
399
|
+
|
|
400
|
+
Read a step's turns as human-readable markdown
|
|
401
|
+
|
|
402
|
+
Arguments:
|
|
403
|
+
step-hash CAS hash of the StepNode
|
|
404
|
+
|
|
405
|
+
Options:
|
|
406
|
+
--quota <chars> Max output characters (default: 4000)
|
|
407
|
+
--prompt Show the assembled prompt sent to the agent
|
|
408
|
+
`;
|
|
409
|
+
const STEP_TURNS_HELP = `Usage: uwf step turns <thread-id> [options]
|
|
410
|
+
|
|
411
|
+
Show all turns across a thread's steps (the whole-chain panorama)
|
|
412
|
+
|
|
413
|
+
Arguments:
|
|
414
|
+
thread-id Thread ULID
|
|
415
|
+
|
|
416
|
+
Options:
|
|
417
|
+
--role <role> Filter to one role's steps across the whole chain
|
|
418
|
+
--live Follow the in-flight step's turns
|
|
419
|
+
--limit <n> Max turns to show from the flattened cross-step sequence
|
|
420
|
+
--offset <n> Skip the first N turns of the flattened cross-step sequence
|
|
421
|
+
`;
|
|
422
|
+
const STEP_FORK_HELP = `Usage: uwf step fork <step-hash>
|
|
423
|
+
|
|
424
|
+
Fork a thread from a specific step
|
|
425
|
+
|
|
426
|
+
Arguments:
|
|
427
|
+
step-hash CAS hash of the StartNode or StepNode to fork from
|
|
428
|
+
`;
|
|
429
|
+
const SETUP_HELP = `Usage: uwf setup [options]
|
|
430
|
+
|
|
431
|
+
Configure the default agent. Run without --agent for interactive wizard.
|
|
432
|
+
|
|
433
|
+
Options:
|
|
434
|
+
--agent <name> Default agent adapter (e.g. builtin, or a Sumeru gateway alias)
|
|
435
|
+
`;
|
|
436
|
+
const LOG_HELP = `Usage: uwf log <command>
|
|
437
|
+
|
|
438
|
+
Process-level debug logs
|
|
439
|
+
|
|
440
|
+
Commands:
|
|
441
|
+
list List log files with sizes
|
|
442
|
+
show Show and filter log entries
|
|
443
|
+
clean Delete log files older than given date
|
|
444
|
+
`;
|
|
445
|
+
const LOG_LIST_HELP = `Usage: uwf log list
|
|
446
|
+
|
|
447
|
+
List log files with sizes
|
|
448
|
+
`;
|
|
449
|
+
const LOG_SHOW_HELP = `Usage: uwf log show [options]
|
|
450
|
+
|
|
451
|
+
Show and filter log entries
|
|
452
|
+
|
|
453
|
+
Options:
|
|
454
|
+
--thread <thread-id> Filter by thread ID
|
|
455
|
+
--process <pid> Filter by process ID
|
|
456
|
+
--date <date> Filter by date (YYYY-MM-DD)
|
|
457
|
+
`;
|
|
458
|
+
const LOG_CLEAN_HELP = `Usage: uwf log clean --before <date>
|
|
459
|
+
|
|
460
|
+
Delete log files older than given date
|
|
461
|
+
|
|
462
|
+
Options:
|
|
463
|
+
--before <date> Delete files before this date (YYYY-MM-DD) (required)
|
|
464
|
+
`;
|
|
465
|
+
const CONFIG_HELP = `Usage: uwf config <command>
|
|
466
|
+
|
|
467
|
+
Configuration management
|
|
468
|
+
|
|
469
|
+
Commands:
|
|
470
|
+
list Display all configuration values (masks API keys)
|
|
471
|
+
get Get a specific configuration value
|
|
472
|
+
set Set a specific configuration value
|
|
473
|
+
`;
|
|
474
|
+
const CONFIG_LIST_HELP = `Usage: uwf config list
|
|
475
|
+
|
|
476
|
+
Display all configuration values (masks API keys)
|
|
477
|
+
`;
|
|
478
|
+
const CONFIG_GET_HELP = `Usage: uwf config get <key>
|
|
479
|
+
|
|
480
|
+
Get a specific configuration value
|
|
481
|
+
|
|
482
|
+
Arguments:
|
|
483
|
+
key Dot-notation path to config value
|
|
484
|
+
`;
|
|
485
|
+
const CONFIG_SET_HELP = `Usage: uwf config set <key> <value>
|
|
486
|
+
|
|
487
|
+
Set a specific configuration value
|
|
488
|
+
|
|
489
|
+
Arguments:
|
|
490
|
+
key Dot-notation path to config value
|
|
491
|
+
value New value (use JSON array for 'args' key)
|
|
492
|
+
`;
|
|
493
|
+
const HELP_MAP = {
|
|
494
|
+
"": TOP_LEVEL_HELP,
|
|
495
|
+
prompt: PROMPT_HELP,
|
|
496
|
+
workflow: WORKFLOW_HELP,
|
|
497
|
+
"workflow add": WORKFLOW_ADD_HELP,
|
|
498
|
+
"workflow validate": WORKFLOW_VALIDATE_HELP,
|
|
499
|
+
"workflow show": WORKFLOW_SHOW_HELP,
|
|
500
|
+
"workflow list": WORKFLOW_LIST_HELP,
|
|
501
|
+
thread: THREAD_HELP,
|
|
502
|
+
"thread start": THREAD_START_HELP,
|
|
503
|
+
"thread exec": THREAD_EXEC_HELP,
|
|
504
|
+
"thread show": THREAD_SHOW_HELP,
|
|
505
|
+
"thread list": THREAD_LIST_HELP,
|
|
506
|
+
"thread resume": THREAD_RESUME_HELP,
|
|
507
|
+
"thread poke": THREAD_POKE_HELP,
|
|
508
|
+
"thread stop": THREAD_STOP_HELP,
|
|
509
|
+
"thread cancel": THREAD_CANCEL_HELP,
|
|
510
|
+
"thread join": THREAD_JOIN_HELP,
|
|
511
|
+
"thread read": THREAD_READ_HELP,
|
|
512
|
+
step: STEP_HELP,
|
|
513
|
+
"step list": STEP_LIST_HELP,
|
|
514
|
+
"step show": STEP_SHOW_HELP,
|
|
515
|
+
"step ask": STEP_ASK_HELP,
|
|
516
|
+
"step read": STEP_READ_HELP,
|
|
517
|
+
"step turns": STEP_TURNS_HELP,
|
|
518
|
+
"step fork": STEP_FORK_HELP,
|
|
519
|
+
setup: SETUP_HELP,
|
|
520
|
+
log: LOG_HELP,
|
|
521
|
+
"log list": LOG_LIST_HELP,
|
|
522
|
+
"log show": LOG_SHOW_HELP,
|
|
523
|
+
"log clean": LOG_CLEAN_HELP,
|
|
524
|
+
config: CONFIG_HELP,
|
|
525
|
+
"config list": CONFIG_LIST_HELP,
|
|
526
|
+
"config get": CONFIG_GET_HELP,
|
|
527
|
+
"config set": CONFIG_SET_HELP,
|
|
528
|
+
};
|
|
529
|
+
// --- Early intercepts (cli-kit v0.2.1 workarounds) ---
|
|
530
|
+
/** Print help text for the command path extracted from argv, then exit. */
|
|
531
|
+
function printHelp(argv) {
|
|
532
|
+
const helpIdx = argv.findIndex((t) => t === "--help" || t === "-h");
|
|
533
|
+
const tokens = helpIdx >= 0 ? argv.slice(0, helpIdx).filter((t) => !t.startsWith("-")) : [];
|
|
534
|
+
for (let len = tokens.length; len >= 0; len--) {
|
|
535
|
+
const path = tokens.slice(0, len).join(" ");
|
|
536
|
+
const text = HELP_MAP[path];
|
|
537
|
+
if (text !== undefined) {
|
|
538
|
+
process.stdout.write(text);
|
|
539
|
+
process.exit(0);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
process.stdout.write(TOP_LEVEL_HELP);
|
|
543
|
+
process.exit(0);
|
|
544
|
+
}
|
|
545
|
+
/** Intercept deprecated commands before cli-kit parsing. Prints message + exit(1). */
|
|
546
|
+
function handleDeprecated(argv) {
|
|
547
|
+
const [cmd, sub] = argv;
|
|
548
|
+
if (cmd === "workflow" && sub === "put") {
|
|
549
|
+
process.stderr.write(`Error: Command 'workflow put' has been removed.
|
|
550
|
+
Use 'workflow add' instead.
|
|
551
|
+
|
|
552
|
+
For more information, see: uwf help workflow add
|
|
553
|
+
`);
|
|
554
|
+
process.exit(1);
|
|
555
|
+
}
|
|
556
|
+
if (cmd === "thread") {
|
|
557
|
+
if (sub === "step") {
|
|
558
|
+
process.stderr.write(`Error: Command 'thread step' has been removed.
|
|
559
|
+
Use 'thread exec' instead.
|
|
560
|
+
|
|
561
|
+
For more information, see: uwf help thread exec
|
|
562
|
+
`);
|
|
563
|
+
process.exit(1);
|
|
564
|
+
}
|
|
565
|
+
if (sub === "steps") {
|
|
566
|
+
process.stderr.write(`Error: Command 'thread steps' has been removed.
|
|
567
|
+
Use 'step list' instead.
|
|
568
|
+
|
|
569
|
+
For more information, see: uwf help step list
|
|
570
|
+
`);
|
|
571
|
+
process.exit(1);
|
|
572
|
+
}
|
|
573
|
+
if (sub === "step-details") {
|
|
574
|
+
process.stderr.write(`Error: Command 'thread step-details' has been removed.
|
|
575
|
+
Use 'step show' instead.
|
|
576
|
+
|
|
577
|
+
For more information, see: uwf help step show
|
|
578
|
+
`);
|
|
579
|
+
process.exit(1);
|
|
580
|
+
}
|
|
581
|
+
if (sub === "fork") {
|
|
582
|
+
process.stderr.write(`Error: Command 'thread fork' has been removed.
|
|
583
|
+
Use 'step fork' instead.
|
|
584
|
+
|
|
585
|
+
For more information, see: uwf help step fork
|
|
586
|
+
`);
|
|
587
|
+
process.exit(1);
|
|
588
|
+
}
|
|
589
|
+
if (sub === "kill") {
|
|
590
|
+
process.stderr.write(`Error: Command 'thread kill' has been removed.
|
|
591
|
+
Use 'thread stop' to stop background execution (keep thread active),
|
|
592
|
+
or 'thread cancel' to cancel and archive the thread.
|
|
593
|
+
|
|
594
|
+
For more information, see:
|
|
595
|
+
uwf help thread stop
|
|
596
|
+
uwf help thread cancel
|
|
597
|
+
`);
|
|
598
|
+
process.exit(1);
|
|
599
|
+
}
|
|
600
|
+
if (sub === "running") {
|
|
601
|
+
process.stderr.write(`Error: Command 'thread running' has been removed.
|
|
602
|
+
Use 'thread list --status running' instead.
|
|
603
|
+
|
|
604
|
+
For more information, see: uwf help thread list
|
|
605
|
+
`);
|
|
606
|
+
process.exit(1);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/** Strip `--format <value>` / `--format=value` from argv, returning cleaned argv. */
|
|
611
|
+
function stripFormatFlag(argv) {
|
|
612
|
+
const out = [];
|
|
613
|
+
for (let i = 0; i < argv.length; i++) {
|
|
614
|
+
const token = argv[i];
|
|
615
|
+
if (token === "--format") {
|
|
616
|
+
const value = argv[i + 1];
|
|
617
|
+
if (value !== undefined) {
|
|
618
|
+
formatOverride = value;
|
|
619
|
+
i++;
|
|
620
|
+
}
|
|
621
|
+
continue;
|
|
622
|
+
}
|
|
623
|
+
if (token.startsWith("--format=")) {
|
|
624
|
+
formatOverride = token.slice("--format=".length);
|
|
625
|
+
continue;
|
|
626
|
+
}
|
|
627
|
+
out.push(token);
|
|
628
|
+
}
|
|
629
|
+
return out;
|
|
630
|
+
}
|
|
631
|
+
/** Strip `--count <value>` / `--count=value` / `-c <value>` from argv. */
|
|
632
|
+
function stripCountFlag(argv) {
|
|
633
|
+
const out = [];
|
|
634
|
+
for (let i = 0; i < argv.length; i++) {
|
|
635
|
+
const token = argv[i];
|
|
636
|
+
if (token === "--count" || token === "-c") {
|
|
637
|
+
const value = argv[i + 1];
|
|
638
|
+
if (value !== undefined) {
|
|
639
|
+
countOverride = value;
|
|
640
|
+
i++;
|
|
641
|
+
}
|
|
642
|
+
continue;
|
|
643
|
+
}
|
|
644
|
+
if (token.startsWith("--count=")) {
|
|
645
|
+
countOverride = token.slice("--count=".length);
|
|
646
|
+
continue;
|
|
647
|
+
}
|
|
648
|
+
out.push(token);
|
|
649
|
+
}
|
|
650
|
+
return out;
|
|
651
|
+
}
|
|
652
|
+
// --- Build CLI with @ocas/cli-kit ---
|
|
653
|
+
const cli = createCLI({
|
|
654
|
+
name: "uwf",
|
|
655
|
+
version: VERSION,
|
|
656
|
+
});
|
|
657
|
+
const unknownSchema = z.unknown();
|
|
658
|
+
// ── workflow group ───────────────────────────────────────────────────────────
|
|
659
|
+
const workflow = cli.command("workflow");
|
|
660
|
+
workflow
|
|
661
|
+
.command("add")
|
|
662
|
+
.returns(unknownSchema, "")
|
|
663
|
+
.action(async (_args, flags) => {
|
|
664
|
+
const file = requirePositional(flags, 0, "file");
|
|
665
|
+
const storageRoot = resolveStorageRoot();
|
|
666
|
+
await runAction(async () => {
|
|
667
|
+
const result = await cmdWorkflowAdd(storageRoot, file);
|
|
668
|
+
await writeOutput(toWorkflowAddPayload(result), "workflow-add", storageRoot);
|
|
669
|
+
});
|
|
670
|
+
return undefined;
|
|
671
|
+
});
|
|
672
|
+
workflow
|
|
673
|
+
.command("validate")
|
|
674
|
+
.returns(unknownSchema, "")
|
|
675
|
+
.action(async (_args, flags) => {
|
|
676
|
+
const file = requirePositional(flags, 0, "file");
|
|
677
|
+
const storageRoot = resolveStorageRoot();
|
|
678
|
+
await runAction(async () => {
|
|
679
|
+
const errors = await cmdWorkflowValidate(file);
|
|
680
|
+
await writeOutput(toValidateResultPayload(errors), "validate-result", storageRoot);
|
|
681
|
+
if (errors.length > 0) {
|
|
682
|
+
process.exit(1);
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
return undefined;
|
|
686
|
+
});
|
|
687
|
+
workflow
|
|
688
|
+
.command("show")
|
|
689
|
+
.returns(unknownSchema, "")
|
|
690
|
+
.action(async (_args, flags) => {
|
|
691
|
+
const id = requirePositional(flags, 0, "id");
|
|
692
|
+
const storageRoot = resolveStorageRoot();
|
|
693
|
+
await runAction(async () => {
|
|
694
|
+
const result = await cmdWorkflowShow(storageRoot, id, process.cwd());
|
|
695
|
+
await writeOutput(toWorkflowDetailPayload(result), "workflow-detail", storageRoot);
|
|
696
|
+
});
|
|
697
|
+
return undefined;
|
|
698
|
+
});
|
|
699
|
+
workflow
|
|
700
|
+
.command("list")
|
|
701
|
+
.returns(unknownSchema, "")
|
|
702
|
+
.action(async () => {
|
|
703
|
+
const storageRoot = resolveStorageRoot();
|
|
704
|
+
await runAction(async () => {
|
|
705
|
+
const result = await cmdWorkflowList(storageRoot, process.cwd());
|
|
706
|
+
await writeOutput(toWorkflowListPayload(result), "workflow-list", storageRoot);
|
|
707
|
+
});
|
|
708
|
+
return undefined;
|
|
709
|
+
});
|
|
710
|
+
// ── thread group ─────────────────────────────────────────────────────────────
|
|
711
|
+
const thread = cli.command("thread");
|
|
712
|
+
thread
|
|
713
|
+
.command("start")
|
|
714
|
+
.flag("prompt", { type: "string" })
|
|
715
|
+
.flag("p", { type: "string" })
|
|
716
|
+
.flag("cwd", { type: "string" })
|
|
717
|
+
.returns(unknownSchema, "")
|
|
718
|
+
.action(async (_args, flags) => {
|
|
719
|
+
const workflowName = requirePositional(flags, 0, "workflow");
|
|
720
|
+
const prompt = flags.prompt ?? flags.p;
|
|
721
|
+
if (prompt === undefined) {
|
|
722
|
+
process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
|
|
723
|
+
process.exit(1);
|
|
724
|
+
}
|
|
725
|
+
const storageRoot = resolveStorageRoot();
|
|
726
|
+
await runAction(async () => {
|
|
727
|
+
const result = await cmdThreadStart(storageRoot, workflowName, prompt, process.cwd(), flags.cwd ?? process.cwd());
|
|
728
|
+
await writeOutput(toThreadStartPayload(result), "thread-start", storageRoot);
|
|
729
|
+
});
|
|
730
|
+
return undefined;
|
|
731
|
+
});
|
|
732
|
+
thread
|
|
733
|
+
.command("exec")
|
|
734
|
+
.flag("agent", { type: "string" })
|
|
735
|
+
.flag("background", { type: "boolean", default: false })
|
|
736
|
+
.flag("_background-worker", { type: "boolean", default: false })
|
|
737
|
+
.returns(unknownSchema, "")
|
|
738
|
+
.action(async (_args, flags) => {
|
|
739
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
740
|
+
const storageRoot = resolveStorageRoot();
|
|
741
|
+
await runAction(async () => {
|
|
742
|
+
const agentOverride = flags.agent ?? null;
|
|
743
|
+
const count = countOverride !== null ? Number(countOverride) : 1;
|
|
744
|
+
const background = flags.background;
|
|
745
|
+
const backgroundWorker = flags["_background-worker"] ?? false;
|
|
746
|
+
const results = await cmdThreadExec(storageRoot, threadId, agentOverride, count, background, backgroundWorker);
|
|
747
|
+
await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
|
|
748
|
+
});
|
|
749
|
+
return undefined;
|
|
750
|
+
});
|
|
751
|
+
thread
|
|
752
|
+
.command("show")
|
|
753
|
+
.returns(unknownSchema, "")
|
|
754
|
+
.action(async (_args, flags) => {
|
|
755
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
756
|
+
const storageRoot = resolveStorageRoot();
|
|
757
|
+
await runAction(async () => {
|
|
758
|
+
const result = await cmdThreadShow(storageRoot, threadId);
|
|
759
|
+
await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
|
|
760
|
+
});
|
|
761
|
+
return undefined;
|
|
762
|
+
});
|
|
206
763
|
thread
|
|
207
764
|
.command("list")
|
|
208
|
-
.
|
|
209
|
-
.
|
|
210
|
-
.
|
|
211
|
-
.
|
|
212
|
-
.
|
|
213
|
-
.
|
|
214
|
-
.
|
|
215
|
-
.
|
|
765
|
+
.flag("status", { type: "string" })
|
|
766
|
+
.flag("all", { type: "boolean", default: false })
|
|
767
|
+
.flag("after", { type: "string" })
|
|
768
|
+
.flag("before", { type: "string" })
|
|
769
|
+
.flag("skip", { type: "string" })
|
|
770
|
+
.flag("take", { type: "string" })
|
|
771
|
+
.flag("limit", { type: "string" })
|
|
772
|
+
.flag("offset", { type: "string" })
|
|
773
|
+
.returns(unknownSchema, "")
|
|
774
|
+
.action(async (_args, flags) => {
|
|
216
775
|
const storageRoot = resolveStorageRoot();
|
|
217
|
-
runAction(async () => {
|
|
218
|
-
const statusFilter = parseStatusFilter(
|
|
776
|
+
await runAction(async () => {
|
|
777
|
+
const statusFilter = parseStatusFilter(flags.status);
|
|
219
778
|
const nowMs = Date.now();
|
|
220
|
-
const { afterMs, beforeMs } = parseTimeFilters(
|
|
221
|
-
const { skip, take } =
|
|
222
|
-
|
|
779
|
+
const { afterMs, beforeMs } = parseTimeFilters(flags.after, flags.before, nowMs);
|
|
780
|
+
const { skip, take } = resolveThreadListPagination({
|
|
781
|
+
skip: flags.skip,
|
|
782
|
+
take: flags.take,
|
|
783
|
+
limit: flags.limit,
|
|
784
|
+
offset: flags.offset,
|
|
785
|
+
});
|
|
786
|
+
const showAll = flags.all === true;
|
|
223
787
|
const result = await cmdThreadList(storageRoot, statusFilter, afterMs, beforeMs, skip, take, showAll);
|
|
224
788
|
await writeOutput(toThreadListPayload(result), "thread-list", storageRoot);
|
|
225
789
|
});
|
|
790
|
+
return undefined;
|
|
226
791
|
});
|
|
227
792
|
thread
|
|
228
793
|
.command("resume")
|
|
229
|
-
.
|
|
230
|
-
.
|
|
231
|
-
.
|
|
232
|
-
.
|
|
233
|
-
.action((
|
|
794
|
+
.flag("prompt", { type: "string" })
|
|
795
|
+
.flag("p", { type: "string" })
|
|
796
|
+
.flag("agent", { type: "string" })
|
|
797
|
+
.returns(unknownSchema, "")
|
|
798
|
+
.action(async (_args, flags) => {
|
|
799
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
234
800
|
const storageRoot = resolveStorageRoot();
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const
|
|
801
|
+
const prompt = flags.prompt ?? flags.p;
|
|
802
|
+
await runAction(async () => {
|
|
803
|
+
const supplement = prompt ?? null;
|
|
804
|
+
const agentOverride = flags.agent ?? null;
|
|
238
805
|
const result = await cmdThreadResume(storageRoot, threadId, supplement, agentOverride);
|
|
239
806
|
await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
|
|
240
807
|
});
|
|
808
|
+
return undefined;
|
|
241
809
|
});
|
|
242
810
|
thread
|
|
243
811
|
.command("poke")
|
|
244
|
-
.
|
|
245
|
-
.
|
|
246
|
-
.
|
|
247
|
-
.
|
|
248
|
-
.action((
|
|
812
|
+
.flag("prompt", { type: "string" })
|
|
813
|
+
.flag("p", { type: "string" })
|
|
814
|
+
.flag("agent", { type: "string" })
|
|
815
|
+
.returns(unknownSchema, "")
|
|
816
|
+
.action(async (_args, flags) => {
|
|
817
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
818
|
+
const prompt = flags.prompt ?? flags.p;
|
|
819
|
+
if (prompt === undefined) {
|
|
820
|
+
process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
|
|
821
|
+
process.exit(1);
|
|
822
|
+
}
|
|
249
823
|
const storageRoot = resolveStorageRoot();
|
|
250
|
-
runAction(async () => {
|
|
251
|
-
const agentOverride =
|
|
252
|
-
const result = await cmdThreadPoke(storageRoot, threadId,
|
|
824
|
+
await runAction(async () => {
|
|
825
|
+
const agentOverride = flags.agent ?? null;
|
|
826
|
+
const result = await cmdThreadPoke(storageRoot, threadId, prompt, agentOverride);
|
|
253
827
|
await writeOutput(toThreadStatusPayload(result), "thread-status", storageRoot);
|
|
254
828
|
});
|
|
829
|
+
return undefined;
|
|
255
830
|
});
|
|
256
831
|
thread
|
|
257
832
|
.command("stop")
|
|
258
|
-
.
|
|
259
|
-
.
|
|
260
|
-
|
|
833
|
+
.returns(unknownSchema, "")
|
|
834
|
+
.action(async (_args, flags) => {
|
|
835
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
261
836
|
const storageRoot = resolveStorageRoot();
|
|
262
|
-
runAction(async () => {
|
|
837
|
+
await runAction(async () => {
|
|
263
838
|
const result = await cmdThreadStop(storageRoot, threadId);
|
|
264
839
|
writeRawOutput(result, "thread stop");
|
|
265
840
|
});
|
|
841
|
+
return undefined;
|
|
266
842
|
});
|
|
267
843
|
thread
|
|
268
844
|
.command("cancel")
|
|
269
|
-
.
|
|
270
|
-
.
|
|
271
|
-
|
|
845
|
+
.returns(unknownSchema, "")
|
|
846
|
+
.action(async (_args, flags) => {
|
|
847
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
272
848
|
const storageRoot = resolveStorageRoot();
|
|
273
|
-
runAction(async () => {
|
|
849
|
+
await runAction(async () => {
|
|
274
850
|
const result = await cmdThreadCancel(storageRoot, threadId);
|
|
275
851
|
writeRawOutput(result, "thread cancel");
|
|
276
852
|
});
|
|
853
|
+
return undefined;
|
|
277
854
|
});
|
|
278
855
|
thread
|
|
279
856
|
.command("join")
|
|
280
|
-
.
|
|
281
|
-
.
|
|
282
|
-
.
|
|
283
|
-
|
|
857
|
+
.flag("timeout", { type: "string" })
|
|
858
|
+
.returns(unknownSchema, "")
|
|
859
|
+
.action(async (_args, flags) => {
|
|
860
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
284
861
|
const storageRoot = resolveStorageRoot();
|
|
285
|
-
runAction(async () => {
|
|
286
|
-
const
|
|
862
|
+
await runAction(async () => {
|
|
863
|
+
const timeoutRaw = flags.timeout;
|
|
864
|
+
const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) * 1000 : null;
|
|
287
865
|
if (timeoutMs !== null && (!Number.isFinite(timeoutMs) || timeoutMs <= 0)) {
|
|
288
866
|
process.stderr.write("invalid --timeout: must be a positive number\n");
|
|
289
867
|
process.exit(1);
|
|
@@ -291,311 +869,299 @@ thread
|
|
|
291
869
|
const results = await cmdThreadJoin(storageRoot, threadId, timeoutMs);
|
|
292
870
|
await writeOutput(toThreadExecPayload(results), "thread-exec", storageRoot);
|
|
293
871
|
});
|
|
872
|
+
return undefined;
|
|
294
873
|
});
|
|
295
874
|
thread
|
|
296
875
|
.command("read")
|
|
297
|
-
.
|
|
298
|
-
.
|
|
299
|
-
.
|
|
300
|
-
.
|
|
301
|
-
.
|
|
302
|
-
|
|
876
|
+
.flag("quota", { type: "string", default: String(THREAD_READ_DEFAULT_QUOTA) })
|
|
877
|
+
.flag("before", { type: "string" })
|
|
878
|
+
.flag("start", { type: "boolean", default: false })
|
|
879
|
+
.returns(unknownSchema, "")
|
|
880
|
+
.action(async (_args, flags) => {
|
|
881
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
303
882
|
const storageRoot = resolveStorageRoot();
|
|
304
|
-
runAction(async () => {
|
|
305
|
-
const quota = Number.parseInt(
|
|
883
|
+
await runAction(async () => {
|
|
884
|
+
const quota = Number.parseInt(flags.quota, 10);
|
|
306
885
|
if (!Number.isFinite(quota) || quota < 1) {
|
|
307
886
|
process.stderr.write("invalid --quota: must be a positive integer\n");
|
|
308
887
|
process.exit(1);
|
|
309
888
|
}
|
|
310
|
-
const before =
|
|
311
|
-
const markdown = await cmdThreadRead(storageRoot, threadId, quota, before,
|
|
889
|
+
const before = flags.before ?? null;
|
|
890
|
+
const markdown = await cmdThreadRead(storageRoot, threadId, quota, before, flags.start ?? false);
|
|
312
891
|
process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
|
|
313
892
|
});
|
|
893
|
+
return undefined;
|
|
314
894
|
});
|
|
315
|
-
|
|
895
|
+
// ── step group ───────────────────────────────────────────────────────────────
|
|
896
|
+
const step = cli.command("step");
|
|
316
897
|
step
|
|
317
898
|
.command("list")
|
|
318
|
-
.
|
|
319
|
-
.
|
|
320
|
-
|
|
899
|
+
.returns(unknownSchema, "")
|
|
900
|
+
.action(async (_args, flags) => {
|
|
901
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
321
902
|
const storageRoot = resolveStorageRoot();
|
|
322
|
-
runAction(async () => {
|
|
903
|
+
await runAction(async () => {
|
|
323
904
|
const result = await cmdStepList(storageRoot, threadId);
|
|
324
905
|
await writeOutput(toStepListPayload(result), "step-list", storageRoot);
|
|
325
906
|
});
|
|
907
|
+
return undefined;
|
|
326
908
|
});
|
|
327
909
|
step
|
|
328
910
|
.command("show")
|
|
329
|
-
.
|
|
330
|
-
.
|
|
331
|
-
|
|
911
|
+
.returns(unknownSchema, "")
|
|
912
|
+
.action(async (_args, flags) => {
|
|
913
|
+
const stepHash = requirePositional(flags, 0, "step-hash");
|
|
332
914
|
const storageRoot = resolveStorageRoot();
|
|
333
|
-
runAction(async () => {
|
|
915
|
+
await runAction(async () => {
|
|
334
916
|
const detail = await cmdStepShow(storageRoot, stepHash);
|
|
335
917
|
await writeOutput(toStepDetailPayload(stepHash, detail), "step-detail", storageRoot);
|
|
336
918
|
});
|
|
919
|
+
return undefined;
|
|
337
920
|
});
|
|
338
921
|
step
|
|
339
922
|
.command("ask")
|
|
340
|
-
.
|
|
341
|
-
.
|
|
342
|
-
.
|
|
343
|
-
.
|
|
344
|
-
.
|
|
345
|
-
.action((
|
|
923
|
+
.flag("prompt", { type: "string" })
|
|
924
|
+
.flag("p", { type: "string" })
|
|
925
|
+
.flag("agent", { type: "string" })
|
|
926
|
+
.flag("no-fork", { type: "boolean", default: false })
|
|
927
|
+
.returns(unknownSchema, "")
|
|
928
|
+
.action(async (_args, flags) => {
|
|
929
|
+
const stepHash = requirePositional(flags, 0, "step-hash");
|
|
930
|
+
const prompt = flags.prompt ?? flags.p;
|
|
931
|
+
if (prompt === undefined) {
|
|
932
|
+
process.stderr.write("Error: missing required option: -p, --prompt <text>\n");
|
|
933
|
+
process.exit(1);
|
|
934
|
+
}
|
|
346
935
|
const storageRoot = resolveStorageRoot();
|
|
347
|
-
runAction(async () => {
|
|
936
|
+
await runAction(async () => {
|
|
348
937
|
const stdout = await cmdStepAsk(storageRoot, stepHash, {
|
|
349
|
-
prompt
|
|
350
|
-
agentOverride:
|
|
351
|
-
fork:
|
|
938
|
+
prompt,
|
|
939
|
+
agentOverride: flags.agent ?? null,
|
|
940
|
+
fork: !flags["no-fork"],
|
|
352
941
|
});
|
|
353
942
|
process.stdout.write(stdout.endsWith("\n") ? stdout : `${stdout}\n`);
|
|
354
943
|
});
|
|
944
|
+
return undefined;
|
|
355
945
|
});
|
|
356
946
|
step
|
|
357
947
|
.command("read")
|
|
358
|
-
.
|
|
359
|
-
.
|
|
360
|
-
.
|
|
361
|
-
.
|
|
362
|
-
|
|
948
|
+
.flag("quota", { type: "string", default: "4000" })
|
|
949
|
+
.flag("prompt", { type: "boolean", default: false })
|
|
950
|
+
.returns(unknownSchema, "")
|
|
951
|
+
.action(async (_args, flags) => {
|
|
952
|
+
const stepHash = requirePositional(flags, 0, "step-hash");
|
|
363
953
|
const storageRoot = resolveStorageRoot();
|
|
364
|
-
runAction(async () => {
|
|
365
|
-
const quota = Number.parseInt(
|
|
954
|
+
await runAction(async () => {
|
|
955
|
+
const quota = Number.parseInt(flags.quota, 10);
|
|
366
956
|
if (!Number.isFinite(quota) || quota < 1) {
|
|
367
957
|
process.stderr.write("invalid --quota: must be a positive integer\n");
|
|
368
958
|
process.exit(1);
|
|
369
959
|
}
|
|
370
|
-
const markdown = await cmdStepRead(storageRoot, stepHash, quota,
|
|
960
|
+
const markdown = await cmdStepRead(storageRoot, stepHash, quota, flags.prompt === true);
|
|
371
961
|
process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
|
|
372
962
|
});
|
|
963
|
+
return undefined;
|
|
964
|
+
});
|
|
965
|
+
step
|
|
966
|
+
.command("turns")
|
|
967
|
+
.flag("role", { type: "string" })
|
|
968
|
+
.flag("live", { type: "boolean", default: false })
|
|
969
|
+
.flag("limit", { type: "string" })
|
|
970
|
+
.flag("offset", { type: "string" })
|
|
971
|
+
.returns(unknownSchema, "")
|
|
972
|
+
.action(async (_args, flags) => {
|
|
973
|
+
const threadId = requirePositional(flags, 0, "thread-id");
|
|
974
|
+
const storageRoot = resolveStorageRoot();
|
|
975
|
+
await runAction(async () => {
|
|
976
|
+
const limit = parseTurnsPageOption("--limit", flags.limit);
|
|
977
|
+
const offset = parseTurnsPageOption("--offset", flags.offset) ?? 0;
|
|
978
|
+
const markdown = await cmdStepTurns(storageRoot, threadId, {
|
|
979
|
+
role: flags.role ?? null,
|
|
980
|
+
live: flags.live === true,
|
|
981
|
+
limit,
|
|
982
|
+
offset,
|
|
983
|
+
});
|
|
984
|
+
if (markdown !== "") {
|
|
985
|
+
process.stdout.write(markdown.endsWith("\n") ? markdown : `${markdown}\n`);
|
|
986
|
+
}
|
|
987
|
+
});
|
|
988
|
+
return undefined;
|
|
373
989
|
});
|
|
374
990
|
step
|
|
375
991
|
.command("fork")
|
|
376
|
-
.
|
|
377
|
-
.
|
|
378
|
-
|
|
992
|
+
.returns(unknownSchema, "")
|
|
993
|
+
.action(async (_args, flags) => {
|
|
994
|
+
const stepHash = requirePositional(flags, 0, "step-hash");
|
|
379
995
|
const storageRoot = resolveStorageRoot();
|
|
380
|
-
runAction(async () => {
|
|
996
|
+
await runAction(async () => {
|
|
381
997
|
const result = await cmdStepFork(storageRoot, stepHash);
|
|
382
998
|
writeRawOutput(result);
|
|
383
999
|
});
|
|
1000
|
+
return undefined;
|
|
384
1001
|
});
|
|
385
|
-
// ──
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
.command("put")
|
|
389
|
-
.description("[DEPRECATED] Use 'workflow add' instead")
|
|
390
|
-
.argument("<file>", "Workflow YAML file")
|
|
391
|
-
.action(() => {
|
|
392
|
-
process.stderr.write(`Error: Command 'workflow put' has been removed.
|
|
393
|
-
Use 'workflow add' instead.
|
|
394
|
-
|
|
395
|
-
For more information, see: uwf help workflow add
|
|
396
|
-
`);
|
|
397
|
-
process.exit(1);
|
|
398
|
-
});
|
|
399
|
-
thread
|
|
400
|
-
.command("step")
|
|
401
|
-
.description("[DEPRECATED] Use 'thread exec' instead")
|
|
402
|
-
.argument("<thread-id>", "Thread ULID")
|
|
403
|
-
.allowUnknownOption()
|
|
404
|
-
.action(() => {
|
|
405
|
-
process.stderr.write(`Error: Command 'thread step' has been removed.
|
|
406
|
-
Use 'thread exec' instead.
|
|
407
|
-
|
|
408
|
-
For more information, see: uwf help thread exec
|
|
409
|
-
`);
|
|
410
|
-
process.exit(1);
|
|
411
|
-
});
|
|
412
|
-
thread
|
|
413
|
-
.command("steps")
|
|
414
|
-
.description("[DEPRECATED] Use 'step list' instead")
|
|
415
|
-
.argument("<thread-id>", "Thread ULID")
|
|
416
|
-
.action(() => {
|
|
417
|
-
process.stderr.write(`Error: Command 'thread steps' has been removed.
|
|
418
|
-
Use 'step list' instead.
|
|
419
|
-
|
|
420
|
-
For more information, see: uwf help step list
|
|
421
|
-
`);
|
|
422
|
-
process.exit(1);
|
|
423
|
-
});
|
|
424
|
-
thread
|
|
425
|
-
.command("step-details")
|
|
426
|
-
.description("[DEPRECATED] Use 'step show' instead")
|
|
427
|
-
.argument("<step-hash>", "Step hash")
|
|
428
|
-
.action(() => {
|
|
429
|
-
process.stderr.write(`Error: Command 'thread step-details' has been removed.
|
|
430
|
-
Use 'step show' instead.
|
|
431
|
-
|
|
432
|
-
For more information, see: uwf help step show
|
|
433
|
-
`);
|
|
434
|
-
process.exit(1);
|
|
435
|
-
});
|
|
436
|
-
thread
|
|
437
|
-
.command("fork")
|
|
438
|
-
.description("[DEPRECATED] Use 'step fork' instead")
|
|
439
|
-
.argument("<step-hash>", "Step hash")
|
|
440
|
-
.action(() => {
|
|
441
|
-
process.stderr.write(`Error: Command 'thread fork' has been removed.
|
|
442
|
-
Use 'step fork' instead.
|
|
443
|
-
|
|
444
|
-
For more information, see: uwf help step fork
|
|
445
|
-
`);
|
|
446
|
-
process.exit(1);
|
|
447
|
-
});
|
|
448
|
-
thread
|
|
449
|
-
.command("kill")
|
|
450
|
-
.description("[DEPRECATED] Use 'thread stop' or 'thread cancel' instead")
|
|
451
|
-
.argument("<thread-id>", "Thread ULID")
|
|
452
|
-
.action(() => {
|
|
453
|
-
process.stderr.write(`Error: Command 'thread kill' has been removed.
|
|
454
|
-
Use 'thread stop' to stop background execution (keep thread active),
|
|
455
|
-
or 'thread cancel' to cancel and archive the thread.
|
|
456
|
-
|
|
457
|
-
For more information, see:
|
|
458
|
-
uwf help thread stop
|
|
459
|
-
uwf help thread cancel
|
|
460
|
-
`);
|
|
461
|
-
process.exit(1);
|
|
462
|
-
});
|
|
463
|
-
thread
|
|
464
|
-
.command("running")
|
|
465
|
-
.description("[DEPRECATED] Use 'thread list --status running' instead")
|
|
466
|
-
.action(() => {
|
|
467
|
-
process.stderr.write(`Error: Command 'thread running' has been removed.
|
|
468
|
-
Use 'thread list --status running' instead.
|
|
469
|
-
|
|
470
|
-
For more information, see: uwf help thread list
|
|
471
|
-
`);
|
|
472
|
-
process.exit(1);
|
|
473
|
-
});
|
|
474
|
-
const prompt = program.command("prompt").description("Built-in prompt references for agents");
|
|
475
|
-
prompt.addHelpCommand(false);
|
|
476
|
-
prompt
|
|
1002
|
+
// ── prompt group ─────────────────────────────────────────────────────────────
|
|
1003
|
+
const promptGroup = cli.command("prompt");
|
|
1004
|
+
promptGroup
|
|
477
1005
|
.command("usage")
|
|
478
|
-
.
|
|
479
|
-
.action(() => {
|
|
1006
|
+
.returns(unknownSchema, "")
|
|
1007
|
+
.action(async () => {
|
|
480
1008
|
console.log(cmdPromptUsage());
|
|
1009
|
+
return undefined;
|
|
481
1010
|
});
|
|
482
|
-
|
|
1011
|
+
promptGroup
|
|
483
1012
|
.command("bootstrap")
|
|
484
|
-
.
|
|
485
|
-
.action(() => {
|
|
1013
|
+
.returns(unknownSchema, "")
|
|
1014
|
+
.action(async () => {
|
|
486
1015
|
console.log(cmdPromptBootstrap());
|
|
1016
|
+
return undefined;
|
|
487
1017
|
});
|
|
488
|
-
|
|
1018
|
+
promptGroup
|
|
489
1019
|
.command("workflow-authoring")
|
|
490
|
-
.
|
|
491
|
-
.action(() => {
|
|
1020
|
+
.returns(unknownSchema, "")
|
|
1021
|
+
.action(async () => {
|
|
492
1022
|
console.log(cmdPromptWorkflowAuthoring());
|
|
1023
|
+
return undefined;
|
|
493
1024
|
});
|
|
494
|
-
|
|
1025
|
+
promptGroup
|
|
495
1026
|
.command("adapter-developing")
|
|
496
|
-
.
|
|
497
|
-
.action(() => {
|
|
1027
|
+
.returns(unknownSchema, "")
|
|
1028
|
+
.action(async () => {
|
|
498
1029
|
console.log(cmdPromptAdapterDeveloping());
|
|
1030
|
+
return undefined;
|
|
499
1031
|
});
|
|
500
|
-
|
|
1032
|
+
promptGroup
|
|
501
1033
|
.command("list")
|
|
502
|
-
.
|
|
503
|
-
.action(() => {
|
|
1034
|
+
.returns(unknownSchema, "")
|
|
1035
|
+
.action(async () => {
|
|
504
1036
|
console.log(cmdPromptList().join("\n"));
|
|
1037
|
+
return undefined;
|
|
505
1038
|
});
|
|
506
|
-
|
|
1039
|
+
// ── setup (top-level) ────────────────────────────────────────────────────────
|
|
1040
|
+
cli
|
|
507
1041
|
.command("setup")
|
|
508
|
-
.
|
|
509
|
-
|
|
510
|
-
.
|
|
511
|
-
.action((opts) => {
|
|
1042
|
+
.flag("agent", { type: "string" })
|
|
1043
|
+
.returns(unknownSchema, "")
|
|
1044
|
+
.action(async (_args, flags) => {
|
|
512
1045
|
const storageRoot = resolveStorageRoot();
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
1046
|
+
const agent = flags.agent;
|
|
1047
|
+
await runAction(async () => {
|
|
1048
|
+
if (agent !== undefined && agent !== "") {
|
|
1049
|
+
const result = await cmdSetup({ agent, storageRoot });
|
|
516
1050
|
writeRawOutput(result);
|
|
517
1051
|
}
|
|
518
1052
|
else {
|
|
519
1053
|
await cmdSetupInteractive(storageRoot);
|
|
520
1054
|
}
|
|
521
1055
|
});
|
|
1056
|
+
return undefined;
|
|
522
1057
|
});
|
|
523
|
-
|
|
1058
|
+
// ── log group ────────────────────────────────────────────────────────────────
|
|
1059
|
+
const log = cli.command("log");
|
|
524
1060
|
log
|
|
525
1061
|
.command("list")
|
|
526
|
-
.
|
|
527
|
-
.action(() => {
|
|
1062
|
+
.returns(unknownSchema, "")
|
|
1063
|
+
.action(async () => {
|
|
528
1064
|
const storageRoot = resolveStorageRoot();
|
|
529
|
-
runAction(async () => {
|
|
1065
|
+
await runAction(async () => {
|
|
530
1066
|
const result = await cmdLogList(storageRoot);
|
|
531
1067
|
writeRawOutput(result, "log list");
|
|
532
1068
|
});
|
|
1069
|
+
return undefined;
|
|
533
1070
|
});
|
|
534
1071
|
log
|
|
535
1072
|
.command("show")
|
|
536
|
-
.
|
|
537
|
-
.
|
|
538
|
-
.
|
|
539
|
-
.
|
|
540
|
-
.action((
|
|
1073
|
+
.flag("thread", { type: "string" })
|
|
1074
|
+
.flag("process", { type: "string" })
|
|
1075
|
+
.flag("date", { type: "string" })
|
|
1076
|
+
.returns(unknownSchema, "")
|
|
1077
|
+
.action(async (_args, flags) => {
|
|
541
1078
|
const storageRoot = resolveStorageRoot();
|
|
542
|
-
runAction(async () => {
|
|
1079
|
+
await runAction(async () => {
|
|
543
1080
|
const result = await cmdLogShow(storageRoot, {
|
|
544
|
-
thread:
|
|
545
|
-
process:
|
|
546
|
-
date:
|
|
1081
|
+
thread: flags.thread ?? null,
|
|
1082
|
+
process: flags.process ?? null,
|
|
1083
|
+
date: flags.date ?? null,
|
|
547
1084
|
});
|
|
548
1085
|
writeRawOutput(result, "log show");
|
|
549
1086
|
});
|
|
1087
|
+
return undefined;
|
|
550
1088
|
});
|
|
551
1089
|
log
|
|
552
1090
|
.command("clean")
|
|
553
|
-
.
|
|
554
|
-
.
|
|
555
|
-
.action((
|
|
1091
|
+
.flag("before", { type: "string" })
|
|
1092
|
+
.returns(unknownSchema, "")
|
|
1093
|
+
.action(async (_args, flags) => {
|
|
1094
|
+
const before = flags.before;
|
|
1095
|
+
if (before === undefined) {
|
|
1096
|
+
process.stderr.write("Error: missing required option: --before <date>\n");
|
|
1097
|
+
process.exit(1);
|
|
1098
|
+
}
|
|
556
1099
|
const storageRoot = resolveStorageRoot();
|
|
557
|
-
runAction(async () => {
|
|
558
|
-
const result = await cmdLogClean(storageRoot,
|
|
1100
|
+
await runAction(async () => {
|
|
1101
|
+
const result = await cmdLogClean(storageRoot, before);
|
|
559
1102
|
writeRawOutput(result);
|
|
560
1103
|
});
|
|
1104
|
+
return undefined;
|
|
561
1105
|
});
|
|
562
|
-
|
|
1106
|
+
// ── config group ─────────────────────────────────────────────────────────────
|
|
1107
|
+
const config = cli.command("config");
|
|
563
1108
|
config
|
|
564
1109
|
.command("list")
|
|
565
|
-
.
|
|
566
|
-
.action(() => {
|
|
1110
|
+
.returns(unknownSchema, "")
|
|
1111
|
+
.action(async () => {
|
|
567
1112
|
const storageRoot = resolveStorageRoot();
|
|
568
|
-
runAction(async () => {
|
|
1113
|
+
await runAction(async () => {
|
|
569
1114
|
const result = await cmdConfigList(storageRoot);
|
|
570
1115
|
writeRawOutput(result, "config list");
|
|
571
1116
|
});
|
|
1117
|
+
return undefined;
|
|
572
1118
|
});
|
|
573
1119
|
config
|
|
574
1120
|
.command("get")
|
|
575
|
-
.
|
|
576
|
-
.
|
|
577
|
-
|
|
1121
|
+
.returns(unknownSchema, "")
|
|
1122
|
+
.action(async (_args, flags) => {
|
|
1123
|
+
const key = requirePositional(flags, 0, "key");
|
|
578
1124
|
const storageRoot = resolveStorageRoot();
|
|
579
|
-
runAction(async () => {
|
|
1125
|
+
await runAction(async () => {
|
|
580
1126
|
const result = await cmdConfigGet(storageRoot, key);
|
|
581
1127
|
writeRawOutput({ value: result }, "config get");
|
|
582
1128
|
});
|
|
1129
|
+
return undefined;
|
|
583
1130
|
});
|
|
584
1131
|
config
|
|
585
1132
|
.command("set")
|
|
586
|
-
.
|
|
587
|
-
.
|
|
588
|
-
|
|
589
|
-
|
|
1133
|
+
.returns(unknownSchema, "")
|
|
1134
|
+
.action(async (_args, flags) => {
|
|
1135
|
+
const key = requirePositional(flags, 0, "key");
|
|
1136
|
+
const value = requirePositional(flags, 1, "value");
|
|
590
1137
|
const storageRoot = resolveStorageRoot();
|
|
591
|
-
runAction(async () => {
|
|
1138
|
+
await runAction(async () => {
|
|
592
1139
|
const result = await cmdConfigSet(storageRoot, key, value);
|
|
593
1140
|
writeRawOutput(result, "config set");
|
|
594
1141
|
});
|
|
1142
|
+
return undefined;
|
|
595
1143
|
});
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
1144
|
+
// --- Main execution: early intercepts + cli.run() ---
|
|
1145
|
+
const rawArgv = process.argv.slice(2);
|
|
1146
|
+
// 1. --version / -V (cli-kit doesn't handle these)
|
|
1147
|
+
const firstToken = rawArgv[0];
|
|
1148
|
+
if (firstToken === "--version" || firstToken === "-V") {
|
|
1149
|
+
process.stdout.write(`${VERSION}\n`);
|
|
1150
|
+
process.exit(0);
|
|
1151
|
+
}
|
|
1152
|
+
// 2. Strip --format (cli-kit has no global --format; parse into module-level var)
|
|
1153
|
+
const argvNoFormat = stripFormatFlag(rawArgv);
|
|
1154
|
+
// 3. --help / -h / no args (cli-kit has no per-command --help)
|
|
1155
|
+
if (argvNoFormat.length === 0 || argvNoFormat.includes("--help") || argvNoFormat.includes("-h")) {
|
|
1156
|
+
printHelp(argvNoFormat);
|
|
1157
|
+
}
|
|
1158
|
+
// 4. Deprecated commands (intercept before cli-kit parsing)
|
|
1159
|
+
handleDeprecated(argvNoFormat);
|
|
1160
|
+
// 5. Strip --count / -c (cli-kit rejects values starting with `-`)
|
|
1161
|
+
const argvNoCount = stripCountFlag(argvNoFormat);
|
|
1162
|
+
// 6. Run cli-kit
|
|
1163
|
+
const exitCode = await cli.run({ argv: argvNoCount });
|
|
1164
|
+
if (exitCode !== 0) {
|
|
1165
|
+
process.exit(exitCode);
|
|
1166
|
+
}
|
|
601
1167
|
//# sourceMappingURL=cli.js.map
|