@ank1015/providers 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +93 -383
- package/dist/agent/conversation.d.ts +97 -0
- package/dist/agent/conversation.d.ts.map +1 -0
- package/dist/agent/conversation.js +328 -0
- package/dist/agent/conversation.js.map +1 -0
- package/dist/agent/runner.d.ts +37 -0
- package/dist/agent/runner.d.ts.map +1 -0
- package/dist/agent/runner.js +169 -0
- package/dist/agent/runner.js.map +1 -0
- package/dist/agent/tools/calculate.d.ts +15 -0
- package/dist/agent/tools/calculate.d.ts.map +1 -0
- package/dist/agent/tools/calculate.js +23 -0
- package/dist/agent/tools/calculate.js.map +1 -0
- package/dist/agent/tools/get-current-time.d.ts +15 -0
- package/dist/agent/tools/get-current-time.d.ts.map +1 -0
- package/dist/agent/tools/get-current-time.js +38 -0
- package/dist/agent/tools/get-current-time.js.map +1 -0
- package/dist/agent/tools/index.d.ts +3 -0
- package/dist/agent/tools/index.d.ts.map +1 -0
- package/dist/agent/tools/index.js +3 -0
- package/dist/agent/tools/index.js.map +1 -0
- package/dist/agent/types.d.ts +53 -31
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent/types.js +1 -2
- package/dist/agent/utils.d.ts +14 -0
- package/dist/agent/utils.d.ts.map +1 -0
- package/dist/agent/utils.js +59 -0
- package/dist/agent/utils.js.map +1 -0
- package/dist/index.d.ts +16 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/llm.d.ts +15 -0
- package/dist/llm.d.ts.map +1 -0
- package/dist/llm.js +92 -0
- package/dist/llm.js.map +1 -0
- package/dist/models.d.ts +8 -1
- package/dist/models.d.ts.map +1 -1
- package/dist/models.generated.d.ts +25 -112
- package/dist/models.generated.d.ts.map +1 -1
- package/dist/models.generated.js +72 -227
- package/dist/models.generated.js.map +1 -1
- package/dist/models.js +30 -32
- package/dist/models.js.map +1 -1
- package/dist/providers/google/complete.d.ts +3 -0
- package/dist/providers/google/complete.d.ts.map +1 -0
- package/dist/providers/google/complete.js +53 -0
- package/dist/providers/google/complete.js.map +1 -0
- package/dist/providers/google/index.d.ts +6 -0
- package/dist/providers/google/index.d.ts.map +1 -0
- package/dist/providers/google/index.js +6 -0
- package/dist/providers/google/index.js.map +1 -0
- package/dist/providers/google/stream.d.ts +3 -0
- package/dist/providers/google/stream.d.ts.map +1 -0
- package/dist/providers/{google.js → google/stream.js} +67 -231
- package/dist/providers/google/stream.js.map +1 -0
- package/dist/providers/google/types.d.ts +8 -0
- package/dist/providers/google/types.d.ts.map +1 -0
- package/dist/providers/google/types.js +2 -0
- package/dist/providers/google/types.js.map +1 -0
- package/dist/providers/google/utils.d.ts +30 -0
- package/dist/providers/google/utils.d.ts.map +1 -0
- package/dist/providers/google/utils.js +354 -0
- package/dist/providers/google/utils.js.map +1 -0
- package/dist/providers/openai/complete.d.ts +3 -0
- package/dist/providers/openai/complete.d.ts.map +1 -0
- package/dist/providers/openai/complete.js +57 -0
- package/dist/providers/openai/complete.js.map +1 -0
- package/dist/providers/openai/index.d.ts +4 -0
- package/dist/providers/openai/index.d.ts.map +1 -0
- package/dist/providers/openai/index.js +4 -0
- package/dist/providers/openai/index.js.map +1 -0
- package/dist/providers/openai/stream.d.ts +3 -0
- package/dist/providers/openai/stream.d.ts.map +1 -0
- package/dist/providers/{openai.js → openai/stream.js} +74 -152
- package/dist/providers/openai/stream.js.map +1 -0
- package/dist/providers/openai/types.d.ts +8 -0
- package/dist/providers/openai/types.d.ts.map +1 -0
- package/dist/providers/openai/types.js +2 -0
- package/dist/providers/openai/types.js.map +1 -0
- package/dist/providers/openai/utils.d.ts +13 -0
- package/dist/providers/openai/utils.d.ts.map +1 -0
- package/dist/providers/openai/utils.js +285 -0
- package/dist/providers/openai/utils.js.map +1 -0
- package/dist/types.d.ts +95 -87
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -9
- package/dist/types.js.map +1 -1
- package/dist/utils/event-stream.d.ts +2 -2
- package/dist/utils/event-stream.d.ts.map +1 -1
- package/dist/utils/event-stream.js +2 -7
- package/dist/utils/event-stream.js.map +1 -1
- package/dist/utils/json-parse.js +3 -6
- package/dist/utils/json-parse.js.map +1 -1
- package/dist/utils/overflow.d.ts +51 -0
- package/dist/utils/overflow.d.ts.map +1 -0
- package/dist/utils/overflow.js +106 -0
- package/dist/utils/overflow.js.map +1 -0
- package/dist/utils/sanitize-unicode.js +1 -4
- package/dist/utils/sanitize-unicode.js.map +1 -1
- package/dist/utils/uuid.d.ts +6 -0
- package/dist/utils/uuid.d.ts.map +1 -0
- package/dist/utils/uuid.js +9 -0
- package/dist/utils/uuid.js.map +1 -0
- package/dist/utils/validation.d.ts +10 -3
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +20 -12
- package/dist/utils/validation.js.map +1 -1
- package/package.json +47 -8
- package/biome.json +0 -43
- package/dist/agent/agent-loop.d.ts +0 -5
- package/dist/agent/agent-loop.d.ts.map +0 -1
- package/dist/agent/agent-loop.js +0 -219
- package/dist/agent/agent-loop.js.map +0 -1
- package/dist/providers/convert.d.ts +0 -6
- package/dist/providers/convert.d.ts.map +0 -1
- package/dist/providers/convert.js +0 -207
- package/dist/providers/convert.js.map +0 -1
- package/dist/providers/google.d.ts +0 -26
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/openai.d.ts +0 -17
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/providers/openai.js.map +0 -1
- package/dist/stream.d.ts +0 -4
- package/dist/stream.d.ts.map +0 -1
- package/dist/stream.js +0 -40
- package/dist/stream.js.map +0 -1
- package/dist/test-google-agent-loop.d.ts +0 -2
- package/dist/test-google-agent-loop.d.ts.map +0 -1
- package/dist/test-google-agent-loop.js +0 -186
- package/dist/test-google-agent-loop.js.map +0 -1
- package/dist/test-google.d.ts +0 -2
- package/dist/test-google.d.ts.map +0 -1
- package/dist/test-google.js +0 -41
- package/dist/test-google.js.map +0 -1
- package/src/agent/agent-loop.ts +0 -275
- package/src/agent/types.ts +0 -80
- package/src/index.ts +0 -72
- package/src/models.generated.ts +0 -314
- package/src/models.ts +0 -45
- package/src/providers/convert.ts +0 -222
- package/src/providers/google.ts +0 -496
- package/src/providers/openai.ts +0 -437
- package/src/stream.ts +0 -60
- package/src/types.ts +0 -198
- package/src/utils/event-stream.ts +0 -60
- package/src/utils/json-parse.ts +0 -28
- package/src/utils/sanitize-unicode.ts +0 -25
- package/src/utils/validation.ts +0 -69
- package/test/core/agent-loop.test.ts +0 -958
- package/test/core/stream.test.ts +0 -409
- package/test/data/red-circle.png +0 -0
- package/test/data/superintelligentwill.pdf +0 -0
- package/test/edge-cases/general.test.ts +0 -565
- package/test/integration/e2e.test.ts +0 -530
- package/test/models/cost.test.ts +0 -499
- package/test/models/registry.test.ts +0 -298
- package/test/providers/convert.test.ts +0 -846
- package/test/providers/google-schema.test.ts +0 -666
- package/test/providers/google-stream.test.ts +0 -369
- package/test/providers/openai-stream.test.ts +0 -251
- package/test/utils/event-stream.test.ts +0 -289
- package/test/utils/json-parse.test.ts +0 -344
- package/test/utils/sanitize-unicode.test.ts +0 -329
- package/test/utils/validation.test.ts +0 -614
- package/tsconfig.json +0 -21
- package/vitest.config.ts +0 -9
|
@@ -1,289 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { EventStream } from '../../src/utils/event-stream';
|
|
3
|
-
|
|
4
|
-
describe('EventStream', () => {
|
|
5
|
-
describe('Basic functionality', () => {
|
|
6
|
-
it('should push and iterate events', async () => {
|
|
7
|
-
const stream = new EventStream<string, number>();
|
|
8
|
-
|
|
9
|
-
// Push events
|
|
10
|
-
stream.push('event1');
|
|
11
|
-
stream.push('event2');
|
|
12
|
-
stream.push('event3');
|
|
13
|
-
stream.end(42);
|
|
14
|
-
|
|
15
|
-
// Collect events
|
|
16
|
-
const events: string[] = [];
|
|
17
|
-
for await (const event of stream) {
|
|
18
|
-
events.push(event);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
expect(events).toEqual(['event1', 'event2', 'event3']);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should handle result promise', async () => {
|
|
25
|
-
const stream = new EventStream<string, number>();
|
|
26
|
-
|
|
27
|
-
stream.push('event1');
|
|
28
|
-
stream.end(42);
|
|
29
|
-
|
|
30
|
-
const result = await stream.result();
|
|
31
|
-
expect(result).toBe(42);
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should handle result before end (waits for end)', async () => {
|
|
35
|
-
const stream = new EventStream<string, number>();
|
|
36
|
-
|
|
37
|
-
stream.push('event1');
|
|
38
|
-
|
|
39
|
-
// Request result before end
|
|
40
|
-
const resultPromise = stream.result();
|
|
41
|
-
|
|
42
|
-
// End stream after a delay
|
|
43
|
-
setTimeout(() => {
|
|
44
|
-
stream.end(42);
|
|
45
|
-
}, 10);
|
|
46
|
-
|
|
47
|
-
const result = await resultPromise;
|
|
48
|
-
expect(result).toBe(42);
|
|
49
|
-
});
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('Push multiple events before iteration', () => {
|
|
53
|
-
it('should queue events when no consumer is ready', async () => {
|
|
54
|
-
const stream = new EventStream<number, string>();
|
|
55
|
-
|
|
56
|
-
// Push many events before iteration starts
|
|
57
|
-
for (let i = 0; i < 100; i++) {
|
|
58
|
-
stream.push(i);
|
|
59
|
-
}
|
|
60
|
-
stream.end('done');
|
|
61
|
-
|
|
62
|
-
// Now iterate and collect
|
|
63
|
-
const events: number[] = [];
|
|
64
|
-
for await (const event of stream) {
|
|
65
|
-
events.push(event);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
expect(events).toHaveLength(100);
|
|
69
|
-
expect(events).toEqual(Array.from({ length: 100 }, (_, i) => i));
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe('Iteration waits for events (waiter-based)', () => {
|
|
74
|
-
it('should wait for events to arrive during iteration', async () => {
|
|
75
|
-
const stream = new EventStream<string, void>();
|
|
76
|
-
const events: string[] = [];
|
|
77
|
-
|
|
78
|
-
// Start iteration in background
|
|
79
|
-
const iterationPromise = (async () => {
|
|
80
|
-
for await (const event of stream) {
|
|
81
|
-
events.push(event);
|
|
82
|
-
}
|
|
83
|
-
})();
|
|
84
|
-
|
|
85
|
-
// Push events with delays
|
|
86
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
87
|
-
stream.push('event1');
|
|
88
|
-
|
|
89
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
90
|
-
stream.push('event2');
|
|
91
|
-
|
|
92
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
93
|
-
stream.push('event3');
|
|
94
|
-
|
|
95
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
96
|
-
stream.end();
|
|
97
|
-
|
|
98
|
-
// Wait for iteration to complete
|
|
99
|
-
await iterationPromise;
|
|
100
|
-
|
|
101
|
-
expect(events).toEqual(['event1', 'event2', 'event3']);
|
|
102
|
-
});
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
describe('Multiple concurrent iterators', () => {
|
|
106
|
-
it('should handle events distributed across multiple iterators', async () => {
|
|
107
|
-
// Note: EventStream is a queue-based system where events are consumed
|
|
108
|
-
// Multiple iterators will share/compete for events, not all receive all events
|
|
109
|
-
const stream = new EventStream<number, void>();
|
|
110
|
-
|
|
111
|
-
const events1: number[] = [];
|
|
112
|
-
const events2: number[] = [];
|
|
113
|
-
|
|
114
|
-
// Start two concurrent consumers
|
|
115
|
-
const consumer1 = (async () => {
|
|
116
|
-
for await (const event of stream) {
|
|
117
|
-
events1.push(event);
|
|
118
|
-
}
|
|
119
|
-
})();
|
|
120
|
-
|
|
121
|
-
const consumer2 = (async () => {
|
|
122
|
-
for await (const event of stream) {
|
|
123
|
-
events2.push(event);
|
|
124
|
-
}
|
|
125
|
-
})();
|
|
126
|
-
|
|
127
|
-
// Push events
|
|
128
|
-
stream.push(1);
|
|
129
|
-
stream.push(2);
|
|
130
|
-
stream.push(3);
|
|
131
|
-
stream.end();
|
|
132
|
-
|
|
133
|
-
await Promise.all([consumer1, consumer2]);
|
|
134
|
-
|
|
135
|
-
// Events should be distributed across consumers
|
|
136
|
-
const totalEvents = [...events1, ...events2];
|
|
137
|
-
expect(totalEvents.sort()).toEqual([1, 2, 3]);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
describe('Iteration after stream ended', () => {
|
|
142
|
-
it('should allow iteration after stream has ended', async () => {
|
|
143
|
-
const stream = new EventStream<string, number>();
|
|
144
|
-
|
|
145
|
-
stream.push('event1');
|
|
146
|
-
stream.push('event2');
|
|
147
|
-
stream.end(42);
|
|
148
|
-
|
|
149
|
-
// Wait a bit
|
|
150
|
-
await new Promise(resolve => setTimeout(resolve, 10));
|
|
151
|
-
|
|
152
|
-
// Now iterate (after stream has ended)
|
|
153
|
-
const events: string[] = [];
|
|
154
|
-
for await (const event of stream) {
|
|
155
|
-
events.push(event);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
expect(events).toEqual(['event1', 'event2']);
|
|
159
|
-
});
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
describe('Event queue behavior', () => {
|
|
163
|
-
it('should maintain event order', async () => {
|
|
164
|
-
const stream = new EventStream<number, void>();
|
|
165
|
-
|
|
166
|
-
// Push events rapidly
|
|
167
|
-
for (let i = 0; i < 1000; i++) {
|
|
168
|
-
stream.push(i);
|
|
169
|
-
}
|
|
170
|
-
stream.end();
|
|
171
|
-
|
|
172
|
-
// Collect and verify order
|
|
173
|
-
const events: number[] = [];
|
|
174
|
-
for await (const event of stream) {
|
|
175
|
-
events.push(event);
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
expect(events).toEqual(Array.from({ length: 1000 }, (_, i) => i));
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
describe('Type safety', () => {
|
|
183
|
-
it('should enforce event type', async () => {
|
|
184
|
-
interface CustomEvent {
|
|
185
|
-
type: string;
|
|
186
|
-
data: number;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const stream = new EventStream<CustomEvent, string>();
|
|
190
|
-
|
|
191
|
-
stream.push({ type: 'test', data: 42 });
|
|
192
|
-
stream.push({ type: 'another', data: 100 });
|
|
193
|
-
stream.end('final result');
|
|
194
|
-
|
|
195
|
-
const events: CustomEvent[] = [];
|
|
196
|
-
for await (const event of stream) {
|
|
197
|
-
events.push(event);
|
|
198
|
-
expect(event).toHaveProperty('type');
|
|
199
|
-
expect(event).toHaveProperty('data');
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const result = await stream.result();
|
|
203
|
-
expect(result).toBe('final result');
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe('Edge cases', () => {
|
|
208
|
-
it('should handle stream with no events', async () => {
|
|
209
|
-
const stream = new EventStream<string, number>();
|
|
210
|
-
stream.end(42);
|
|
211
|
-
|
|
212
|
-
const events: string[] = [];
|
|
213
|
-
for await (const event of stream) {
|
|
214
|
-
events.push(event);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
expect(events).toEqual([]);
|
|
218
|
-
expect(await stream.result()).toBe(42);
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
it('should handle undefined result', async () => {
|
|
222
|
-
const stream = new EventStream<string, undefined>();
|
|
223
|
-
stream.push('event1');
|
|
224
|
-
stream.end(undefined);
|
|
225
|
-
|
|
226
|
-
const result = await stream.result();
|
|
227
|
-
expect(result).toBeUndefined();
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
it('should handle null result', async () => {
|
|
231
|
-
const stream = new EventStream<string, null>();
|
|
232
|
-
stream.push('event1');
|
|
233
|
-
stream.end(null);
|
|
234
|
-
|
|
235
|
-
const result = await stream.result();
|
|
236
|
-
expect(result).toBeNull();
|
|
237
|
-
});
|
|
238
|
-
|
|
239
|
-
it('should handle complex object results', async () => {
|
|
240
|
-
interface Result {
|
|
241
|
-
status: string;
|
|
242
|
-
data: { items: number[] };
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
const stream = new EventStream<string, Result>();
|
|
246
|
-
stream.push('event1');
|
|
247
|
-
|
|
248
|
-
const expectedResult: Result = {
|
|
249
|
-
status: 'success',
|
|
250
|
-
data: { items: [1, 2, 3] }
|
|
251
|
-
};
|
|
252
|
-
stream.end(expectedResult);
|
|
253
|
-
|
|
254
|
-
const result = await stream.result();
|
|
255
|
-
expect(result).toEqual(expectedResult);
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
describe('Mixed push and iteration patterns', () => {
|
|
260
|
-
it('should handle events pushed during iteration', async () => {
|
|
261
|
-
const stream = new EventStream<number, void>();
|
|
262
|
-
const events: number[] = [];
|
|
263
|
-
let pushCount = 0;
|
|
264
|
-
|
|
265
|
-
// Start iteration
|
|
266
|
-
const iterationPromise = (async () => {
|
|
267
|
-
for await (const event of stream) {
|
|
268
|
-
events.push(event);
|
|
269
|
-
|
|
270
|
-
// Push more events during iteration
|
|
271
|
-
if (pushCount < 5) {
|
|
272
|
-
pushCount++;
|
|
273
|
-
setTimeout(() => stream.push(pushCount), 5);
|
|
274
|
-
} else if (pushCount === 5) {
|
|
275
|
-
pushCount++;
|
|
276
|
-
setTimeout(() => stream.end(), 5);
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
})();
|
|
280
|
-
|
|
281
|
-
// Start the process
|
|
282
|
-
stream.push(0);
|
|
283
|
-
|
|
284
|
-
await iterationPromise;
|
|
285
|
-
|
|
286
|
-
expect(events).toHaveLength(6); // 0, 1, 2, 3, 4, 5
|
|
287
|
-
});
|
|
288
|
-
});
|
|
289
|
-
});
|
|
@@ -1,344 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
import { parseStreamingJson } from '../../src/utils/json-parse';
|
|
3
|
-
|
|
4
|
-
describe('parseStreamingJson', () => {
|
|
5
|
-
describe('Complete valid JSON', () => {
|
|
6
|
-
it('should parse complete valid object', () => {
|
|
7
|
-
const json = '{"name": "John", "age": 30}';
|
|
8
|
-
const result = parseStreamingJson(json);
|
|
9
|
-
|
|
10
|
-
expect(result).toEqual({ name: 'John', age: 30 });
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it('should parse complete valid array', () => {
|
|
14
|
-
const json = '[1, 2, 3, 4, 5]';
|
|
15
|
-
const result = parseStreamingJson(json);
|
|
16
|
-
|
|
17
|
-
expect(result).toEqual([1, 2, 3, 4, 5]);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should parse nested objects', () => {
|
|
21
|
-
const json = '{"user": {"name": "John", "address": {"city": "NYC"}}}';
|
|
22
|
-
const result = parseStreamingJson(json);
|
|
23
|
-
|
|
24
|
-
expect(result).toEqual({
|
|
25
|
-
user: {
|
|
26
|
-
name: 'John',
|
|
27
|
-
address: {
|
|
28
|
-
city: 'NYC',
|
|
29
|
-
},
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
it('should parse complex nested structure', () => {
|
|
35
|
-
const json = '{"items": [{"id": 1, "data": {"value": true}}, {"id": 2}]}';
|
|
36
|
-
const result = parseStreamingJson(json);
|
|
37
|
-
|
|
38
|
-
expect(result).toEqual({
|
|
39
|
-
items: [
|
|
40
|
-
{ id: 1, data: { value: true } },
|
|
41
|
-
{ id: 2 },
|
|
42
|
-
],
|
|
43
|
-
});
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should parse JSON with special characters', () => {
|
|
47
|
-
const json = '{"text": "Hello\\nWorld\\t!", "emoji": "😀"}';
|
|
48
|
-
const result = parseStreamingJson(json);
|
|
49
|
-
|
|
50
|
-
expect(result).toEqual({
|
|
51
|
-
text: 'Hello\nWorld\t!',
|
|
52
|
-
emoji: '😀',
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('should parse JSON with numbers', () => {
|
|
57
|
-
const json = '{"int": 42, "float": 3.14, "negative": -10, "exp": 1e5}';
|
|
58
|
-
const result = parseStreamingJson(json);
|
|
59
|
-
|
|
60
|
-
expect(result).toEqual({
|
|
61
|
-
int: 42,
|
|
62
|
-
float: 3.14,
|
|
63
|
-
negative: -10,
|
|
64
|
-
exp: 100000,
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should parse JSON with booleans and null', () => {
|
|
69
|
-
const json = '{"isTrue": true, "isFalse": false, "empty": null}';
|
|
70
|
-
const result = parseStreamingJson(json);
|
|
71
|
-
|
|
72
|
-
expect(result).toEqual({
|
|
73
|
-
isTrue: true,
|
|
74
|
-
isFalse: false,
|
|
75
|
-
empty: null,
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
describe('Incomplete JSON (partial)', () => {
|
|
81
|
-
it('should handle incomplete object (missing closing brace)', () => {
|
|
82
|
-
const json = '{"name": "John", "age": 30';
|
|
83
|
-
const result = parseStreamingJson(json);
|
|
84
|
-
|
|
85
|
-
// partial-json library should handle this
|
|
86
|
-
expect(result).toBeDefined();
|
|
87
|
-
expect(typeof result).toBe('object');
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('should handle incomplete array (missing closing bracket)', () => {
|
|
91
|
-
const json = '[1, 2, 3, 4';
|
|
92
|
-
const result = parseStreamingJson(json);
|
|
93
|
-
|
|
94
|
-
expect(result).toBeDefined();
|
|
95
|
-
expect(Array.isArray(result) || typeof result === 'object').toBe(true);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it('should handle incomplete string value', () => {
|
|
99
|
-
const json = '{"name": "John';
|
|
100
|
-
const result = parseStreamingJson(json);
|
|
101
|
-
|
|
102
|
-
expect(result).toBeDefined();
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
it('should handle partial nested object', () => {
|
|
106
|
-
const json = '{"user": {"name": "John", "address": {';
|
|
107
|
-
const result = parseStreamingJson(json);
|
|
108
|
-
|
|
109
|
-
expect(result).toBeDefined();
|
|
110
|
-
expect(typeof result).toBe('object');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should handle partial array in object', () => {
|
|
114
|
-
const json = '{"items": [1, 2';
|
|
115
|
-
const result = parseStreamingJson(json);
|
|
116
|
-
|
|
117
|
-
expect(result).toBeDefined();
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it('should handle incomplete key-value pair', () => {
|
|
121
|
-
const json = '{"name": "John", "age":';
|
|
122
|
-
const result = parseStreamingJson(json);
|
|
123
|
-
|
|
124
|
-
expect(result).toBeDefined();
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should handle trailing comma', () => {
|
|
128
|
-
const json = '{"name": "John", "age": 30,';
|
|
129
|
-
const result = parseStreamingJson(json);
|
|
130
|
-
|
|
131
|
-
expect(result).toBeDefined();
|
|
132
|
-
});
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
describe('Invalid JSON', () => {
|
|
136
|
-
it('should return empty object for completely invalid JSON', () => {
|
|
137
|
-
const json = 'this is not json at all';
|
|
138
|
-
const result = parseStreamingJson(json);
|
|
139
|
-
|
|
140
|
-
expect(result).toEqual({});
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it('should return empty object for malformed JSON', () => {
|
|
144
|
-
const json = '{name: John}'; // Missing quotes
|
|
145
|
-
const result = parseStreamingJson(json);
|
|
146
|
-
|
|
147
|
-
expect(result).toEqual({});
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it('should return empty object for random characters', () => {
|
|
151
|
-
const json = '!@#$%^&*()';
|
|
152
|
-
const result = parseStreamingJson(json);
|
|
153
|
-
|
|
154
|
-
expect(result).toEqual({});
|
|
155
|
-
});
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
describe('Empty input', () => {
|
|
159
|
-
it('should handle empty string', () => {
|
|
160
|
-
const json = '';
|
|
161
|
-
const result = parseStreamingJson(json);
|
|
162
|
-
|
|
163
|
-
expect(result).toEqual({});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
it('should handle whitespace only', () => {
|
|
167
|
-
const json = ' \n\t ';
|
|
168
|
-
const result = parseStreamingJson(json);
|
|
169
|
-
|
|
170
|
-
expect(result).toEqual({});
|
|
171
|
-
});
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
describe('Tool argument streaming scenarios', () => {
|
|
175
|
-
it('should handle streaming tool arguments (early stage)', () => {
|
|
176
|
-
const json = '{"expressi';
|
|
177
|
-
const result = parseStreamingJson(json);
|
|
178
|
-
|
|
179
|
-
// Should not crash and return something
|
|
180
|
-
expect(result).toBeDefined();
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
it('should handle streaming tool arguments (mid stage)', () => {
|
|
184
|
-
const json = '{"expression": "2 + 2';
|
|
185
|
-
const result = parseStreamingJson(json);
|
|
186
|
-
|
|
187
|
-
expect(result).toBeDefined();
|
|
188
|
-
if (typeof result === 'object' && result !== null && 'expression' in result) {
|
|
189
|
-
expect(typeof (result as any).expression).toBe('string');
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
it('should handle streaming tool arguments (near complete)', () => {
|
|
194
|
-
const json = '{"expression": "2 + 2", "format": "decimal"';
|
|
195
|
-
const result = parseStreamingJson(json);
|
|
196
|
-
|
|
197
|
-
expect(result).toBeDefined();
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('should handle complex tool arguments partial', () => {
|
|
201
|
-
const json = '{"query": "search term", "filters": {"category": "tech", "date":';
|
|
202
|
-
const result = parseStreamingJson(json);
|
|
203
|
-
|
|
204
|
-
expect(result).toBeDefined();
|
|
205
|
-
expect(typeof result).toBe('object');
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('should handle array argument partial', () => {
|
|
209
|
-
const json = '{"ids": [1, 2, 3';
|
|
210
|
-
const result = parseStreamingJson(json);
|
|
211
|
-
|
|
212
|
-
expect(result).toBeDefined();
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('Unicode handling', () => {
|
|
217
|
-
it('should handle Unicode characters', () => {
|
|
218
|
-
const json = '{"text": "Hello 世界", "emoji": "🎉"}';
|
|
219
|
-
const result = parseStreamingJson(json);
|
|
220
|
-
|
|
221
|
-
expect(result).toEqual({
|
|
222
|
-
text: 'Hello 世界',
|
|
223
|
-
emoji: '🎉',
|
|
224
|
-
});
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
it('should handle escaped Unicode', () => {
|
|
228
|
-
const json = '{"text": "\\u0048\\u0065\\u006C\\u006C\\u006F"}'; // "Hello"
|
|
229
|
-
const result = parseStreamingJson(json);
|
|
230
|
-
|
|
231
|
-
expect(result).toEqual({ text: 'Hello' });
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
describe('Escaped characters', () => {
|
|
236
|
-
it('should handle escaped quotes', () => {
|
|
237
|
-
const json = '{"text": "He said \\"Hello\\""}';
|
|
238
|
-
const result = parseStreamingJson(json);
|
|
239
|
-
|
|
240
|
-
expect(result).toEqual({ text: 'He said "Hello"' });
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should handle escaped backslashes', () => {
|
|
244
|
-
const json = '{"path": "C:\\\\Users\\\\John"}';
|
|
245
|
-
const result = parseStreamingJson(json);
|
|
246
|
-
|
|
247
|
-
expect(result).toEqual({ path: 'C:\\Users\\John' });
|
|
248
|
-
});
|
|
249
|
-
|
|
250
|
-
it('should handle multiple escape sequences', () => {
|
|
251
|
-
const json = '{"text": "Line1\\nLine2\\tTabbed\\rReturn"}';
|
|
252
|
-
const result = parseStreamingJson(json);
|
|
253
|
-
|
|
254
|
-
expect(result).toEqual({
|
|
255
|
-
text: 'Line1\nLine2\tTabbed\rReturn',
|
|
256
|
-
});
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
describe('Large JSON', () => {
|
|
261
|
-
it('should handle large object', () => {
|
|
262
|
-
const largeObj: Record<string, number> = {};
|
|
263
|
-
for (let i = 0; i < 1000; i++) {
|
|
264
|
-
largeObj[`key${i}`] = i;
|
|
265
|
-
}
|
|
266
|
-
const json = JSON.stringify(largeObj);
|
|
267
|
-
const result = parseStreamingJson(json);
|
|
268
|
-
|
|
269
|
-
expect(result).toEqual(largeObj);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('should handle large array', () => {
|
|
273
|
-
const largeArray = Array.from({ length: 1000 }, (_, i) => i);
|
|
274
|
-
const json = JSON.stringify(largeArray);
|
|
275
|
-
const result = parseStreamingJson(json);
|
|
276
|
-
|
|
277
|
-
expect(result).toEqual(largeArray);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
describe('Edge cases', () => {
|
|
282
|
-
it('should handle single character', () => {
|
|
283
|
-
const json = '{';
|
|
284
|
-
const result = parseStreamingJson(json);
|
|
285
|
-
|
|
286
|
-
expect(result).toBeDefined();
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it('should handle just opening bracket', () => {
|
|
290
|
-
const json = '[';
|
|
291
|
-
const result = parseStreamingJson(json);
|
|
292
|
-
|
|
293
|
-
expect(result).toBeDefined();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('should handle empty object', () => {
|
|
297
|
-
const json = '{}';
|
|
298
|
-
const result = parseStreamingJson(json);
|
|
299
|
-
|
|
300
|
-
expect(result).toEqual({});
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
it('should handle empty array', () => {
|
|
304
|
-
const json = '[]';
|
|
305
|
-
const result = parseStreamingJson(json);
|
|
306
|
-
|
|
307
|
-
expect(result).toEqual([]);
|
|
308
|
-
});
|
|
309
|
-
|
|
310
|
-
it('should handle deeply nested structures', () => {
|
|
311
|
-
const json = '{"a":{"b":{"c":{"d":{"e":"value"}}}}}';
|
|
312
|
-
const result = parseStreamingJson(json);
|
|
313
|
-
|
|
314
|
-
expect(result).toEqual({
|
|
315
|
-
a: { b: { c: { d: { e: 'value' } } } },
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
it('should handle mixed array elements', () => {
|
|
320
|
-
const json = '[1, "two", true, null, {"key": "value"}]';
|
|
321
|
-
const result = parseStreamingJson(json);
|
|
322
|
-
|
|
323
|
-
expect(result).toEqual([1, 'two', true, null, { key: 'value' }]);
|
|
324
|
-
});
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
describe('Fallback behavior', () => {
|
|
328
|
-
it('should fallback to partial-json for incomplete JSON', () => {
|
|
329
|
-
// Standard JSON.parse would fail, but parseStreamingJson should handle it
|
|
330
|
-
const json = '{"key": "val';
|
|
331
|
-
|
|
332
|
-
expect(() => JSON.parse(json)).toThrow();
|
|
333
|
-
expect(() => parseStreamingJson(json)).not.toThrow();
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('should try standard JSON.parse first for complete JSON', () => {
|
|
337
|
-
const json = '{"valid": "json"}';
|
|
338
|
-
const result = parseStreamingJson(json);
|
|
339
|
-
|
|
340
|
-
// Should work via standard JSON.parse (faster path)
|
|
341
|
-
expect(result).toEqual({ valid: 'json' });
|
|
342
|
-
});
|
|
343
|
-
});
|
|
344
|
-
});
|