import type { AgentFn, Role, StartStep } from "@uncaged/nerve-core"; import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils"; import { createRole } from "@uncaged/nerve-workflow-utils"; import { z } from "zod"; export const coderMetaSchema = z.object({ filesCreated: z.boolean().describe("true if the sense files were created"), }); export type CoderMeta = z.infer; export function coderPrompt({ threadId }: { threadId: string }): string { return `Read the workflow thread for the planner's sense design and any tester feedback: \`nerve thread ${threadId}\` Read the nerve-dev skill for sense file structure and conventions: \`cat node_modules/@uncaged/nerve-skills/nerve-dev/SKILL.md\` ## Your task Implement (or fix) the sense the planner designed. If there is tester feedback in the thread, fix the issues it identified. ## Multi-step approach You do NOT need to finish everything in one pass. You may return \`done: false\` to continue in the next iteration. ## File structure for each sense - \`senses//src/index.ts\` — TypeScript compute source; import schema as \`./schema.ts\` - \`senses//src/schema.ts\` — Drizzle schema (TypeScript) - \`senses//migrations/\` — Drizzle migration files (at sense root, not inside src/) - \`senses//package.json\` — with esbuild build script - \`senses//index.js\` — bundled output generated by \`pnpm build\` (do NOT edit by hand) Look at existing senses for the package.json template and patterns. ## When to return done: true Return \`done: true\` ONLY when ALL of the following are true: - All required files are created - \`pnpm install --no-cache && pnpm build\` succeeds (run it!) - \`nerve.yaml\` is updated with the sense config Return \`done: false\` if you made progress but there is still work to do.`; } export function createCoderRole(adapter: AgentFn, extract: LlmExtractorConfig): Role { return createRole( adapter, async (start: StartStep) => coderPrompt({ threadId: start.meta.threadId }), coderMetaSchema, extract, ); }