fix(agent-claude-code): use buildContinuationPrompt for step context
Replace custom buildHistorySummary with shared buildContinuationPrompt
from workflow-agent-kit. This aligns claude-code agent with hermes agent:
- First visit: includes step content (within 32k quota)
- Re-entry: shows only steps since last visit (meta only, session has context)
Previously developer could not see reviewer's detailed feedback on
re-entry, only {"approved":false}. Now gets full review text.
Fixes #486
This commit is contained in:
@@ -39,7 +39,7 @@ describe("buildClaudeCodePrompt", () => {
|
|||||||
expect(result).toContain("## Task\nFix the bug");
|
expect(result).toContain("## Task\nFix the bug");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("includes previous steps as history summary", () => {
|
test("includes previous steps with content on first visit", () => {
|
||||||
const ctx = makeCtx({
|
const ctx = makeCtx({
|
||||||
steps: [
|
steps: [
|
||||||
{
|
{
|
||||||
@@ -48,18 +48,50 @@ describe("buildClaudeCodePrompt", () => {
|
|||||||
agent: "hermes",
|
agent: "hermes",
|
||||||
detail: "detail-1",
|
detail: "detail-1",
|
||||||
edgePrompt: "Create a plan.",
|
edgePrompt: "Create a plan.",
|
||||||
|
content: "Here is my detailed plan for doing X.",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
const result = buildClaudeCodePrompt(ctx);
|
const result = buildClaudeCodePrompt(ctx);
|
||||||
expect(result).toContain("## Previous Steps");
|
expect(result).toContain("## What Happened Since Your Last Turn");
|
||||||
expect(result).toContain("Step 1: planner");
|
expect(result).toContain("Step 1: planner");
|
||||||
expect(result).toContain("do X");
|
expect(result).toContain("do X");
|
||||||
|
// First visit should include step content
|
||||||
|
expect(result).toContain("Here is my detailed plan for doing X.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("re-entry shows steps since last visit without content", () => {
|
||||||
|
const ctx = makeCtx({
|
||||||
|
isFirstVisit: false,
|
||||||
|
steps: [
|
||||||
|
{
|
||||||
|
role: "developer",
|
||||||
|
output: '{"status":"done"}',
|
||||||
|
agent: "claude-code",
|
||||||
|
detail: "detail-1",
|
||||||
|
edgePrompt: "Implement.",
|
||||||
|
content: "I implemented everything.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
role: "reviewer",
|
||||||
|
output: '{"approved":false}',
|
||||||
|
agent: "claude-code",
|
||||||
|
detail: "detail-2",
|
||||||
|
edgePrompt: "Review.",
|
||||||
|
content: "Rejected: complexity too high, refactor cmdStepRead.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const result = buildClaudeCodePrompt(ctx);
|
||||||
|
expect(result).toContain("## What Happened Since Your Last Turn");
|
||||||
|
expect(result).toContain("reviewer");
|
||||||
|
expect(result).toContain("approved");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("omits history section when steps array is empty", () => {
|
test("omits history section when steps array is empty", () => {
|
||||||
const result = buildClaudeCodePrompt(makeCtx({ steps: [] }));
|
const result = buildClaudeCodePrompt(makeCtx({ steps: [] }));
|
||||||
expect(result).not.toContain("## Previous Steps");
|
expect(result).not.toContain("## What Happened Since Your Last Turn");
|
||||||
|
expect(result).toContain("## Current Instruction");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("works without outputFormatInstruction", () => {
|
test("works without outputFormatInstruction", () => {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type { Store } from "@uncaged/json-cas";
|
|||||||
import {
|
import {
|
||||||
type AgentContext,
|
type AgentContext,
|
||||||
type AgentRunResult,
|
type AgentRunResult,
|
||||||
|
buildContinuationPrompt,
|
||||||
buildRolePrompt,
|
buildRolePrompt,
|
||||||
createAgent,
|
createAgent,
|
||||||
getCachedSessionId,
|
getCachedSessionId,
|
||||||
@@ -18,25 +19,6 @@ const CLAUDE_COMMAND = "claude";
|
|||||||
const CLAUDE_MAX_TURNS = 90;
|
const CLAUDE_MAX_TURNS = 90;
|
||||||
const CLAUDE_MODEL = process.env.CLAUDE_MODEL ?? null;
|
const CLAUDE_MODEL = process.env.CLAUDE_MODEL ?? null;
|
||||||
|
|
||||||
function buildHistorySummary(steps: AgentContext["steps"]): string {
|
|
||||||
if (steps.length === 0) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
const lines: string[] = ["## Previous Steps"];
|
|
||||||
for (let i = 0; i < steps.length; i++) {
|
|
||||||
const step = steps[i];
|
|
||||||
if (step === undefined) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
lines.push("");
|
|
||||||
lines.push(`### Step ${i + 1}: ${step.role}`);
|
|
||||||
lines.push(`Output: ${JSON.stringify(step.output)}`);
|
|
||||||
lines.push(`Agent: ${step.agent}`);
|
|
||||||
}
|
|
||||||
return lines.join("\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Assemble system prompt, task, and prior step outputs for Claude Code. */
|
/** Assemble system prompt, task, and prior step outputs for Claude Code. */
|
||||||
export function buildClaudeCodePrompt(ctx: AgentContext): string {
|
export function buildClaudeCodePrompt(ctx: AgentContext): string {
|
||||||
const roleDef = ctx.workflow.roles[ctx.role];
|
const roleDef = ctx.workflow.roles[ctx.role];
|
||||||
@@ -46,11 +28,23 @@ export function buildClaudeCodePrompt(ctx: AgentContext): string {
|
|||||||
parts.push(ctx.outputFormatInstruction, "");
|
parts.push(ctx.outputFormatInstruction, "");
|
||||||
}
|
}
|
||||||
parts.push(rolePrompt, "", "## Task", ctx.start.prompt);
|
parts.push(rolePrompt, "", "## Task", ctx.start.prompt);
|
||||||
const historyBlock = buildHistorySummary(ctx.steps);
|
|
||||||
if (historyBlock !== "") {
|
if (!ctx.isFirstVisit) {
|
||||||
parts.push("", historyBlock);
|
// Re-entry (session will be resumed): show only steps since last visit, meta only
|
||||||
|
parts.push("", buildContinuationPrompt(ctx.steps, ctx.role, ctx.edgePrompt));
|
||||||
|
} else if (ctx.steps.length > 0) {
|
||||||
|
// First visit: show all steps with content for recent ones
|
||||||
|
parts.push(
|
||||||
|
"",
|
||||||
|
buildContinuationPrompt(ctx.steps, ctx.role, ctx.edgePrompt, {
|
||||||
|
includeContent: true,
|
||||||
|
quota: 32000,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
parts.push("", "## Current Instruction", "", ctx.edgePrompt);
|
||||||
}
|
}
|
||||||
parts.push("", "## Current Instruction", "", ctx.edgePrompt);
|
|
||||||
return parts.join("\n");
|
return parts.join("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user