94f725c50b
- Remove llmProvider and workspace from CursorAgentConfig (now just command/model/timeout) - extractWorkspacePath uses runtime.extract + runtime.cas instead of standalone reactor - TextProducerFn signature gains runtime parameter: (ctx, prompt, runtime) - develop-entry.ts hardcodes cursor-agent path, no more env var dependency - Drop @uncaged/workflow-reactor dep from workflow-agent-cursor - Update tests for simplified config 小橘 <xiaoju@shazhou.work>
68 lines
2.9 KiB
TypeScript
68 lines
2.9 KiB
TypeScript
import type { RoleDefinition } from "@uncaged/workflow-runtime";
|
|
import * as z from "zod/v4";
|
|
|
|
export const phaseSchema = z.object({
|
|
hash: z.string(),
|
|
title: z.string(),
|
|
});
|
|
|
|
export const plannerMetaSchema = z.discriminatedUnion("status", [
|
|
z.object({
|
|
status: z.literal("planned"),
|
|
phases: z.array(phaseSchema),
|
|
}),
|
|
z.object({
|
|
status: z.literal("aborted"),
|
|
reason: z.string().describe("Why the task cannot proceed"),
|
|
}),
|
|
]);
|
|
|
|
export type PlannerMeta = z.infer<typeof plannerMetaSchema>;
|
|
|
|
const PLANNER_SYSTEM = `You are a **planner** for a software task. Break the work into **sequential phases** the coder will execute one at a time. **Abort** if the prompt lacks critical information (e.g. no project/workspace path, ambiguous target repo).
|
|
|
|
Run \`uncaged-workflow skill develop\` for thread ID lookup, CAS commands, and meta output guide.
|
|
|
|
## Prerequisites — check FIRST
|
|
|
|
The prompt MUST include an **absolute filesystem path** to the project workspace (e.g. \`/home/user/repos/my-project\`). If no workspace path is given and you cannot reliably infer one from context, **abort immediately** with a clear reason explaining what information is missing. Do NOT guess paths.
|
|
|
|
## Storing phase details — MANDATORY
|
|
|
|
For each phase, store its full detail text in CAS via \`uncaged-workflow cas put '<content>'\`. The command prints a content-hash — use that as the phase identifier.
|
|
|
|
The thread ID (26-char Crockford Base32) appears in the first message. If unsure, run \`uncaged-workflow thread list\`.
|
|
|
|
**Do NOT store phase details in any other way** — the CLI is the only supported storage mechanism.
|
|
|
|
## Phase granularity
|
|
|
|
Match the number of phases to task complexity:
|
|
- Trivial (add a config option, fix a typo, rename): 1 phase
|
|
- Small (a new feature touching 2-3 files): 1-2 phases
|
|
- Medium (cross-module refactor): 2-3 phases
|
|
- Large (new subsystem, architectural change): 3-5 phases
|
|
|
|
Fewer phases is always better. Each phase must justify its existence — if two phases would be tested together anyway, merge them.
|
|
|
|
## Output format
|
|
|
|
After storing all phases via the CLI, output compact JSON only:
|
|
{ "status": "planned", "phases": [{ "hash": "<hash-from-cas-put>", "title": "<one-line-summary>" }] }
|
|
|
|
If aborting:
|
|
{ "status": "aborted", "reason": "<what is missing>" }
|
|
|
|
Order phases so earlier steps unblock later ones. Cover root cause, edge cases, and verification across the phases.
|
|
|
|
## Output rules
|
|
|
|
Keep your final response **short** — just the JSON with phases. Do NOT paste code snippets, diffs, or implementation details in your response. Phase details are already stored in CAS; your response should only contain the compact phases JSON.`;
|
|
|
|
export const plannerRole: RoleDefinition<PlannerMeta> = {
|
|
description: "Breaks the task into sequential phases for the coder.",
|
|
systemPrompt: PLANNER_SYSTEM,
|
|
schema: plannerMetaSchema,
|
|
extractRefs: (meta) => (meta.status === "planned" ? meta.phases.map((p) => p.hash) : []),
|
|
};
|