The previous commit incorrectly deleted all workflows. Only restart-gateway should be removed (replaced by direct shell trigger). Other workflows (solve-issue, extract-knowledge, develop-sense, develop-workflow) are CLI-triggered and independent of sense coupling.
94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import type { AgentFn, Role, ThreadContext, WorkflowMessage } from "@uncaged/nerve-core";
|
|
import type { LlmExtractorConfig } from "@uncaged/nerve-workflow-utils";
|
|
import { createRole } from "@uncaged/nerve-workflow-utils";
|
|
import { z } from "zod";
|
|
|
|
import { resolveWorkdir } from "../lib/workdir.js";
|
|
|
|
import type { AnswererMeta } from "./answerer.js";
|
|
import type { QuestionerMeta } from "./questioner.js";
|
|
|
|
export const explorerMetaSchema = z.object({
|
|
patches: z.array(
|
|
z.object({
|
|
card: z.string(),
|
|
section: z.string(),
|
|
}),
|
|
),
|
|
new_cards: z.array(z.string()),
|
|
});
|
|
|
|
export type ExplorerMeta = z.infer<typeof explorerMetaSchema>;
|
|
|
|
export type CreateExplorerRoleDeps = {
|
|
extract: LlmExtractorConfig;
|
|
};
|
|
|
|
function lastMeta<M>(messages: WorkflowMessage[], role: string): M | undefined {
|
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
if (messages[i].role === role) {
|
|
return messages[i].meta as M;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function explorerPrompt(ctx: ThreadContext): string {
|
|
const messages = ctx.steps as unknown as WorkflowMessage[];
|
|
const threadId = ctx.start.meta.threadId;
|
|
const qm = lastMeta<QuestionerMeta>(messages, "questioner");
|
|
const am = lastMeta<AnswererMeta>(messages, "answerer");
|
|
const cwd = resolveWorkdir(ctx.start);
|
|
|
|
const unanswered =
|
|
am?.results.filter((r) => !r.found).map((r) => r.id) ?? [];
|
|
|
|
return `You are the **explorer** in an extract-knowledge workflow.
|
|
|
|
## Context
|
|
|
|
- Thread: \`nerve thread ${threadId}\`
|
|
- Working directory (repo root for paths): ${cwd}
|
|
- Current knowledge card (questioner): ${qm?.card ?? "(unknown)"}
|
|
|
|
## Unanswered question ids
|
|
|
|
${JSON.stringify(unanswered)}
|
|
|
|
Use the prior answerer results in the thread to map ids to full question text when you read messages above.
|
|
|
|
## Task
|
|
|
|
For each unanswered question, **read the codebase** as needed, then either:
|
|
|
|
- Add a new markdown file under \`.knowledge/\`, or
|
|
- Patch an existing card (prefer updating the card listed above when appropriate).
|
|
|
|
After any write or patch to \`.knowledge\`, run:
|
|
|
|
\`\`\`bash
|
|
nerve knowledge sync
|
|
\`\`\`
|
|
|
|
from this repo root (${cwd}), and fix failures until sync succeeds.
|
|
|
|
## Output meta
|
|
|
|
Report \`patches\` as { card, section } entries for cards you edited (section is a short heading or path hint).
|
|
Report \`new_cards\` as repo-relative paths for brand-new files you created (e.g. \`.knowledge/new-topic.md\`).
|
|
|
|
Do not claim work you did not perform.`;
|
|
}
|
|
|
|
export function createExplorerRole(
|
|
adapter: AgentFn,
|
|
{ extract }: CreateExplorerRoleDeps,
|
|
): Role<ExplorerMeta> {
|
|
return createRole(
|
|
adapter,
|
|
async (ctx: ThreadContext) => explorerPrompt(ctx),
|
|
explorerMetaSchema,
|
|
extract,
|
|
);
|
|
}
|