小橘 🍊(NEKO Team) 56ce22fb1b Migrate workflows to WorkflowSpec-style roles (RFC-003)
Replace createCursorRole/createHermesRole with adapter + prompt + zod meta.

Add shared compileRoleSpec, cursor ask adapter, nerve.yaml extract defaults.

Refs #248

Made-with: Cursor
2026-04-29 09:23:55 +00:00

68 lines
2.0 KiB
TypeScript

import type { Role, RoleResult, RoleSpec, StartStep, WorkflowMessage } from "@uncaged/nerve-core";
import { createCursorAdapter } from "@uncaged/nerve-adapter-cursor";
import type { LlmProvider } from "@uncaged/nerve-workflow-utils";
import { z } from "zod";
import { compileRoleSpec, zodMeta } from "../../../_shared/rfc003-compile.js";
import { resolveRepoCwd } from "../../lib/repo-context.js";
import { buildImplementPrompt } from "./prompt.js";
export const implementMetaSchema = z.object({
done: z.boolean().describe("true when changes are complete and build passes this round"),
});
export type ImplementMeta = z.infer<typeof implementMetaSchema>;
export type BuildImplementDeps = {
provider: LlmProvider;
nerveRoot: string;
};
const CURSOR_TIMEOUT_MS = 300_000;
export function buildImplementRole({ provider, nerveRoot }: BuildImplementDeps): Role<ImplementMeta> {
const innerSpec = {
adapter: createCursorAdapter({
type: "cursor",
model: "auto",
timeout: CURSOR_TIMEOUT_MS,
}),
prompt: async (start: StartStep) =>
buildImplementPrompt({
threadId: start.meta.threadId,
nerveRoot,
}),
meta: zodMeta(implementMetaSchema),
} satisfies RoleSpec<ImplementMeta>;
return async (start: StartStep, messages: WorkflowMessage[]): Promise<RoleResult<ImplementMeta>> => {
const cwd = resolveRepoCwd(messages);
if (cwd === null) {
return {
content: "implement cannot run: missing repo path in thread markers",
meta: { done: false },
};
}
const run = compileRoleSpec(innerSpec, {
provider,
createContext: (s, m) => ({
start: s,
messages: m,
workdir: cwd,
signal: new AbortController().signal,
}),
});
try {
return await run(start, messages);
} catch (e) {
const msg = e instanceof Error ? e.message : String(e);
return {
content: `implement failed: ${msg}`,
meta: { done: false },
};
}
};
}