fix(tools): avoid rendering undefined feedback; omit empty feedback line

refactor(mentions): always process text; remove no-op gate; update docstring
This commit is contained in:
Hannes Rudolph 2025-11-03 19:12:03 -07:00
parent 7171bffd8c
commit b899f29557
3 changed files with 30 additions and 41 deletions

View file

@ -4,7 +4,7 @@ import { UrlContentFetcher } from "../../services/browser/UrlContentFetcher"
import { FileContextTracker } from "../context-tracking/FileContextTracker"
/**
* Process mentions in user content, specifically within task and feedback tags
* Process mentions in all user content uniformly (text and tool_result text blocks).
*/
export async function processUserContentMentions({
userContent,
@ -35,14 +35,27 @@ export async function processUserContentMentions({
// 3. ToolResultBlockParam's array content where blocks are text type
return Promise.all(
userContent.map(async (block) => {
const shouldProcessMentions = (_text: string) => true
if (block.type === "text") {
if (shouldProcessMentions(block.text)) {
return {
...block,
text: await parseMentions(
block.text,
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles,
includeDiagnosticMessages,
maxDiagnosticMessages,
maxReadFileLine,
),
}
} else if (block.type === "tool_result") {
if (typeof block.content === "string") {
return {
...block,
text: await parseMentions(
block.text,
content: await parseMentions(
block.content,
cwd,
urlContentFetcher,
fileContextTracker,
@ -53,33 +66,10 @@ export async function processUserContentMentions({
maxReadFileLine,
),
}
}
return block
} else if (block.type === "tool_result") {
if (typeof block.content === "string") {
if (shouldProcessMentions(block.content)) {
return {
...block,
content: await parseMentions(
block.content,
cwd,
urlContentFetcher,
fileContextTracker,
rooIgnoreController,
showRooIgnoredFiles,
includeDiagnosticMessages,
maxDiagnosticMessages,
maxReadFileLine,
),
}
}
return block
} else if (Array.isArray(block.content)) {
const parsedContent = await Promise.all(
block.content.map(async (contentBlock) => {
if (contentBlock.type === "text" && shouldProcessMentions(contentBlock.text)) {
if (contentBlock.type === "text") {
return {
...contentBlock,
text: await parseMentions(

View file

@ -123,9 +123,10 @@ export async function attemptCompletionTool(
await cline.say("user_feedback", text ?? "", images)
const toolResults: (Anthropic.TextBlockParam | Anthropic.ImageBlockParam)[] = []
const feedbackSuffix = text && text.trim().length > 0 ? `\n${text}` : ""
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${text}`,
text: `The user has provided feedback on the results. Consider their input to continue the task, and then attempt completion again.${feedbackSuffix}`,
})
toolResults.push(...formatResponse.imageBlocks(images))

View file

@ -311,17 +311,15 @@ export async function executeCommand(
const { text, images } = message
await task.say("user_feedback", text, images)
return [
true,
formatResponse.toolResult(
[
`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:\n${text}`,
].join("\n"),
images,
),
const parts: string[] = [
`Command is still running in terminal from '${terminal.getCurrentWorkingDirectory().toPosix()}'.`,
result.length > 0 ? `Here's the output so far:\n${result}\n` : "\n",
]
if (text && text.trim().length > 0) {
parts.push(`The user provided the following feedback:\n${text}`)
}
return [true, formatResponse.toolResult(parts.join("\n"), images)]
} else if (completed || exitDetails) {
let exitStatus: string = ""