@ank1015/providers 0.0.1 → 0.0.2

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.
Files changed (169) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -383
  3. package/dist/agent/conversation.d.ts +97 -0
  4. package/dist/agent/conversation.d.ts.map +1 -0
  5. package/dist/agent/conversation.js +328 -0
  6. package/dist/agent/conversation.js.map +1 -0
  7. package/dist/agent/runner.d.ts +37 -0
  8. package/dist/agent/runner.d.ts.map +1 -0
  9. package/dist/agent/runner.js +169 -0
  10. package/dist/agent/runner.js.map +1 -0
  11. package/dist/agent/tools/calculate.d.ts +15 -0
  12. package/dist/agent/tools/calculate.d.ts.map +1 -0
  13. package/dist/agent/tools/calculate.js +23 -0
  14. package/dist/agent/tools/calculate.js.map +1 -0
  15. package/dist/agent/tools/get-current-time.d.ts +15 -0
  16. package/dist/agent/tools/get-current-time.d.ts.map +1 -0
  17. package/dist/agent/tools/get-current-time.js +38 -0
  18. package/dist/agent/tools/get-current-time.js.map +1 -0
  19. package/dist/agent/tools/index.d.ts +3 -0
  20. package/dist/agent/tools/index.d.ts.map +1 -0
  21. package/dist/agent/tools/index.js +3 -0
  22. package/dist/agent/tools/index.js.map +1 -0
  23. package/dist/agent/types.d.ts +53 -31
  24. package/dist/agent/types.d.ts.map +1 -1
  25. package/dist/agent/types.js +1 -2
  26. package/dist/agent/utils.d.ts +14 -0
  27. package/dist/agent/utils.d.ts.map +1 -0
  28. package/dist/agent/utils.js +59 -0
  29. package/dist/agent/utils.js.map +1 -0
  30. package/dist/index.d.ts +16 -9
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +16 -28
  33. package/dist/index.js.map +1 -1
  34. package/dist/llm.d.ts +15 -0
  35. package/dist/llm.d.ts.map +1 -0
  36. package/dist/llm.js +92 -0
  37. package/dist/llm.js.map +1 -0
  38. package/dist/models.d.ts +8 -1
  39. package/dist/models.d.ts.map +1 -1
  40. package/dist/models.generated.d.ts +25 -112
  41. package/dist/models.generated.d.ts.map +1 -1
  42. package/dist/models.generated.js +72 -227
  43. package/dist/models.generated.js.map +1 -1
  44. package/dist/models.js +30 -32
  45. package/dist/models.js.map +1 -1
  46. package/dist/providers/google/complete.d.ts +3 -0
  47. package/dist/providers/google/complete.d.ts.map +1 -0
  48. package/dist/providers/google/complete.js +53 -0
  49. package/dist/providers/google/complete.js.map +1 -0
  50. package/dist/providers/google/index.d.ts +6 -0
  51. package/dist/providers/google/index.d.ts.map +1 -0
  52. package/dist/providers/google/index.js +6 -0
  53. package/dist/providers/google/index.js.map +1 -0
  54. package/dist/providers/google/stream.d.ts +3 -0
  55. package/dist/providers/google/stream.d.ts.map +1 -0
  56. package/dist/providers/{google.js → google/stream.js} +67 -231
  57. package/dist/providers/google/stream.js.map +1 -0
  58. package/dist/providers/google/types.d.ts +8 -0
  59. package/dist/providers/google/types.d.ts.map +1 -0
  60. package/dist/providers/google/types.js +2 -0
  61. package/dist/providers/google/types.js.map +1 -0
  62. package/dist/providers/google/utils.d.ts +30 -0
  63. package/dist/providers/google/utils.d.ts.map +1 -0
  64. package/dist/providers/google/utils.js +354 -0
  65. package/dist/providers/google/utils.js.map +1 -0
  66. package/dist/providers/openai/complete.d.ts +3 -0
  67. package/dist/providers/openai/complete.d.ts.map +1 -0
  68. package/dist/providers/openai/complete.js +57 -0
  69. package/dist/providers/openai/complete.js.map +1 -0
  70. package/dist/providers/openai/index.d.ts +4 -0
  71. package/dist/providers/openai/index.d.ts.map +1 -0
  72. package/dist/providers/openai/index.js +4 -0
  73. package/dist/providers/openai/index.js.map +1 -0
  74. package/dist/providers/openai/stream.d.ts +3 -0
  75. package/dist/providers/openai/stream.d.ts.map +1 -0
  76. package/dist/providers/{openai.js → openai/stream.js} +74 -152
  77. package/dist/providers/openai/stream.js.map +1 -0
  78. package/dist/providers/openai/types.d.ts +8 -0
  79. package/dist/providers/openai/types.d.ts.map +1 -0
  80. package/dist/providers/openai/types.js +2 -0
  81. package/dist/providers/openai/types.js.map +1 -0
  82. package/dist/providers/openai/utils.d.ts +13 -0
  83. package/dist/providers/openai/utils.d.ts.map +1 -0
  84. package/dist/providers/openai/utils.js +285 -0
  85. package/dist/providers/openai/utils.js.map +1 -0
  86. package/dist/types.d.ts +95 -87
  87. package/dist/types.d.ts.map +1 -1
  88. package/dist/types.js +1 -9
  89. package/dist/types.js.map +1 -1
  90. package/dist/utils/event-stream.d.ts +2 -2
  91. package/dist/utils/event-stream.d.ts.map +1 -1
  92. package/dist/utils/event-stream.js +2 -7
  93. package/dist/utils/event-stream.js.map +1 -1
  94. package/dist/utils/json-parse.js +3 -6
  95. package/dist/utils/json-parse.js.map +1 -1
  96. package/dist/utils/overflow.d.ts +51 -0
  97. package/dist/utils/overflow.d.ts.map +1 -0
  98. package/dist/utils/overflow.js +106 -0
  99. package/dist/utils/overflow.js.map +1 -0
  100. package/dist/utils/sanitize-unicode.js +1 -4
  101. package/dist/utils/sanitize-unicode.js.map +1 -1
  102. package/dist/utils/uuid.d.ts +6 -0
  103. package/dist/utils/uuid.d.ts.map +1 -0
  104. package/dist/utils/uuid.js +9 -0
  105. package/dist/utils/uuid.js.map +1 -0
  106. package/dist/utils/validation.d.ts +10 -3
  107. package/dist/utils/validation.d.ts.map +1 -1
  108. package/dist/utils/validation.js +20 -12
  109. package/dist/utils/validation.js.map +1 -1
  110. package/package.json +45 -8
  111. package/biome.json +0 -43
  112. package/dist/agent/agent-loop.d.ts +0 -5
  113. package/dist/agent/agent-loop.d.ts.map +0 -1
  114. package/dist/agent/agent-loop.js +0 -219
  115. package/dist/agent/agent-loop.js.map +0 -1
  116. package/dist/providers/convert.d.ts +0 -6
  117. package/dist/providers/convert.d.ts.map +0 -1
  118. package/dist/providers/convert.js +0 -207
  119. package/dist/providers/convert.js.map +0 -1
  120. package/dist/providers/google.d.ts +0 -26
  121. package/dist/providers/google.d.ts.map +0 -1
  122. package/dist/providers/google.js.map +0 -1
  123. package/dist/providers/openai.d.ts +0 -17
  124. package/dist/providers/openai.d.ts.map +0 -1
  125. package/dist/providers/openai.js.map +0 -1
  126. package/dist/stream.d.ts +0 -4
  127. package/dist/stream.d.ts.map +0 -1
  128. package/dist/stream.js +0 -40
  129. package/dist/stream.js.map +0 -1
  130. package/dist/test-google-agent-loop.d.ts +0 -2
  131. package/dist/test-google-agent-loop.d.ts.map +0 -1
  132. package/dist/test-google-agent-loop.js +0 -186
  133. package/dist/test-google-agent-loop.js.map +0 -1
  134. package/dist/test-google.d.ts +0 -2
  135. package/dist/test-google.d.ts.map +0 -1
  136. package/dist/test-google.js +0 -41
  137. package/dist/test-google.js.map +0 -1
  138. package/src/agent/agent-loop.ts +0 -275
  139. package/src/agent/types.ts +0 -80
  140. package/src/index.ts +0 -72
  141. package/src/models.generated.ts +0 -314
  142. package/src/models.ts +0 -45
  143. package/src/providers/convert.ts +0 -222
  144. package/src/providers/google.ts +0 -496
  145. package/src/providers/openai.ts +0 -437
  146. package/src/stream.ts +0 -60
  147. package/src/types.ts +0 -198
  148. package/src/utils/event-stream.ts +0 -60
  149. package/src/utils/json-parse.ts +0 -28
  150. package/src/utils/sanitize-unicode.ts +0 -25
  151. package/src/utils/validation.ts +0 -69
  152. package/test/core/agent-loop.test.ts +0 -958
  153. package/test/core/stream.test.ts +0 -409
  154. package/test/data/red-circle.png +0 -0
  155. package/test/data/superintelligentwill.pdf +0 -0
  156. package/test/edge-cases/general.test.ts +0 -565
  157. package/test/integration/e2e.test.ts +0 -530
  158. package/test/models/cost.test.ts +0 -499
  159. package/test/models/registry.test.ts +0 -298
  160. package/test/providers/convert.test.ts +0 -846
  161. package/test/providers/google-schema.test.ts +0 -666
  162. package/test/providers/google-stream.test.ts +0 -369
  163. package/test/providers/openai-stream.test.ts +0 -251
  164. package/test/utils/event-stream.test.ts +0 -289
  165. package/test/utils/json-parse.test.ts +0 -344
  166. package/test/utils/sanitize-unicode.test.ts +0 -329
  167. package/test/utils/validation.test.ts +0 -614
  168. package/tsconfig.json +0 -21
  169. 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
- });