@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.
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 +47 -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,369 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { Context } from '../../src/types';
3
- import { MODELS } from '../../src/models.generated';
4
- import { transformSchemaForGoogle } from '../../src/providers/google';
5
- import { buildGoogleMessages } from '../../src/providers/convert';
6
-
7
- describe('Google Provider Streaming Tests', () => {
8
- const model = MODELS.google['gemini-2.5-flash'];
9
-
10
- describe('Schema transformation', () => {
11
- it('should transform const to enum', () => {
12
-
13
- const schema = {
14
- type: 'string',
15
- const: 'active',
16
- };
17
-
18
- const result = transformSchemaForGoogle(schema);
19
-
20
- expect(result).toHaveProperty('enum');
21
- expect(result.enum).toEqual(['active']);
22
- expect(result).not.toHaveProperty('const');
23
- });
24
-
25
- it('should transform anyOf with const values to enum', () => {
26
-
27
- const schema = {
28
- anyOf: [
29
- { const: 'option1' },
30
- { const: 'option2' },
31
- { const: 'option3' },
32
- ],
33
- };
34
-
35
- const result = transformSchemaForGoogle(schema);
36
-
37
- expect(result).toHaveProperty('enum');
38
- expect(result.enum).toEqual(['option1', 'option2', 'option3']);
39
- expect(result).not.toHaveProperty('anyOf');
40
- });
41
-
42
- it('should recursively transform nested schemas', () => {
43
-
44
- const schema = {
45
- type: 'object',
46
- properties: {
47
- status: { const: 'active' },
48
- priority: {
49
- anyOf: [
50
- { const: 'high' },
51
- { const: 'low' },
52
- ],
53
- },
54
- },
55
- };
56
-
57
- const result = transformSchemaForGoogle(schema);
58
-
59
- expect(result.properties.status.enum).toEqual(['active']);
60
- expect(result.properties.priority.enum).toEqual(['high', 'low']);
61
- });
62
-
63
- it('should not transform anyOf without all const values', () => {
64
-
65
- const schema = {
66
- anyOf: [
67
- { const: 'value' },
68
- { type: 'number' },
69
- ],
70
- };
71
-
72
- const result = transformSchemaForGoogle(schema);
73
-
74
- expect(result).toHaveProperty('anyOf');
75
- expect(result).not.toHaveProperty('enum');
76
- });
77
-
78
- it('should preserve other schema properties', () => {
79
-
80
- const schema = {
81
- type: 'string',
82
- description: 'A status field',
83
- const: 'active',
84
- };
85
-
86
- const result = transformSchemaForGoogle(schema);
87
-
88
- expect(result.description).toBe('A status field');
89
- expect(result.type).toBe('string');
90
- });
91
- });
92
-
93
- describe('Message building', () => {
94
- it('should convert user text message correctly', () => {
95
-
96
- const context: Context = {
97
- messages: [
98
- {
99
- role: 'user',
100
- content: [{ type: 'text', content: 'Hello' }],
101
- timestamp: Date.now(),
102
- },
103
- ],
104
- };
105
-
106
- const result = buildGoogleMessages(model, context);
107
-
108
- expect(result).toHaveLength(1);
109
- expect(result[0].role).toBe('user');
110
- expect(result[0].parts).toBeDefined();
111
- });
112
-
113
- it('should convert system prompt correctly', () => {
114
-
115
- const context: Context = {
116
- systemPrompt: 'You are a helpful assistant.',
117
- messages: [],
118
- };
119
-
120
- const result = buildGoogleMessages(model, context);
121
-
122
- // Google uses systemInstruction separately, not in messages
123
- expect(result).toEqual([]);
124
- });
125
-
126
- it('should handle user message with image', () => {
127
-
128
- const context: Context = {
129
- messages: [
130
- {
131
- role: 'user',
132
- content: [
133
- { type: 'text', content: 'Describe:' },
134
- { type: 'image', data: 'base64data', mimeType: 'image/png' },
135
- ],
136
- timestamp: Date.now(),
137
- },
138
- ],
139
- };
140
-
141
- const result = buildGoogleMessages(model, context);
142
-
143
- expect(result).toHaveLength(1);
144
- expect(result[0].parts.length).toBeGreaterThan(1);
145
- // Should have both text and inlineData parts
146
- });
147
-
148
- it('should handle user message with file', () => {
149
-
150
- const context: Context = {
151
- messages: [
152
- {
153
- role: 'user',
154
- content: [
155
- { type: 'text', content: 'Analyze:' },
156
- { type: 'file', data: 'base64pdf', mimeType: 'application/pdf' },
157
- ],
158
- timestamp: Date.now(),
159
- },
160
- ],
161
- };
162
-
163
- const result = buildGoogleMessages(model, context);
164
-
165
- expect(result).toHaveLength(1);
166
- expect(result[0].parts.length).toBeGreaterThan(1);
167
- });
168
-
169
- it('should convert tool result messages', () => {
170
-
171
- const context: Context = {
172
- messages: [
173
- {
174
- role: 'toolResult',
175
- toolName: 'calculator',
176
- toolCallId: 'call_123',
177
- content: [{ type: 'text', content: '42' }],
178
- isError: false,
179
- timestamp: Date.now(),
180
- },
181
- ],
182
- };
183
-
184
- const result = buildGoogleMessages(model, context);
185
-
186
- expect(result).toHaveLength(1);
187
- expect(result[0].role).toBe('user');
188
- });
189
-
190
- it('should handle native Google assistant messages', () => {
191
-
192
- const nativeMessage = {
193
- role: 'assistant' as const,
194
- _provider: 'google' as const,
195
- message: {
196
- candidates: [
197
- {
198
- content: {
199
- parts: [{ text: 'Hello' }],
200
- role: 'model',
201
- },
202
- finishReason: 'STOP',
203
- },
204
- ],
205
- usageMetadata: {
206
- promptTokenCount: 10,
207
- candidatesTokenCount: 5,
208
- totalTokenCount: 15,
209
- },
210
- },
211
- };
212
-
213
- const context: Context = {
214
- messages: [nativeMessage as any],
215
- };
216
-
217
- const result = buildGoogleMessages(model, context);
218
-
219
- expect(result).toHaveLength(1);
220
- expect(result[0].role).toBe('model');
221
- });
222
-
223
- it('should throw on cross-provider assistant messages', () => {
224
-
225
- const openaiMessage = {
226
- role: 'assistant' as const,
227
- _provider: 'openai' as const,
228
- _native: {},
229
- };
230
-
231
- const context: Context = {
232
- messages: [openaiMessage as any],
233
- };
234
-
235
- expect(() => buildGoogleMessages(model, context)).toThrow();
236
- });
237
-
238
- it('should filter out non-supported content types', () => {
239
-
240
- const textOnlyModel = {
241
- ...model,
242
- input: ['text' as const],
243
- };
244
-
245
- const context: Context = {
246
- messages: [
247
- {
248
- role: 'user',
249
- content: [
250
- { type: 'text', content: 'Text' },
251
- { type: 'image', data: 'base64', mimeType: 'image/png' },
252
- ],
253
- timestamp: Date.now(),
254
- },
255
- ],
256
- };
257
-
258
- const result = buildGoogleMessages(textOnlyModel, context);
259
-
260
- expect(result).toHaveLength(1);
261
- // Should only have text parts
262
- expect(result[0].parts.length).toBe(1);
263
- expect(result[0].parts[0]).toHaveProperty('text');
264
- });
265
- });
266
-
267
- describe('Event streaming', () => {
268
- it('should emit start event', () => {
269
- // This would require mocking the Google SDK
270
- expect(true).toBe(true);
271
- });
272
-
273
- it('should emit text delta events', () => {
274
- // This would require mocking the Google SDK
275
- expect(true).toBe(true);
276
- });
277
-
278
- it('should detect thinking mode from part.thought flag', () => {
279
- // This would require mocking the Google SDK
280
- expect(true).toBe(true);
281
- });
282
-
283
- it('should emit done event with complete message', () => {
284
- // This would require mocking the Google SDK
285
- expect(true).toBe(true);
286
- });
287
-
288
- it('should handle function call streaming', () => {
289
- // This would require mocking the Google SDK
290
- expect(true).toBe(true);
291
- });
292
-
293
- it('should auto-generate function call IDs', () => {
294
- // This would require mocking the Google SDK
295
- expect(true).toBe(true);
296
- });
297
-
298
- it('should calculate token usage including thinking tokens', () => {
299
- // This would require mocking the Google SDK
300
- expect(true).toBe(true);
301
- });
302
-
303
- it('should calculate costs correctly', () => {
304
- // This would require mocking the Google SDK
305
- expect(true).toBe(true);
306
- });
307
- });
308
-
309
- describe('Options handling', () => {
310
- it('should pass through temperature parameter', () => {
311
- // Would test that temperature is passed to Google SDK
312
- expect(true).toBe(true);
313
- });
314
-
315
- it('should pass through maxOutputTokens parameter', () => {
316
- // Would test that maxOutputTokens is passed to Google SDK
317
- expect(true).toBe(true);
318
- });
319
-
320
- it('should handle extended thinking configuration', () => {
321
- // Would test extended thinking parameters
322
- expect(true).toBe(true);
323
- });
324
-
325
- it('should handle response MIME type setting', () => {
326
- // Would test response MIME type configuration
327
- expect(true).toBe(true);
328
- });
329
-
330
- it('should handle abort signal', () => {
331
- // Would test abort signal is passed through
332
- expect(true).toBe(true);
333
- });
334
- });
335
-
336
- describe('Error handling', () => {
337
- it('should handle invalid API key error', () => {
338
- // Would test API key validation
339
- expect(true).toBe(true);
340
- });
341
-
342
- it('should handle network errors', () => {
343
- // Would test network error handling
344
- expect(true).toBe(true);
345
- });
346
-
347
- it('should handle rate limit errors', () => {
348
- // Would test rate limit handling
349
- expect(true).toBe(true);
350
- });
351
-
352
- it('should handle finish reason mapping', () => {
353
- // Would test FinishReason to StopReason mapping
354
- expect(true).toBe(true);
355
- });
356
- });
357
-
358
- describe('Parts accumulation', () => {
359
- it('should accumulate consecutive text parts', () => {
360
- // Would test that consecutive text parts are merged
361
- expect(true).toBe(true);
362
- });
363
-
364
- it('should not merge parts with different types', () => {
365
- // Would test that different part types are kept separate
366
- expect(true).toBe(true);
367
- });
368
- });
369
- });
@@ -1,251 +0,0 @@
1
- import { describe, it, expect, vi, beforeEach } from 'vitest';
2
- import { streamOpenAI } from '../../src/providers/openai';
3
- import { Context } from '../../src/types';
4
- import { MODELS } from '../../src/models.generated';
5
- import { buildOpenAIMessages } from '../../src/providers/convert';
6
- import { ResponseInputMessageItem } from 'openai/resources/responses/responses.js';
7
-
8
- describe('OpenAI Provider Streaming Tests', () => {
9
- const model = MODELS.openai['gpt-5-mini'];
10
-
11
- describe('Message building', () => {
12
- it('should convert user text message correctly', () => {
13
-
14
- const context: Context = {
15
- messages: [
16
- {
17
- role: 'user',
18
- content: [{ type: 'text', content: 'Hello' }],
19
- timestamp: Date.now(),
20
- },
21
- ],
22
- };
23
-
24
- const result = buildOpenAIMessages(model, context);
25
-
26
- expect(result).toHaveLength(1);
27
- expect((result[0] as ResponseInputMessageItem).role).toBe('user');
28
- expect((result[0] as ResponseInputMessageItem).content ).toBeDefined();
29
- });
30
-
31
- it('should convert system prompt to developer role', () => {
32
-
33
- const context: Context = {
34
- systemPrompt: 'You are a helpful assistant.',
35
- messages: [],
36
- };
37
-
38
- const result = buildOpenAIMessages(model, context);
39
-
40
- expect(result).toHaveLength(1);
41
- expect((result[0] as ResponseInputMessageItem).role).toBe('developer');
42
- });
43
-
44
- it('should handle user message with mixed content', () => {
45
-
46
- const context: Context = {
47
- messages: [
48
- {
49
- role: 'user',
50
- content: [
51
- { type: 'text', content: 'Describe this:' },
52
- { type: 'image', data: 'base64data', mimeType: 'image/png' },
53
- ],
54
- timestamp: Date.now(),
55
- },
56
- ],
57
- };
58
-
59
- const result = buildOpenAIMessages(model, context);
60
-
61
- expect(result).toHaveLength(1);
62
- expect(Array.isArray((result[0] as ResponseInputMessageItem).content)).toBe(true);
63
- expect(((result[0] as ResponseInputMessageItem).content as any[]).length).toBeGreaterThan(1);
64
- });
65
-
66
- it('should filter out non-supported content types', () => {
67
-
68
- const textOnlyModel = {
69
- ...model,
70
- input: ['text' as const],
71
- };
72
-
73
- const context: Context = {
74
- messages: [
75
- {
76
- role: 'user',
77
- content: [
78
- { type: 'text', content: 'Text' },
79
- { type: 'image', data: 'base64', mimeType: 'image/png' },
80
- ],
81
- timestamp: Date.now(),
82
- },
83
- ],
84
- };
85
-
86
- const result = buildOpenAIMessages(textOnlyModel, context);
87
-
88
- expect(result).toHaveLength(1);
89
- // Should only have text content
90
- if (Array.isArray((result[0] as ResponseInputMessageItem).content)) {
91
- expect((result[0] as ResponseInputMessageItem).content.length).toBe(1);
92
- expect((result[0] as ResponseInputMessageItem).content[0].type).toBe('input_text');
93
- }
94
- });
95
-
96
- it('should convert tool result messages', () => {
97
-
98
- const context: Context = {
99
- messages: [
100
- {
101
- role: 'toolResult',
102
- toolName: 'calculator',
103
- toolCallId: 'call_123',
104
- content: [{ type: 'text', content: '42' }],
105
- isError: false,
106
- timestamp: Date.now(),
107
- },
108
- ],
109
- };
110
-
111
- const result = buildOpenAIMessages(model, context);
112
-
113
- expect(result).toHaveLength(1);
114
- expect((result[0] as ResponseInputMessageItem).role).toBe(undefined);
115
- });
116
-
117
- it('should handle native OpenAI assistant messages', () => {
118
-
119
- const nativeMessage = {
120
- role: 'assistant' as const,
121
- _provider: 'openai' as const,
122
- message: {
123
- output: [
124
- {
125
- type: 'function_call',
126
- call_id: 'call_123',
127
- name: 'calculator',
128
- arguments: '{"expression": "2 + 2"}',
129
- },
130
- ],
131
- id: 'resp_123',
132
- object: "response",
133
- created_at: 1740855869,
134
- output_text: '',
135
- status: "completed",
136
- incomplete_details: null,
137
- parallel_tool_calls: false,
138
- error: null,
139
- instructions: null,
140
- max_output_tokens: null,
141
- model: "gpt-4o-mini-2024-07-18",
142
- user: undefined,
143
- metadata: {},
144
- previous_response_id: null,
145
- temperature: 1,
146
- text: {},
147
- tool_choice: "auto",
148
- tools: [],
149
- top_p: 1,
150
- truncation: "disabled",
151
- usage: { input_tokens: 10, output_tokens: 5, total_tokens: 15, input_tokens_details: {cached_tokens: 0}, output_tokens_details: {reasoning_tokens: 0} },
152
- },
153
- };
154
-
155
- const context: Context = {
156
- messages: [nativeMessage as any],
157
- };
158
-
159
- const result = buildOpenAIMessages(model, context);
160
-
161
- expect(result).toHaveLength(1);
162
- expect((result[0] as ResponseInputMessageItem).role).toBe(undefined);
163
- });
164
-
165
- it('should throw on cross-provider assistant messages', () => {
166
-
167
- const googleMessage = {
168
- role: 'assistant' as const,
169
- _provider: 'google' as const,
170
- _native: {},
171
- };
172
-
173
- const context: Context = {
174
- messages: [googleMessage as any],
175
- };
176
-
177
- expect(() => buildOpenAIMessages(model, context)).toThrow();
178
- });
179
- });
180
-
181
- describe('Event streaming', () => {
182
- it('should emit start event', () => {
183
- // This would require mocking the OpenAI SDK
184
- expect(true).toBe(true);
185
- });
186
-
187
- it('should emit text delta events', () => {
188
- // This would require mocking the OpenAI SDK
189
- expect(true).toBe(true);
190
- });
191
-
192
- it('should emit done event with complete message', () => {
193
- // This would require mocking the OpenAI SDK
194
- expect(true).toBe(true);
195
- });
196
-
197
- it('should handle tool call streaming', () => {
198
- // This would require mocking the OpenAI SDK
199
- expect(true).toBe(true);
200
- });
201
-
202
- it('should calculate token usage correctly', () => {
203
- // This would require mocking the OpenAI SDK
204
- expect(true).toBe(true);
205
- });
206
-
207
- it('should calculate costs correctly', () => {
208
- // This would require mocking the OpenAI SDK
209
- expect(true).toBe(true);
210
- });
211
- });
212
-
213
- describe('Options handling', () => {
214
- it('should pass through temperature parameter', () => {
215
- // Would test that temperature is passed to OpenAI SDK
216
- expect(true).toBe(true);
217
- });
218
-
219
- it('should pass through maxOutputTokens parameter', () => {
220
- // Would test that max_tokens is passed to OpenAI SDK
221
- expect(true).toBe(true);
222
- });
223
-
224
- it('should handle reasoning mode configuration', () => {
225
- // Would test reasoning mode parameters
226
- expect(true).toBe(true);
227
- });
228
-
229
- it('should handle abort signal', () => {
230
- // Would test abort signal is passed through
231
- expect(true).toBe(true);
232
- });
233
- });
234
-
235
- describe('Error handling', () => {
236
- it('should handle invalid API key error', () => {
237
- // Would test API key validation
238
- expect(true).toBe(true);
239
- });
240
-
241
- it('should handle network errors', () => {
242
- // Would test network error handling
243
- expect(true).toBe(true);
244
- });
245
-
246
- it('should handle rate limit errors', () => {
247
- // Would test rate limit handling
248
- expect(true).toBe(true);
249
- });
250
- });
251
- });