diff --git a/packages/workflow-agent-claude-code/__tests__/claude-code.test.ts b/packages/workflow-agent-claude-code/__tests__/claude-code.test.ts index 1b16939..32f1527 100644 --- a/packages/workflow-agent-claude-code/__tests__/claude-code.test.ts +++ b/packages/workflow-agent-claude-code/__tests__/claude-code.test.ts @@ -39,7 +39,7 @@ describe("buildClaudeCodePrompt", () => { 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({ steps: [ { @@ -48,18 +48,50 @@ describe("buildClaudeCodePrompt", () => { agent: "hermes", detail: "detail-1", edgePrompt: "Create a plan.", + content: "Here is my detailed plan for doing X.", }, ], }); 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("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", () => { 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", () => { diff --git a/packages/workflow-agent-claude-code/src/claude-code.ts b/packages/workflow-agent-claude-code/src/claude-code.ts index aa21e5a..52dc03b 100644 --- a/packages/workflow-agent-claude-code/src/claude-code.ts +++ b/packages/workflow-agent-claude-code/src/claude-code.ts @@ -3,6 +3,7 @@ import type { Store } from "@uncaged/json-cas"; import { type AgentContext, type AgentRunResult, + buildContinuationPrompt, buildRolePrompt, createAgent, getCachedSessionId, @@ -18,25 +19,6 @@ const CLAUDE_COMMAND = "claude"; const CLAUDE_MAX_TURNS = 90; 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. */ export function buildClaudeCodePrompt(ctx: AgentContext): string { const roleDef = ctx.workflow.roles[ctx.role]; @@ -46,11 +28,23 @@ export function buildClaudeCodePrompt(ctx: AgentContext): string { parts.push(ctx.outputFormatInstruction, ""); } parts.push(rolePrompt, "", "## Task", ctx.start.prompt); - const historyBlock = buildHistorySummary(ctx.steps); - if (historyBlock !== "") { - parts.push("", historyBlock); + + if (!ctx.isFirstVisit) { + // 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"); }