Skip to content

Commit 5fd156d

Browse files
authored
Revert "chore: remove unused stripAppendedEnvironmentDetails and helpers" (RooCodeInc#11255)
Revert "chore: remove unused stripAppendedEnvironmentDetails and helpers (RooCodeInc#11…" This reverts commit 2d5e633.
1 parent 2053de7 commit 5fd156d

2 files changed

Lines changed: 192 additions & 1 deletion

File tree

src/core/task/__tests__/appendEnvironmentDetails.spec.ts

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
import { Anthropic } from "@anthropic-ai/sdk"
2-
import { appendEnvironmentDetails, removeEnvironmentDetailsBlocks, UserContentBlock } from "../appendEnvironmentDetails"
2+
import {
3+
appendEnvironmentDetails,
4+
removeEnvironmentDetailsBlocks,
5+
stripAppendedEnvironmentDetails,
6+
UserContentBlock,
7+
} from "../appendEnvironmentDetails"
38

49
describe("appendEnvironmentDetails", () => {
510
const envDetails = "<environment_details>\n# Test\nSome details\n</environment_details>"
@@ -314,3 +319,96 @@ describe("removeEnvironmentDetailsBlocks", () => {
314319
expect(result).toHaveLength(0)
315320
})
316321
})
322+
323+
describe("stripAppendedEnvironmentDetails", () => {
324+
const envDetails = "<environment_details>\n# Test\nSome details\n</environment_details>"
325+
326+
it("should strip environment details from the end of a text block", () => {
327+
const content: UserContentBlock[] = [{ type: "text", text: "User message\n\n" + envDetails }]
328+
329+
const result = stripAppendedEnvironmentDetails(content)
330+
331+
expect(result).toHaveLength(1)
332+
expect((result[0] as Anthropic.Messages.TextBlockParam).text).toBe("User message")
333+
})
334+
335+
it("should strip environment details from tool_result string content", () => {
336+
const content: UserContentBlock[] = [
337+
{
338+
type: "tool_result",
339+
tool_use_id: "tool-123",
340+
content: "Tool result\n\n" + envDetails,
341+
},
342+
]
343+
344+
const result = stripAppendedEnvironmentDetails(content)
345+
346+
expect(result).toHaveLength(1)
347+
expect((result[0] as Anthropic.Messages.ToolResultBlockParam).content).toBe("Tool result")
348+
})
349+
350+
it("should strip environment details from tool_result array content", () => {
351+
const content: UserContentBlock[] = [
352+
{
353+
type: "tool_result",
354+
tool_use_id: "tool-123",
355+
content: [{ type: "text", text: "Result text\n\n" + envDetails }],
356+
},
357+
]
358+
359+
const result = stripAppendedEnvironmentDetails(content)
360+
361+
const toolResult = result[0] as Anthropic.Messages.ToolResultBlockParam
362+
const contentArray = toolResult.content as Anthropic.Messages.TextBlockParam[]
363+
expect(contentArray[0].text).toBe("Result text")
364+
})
365+
366+
it("should also remove standalone environment_details blocks", () => {
367+
const content: UserContentBlock[] = [
368+
{ type: "text", text: "User message" },
369+
{ type: "text", text: envDetails },
370+
]
371+
372+
const result = stripAppendedEnvironmentDetails(content)
373+
374+
expect(result).toHaveLength(1)
375+
expect((result[0] as Anthropic.Messages.TextBlockParam).text).toBe("User message")
376+
})
377+
378+
it("should handle content without environment details", () => {
379+
const content: UserContentBlock[] = [
380+
{ type: "text", text: "User message" },
381+
{
382+
type: "tool_result",
383+
tool_use_id: "tool-123",
384+
content: "Tool result",
385+
},
386+
]
387+
388+
const result = stripAppendedEnvironmentDetails(content)
389+
390+
expect(result).toEqual(content)
391+
})
392+
393+
it("should handle empty content", () => {
394+
const result = stripAppendedEnvironmentDetails([])
395+
expect(result).toHaveLength(0)
396+
})
397+
398+
it("should preserve is_error flag when stripping from tool_result", () => {
399+
const content: UserContentBlock[] = [
400+
{
401+
type: "tool_result",
402+
tool_use_id: "tool-123",
403+
content: "Error\n\n" + envDetails,
404+
is_error: true,
405+
},
406+
]
407+
408+
const result = stripAppendedEnvironmentDetails(content)
409+
410+
const toolResult = result[0] as Anthropic.Messages.ToolResultBlockParam
411+
expect(toolResult.is_error).toBe(true)
412+
expect(toolResult.content).toBe("Error")
413+
})
414+
})

src/core/task/appendEnvironmentDetails.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,96 @@ export function removeEnvironmentDetailsBlocks(content: UserContentBlock[]): Use
143143
return true
144144
})
145145
}
146+
147+
/**
148+
* Strips environment details from the last text block or tool_result in the content.
149+
* This handles the case where environment details were appended to an existing block
150+
* rather than added as a standalone block.
151+
*
152+
* @param content - Array of content blocks
153+
* @returns New array with environment details stripped from the last suitable block
154+
*/
155+
export function stripAppendedEnvironmentDetails(content: UserContentBlock[]): UserContentBlock[] {
156+
if (content.length === 0) {
157+
return content
158+
}
159+
160+
// First, remove any standalone environment_details blocks
161+
let result = removeEnvironmentDetailsBlocks(content)
162+
163+
if (result.length === 0) {
164+
return result
165+
}
166+
167+
// Then, strip appended environment details from the last block
168+
const lastIndex = result.length - 1
169+
const lastBlock = result[lastIndex]
170+
171+
if (lastBlock.type === "text") {
172+
const strippedText = stripEnvDetailsFromText(lastBlock.text)
173+
if (strippedText !== lastBlock.text) {
174+
result = [...result]
175+
result[lastIndex] = { type: "text" as const, text: strippedText }
176+
}
177+
} else if (lastBlock.type === "tool_result") {
178+
const strippedToolResult = stripEnvDetailsFromToolResult(lastBlock)
179+
if (strippedToolResult !== lastBlock) {
180+
result = [...result]
181+
result[lastIndex] = strippedToolResult
182+
}
183+
}
184+
185+
return result
186+
}
187+
188+
/**
189+
* Strips environment details from the end of a text string.
190+
*/
191+
function stripEnvDetailsFromText(text: string): string {
192+
// Match environment details at the end of the string, with optional preceding newlines
193+
const envDetailsPattern = /\n*<environment_details>[\s\S]*<\/environment_details>\s*$/
194+
return text.replace(envDetailsPattern, "")
195+
}
196+
197+
/**
198+
* Strips environment details from a tool_result block's content.
199+
*/
200+
function stripEnvDetailsFromToolResult(
201+
toolResult: Anthropic.Messages.ToolResultBlockParam,
202+
): Anthropic.Messages.ToolResultBlockParam {
203+
const { content, ...rest } = toolResult
204+
205+
if (content === undefined || content === null) {
206+
return toolResult
207+
}
208+
209+
if (typeof content === "string") {
210+
const strippedContent = stripEnvDetailsFromText(content)
211+
if (strippedContent === content) {
212+
return toolResult
213+
}
214+
return { ...rest, content: strippedContent }
215+
}
216+
217+
if (Array.isArray(content)) {
218+
let changed = false
219+
const newContent = content.map((block) => {
220+
if (block.type === "text") {
221+
const strippedText = stripEnvDetailsFromText(block.text)
222+
if (strippedText !== block.text) {
223+
changed = true
224+
return { type: "text" as const, text: strippedText }
225+
}
226+
}
227+
return block
228+
})
229+
230+
if (!changed) {
231+
return toolResult
232+
}
233+
234+
return { ...rest, content: newContent }
235+
}
236+
237+
return toolResult
238+
}

0 commit comments

Comments
 (0)