@yourgpt/llm-sdk 1.0.1 → 1.2.0

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 (42) hide show
  1. package/README.md +23 -15
  2. package/dist/adapters/index.d.mts +23 -9
  3. package/dist/adapters/index.d.ts +23 -9
  4. package/dist/adapters/index.js.map +1 -1
  5. package/dist/adapters/index.mjs.map +1 -1
  6. package/dist/{base-D_FyHFKj.d.mts → base-CXNMfvXg.d.mts} +10 -2
  7. package/dist/{base-D_FyHFKj.d.ts → base-CXNMfvXg.d.ts} +10 -2
  8. package/dist/index.d.mts +33 -13
  9. package/dist/index.d.ts +33 -13
  10. package/dist/index.js +160 -177
  11. package/dist/index.js.map +1 -1
  12. package/dist/index.mjs +160 -177
  13. package/dist/index.mjs.map +1 -1
  14. package/dist/providers/anthropic/index.d.mts +2 -2
  15. package/dist/providers/anthropic/index.d.ts +2 -2
  16. package/dist/providers/anthropic/index.js.map +1 -1
  17. package/dist/providers/anthropic/index.mjs.map +1 -1
  18. package/dist/providers/azure/index.d.mts +2 -2
  19. package/dist/providers/azure/index.d.ts +2 -2
  20. package/dist/providers/azure/index.js.map +1 -1
  21. package/dist/providers/azure/index.mjs.map +1 -1
  22. package/dist/providers/google/index.d.mts +23 -10
  23. package/dist/providers/google/index.d.ts +23 -10
  24. package/dist/providers/google/index.js +160 -177
  25. package/dist/providers/google/index.js.map +1 -1
  26. package/dist/providers/google/index.mjs +160 -177
  27. package/dist/providers/google/index.mjs.map +1 -1
  28. package/dist/providers/ollama/index.d.mts +2 -2
  29. package/dist/providers/ollama/index.d.ts +2 -2
  30. package/dist/providers/ollama/index.js.map +1 -1
  31. package/dist/providers/ollama/index.mjs.map +1 -1
  32. package/dist/providers/openai/index.d.mts +2 -2
  33. package/dist/providers/openai/index.d.ts +2 -2
  34. package/dist/providers/openai/index.js.map +1 -1
  35. package/dist/providers/openai/index.mjs.map +1 -1
  36. package/dist/providers/xai/index.d.mts +2 -2
  37. package/dist/providers/xai/index.d.ts +2 -2
  38. package/dist/providers/xai/index.js.map +1 -1
  39. package/dist/providers/xai/index.mjs.map +1 -1
  40. package/dist/{types-BBCZ3Fxy.d.mts → types-B8rxpnYi.d.mts} +1 -1
  41. package/dist/{types-DcoCaVVC.d.ts → types-CrQftISG.d.ts} +1 -1
  42. package/package.json +3 -7
@@ -1,5 +1,13 @@
1
- import { Message, ActionDefinition, LLMConfig, StreamEvent, MessageAttachment } from '@yourgpt/copilot-sdk/core';
1
+ import { Message, ActionDefinition, StreamEvent, LLMConfig, MessageAttachment } from '@yourgpt/copilot-sdk/core';
2
2
 
3
+ /**
4
+ * Request-level LLM configuration overrides
5
+ */
6
+ interface RequestLLMConfig {
7
+ model?: string;
8
+ temperature?: number;
9
+ maxTokens?: number;
10
+ }
3
11
  /**
4
12
  * Chat completion request
5
13
  */
@@ -17,7 +25,7 @@ interface ChatCompletionRequest {
17
25
  /** System prompt */
18
26
  systemPrompt?: string;
19
27
  /** LLM configuration overrides */
20
- config?: Partial<LLMConfig>;
28
+ config?: RequestLLMConfig;
21
29
  /** Abort signal for cancellation */
22
30
  signal?: AbortSignal;
23
31
  }
@@ -1,5 +1,13 @@
1
- import { Message, ActionDefinition, LLMConfig, StreamEvent, MessageAttachment } from '@yourgpt/copilot-sdk/core';
1
+ import { Message, ActionDefinition, StreamEvent, LLMConfig, MessageAttachment } from '@yourgpt/copilot-sdk/core';
2
2
 
