mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-16 12:03:23 +00:00
feat(ai): add partial JSON parsing for streaming tool calls
- Added partial-json package for parsing incomplete JSON during streaming
- Tool call arguments now contain partially parsed JSON during toolcall_delta events
- Enables progressive UI updates (e.g., showing file paths before content is complete)
- Arguments are always valid objects (minimum empty {}), never undefined
- Full validation still occurs at toolcall_end when arguments are complete
- Updated all providers (Anthropic, OpenAI Completions/Responses) to use parseStreamingJson
- Added comprehensive documentation and examples in README
- Added test to verify arguments are always defined during streaming
This commit is contained in:
parent
197259c88a
commit
39c626b6c9
10 changed files with 208 additions and 69 deletions
52
test-partial-json.js
Normal file
52
test-partial-json.js
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
import { parseStreamingJson } from "./packages/ai/dist/json-parse.js";
|
||||
|
||||
// Test cases for partial JSON parsing
|
||||
const testCases = [
|
||||
// Complete JSON
|
||||
{ input: '{"name":"test","value":42}', expected: {name: "test", value: 42} },
|
||||
|
||||
// Partial JSON - incomplete object
|
||||
{ input: '{"name":"test","val', expected: {name: "test"} },
|
||||
{ input: '{"name":"test"', expected: {name: "test"} },
|
||||
{ input: '{"name":', expected: {} },
|
||||
{ input: '{"', expected: {} },
|
||||
{ input: '{', expected: {} },
|
||||
|
||||
// Partial JSON - incomplete array
|
||||
{ input: '{"items":[1,2,3', expected: {items: [1, 2, 3]} },
|
||||
{ input: '{"items":[1,2,', expected: {items: [1, 2]} },
|
||||
{ input: '{"items":[', expected: {items: []} },
|
||||
|
||||
// Partial JSON - incomplete string
|
||||
{ input: '{"message":"Hello wor', expected: {message: "Hello wor"} },
|
||||
|
||||
// Empty or invalid
|
||||
{ input: '', expected: {} },
|
||||
{ input: null, expected: {} },
|
||||
{ input: undefined, expected: {} },
|
||||
|
||||
// Complex nested partial
|
||||
{ input: '{"user":{"name":"John","age":30,"address":{"city":"New Y', expected: {user: {name: "John", age: 30, address: {city: "New Y"}}} },
|
||||
];
|
||||
|
||||
console.log("Testing parseStreamingJson...\n");
|
||||
|
||||
let passed = 0;
|
||||
let failed = 0;
|
||||
|
||||
for (const test of testCases) {
|
||||
const result = parseStreamingJson(test.input);
|
||||
const success = JSON.stringify(result) === JSON.stringify(test.expected);
|
||||
|
||||
if (success) {
|
||||
console.log(`✅ PASS: "${test.input || '(empty)'}" -> ${JSON.stringify(result)}`);
|
||||
passed++;
|
||||
} else {
|
||||
console.log(`❌ FAIL: "${test.input || '(empty)'}"`);
|
||||
console.log(` Expected: ${JSON.stringify(test.expected)}`);
|
||||
console.log(` Got: ${JSON.stringify(result)}`);
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`\n${passed} passed, ${failed} failed`);
|
||||
Loading…
Add table
Add a link
Reference in a new issue