diff --git a/packages/core/src/tool/html-markdown.ts b/packages/core/src/tool/html-markdown.ts index 557b9c7fa2e..65766ab5165 100644 --- a/packages/core/src/tool/html-markdown.ts +++ b/packages/core/src/tool/html-markdown.ts @@ -217,13 +217,20 @@ export function convertHTMLToMarkdown(html: string) { } if (code.inline) { const fence = "`".repeat(Math.max(1, backticks + 1)) - const padding = /^ | $/.test(code.text) && !/^ +$/.test(code.text) ? " " : "" flushSpace() prefixQuote() - const wrapper = encoder.encode(`${fence}${padding}${padding}${fence}`).byteLength - appendRaw( - `${fence}${padding}${sliceBytes(code.text, Math.max(0, CONTENT_BYTES - outputBytes - wrapper))}${padding}${fence}`, - ) + const available = Math.max(0, CONTENT_BYTES - outputBytes - fence.length * 2) + let payload = sliceBytes(code.text, available) + while (payload) { + const padding = /^[ `]|[ `]$/.test(payload) && !/^ +$/.test(payload) ? " " : "" + const bytes = encoder.encode(payload).byteLength + if (bytes + padding.length * 2 <= available) { + appendRaw(`${fence}${padding}${payload}${padding}${fence}`) + return + } + // Padding costs at most two bytes, so at most two whole-code-point trims are needed. + payload = sliceBytes(payload, bytes - 1) + } return } if (activeCell) { diff --git a/packages/core/test/tool-webfetch.test.ts b/packages/core/test/tool-webfetch.test.ts index 1f1ec9aee9b..bcec31a6735 100644 --- a/packages/core/test/tool-webfetch.test.ts +++ b/packages/core/test/tool-webfetch.test.ts @@ -90,6 +90,53 @@ describe("WebFetchTool helpers", () => { ) }) + test.each([ + ["`x`", "`` `x` ``"], + ["`x", "`` `x ``"], + ["x`", "`` x` ``"], + ["`", "`` ` ``"], + ["``", "``` `` ```"], + ["``x`", "``` ``x` ```"], + ["say(`x`)", "``say(`x`)``"], + ["a``b`c", "```a``b`c```"], + ["x", "`x`"], + [" x ", "` x `"], + [" x", "` x `"], + ["x ", "` x `"], + [" ", "` `"], + [" ` ", "`` ` ``"], + ])("preserves inline code boundaries for %j", (content, expected) => { + expect(WebFetchTool.convertHTMLToMarkdown(`
Use ${content}.
${prefix}${content}
beta first
beta second