@@ -12,6 +12,7 @@ import type { ContentPart } from '@pythoughts/kosong';
1212import { describe , expect , it } from 'vitest' ;
1313
1414import { createLoopEventDispatcher , runTurn as runTurnImpl , ToolAccesses } from '../../src/loop' ;
15+ import { parseToolCallArguments } from '../../src/loop/tool-call' ;
1516import type { Logger } from '../../src/logging' ;
1617import type {
1718 ExecutableTool ,
@@ -118,6 +119,42 @@ function makeTestLogger(): {
118119 return { log, entries } ;
119120}
120121
122+ describe ( 'parseToolCallArguments' , ( ) => {
123+ it ( 'repairs markdown-style escapes inside string values' , ( ) => {
124+ const result = parseToolCallArguments ( '{"a":"bold \\*text\\* and \\_x"}' ) ;
125+
126+ expect ( result ) . toEqual ( { success : true , data : { a : 'bold \\*text\\* and \\_x' } } ) ;
127+ } ) ;
128+
129+ it ( 'leaves valid escapes unchanged' , ( ) => {
130+ const raw = '{"a":"line\\nquote\\" uA slash\\\\/"}' ;
131+
132+ expect ( parseToolCallArguments ( raw ) ) . toEqual ( { success : true , data : JSON . parse ( raw ) } ) ;
133+ } ) ;
134+
135+ it ( 'repairs a bad unicode escape inside a string value' , ( ) => {
136+ const result = parseToolCallArguments ( '{"a":"\\u12ZZ"}' ) ;
137+
138+ expect ( result ) . toEqual ( { success : true , data : { a : '\\u12ZZ' } } ) ;
139+ } ) ;
140+
141+ it ( 'returns the original parse error for structurally broken input' , ( ) => {
142+ const raw = '{"a":"truncated' ;
143+ let originalError = '' ;
144+ try {
145+ JSON . parse ( raw ) ;
146+ } catch ( error ) {
147+ originalError = error instanceof Error ? error . message : String ( error ) ;
148+ }
149+
150+ expect ( parseToolCallArguments ( raw ) ) . toEqual ( { success : false , error : originalError } ) ;
151+ } ) ;
152+
153+ it ( 'does not repair a backslash outside a string' , ( ) => {
154+ expect ( parseToolCallArguments ( '{\\*"a":1}' ) . success ) . toBe ( false ) ;
155+ } ) ;
156+ } ) ;
157+
121158describe ( 'runTurn — tool-call behaviour' , ( ) => {
122159 it ( 'strips enabled intent before hooks, validation, execution, and persistence' , async ( ) => {
123160 const hookArgs : unknown [ ] = [ ] ;
0 commit comments