小橘 🍊(NEKO Team) 70fd064bad Refactor workflows to use compileWorkflowSpec from nerve-daemon
Remove workflows/_shared; wire createLlmExtractFn, zodMeta, and createCursorAdapter(mode ask). Plan/implement/publish compile inner specs via daemon.

Made-with: Cursor
2026-04-29 09:35:13 +00:00

98 lines
3.4 KiB
TypeScript

import type {
Schema,
StartStep,
WorkflowContext,
WorkflowDefinition,
WorkflowMessage,
WorkflowSpec,
} from "@uncaged/nerve-core";
import { END } from "@uncaged/nerve-core";
import { compileWorkflowSpec, type CompileWorkflowSpecDeps } from "@uncaged/nerve-daemon";
import { hermesAdapter } from "@uncaged/nerve-adapter-hermes";
import type { LlmProvider } from "@uncaged/nerve-workflow-utils";
import { createLlmExtractFn, zodMeta } from "@uncaged/nerve-workflow-utils";
import { moderator } from "./moderator.js";
import type { WorkflowMeta } from "./moderator.js";
import { buildImplementRole } from "./roles/implement/index.js";
import { buildPlanRole } from "./roles/plan/index.js";
import { prepareMetaSchema } from "./roles/prepare/index.js";
import { preparePrompt } from "./roles/prepare/prompt.js";
import { buildPublishRole } from "./roles/publish/index.js";
import { readIssueMetaSchema } from "./roles/read-issue/index.js";
import { readIssuePrompt } from "./roles/read-issue/prompt.js";
import { reviewMetaSchema } from "./roles/review/index.js";
import { reviewPrompt } from "./roles/review/prompt.js";
import { testMetaSchema } from "./roles/test/index.js";
import { testPrompt } from "./roles/test/prompt.js";
export type BuildSolveIssueDeps = {
nerveRoot: string;
provider: LlmProvider;
};
type SolveHermesAgentMeta = Pick<WorkflowMeta, "read-issue" | "prepare" | "review" | "test">;
function defaultAgentCreateContext(
workdir: string,
): (start: StartStep, messages: WorkflowMessage[]) => WorkflowContext {
return (start, messages) => ({
start,
messages,
workdir,
signal: new AbortController().signal,
});
}
export function buildSolveIssue({ nerveRoot, provider }: BuildSolveIssueDeps): WorkflowDefinition<WorkflowMeta> {
const compileDeps: CompileWorkflowSpecDeps = {
extractFn: async <T>(raw: string, schema: Schema<T>, dryRun: boolean) =>
createLlmExtractFn<T>({ provider, dryRun })(raw, schema),
createContext: defaultAgentCreateContext(nerveRoot),
};
const agentSpec: WorkflowSpec<SolveHermesAgentMeta> = {
name: "solve-issue",
roles: {
"read-issue": {
adapter: hermesAdapter,
prompt: async (start: StartStep) => readIssuePrompt({ threadId: start.meta.threadId }),
meta: zodMeta(readIssueMetaSchema),
},
prepare: {
adapter: hermesAdapter,
prompt: async (start: StartStep) => preparePrompt({ threadId: start.meta.threadId }),
meta: zodMeta(prepareMetaSchema),
},
review: {
adapter: hermesAdapter,
prompt: async (start: StartStep) =>
reviewPrompt({ threadId: start.meta.threadId, nerveRoot }),
meta: zodMeta(reviewMetaSchema),
},
test: {
adapter: hermesAdapter,
prompt: async (start: StartStep) => testPrompt({ threadId: start.meta.threadId }),
meta: zodMeta(testMetaSchema),
},
},
moderator: () => END,
};
const compiled = compileWorkflowSpec(agentSpec, compileDeps);
return {
name: "solve-issue",
roles: {
"read-issue": compiled.roles["read-issue"],
prepare: compiled.roles.prepare,
plan: buildPlanRole({ provider, nerveRoot }),
implement: buildImplementRole({ provider, nerveRoot }),
review: compiled.roles.review,
test: compiled.roles.test,
publish: buildPublishRole({ provider, nerveRoot }),
},
moderator,
};
}