Remove workflows/_shared; wire createLlmExtractFn, zodMeta, and createCursorAdapter(mode ask). Plan/implement/publish compile inner specs via daemon. Made-with: Cursor
110 lines
3.5 KiB
TypeScript
110 lines
3.5 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 { createCursorAdapter } from "@uncaged/nerve-adapter-cursor";
|
|
import { hermesAdapter } from "@uncaged/nerve-adapter-hermes";
|
|
import type { LlmProvider } from "@uncaged/nerve-workflow-utils";
|
|
import { createLlmExtractFn, zodMeta } from "@uncaged/nerve-workflow-utils";
|
|
|
|
import { coderPrompt } from "./roles/coder/prompt.js";
|
|
import { coderMetaSchema } from "./roles/coder/index.js";
|
|
import { plannerPrompt } from "./roles/planner/prompt.js";
|
|
import { plannerMetaSchema } from "./roles/planner/index.js";
|
|
import { reviewerPrompt } from "./roles/reviewer/prompt.js";
|
|
import { reviewerMetaSchema } from "./roles/reviewer/index.js";
|
|
import { testerPrompt } from "./roles/tester/prompt.js";
|
|
import { testerMetaSchema } from "./roles/tester/index.js";
|
|
import { buildCommitterRole } from "./roles/committer/index.js";
|
|
import { moderator } from "./moderator.js";
|
|
import type { SenseMeta } from "./moderator.js";
|
|
|
|
export type BuildSenseGeneratorDeps = {
|
|
provider: LlmProvider;
|
|
cwd: string;
|
|
};
|
|
|
|
const CURSOR_TIMEOUT_MS = 300_000;
|
|
|
|
type SenseAgentMeta = Pick<SenseMeta, "planner" | "coder" | "reviewer" | "tester">;
|
|
|
|
function defaultAgentCreateContext(
|
|
workdir: string,
|
|
): (start: StartStep, messages: WorkflowMessage[]) => WorkflowContext {
|
|
return (start, messages) => ({
|
|
start,
|
|
messages,
|
|
workdir,
|
|
signal: new AbortController().signal,
|
|
});
|
|
}
|
|
|
|
export function buildSenseGenerator({
|
|
provider,
|
|
cwd,
|
|
}: BuildSenseGeneratorDeps): WorkflowDefinition<SenseMeta> {
|
|
const compileDeps: CompileWorkflowSpecDeps = {
|
|
extractFn: async <T>(raw: string, schema: Schema<T>, dryRun: boolean) =>
|
|
createLlmExtractFn<T>({ provider, dryRun })(raw, schema),
|
|
createContext: defaultAgentCreateContext(cwd),
|
|
};
|
|
|
|
const agentSpec: WorkflowSpec<SenseAgentMeta> = {
|
|
name: "develop-sense",
|
|
roles: {
|
|
planner: {
|
|
adapter: createCursorAdapter({
|
|
type: "cursor",
|
|
model: "auto",
|
|
timeout: CURSOR_TIMEOUT_MS,
|
|
mode: "ask",
|
|
}),
|
|
prompt: async (start: StartStep) => plannerPrompt({ threadId: start.meta.threadId }),
|
|
meta: zodMeta(plannerMetaSchema),
|
|
},
|
|
coder: {
|
|
adapter: createCursorAdapter({
|
|
type: "cursor",
|
|
model: "auto",
|
|
timeout: CURSOR_TIMEOUT_MS,
|
|
}),
|
|
prompt: async (start: StartStep) => coderPrompt({ threadId: start.meta.threadId }),
|
|
meta: zodMeta(coderMetaSchema),
|
|
},
|
|
reviewer: {
|
|
adapter: hermesAdapter,
|
|
prompt: async (start: StartStep) =>
|
|
reviewerPrompt({ threadId: start.meta.threadId, nerveRoot: cwd }),
|
|
meta: zodMeta(reviewerMetaSchema),
|
|
},
|
|
tester: {
|
|
adapter: hermesAdapter,
|
|
prompt: async (start: StartStep) =>
|
|
testerPrompt({ threadId: start.meta.threadId, nerveRoot: cwd }),
|
|
meta: zodMeta(testerMetaSchema),
|
|
},
|
|
},
|
|
moderator: () => END,
|
|
};
|
|
|
|
const compiled = compileWorkflowSpec(agentSpec, compileDeps);
|
|
|
|
return {
|
|
name: "develop-sense",
|
|
roles: {
|
|
planner: compiled.roles.planner,
|
|
coder: compiled.roles.coder,
|
|
reviewer: compiled.roles.reviewer,
|
|
tester: compiled.roles.tester,
|
|
committer: buildCommitterRole({ nerveRoot: cwd }),
|
|
},
|
|
moderator,
|
|
};
|
|
}
|