v2.2.2-xml-placeholder-reject: drop placeholder XML tool calls at parse time
Reject qwen3.6 spurious <invoke> tails with path "..." or empty args before they enter toolCalls, preventing duplicate assistant answers. Dropped blocks append to flushed text; four new xml-parser tests. DEFERRED-WORK §6 for console.debug → pino cleanup. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -270,6 +270,44 @@ describe('extractToolCallBlocks (v1.13.16 — unified extraction)', () => {
|
||||
expect(result.flushed).toBe(input);
|
||||
expect(result.remaining).toBe('');
|
||||
});
|
||||
|
||||
describe('placeholder arg rejection (qwen3.6 answer-then-spurious-tools)', () => {
|
||||
it('rejects <invoke> with path "..." — 0 calls, block in flushed', () => {
|
||||
const block = '<invoke name="view_file"><parameter name="path">...</parameter></invoke>';
|
||||
const result = extractToolCallBlocks(`Answer text.\n${block}`);
|
||||
expect(result.calls).toEqual([]);
|
||||
expect(result.flushed).toContain('Answer text.');
|
||||
expect(result.flushed).toContain(block);
|
||||
expect(result.remaining).toBe('');
|
||||
});
|
||||
|
||||
it('rejects <invoke> with empty path — 0 calls, block in flushed', () => {
|
||||
const block = '<invoke name="view_file"><parameter name="path"></parameter></invoke>';
|
||||
const result = extractToolCallBlocks(block);
|
||||
expect(result.calls).toEqual([]);
|
||||
expect(result.flushed).toBe(block);
|
||||
expect(result.remaining).toBe('');
|
||||
});
|
||||
|
||||
it('rejects <invoke> with path "<path>" — 0 calls', () => {
|
||||
const block = '<invoke name="view_file"><parameter name="path"><path></parameter></invoke>';
|
||||
const result = extractToolCallBlocks(block);
|
||||
expect(result.calls).toEqual([]);
|
||||
expect(result.flushed).toBe(block);
|
||||
});
|
||||
|
||||
it('returns 1 valid call and flushes placeholder block when mixed in same buffer', () => {
|
||||
const valid =
|
||||
'<invoke name="view_file"><parameter name="path">/opt/boocode/README.md</parameter></invoke>';
|
||||
const placeholder =
|
||||
'<invoke name="view_file"><parameter name="path">...</parameter></invoke>';
|
||||
const result = extractToolCallBlocks(`${valid} tail ${placeholder}`);
|
||||
expect(result.calls).toEqual([{ name: 'view_file', args: { path: '/opt/boocode/README.md' } }]);
|
||||
expect(result.flushed).toContain('tail');
|
||||
expect(result.flushed).toContain(placeholder);
|
||||
expect(result.remaining).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('levenshtein', () => {
|
||||
|
||||
Reference in New Issue
Block a user