@providerprotocol/ai 0.0.1

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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/anthropic/index.d.ts +41 -0
  4. package/dist/anthropic/index.js +500 -0
  5. package/dist/anthropic/index.js.map +1 -0
  6. package/dist/chunk-CUCRF5W6.js +136 -0
  7. package/dist/chunk-CUCRF5W6.js.map +1 -0
  8. package/dist/chunk-FTFX2VET.js +424 -0
  9. package/dist/chunk-FTFX2VET.js.map +1 -0
  10. package/dist/chunk-QUUX4G7U.js +117 -0
  11. package/dist/chunk-QUUX4G7U.js.map +1 -0
  12. package/dist/chunk-Y6Q7JCNP.js +39 -0
  13. package/dist/chunk-Y6Q7JCNP.js.map +1 -0
  14. package/dist/google/index.d.ts +69 -0
  15. package/dist/google/index.js +517 -0
  16. package/dist/google/index.js.map +1 -0
  17. package/dist/http/index.d.ts +61 -0
  18. package/dist/http/index.js +43 -0
  19. package/dist/http/index.js.map +1 -0
  20. package/dist/index.d.ts +792 -0
  21. package/dist/index.js +898 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/openai/index.d.ts +204 -0
  24. package/dist/openai/index.js +1340 -0
  25. package/dist/openai/index.js.map +1 -0
  26. package/dist/provider-CUJWjgNl.d.ts +192 -0
  27. package/dist/retry-I2661_rv.d.ts +118 -0
  28. package/package.json +88 -0
  29. package/src/anthropic/index.ts +3 -0
  30. package/src/core/image.ts +188 -0
  31. package/src/core/llm.ts +619 -0
  32. package/src/core/provider.ts +92 -0
  33. package/src/google/index.ts +3 -0
  34. package/src/http/errors.ts +112 -0
  35. package/src/http/fetch.ts +210 -0
  36. package/src/http/index.ts +31 -0
  37. package/src/http/keys.ts +136 -0
  38. package/src/http/retry.ts +205 -0
  39. package/src/http/sse.ts +136 -0
  40. package/src/index.ts +32 -0
  41. package/src/openai/index.ts +9 -0
  42. package/src/providers/anthropic/index.ts +17 -0
  43. package/src/providers/anthropic/llm.ts +196 -0
  44. package/src/providers/anthropic/transform.ts +452 -0
  45. package/src/providers/anthropic/types.ts +213 -0
  46. package/src/providers/google/index.ts +17 -0
  47. package/src/providers/google/llm.ts +203 -0
  48. package/src/providers/google/transform.ts +487 -0
  49. package/src/providers/google/types.ts +214 -0
  50. package/src/providers/openai/index.ts +151 -0
  51. package/src/providers/openai/llm.completions.ts +201 -0
  52. package/src/providers/openai/llm.responses.ts +211 -0
  53. package/src/providers/openai/transform.completions.ts +628 -0
  54. package/src/providers/openai/transform.responses.ts +718 -0
  55. package/src/providers/openai/types.ts +711 -0
  56. package/src/types/content.ts +133 -0
  57. package/src/types/errors.ts +85 -0
  58. package/src/types/index.ts +105 -0
  59. package/src/types/llm.ts +211 -0
  60. package/src/types/messages.ts +182 -0
  61. package/src/types/provider.ts +195 -0
  62. package/src/types/schema.ts +58 -0
  63. package/src/types/stream.ts +146 -0
  64. package/src/types/thread.ts +226 -0
  65. package/src/types/tool.ts +88 -0
  66. package/src/types/turn.ts +118 -0
  67. package/src/utils/id.ts +28 -0
