From fecb02b1154c286da4be7b3ee126d265cc9352fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Tue, 26 May 2026 15:51:14 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20add=20user=20skill=20=E2=80=94=20CLI=20?= =?UTF-8?q?guide=20with=20quick=20start=20and=20typical=20workflows?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds 'uwf skill user' command for agents/humans using the uwf CLI. Covers setup, workflow management, thread lifecycle, step operations, CAS queries, logging, and global options with a Quick Start guide. Refs #538 --- .../cli-workflow/src/__tests__/skill.test.ts | 13 ++ packages/cli-workflow/src/cli.ts | 8 ++ packages/cli-workflow/src/commands/skill.ts | 3 +- packages/workflow-util/src/index.ts | 1 + packages/workflow-util/src/user-reference.ts | 125 ++++++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 packages/workflow-util/src/user-reference.ts diff --git a/packages/cli-workflow/src/__tests__/skill.test.ts b/packages/cli-workflow/src/__tests__/skill.test.ts index 18d345c..5ec32ea 100644 --- a/packages/cli-workflow/src/__tests__/skill.test.ts +++ b/packages/cli-workflow/src/__tests__/skill.test.ts @@ -11,6 +11,7 @@ import { cmdSkillCli, cmdSkillList, cmdSkillModerator, + cmdSkillUser, cmdSkillYaml, } from "../commands/skill.js"; @@ -23,6 +24,7 @@ describe("skill commands", () => { expect(result).toContain("yaml"); expect(result).toContain("moderator"); expect(result).toContain("actor"); + expect(result).toContain("user"); for (const name of result) { expect(name).toMatch(/^\S+$/); } @@ -72,6 +74,16 @@ describe("skill commands", () => { expect(result.length).toBeGreaterThan(200); }); + test("skill user returns non-empty markdown string", () => { + const result = cmdSkillUser(); + expect(typeof result).toBe("string"); + expect(result).toContain("uwf"); + expect(result).toContain("thread"); + expect(result).toContain("workflow"); + expect(result).toContain("Quick Start"); + expect(result.length).toBeGreaterThan(500); + }); + test("skill help subcommand is suppressed", () => { const output = execFileSync("bun", ["src/cli.ts", "skill", "--help"], { cwd: join(__dirname, "..", ".."), @@ -84,6 +96,7 @@ describe("skill commands", () => { expect(output).toContain("yaml"); expect(output).toContain("moderator"); expect(output).toContain("actor"); + expect(output).toContain("user"); expect(output).toContain("list"); }); }); diff --git a/packages/cli-workflow/src/cli.ts b/packages/cli-workflow/src/cli.ts index 1f4a9c1..6c1f11f 100755 --- a/packages/cli-workflow/src/cli.ts +++ b/packages/cli-workflow/src/cli.ts @@ -22,6 +22,7 @@ import { cmdSkillCli, cmdSkillList, cmdSkillModerator, + cmdSkillUser, cmdSkillYaml, } from "./commands/skill.js"; import { cmdStepFork, cmdStepList, cmdStepRead, cmdStepShow } from "./commands/step.js"; @@ -518,6 +519,13 @@ skill console.log(cmdSkillModerator()); }); +skill + .command("user") + .description("Print the user reference (CLI guide + typical workflows)") + .action(() => { + console.log(cmdSkillUser()); + }); + skill .command("list") .description("List all available skill names") diff --git a/packages/cli-workflow/src/commands/skill.ts b/packages/cli-workflow/src/commands/skill.ts index c31ae75..4247d03 100644 --- a/packages/cli-workflow/src/commands/skill.ts +++ b/packages/cli-workflow/src/commands/skill.ts @@ -3,10 +3,11 @@ export { generateArchitectureReference as cmdSkillArchitecture, generateCliReference as cmdSkillCli, generateModeratorReference as cmdSkillModerator, + generateUserReference as cmdSkillUser, generateYamlReference as cmdSkillYaml, } from "@uncaged/workflow-util"; -const SKILL_NAMES = ["cli", "architecture", "yaml", "moderator", "actor"] as const; +const SKILL_NAMES = ["cli", "architecture", "yaml", "moderator", "actor", "user"] as const; export function cmdSkillList(): ReadonlyArray { return [...SKILL_NAMES]; diff --git a/packages/workflow-util/src/index.ts b/packages/workflow-util/src/index.ts index ec4f277..ebb6753 100644 --- a/packages/workflow-util/src/index.ts +++ b/packages/workflow-util/src/index.ts @@ -28,4 +28,5 @@ export { err, ok } from "./result.js"; export { getDefaultWorkflowStorageRoot, getGlobalCasDir } from "./storage-root.js"; export type { LogFn, Result } from "./types.js"; export { extractUlidTimestamp, generateUlid } from "./ulid.js"; +export { generateUserReference } from "./user-reference.js"; export { generateYamlReference } from "./yaml-reference.js"; diff --git a/packages/workflow-util/src/user-reference.ts b/packages/workflow-util/src/user-reference.ts new file mode 100644 index 0000000..c515d1e --- /dev/null +++ b/packages/workflow-util/src/user-reference.ts @@ -0,0 +1,125 @@ +export function generateUserReference(): string { + return `# User Reference + +Guide for using the uwf CLI to manage workflows and threads. + +## Quick Start + +\`\`\`bash +# 1. Configure provider and model +uwf setup + +# 2. Register a workflow +uwf workflow add my-workflow.yaml + +# 3. Start a thread (creates but does not execute) +uwf thread start my-workflow -p "Build a login page" + +# 4. Execute the thread (runs moderator → agent → extract cycles) +uwf thread exec # one step +uwf thread exec -c 10 # up to 10 steps +uwf thread exec -c 10 --background # run in background +\`\`\` + +## Concepts + +- **Workflow** — YAML definition with roles and a routing graph; stored as a CAS node +- **Thread** — A running instance of a workflow; a chain of step nodes in CAS +- **Step** — One moderator → agent → extract cycle; contains the role's structured output +- **CAS** — Content-addressable store; every artifact is hashed (XXH64, Crockford Base32) + +## Setup + +\`\`\` +uwf setup # interactive wizard +uwf setup --provider --base-url \\ + --api-key --model # non-interactive + [--agent ] # optional default agent +\`\`\` + +Config is stored at \`~/.uncaged/workflow/config.yaml\`. Override storage root with \`UNCAGED_WORKFLOW_STORAGE_ROOT\`. + +## Workflow Commands + +\`\`\` +uwf workflow add # register from YAML file +uwf workflow show # show by name or CAS hash +uwf workflow list # list all registered workflows +\`\`\` + +You can also pass a file path directly to \`uwf thread start\` without registering first. + +## Thread Lifecycle + +\`\`\` +uwf thread start -p # create thread +uwf thread exec # execute one step + [--agent ] # override agent + [-c, --count ] # run n steps + [--background] # run in background +uwf thread show # show head pointer +uwf thread list # list all threads + [--status ] # idle, running, completed, cancelled, active (comma-separated) + [--after ] # pagination: after this thread + [--before ] # pagination: before this thread + [--skip ] # skip first n results + [--take ] # limit results +uwf thread read # render context as markdown + [--quota ] # max output chars (default 4000) + [--before ] # pagination + [--start] # include start step +uwf thread stop # stop background execution +uwf thread cancel # cancel and archive thread +\`\`\` + +### Typical Lifecycle + +\`\`\` +start → exec (repeat) → thread reaches $END → auto-completed + → or: cancel to abort +\`\`\` + +## Step Commands + +\`\`\` +uwf step list # list all steps +uwf step show # show step details +uwf step fork # fork thread from a step (branch) +\`\`\` + +Forking creates a new thread that shares history up to the fork point — useful for retrying from a known-good state. + +## CAS Commands + +\`\`\` +uwf cas get # read a node (type + payload) + [--timestamp] # include timestamp +uwf cas put # store typed JSON, print hash +uwf cas put-text # store plain text, print hash +uwf cas has # check existence +uwf cas refs # list direct references +uwf cas walk # recursive traversal +uwf cas reindex # rebuild type index +uwf cas schema list # list schemas +uwf cas schema get # show schema definition +\`\`\` + +## Log Commands + +\`\`\` +uwf log list # list log files +uwf log show # show log entries + [--thread ] # filter by thread + [--process ] # filter by process + [--date ] # filter by date +uwf log clean --before # delete old logs +\`\`\` + +## Global Options + +\`\`\` +uwf --format # output format (default: json) +uwf -V, --version # print version +\`\`\` +`; +}