fix(agents): decode smart-quoted arg escapes · openclaw/openclaw@fae5859
ferminquant
·
2026-05-29
·
via Recent Commits to openclaw:main
File tree
src/agents/embedded-agent-runner/run
| Original file line number | Diff line number | Diff line change |
|---|
@@ -312,6 +312,17 @@ const re = /\d+/;
|
312 | 312 | expectAllToolCallArgs(result, { path: "safe.txt" }); |
313 | 313 | }); |
314 | 314 | |
| 315 | +it("decodes JSON escapes inside smart-quoted string args", async () => { |
| 316 | +const result = await runToolCallRepairCase({ |
| 317 | +delta: String.raw` {“path”:“safe.txt”,“content”:“line\nnext \"quoted\" path C:\\tmp mark \u2713 invalid \d”}`, |
| 318 | +}); |
| 319 | + |
| 320 | +expectAllToolCallArgs(result, { |
| 321 | +path: "safe.txt", |
| 322 | +content: 'line\nnext "quoted" path C:\\tmp mark ✓ invalid \\d', |
| 323 | +}); |
| 324 | +}); |
| 325 | + |
315 | 326 | it("keeps duplicate-looking smart-quoted args inside content", async () => { |
316 | 327 | const result = await runToolCallRepairCase({ |
317 | 328 | delta: String.raw` {“path”:“safe.txt”,“content”:“text ”, “path”: “other.txt””}`, |
|
| Original file line number | Diff line number | Diff line change |
|---|
@@ -76,6 +76,16 @@ const TOOLCALL_REPAIR_FREEFORM_SUCCESSOR_KEYS: Record<string, string> = {
|
76 | 76 | old_string: "new_string", |
77 | 77 | oldText: "newText", |
78 | 78 | }; |
| 79 | +const TOOLCALL_REPAIR_JSON_STRING_ESCAPES: Record<string, string> = { |
| 80 | +'"': '"', |
| 81 | +"\\": "\\", |
| 82 | +"/": "/", |
| 83 | +b: "\b", |
| 84 | +f: "\f", |
| 85 | +n: "\n", |
| 86 | +r: "\r", |
| 87 | +t: "\t", |
| 88 | +}; |
79 | 89 | |
80 | 90 | function shouldAttemptMalformedToolCallRepair(partialJson: string, delta: string): boolean { |
81 | 91 | if (/[}\]]/.test(delta)) { |
@@ -239,6 +249,14 @@ function shouldCloseSmartQuotedValueAt(raw: string, quoteIndex: number, valueKey
|
239 | 249 | return TOOLCALL_REPAIR_FREEFORM_SUCCESSOR_KEYS[valueKey] === nextKey; |
240 | 250 | } |
241 | 251 | |
| 252 | +function decodeSmartQuotedJsonStringEscapes(value: string): string { |
| 253 | +return value.replace(/\\(?:(["\\/bfnrt])|u([0-9a-fA-F]{4}))/g, (_match, escaped, hex) => |
| 254 | +typeof hex === "string" |
| 255 | + ? String.fromCharCode(parseInt(hex, 16)) |
| 256 | + : TOOLCALL_REPAIR_JSON_STRING_ESCAPES[escaped as string], |
| 257 | +); |
| 258 | +} |
| 259 | + |
242 | 260 | function readSmartQuotedValue( |
243 | 261 | raw: string, |
244 | 262 | startIndex: number, |
@@ -248,7 +266,7 @@ function readSmartQuotedValue(
|
248 | 266 | for (let i = startIndex + 1; i < raw.length; i += 1) { |
249 | 267 | const char = raw[i]; |
250 | 268 | if (isToolCallRepairSmartQuote(char) && shouldCloseSmartQuotedValueAt(raw, i, key)) { |
251 | | -return { value, endIndex: i + 1 }; |
| 269 | +return { value: decodeSmartQuotedJsonStringEscapes(value), endIndex: i + 1 }; |
252 | 270 | } |
253 | 271 | value += char; |
254 | 272 | } |
|
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。