refactor: remove buildSenseExamples, use @uncaged/nerve-skills for agent discovery

- Delete buildSenseExamples() (~25 lines of runtime file reading)
- Remove senseExamples from BuildSenseGeneratorDeps and BuildPlannerDeps
- Planner prompt now directs agent to read nerve-dev skill via npm package
- Clean up unused existsSync import

Closes xiaoju/nerve-workspace#2
This commit is contained in:
小橘 2026-04-28 04:38:33 +00:00
parent 69eb4ffe49
commit fc2ca13dc3
4 changed files with 10 additions and 40 deletions

View File

@ -10,7 +10,6 @@ export type BuildSenseGeneratorDeps = {
provider: LlmProvider;
nerveRoot: string;
sensesDir: string;
senseExamples: string;
nerveYaml: string;
};
@ -18,13 +17,12 @@ export function buildSenseGenerator({
provider,
nerveRoot,
sensesDir,
senseExamples,
nerveYaml,
}: BuildSenseGeneratorDeps): WorkflowDefinition<SenseMeta> {
return {
name: "sense-generator",
roles: {
planner: buildPlannerRole({ provider, cwd: nerveRoot, senseExamples, nerveYaml }),
planner: buildPlannerRole({ provider, cwd: nerveRoot, nerveYaml }),
coder: buildCoderRole({ provider, cwd: nerveRoot, sensesDir, nerveRoot }),
tester: buildTesterRole({ provider, sensesDir, nerveRoot }),
},

View File

@ -1,4 +1,4 @@
import { existsSync, readFileSync } from "node:fs";
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { spawnSafe } from "@uncaged/nerve-workflow-utils";
import { buildSenseGenerator } from "./build.js";
@ -38,39 +38,12 @@ function getNerveYaml(): string {
}
}
function buildSenseExamples(): string {
const examples: string[] = [];
for (const name of ["cpu-usage", "linux-system-health"]) {
const dir = join(SENSES_DIR, name);
if (!existsSync(dir)) continue;
const indexFile = existsSync(join(dir, "index.js"))
? readFileSync(join(dir, "index.js"), "utf-8")
: "";
const schema = existsSync(join(dir, "schema.ts"))
? readFileSync(join(dir, "schema.ts"), "utf-8")
: "";
const migrationDir = join(dir, "migrations");
let migration = "";
if (existsSync(join(migrationDir, "0001_init.sql"))) {
migration = readFileSync(join(migrationDir, "0001_init.sql"), "utf-8");
}
examples.push(
`### Example sense: ${name}\n\n` +
`**index.js:**\n\`\`\`js\n${indexFile}\n\`\`\`\n\n` +
`**schema.ts:**\n\`\`\`ts\n${schema}\n\`\`\`\n\n` +
`**migrations/0001_init.sql:**\n\`\`\`sql\n${migration}\n\`\`\``,
);
}
return examples.join("\n\n---\n\n");
}
// --- Wire up ---
const workflow = buildSenseGenerator({
provider: { apiKey, baseUrl, model },
nerveRoot: NERVE_ROOT,
sensesDir: SENSES_DIR,
senseExamples: buildSenseExamples(),
nerveYaml: getNerveYaml(),
});

View File

@ -7,15 +7,14 @@ import { plannerPrompt } from "./prompt.js";
export type BuildPlannerDeps = {
provider: LlmProvider;
cwd: string;
senseExamples: string;
nerveYaml: string;
};
export function buildPlannerRole({ provider, cwd, senseExamples, nerveYaml }: BuildPlannerDeps) {
export function buildPlannerRole({ provider, cwd, nerveYaml }: BuildPlannerDeps) {
return createCursorRole<PlannerMeta>({
cwd,
mode: "ask",
prompt: async (threadId) => plannerPrompt({ threadId, senseExamples, nerveYaml }),
prompt: async (threadId) => plannerPrompt({ threadId, nerveYaml }),
extract: { provider, schema: plannerMetaSchema },
});
}

View File

@ -1,11 +1,10 @@
export function plannerPrompt(vars: {
export function plannerPrompt({ threadId, nerveYaml }: {
threadId: string;
senseExamples: string;
nerveYaml: string;
}): string {
return `You are planning a new Nerve sense.
Read the workflow thread for the user's request: \`nerve thread ${vars.threadId}\`
Read the workflow thread for the user's request: \`nerve thread ${threadId}\`
Pick a good kebab-case name for this sense. Produce a PLAN (not code) in markdown:
@ -15,12 +14,13 @@ Pick a good kebab-case name for this sense. Produce a PLAN (not code) in markdow
### Compute Logic step-by-step, specific Node.js APIs or shell commands
### Trigger Config group, interval, throttle, timeout
Reference senses:
${vars.senseExamples}
For reference examples of existing senses (schema, compute logic, migrations), read the nerve-dev skill:
\`cat node_modules/@uncaged/nerve-skills/nerve-dev/SKILL.md\`
Also look at existing senses in the \`senses/\` directory for patterns.
Current nerve.yaml:
\`\`\`yaml
${vars.nerveYaml}
${nerveYaml}
\`\`\`
Output ONLY the plan. Be precise and implementation-ready.`;