From 995f273fa5e7a3494c51f0b9ae8727e99a24dfbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E6=A9=98?= Date: Fri, 22 May 2026 03:29:01 +0000 Subject: [PATCH] address review: move CLI reference to workflow-util, inline in prompt - Move generateCliReference() to @uncaged/workflow-util - buildRolePrompt inlines CLI reference directly (no agent tool call) - Fix Role terminology to use new field names - Add maintenance comment in cli-reference.ts - Fix test assertions --- packages/cli-workflow/src/commands/skill.ts | 71 +----------------- .../__tests__/build-role-prompt.test.ts | 6 +- .../src/build-role-prompt.ts | 18 ++--- packages/workflow-util/src/cli-reference.ts | 72 +++++++++++++++++++ packages/workflow-util/src/index.ts | 1 + 5 files changed, 83 insertions(+), 85 deletions(-) create mode 100644 packages/workflow-util/src/cli-reference.ts diff --git a/packages/cli-workflow/src/commands/skill.ts b/packages/cli-workflow/src/commands/skill.ts index e86294a..59307ca 100644 --- a/packages/cli-workflow/src/commands/skill.ts +++ b/packages/cli-workflow/src/commands/skill.ts @@ -1,70 +1 @@ -export function cmdSkillCli(): string { - return `# uwf CLI Reference - -## Setup - -\`\`\` -uwf setup # interactive setup wizard -uwf setup --provider --base-url \\ - --api-key --model # non-interactive setup - [--agent ] # optional: default agent alias -\`\`\` - -## Workflow Commands - -\`\`\` -uwf workflow put # register a workflow from YAML file -uwf workflow show # show workflow by name or CAS hash -uwf workflow list # list all registered workflows -\`\`\` - -## Thread Commands - -\`\`\` -uwf thread start -p # create a thread (no execution) -uwf thread step # execute one moderator→agent→extract cycle - [--agent ] # override agent command -uwf thread show # show thread head pointer -uwf thread list # list active threads - [--all] # include archived threads -uwf thread kill # terminate and archive a thread -uwf thread steps # list all steps in a thread -uwf thread read # render thread context as markdown - [--quota ] # max output characters (default 32000) - [--before ] # load steps before this hash (exclusive) - [--start] # include start step in output -uwf thread fork # fork a thread from a specific step -uwf thread step-details # dump full detail node of a step as YAML -\`\`\` - -## CAS Commands - -\`\`\` -uwf cas get # read a CAS node (type + payload) - [--timestamp] # include timestamp in output -uwf cas put # store a node, print its hash - # : JSON file path or inline JSON string -uwf cas has # check if a hash exists -uwf cas refs # list direct CAS references from a node -uwf cas walk # recursive traversal from a node -uwf cas reindex # rebuild type index from all CAS nodes -uwf cas schema list # list all registered schemas -uwf cas schema get # show a schema by its type hash -\`\`\` - -## Global Options - -\`\`\` -uwf --format # output format: json (default) or yaml -uwf -V, --version # print version -\`\`\` - -## Key Concepts - -- **Workflow**: YAML definition with roles, conditions, and a routing graph; stored as a CAS node identified by its XXH64 hash. -- **Thread**: A single workflow execution (ULID). State is an immutable CAS chain; active threads are indexed in \`threads.yaml\`. -- **Step**: One moderator→agent→extract cycle. Run \`uwf thread step\` repeatedly until \`$END\`. -- **CAS**: Content-Addressed Storage — all nodes are immutable and identified by hash. -- **Role**: Named actor with a system prompt and JSON Schema output; the moderator routes between roles. -`; -} +export { generateCliReference as cmdSkillCli } from "@uncaged/workflow-util"; diff --git a/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts b/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts index 1a0fd0c..a56f702 100644 --- a/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts +++ b/packages/workflow-agent-kit/__tests__/build-role-prompt.test.ts @@ -19,7 +19,7 @@ describe("buildRolePrompt", () => { expect(result).toContain("- cursor-agent"); expect(result).toContain("- file-edit"); expect(result).toContain("## Prepare"); - expect(result).toContain("uwf skill cli"); + expect(result).toContain("uwf CLI Reference"); expect(result).toContain("cursor-agent, file-edit"); expect(result).toContain("## Procedure"); expect(result).toContain("Implement the feature."); @@ -39,7 +39,7 @@ describe("buildRolePrompt", () => { const result = buildRolePrompt(role); expect(result).toContain("## Goal"); expect(result).toContain("## Prepare"); - expect(result).toContain("uwf skill cli"); + expect(result).toContain("uwf CLI Reference"); expect(result).toContain("## Procedure"); expect(result).not.toContain("## Capabilities"); expect(result).not.toContain("## Output"); @@ -56,7 +56,7 @@ describe("buildRolePrompt", () => { }; const result = buildRolePrompt(role); expect(result).toContain("## Prepare"); - expect(result).toContain("uwf skill cli"); + expect(result).toContain("uwf CLI Reference"); expect(result).not.toContain("## Goal"); expect(result).not.toContain("## Capabilities"); expect(result).not.toContain("## Procedure"); diff --git a/packages/workflow-agent-kit/src/build-role-prompt.ts b/packages/workflow-agent-kit/src/build-role-prompt.ts index 5cc7de7..d307b59 100644 --- a/packages/workflow-agent-kit/src/build-role-prompt.ts +++ b/packages/workflow-agent-kit/src/build-role-prompt.ts @@ -1,4 +1,5 @@ import type { RoleDefinition } from "@uncaged/workflow-protocol"; +import { generateCliReference } from "@uncaged/workflow-util"; /** * Build the role prompt from a RoleDefinition. @@ -6,9 +7,9 @@ import type { RoleDefinition } from "@uncaged/workflow-protocol"; * Assembles structured sections: Goal, Capabilities, Prepare, Procedure, Output. * Empty strings and empty arrays are omitted from the output. * - * The Prepare section always instructs the agent to run `uwf skill cli` to load - * workflow knowledge, plus renders the capabilities array as keyword hints for - * implicit skill loading. + * The Prepare section always inlines the uwf CLI reference so the agent has + * workflow knowledge without needing to run an external command. The capabilities + * array is rendered as keyword hints for implicit skill loading. */ export function buildRolePrompt(role: RoleDefinition): string { const sections: string[] = []; @@ -22,21 +23,14 @@ export function buildRolePrompt(role: RoleDefinition): string { sections.push(`## Capabilities\n\n${list}`); } - const prepareLines: string[] = [ - "Run the following command to load workflow CLI knowledge before starting work:", - "", - "```", - "uwf skill cli", - "```", - ]; + const prepareLines: string[] = [generateCliReference()]; if (role.capabilities.length > 0) { const keywords = role.capabilities.join(", "); prepareLines.push( - "", `You have the following capabilities: ${keywords}. Load relevant skills matching these keywords before starting work.`, ); } - sections.push(`## Prepare\n\n${prepareLines.join("\n")}`); + sections.push(`## Prepare\n\n${prepareLines.join("\n\n")}`); if (role.procedure !== "") { sections.push(`## Procedure\n\n${role.procedure}`); diff --git a/packages/workflow-util/src/cli-reference.ts b/packages/workflow-util/src/cli-reference.ts new file mode 100644 index 0000000..f2d3881 --- /dev/null +++ b/packages/workflow-util/src/cli-reference.ts @@ -0,0 +1,72 @@ +// MAINTENANCE: This string must be kept in sync with the actual uwf CLI commands. +// Update whenever commands are added, removed, or their signatures change. +export function generateCliReference(): string { + return `# uwf CLI Reference + +## Setup + +\`\`\` +uwf setup # interactive setup wizard +uwf setup --provider --base-url \\ + --api-key --model # non-interactive setup + [--agent ] # optional: default agent alias +\`\`\` + +## Workflow Commands + +\`\`\` +uwf workflow put # register a workflow from YAML file +uwf workflow show # show workflow by name or CAS hash +uwf workflow list # list all registered workflows +\`\`\` + +## Thread Commands + +\`\`\` +uwf thread start -p # create a thread (no execution) +uwf thread step # execute one moderator→agent→extract cycle + [--agent ] # override agent command +uwf thread show # show thread head pointer +uwf thread list # list active threads + [--all] # include archived threads +uwf thread kill # terminate and archive a thread +uwf thread steps # list all steps in a thread +uwf thread read # render thread context as markdown + [--quota ] # max output characters (default 32000) + [--before ] # load steps before this hash (exclusive) + [--start] # include start step in output +uwf thread fork # fork a thread from a specific step +uwf thread step-details # dump full detail node of a step as YAML +\`\`\` + +## CAS Commands + +\`\`\` +uwf cas get # read a CAS node (type + payload) + [--timestamp] # include timestamp in output +uwf cas put # store a node, print its hash + # : JSON file path or inline JSON string +uwf cas has # check if a hash exists +uwf cas refs # list direct CAS references from a node +uwf cas walk # recursive traversal from a node +uwf cas reindex # rebuild type index from all CAS nodes +uwf cas schema list # list all registered schemas +uwf cas schema get # show a schema by its type hash +\`\`\` + +## Global Options + +\`\`\` +uwf --format # output format: json (default) or yaml +uwf -V, --version # print version +\`\`\` + +## Key Concepts + +- **Workflow**: YAML definition with roles, conditions, and a routing graph; stored as a CAS node identified by its XXH64 hash. +- **Thread**: A single workflow execution (ULID). State is an immutable CAS chain; active threads are indexed in \`threads.yaml\`. +- **Step**: One moderator→agent→extract cycle. Run \`uwf thread step\` repeatedly until \`$END\`. +- **CAS**: Content-Addressed Storage — all nodes are immutable and identified by hash. +- **Role**: Named actor with goal, capabilities, procedure, output, and meta; the moderator routes between roles. +`; +} diff --git a/packages/workflow-util/src/index.ts b/packages/workflow-util/src/index.ts index bdea551..58c2fcf 100644 --- a/packages/workflow-util/src/index.ts +++ b/packages/workflow-util/src/index.ts @@ -1,4 +1,5 @@ export { encodeUint64AsCrockford } from "./base32.js"; +export { generateCliReference } from "./cli-reference.js"; export { env } from "./env.js"; export type { AgentFrontmatter,