3
+ /**
4
+ * Request-level LLM configuration overrides
5
+ */
6
+ interface RequestLLMConfig {
7
+ model?: string;
8
+ temperature?: number;
9
+ maxTokens?: number;
10
+ }
3
11
  /**
4
12
  * Chat completion request
5
13
  */
@@ -17,7 +25,7 @@ interface ChatCompletionRequest {
17
25
  /** System prompt */
18
26
  systemPrompt?: string;
19
27
  /** LLM configuration overrides */
20
- config?: Partial<LLMConfig>;
28
+ config?: RequestLLMConfig;
21
29
  /** Abort signal for cancellation */
22
30
  signal?: AbortSignal;
23
31
  }
package/dist/index.d.mts CHANGED
@@ -5,12 +5,12 @@ export { createOpenAI, openai } from './providers/openai/index.mjs';
5
5
  export { anthropic, createAnthropic } from './providers/anthropic/index.mjs';
6
6
  export { createXAI, xai } from './providers/xai/index.mjs';
7
7
  export { createGoogle, google } from './providers/google/index.mjs';
8
- import { LLMConfig, ActionDefinition, ToolDefinition, AgentLoopConfig, KnowledgeBaseConfig, DoneEventMessage, StreamEvent, Message, AIProvider as AIProvider$1, ToolResponse } from '@yourgpt/copilot-sdk/core';
9
- export { ActionDefinition, AgentLoopConfig, LLMConfig, LLMProvider, Message, StreamEvent, ToolDefinition, ToolExecution, ToolLocation, ToolResponse, UnifiedToolCall, UnifiedToolResult } from '@yourgpt/copilot-sdk/core';
10
- import { A as AIProvider, P as ProviderCapabilities, d as ProviderFormatter } from './types-BBCZ3Fxy.mjs';
11
- export { c as AnthropicProviderConfig, e as AnthropicTool, g as AnthropicToolResult, f as AnthropicToolUse, a as AzureProviderConfig, B as BaseProviderConfig, l as GeminiFunctionCall, k as GeminiFunctionDeclaration, m as GeminiFunctionResponse, G as GoogleProviderConfig, O as OllamaProviderConfig, b as OpenAIProviderConfig, h as OpenAITool, i as OpenAIToolCall, j as OpenAIToolResult, X as XAIProviderConfig } from './types-BBCZ3Fxy.mjs';
12
- import { L as LLMAdapter } from './base-D_FyHFKj.mjs';
13
- export { A as AdapterFactory, C as ChatCompletionRequest } from './base-D_FyHFKj.mjs';
8
+ import { ActionDefinition, ToolDefinition, AgentLoopConfig, KnowledgeBaseConfig, DoneEventMessage, StreamEvent, Message, AIProvider as AIProvider$1, ToolResponse } from '@yourgpt/copilot-sdk/core';
9
+ export { ActionDefinition, AgentLoopConfig, LLMConfig, Message, StreamEvent, ToolDefinition, ToolExecution, ToolLocation, ToolResponse, UnifiedToolCall, UnifiedToolResult } from '@yourgpt/copilot-sdk/core';
10
+ import { A as AIProvider, P as ProviderCapabilities, d as ProviderFormatter } from './types-B8rxpnYi.mjs';
11
+ export { c as AnthropicProviderConfig, e as AnthropicTool, g as AnthropicToolResult, f as AnthropicToolUse, a as AzureProviderConfig, B as BaseProviderConfig, l as GeminiFunctionCall, k as GeminiFunctionDeclaration, m as GeminiFunctionResponse, G as GoogleProviderConfig, O as OllamaProviderConfig, b as OpenAIProviderConfig, h as OpenAITool, i as OpenAIToolCall, j as OpenAIToolResult, X as XAIProviderConfig } from './types-B8rxpnYi.mjs';
12
+ import { L as LLMAdapter } from './base-CXNMfvXg.mjs';
13
+ export { A as AdapterFactory, C as ChatCompletionRequest } from './base-CXNMfvXg.mjs';
14
14
  import * as hono from 'hono';
15
15
  import { Hono } from 'hono';
16
16
  export { AnthropicAdapter, AnthropicAdapterConfig, AzureAdapter, AzureAdapterConfig, GoogleAdapter, GoogleAdapterConfig, OllamaAdapter, OllamaAdapterConfig, OpenAIAdapter, OpenAIAdapterConfig, XAIAdapter, XAIAdapterConfig, createAnthropicAdapter, createAzureAdapter, createGoogleAdapter, createOllamaAdapter, createOpenAIAdapter, createXAIAdapter } from './adapters/index.mjs';
