Remove XML-like <task>/<feedback> wrappers; process plain user input; update code/tests

This commit is contained in:
Hannes Rudolph 2025-10-11 16:06:30 -06:00
parent 3a47c55a2e
commit be3bda8136
8 changed files with 22 additions and 24 deletions

View file

@ -162,7 +162,7 @@ describe("processUserContentMentions", () => {
})
})
it("should not process text blocks without task or feedback tags", async () => {
it("should process text blocks without special tags", async () => {
const userContent = [
{
type: "text" as const,
@ -177,8 +177,11 @@ describe("processUserContentMentions", () => {
fileContextTracker: mockFileContextTracker,
})
expect(parseMentions).not.toHaveBeenCalled()
expect(result[0]).toEqual(userContent[0])
expect(parseMentions).toHaveBeenCalled()
expect(result[0]).toEqual({
type: "text",
text: "parsed: Regular text without special tags",
})
})
it("should process tool_result blocks with string content", async () => {
@ -230,7 +233,7 @@ describe("processUserContentMentions", () => {
fileContextTracker: mockFileContextTracker,
})
expect(parseMentions).toHaveBeenCalledTimes(1)
expect(parseMentions).toHaveBeenCalledTimes(2)
expect(result[0]).toEqual({
type: "tool_result",
tool_use_id: "123",
@ -241,7 +244,7 @@ describe("processUserContentMentions", () => {
},
{
type: "text",
text: "Regular text",
text: "parsed: Regular text",
},
],
})

View file

@ -39,11 +39,7 @@ export async function processUserContentMentions({
// should parse mentions).
return Promise.all(
userContent.map(async (block) => {
const shouldProcessMentions = (text: string) =>
text.includes("<task>") ||
text.includes("<feedback>") ||
text.includes("<answer>") ||
text.includes("<user_message>")
const shouldProcessMentions = (_text: string) => true
if (block.type === "text") {
if (shouldProcessMentions(block.text)) {

View file

@ -8,10 +8,10 @@ export const formatResponse = {
toolDenied: () => `The user denied this operation.`,
toolDeniedWithFeedback: (feedback?: string) =>
`The user denied this operation and provided the following feedback:\n<feedback>\n${feedback}\n</feedback>`,
`The user denied this operation and provided the following feedback:\n${feedback}`,
toolApprovedWithFeedback: (feedback?: string) =>
`The user approved this operation and provided the following context:\n<feedback>\n${feedback}\n</feedback>`,
`The user approved this operation and provided the following context:\n${feedback}`,
toolError: (error?: string) => `The tool execution failed with the following error:\n<error>\n${error}\n</error>`,
@ -31,7 +31,7 @@ Otherwise, if you have not completed the task and do not need additional informa
(This is an automated message, so do not respond to it conversationally.)`,
tooManyMistakes: (feedback?: string) =>
`You seem to be having trouble proceeding. The user has provided the following feedback to help guide you:\n<feedback>\n${feedback}\n</feedback>`,
`You seem to be having trouble proceeding. The user has provided the following feedback to help guide you:\n${feedback}`,
missingToolParameterError: (paramName: string) =>
`Missing value for required parameter '${paramName}'. Please retry with complete response.\n\n${toolUseInstructionsReminder}`,

View file

@ -1222,7 +1222,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
await this.initiateTaskLoop([
{
type: "text",
text: `<task>\n${task}\n</task>`,
text: task ?? "",
},
...imageBlocks,
])

View file

@ -918,8 +918,9 @@ describe("Cline", () => {
fileContextTracker: cline.fileContextTracker,
})
// Regular text should not be processed
expect((processedContent[0] as Anthropic.TextBlockParam).text).toBe(
// Regular text should be processed
expect((processedContent[0] as Anthropic.TextBlockParam).text).toContain("processed:")
expect((processedContent[0] as Anthropic.TextBlockParam).text).toContain(
"Regular text with 'some/path' (see below for file content)",
)
@ -937,10 +938,11 @@ describe("Cline", () => {
"<feedback>Check 'some/path' (see below for file content)</feedback>",
)
// Regular tool result should not be processed
// Regular tool result should be processed now
const toolResult2 = processedContent[3] as Anthropic.ToolResultBlockParam
const content2 = Array.isArray(toolResult2.content) ? toolResult2.content[0] : toolResult2.content
expect((content2 as Anthropic.TextBlockParam).text).toBe(
expect((content2 as Anthropic.TextBlockParam).text).toContain("processed:")
expect((content2 as Anthropic.TextBlockParam).text).toContain(
"Regular tool result with 'path' (see below for file content)",
)

View file

@ -125,7 +125,7 @@ export async function attemptCompletionTool(
toolResults.push({
type: "text",
text: `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.\n<feedback>\n${text}\n</feedback>`,
text: `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.\n${text}`,
})
toolResults.push(...formatResponse.imageBlocks(images))

View file

@ -317,8 +317,7 @@ export async function executeCommand(
[
`Command is still running in terminal from '${terminal.getCurrentWorkingDirectory().toPosix()}'.`,
result.length > 0 ? `Here's the output so far:\n${result}\n` : "\n",
`The user provided the following feedback:`,
`<feedback>\n${text}\n</feedback>`,
`The user provided the following feedback:\n${text}`,
].join("\n"),
images,
),

View file

@ -11,11 +11,9 @@ const BUILT_IN_COMMANDS: Record<string, BuiltInCommandDefinition> = {
init: {
name: "init",
description: "Analyze codebase and create concise AGENTS.md files for AI assistants",
content: `<task>
Please analyze this codebase and create an AGENTS.md file containing:
content: `Please analyze this codebase and create an AGENTS.md file containing:
1. Build/lint/test commands - especially for running a single test
2. Code style guidelines including imports, formatting, types, naming conventions, error handling, etc.
</task>
<initialization>
<purpose>