@@ -0,0 +1,517 @@
1
+ import {
2
+ createProvider
3
+ } from "../chunk-Y6Q7JCNP.js";
4
+ import {
5
+ AssistantMessage,
6
+ isAssistantMessage,
7
+ isToolResultMessage,
8
+ isUserMessage
9
+ } from "../chunk-QUUX4G7U.js";
10
+ import {
11
+ UPPError,
12
+ doFetch,
13
+ doStreamFetch,
14
+ normalizeHttpError,
15
+ parseSSEStream,
16
+ resolveApiKey
17
+ } from "../chunk-FTFX2VET.js";
18
+
19
+ // src/providers/google/transform.ts
20
+ function transformRequest(request, modelId) {
21
+ const params = request.params ?? {};
22
+ const googleRequest = {
23
+ contents: transformMessages(request.messages)
24
+ };
25
+ if (request.system) {
26
+ googleRequest.systemInstruction = {
27
+ parts: [{ text: request.system }]
28
+ };
29
+ }
30
+ const generationConfig = {};
31
+ if (params.maxOutputTokens !== void 0) {
32
+ generationConfig.maxOutputTokens = params.maxOutputTokens;
33
+ }
34
+ if (params.temperature !== void 0) {
35
+ generationConfig.temperature = params.temperature;
36
+ }
37
+ if (params.topP !== void 0) {
38
+ generationConfig.topP = params.topP;
39
+ }
40
+ if (params.topK !== void 0) {
41
+ generationConfig.topK = params.topK;
42
+ }
43
+ if (params.stopSequences !== void 0) {
44
+ generationConfig.stopSequences = params.stopSequences;
45
+ }
46
+ if (params.candidateCount !== void 0) {
47
+ generationConfig.candidateCount = params.candidateCount;
48
+ }
49
+ if (params.responseMimeType !== void 0) {
50
+ generationConfig.responseMimeType = params.responseMimeType;
51
+ }
52
+ if (params.responseSchema !== void 0) {
53
+ generationConfig.responseSchema = params.responseSchema;
54
+ }
55
+ if (params.presencePenalty !== void 0) {
56
+ generationConfig.presencePenalty = params.presencePenalty;
57
+ }
58
+ if (params.frequencyPenalty !== void 0) {
59
+ generationConfig.frequencyPenalty = params.frequencyPenalty;
60
+ }
61
+ if (params.seed !== void 0) {
62
+ generationConfig.seed = params.seed;
63
+ }
64
+ if (params.responseLogprobs !== void 0) {
65
+ generationConfig.responseLogprobs = params.responseLogprobs;
66
+ }
67
+ if (params.logprobs !== void 0) {
68
+ generationConfig.logprobs = params.logprobs;
69
+ }
70
+ if (params.audioTimestamp !== void 0) {
71
+ generationConfig.audioTimestamp = params.audioTimestamp;
72
+ }
73
+ if (params.thinkingConfig !== void 0) {
74
+ generationConfig.thinkingConfig = params.thinkingConfig;
75
+ }
76
+ if (request.structure) {
77
+ generationConfig.responseMimeType = "application/json";
78
+ generationConfig.responseSchema = request.structure;
79
+ }
80
+ if (Object.keys(generationConfig).length > 0) {
81
+ googleRequest.generationConfig = generationConfig;
82
+ }
83
+ if (request.tools && request.tools.length > 0) {
84
+ googleRequest.tools = [
85
+ {
86
+ functionDeclarations: request.tools.map(transformTool)
87
+ }
88
+ ];
89
+ }
90
+ return googleRequest;
91
+ }
92
+ function filterValidContent(content) {
93
+ return content.filter((c) => c && typeof c.type === "string");
94
+ }
95
+ function transformMessages(messages) {
96
+ const contents = [];
97
+ for (const msg of messages) {
98
+ if (isUserMessage(msg)) {
99
+ const validContent = filterValidContent(msg.content);
100
+ const parts = validContent.map(transformContentBlock);
101
+ if (parts.length === 0) {
102
+ parts.push({ text: "" });
103
+ }
104
+ contents.push({
105
+ role: "user",
106
+ parts
107
+ });
108
+ } else if (isAssistantMessage(msg)) {
109
+ const validContent = filterValidContent(msg.content);
110
+ const parts = validContent.map(transformContentBlock);
111
+ const googleMeta = msg.metadata?.google;
112
+ if (googleMeta?.functionCallParts && googleMeta.functionCallParts.length > 0) {
113
+ for (const fc of googleMeta.functionCallParts) {
114
+ const part = {
115
+ functionCall: {
116
+ name: fc.name,
117
+ args: fc.args
118
+ }
119
+ };
120
+ if (fc.thoughtSignature) {
121
+ part.thoughtSignature = fc.thoughtSignature;
122
+ }
123
+ parts.push(part);
124
+ }
125
+ } else if (msg.toolCalls) {
126
+ for (const call of msg.toolCalls) {
127
+ parts.push({
128
+ functionCall: {
129
+ name: call.toolName,
130
+ args: call.arguments
131
+ }
132
+ });
133
+ }
134
+ }
135
+ if (parts.length === 0) {
136
+ parts.push({ text: "" });
137
+ }
138
+ contents.push({
139
+ role: "model",
140
+ parts
141
+ });
142
+ } else if (isToolResultMessage(msg)) {
143
+ contents.push({
144
+ role: "user",
145
+ parts: msg.results.map((result) => ({
146
+ functionResponse: {
147
+ name: result.toolCallId,
148
+ // Google uses the function name, but we store it in toolCallId
149
+ response: typeof result.result === "object" ? result.result : { result: result.result }
150
+ }
151
+ }))
152
+ });
153
+ }
154
+ }
155
+ return contents;
156
+ }
157
+ function transformContentBlock(block) {
158
+ switch (block.type) {
159
+ case "text":
160
+ return { text: block.text };
161
+ case "image": {
162
+ const imageBlock = block;
163
+ let data;
164
+ if (imageBlock.source.type === "base64") {
165
+ data = imageBlock.source.data;
166
+ } else if (imageBlock.source.type === "bytes") {
167
+ data = btoa(
168
+ Array.from(imageBlock.source.data).map((b) => String.fromCharCode(b)).join("")
169
+ );
170
+ } else {
171
+ throw new Error("Google API does not support URL image sources directly");
172
+ }
173
+ return {
174
+ inlineData: {
175
+ mimeType: imageBlock.mimeType,
176
+ data
177
+ }
178
+ };
179
+ }
180
+ default:
181
+ throw new Error(`Unsupported content type: ${block.type}`);
182
+ }
183
+ }
184
+ function transformTool(tool) {
185
+ return {
186
+ name: tool.name,
187
+ description: tool.description,
188
+ parameters: {
189
+ type: "object",
190
+ properties: tool.parameters.properties,
191
+ required: tool.parameters.required
192
+ }
193
+ };
194
+ }
195
+ function transformResponse(data) {
196
+ const candidate = data.candidates?.[0];
197
+ if (!candidate) {
198
+ throw new Error("No candidates in Google response");
199
+ }
200
+ const textContent = [];
201
+ const toolCalls = [];
202
+ let structuredData;
203
+ const functionCallParts = [];
204
+ for (const part of candidate.content.parts) {
205
+ if ("text" in part) {
206
+ textContent.push({ type: "text", text: part.text });
207
+ if (structuredData === void 0) {
208
+ try {
209
+ structuredData = JSON.parse(part.text);
210
+ } catch {
211
+ }
212
+ }
213
+ } else if ("functionCall" in part) {
214
+ const fc = part;
215
+ toolCalls.push({
216
+ toolCallId: fc.functionCall.name,
217
+ // Google doesn't have call IDs, use name
218
+ toolName: fc.functionCall.name,
219
+ arguments: fc.functionCall.args
220
+ });
221
+ functionCallParts.push({
222
+ name: fc.functionCall.name,
223
+ args: fc.functionCall.args,
224
+ thoughtSignature: fc.thoughtSignature
225
+ });
226
+ }
227
+ }
228
+ const message = new AssistantMessage(
229
+ textContent,
230
+ toolCalls.length > 0 ? toolCalls : void 0,
231
+ {
232
+ metadata: {
233
+ google: {
234
+ finishReason: candidate.finishReason,
235
+ safetyRatings: candidate.safetyRatings,
236
+ // Store function call parts with thought signatures for multi-turn
237
+ functionCallParts: functionCallParts.length > 0 ? functionCallParts : void 0
238
+ }
239
+ }
240
+ }
241
+ );
242
+ const usage = {
243
+ inputTokens: data.usageMetadata?.promptTokenCount ?? 0,
244
+ outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,
245
+ totalTokens: data.usageMetadata?.totalTokenCount ?? 0
246
+ };
247
+ return {
248
+ message,
249
+ usage,
250
+ stopReason: candidate.finishReason ?? "STOP",
251
+ data: structuredData
252
+ };
253
+ }
254
+ function createStreamState() {
255
+ return {
256
+ content: "",
257
+ toolCalls: [],
258
+ finishReason: null,
259
+ inputTokens: 0,
260
+ outputTokens: 0,
261
+ isFirstChunk: true
262
+ };
263
+ }
264
+ function transformStreamChunk(chunk, state) {
265
+ const events = [];
266
+ if (state.isFirstChunk) {
267
+ events.push({ type: "message_start", index: 0, delta: {} });
268
+ state.isFirstChunk = false;
269
+ }
270
+ if (chunk.usageMetadata) {
271
+ state.inputTokens = chunk.usageMetadata.promptTokenCount;
272
+ state.outputTokens = chunk.usageMetadata.candidatesTokenCount;
273
+ }
274
+ const candidate = chunk.candidates?.[0];
275
+ if (!candidate) {
276
+ return events;
277
+ }
278
+ for (const part of candidate.content?.parts ?? []) {
279
+ if ("text" in part) {
280
+ state.content += part.text;
281
+ events.push({
282
+ type: "text_delta",
283
+ index: 0,
284
+ delta: { text: part.text }
285
+ });
286
+ } else if ("functionCall" in part) {
287
+ const fc = part;
288
+ state.toolCalls.push({
289
+ name: fc.functionCall.name,
290
+ args: fc.functionCall.args,
291
+ thoughtSignature: fc.thoughtSignature
292
+ });
293
+ events.push({
294
+ type: "tool_call_delta",
295
+ index: state.toolCalls.length - 1,
296
+ delta: {
297
+ toolCallId: fc.functionCall.name,
298
+ toolName: fc.functionCall.name,
299
+ argumentsJson: JSON.stringify(fc.functionCall.args)
300
+ }
301
+ });
302
+ }
303
+ }
304
+ if (candidate.finishReason) {
305
+ state.finishReason = candidate.finishReason;
306
+ events.push({ type: "message_stop", index: 0, delta: {} });
307
+ }
308
+ return events;
309
+ }
310
+ function buildResponseFromState(state) {
311
+ const textContent = [];
312
+ const toolCalls = [];
313
+ let structuredData;
314
+ const functionCallParts = [];
315
+ if (state.content) {
316
+ textContent.push({ type: "text", text: state.content });
317
+ try {
318
+ structuredData = JSON.parse(state.content);
319
+ } catch {
320
+ }
321
+ }
322
+ for (const tc of state.toolCalls) {
323
+ toolCalls.push({
324
+ toolCallId: tc.name,
325
+ toolName: tc.name,
326
+ arguments: tc.args
327
+ });
328
+ functionCallParts.push({
329
+ name: tc.name,
330
+ args: tc.args,
331
+ thoughtSignature: tc.thoughtSignature
332
+ });
333
+ }
334
+ const message = new AssistantMessage(
335
+ textContent,
336
+ toolCalls.length > 0 ? toolCalls : void 0,
337
+ {
338
+ metadata: {
339
+ google: {
340
+ finishReason: state.finishReason,
341
+ // Store function call parts with thought signatures for multi-turn
342
+ functionCallParts: functionCallParts.length > 0 ? functionCallParts : void 0
343
+ }
344
+ }
345
+ }
346
+ );
347
+ const usage = {
348
+ inputTokens: state.inputTokens,
349
+ outputTokens: state.outputTokens,
350
+ totalTokens: state.inputTokens + state.outputTokens
351
+ };
352
+ return {
353
+ message,
354
+ usage,
355
+ stopReason: state.finishReason ?? "STOP",
356
+ data: structuredData
357
+ };
358
+ }
359
+
360
+ // src/providers/google/llm.ts
361
+ var GOOGLE_API_BASE = "https://generativelanguage.googleapis.com/v1beta";
362
+ var GOOGLE_CAPABILITIES = {
363
+ streaming: true,
364
+ tools: true,
365
+ structuredOutput: true,
366
+ imageInput: true,
367
+ videoInput: true,
368
+ audioInput: true
369
+ };
370
+ function buildUrl(modelId, action, apiKey) {
371
+ const base = `${GOOGLE_API_BASE}/models/${modelId}:${action}`;
372
+ return `${base}?key=${apiKey}`;
373
+ }
374
+ function createLLMHandler() {
375
+ let providerRef = null;
376
+ return {
377
+ _setProvider(provider) {
378
+ providerRef = provider;
379
+ },
380
+ bind(modelId) {
381
+ if (!providerRef) {
382
+ throw new UPPError(
383
+ "Provider reference not set. Handler must be used with createProvider().",
384
+ "INVALID_REQUEST",
385
+ "google",
386
+ "llm"
387
+ );
388
+ }
389
+ const model = {
390
+ modelId,
391
+ capabilities: GOOGLE_CAPABILITIES,
392
+ get provider() {
393
+ return providerRef;
394
+ },
395
+ async complete(request) {
396
+ const apiKey = await resolveApiKey(
397
+ request.config,
398
+ "GOOGLE_API_KEY",
399
+ "google",
400
+ "llm"
401
+ );
402
+ const url = request.config.baseUrl ? `${request.config.baseUrl}/models/${modelId}:generateContent?key=${apiKey}` : buildUrl(modelId, "generateContent", apiKey);
403
+ const body = transformRequest(request, modelId);
404
+ const response = await doFetch(
405
+ url,
406
+ {
407
+ method: "POST",
408
+ headers: {
409
+ "Content-Type": "application/json"
410
+ },
411
+ body: JSON.stringify(body),
412
+ signal: request.signal
413
+ },
414
+ request.config,
415
+ "google",
416
+ "llm"
417
+ );
418
+ const data = await response.json();
419
+ return transformResponse(data);
420
+ },
421
+ stream(request) {
422
+ const state = createStreamState();
423
+ let responseResolve;
424
+ let responseReject;
425
+ const responsePromise = new Promise((resolve, reject) => {
426
+ responseResolve = resolve;
427
+ responseReject = reject;
428
+ });
429
+ async function* generateEvents() {
430
+ try {
431
+ const apiKey = await resolveApiKey(
432
+ request.config,
433
+ "GOOGLE_API_KEY",
434
+ "google",
435
+ "llm"
436
+ );
437
+ const url = request.config.baseUrl ? `${request.config.baseUrl}/models/${modelId}:streamGenerateContent?alt=sse&key=${apiKey}` : `${buildUrl(modelId, "streamGenerateContent", apiKey)}&alt=sse`;
438
+ const body = transformRequest(request, modelId);
439
+ const response = await doStreamFetch(
440
+ url,
441
+ {
442
+ method: "POST",
443
+ headers: {
444
+ "Content-Type": "application/json"
445
+ },
446
+ body: JSON.stringify(body),
447
+ signal: request.signal
448
+ },
449
+ request.config,
450
+ "google",
451
+ "llm"
452
+ );
453
+ if (!response.ok) {
454
+ const error = await normalizeHttpError(response, "google", "llm");
455
+ responseReject(error);
456
+ throw error;
457
+ }
458
+ if (!response.body) {
459
+ const error = new UPPError(
460
+ "No response body for streaming request",
461
+ "PROVIDER_ERROR",
462
+ "google",
463
+ "llm"
464
+ );
465
+ responseReject(error);
466
+ throw error;
467
+ }
468
+ for await (const data of parseSSEStream(response.body)) {
469
+ if (typeof data === "object" && data !== null) {
470
+ const chunk = data;
471
+ if ("error" in chunk) {
472
+ const error = new UPPError(
473
+ chunk.error.message,
474
+ "PROVIDER_ERROR",
475
+ "google",
476
+ "llm"
477
+ );
478
+ responseReject(error);
479
+ throw error;
480
+ }
481
+ const events = transformStreamChunk(chunk, state);
482
+ for (const event of events) {
483
+ yield event;
484
+ }
485
+ }
486
+ }
487
+ responseResolve(buildResponseFromState(state));
488
+ } catch (error) {
489
+ responseReject(error);
490
+ throw error;
491
+ }
492
+ }
493
+ return {
494
+ [Symbol.asyncIterator]() {
495
+ return generateEvents();
496
+ },
497
+ response: responsePromise
498
+ };
499
+ }
500
+ };
501
+ return model;
502
+ }
503
+ };
504
+ }
505
+
506
+ // src/providers/google/index.ts
507
+ var google = createProvider({
508
+ name: "google",
509
+ version: "1.0.0",
510
+ modalities: {
511
+ llm: createLLMHandler()
512
+ }
513
+ });
514
+ export {
515
+ google
516
+ };
517
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/providers/google/transform.ts","../../src/providers/google/llm.ts","../../src/providers/google/index.ts"],"sourcesContent":["import type { LLMRequest, LLMResponse } from '../../types/llm.ts';\nimport type { Message } from '../../types/messages.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { Tool, ToolCall } from '../../types/tool.ts';\nimport type { TokenUsage } from '../../types/turn.ts';\nimport type { ContentBlock, TextBlock, ImageBlock } from '../../types/content.ts';\nimport {\n AssistantMessage,\n isUserMessage,\n isAssistantMessage,\n isToolResultMessage,\n} from '../../types/messages.ts';\nimport type {\n GoogleLLMParams,\n GoogleRequest,\n GoogleContent,\n GooglePart,\n GoogleTool,\n GoogleResponse,\n GoogleStreamChunk,\n GoogleFunctionCallPart,\n} from './types.ts';\n\n/**\n * Transform UPP request to Google format\n */\nexport function transformRequest<TParams extends GoogleLLMParams>(\n request: LLMRequest<TParams>,\n modelId: string\n): GoogleRequest {\n const params = (request.params ?? {}) as GoogleLLMParams;\n\n const googleRequest: GoogleRequest = {\n contents: transformMessages(request.messages),\n };\n\n // System instruction (separate from contents in Google)\n if (request.system) {\n googleRequest.systemInstruction = {\n parts: [{ text: request.system }],\n };\n }\n\n // Generation config\n const generationConfig: NonNullable<GoogleRequest['generationConfig']> = {};\n\n if (params.maxOutputTokens !== undefined) {\n generationConfig.maxOutputTokens = params.maxOutputTokens;\n }\n if (params.temperature !== undefined) {\n generationConfig.temperature = params.temperature;\n }\n if (params.topP !== undefined) {\n generationConfig.topP = params.topP;\n }\n if (params.topK !== undefined) {\n generationConfig.topK = params.topK;\n }\n if (params.stopSequences !== undefined) {\n generationConfig.stopSequences = params.stopSequences;\n }\n if (params.candidateCount !== undefined) {\n generationConfig.candidateCount = params.candidateCount;\n }\n if (params.responseMimeType !== undefined) {\n generationConfig.responseMimeType = params.responseMimeType;\n }\n if (params.responseSchema !== undefined) {\n generationConfig.responseSchema = params.responseSchema as Record<string, unknown>;\n }\n if (params.presencePenalty !== undefined) {\n generationConfig.presencePenalty = params.presencePenalty;\n }\n if (params.frequencyPenalty !== undefined) {\n generationConfig.frequencyPenalty = params.frequencyPenalty;\n }\n if (params.seed !== undefined) {\n generationConfig.seed = params.seed;\n }\n if (params.responseLogprobs !== undefined) {\n generationConfig.responseLogprobs = params.responseLogprobs;\n }\n if (params.logprobs !== undefined) {\n generationConfig.logprobs = params.logprobs;\n }\n if (params.audioTimestamp !== undefined) {\n generationConfig.audioTimestamp = params.audioTimestamp;\n }\n if (params.thinkingConfig !== undefined) {\n generationConfig.thinkingConfig = params.thinkingConfig;\n }\n\n // Protocol-level structured output (overrides provider-specific settings)\n if (request.structure) {\n generationConfig.responseMimeType = 'application/json';\n generationConfig.responseSchema = request.structure as unknown as Record<string, unknown>;\n }\n\n if (Object.keys(generationConfig).length > 0) {\n googleRequest.generationConfig = generationConfig;\n }\n\n // Tools\n if (request.tools && request.tools.length > 0) {\n googleRequest.tools = [\n {\n functionDeclarations: request.tools.map(transformTool),\n },\n ];\n }\n\n return googleRequest;\n}\n\n/**\n * Filter to only valid content blocks with a type property\n */\nfunction filterValidContent<T extends { type?: string }>(content: T[]): T[] {\n return content.filter((c) => c && typeof c.type === 'string');\n}\n\n/**\n * Transform UPP Messages to Google contents\n */\nfunction transformMessages(messages: Message[]): GoogleContent[] {\n const contents: GoogleContent[] = [];\n\n for (const msg of messages) {\n if (isUserMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts = validContent.map(transformContentBlock);\n // Google requires at least one part - add placeholder if empty\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n contents.push({\n role: 'user',\n parts,\n });\n } else if (isAssistantMessage(msg)) {\n const validContent = filterValidContent(msg.content);\n const parts: GooglePart[] = validContent.map(transformContentBlock);\n\n // Add function calls - use stored parts with thought signatures if available\n const googleMeta = msg.metadata?.google as {\n functionCallParts?: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }>;\n } | undefined;\n\n if (googleMeta?.functionCallParts && googleMeta.functionCallParts.length > 0) {\n // Use stored function call parts with thought signatures\n for (const fc of googleMeta.functionCallParts) {\n const part: GoogleFunctionCallPart = {\n functionCall: {\n name: fc.name,\n args: fc.args,\n },\n };\n if (fc.thoughtSignature) {\n part.thoughtSignature = fc.thoughtSignature;\n }\n parts.push(part);\n }\n } else if (msg.toolCalls) {\n // Fallback: reconstruct from tool calls (no thought signatures)\n for (const call of msg.toolCalls) {\n parts.push({\n functionCall: {\n name: call.toolName,\n args: call.arguments,\n },\n });\n }\n }\n\n // Google requires at least one part - add placeholder if empty\n if (parts.length === 0) {\n parts.push({ text: '' });\n }\n\n contents.push({\n role: 'model',\n parts,\n });\n } else if (isToolResultMessage(msg)) {\n // Function results are sent as user messages in Google\n contents.push({\n role: 'user',\n parts: msg.results.map((result) => ({\n functionResponse: {\n name: result.toolCallId, // Google uses the function name, but we store it in toolCallId\n response:\n typeof result.result === 'object'\n ? (result.result as Record<string, unknown>)\n : { result: result.result },\n },\n })),\n });\n }\n }\n\n return contents;\n}\n\n/**\n * Transform a content block to Google format\n */\nfunction transformContentBlock(block: ContentBlock): GooglePart {\n switch (block.type) {\n case 'text':\n return { text: block.text };\n\n case 'image': {\n const imageBlock = block as ImageBlock;\n let data: string;\n\n if (imageBlock.source.type === 'base64') {\n data = imageBlock.source.data;\n } else if (imageBlock.source.type === 'bytes') {\n data = btoa(\n Array.from(imageBlock.source.data)\n .map((b) => String.fromCharCode(b))\n .join('')\n );\n } else {\n throw new Error('Google API does not support URL image sources directly');\n }\n\n return {\n inlineData: {\n mimeType: imageBlock.mimeType,\n data,\n },\n };\n }\n\n default:\n throw new Error(`Unsupported content type: ${block.type}`);\n }\n}\n\n/**\n * Transform a UPP Tool to Google format\n */\nfunction transformTool(tool: Tool): GoogleTool['functionDeclarations'][0] {\n return {\n name: tool.name,\n description: tool.description,\n parameters: {\n type: 'object',\n properties: tool.parameters.properties,\n required: tool.parameters.required,\n },\n };\n}\n\n/**\n * Transform Google response to UPP LLMResponse\n */\nexport function transformResponse(data: GoogleResponse): LLMResponse {\n const candidate = data.candidates?.[0];\n if (!candidate) {\n throw new Error('No candidates in Google response');\n }\n\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n // Store original function call parts with thought signatures for echoing back\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n for (const part of candidate.content.parts) {\n if ('text' in part) {\n textContent.push({ type: 'text', text: part.text });\n // Try to parse as JSON for structured output (native JSON mode)\n if (structuredData === undefined) {\n try {\n structuredData = JSON.parse(part.text);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\n }\n }\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n toolCalls.push({\n toolCallId: fc.functionCall.name, // Google doesn't have call IDs, use name\n toolName: fc.functionCall.name,\n arguments: fc.functionCall.args,\n });\n // Store the full part including thought signature\n functionCallParts.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n }\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: candidate.finishReason,\n safetyRatings: candidate.safetyRatings,\n // Store function call parts with thought signatures for multi-turn\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: data.usageMetadata?.promptTokenCount ?? 0,\n outputTokens: data.usageMetadata?.candidatesTokenCount ?? 0,\n totalTokens: data.usageMetadata?.totalTokenCount ?? 0,\n };\n\n return {\n message,\n usage,\n stopReason: candidate.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n\n/**\n * State for accumulating streaming response\n */\nexport interface StreamState {\n content: string;\n toolCalls: Array<{ name: string; args: Record<string, unknown>; thoughtSignature?: string }>;\n finishReason: string | null;\n inputTokens: number;\n outputTokens: number;\n isFirstChunk: boolean;\n}\n\n/**\n * Create initial stream state\n */\nexport function createStreamState(): StreamState {\n return {\n content: '',\n toolCalls: [],\n finishReason: null,\n inputTokens: 0,\n outputTokens: 0,\n isFirstChunk: true,\n };\n}\n\n/**\n * Transform Google stream chunk to UPP StreamEvents\n */\nexport function transformStreamChunk(\n chunk: GoogleStreamChunk,\n state: StreamState\n): StreamEvent[] {\n const events: StreamEvent[] = [];\n\n // First chunk - emit message start\n if (state.isFirstChunk) {\n events.push({ type: 'message_start', index: 0, delta: {} });\n state.isFirstChunk = false;\n }\n\n // Usage metadata\n if (chunk.usageMetadata) {\n state.inputTokens = chunk.usageMetadata.promptTokenCount;\n state.outputTokens = chunk.usageMetadata.candidatesTokenCount;\n }\n\n const candidate = chunk.candidates?.[0];\n if (!candidate) {\n return events;\n }\n\n // Process parts\n for (const part of candidate.content?.parts ?? []) {\n if ('text' in part) {\n state.content += part.text;\n events.push({\n type: 'text_delta',\n index: 0,\n delta: { text: part.text },\n });\n } else if ('functionCall' in part) {\n const fc = part as GoogleFunctionCallPart;\n // Store with thought signature for echoing back\n state.toolCalls.push({\n name: fc.functionCall.name,\n args: fc.functionCall.args,\n thoughtSignature: fc.thoughtSignature,\n });\n events.push({\n type: 'tool_call_delta',\n index: state.toolCalls.length - 1,\n delta: {\n toolCallId: fc.functionCall.name,\n toolName: fc.functionCall.name,\n argumentsJson: JSON.stringify(fc.functionCall.args),\n },\n });\n }\n }\n\n // Finish reason\n if (candidate.finishReason) {\n state.finishReason = candidate.finishReason;\n events.push({ type: 'message_stop', index: 0, delta: {} });\n }\n\n return events;\n}\n\n/**\n * Build LLMResponse from accumulated stream state\n */\nexport function buildResponseFromState(state: StreamState): LLMResponse {\n const textContent: TextBlock[] = [];\n const toolCalls: ToolCall[] = [];\n let structuredData: unknown;\n const functionCallParts: Array<{\n name: string;\n args: Record<string, unknown>;\n thoughtSignature?: string;\n }> = [];\n\n if (state.content) {\n textContent.push({ type: 'text', text: state.content });\n // Try to parse as JSON for structured output (native JSON mode)\n try {\n structuredData = JSON.parse(state.content);\n } catch {\n // Not valid JSON - that's fine, might not be structured output\n }\n }\n\n for (const tc of state.toolCalls) {\n toolCalls.push({\n toolCallId: tc.name,\n toolName: tc.name,\n arguments: tc.args,\n });\n functionCallParts.push({\n name: tc.name,\n args: tc.args,\n thoughtSignature: tc.thoughtSignature,\n });\n }\n\n const message = new AssistantMessage(\n textContent,\n toolCalls.length > 0 ? toolCalls : undefined,\n {\n metadata: {\n google: {\n finishReason: state.finishReason,\n // Store function call parts with thought signatures for multi-turn\n functionCallParts: functionCallParts.length > 0 ? functionCallParts : undefined,\n },\n },\n }\n );\n\n const usage: TokenUsage = {\n inputTokens: state.inputTokens,\n outputTokens: state.outputTokens,\n totalTokens: state.inputTokens + state.outputTokens,\n };\n\n return {\n message,\n usage,\n stopReason: state.finishReason ?? 'STOP',\n data: structuredData,\n };\n}\n","import type { LLMHandler, BoundLLMModel, LLMRequest, LLMResponse, LLMStreamResult, LLMCapabilities } from '../../types/llm.ts';\nimport type { StreamEvent } from '../../types/stream.ts';\nimport type { LLMProvider } from '../../types/provider.ts';\nimport { UPPError } from '../../types/errors.ts';\nimport { resolveApiKey } from '../../http/keys.ts';\nimport { doFetch, doStreamFetch } from '../../http/fetch.ts';\nimport { parseSSEStream } from '../../http/sse.ts';\nimport { normalizeHttpError } from '../../http/errors.ts';\nimport type { GoogleLLMParams, GoogleResponse, GoogleStreamChunk } from './types.ts';\nimport {\n transformRequest,\n transformResponse,\n transformStreamChunk,\n createStreamState,\n buildResponseFromState,\n} from './transform.ts';\n\nconst GOOGLE_API_BASE = 'https://generativelanguage.googleapis.com/v1beta';\n\n/**\n * Google API capabilities\n */\nconst GOOGLE_CAPABILITIES: LLMCapabilities = {\n streaming: true,\n tools: true,\n structuredOutput: true,\n imageInput: true,\n videoInput: true,\n audioInput: true,\n};\n\n/**\n * Build Google API URL for a model\n */\nfunction buildUrl(modelId: string, action: 'generateContent' | 'streamGenerateContent', apiKey: string): string {\n const base = `${GOOGLE_API_BASE}/models/${modelId}:${action}`;\n return `${base}?key=${apiKey}`;\n}\n\n/**\n * Create Google LLM handler\n */\nexport function createLLMHandler(): LLMHandler<GoogleLLMParams> {\n // Provider reference injected by createProvider() after construction\n let providerRef: LLMProvider<GoogleLLMParams> | null = null;\n\n return {\n _setProvider(provider: LLMProvider<GoogleLLMParams>) {\n providerRef = provider;\n },\n\n bind(modelId: string): BoundLLMModel<GoogleLLMParams> {\n // Use the injected provider reference (set by createProvider)\n if (!providerRef) {\n throw new UPPError(\n 'Provider reference not set. Handler must be used with createProvider().',\n 'INVALID_REQUEST',\n 'google',\n 'llm'\n );\n }\n\n const model: BoundLLMModel<GoogleLLMParams> = {\n modelId,\n capabilities: GOOGLE_CAPABILITIES,\n\n get provider(): LLMProvider<GoogleLLMParams> {\n return providerRef!;\n },\n\n async complete(request: LLMRequest<GoogleLLMParams>): Promise<LLMResponse> {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:generateContent?key=${apiKey}`\n : buildUrl(modelId, 'generateContent', apiKey);\n\n const body = transformRequest(request, modelId);\n\n const response = await doFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n const data = (await response.json()) as GoogleResponse;\n return transformResponse(data);\n },\n\n stream(request: LLMRequest<GoogleLLMParams>): LLMStreamResult {\n const state = createStreamState();\n let responseResolve: (value: LLMResponse) => void;\n let responseReject: (error: Error) => void;\n\n const responsePromise = new Promise<LLMResponse>((resolve, reject) => {\n responseResolve = resolve;\n responseReject = reject;\n });\n\n async function* generateEvents(): AsyncGenerator<StreamEvent, void, unknown> {\n try {\n const apiKey = await resolveApiKey(\n request.config,\n 'GOOGLE_API_KEY',\n 'google',\n 'llm'\n );\n\n const url = request.config.baseUrl\n ? `${request.config.baseUrl}/models/${modelId}:streamGenerateContent?alt=sse&key=${apiKey}`\n : `${buildUrl(modelId, 'streamGenerateContent', apiKey)}&alt=sse`;\n\n const body = transformRequest(request, modelId);\n\n const response = await doStreamFetch(\n url,\n {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal: request.signal,\n },\n request.config,\n 'google',\n 'llm'\n );\n\n if (!response.ok) {\n const error = await normalizeHttpError(response, 'google', 'llm');\n responseReject(error);\n throw error;\n }\n\n if (!response.body) {\n const error = new UPPError(\n 'No response body for streaming request',\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n for await (const data of parseSSEStream(response.body)) {\n if (typeof data === 'object' && data !== null) {\n const chunk = data as GoogleStreamChunk;\n\n // Check for error\n if ('error' in chunk) {\n const error = new UPPError(\n (chunk as any).error.message,\n 'PROVIDER_ERROR',\n 'google',\n 'llm'\n );\n responseReject(error);\n throw error;\n }\n\n const events = transformStreamChunk(chunk, state);\n for (const event of events) {\n yield event;\n }\n }\n }\n\n responseResolve(buildResponseFromState(state));\n } catch (error) {\n responseReject(error as Error);\n throw error;\n }\n }\n\n return {\n [Symbol.asyncIterator]() {\n return generateEvents();\n },\n response: responsePromise,\n };\n },\n };\n\n return model;\n },\n };\n}\n","import { createProvider } from '../../core/provider.ts';\nimport { createLLMHandler } from './llm.ts';\n\n/**\n * Google Gemini provider\n * Supports LLM modality with Gemini models\n */\nexport const google = createProvider({\n name: 'google',\n version: '1.0.0',\n modalities: {\n llm: createLLMHandler(),\n },\n});\n\n// Re-export types\nexport type { GoogleLLMParams } from './types.ts';\n"],"mappings":"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","names":[]}
@@ -0,0 +1,61 @@
1
+ export { D as DynamicKey, E as ExponentialBackoff, L as LinearBackoff, N as NoRetry, a as RetryAfterStrategy, R as RoundRobinKeys, T as TokenBucket, W as WeightedKeys, r as resolveApiKey } from '../retry-I2661_rv.js';
2
+ import { P as ProviderConfig, d as Modality, U as UPPError, c as ErrorCode } from '../provider-CUJWjgNl.js';
3
+
4
+ /**
5
+ * Execute fetch with retry, timeout, and error normalization
6
+ *
7
+ * @param url - Request URL
8
+ * @param init - Fetch init options
9
+ * @param config - Provider config
10
+ * @param provider - Provider name for error messages
11
+ * @param modality - Modality for error messages
12
+ */
13
+ declare function doFetch(url: string, init: RequestInit, config: ProviderConfig, provider: string, modality: Modality): Promise<Response>;
14
+ /**
15
+ * Streaming fetch - returns response without checking ok status
16
+ * Used when we need to read the stream for SSE
17
+ */
18
+ declare function doStreamFetch(url: string, init: RequestInit, config: ProviderConfig, provider: string, modality: Modality): Promise<Response>;
19
+
20
+ /**
21
+ * Server-Sent Events (SSE) stream parser
22
+ */
23
+ /**
24
+ * Parse a Server-Sent Events stream into JSON objects
25
+ * Handles standard SSE format with "data:" prefix
26
+ * Yields parsed JSON for each event
27
+ * Terminates on "[DONE]" message (OpenAI style)
28
+ *
29
+ * @param body - ReadableStream from fetch response
30
+ */
31
+ declare function parseSSEStream(body: ReadableStream<Uint8Array>): AsyncGenerator<unknown, void, unknown>;
32
+ /**
33
+ * Create a simple SSE reader that handles basic text streaming
34
+ * For providers that just stream text deltas
35
+ */
36
+ declare function parseSimpleTextStream(body: ReadableStream<Uint8Array>): AsyncGenerator<string, void, unknown>;
37
+
38
+ /**
39
+ * Map HTTP status codes to UPP error codes
40
+ */
41
+ declare function statusToErrorCode(status: number): ErrorCode;
42
+ /**
43
+ * Normalize HTTP error responses to UPPError
44
+ * Maps HTTP status codes to appropriate ErrorCode values
45
+ * Extracts error message from response body when available
46
+ */
47
+ declare function normalizeHttpError(response: Response, provider: string, modality: Modality): Promise<UPPError>;
48
+ /**
49
+ * Create a network error
50
+ */
51
+ declare function networkError(error: Error, provider: string, modality: Modality): UPPError;
52
+ /**
53
+ * Create a timeout error
54
+ */
55
+ declare function timeoutError(timeout: number, provider: string, modality: Modality): UPPError;
56
+ /**
57
+ * Create a cancelled error
58
+ */
59
+ declare function cancelledError(provider: string, modality: Modality): UPPError;
60
+
61
+ export { cancelledError, doFetch, doStreamFetch, networkError, normalizeHttpError, parseSSEStream, parseSimpleTextStream, statusToErrorCode, timeoutError };
@@ -0,0 +1,43 @@
1
+ import {
2
+ ExponentialBackoff,
3
+ LinearBackoff,
4
+ NoRetry,
5
+ RetryAfterStrategy,
6
+ TokenBucket
7
+ } from "../chunk-CUCRF5W6.js";
8
+ import {
9
+ DynamicKey,
10
+ RoundRobinKeys,
11
+ WeightedKeys,
12
+ cancelledError,
13
+ doFetch,
14
+ doStreamFetch,
15
+ networkError,
16
+ normalizeHttpError,
17
+ parseSSEStream,
18
+ parseSimpleTextStream,
19
+ resolveApiKey,
20
+ statusToErrorCode,
21
+ timeoutError
22
+ } from "../chunk-FTFX2VET.js";
23
+ export {
24
+ DynamicKey,
25
+ ExponentialBackoff,
26
+ LinearBackoff,
27
+ NoRetry,
28
+ RetryAfterStrategy,
29
+ RoundRobinKeys,
30
+ TokenBucket,
31
+ WeightedKeys,
32
+ cancelledError,
33
+ doFetch,
34
+ doStreamFetch,
35
+ networkError,
36
+ normalizeHttpError,
37
+ parseSSEStream,
38
+ parseSimpleTextStream,
39
+ resolveApiKey,
40
+ statusToErrorCode,
41
+ timeoutError
42
+ };
43
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}