@@ -177,14 +177,33 @@ declare function formatToolsForGoogle(tools: Record<string, Tool>): Array<{
177
177
  }>;
178
178
  }>;
179
179
 
180
+ /**
181
+ * LLM provider type for server-side configuration
182
+ */
183
+ type LLMProvider = "openai" | "anthropic" | "google" | "ollama" | "xai" | "azure";
184
+ /**
185
+ * Server-side LLM configuration (complete config for runtime)
186
+ */
187
+ interface ServerLLMConfig {
188
+ /** LLM provider */
189
+ provider: LLMProvider;
190
+ /** API key for the provider */
191
+ apiKey: string;
192
+ /** Model name */
193
+ model?: string;
194
+ /** Base URL for custom/self-hosted models */
195
+ baseUrl?: string;
196
+ /** Temperature (0-2) */
197
+ temperature?: number;
198
+ /** Maximum tokens in response */
199
+ maxTokens?: number;
200
+ }
180
201
  /**
181
202
  * Runtime configuration with LLM config
182
203
  */
183
204
  interface RuntimeConfigWithLLM {
184
205
  /** LLM configuration */
185
- llm: LLMConfig & {
186
- apiKey: string;
187
- };
206
+ llm: ServerLLMConfig;
188
207
  /** Custom LLM adapter (overrides llm config) */
189
208
  adapter?: LLMAdapter;
190
209
  /** System prompt */
@@ -220,9 +239,7 @@ interface RuntimeConfigWithAdapter {
220
239
  /** Custom LLM adapter */
221
240
  adapter: LLMAdapter;
222
241
  /** LLM configuration (optional when adapter provided) */
223
- llm?: LLMConfig & {
224
- apiKey: string;
225
- };
242
+ llm?: ServerLLMConfig;
226
243
  /** System prompt */
227
244
  systemPrompt?: string;
228
245
  /** Available actions (legacy) */
@@ -312,7 +329,10 @@ interface ChatRequest {
312
329
  /** Bot ID (for cloud) */
313
330
  botId?: string;
314
331
  /** LLM config overrides */
315
- config?: Partial<LLMConfig>;
332
+ config?: {
333
+ temperature?: number;
334
+ maxTokens?: number;
335
+ };
316
336
  /** System prompt override */
317
337
  systemPrompt?: string;
318
338
  /** Actions from client (legacy) */
package/dist/index.d.ts CHANGED
@@ -5,12 +5,12 @@ export { createOpenAI, openai } from './providers/openai/index.js';
5
5
  export { anthropic, createAnthropic } from './providers/anthropic/index.js';
6
6
  export { createXAI, xai } from './providers/xai/index.js';
7
7
  export { createGoogle, google } from './providers/google/index.js';
8
- import { LLMConfig, ActionDefinition, ToolDefinition, AgentLoopConfig, KnowledgeBaseConfig, DoneEventMessage, StreamEvent, Message, AIProvider as AIProvider$1, ToolResponse } from '@yourgpt/copilot-sdk/core';
9
- export { ActionDefinition, AgentLoopConfig, LLMConfig, LLMProvider, Message, StreamEvent, ToolDefinition, ToolExecution, ToolLocation, ToolResponse, UnifiedToolCall, UnifiedToolResult } from '@yourgpt/copilot-sdk/core';
10
- import { A as AIProvider, P as ProviderCapabilities, d as ProviderFormatter } from './types-DcoCaVVC.js';
11
- export { c as AnthropicProviderConfig, e as AnthropicTool, g as AnthropicToolResult, f as AnthropicToolUse, a as AzureProviderConfig, B as BaseProviderConfig, l as GeminiFunctionCall, k as GeminiFunctionDeclaration, m as GeminiFunctionResponse, G as GoogleProviderConfig, O as OllamaProviderConfig, b as OpenAIProviderConfig, h as OpenAITool, i as OpenAIToolCall, j as OpenAIToolResult, X as XAIProviderConfig } from './types-DcoCaVVC.js';
12
- import { L as LLMAdapter } from './base-D_FyHFKj.js';
13
- export { A as AdapterFactory, C as ChatCompletionRequest } from './base-D_FyHFKj.js';
8
+ import { ActionDefinition, ToolDefinition, AgentLoopConfig, KnowledgeBaseConfig, DoneEventMessage, StreamEvent, Message, AIProvider as AIProvider$1, ToolResponse } from '@yourgpt/copilot-sdk/core';
9
+ export { ActionDefinition, AgentLoopConfig, LLMConfig, Message, StreamEvent, ToolDefinition, ToolExecution, ToolLocation, ToolResponse, UnifiedToolCall, UnifiedToolResult } from '@yourgpt/copilot-sdk/core';
10
+ import { A as AIProvider, P as ProviderCapabilities, d as ProviderFormatter } from './types-CrQftISG.js';
11
+ export { c as AnthropicProviderConfig, e as AnthropicTool, g as AnthropicToolResult, f as AnthropicToolUse, a as AzureProviderConfig, B as BaseProviderConfig, l as GeminiFunctionCall, k as GeminiFunctionDeclaration, m as GeminiFunctionResponse, G as GoogleProviderConfig, O as OllamaProviderConfig, b as OpenAIProviderConfig, h as OpenAITool, i as OpenAIToolCall, j as OpenAIToolResult, X as XAIProviderConfig } from './types-CrQftISG.js';
12
+ import { L as LLMAdapter } from './base-CXNMfvXg.js';
13
+ export { A as AdapterFactory, C as ChatCompletionRequest } from './base-CXNMfvXg.js';
14
14
  import * as hono from 'hono';
15
15
  import { Hono } from 'hono';
16
16
  export { AnthropicAdapter, AnthropicAdapterConfig, AzureAdapter, AzureAdapterConfig, GoogleAdapter, GoogleAdapterConfig, OllamaAdapter, OllamaAdapterConfig, OpenAIAdapter, OpenAIAdapterConfig, XAIAdapter, XAIAdapterConfig, createAnthropicAdapter, createAzureAdapter, createGoogleAdapter, createOllamaAdapter, createOpenAIAdapter, createXAIAdapter } from './adapters/index.js';
@@ -177,14 +177,33 @@ declare function formatToolsForGoogle(tools: Record<string, Tool>): Array<{
177
177
  }>;
178
178
  }>;
179
179
 
180
+ /**
181
+ * LLM provider type for server-side configuration
182
+ */
183
+ type LLMProvider = "openai" | "anthropic" | "google" | "ollama" | "xai" | "azure";
184
+ /**
185
+ * Server-side LLM configuration (complete config for runtime)
186
+ */
187
+ interface ServerLLMConfig {
188
+ /** LLM provider */
189
+ provider: LLMProvider;
190
+ /** API key for the provider */
191
+ apiKey: string;
192
+ /** Model name */
193
+ model?: string;
194
+ /** Base URL for custom/self-hosted models */
195
+ baseUrl?: string;
196
+ /** Temperature (0-2) */
197
+ temperature?: number;
198
+ /** Maximum tokens in response */
199
+ maxTokens?: number;
200
+ }
180
201
  /**
181
202
  * Runtime configuration with LLM config
182
203
  */
183
204
  interface RuntimeConfigWithLLM {
184
205
  /** LLM configuration */
185
- llm: LLMConfig & {
186
- apiKey: string;
187
- };
206
+ llm: ServerLLMConfig;
188
207
  /** Custom LLM adapter (overrides llm config) */
189
208
  adapter?: LLMAdapter;
190
209
  /** System prompt */
@@ -220,9 +239,7 @@ interface RuntimeConfigWithAdapter {
220
239
  /** Custom LLM adapter */
221
240
  adapter: LLMAdapter;
222
241
  /** LLM configuration (optional when adapter provided) */
223
- llm?: LLMConfig & {
224
- apiKey: string;
225
- };
242
+ llm?: ServerLLMConfig;
226
243
  /** System prompt */
227
244
  systemPrompt?: string;
228
245
  /** Available actions (legacy) */
@@ -312,7 +329,10 @@ interface ChatRequest {
312
329
  /** Bot ID (for cloud) */
313
330
  botId?: string;
314
331
  /** LLM config overrides */
315
- config?: Partial<LLMConfig>;
332
+ config?: {
333
+ temperature?: number;
334
+ maxTokens?: number;
335
+ };
316
336
  /** System prompt override */
317
337
  systemPrompt?: string;
318
338
  /** Actions from client (legacy) */
package/dist/index.js CHANGED
@@ -1393,6 +1393,21 @@ function formatMessagesForXAI(messages) {
1393
1393
 
1394
1394
  // src/providers/google/provider.ts
1395
1395
  var GOOGLE_MODELS = {
1396
+ // Gemini 2.5 (Experimental)
1397
+ "gemini-2.5-pro-preview-05-06": {
1398
+ vision: true,
1399
+ tools: true,
1400
+ audio: true,
1401
+ video: true,
1402
+ maxTokens: 1048576
1403
+ },
1404
+ "gemini-2.5-flash-preview-05-20": {
1405
+ vision: true,
1406
+ tools: true,
1407
+ audio: true,
1408
+ video: true,
1409
+ maxTokens: 1048576
1410
+ },
1396
1411
  // Gemini 2.0
1397
1412
  "gemini-2.0-flash": {
1398
1413
  vision: true,
@@ -1408,6 +1423,13 @@ var GOOGLE_MODELS = {
1408
1423
  video: true,
1409
1424
  maxTokens: 1048576
1410
1425
  },
1426
+ "gemini-2.0-flash-lite": {
1427
+ vision: true,
1428
+ tools: true,
1429
+ audio: false,
1430
+ video: false,
1431
+ maxTokens: 1048576
1432
+ },
1411
1433
  "gemini-2.0-flash-thinking-exp": {
1412
1434
  vision: true,
1413
1435
  tools: false,
@@ -1454,11 +1476,15 @@ var GOOGLE_MODELS = {
1454
1476
  };
1455
1477
  function google(modelId, options = {}) {
1456
1478
  const apiKey = options.apiKey ?? process.env.GOOGLE_API_KEY ?? process.env.GEMINI_API_KEY;
1479
+ const baseURL = options.baseURL ?? "https://generativelanguage.googleapis.com/v1beta/openai/";
1457
1480
  let client = null;
1458
1481
  async function getClient() {
1459
1482
  if (!client) {
1460
- const { GoogleGenerativeAI } = await import('@google/generative-ai');
1461
- client = new GoogleGenerativeAI(apiKey);
1483
+ const { default: OpenAI } = await import('openai');
1484
+ client = new OpenAI({
1485
+ apiKey,
1486
+ baseURL
1487
+ });
1462
1488
  }
1463
1489
  return client;
1464
1490
  }
@@ -1478,219 +1504,176 @@ function google(modelId, options = {}) {
1478
1504
  },
1479
1505
  async doGenerate(params) {
1480
1506
  const client2 = await getClient();
1481
- const model = client2.getGenerativeModel({
1507
+ const messages = formatMessagesForGoogle(params.messages);
1508
+ const response = await client2.chat.completions.create({
1482
1509
  model: modelId,
1483
- safetySettings: options.safetySettings
1510
+ messages,
1511
+ tools: params.tools,
1512
+ temperature: params.temperature,
1513
+ max_tokens: params.maxTokens
1484
1514
  });
1485
- const { systemInstruction, contents } = formatMessagesForGemini(
1486
- params.messages
1515
+ const choice = response.choices[0];
1516
+ const message = choice.message;
1517
+ const toolCalls = (message.tool_calls ?? []).map(
1518
+ (tc) => ({
1519
+ id: tc.id,
1520
+ name: tc.function.name,
1521
+ args: JSON.parse(tc.function.arguments || "{}")
1522
+ })
1487
1523
  );
1488
- const chat = model.startChat({
1489
- history: contents.slice(0, -1),
1490
- systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
1491
- tools: params.tools ? [{ functionDeclarations: formatToolsForGemini(params.tools) }] : void 0,
1492
- generationConfig: {
1493
- temperature: params.temperature,
1494
- maxOutputTokens: params.maxTokens
1495
- }
1496
- });
1497
- const lastMessage = contents[contents.length - 1];
1498
- const result = await chat.sendMessage(lastMessage.parts);
1499
- const response = result.response;
1500
- let text = "";
1501
- const toolCalls = [];
1502
- let toolCallIndex = 0;
1503
- const candidate = response.candidates?.[0];
1504
- if (candidate?.content?.parts) {
1505
- for (const part of candidate.content.parts) {
1506
- if ("text" in part && part.text) {
1507
- text += part.text;
1508
- }
1509
- if ("functionCall" in part && part.functionCall) {
1510
- toolCalls.push({
1511
- id: `call_${toolCallIndex++}`,
1512
- name: part.functionCall.name,
1513
- args: part.functionCall.args || {}
1514
- });
1515
- }
1516
- }
1517
- }
1518
1524
  return {
1519
- text,
1525
+ text: message.content ?? "",
1520
1526
  toolCalls,
1521
- finishReason: mapFinishReason4(candidate?.finishReason),
1527
+ finishReason: mapFinishReason4(choice.finish_reason),
1522
1528
  usage: {
1523
- promptTokens: response.usageMetadata?.promptTokenCount ?? 0,
1524
- completionTokens: response.usageMetadata?.candidatesTokenCount ?? 0,
1525
- totalTokens: response.usageMetadata?.totalTokenCount ?? 0
1529
+ promptTokens: response.usage?.prompt_tokens ?? 0,
1530
+ completionTokens: response.usage?.completion_tokens ?? 0,
1531
+ totalTokens: response.usage?.total_tokens ?? 0
1526
1532
  },
1527
1533
  rawResponse: response
1528
1534
  };
1529
1535
  },
1530
1536
  async *doStream(params) {
1531
1537
  const client2 = await getClient();
1532
- const model = client2.getGenerativeModel({
1538
+ const messages = formatMessagesForGoogle(params.messages);
1539
+ const stream = await client2.chat.completions.create({
1533
1540
  model: modelId,
1534
- safetySettings: options.safetySettings
1541
+ messages,
1542
+ tools: params.tools,
1543
+ temperature: params.temperature,
1544
+ max_tokens: params.maxTokens,
1545
+ stream: true
1535
1546
  });
1536
- const { systemInstruction, contents } = formatMessagesForGemini(
1537
- params.messages
1538
- );
1539
- const chat = model.startChat({
1540
- history: contents.slice(0, -1),
1541
- systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,
1542
- tools: params.tools ? [{ functionDeclarations: formatToolsForGemini(params.tools) }] : void 0,
1543
- generationConfig: {
1544
- temperature: params.temperature,
1545
- maxOutputTokens: params.maxTokens
1547
+ let currentToolCall = null;
1548
+ let totalPromptTokens = 0;
1549
+ let totalCompletionTokens = 0;
1550
+ for await (const chunk of stream) {
1551
+ if (params.signal?.aborted) {
1552
+ yield { type: "error", error: new Error("Aborted") };
1553
+ return;
1546
1554
  }
1547
- });
1548
- const lastMessage = contents[contents.length - 1];
1549
- const result = await chat.sendMessageStream(lastMessage.parts);
1550
- let toolCallIndex = 0;
1551
- let promptTokens = 0;
1552
- let completionTokens = 0;
1553
- try {
1554
- for await (const chunk of result.stream) {
1555
- if (params.signal?.aborted) {
1556
- yield { type: "error", error: new Error("Aborted") };
1557
- return;
1558
- }
1559
- const candidate = chunk.candidates?.[0];
1560
- if (!candidate?.content?.parts) continue;
1561
- for (const part of candidate.content.parts) {
1562
- if ("text" in part && part.text) {
1563
- yield { type: "text-delta", text: part.text };
1564
- }
1565
- if ("functionCall" in part && part.functionCall) {
1566
- yield {
1567
- type: "tool-call",
1568
- toolCall: {
1569
- id: `call_${toolCallIndex++}`,
1570
- name: part.functionCall.name,
1571
- args: part.functionCall.args || {}
1572
- }
1555
+ const choice = chunk.choices[0];
1556
+ const delta = choice?.delta;
1557
+ if (delta?.content) {
1558
+ yield { type: "text-delta", text: delta.content };
1559
+ }
1560
+ if (delta?.tool_calls) {
1561
+ for (const tc of delta.tool_calls) {
1562
+ if (tc.id) {
1563
+ if (currentToolCall) {
1564
+ yield {
1565
+ type: "tool-call",
1566
+ toolCall: {
1567
+ id: currentToolCall.id,
1568
+ name: currentToolCall.name,
1569
+ args: JSON.parse(currentToolCall.arguments || "{}")
1570
+ }
1571
+ };
1572
+ }
1573
+ currentToolCall = {
1574
+ id: tc.id,
1575
+ name: tc.function?.name ?? "",
1576
+ arguments: tc.function?.arguments ?? ""
1573
1577
  };
1578
+ } else if (currentToolCall && tc.function?.arguments) {
1579
+ currentToolCall.arguments += tc.function.arguments;
1574
1580
  }
1575
1581
  }
1576
- if (chunk.usageMetadata) {
1577
- promptTokens = chunk.usageMetadata.promptTokenCount ?? 0;
1578
- completionTokens = chunk.usageMetadata.candidatesTokenCount ?? 0;
1579
- }
1580
- if (candidate.finishReason) {
1582
+ }
1583
+ if (choice?.finish_reason) {
1584
+ if (currentToolCall) {
1581
1585
  yield {
1582
- type: "finish",
1583
- finishReason: mapFinishReason4(candidate.finishReason),
1584
- usage: {
1585
- promptTokens,
1586
- completionTokens,
1587
- totalTokens: promptTokens + completionTokens
1586
+ type: "tool-call",
1587
+ toolCall: {
1588
+ id: currentToolCall.id,
1589
+ name: currentToolCall.name,
1590
+ args: JSON.parse(currentToolCall.arguments || "{}")
1588
1591
  }
1589
1592
  };
1593
+ currentToolCall = null;
1594
+ }
1595
+ if (chunk.usage) {
1596
+ totalPromptTokens = chunk.usage.prompt_tokens;
1597
+ totalCompletionTokens = chunk.usage.completion_tokens;
1590
1598
  }
1599
+ yield {
1600
+ type: "finish",
1601
+ finishReason: mapFinishReason4(choice.finish_reason),
1602
+ usage: {
1603
+ promptTokens: totalPromptTokens,
1604
+ completionTokens: totalCompletionTokens,
1605
+ totalTokens: totalPromptTokens + totalCompletionTokens
1606
+ }
1607
+ };
1591
1608
  }
1592
- } catch (error) {
1593
- yield {
1594
- type: "error",
1595
- error: error instanceof Error ? error : new Error(String(error))
1596
- };
1597
1609
  }
1598
1610
  }
1599
1611
  };
1600
1612
  }
1601
1613
  function mapFinishReason4(reason) {
1602
1614
  switch (reason) {
1603
- case "STOP":
1615
+ case "stop":
1604
1616
  return "stop";
1605
- case "MAX_TOKENS":
1617
+ case "length":
1606
1618
  return "length";
1607
- case "SAFETY":
1619
+ case "tool_calls":
1620
+ case "function_call":
1621
+ return "tool-calls";
1622
+ case "content_filter":
1608
1623
  return "content-filter";
1609
1624
  default:
1610
1625
  return "unknown";
1611
1626
  }
1612
1627
  }
1613
- function formatMessagesForGemini(messages) {
1614
- let systemInstruction = "";
1615
- const contents = [];
1616
- for (const msg of messages) {
1617
- if (msg.role === "system") {
1618
- systemInstruction += (systemInstruction ? "\n" : "") + msg.content;
1619
- continue;
1620
- }
1621
- const parts = [];
1622
- if (msg.role === "user") {
1623
- if (typeof msg.content === "string") {
1624
- parts.push({ text: msg.content });
1625
- } else {
1626
- for (const part of msg.content) {
1627
- if (part.type === "text") {
1628
- parts.push({ text: part.text });
1629
- } else if (part.type === "image") {
1630
- const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
1631
- const base64 = imageData.startsWith("data:") ? imageData.split(",")[1] : imageData;
1632
- parts.push({
1633
- inlineData: {
1634
- mimeType: part.mimeType ?? "image/png",
1635
- data: base64
1636
- }
1637
- });
1638
- }
1628
+ function formatMessagesForGoogle(messages) {
1629
+ return messages.map((msg) => {
1630
+ switch (msg.role) {
1631
+ case "system":
1632
+ return { role: "system", content: msg.content };
1633
+ case "user":
1634
+ if (typeof msg.content === "string") {
1635
+ return { role: "user", content: msg.content };
1639
1636
  }
1640
- }
1641
- contents.push({ role: "user", parts });
1642
- } else if (msg.role === "assistant") {
1643
- if (msg.content) {
1644
- parts.push({ text: msg.content });
1645
- }
1646
- if (msg.toolCalls?.length) {
1647
- for (const tc of msg.toolCalls) {
1648
- parts.push({
1649
- functionCall: {
1637
+ return {
1638
+ role: "user",
1639
+ content: msg.content.map((part) => {
1640
+ if (part.type === "text") {
1641
+ return { type: "text", text: part.text };
1642
+ }
1643
+ if (part.type === "image") {
1644
+ const imageData = typeof part.image === "string" ? part.image : Buffer.from(part.image).toString("base64");
1645
+ const url = imageData.startsWith("data:") ? imageData : `data:${part.mimeType ?? "image/png"};base64,${imageData}`;
1646
+ return { type: "image_url", image_url: { url, detail: "auto" } };
1647
+ }
1648
+ return { type: "text", text: "" };
1649
+ })
1650
+ };
1651
+ case "assistant":
1652
+ const assistantMsg = {
1653
+ role: "assistant",
1654
+ content: msg.content
1655
+ };
1656
+ if (msg.toolCalls && msg.toolCalls.length > 0) {
1657
+ assistantMsg.tool_calls = msg.toolCalls.map((tc) => ({
1658
+ id: tc.id,
1659
+ type: "function",
1660
+ function: {
1650
1661
  name: tc.name,
1651
- args: tc.args
1662
+ arguments: JSON.stringify(tc.args)
1652
1663
  }
1653
- });
1664
+ }));
1654
1665
  }
1655
- }
1656
- if (parts.length > 0) {
1657
- contents.push({ role: "model", parts });
1658
- }
1659
- } else if (msg.role === "tool") {
1660
- contents.push({
1661
- role: "user",
1662
- parts: [
1663
- {
1664
- functionResponse: {
1665
- name: "tool",
1666
- // Gemini doesn't track by ID
1667
- response: JSON.parse(msg.content || "{}")
1668
- }
1669
- }
1670
- ]
1671
- });
1672
- }
1673
- }
1674
- if (contents.length === 0 || contents[0].role !== "user") {
1675
- contents.unshift({ role: "user", parts: [{ text: "" }] });
1676
- }
1677
- const merged = [];
1678
- for (const content of contents) {
1679
- const last = merged[merged.length - 1];
1680
- if (last && last.role === content.role) {
1681
- last.parts.push(...content.parts);
1682
- } else {
1683
- merged.push({ ...content, parts: [...content.parts] });
1666
+ return assistantMsg;
1667
+ case "tool":
1668
+ return {
1669
+ role: "tool",
1670
+ tool_call_id: msg.toolCallId,
1671
+ content: msg.content
1672
+ };
1673
+ default:
1674
+ return msg;
1684
1675
  }
1685
- }
1686
- return { systemInstruction, contents: merged };
1687
- }
1688
- function formatToolsForGemini(tools) {
1689
- return tools.map((t) => ({
1690
- name: t.function.name,
1691
- description: t.function.description,
1692
- parameters: t.function.parameters
1693
- }));
1676
+ });
1694
1677
  }
1695
1678
 
1696
1679
  // src/adapters/base.ts
@@ -2596,7 +2579,7 @@ function messageToGeminiContent(msg) {
2596
2579
  parts
2597
2580
  };
2598
2581
  }
2599
- function formatToolsForGemini2(actions) {
2582
+ function formatToolsForGemini(actions) {
2600
2583
  if (!actions || actions.length === 0) return void 0;
2601
2584
  return {
2602
2585
  functionDeclarations: actions.map((action) => ({
@@ -2682,7 +2665,7 @@ var GoogleAdapter = class {
2682
2665
  mergedContents.push({ ...content, parts: [...content.parts] });
2683
2666
  }
2684
2667
  }
2685
- const tools = formatToolsForGemini2(request.actions);
2668
+ const tools = formatToolsForGemini(request.actions);
2686
2669
  const messageId = core.generateMessageId();
2687
2670
  yield { type: "message:start", id: messageId };
2688
2671
  try {
@@ -2788,7 +2771,7 @@ var GoogleAdapter = class {
2788
2771
  mergedContents.push({ ...content, parts: [...content.parts] });
2789
2772
  }
2790
2773
  }
2791
- const tools = formatToolsForGemini2(request.actions);
2774
+ const tools = formatToolsForGemini(request.actions);
2792
2775
  const chat = model.startChat({
2793
2776
  history: mergedContents.slice(0, -1),
2794
2777
  systemInstruction: systemInstruction ? { parts: [{ text: systemInstruction }] } : void 0,