fix(acp): harden resource link metadata formatting

This commit is contained in:
Peter Steinberger
2026-02-21 12:59:54 +01:00
parent 073651fb57
commit 6aa11f3092
2 changed files with 55 additions and 2 deletions

View File

@@ -6,6 +6,35 @@ export type GatewayAttachment = {
content: string;
};
function escapeInlineControlChars(value: string): string {
const withoutNull = value.replaceAll("\0", "\\0");
return withoutNull.replace(/[\r\n\t\v\f\u2028\u2029]/g, (char) => {
switch (char) {
case "\r":
return "\\r";
case "\n":
return "\\n";
case "\t":
return "\\t";
case "\v":
return "\\v";
case "\f":
return "\\f";
case "\u2028":
return "\\u2028";
case "\u2029":
return "\\u2029";
default:
return char;
}
});
}
function escapeResourceTitle(value: string): string {
// Keep title content, but escape characters that can break the resource-link annotation shape.
return escapeInlineControlChars(value).replace(/[()[\]]/g, (char) => `\\${char}`);
}
export function extractTextFromPrompt(prompt: ContentBlock[], maxBytes?: number): string {
const parts: string[] = [];
// Track accumulated byte count per block to catch oversized prompts before full concatenation
@@ -20,8 +49,8 @@ export function extractTextFromPrompt(prompt: ContentBlock[], maxBytes?: number)
blockText = resource.text;
}
} else if (block.type === "resource_link") {
const title = block.title ? ` (${block.title})` : "";
const uri = block.uri ?? "";
const title = block.title ? ` (${escapeResourceTitle(block.title)})` : "";
const uri = block.uri ? escapeInlineControlChars(block.uri) : "";
blockText = uri ? `[Resource link${title}] ${uri}` : `[Resource link${title}]`;
}
if (blockText !== undefined) {