@amux.ai/adapter-google 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,847 @@
1
+ // src/inbound/request-parser.ts
2
+ function isOpenAIFormat(request) {
3
+ const req = request;
4
+ return Array.isArray(req.messages);
5
+ }
6
+ function parseRequest(request) {
7
+ if (isOpenAIFormat(request)) {
8
+ return parseOpenAIRequest(request);
9
+ }
10
+ return parseGeminiRequest(request);
11
+ }
12
+ function parseOpenAIRequest(req) {
13
+ const messages = [];
14
+ for (const msg of req.messages) {
15
+ messages.push({
16
+ role: msg.role,
17
+ content: parseOpenAIContent(msg.content),
18
+ name: msg.name,
19
+ toolCalls: msg.tool_calls,
20
+ toolCallId: msg.tool_call_id
21
+ });
22
+ }
23
+ const tools = req.tools?.map((tool) => ({
24
+ type: "function",
25
+ function: {
26
+ name: tool.function.name,
27
+ description: tool.function.description,
28
+ parameters: tool.function.parameters
29
+ }
30
+ }));
31
+ let toolChoice;
32
+ if (req.tool_choice) {
33
+ if (typeof req.tool_choice === "string") {
34
+ toolChoice = req.tool_choice;
35
+ } else {
36
+ toolChoice = {
37
+ type: "function",
38
+ function: { name: req.tool_choice.function.name }
39
+ };
40
+ }
41
+ }
42
+ return {
43
+ messages,
44
+ model: req.model,
45
+ tools,
46
+ toolChoice,
47
+ stream: req.stream,
48
+ generation: {
49
+ temperature: req.temperature,
50
+ topP: req.top_p,
51
+ maxTokens: req.max_tokens,
52
+ stopSequences: req.stop ? Array.isArray(req.stop) ? req.stop : [req.stop] : void 0
53
+ },
54
+ raw: req
55
+ };
56
+ }
57
+ function parseOpenAIContent(content) {
58
+ if (content === null || content === void 0) {
59
+ return "";
60
+ }
61
+ if (typeof content === "string") {
62
+ return content;
63
+ }
64
+ return content.map((part) => {
65
+ if (part.type === "text") {
66
+ return {
67
+ type: "text",
68
+ text: part.text ?? ""
69
+ };
70
+ }
71
+ if (part.type === "image_url" && part.image_url) {
72
+ const url = part.image_url.url;
73
+ if (url.startsWith("data:")) {
74
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
75
+ if (match) {
76
+ return {
77
+ type: "image",
78
+ source: {
79
+ type: "base64",
80
+ mediaType: match[1],
81
+ data: match[2]
82
+ }
83
+ };
84
+ }
85
+ }
86
+ return {
87
+ type: "image",
88
+ source: {
89
+ type: "url",
90
+ url
91
+ }
92
+ };
93
+ }
94
+ return {
95
+ type: "text",
96
+ text: JSON.stringify(part)
97
+ };
98
+ });
99
+ }
100
+ function parseGeminiRequest(req) {
101
+ let system;
102
+ if (req.systemInstruction?.parts) {
103
+ system = req.systemInstruction.parts.map((p) => p.text).join("\n");
104
+ }
105
+ const messages = req.contents.flatMap((content) => parseGeminiContent(content));
106
+ const tools = req.tools?.[0]?.functionDeclarations?.map((fn) => ({
107
+ type: "function",
108
+ function: {
109
+ name: fn.name,
110
+ description: fn.description,
111
+ parameters: fn.parameters ? {
112
+ type: fn.parameters.type,
113
+ properties: fn.parameters.properties,
114
+ required: fn.parameters.required
115
+ } : void 0
116
+ }
117
+ }));
118
+ let toolChoice;
119
+ if (req.toolConfig?.functionCallingConfig) {
120
+ const mode = req.toolConfig.functionCallingConfig.mode;
121
+ if (mode === "AUTO") toolChoice = "auto";
122
+ else if (mode === "NONE") toolChoice = "none";
123
+ else if (mode === "ANY") toolChoice = "required";
124
+ }
125
+ return {
126
+ messages,
127
+ tools,
128
+ toolChoice,
129
+ system,
130
+ generation: req.generationConfig ? {
131
+ temperature: req.generationConfig.temperature,
132
+ topP: req.generationConfig.topP,
133
+ topK: req.generationConfig.topK,
134
+ maxTokens: req.generationConfig.maxOutputTokens,
135
+ stopSequences: req.generationConfig.stopSequences,
136
+ responseFormat: req.generationConfig.responseMimeType === "application/json" ? { type: "json_object" } : void 0
137
+ } : void 0,
138
+ raw: req
139
+ };
140
+ }
141
+ function parseGeminiContent(content) {
142
+ const role = content.role === "model" ? "assistant" : "user";
143
+ const parts = [];
144
+ const toolCalls = [];
145
+ const toolResults = [];
146
+ for (const part of content.parts) {
147
+ if ("text" in part) {
148
+ parts.push({
149
+ type: "text",
150
+ text: part.text
151
+ });
152
+ } else if ("inlineData" in part) {
153
+ parts.push({
154
+ type: "image",
155
+ source: {
156
+ type: "base64",
157
+ mediaType: part.inlineData.mimeType,
158
+ data: part.inlineData.data
159
+ }
160
+ });
161
+ } else if ("fileData" in part) {
162
+ parts.push({
163
+ type: "image",
164
+ source: {
165
+ type: "url",
166
+ url: part.fileData.fileUri
167
+ }
168
+ });
169
+ } else if ("functionCall" in part) {
170
+ toolCalls.push({
171
+ id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
172
+ type: "function",
173
+ function: {
174
+ name: part.functionCall.name,
175
+ arguments: JSON.stringify(part.functionCall.args)
176
+ }
177
+ });
178
+ } else if ("functionResponse" in part) {
179
+ toolResults.push({
180
+ role: "tool",
181
+ content: JSON.stringify(part.functionResponse.response),
182
+ toolCallId: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
183
+ name: part.functionResponse.name
184
+ });
185
+ }
186
+ }
187
+ const messages = [];
188
+ if (parts.length > 0 || toolCalls.length > 0) {
189
+ const allText = parts.every((p) => p.type === "text");
190
+ const messageContent = allText && parts.length === 1 ? parts[0].text : parts.length > 0 ? parts : "";
191
+ const message = {
192
+ role,
193
+ content: messageContent
194
+ };
195
+ if (toolCalls.length > 0) {
196
+ message.toolCalls = toolCalls;
197
+ }
198
+ messages.push(message);
199
+ }
200
+ messages.push(...toolResults);
201
+ return messages;
202
+ }
203
+
204
+ // src/inbound/response-parser.ts
205
+ function mapFinishReason(reason) {
206
+ if (!reason) return "stop";
207
+ const reasonMap = {
208
+ STOP: "stop",
209
+ MAX_TOKENS: "length",
210
+ SAFETY: "content_filter",
211
+ RECITATION: "content_filter",
212
+ OTHER: "stop"
213
+ };
214
+ return reasonMap[reason] ?? "stop";
215
+ }
216
+ function parseResponse(response) {
217
+ const res = response;
218
+ const choices = res.candidates.map((candidate, index) => {
219
+ const { contentParts, toolCalls } = parseParts(candidate.content.parts);
220
+ const allText = contentParts.every((p) => p.type === "text");
221
+ const content = allText && contentParts.length === 1 ? contentParts[0].text : contentParts;
222
+ return {
223
+ index: candidate.index ?? index,
224
+ message: {
225
+ role: "assistant",
226
+ content,
227
+ toolCalls: toolCalls.length > 0 ? toolCalls : void 0
228
+ },
229
+ finishReason: mapFinishReason(candidate.finishReason)
230
+ };
231
+ });
232
+ return {
233
+ id: res.responseId ?? `gemini-${Date.now()}`,
234
+ model: res.modelVersion ?? "gemini",
235
+ choices,
236
+ usage: res.usageMetadata ? {
237
+ promptTokens: res.usageMetadata.promptTokenCount,
238
+ completionTokens: res.usageMetadata.candidatesTokenCount,
239
+ totalTokens: res.usageMetadata.totalTokenCount,
240
+ details: res.usageMetadata.cachedContentTokenCount ? { cachedTokens: res.usageMetadata.cachedContentTokenCount } : void 0
241
+ } : void 0,
242
+ raw: response
243
+ };
244
+ }
245
+ function parseParts(parts) {
246
+ const contentParts = [];
247
+ const toolCalls = [];
248
+ for (const part of parts) {
249
+ if ("text" in part) {
250
+ contentParts.push({
251
+ type: "text",
252
+ text: part.text
253
+ });
254
+ } else if ("functionCall" in part) {
255
+ toolCalls.push({
256
+ id: `call_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
257
+ type: "function",
258
+ function: {
259
+ name: part.functionCall.name,
260
+ arguments: JSON.stringify(part.functionCall.args)
261
+ }
262
+ });
263
+ }
264
+ }
265
+ return { contentParts, toolCalls };
266
+ }
267
+
268
+ // src/inbound/stream-parser.ts
269
+ function mapFinishReason2(reason) {
270
+ if (!reason) return "stop";
271
+ const reasonMap = {
272
+ STOP: "stop",
273
+ MAX_TOKENS: "length",
274
+ SAFETY: "content_filter",
275
+ RECITATION: "content_filter",
276
+ OTHER: "stop",
277
+ // OpenAI-compatible reasons
278
+ stop: "stop",
279
+ length: "length",
280
+ tool_calls: "tool_calls",
281
+ content_filter: "content_filter"
282
+ };
283
+ return reasonMap[reason] ?? "stop";
284
+ }
285
+ function isOpenAIFormat2(chunk) {
286
+ const c = chunk;
287
+ return Array.isArray(c.choices) && c.choices.length > 0 && "delta" in c.choices[0];
288
+ }
289
+ function parseStream(chunk) {
290
+ if (isOpenAIFormat2(chunk)) {
291
+ return parseOpenAIStream(chunk);
292
+ }
293
+ return parseGeminiStream(chunk);
294
+ }
295
+ function parseOpenAIStream(data) {
296
+ if (!data.choices || data.choices.length === 0) {
297
+ if (data.usage) {
298
+ return {
299
+ type: "end",
300
+ id: data.id,
301
+ model: data.model,
302
+ usage: {
303
+ promptTokens: data.usage.prompt_tokens,
304
+ completionTokens: data.usage.completion_tokens,
305
+ totalTokens: data.usage.total_tokens
306
+ },
307
+ raw: data
308
+ };
309
+ }
310
+ return null;
311
+ }
312
+ const choice = data.choices[0];
313
+ if (!choice) return null;
314
+ const delta = choice.delta;
315
+ if (choice.index === 0 && !delta.content && !delta.tool_calls && !choice.finish_reason) {
316
+ return {
317
+ type: "start",
318
+ id: data.id,
319
+ model: data.model,
320
+ raw: data
321
+ };
322
+ }
323
+ if (delta.content) {
324
+ return {
325
+ type: "content",
326
+ id: data.id,
327
+ model: data.model,
328
+ content: {
329
+ type: "content",
330
+ delta: delta.content,
331
+ index: choice.index
332
+ },
333
+ raw: data
334
+ };
335
+ }
336
+ if (delta.tool_calls && delta.tool_calls.length > 0) {
337
+ const toolCall = delta.tool_calls[0];
338
+ if (toolCall) {
339
+ return {
340
+ type: "tool_call",
341
+ id: data.id,
342
+ model: data.model,
343
+ toolCall: {
344
+ type: "tool_call",
345
+ id: toolCall.id,
346
+ name: toolCall.function?.name,
347
+ arguments: toolCall.function?.arguments,
348
+ index: toolCall.index
349
+ },
350
+ raw: data
351
+ };
352
+ }
353
+ }
354
+ if (choice.finish_reason) {
355
+ return {
356
+ type: "end",
357
+ id: data.id,
358
+ model: data.model,
359
+ finishReason: mapFinishReason2(choice.finish_reason),
360
+ usage: data.usage ? {
361
+ promptTokens: data.usage.prompt_tokens,
362
+ completionTokens: data.usage.completion_tokens,
363
+ totalTokens: data.usage.total_tokens
364
+ } : void 0,
365
+ raw: data
366
+ };
367
+ }
368
+ return null;
369
+ }
370
+ function parseGeminiStream(data) {
371
+ if (!data.candidates || data.candidates.length === 0) {
372
+ if (data.usageMetadata) {
373
+ return {
374
+ type: "end",
375
+ model: data.modelVersion,
376
+ usage: {
377
+ promptTokens: data.usageMetadata.promptTokenCount,
378
+ completionTokens: data.usageMetadata.candidatesTokenCount,
379
+ totalTokens: data.usageMetadata.totalTokenCount
380
+ },
381
+ raw: data
382
+ };
383
+ }
384
+ return null;
385
+ }
386
+ const candidate = data.candidates[0];
387
+ if (!candidate) return null;
388
+ const events = [];
389
+ if (candidate.content?.parts) {
390
+ for (const part of candidate.content.parts) {
391
+ if ("text" in part) {
392
+ events.push({
393
+ type: "content",
394
+ model: data.modelVersion,
395
+ content: {
396
+ type: "content",
397
+ delta: part.text,
398
+ index: candidate.index ?? 0
399
+ },
400
+ raw: data
401
+ });
402
+ } else if ("functionCall" in part) {
403
+ events.push({
404
+ type: "tool_call",
405
+ model: data.modelVersion,
406
+ toolCall: {
407
+ type: "tool_call",
408
+ id: `call_${Date.now()}_${part.functionCall.name}`,
409
+ name: part.functionCall.name,
410
+ arguments: JSON.stringify(part.functionCall.args),
411
+ index: candidate.index ?? 0
412
+ },
413
+ raw: data
414
+ });
415
+ }
416
+ }
417
+ }
418
+ if (candidate.finishReason) {
419
+ events.push({
420
+ type: "end",
421
+ model: data.modelVersion,
422
+ finishReason: mapFinishReason2(candidate.finishReason),
423
+ usage: data.usageMetadata ? {
424
+ promptTokens: data.usageMetadata.promptTokenCount,
425
+ completionTokens: data.usageMetadata.candidatesTokenCount,
426
+ totalTokens: data.usageMetadata.totalTokenCount
427
+ } : void 0,
428
+ raw: data
429
+ });
430
+ }
431
+ if (events.length === 0) {
432
+ return null;
433
+ }
434
+ const firstEvent = events[0];
435
+ return events.length === 1 && firstEvent ? firstEvent : events;
436
+ }
437
+
438
+ // src/inbound/error-parser.ts
439
+ function parseError(error) {
440
+ if (error && typeof error === "object" && "error" in error) {
441
+ const err = error.error;
442
+ return {
443
+ type: mapErrorType(err.status, err.code),
444
+ message: err.message,
445
+ code: err.status,
446
+ status: err.code,
447
+ raw: error
448
+ };
449
+ }
450
+ return {
451
+ type: "unknown",
452
+ message: String(error),
453
+ raw: error
454
+ };
455
+ }
456
+ function mapErrorType(status, code) {
457
+ if (code) {
458
+ const codeMap = {
459
+ 400: "validation",
460
+ 401: "authentication",
461
+ 403: "permission",
462
+ 404: "not_found",
463
+ 429: "rate_limit",
464
+ 500: "server"
465
+ };
466
+ if (codeMap[code]) return codeMap[code];
467
+ }
468
+ if (status) {
469
+ const statusMap = {
470
+ INVALID_ARGUMENT: "validation",
471
+ UNAUTHENTICATED: "authentication",
472
+ PERMISSION_DENIED: "permission",
473
+ NOT_FOUND: "not_found",
474
+ RESOURCE_EXHAUSTED: "rate_limit",
475
+ INTERNAL: "server"
476
+ };
477
+ if (statusMap[status]) return statusMap[status];
478
+ }
479
+ return "unknown";
480
+ }
481
+
482
+ // src/outbound/request-builder.ts
483
+ function buildRequest(ir) {
484
+ const request = {
485
+ contents: []
486
+ };
487
+ if (ir.system) {
488
+ request.systemInstruction = {
489
+ parts: [{ text: ir.system }]
490
+ };
491
+ }
492
+ for (const msg of ir.messages) {
493
+ if (msg.role === "system") continue;
494
+ if (msg.role === "tool") {
495
+ const resultContent = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
496
+ request.contents.push({
497
+ role: "user",
498
+ parts: [{
499
+ functionResponse: {
500
+ name: msg.name ?? "unknown",
501
+ response: { result: resultContent }
502
+ }
503
+ }]
504
+ });
505
+ continue;
506
+ }
507
+ const content = buildContent(msg);
508
+ if (content) {
509
+ request.contents.push(content);
510
+ }
511
+ }
512
+ if (ir.tools && ir.tools.length > 0) {
513
+ request.tools = [
514
+ {
515
+ functionDeclarations: ir.tools.map((tool) => ({
516
+ name: tool.function.name,
517
+ description: tool.function.description,
518
+ parameters: tool.function.parameters ? {
519
+ type: tool.function.parameters.type ?? "object",
520
+ properties: tool.function.parameters.properties,
521
+ required: tool.function.parameters.required
522
+ } : void 0
523
+ }))
524
+ }
525
+ ];
526
+ }
527
+ if (ir.toolChoice) {
528
+ let mode = "AUTO";
529
+ if (ir.toolChoice === "none") mode = "NONE";
530
+ else if (ir.toolChoice === "required") mode = "ANY";
531
+ else if (ir.toolChoice === "auto") mode = "AUTO";
532
+ else if (typeof ir.toolChoice === "object") {
533
+ mode = "ANY";
534
+ request.toolConfig = {
535
+ functionCallingConfig: {
536
+ mode,
537
+ allowedFunctionNames: [ir.toolChoice.function.name]
538
+ }
539
+ };
540
+ }
541
+ if (!request.toolConfig) {
542
+ request.toolConfig = {
543
+ functionCallingConfig: { mode }
544
+ };
545
+ }
546
+ }
547
+ if (ir.generation) {
548
+ request.generationConfig = {};
549
+ if (ir.generation.temperature !== void 0) {
550
+ request.generationConfig.temperature = ir.generation.temperature;
551
+ }
552
+ if (ir.generation.topP !== void 0) {
553
+ request.generationConfig.topP = ir.generation.topP;
554
+ }
555
+ if (ir.generation.topK !== void 0) {
556
+ request.generationConfig.topK = ir.generation.topK;
557
+ }
558
+ if (ir.generation.maxTokens !== void 0) {
559
+ request.generationConfig.maxOutputTokens = ir.generation.maxTokens;
560
+ }
561
+ if (ir.generation.stopSequences && ir.generation.stopSequences.length > 0) {
562
+ request.generationConfig.stopSequences = ir.generation.stopSequences;
563
+ }
564
+ if (ir.generation.responseFormat?.type === "json_object") {
565
+ request.generationConfig.responseMimeType = "application/json";
566
+ }
567
+ }
568
+ return request;
569
+ }
570
+ function buildContent(msg) {
571
+ const role = msg.role === "assistant" ? "model" : "user";
572
+ const parts = [];
573
+ if (typeof msg.content === "string") {
574
+ if (msg.content) {
575
+ parts.push({ text: msg.content });
576
+ }
577
+ } else if (Array.isArray(msg.content)) {
578
+ for (const part of msg.content) {
579
+ if (part.type === "text") {
580
+ parts.push({ text: part.text });
581
+ } else if (part.type === "image") {
582
+ const imgPart = part;
583
+ if (imgPart.source.type === "base64") {
584
+ parts.push({
585
+ inlineData: {
586
+ mimeType: imgPart.source.mediaType,
587
+ data: imgPart.source.data
588
+ }
589
+ });
590
+ } else {
591
+ parts.push({
592
+ fileData: {
593
+ mimeType: "image/*",
594
+ fileUri: imgPart.source.url
595
+ }
596
+ });
597
+ }
598
+ }
599
+ }
600
+ }
601
+ if (msg.toolCalls && Array.isArray(msg.toolCalls)) {
602
+ for (const toolCall of msg.toolCalls) {
603
+ parts.push({
604
+ functionCall: {
605
+ name: toolCall.function.name,
606
+ args: JSON.parse(toolCall.function.arguments)
607
+ }
608
+ });
609
+ }
610
+ }
611
+ if (parts.length === 0) {
612
+ return null;
613
+ }
614
+ return { role, parts };
615
+ }
616
+
617
+ // src/outbound/response-builder.ts
618
+ function mapFinishReason3(reason) {
619
+ if (!reason) return "STOP";
620
+ const reasonMap = {
621
+ stop: "STOP",
622
+ length: "MAX_TOKENS",
623
+ tool_calls: "STOP",
624
+ content_filter: "SAFETY",
625
+ error: "OTHER"
626
+ };
627
+ return reasonMap[reason] ?? "STOP";
628
+ }
629
+ function buildResponse(ir) {
630
+ return {
631
+ candidates: ir.choices.map((choice) => ({
632
+ content: {
633
+ role: "model",
634
+ parts: buildParts(choice.message.content, choice.message.toolCalls)
635
+ },
636
+ finishReason: mapFinishReason3(choice.finishReason),
637
+ index: choice.index
638
+ })),
639
+ usageMetadata: ir.usage ? {
640
+ promptTokenCount: ir.usage.promptTokens,
641
+ candidatesTokenCount: ir.usage.completionTokens,
642
+ totalTokenCount: ir.usage.totalTokens,
643
+ cachedContentTokenCount: ir.usage.details?.cachedTokens
644
+ } : void 0,
645
+ responseId: ir.id,
646
+ modelVersion: ir.model
647
+ };
648
+ }
649
+ function buildParts(content, toolCalls) {
650
+ const parts = [];
651
+ if (typeof content === "string") {
652
+ if (content) {
653
+ parts.push({ text: content });
654
+ }
655
+ } else if (Array.isArray(content)) {
656
+ for (const part of content) {
657
+ if (part.type === "text") {
658
+ parts.push({ text: part.text });
659
+ }
660
+ }
661
+ }
662
+ if (toolCalls) {
663
+ for (const toolCall of toolCalls) {
664
+ parts.push({
665
+ functionCall: {
666
+ name: toolCall.function.name,
667
+ args: JSON.parse(toolCall.function.arguments)
668
+ }
669
+ });
670
+ }
671
+ }
672
+ return parts;
673
+ }
674
+
675
+ // src/outbound/stream-builder.ts
676
+ function createStreamBuilder() {
677
+ let responseId = `gemini-${Date.now()}`;
678
+ let model = "";
679
+ return {
680
+ process(event) {
681
+ const events = [];
682
+ if (event.id) responseId = event.id;
683
+ if (event.model) model = event.model;
684
+ if (event.type === "start") {
685
+ return events;
686
+ }
687
+ if (event.type === "content" && event.content?.delta) {
688
+ events.push({
689
+ event: "data",
690
+ data: {
691
+ candidates: [{
692
+ content: {
693
+ role: "model",
694
+ parts: [{ text: event.content.delta }]
695
+ },
696
+ index: 0
697
+ }],
698
+ modelVersion: model,
699
+ responseId
700
+ }
701
+ });
702
+ }
703
+ if (event.type === "tool_call" && event.toolCall) {
704
+ if (event.toolCall.name) {
705
+ let args = {};
706
+ if (event.toolCall.arguments) {
707
+ try {
708
+ args = JSON.parse(event.toolCall.arguments);
709
+ } catch {
710
+ args = {};
711
+ }
712
+ }
713
+ events.push({
714
+ event: "data",
715
+ data: {
716
+ candidates: [{
717
+ content: {
718
+ role: "model",
719
+ parts: [{
720
+ functionCall: {
721
+ name: event.toolCall.name,
722
+ args
723
+ }
724
+ }]
725
+ },
726
+ index: 0
727
+ }],
728
+ modelVersion: model,
729
+ responseId
730
+ }
731
+ });
732
+ }
733
+ }
734
+ if (event.type === "end") {
735
+ const finishReason = mapFinishReason4(event.finishReason);
736
+ const finalChunk = {
737
+ candidates: [{
738
+ content: {
739
+ role: "model",
740
+ parts: [{ text: "" }]
741
+ },
742
+ finishReason,
743
+ index: 0
744
+ }],
745
+ modelVersion: model,
746
+ responseId
747
+ };
748
+ if (event.usage) {
749
+ finalChunk.usageMetadata = {
750
+ promptTokenCount: event.usage.promptTokens ?? 0,
751
+ candidatesTokenCount: event.usage.completionTokens ?? 0,
752
+ totalTokenCount: event.usage.totalTokens ?? 0
753
+ };
754
+ }
755
+ events.push({ event: "data", data: finalChunk });
756
+ }
757
+ if (event.type === "error" && event.error) {
758
+ events.push({
759
+ event: "data",
760
+ data: {
761
+ error: {
762
+ code: 500,
763
+ message: event.error.message,
764
+ status: "INTERNAL"
765
+ }
766
+ }
767
+ });
768
+ }
769
+ return events;
770
+ }
771
+ };
772
+ }
773
+ function mapFinishReason4(reason) {
774
+ if (!reason) return "STOP";
775
+ const reasonMap = {
776
+ stop: "STOP",
777
+ length: "MAX_TOKENS",
778
+ tool_calls: "STOP",
779
+ content_filter: "SAFETY",
780
+ end_turn: "STOP",
781
+ max_tokens: "MAX_TOKENS"
782
+ };
783
+ return reasonMap[reason] ?? "STOP";
784
+ }
785
+
786
+ // src/adapter.ts
787
+ var googleAdapter = {
788
+ name: "google",
789
+ version: "1.0.0",
790
+ capabilities: {
791
+ streaming: true,
792
+ tools: true,
793
+ vision: true,
794
+ multimodal: true,
795
+ // Supports images, audio, video, PDFs
796
+ systemPrompt: true,
797
+ // Via systemInstruction
798
+ toolChoice: true,
799
+ // Via functionCallingConfig
800
+ reasoning: false,
801
+ webSearch: false,
802
+ jsonMode: true,
803
+ logprobs: false,
804
+ seed: false
805
+ },
806
+ inbound: {
807
+ parseRequest: (request) => {
808
+ return parseRequest(request);
809
+ },
810
+ parseResponse: (response) => {
811
+ return parseResponse(response);
812
+ },
813
+ parseStream: (chunk) => {
814
+ return parseStream(chunk);
815
+ },
816
+ parseError: (error) => {
817
+ return parseError(error);
818
+ }
819
+ },
820
+ outbound: {
821
+ buildRequest: (ir) => {
822
+ return buildRequest(ir);
823
+ },
824
+ buildResponse: (ir) => {
825
+ return buildResponse(ir);
826
+ },
827
+ createStreamBuilder
828
+ },
829
+ getInfo() {
830
+ return {
831
+ name: this.name,
832
+ version: this.version,
833
+ capabilities: this.capabilities,
834
+ endpoint: {
835
+ baseUrl: "https://generativelanguage.googleapis.com",
836
+ chatPath: "/v1beta/models/{model}:streamGenerateContent",
837
+ // Use streaming endpoint
838
+ modelsPath: "/v1beta/models"
839
+ }
840
+ };
841
+ }
842
+ };
843
+ var geminiAdapter = googleAdapter;
844
+
845
+ export { geminiAdapter, googleAdapter };
846
+ //# sourceMappingURL=index.js.map
847
+ //# sourceMappingURL=index.js.map