From f1d026399b82bd84e49d4c8dd8833e4e9b2fc656 Mon Sep 17 00:00:00 2001 From: Sweets Sweetman Date: Thu, 21 May 2026 19:44:32 -0500 Subject: [PATCH 1/3] feat(chat-workflow): thread real cwd + currentBranch into system prompt (Bundle A.7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Third open-agents → api cutover bundle. The handler hardcoded `workingDirectory: DEFAULT_WORKING_DIRECTORY` and never set `currentBranch`, so the agent had no environment info in its system prompt and had to run `pwd` / `git branch` on every turn. Production verification (today, before this fix): agent: "My system prompt does not contain working directory or branch information." After this fix the agent receives an Environment section + Current branch line + cloud-sandbox checkpointing block — same shape as open-agents (sandbox.recoupable.com) emits. Changes: - New `lib/chat/buildAgentSystemPrompt.ts` (SRP) — assembles environment section → Current branch → cloud-sandbox checkpointing → custom instructions, all conditional on inputs. Mirrors open-agents' `buildSystemPrompt` (packages/agent/system-prompt.ts). - New `lib/chat/cloudSandboxInstructions.ts` (SRP) — ports open-agents' `CLOUD_SANDBOX_INSTRUCTIONS` block with `{branch}` placeholder substitution. - `handleChatWorkflowStream`: connect the sandbox once for both skill discovery AND cwd/branch reading, then thread real values into `AgentContext.sandbox.workingDirectory` + `.currentBranch`. On connect failure, fall back to DEFAULT_WORKING_DIRECTORY (preserves today's behavior; tools surface real errors later when they reconnect). - `runAgentStep`: build the system prompt via `buildAgentSystemPrompt({cwd, currentBranch, customInstructions})` instead of using the static `agentCustomInstructions` directly. Scope reduced from the original "A.7+9" bundle: dropped contextLimit plumbing because it's a client-side display concern in open-agents, not server-side model routing (verified via grep — open-agents' server never reads context.contextLimit either). Tests: 7 new (6 buildAgentSystemPrompt + 1 runAgentStep wiring); full suite 3121/3121 pass; lint clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../workflows/__tests__/runAgentStep.test.ts | 25 ++++++++ app/lib/workflows/runAgentStep.ts | 13 +++- .../__tests__/buildAgentSystemPrompt.test.ts | 54 +++++++++++++++++ lib/chat/buildAgentSystemPrompt.ts | 60 +++++++++++++++++++ lib/chat/cloudSandboxInstructions.ts | 45 ++++++++++++++ lib/chat/handleChatWorkflowStream.ts | 25 +++++--- 6 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 lib/chat/__tests__/buildAgentSystemPrompt.test.ts create mode 100644 lib/chat/buildAgentSystemPrompt.ts create mode 100644 lib/chat/cloudSandboxInstructions.ts diff --git a/app/lib/workflows/__tests__/runAgentStep.test.ts b/app/lib/workflows/__tests__/runAgentStep.test.ts index 429a37505..21b5b227a 100644 --- a/app/lib/workflows/__tests__/runAgentStep.test.ts +++ b/app/lib/workflows/__tests__/runAgentStep.test.ts @@ -88,6 +88,31 @@ describe("runAgentStep", () => { expect(meta?.modelId).toBe("anthropic/claude-haiku-4.5"); }); + it("includes cwd + currentBranch from agentContext.sandbox in the system prompt", async () => { + const captured: unknown[] = []; + vi.mocked(streamText).mockReturnValue(makeStreamResult({ metadataCalls: captured }) as never); + const { stream } = makeWritable(); + + await runAgentStep({ + ...baseInput, + agentContext: { + sandbox: { + state: { type: "vercel" }, + workingDirectory: "/sandbox/mono", + currentBranch: "feat/xyz", + }, + }, + writable: stream, + } as never); + + const args = vi.mocked(streamText).mock.calls[0]?.[0] as { system?: string }; + expect(args.system).toMatch(/# Environment/); + expect(args.system).toMatch(/Working directory: \. \(workspace root\)/); + expect(args.system).toMatch(/Current branch: feat\/xyz/); + expect(args.system).toMatch(/# Cloud Sandbox/); + expect(args.system).toMatch(/git push -u origin feat\/xyz/); + }); + it("the wired callback returns undefined for non-finish-step parts", async () => { const captured: unknown[] = []; vi.mocked(streamText).mockReturnValue(makeStreamResult({ metadataCalls: captured }) as never); diff --git a/app/lib/workflows/runAgentStep.ts b/app/lib/workflows/runAgentStep.ts index 983bf4d7a..6890ad7a4 100644 --- a/app/lib/workflows/runAgentStep.ts +++ b/app/lib/workflows/runAgentStep.ts @@ -1,6 +1,7 @@ import { streamText, convertToModelMessages, type UIMessage, type UIMessageChunk } from "ai"; import { gateway } from "@ai-sdk/gateway"; import { agentCustomInstructions } from "@/lib/chat/agentCustomInstructions"; +import { buildAgentSystemPrompt } from "@/lib/chat/buildAgentSystemPrompt"; import { CHAT_AGENT_STOP_WHEN } from "@/lib/chat/const"; import { buildAgentTools } from "@/lib/agent/buildAgentTools"; import type { AgentContext, DurableAgentContext } from "@/lib/agent/tools/AgentContext"; @@ -57,9 +58,19 @@ export async function runAgentStep(input: RunAgentStepInput): Promise<{ finishRe ...input.agentContext, model: callModel, }; + // Build the system prompt with the sandbox's real cwd + currentBranch + // baked in (rather than a static `agentCustomInstructions` string). + // Without this the agent has to `pwd` / `git branch` on every turn + // because its prompt doesn't tell it where it is. Mirrors open-agents' + // `buildSystemPrompt`. + const systemPrompt = buildAgentSystemPrompt({ + cwd: input.agentContext.sandbox.workingDirectory, + currentBranch: input.agentContext.sandbox.currentBranch, + customInstructions: agentCustomInstructions, + }); const result = streamText({ model: callModel, - system: agentCustomInstructions, + system: systemPrompt, messages: modelMessages, tools, stopWhen: CHAT_AGENT_STOP_WHEN, diff --git a/lib/chat/__tests__/buildAgentSystemPrompt.test.ts b/lib/chat/__tests__/buildAgentSystemPrompt.test.ts new file mode 100644 index 000000000..e72db5459 --- /dev/null +++ b/lib/chat/__tests__/buildAgentSystemPrompt.test.ts @@ -0,0 +1,54 @@ +import { describe, it, expect } from "vitest"; +import { buildAgentSystemPrompt } from "@/lib/chat/buildAgentSystemPrompt"; + +describe("buildAgentSystemPrompt", () => { + it("emits only customInstructions when no cwd/branch is provided", () => { + const prompt = buildAgentSystemPrompt({ customInstructions: "hello" }); + expect(prompt).toContain("hello"); + expect(prompt).not.toMatch(/Working directory/); + expect(prompt).not.toMatch(/Current branch/); + }); + + it("includes an Environment section when cwd is provided", () => { + const prompt = buildAgentSystemPrompt({ cwd: "/vercel/sandbox" }); + expect(prompt).toMatch(/# Environment/); + expect(prompt).toMatch(/Working directory: \. \(workspace root\)/); + expect(prompt).toMatch(/workspace-relative paths/); + }); + + it("includes Current branch + cloud sandbox checkpointing when currentBranch is provided", () => { + const prompt = buildAgentSystemPrompt({ + cwd: "/sandbox", + currentBranch: "feat/foo", + }); + expect(prompt).toMatch(/Current branch: feat\/foo/); + expect(prompt).toMatch(/# Cloud Sandbox/); + expect(prompt).toMatch(/git push -u origin feat\/foo/); + }); + + it("omits cloud sandbox checkpointing when no currentBranch", () => { + const prompt = buildAgentSystemPrompt({ cwd: "/sandbox" }); + expect(prompt).not.toMatch(/# Cloud Sandbox/); + expect(prompt).not.toMatch(/Current branch/); + }); + + it("appends customInstructions AFTER the environment + branch sections", () => { + const prompt = buildAgentSystemPrompt({ + cwd: "/sandbox", + currentBranch: "main", + customInstructions: "MARK_AT_END", + }); + const envIdx = prompt.indexOf("# Environment"); + const branchIdx = prompt.indexOf("Current branch"); + const cloudIdx = prompt.indexOf("# Cloud Sandbox"); + const customIdx = prompt.indexOf("MARK_AT_END"); + expect(envIdx).toBeGreaterThanOrEqual(0); + expect(branchIdx).toBeGreaterThan(envIdx); + expect(cloudIdx).toBeGreaterThan(branchIdx); + expect(customIdx).toBeGreaterThan(cloudIdx); + }); + + it("returns empty string when all options are empty", () => { + expect(buildAgentSystemPrompt({})).toBe(""); + }); +}); diff --git a/lib/chat/buildAgentSystemPrompt.ts b/lib/chat/buildAgentSystemPrompt.ts new file mode 100644 index 000000000..18f4da1af --- /dev/null +++ b/lib/chat/buildAgentSystemPrompt.ts @@ -0,0 +1,60 @@ +import { renderCloudSandboxInstructions } from "@/lib/chat/cloudSandboxInstructions"; + +const ENVIRONMENT_SECTION = `# Environment + +Working directory: . (workspace root) +Use workspace-relative paths for all file operations.`; + +export type BuildAgentSystemPromptOptions = { + /** + * Sandbox working directory. Triggers inclusion of the Environment + * section. The literal value isn't exposed to the model — the + * section just signals "you're in a workspace; use relative paths" + * (mirrors open-agents). + */ + cwd?: string; + /** + * Current git branch on the sandbox checkout. Triggers inclusion of + * `Current branch: ` plus the cloud-sandbox checkpointing + * block, with the branch substituted into the example `git push` + * command. + */ + currentBranch?: string; + /** + * Project-specific custom instructions appended at the end of the + * prompt (api's existing `agentCustomInstructions` — assistant file + * link prompt + recoup-api skill prompt). + */ + customInstructions?: string; +}; + +/** + * Assemble the system prompt for `runAgentStep`. Mirrors open-agents' + * `buildSystemPrompt` (`packages/agent/system-prompt.ts`) at the + * structural level — environment section → branch info → cloud + * sandbox checkpointing → custom instructions — so the agent knows + * its execution context without having to run `pwd` / `git branch` + * on every prompt. + * + * Sections render only when their inputs are provided, so a request + * without sandbox context (or before sandbox boot) still produces a + * coherent (env-less) prompt. + */ +export function buildAgentSystemPrompt(options: BuildAgentSystemPromptOptions): string { + const parts: string[] = []; + + if (options.cwd) { + parts.push(ENVIRONMENT_SECTION); + } + + if (options.currentBranch) { + parts.push(`Current branch: ${options.currentBranch}`); + parts.push(renderCloudSandboxInstructions(options.currentBranch)); + } + + if (options.customInstructions) { + parts.push(options.customInstructions); + } + + return parts.join("\n\n"); +} diff --git a/lib/chat/cloudSandboxInstructions.ts b/lib/chat/cloudSandboxInstructions.ts new file mode 100644 index 000000000..5240529e6 --- /dev/null +++ b/lib/chat/cloudSandboxInstructions.ts @@ -0,0 +1,45 @@ +/** + * Cloud-sandbox checkpointing instructions injected into the system + * prompt when `currentBranch` is known. Mirrors open-agents' + * `CLOUD_SANDBOX_INSTRUCTIONS` (`packages/agent/system-prompt.ts`) + * — the `{branch}` placeholder is substituted with the live branch + * name before injection. + * + * The block tells the model: this sandbox is ephemeral; commit + push + * frequently because work is lost when the session ends. Without it + * the model can't know to checkpoint its work, which surfaces as + * "I made these changes" assistant replies whose changes evaporate + * after the sandbox tears down. + */ +const CLOUD_SANDBOX_INSTRUCTIONS = `# Cloud Sandbox + +Your sandbox is ephemeral. All work is lost when the session ends unless committed and pushed to git. + +## Checkpointing Rules + +1. **Commit after every meaningful change** — new file, completed function, fixed bug +2. **Push immediately after each commit** — do not batch commits +3. **Commit BEFORE long operations** — package installs, builds, test runs +4. **Use clear WIP messages** — "WIP: add user authentication endpoint" +5. **When in doubt, checkpoint** — it is better to have extra commits than lost work + +## Git Workflow + +- Push with: \`git push -u origin {branch}\` +- Your work is only safe once pushed to remote +- If push fails, retry once then report the failure — do not proceed with more work until push succeeds + +## On Task Completion + +- Squash WIP commits into logical units if appropriate +- Write a final commit message summarizing changes +- Ensure all changes are pushed before reporting completion`; + +/** + * Render the cloud-sandbox checkpointing block with a real branch + * name substituted into the `{branch}` placeholder inside the + * `git push` example. + */ +export function renderCloudSandboxInstructions(branch: string): string { + return CLOUD_SANDBOX_INSTRUCTIONS.replace("{branch}", branch); +} diff --git a/lib/chat/handleChatWorkflowStream.ts b/lib/chat/handleChatWorkflowStream.ts index 818c70f8c..9a3686162 100644 --- a/lib/chat/handleChatWorkflowStream.ts +++ b/lib/chat/handleChatWorkflowStream.ts @@ -94,18 +94,27 @@ export async function handleChatWorkflowStream(request: NextRequest): Promise> = []; + let workingDirectory: string = DEFAULT_WORKING_DIRECTORY; + let currentBranch: string | undefined; try { const sandbox = await connectVercel(session.sandbox_state as VercelState); + workingDirectory = sandbox.workingDirectory; + currentBranch = sandbox.currentBranch; const dirs = await getSandboxSkillDirectories(sandbox); skills = await discoverSkills(sandbox, dirs); } catch (error) { console.error( - "[handleChatWorkflowStream] skill discovery failed; continuing with empty catalog:", + "[handleChatWorkflowStream] sandbox connect / skill discovery failed; continuing with defaults:", error, ); } @@ -119,10 +128,8 @@ export async function handleChatWorkflowStream(request: NextRequest): Promise Date: Thu, 21 May 2026 21:03:14 -0500 Subject: [PATCH 2/3] chore(chat-workflow): drop currentBranch handling from system prompt Per direction: branch is always `main` (the default branch) in api's deployment topology, so the per-branch `Current branch: ` line and cloud-sandbox checkpointing block don't add information today. Strip the templating to keep the system prompt focused on what's load-bearing (the Environment section indicating workspace-relative paths). - Delete `lib/chat/cloudSandboxInstructions.ts` (was a port of open-agents' CLOUD_SANDBOX_INSTRUCTIONS, only useful with a real per-session branch) - Drop `currentBranch` from `buildAgentSystemPrompt` options + rendering - Stop reading `sandbox.currentBranch` in handleChatWorkflowStream (the field stays on AgentContext.sandbox for type completeness; also consumed by createSandboxHandler unchanged) - Remove branch-related test cases Can be re-added later if/when meaningful per-session branches (e.g. xx/abcdef12 generated branches) land. Tests: 3119/3119 pass; lint clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../workflows/__tests__/runAgentStep.test.ts | 7 +-- .../__tests__/buildAgentSystemPrompt.test.ts | 30 ++----------- lib/chat/buildAgentSystemPrompt.ts | 29 +++++------- lib/chat/cloudSandboxInstructions.ts | 45 ------------------- lib/chat/handleChatWorkflowStream.ts | 15 +++---- 5 files changed, 23 insertions(+), 103 deletions(-) delete mode 100644 lib/chat/cloudSandboxInstructions.ts diff --git a/app/lib/workflows/__tests__/runAgentStep.test.ts b/app/lib/workflows/__tests__/runAgentStep.test.ts index 21b5b227a..0d48f81f8 100644 --- a/app/lib/workflows/__tests__/runAgentStep.test.ts +++ b/app/lib/workflows/__tests__/runAgentStep.test.ts @@ -88,7 +88,7 @@ describe("runAgentStep", () => { expect(meta?.modelId).toBe("anthropic/claude-haiku-4.5"); }); - it("includes cwd + currentBranch from agentContext.sandbox in the system prompt", async () => { + it("includes cwd from agentContext.sandbox in the system prompt", async () => { const captured: unknown[] = []; vi.mocked(streamText).mockReturnValue(makeStreamResult({ metadataCalls: captured }) as never); const { stream } = makeWritable(); @@ -99,7 +99,6 @@ describe("runAgentStep", () => { sandbox: { state: { type: "vercel" }, workingDirectory: "/sandbox/mono", - currentBranch: "feat/xyz", }, }, writable: stream, @@ -108,9 +107,7 @@ describe("runAgentStep", () => { const args = vi.mocked(streamText).mock.calls[0]?.[0] as { system?: string }; expect(args.system).toMatch(/# Environment/); expect(args.system).toMatch(/Working directory: \. \(workspace root\)/); - expect(args.system).toMatch(/Current branch: feat\/xyz/); - expect(args.system).toMatch(/# Cloud Sandbox/); - expect(args.system).toMatch(/git push -u origin feat\/xyz/); + expect(args.system).toMatch(/workspace-relative paths/); }); it("the wired callback returns undefined for non-finish-step parts", async () => { diff --git a/lib/chat/__tests__/buildAgentSystemPrompt.test.ts b/lib/chat/__tests__/buildAgentSystemPrompt.test.ts index e72db5459..81cb9268d 100644 --- a/lib/chat/__tests__/buildAgentSystemPrompt.test.ts +++ b/lib/chat/__tests__/buildAgentSystemPrompt.test.ts @@ -2,11 +2,10 @@ import { describe, it, expect } from "vitest"; import { buildAgentSystemPrompt } from "@/lib/chat/buildAgentSystemPrompt"; describe("buildAgentSystemPrompt", () => { - it("emits only customInstructions when no cwd/branch is provided", () => { + it("emits only customInstructions when no cwd is provided", () => { const prompt = buildAgentSystemPrompt({ customInstructions: "hello" }); - expect(prompt).toContain("hello"); + expect(prompt).toBe("hello"); expect(prompt).not.toMatch(/Working directory/); - expect(prompt).not.toMatch(/Current branch/); }); it("includes an Environment section when cwd is provided", () => { @@ -16,36 +15,15 @@ describe("buildAgentSystemPrompt", () => { expect(prompt).toMatch(/workspace-relative paths/); }); - it("includes Current branch + cloud sandbox checkpointing when currentBranch is provided", () => { + it("appends customInstructions AFTER the environment section", () => { const prompt = buildAgentSystemPrompt({ cwd: "/sandbox", - currentBranch: "feat/foo", - }); - expect(prompt).toMatch(/Current branch: feat\/foo/); - expect(prompt).toMatch(/# Cloud Sandbox/); - expect(prompt).toMatch(/git push -u origin feat\/foo/); - }); - - it("omits cloud sandbox checkpointing when no currentBranch", () => { - const prompt = buildAgentSystemPrompt({ cwd: "/sandbox" }); - expect(prompt).not.toMatch(/# Cloud Sandbox/); - expect(prompt).not.toMatch(/Current branch/); - }); - - it("appends customInstructions AFTER the environment + branch sections", () => { - const prompt = buildAgentSystemPrompt({ - cwd: "/sandbox", - currentBranch: "main", customInstructions: "MARK_AT_END", }); const envIdx = prompt.indexOf("# Environment"); - const branchIdx = prompt.indexOf("Current branch"); - const cloudIdx = prompt.indexOf("# Cloud Sandbox"); const customIdx = prompt.indexOf("MARK_AT_END"); expect(envIdx).toBeGreaterThanOrEqual(0); - expect(branchIdx).toBeGreaterThan(envIdx); - expect(cloudIdx).toBeGreaterThan(branchIdx); - expect(customIdx).toBeGreaterThan(cloudIdx); + expect(customIdx).toBeGreaterThan(envIdx); }); it("returns empty string when all options are empty", () => { diff --git a/lib/chat/buildAgentSystemPrompt.ts b/lib/chat/buildAgentSystemPrompt.ts index 18f4da1af..922273ae7 100644 --- a/lib/chat/buildAgentSystemPrompt.ts +++ b/lib/chat/buildAgentSystemPrompt.ts @@ -1,5 +1,3 @@ -import { renderCloudSandboxInstructions } from "@/lib/chat/cloudSandboxInstructions"; - const ENVIRONMENT_SECTION = `# Environment Working directory: . (workspace root) @@ -13,13 +11,6 @@ export type BuildAgentSystemPromptOptions = { * (mirrors open-agents). */ cwd?: string; - /** - * Current git branch on the sandbox checkout. Triggers inclusion of - * `Current branch: ` plus the cloud-sandbox checkpointing - * block, with the branch substituted into the example `git push` - * command. - */ - currentBranch?: string; /** * Project-specific custom instructions appended at the end of the * prompt (api's existing `agentCustomInstructions` — assistant file @@ -31,14 +22,21 @@ export type BuildAgentSystemPromptOptions = { /** * Assemble the system prompt for `runAgentStep`. Mirrors open-agents' * `buildSystemPrompt` (`packages/agent/system-prompt.ts`) at the - * structural level — environment section → branch info → cloud - * sandbox checkpointing → custom instructions — so the agent knows - * its execution context without having to run `pwd` / `git branch` - * on every prompt. + * structural level — environment section → custom instructions — so + * the agent knows it's in a sandboxed workspace without having to + * run `pwd` on every prompt. * * Sections render only when their inputs are provided, so a request * without sandbox context (or before sandbox boot) still produces a * coherent (env-less) prompt. + * + * `currentBranch` handling deliberately omitted in this slim port — + * the cloud-sandbox checkpointing block in open-agents templates a + * `git push -u origin {branch}` example per session, but in api's + * deployment topology the branch is always the org repo's default + * (`main`), so the per-branch templating doesn't add value yet. Add + * back when a meaningful per-session branch lands (e.g. xx/abcdef12 + * generated branches). */ export function buildAgentSystemPrompt(options: BuildAgentSystemPromptOptions): string { const parts: string[] = []; @@ -47,11 +45,6 @@ export function buildAgentSystemPrompt(options: BuildAgentSystemPromptOptions): parts.push(ENVIRONMENT_SECTION); } - if (options.currentBranch) { - parts.push(`Current branch: ${options.currentBranch}`); - parts.push(renderCloudSandboxInstructions(options.currentBranch)); - } - if (options.customInstructions) { parts.push(options.customInstructions); } diff --git a/lib/chat/cloudSandboxInstructions.ts b/lib/chat/cloudSandboxInstructions.ts deleted file mode 100644 index 5240529e6..000000000 --- a/lib/chat/cloudSandboxInstructions.ts +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Cloud-sandbox checkpointing instructions injected into the system - * prompt when `currentBranch` is known. Mirrors open-agents' - * `CLOUD_SANDBOX_INSTRUCTIONS` (`packages/agent/system-prompt.ts`) - * — the `{branch}` placeholder is substituted with the live branch - * name before injection. - * - * The block tells the model: this sandbox is ephemeral; commit + push - * frequently because work is lost when the session ends. Without it - * the model can't know to checkpoint its work, which surfaces as - * "I made these changes" assistant replies whose changes evaporate - * after the sandbox tears down. - */ -const CLOUD_SANDBOX_INSTRUCTIONS = `# Cloud Sandbox - -Your sandbox is ephemeral. All work is lost when the session ends unless committed and pushed to git. - -## Checkpointing Rules - -1. **Commit after every meaningful change** — new file, completed function, fixed bug -2. **Push immediately after each commit** — do not batch commits -3. **Commit BEFORE long operations** — package installs, builds, test runs -4. **Use clear WIP messages** — "WIP: add user authentication endpoint" -5. **When in doubt, checkpoint** — it is better to have extra commits than lost work - -## Git Workflow - -- Push with: \`git push -u origin {branch}\` -- Your work is only safe once pushed to remote -- If push fails, retry once then report the failure — do not proceed with more work until push succeeds - -## On Task Completion - -- Squash WIP commits into logical units if appropriate -- Write a final commit message summarizing changes -- Ensure all changes are pushed before reporting completion`; - -/** - * Render the cloud-sandbox checkpointing block with a real branch - * name substituted into the `{branch}` placeholder inside the - * `git push` example. - */ -export function renderCloudSandboxInstructions(branch: string): string { - return CLOUD_SANDBOX_INSTRUCTIONS.replace("{branch}", branch); -} diff --git a/lib/chat/handleChatWorkflowStream.ts b/lib/chat/handleChatWorkflowStream.ts index 9a3686162..5a1c89603 100644 --- a/lib/chat/handleChatWorkflowStream.ts +++ b/lib/chat/handleChatWorkflowStream.ts @@ -95,21 +95,19 @@ export async function handleChatWorkflowStream(request: NextRequest): Promise> = []; let workingDirectory: string = DEFAULT_WORKING_DIRECTORY; - let currentBranch: string | undefined; try { const sandbox = await connectVercel(session.sandbox_state as VercelState); workingDirectory = sandbox.workingDirectory; - currentBranch = sandbox.currentBranch; const dirs = await getSandboxSkillDirectories(sandbox); skills = await discoverSkills(sandbox, dirs); } catch (error) { @@ -129,7 +127,6 @@ export async function handleChatWorkflowStream(request: NextRequest): Promise Date: Thu, 21 May 2026 21:06:11 -0500 Subject: [PATCH 3/3] fix(chat-workflow): drop stale currentBranch arg from buildAgentSystemPrompt call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build failure on bf1e2451 — runAgentStep was still passing `currentBranch: input.agentContext.sandbox.currentBranch` after buildAgentSystemPrompt's option was removed. Stripping it. Co-Authored-By: Claude Opus 4.7 (1M context) --- app/lib/workflows/runAgentStep.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/lib/workflows/runAgentStep.ts b/app/lib/workflows/runAgentStep.ts index 6890ad7a4..9d752e1a7 100644 --- a/app/lib/workflows/runAgentStep.ts +++ b/app/lib/workflows/runAgentStep.ts @@ -58,14 +58,13 @@ export async function runAgentStep(input: RunAgentStepInput): Promise<{ finishRe ...input.agentContext, model: callModel, }; - // Build the system prompt with the sandbox's real cwd + currentBranch - // baked in (rather than a static `agentCustomInstructions` string). - // Without this the agent has to `pwd` / `git branch` on every turn - // because its prompt doesn't tell it where it is. Mirrors open-agents' + // Build the system prompt with the sandbox's real cwd baked in + // (rather than a static `agentCustomInstructions` string). Without + // this the agent has to `pwd` on every turn because its prompt + // doesn't tell it where it is. Mirrors open-agents' // `buildSystemPrompt`. const systemPrompt = buildAgentSystemPrompt({ cwd: input.agentContext.sandbox.workingDirectory, - currentBranch: input.agentContext.sandbox.currentBranch, customInstructions: agentCustomInstructions, }); const result = streamText({