Merge pull request 'feat: add actor skill — frontmatter protocol + CAS reference' (#545) from feat/540-skill-actor into main
This commit is contained in:
@@ -6,6 +6,7 @@ import { describe, expect, test } from "vitest";
|
|||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
cmdSkillActor,
|
||||||
cmdSkillArchitecture,
|
cmdSkillArchitecture,
|
||||||
cmdSkillCli,
|
cmdSkillCli,
|
||||||
cmdSkillList,
|
cmdSkillList,
|
||||||
@@ -21,8 +22,8 @@ describe("skill commands", () => {
|
|||||||
expect(result).toContain("architecture");
|
expect(result).toContain("architecture");
|
||||||
expect(result).toContain("yaml");
|
expect(result).toContain("yaml");
|
||||||
expect(result).toContain("moderator");
|
expect(result).toContain("moderator");
|
||||||
|
expect(result).toContain("actor");
|
||||||
for (const name of result) {
|
for (const name of result) {
|
||||||
expect(typeof name).toBe("string");
|
|
||||||
expect(name).toMatch(/^\S+$/);
|
expect(name).toMatch(/^\S+$/);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -62,6 +63,15 @@ describe("skill commands", () => {
|
|||||||
expect(result).toContain("uwf");
|
expect(result).toContain("uwf");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("skill actor returns non-empty markdown string", () => {
|
||||||
|
const result = cmdSkillActor();
|
||||||
|
expect(typeof result).toBe("string");
|
||||||
|
expect(result).toContain("frontmatter");
|
||||||
|
expect(result).toContain("CAS");
|
||||||
|
expect(result).toContain("status");
|
||||||
|
expect(result.length).toBeGreaterThan(200);
|
||||||
|
});
|
||||||
|
|
||||||
test("skill help subcommand is suppressed", () => {
|
test("skill help subcommand is suppressed", () => {
|
||||||
const output = execFileSync("bun", ["src/cli.ts", "skill", "--help"], {
|
const output = execFileSync("bun", ["src/cli.ts", "skill", "--help"], {
|
||||||
cwd: join(__dirname, "..", ".."),
|
cwd: join(__dirname, "..", ".."),
|
||||||
@@ -73,6 +83,7 @@ describe("skill commands", () => {
|
|||||||
expect(output).toContain("architecture");
|
expect(output).toContain("architecture");
|
||||||
expect(output).toContain("yaml");
|
expect(output).toContain("yaml");
|
||||||
expect(output).toContain("moderator");
|
expect(output).toContain("moderator");
|
||||||
|
expect(output).toContain("actor");
|
||||||
expect(output).toContain("list");
|
expect(output).toContain("list");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import { cmdConfigGet, cmdConfigList, cmdConfigSet } from "./commands/config.js"
|
|||||||
import { cmdLogClean, cmdLogList, cmdLogShow } from "./commands/log.js";
|
import { cmdLogClean, cmdLogList, cmdLogShow } from "./commands/log.js";
|
||||||
import { cmdSetup, cmdSetupInteractive } from "./commands/setup.js";
|
import { cmdSetup, cmdSetupInteractive } from "./commands/setup.js";
|
||||||
import {
|
import {
|
||||||
|
cmdSkillActor,
|
||||||
cmdSkillArchitecture,
|
cmdSkillArchitecture,
|
||||||
cmdSkillCli,
|
cmdSkillCli,
|
||||||
cmdSkillList,
|
cmdSkillList,
|
||||||
@@ -503,6 +504,13 @@ skill
|
|||||||
console.log(cmdSkillYaml());
|
console.log(cmdSkillYaml());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
skill
|
||||||
|
.command("actor")
|
||||||
|
.description("Print the actor reference (frontmatter protocol + CAS)")
|
||||||
|
.action(() => {
|
||||||
|
console.log(cmdSkillActor());
|
||||||
|
});
|
||||||
|
|
||||||
skill
|
skill
|
||||||
.command("moderator")
|
.command("moderator")
|
||||||
.description("Print the moderator reference")
|
.description("Print the moderator reference")
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
export {
|
export {
|
||||||
|
generateActorReference as cmdSkillActor,
|
||||||
generateArchitectureReference as cmdSkillArchitecture,
|
generateArchitectureReference as cmdSkillArchitecture,
|
||||||
generateCliReference as cmdSkillCli,
|
generateCliReference as cmdSkillCli,
|
||||||
generateModeratorReference as cmdSkillModerator,
|
generateModeratorReference as cmdSkillModerator,
|
||||||
generateYamlReference as cmdSkillYaml,
|
generateYamlReference as cmdSkillYaml,
|
||||||
} from "@uncaged/workflow-util";
|
} from "@uncaged/workflow-util";
|
||||||
|
|
||||||
const SKILL_NAMES = ["cli", "architecture", "yaml", "moderator"] as const;
|
const SKILL_NAMES = ["cli", "architecture", "yaml", "moderator", "actor"] as const;
|
||||||
|
|
||||||
export function cmdSkillList(): ReadonlyArray<string> {
|
export function cmdSkillList(): ReadonlyArray<string> {
|
||||||
return [...SKILL_NAMES];
|
return [...SKILL_NAMES];
|
||||||
|
|||||||
@@ -0,0 +1,68 @@
|
|||||||
|
export function generateActorReference(): string {
|
||||||
|
return `# Actor Reference
|
||||||
|
|
||||||
|
You are executing a workflow role. Your system prompt defines your goal, procedure, and output requirements. This reference covers two things you need to know about the workflow engine.
|
||||||
|
|
||||||
|
## 1. Frontmatter Output Protocol
|
||||||
|
|
||||||
|
Your response **MUST** begin with a YAML frontmatter block at byte position 0 — no preamble text before it.
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
---
|
||||||
|
status: done
|
||||||
|
myField: some value
|
||||||
|
---
|
||||||
|
|
||||||
|
... markdown body (your work, explanation, notes) ...
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Standard Field
|
||||||
|
|
||||||
|
| Field | Values | Default | Description |
|
||||||
|
|-------|--------|---------|-------------|
|
||||||
|
| \`status\` | \`done\`, \`needs_input\`, \`in_progress\`, \`failed\` | \`done\` | Completion signal — determines which graph edge the moderator follows next |
|
||||||
|
|
||||||
|
### Schema-Defined Fields
|
||||||
|
|
||||||
|
Your role's output schema (shown in the system prompt under "Deliverable Format") defines additional fields. Output **only** the fields listed there — do not invent extra fields.
|
||||||
|
|
||||||
|
### Body
|
||||||
|
|
||||||
|
Everything after the closing \`---\` fence is the markdown body. Use it for explanations, logs, or human-readable notes. The body is stored but not parsed by the engine.
|
||||||
|
|
||||||
|
### Retry
|
||||||
|
|
||||||
|
If the engine cannot parse your frontmatter, it will ask you to retry (up to 2 times). Just output the corrected frontmatter block — don't panic.
|
||||||
|
|
||||||
|
## 2. CAS (Content-Addressable Store)
|
||||||
|
|
||||||
|
Your frontmatter output is automatically stored in CAS. You can also **use CAS directly** to store intermediate artifacts, build merkle DAGs for large outputs, or reference data from previous steps.
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
uwf cas put-text <text> # store plain text, print hash
|
||||||
|
uwf cas put <type-hash> <json> # store typed JSON data, print hash
|
||||||
|
uwf cas get <hash> # read a CAS node (type + payload)
|
||||||
|
uwf cas has <hash> # check if a hash exists
|
||||||
|
uwf cas refs <hash> # list direct references from a node
|
||||||
|
uwf cas walk <hash> # recursive traversal from a node
|
||||||
|
uwf cas schema list # list registered schemas
|
||||||
|
uwf cas schema get <hash> # show a schema definition
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
### Merkle DAG Pattern
|
||||||
|
|
||||||
|
For large outputs, store parts individually and reference their hashes:
|
||||||
|
|
||||||
|
\`\`\`bash
|
||||||
|
# Store individual sections
|
||||||
|
HASH1=$(uwf cas put-text "section 1 content")
|
||||||
|
HASH2=$(uwf cas put-text "section 2 content")
|
||||||
|
|
||||||
|
# Reference hashes in your frontmatter or in a parent node
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
This enables progressive loading — consumers can fetch the root and resolve children on demand.
|
||||||
|
`;
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
export { generateActorReference } from "./actor-reference.js";
|
||||||
export { generateArchitectureReference } from "./architecture-reference.js";
|
export { generateArchitectureReference } from "./architecture-reference.js";
|
||||||
export { encodeUint64AsCrockford } from "./base32.js";
|
export { encodeUint64AsCrockford } from "./base32.js";
|
||||||
export { generateCliReference } from "./cli-reference.js";
|
export { generateCliReference } from "./cli-reference.js";
|
||||||
|
|||||||
Reference in New Issue
Block a user