mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
refactor: unify user content tags to <user_message>
Replace all user content wrapper tags (<task>, <feedback>, <answer>, <user_message>) with a single unified <user_message> tag and strip all accompanying explanatory blurbs. Changes: - processUserContentMentions.ts: Simplified shouldProcessMentions() to only detect <user_message> - responses.ts: Updated toolDeniedWithFeedback(), toolApprovedWithFeedback(), tooManyMistakes() - Removed explanatory blurbs from XML output - Removed 'message' field from native protocol JSON - Task.ts: Changed initial task and continuation wrappers to use <user_message> - AttemptCompletionTool.ts: Removed blurb, changed <feedback> to <user_message> - AskFollowupQuestionTool.ts: Changed <answer> to <user_message> - Updated all related test files Breaking changes: - Old task history with <task>, <feedback>, or <answer> tags will no longer have mentions re-parsed - Models no longer receive explicit blurbs explaining the nature of user input
This commit is contained in:
parent
72a6805b4b
commit
0d013e35c4
8 changed files with 38 additions and 67 deletions
|
|
@ -31,7 +31,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Read file with limit</task>",
|
||||
text: "<user_message>Read file with limit</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalledWith(
|
||||
"<task>Read file with limit</task>",
|
||||
"<user_message>Read file with limit</user_message>",
|
||||
"/test",
|
||||
mockUrlContentFetcher,
|
||||
mockFileContextTracker,
|
||||
|
|
@ -61,7 +61,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Read file without limit</task>",
|
||||
text: "<user_message>Read file without limit</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalledWith(
|
||||
"<task>Read file without limit</task>",
|
||||
"<user_message>Read file without limit</user_message>",
|
||||
"/test",
|
||||
mockUrlContentFetcher,
|
||||
mockFileContextTracker,
|
||||
|
|
@ -90,7 +90,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Read unlimited lines</task>",
|
||||
text: "<user_message>Read unlimited lines</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalledWith(
|
||||
"<task>Read unlimited lines</task>",
|
||||
"<user_message>Read unlimited lines</user_message>",
|
||||
"/test",
|
||||
mockUrlContentFetcher,
|
||||
mockFileContextTracker,
|
||||
|
|
@ -118,11 +118,11 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
describe("content processing", () => {
|
||||
it("should process text blocks with <task> tags", async () => {
|
||||
it("should process text blocks with <user_message> tags", async () => {
|
||||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Do something</task>",
|
||||
text: "<user_message>Do something</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -136,33 +136,11 @@ describe("processUserContentMentions", () => {
|
|||
expect(parseMentions).toHaveBeenCalled()
|
||||
expect(result[0]).toEqual({
|
||||
type: "text",
|
||||
text: "parsed: <task>Do something</task>",
|
||||
text: "parsed: <user_message>Do something</user_message>",
|
||||
})
|
||||
})
|
||||
|
||||
it("should process text blocks with <feedback> tags", async () => {
|
||||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<feedback>Fix this issue</feedback>",
|
||||
},
|
||||
]
|
||||
|
||||
const result = await processUserContentMentions({
|
||||
userContent,
|
||||
cwd: "/test",
|
||||
urlContentFetcher: mockUrlContentFetcher,
|
||||
fileContextTracker: mockFileContextTracker,
|
||||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalled()
|
||||
expect(result[0]).toEqual({
|
||||
type: "text",
|
||||
text: "parsed: <feedback>Fix this issue</feedback>",
|
||||
})
|
||||
})
|
||||
|
||||
it("should not process text blocks without task or feedback tags", async () => {
|
||||
it("should not process text blocks without user_message tags", async () => {
|
||||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
|
|
@ -186,7 +164,7 @@ describe("processUserContentMentions", () => {
|
|||
{
|
||||
type: "tool_result" as const,
|
||||
tool_use_id: "123",
|
||||
content: "<feedback>Tool feedback</feedback>",
|
||||
content: "<user_message>Tool feedback</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -201,7 +179,7 @@ describe("processUserContentMentions", () => {
|
|||
expect(result[0]).toEqual({
|
||||
type: "tool_result",
|
||||
tool_use_id: "123",
|
||||
content: "parsed: <feedback>Tool feedback</feedback>",
|
||||
content: "parsed: <user_message>Tool feedback</user_message>",
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -213,7 +191,7 @@ describe("processUserContentMentions", () => {
|
|||
content: [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Array task</task>",
|
||||
text: "<user_message>Array task</user_message>",
|
||||
},
|
||||
{
|
||||
type: "text" as const,
|
||||
|
|
@ -237,7 +215,7 @@ describe("processUserContentMentions", () => {
|
|||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "parsed: <task>Array task</task>",
|
||||
text: "parsed: <user_message>Array task</user_message>",
|
||||
},
|
||||
{
|
||||
type: "text",
|
||||
|
|
@ -251,7 +229,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>First task</task>",
|
||||
text: "<user_message>First task</user_message>",
|
||||
},
|
||||
{
|
||||
type: "image" as const,
|
||||
|
|
@ -264,7 +242,7 @@ describe("processUserContentMentions", () => {
|
|||
{
|
||||
type: "tool_result" as const,
|
||||
tool_use_id: "456",
|
||||
content: "<feedback>Feedback</feedback>",
|
||||
content: "<user_message>Feedback</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -280,13 +258,13 @@ describe("processUserContentMentions", () => {
|
|||
expect(result).toHaveLength(3)
|
||||
expect(result[0]).toEqual({
|
||||
type: "text",
|
||||
text: "parsed: <task>First task</task>",
|
||||
text: "parsed: <user_message>First task</user_message>",
|
||||
})
|
||||
expect(result[1]).toEqual(userContent[1]) // Image block unchanged
|
||||
expect(result[2]).toEqual({
|
||||
type: "tool_result",
|
||||
tool_use_id: "456",
|
||||
content: "parsed: <feedback>Feedback</feedback>",
|
||||
content: "parsed: <user_message>Feedback</user_message>",
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
@ -296,7 +274,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Test default</task>",
|
||||
text: "<user_message>Test default</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -308,7 +286,7 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalledWith(
|
||||
"<task>Test default</task>",
|
||||
"<user_message>Test default</user_message>",
|
||||
"/test",
|
||||
mockUrlContentFetcher,
|
||||
mockFileContextTracker,
|
||||
|
|
@ -324,7 +302,7 @@ describe("processUserContentMentions", () => {
|
|||
const userContent = [
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "<task>Test explicit false</task>",
|
||||
text: "<user_message>Test explicit false</user_message>",
|
||||
},
|
||||
]
|
||||
|
||||
|
|
@ -337,7 +315,7 @@ describe("processUserContentMentions", () => {
|
|||
})
|
||||
|
||||
expect(parseMentions).toHaveBeenCalledWith(
|
||||
"<task>Test explicit false</task>",
|
||||
"<user_message>Test explicit false</user_message>",
|
||||
"/test",
|
||||
mockUrlContentFetcher,
|
||||
mockFileContextTracker,
|
||||
|
|
|
|||
|
|
@ -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) => text.includes("<user_message>")
|
||||
|
||||
if (block.type === "text") {
|
||||
if (shouldProcessMentions(block.text)) {
|
||||
|
|
|
|||
|
|
@ -20,22 +20,20 @@ export const formatResponse = {
|
|||
if (isNativeProtocol(protocol ?? TOOL_PROTOCOL.XML)) {
|
||||
return JSON.stringify({
|
||||
status: "denied",
|
||||
message: "The user denied this operation and provided the following feedback",
|
||||
feedback: feedback,
|
||||
})
|
||||
}
|
||||
return `The user denied this operation and provided the following feedback:\n<feedback>\n${feedback}\n</feedback>`
|
||||
return `<user_message>\n${feedback}\n</user_message>`
|
||||
},
|
||||
|
||||
toolApprovedWithFeedback: (feedback?: string, protocol?: ToolProtocol) => {
|
||||
if (isNativeProtocol(protocol ?? TOOL_PROTOCOL.XML)) {
|
||||
return JSON.stringify({
|
||||
status: "approved",
|
||||
message: "The user approved this operation and provided the following context",
|
||||
feedback: feedback,
|
||||
})
|
||||
}
|
||||
return `The user approved this operation and provided the following context:\n<feedback>\n${feedback}\n</feedback>`
|
||||
return `<user_message>\n${feedback}\n</user_message>`
|
||||
},
|
||||
|
||||
toolError: (error?: string, protocol?: ToolProtocol) => {
|
||||
|
|
@ -81,11 +79,10 @@ Otherwise, if you have not completed the task and do not need additional informa
|
|||
if (isNativeProtocol(protocol ?? TOOL_PROTOCOL.XML)) {
|
||||
return JSON.stringify({
|
||||
status: "guidance",
|
||||
message: "You seem to be having trouble proceeding",
|
||||
feedback: feedback,
|
||||
})
|
||||
}
|
||||
return `You seem to be having trouble proceeding. The user has provided the following feedback to help guide you:\n<feedback>\n${feedback}\n</feedback>`
|
||||
return `<user_message>\n${feedback}\n</user_message>`
|
||||
},
|
||||
|
||||
missingToolParameterError: (paramName: string, protocol?: ToolProtocol) => {
|
||||
|
|
|
|||
|
|
@ -1546,7 +1546,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
await this.initiateTaskLoop([
|
||||
{
|
||||
type: "text",
|
||||
text: `<task>\n${task}\n</task>`,
|
||||
text: `<user_message>\n${task}\n</user_message>`,
|
||||
},
|
||||
...imageBlocks,
|
||||
]).catch((error) => {
|
||||
|
|
@ -1801,7 +1801,7 @@ export class Task extends EventEmitter<TaskEvents> implements TaskLike {
|
|||
if (responseText) {
|
||||
newUserContent.push({
|
||||
type: "text",
|
||||
text: `\n\nNew instructions for task continuation:\n<user_message>\n${responseText}\n</user_message>`,
|
||||
text: `<user_message>\n${responseText}\n</user_message>`,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -881,7 +881,7 @@ describe("Cline", () => {
|
|||
})
|
||||
|
||||
describe("processUserContentMentions", () => {
|
||||
it("should process mentions in task and feedback tags", async () => {
|
||||
it("should process mentions in user_message tags", async () => {
|
||||
const [cline, task] = Task.create({
|
||||
provider: mockProvider,
|
||||
apiConfiguration: mockApiConfig,
|
||||
|
|
@ -895,7 +895,7 @@ describe("Cline", () => {
|
|||
} as const,
|
||||
{
|
||||
type: "text",
|
||||
text: "<task>Text with 'some/path' (see below for file content) in task tags</task>",
|
||||
text: "<user_message>Text with 'some/path' (see below for file content) in user_message tags</user_message>",
|
||||
} as const,
|
||||
{
|
||||
type: "tool_result",
|
||||
|
|
@ -903,7 +903,7 @@ describe("Cline", () => {
|
|||
content: [
|
||||
{
|
||||
type: "text",
|
||||
text: "<feedback>Check 'some/path' (see below for file content)</feedback>",
|
||||
text: "<user_message>Check 'some/path' (see below for file content)</user_message>",
|
||||
},
|
||||
],
|
||||
} as Anthropic.ToolResultBlockParam,
|
||||
|
|
@ -931,18 +931,18 @@ describe("Cline", () => {
|
|||
"Regular text with 'some/path' (see below for file content)",
|
||||
)
|
||||
|
||||
// Text within task tags should be processed
|
||||
// Text within user_message tags should be processed
|
||||
expect((processedContent[1] as Anthropic.TextBlockParam).text).toContain("processed:")
|
||||
expect((processedContent[1] as Anthropic.TextBlockParam).text).toContain(
|
||||
"<task>Text with 'some/path' (see below for file content) in task tags</task>",
|
||||
"<user_message>Text with 'some/path' (see below for file content) in user_message tags</user_message>",
|
||||
)
|
||||
|
||||
// Feedback tag content should be processed
|
||||
// user_message tag content should be processed
|
||||
const toolResult1 = processedContent[2] as Anthropic.ToolResultBlockParam
|
||||
const content1 = Array.isArray(toolResult1.content) ? toolResult1.content[0] : toolResult1.content
|
||||
expect((content1 as Anthropic.TextBlockParam).text).toContain("processed:")
|
||||
expect((content1 as Anthropic.TextBlockParam).text).toContain(
|
||||
"<feedback>Check 'some/path' (see below for file content)</feedback>",
|
||||
"<user_message>Check 'some/path' (see below for file content)</user_message>",
|
||||
)
|
||||
|
||||
// Regular tool result should not be processed
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ describe("Task Tool History Handling", () => {
|
|||
},
|
||||
{
|
||||
type: "text" as const,
|
||||
text: "Another message with <task> tags",
|
||||
text: "Another message with <user_message> tags",
|
||||
},
|
||||
{
|
||||
type: "tool_result" as const,
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ export class AskFollowupQuestionTool extends BaseTool<"ask_followup_question"> {
|
|||
task.consecutiveMistakeCount = 0
|
||||
const { text, images } = await task.ask("followup", JSON.stringify(follow_up_json), false)
|
||||
await task.say("user_feedback", text ?? "", images)
|
||||
pushToolResult(formatResponse.toolResult(`<answer>\n${text}\n</answer>`, images))
|
||||
pushToolResult(formatResponse.toolResult(`<user_message>\n${text}\n</user_message>`, images))
|
||||
} catch (error) {
|
||||
await handleError("asking question", error as Error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ export class AttemptCompletionTool extends BaseTool<"attempt_completion"> {
|
|||
// User provided feedback - push tool result to continue the conversation
|
||||
await task.say("user_feedback", text ?? "", images)
|
||||
|
||||
const feedbackText = `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>`
|
||||
const feedbackText = `<user_message>\n${text}\n</user_message>`
|
||||
pushToolResult(formatResponse.toolResult(feedbackText, images))
|
||||
} catch (error) {
|
||||
await handleError("inspecting site", error as Error)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue