refactor: all-agentic architecture — roles as pure data, agent binding at runtime

BREAKING: Major architecture change.

- RoleDefinition = pure data (systemPrompt + schema + dryRunMeta)
- AgentFn = (ctx: ThreadContext) => Promise<string>, reads ctx.currentRole
- WorkflowDefinition decoupled from agents, bound via AgentBinding at runtime
- createWorkflow(def, binding, extract) replaces createRoleModerator
- Meta extraction moved into engine loop
- Delete workflow-util-role package (createRole, decorators, extract all gone)
- Role packages become pure data exports
- Agent packages updated to single-arg AgentFn

小橘 <xiaoju@shazhou.work>
This commit is contained in:
2026-05-06 14:14:33 +00:00
parent fce2bf7441
commit fa9163e462
52 changed files with 434 additions and 1565 deletions
@@ -10,8 +10,6 @@
},
"dependencies": {
"@uncaged/workflow": "workspace:*",
"@uncaged/workflow-agent-llm": "workspace:*",
"@uncaged/workflow-util-role": "workspace:*",
"zod": "^4.0.0"
}
}
+14 -40
View File
@@ -1,6 +1,4 @@
import type { AgentFn, Role } from "@uncaged/workflow";
import { createRole } from "@uncaged/workflow-agent-llm";
import type { LlmProvider } from "@uncaged/workflow-util-role";
import type { RoleDefinition } from "@uncaged/workflow";
import * as z from "zod/v4";
export const coderMetaSchema = z.object({
@@ -11,41 +9,17 @@ export const coderMetaSchema = z.object({
export type CoderMeta = z.infer<typeof coderMetaSchema>;
export type CoderConfig = {
cwd: string;
const CODER_SYSTEM = `You are a **coder**. Read the thread for the plan and work on the NEXT incomplete phase only.
Report which phase you completed. List the files you changed and summarize what you did.`;
export const coderRole: RoleDefinition<CoderMeta> = {
description:
"Implements the next incomplete planner phase and reports structured completion metadata.",
systemPrompt: CODER_SYSTEM,
schema: coderMetaSchema,
dryRunMeta: {
completedPhase: "phase-1",
filesChanged: [],
summary: "",
},
};
export const DEFAULT_CODER_CONFIG: CoderConfig = {
cwd: ".",
};
function coderSystemPrompt(config: CoderConfig): string {
return `You are a **coder**. The project is at \`${config.cwd}\`.
Read the thread: the planner produced ordered **phases**. Identify the **next** phase that is not yet completed according to prior coder steps (each coder step reports a completedPhase).
Implement **only that phase** — do not tackle multiple phases in one turn unless the planner defined a single phase. Follow project conventions; summarize what changed and list touched files.
When done with the phase you worked on, set **completedPhase** to that phase's **name** exactly as given by the planner.`;
}
/**
* Coder role: implements the next incomplete planner phase and reports structured completion metadata.
*/
export function createCoderRole(
adapter: AgentFn,
extract: { provider: LlmProvider; dryRun: boolean | null; dryRunMeta: CoderMeta },
config: CoderConfig = DEFAULT_CODER_CONFIG,
): Role<CoderMeta> {
return createRole({
name: "coder",
schema: coderMetaSchema,
systemPrompt: coderSystemPrompt(config),
agent: adapter,
extract: {
provider: extract.provider,
dryRun: extract.dryRun,
dryRunMeta: extract.dryRunMeta,
},
});
}
+1 -7
View File
@@ -1,7 +1 @@
export {
type CoderConfig,
type CoderMeta,
coderMetaSchema,
createCoderRole,
DEFAULT_CODER_CONFIG,
} from "./coder.js";
export { type CoderMeta, coderMetaSchema, coderRole } from "./coder.js";
+1 -5
View File
@@ -6,9 +6,5 @@
"composite": true
},
"include": ["src/**/*.ts"],
"references": [
{ "path": "../workflow" },
{ "path": "../workflow-agent-llm" },
{ "path": "../workflow-util-role" }
]
"references": [{ "path": "../workflow" }]
}