docs(rfc-001): WorkflowFn input → ThreadInput for fork/resume support
- First param is now { prompt, steps } instead of bare prompt
- steps: [] for new thread, pre-filled for fork/resume
- createRoleModerator naturally handles resume via moderator routing
- No special replay logic needed
小橘 <xiaoju@shazhou.work>
This commit is contained in:
@@ -35,21 +35,11 @@ describe("cli workflow commands", () => {
|
||||
bundlePath,
|
||||
`import fs from "node:fs";
|
||||
|
||||
export default {
|
||||
name: "solve-issue",
|
||||
roles: {
|
||||
noop: async () => {
|
||||
fs.existsSync(".");
|
||||
return { content: "ok", meta: { done: true } };
|
||||
},
|
||||
},
|
||||
moderator(ctx) {
|
||||
if (ctx.steps.length === 0) {
|
||||
return "noop";
|
||||
}
|
||||
return "__end__";
|
||||
},
|
||||
};
|
||||
export default async function* () {
|
||||
fs.existsSync(".");
|
||||
yield { role: "noop", content: "ok", meta: { done: true } };
|
||||
return { returnCode: 0, summary: "done" };
|
||||
}
|
||||
`,
|
||||
"utf8",
|
||||
);
|
||||
@@ -91,7 +81,7 @@ export default {
|
||||
const bundlePath = join(storageRoot, "bad.esm.js");
|
||||
await writeFile(
|
||||
bundlePath,
|
||||
'import x from "./local";\nexport default async function run() { return { returnCode: 0, summary: "" }; }\n',
|
||||
'import x from "./local";\nexport default async function* run() { return { returnCode: 0, summary: "" }; }\n',
|
||||
"utf8",
|
||||
);
|
||||
const r = await cmdAdd(storageRoot, "solve-issue", bundlePath);
|
||||
|
||||
@@ -13,54 +13,29 @@ import { cmdThreadRemove, cmdThreadShow } from "../src/cmd-thread.js";
|
||||
import { cmdThreads } from "../src/cmd-threads.js";
|
||||
import { pathExists } from "../src/fs-utils.js";
|
||||
|
||||
const fastBundleSource = `export default {
|
||||
name: "solve-issue",
|
||||
roles: {
|
||||
planner: async () => ({ content: "plan", meta: { plan: "x" } }),
|
||||
coder: async () => ({ content: "code", meta: { diff: "y" } }),
|
||||
},
|
||||
moderator(ctx) {
|
||||
if (ctx.steps.length === 0) return "planner";
|
||||
if (ctx.steps.length === 1) return "coder";
|
||||
return "__end__";
|
||||
},
|
||||
};
|
||||
const fastBundleSource = `export default async function* () {
|
||||
yield { role: "planner", content: "plan", meta: { plan: "x" } };
|
||||
yield { role: "coder", content: "code", meta: { diff: "y" } };
|
||||
return { returnCode: 0, summary: "done" };
|
||||
}
|
||||
`;
|
||||
|
||||
const slowPlannerBundleSource = `export default {
|
||||
name: "solve-issue",
|
||||
roles: {
|
||||
planner: async () => {
|
||||
await new Promise((r) => setTimeout(r, 400));
|
||||
return { content: "plan", meta: { plan: "x" } };
|
||||
},
|
||||
coder: async () => ({ content: "code", meta: { diff: "y" } }),
|
||||
},
|
||||
moderator(ctx) {
|
||||
if (ctx.steps.length === 0) return "planner";
|
||||
if (ctx.steps.length === 1) return "coder";
|
||||
return "__end__";
|
||||
},
|
||||
};
|
||||
const slowPlannerBundleSource = `export default async function* () {
|
||||
await new Promise((r) => setTimeout(r, 400));
|
||||
yield { role: "planner", content: "plan", meta: { plan: "x" } };
|
||||
yield { role: "coder", content: "code", meta: { diff: "y" } };
|
||||
return { returnCode: 0, summary: "done" };
|
||||
}
|
||||
`;
|
||||
|
||||
const cliEntryPath = fileURLToPath(new URL("../src/cli.ts", import.meta.url));
|
||||
|
||||
const abortablePlannerBundleSource = `export default {
|
||||
name: "solve-issue",
|
||||
roles: {
|
||||
planner: async () => {
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
return { content: "plan", meta: { plan: "x" } };
|
||||
},
|
||||
coder: async () => ({ content: "code", meta: { diff: "y" } }),
|
||||
},
|
||||
moderator(ctx) {
|
||||
if (ctx.steps.length === 0) return "planner";
|
||||
if (ctx.steps.length === 1) return "coder";
|
||||
return "__end__";
|
||||
},
|
||||
};
|
||||
const abortablePlannerBundleSource = `export default async function* () {
|
||||
await new Promise((r) => setTimeout(r, 600));
|
||||
yield { role: "planner", content: "plan", meta: { plan: "x" } };
|
||||
yield { role: "coder", content: "code", meta: { diff: "y" } };
|
||||
return { returnCode: 0, summary: "done" };
|
||||
}
|
||||
`;
|
||||
|
||||
describe("cli thread commands", () => {
|
||||
|
||||
@@ -43,6 +43,7 @@ export async function cmdRun(
|
||||
const sent = await sendWorkerTcpCommand(worker.value.port, {
|
||||
type: "run",
|
||||
threadId,
|
||||
workflowName: name,
|
||||
prompt,
|
||||
options: { isDryRun, maxRounds },
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user