@aigne/gemini 1.74.0-beta.3 → 1.74.0-beta.4

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/README.md CHANGED
@@ -44,19 +44,19 @@ AIGNE Gemini SDK for integrating with Google's Gemini AI models within the [AIGN
44
44
  ### Using npm
45
45
 
46
46
  ```bash
47
- npm install @aigne/gemini @aigne/core
47
+ npm install @aigne/gemini @aigne/model-base
48
48
  ```
49
49
 
50
50
  ### Using yarn
51
51
 
52
52
  ```bash
53
- yarn add @aigne/gemini @aigne/core
53
+ yarn add @aigne/gemini @aigne/model-base
54
54
  ```
55
55
 
56
56
  ### Using pnpm
57
57
 
58
58
  ```bash
59
- pnpm add @aigne/gemini @aigne/core
59
+ pnpm add @aigne/gemini @aigne/model-base
60
60
  ```
61
61
 
62
62
  ## Chat Completions
@@ -235,7 +235,7 @@ console.log(result.images); // Array of edited images
235
235
  ## Streaming Responses
236
236
 
237
237
  ```typescript file="test/gemini-chat-model.test.ts" region="example-gemini-chat-model-streaming"
238
- import { isAgentResponseDelta } from "@aigne/core";
238
+ import { isAgentResponseDelta } from "@aigne/model-base";
239
239
  import { GeminiChatModel } from "@aigne/gemini";
240
240
 
241
241
  const model = new GeminiChatModel({
@@ -1,8 +1,8 @@
1
- let _aigne_core = require("@aigne/core");
2
- let _aigne_core_utils_logger = require("@aigne/core/utils/logger");
3
- let _aigne_core_utils_model_utils = require("@aigne/core/utils/model-utils");
4
- let _aigne_core_utils_type_utils = require("@aigne/core/utils/type-utils");
5
- let _aigne_utils_nodejs = require("@aigne/utils/nodejs");
1
+ let _aigne_model_base = require("@aigne/model-base");
2
+ let _aigne_model_base_utils_logger = require("@aigne/model-base/utils/logger");
3
+ let _aigne_model_base_utils_model_utils = require("@aigne/model-base/utils/model-utils");
4
+ let _aigne_model_base_utils_nodejs = require("@aigne/model-base/utils/nodejs");
5
+ let _aigne_model_base_utils_type_utils = require("@aigne/model-base/utils/type-utils");
6
6
  let _aigne_uuid = require("@aigne/uuid");
7
7
  let _google_genai = require("@google/genai");
8
8
  let yaml = require("yaml");
@@ -24,7 +24,7 @@ const NEED_UPLOAD_MAX_FILE_SIZE_MB = 20;
24
24
  * Here's an example with streaming response:
25
25
  * {@includeCode ../test/gemini-chat-model.test.ts#example-gemini-chat-model-streaming}
26
26
  */
27
- var GeminiChatModel = class extends _aigne_core.ChatModel {
27
+ var GeminiChatModel = class extends _aigne_model_base.ChatModel {
28
28
  constructor(options) {
29
29
  super({
30
30
  ...options,
@@ -67,7 +67,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
67
67
  model,
68
68
  contents
69
69
  })).totalTokens;
70
- if (!(0, _aigne_core_utils_type_utils.isNil)(tokens)) return tokens;
70
+ if (!(0, _aigne_model_base_utils_type_utils.isNil)(tokens)) return tokens;
71
71
  return super.countTokens(input);
72
72
  }
73
73
  contentUnionToContent(content) {
@@ -233,14 +233,14 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
233
233
  if (toolCalls.length) yield { delta: { json: { toolCalls } } };
234
234
  if (input.responseFormat?.type === "json_schema") {
235
235
  if (json) yield { delta: { json: { json } } };
236
- else if (text) yield { delta: { json: { json: (0, _aigne_core.safeParseJSON)(text) } } };
237
- else if (!toolCalls.length) throw new _aigne_core.StructuredOutputError("No JSON response from the model");
236
+ else if (text) yield { delta: { json: { json: (0, _aigne_model_base.safeParseJSON)(text) } } };
237
+ else if (!toolCalls.length) throw new _aigne_model_base.StructuredOutputError("No JSON response from the model");
238
238
  } else if (!toolCalls.length) {
239
239
  if (!text && !files.length) {
240
- _aigne_core_utils_logger.logger.warn("Empty response from Gemini, retrying with structured output mode");
240
+ _aigne_model_base_utils_logger.logger.warn("Empty response from Gemini, retrying with structured output mode");
241
241
  try {
242
242
  const outputSchema = zod.z.object({ output: zod.z.string().describe("The final answer from the model") });
243
- const result = await (0, _aigne_core.agentProcessResultToObject)(await this.process({
243
+ const result = await (0, _aigne_model_base.modelProcessResultToObject)(await this.process({
244
244
  ...input,
245
245
  responseFormat: {
246
246
  type: "json_schema",
@@ -250,7 +250,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
250
250
  }
251
251
  }
252
252
  }, options));
253
- usage = (0, _aigne_core_utils_model_utils.mergeUsage)(usage, result.usage);
253
+ usage = (0, _aigne_model_base_utils_model_utils.mergeUsage)(usage, result.usage);
254
254
  if (result.toolCalls?.length) {
255
255
  toolCalls.push(...result.toolCalls);
256
256
  yield { delta: { json: { toolCalls } } };
@@ -260,11 +260,11 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
260
260
  if (!parsed.success) throw new Error("Retrying with structured output mode got invalid json response");
261
261
  text = parsed.data.output;
262
262
  yield { delta: { text: { text } } };
263
- _aigne_core_utils_logger.logger.warn("Empty response from Gemini, retried with structured output mode successfully");
263
+ _aigne_model_base_utils_logger.logger.warn("Empty response from Gemini, retried with structured output mode successfully");
264
264
  }
265
265
  } catch (error) {
266
- _aigne_core_utils_logger.logger.error("Empty response from Gemini, retrying with structured output mode failed", error);
267
- throw new _aigne_core.StructuredOutputError("No response from the model");
266
+ _aigne_model_base_utils_logger.logger.error("Empty response from Gemini, retrying with structured output mode failed", error);
267
+ throw new _aigne_model_base.StructuredOutputError("No response from the model");
268
268
  }
269
269
  }
270
270
  }
@@ -313,7 +313,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
313
313
  async buildVideoContentParts(media) {
314
314
  const { path: filePath, mimeType: fileMimeType } = await this.transformFileType("local", media);
315
315
  if (filePath) {
316
- if ((await _aigne_utils_nodejs.nodejs.fs.stat(filePath)).size / (1024 * 1024) > NEED_UPLOAD_MAX_FILE_SIZE_MB) {
316
+ if ((await _aigne_model_base_utils_nodejs.nodejs.fs.stat(filePath)).size / (1024 * 1024) > NEED_UPLOAD_MAX_FILE_SIZE_MB) {
317
317
  let file = await this.googleClient.files.upload({
318
318
  file: filePath,
319
319
  config: { mimeType: fileMimeType }
@@ -326,7 +326,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
326
326
  if (file.uri && file.mimeType) {
327
327
  const part = (0, _google_genai.createUserContent)([(0, _google_genai.createPartFromUri)(file.uri, file.mimeType), ""]).parts?.find((x) => x.fileData);
328
328
  if (part) {
329
- await _aigne_utils_nodejs.nodejs.fs.rm(filePath);
329
+ await _aigne_model_base_utils_nodejs.nodejs.fs.rm(filePath);
330
330
  return part;
331
331
  }
332
332
  }
@@ -370,7 +370,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
370
370
  if (text) {
371
371
  try {
372
372
  const obj = (0, yaml.parse)(text);
373
- if ((0, _aigne_core_utils_type_utils.isRecord)(obj)) toolResult = obj;
373
+ if ((0, _aigne_model_base_utils_type_utils.isRecord)(obj)) toolResult = obj;
374
374
  } catch {}
375
375
  if (!toolResult) toolResult = { result: text };
376
376
  }
@@ -384,7 +384,7 @@ var GeminiChatModel = class extends _aigne_core.ChatModel {
384
384
  content.parts = [{ functionResponse }];
385
385
  } else if (msg.content) content.parts = await this.contentToParts(msg.content);
386
386
  return content;
387
- }))).filter(_aigne_core_utils_type_utils.isNonNullable);
387
+ }))).filter(_aigne_model_base_utils_type_utils.isNonNullable);
388
388
  this.ensureMessagesHasUserMessage(systemParts, result.contents);
389
389
  if (systemParts.length) {
390
390
  result.config ??= {};
@@ -1,19 +1,18 @@
1
- import * as _aigne_core0 from "@aigne/core";
2
- import { AgentInvokeOptions, AgentProcessResult, ChatModel, ChatModelInput, ChatModelInputOptions, ChatModelOptions, ChatModelOutput } from "@aigne/core";
3
- import { PromiseOrValue } from "@aigne/core/utils/type-utils";
1
+ import { ChatModel, ChatModelInput, ChatModelInputOptions, ChatModelOptions, ChatModelOutput, ModelInvokeOptions, ModelProcessResult } from "@aigne/model-base";
2
+ import { PromiseOrValue } from "@aigne/model-base/utils/type-utils";
4
3
  import { GoogleGenAI, GoogleGenAIOptions, ThinkingLevel } from "@google/genai";
5
4
 
6
5
  //#region src/gemini-chat-model.d.ts
7
6
  interface GeminiChatModelOptions extends ChatModelOptions {
8
7
  /**
9
- * API key for Gemini API
10
- *
11
- * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables
12
- */
8
+ * API key for Gemini API
9
+ *
10
+ * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables
11
+ */
13
12
  apiKey?: string;
14
13
  /**
15
- * Optional client options for the Gemini SDK
16
- */
14
+ * Optional client options for the Gemini SDK
15
+ */
17
16
  clientOptions?: Partial<GoogleGenAIOptions>;
18
17
  }
19
18
  /**
@@ -37,42 +36,10 @@ declare class GeminiChatModel extends ChatModel {
37
36
  apiKey: string | undefined;
38
37
  model: string;
39
38
  };
40
- get modelOptions(): Partial<{
41
- [x: string]: unknown;
42
- model?: string | {
43
- $get: string;
44
- } | undefined;
45
- temperature?: number | {
46
- $get: string;
47
- } | undefined;
48
- topP?: number | {
49
- $get: string;
50
- } | undefined;
51
- frequencyPenalty?: number | {
52
- $get: string;
53
- } | undefined;
54
- presencePenalty?: number | {
55
- $get: string;
56
- } | undefined;
57
- parallelToolCalls?: boolean | {
58
- $get: string;
59
- } | undefined;
60
- modalities?: {
61
- $get: string;
62
- } | _aigne_core0.Modality[] | undefined;
63
- preferInputFileType?: "url" | {
64
- $get: string;
65
- } | "file" | undefined;
66
- reasoningEffort?: number | {
67
- $get: string;
68
- } | "minimal" | "low" | "medium" | "high" | undefined;
69
- cacheConfig?: {
70
- $get: string;
71
- } | _aigne_core0.CacheConfig | undefined;
72
- }> | undefined;
39
+ get modelOptions(): ChatModelInputOptions | undefined;
73
40
  countTokens(input: ChatModelInput): Promise<number>;
74
41
  private contentUnionToContent;
75
- process(input: ChatModelInput, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
42
+ process(input: ChatModelInput, options: ModelInvokeOptions): PromiseOrValue<ModelProcessResult<ChatModelOutput>>;
76
43
  protected thinkingBudgetModelMap: ({
77
44
  pattern: RegExp;
78
45
  support: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-chat-model.d.cts","names":[],"sources":["../src/gemini-chat-model.ts"],"mappings":";;;;;;UA+CiB,sBAAA,SAA+B,gBAAA;EAAA;;AAyBhD;;;EAzBgD,MAAA;EAAA;;AAyBhD;EAzBgD,aAAA,GAW9B,OAAA,CAAQ,kBAAA;AAAA;AAAA;;;;AAc1B;;;;;;;AAd0B,cAcb,eAAA,SAAwB,SAAA;EAAA,OAAA,GACG,sBAAA;EAAA,YAAA,OAAA,GAAA,sBAAA;EAAA,UAAA,aAAA;EAAA,UAAA,aAAA,GASZ,WAAA;EAAA,IAAA,aAAA,GAEV,WAAA;EAAA,IAAA,WAAA;IAAA,MAAA;IAAA,KAAA;EAAA;EAAA,IAAA,aAAA,GA+BA,OAAA;IAAA,CAAA,CAAA;IAAA,KAAA;MAAA,IAAA;IAAA;IAAA,WAAA;MAAA,IAAA;IAAA;IAAA,IAAA;MAAA,IAAA;IAAA;IAAA,gBAAA;MAAA,IAAA;IAAA;IAAA,eAAA;MAAA,IAAA;IAAA;IAAA,iBAAA;MAAA,IAAA;IAAA;IAAA,UAAA;MAAA,IAAA;IAAA,IA/BA,YAAA,CAAA,QAAA;IAAA,mBAAA;MAAA,IAAA;IAAA;IAAA,eAAA;MAAA,IAAA;IAAA;IAAA,WAAA;MAAA,IAAA;IAAA;;qBAmCkB,cAAA,GAAiB,OAAA;EAAA,QAAA,qBAAA;EAAA,QAAA,KAAA,EAwC1C,cAAA,EAAA,OAAA,EACE,kBAAA,GACR,cAAA,CAAe,kBAAA,CAAmB,eAAA;EAAA,UAAA,sBAAA;IAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAwD3B,qBAAA;IAAA,OAAA;IAAA,MAAA;IAAA,KAAA,GACsC,aAAA;EAAA;EAAA,QAAA,aAAA;EAAA,QAAA,YAAA;EAAA,QAAA,WAAA;EAAA,QAAA,UAAA;EAAA,QAAA,sBAAA;EAAA,QAAA,aAAA;EAAA,QAAA,cAAA;EAAA,QAAA,4BAAA;AAAA"}
1
+ {"version":3,"file":"gemini-chat-model.d.cts","names":[],"sources":["../src/gemini-chat-model.ts"],"mappings":";;;;;UAoDiB,sBAAA,SAA+B,gBAAA;;AAAhD;;;;EAME,MAAA;EAN8C;;;EAW9C,aAAA,GAAgB,OAAA,CAAQ,kBAAA;AAAA;;;;;;AAc1B;;;;;;cAAa,eAAA,SAAwB,SAAA;EACP,OAAA,GAAU,sBAAA;cAAV,OAAA,GAAU,sBAAA;EAAA,UAO5B,aAAA;EAAA,UAEA,aAAA,GAAgB,WAAA;EAAA,IAEtB,YAAA,CAAA,GAAY,WAAA;EAAA,IAkBH,UAAA,CAAA;;;;MAaT,YAAA,CAAA,GAAY,qBAAA;EAID,WAAA,CAAY,KAAA,EAAO,cAAA,GAAiB,OAAA;EAAA,QAwB3C,qBAAA;EAeC,OAAA,CACP,KAAA,EAAO,cAAA,EACP,OAAA,EAAS,kBAAA,GACR,cAAA,CAAe,kBAAA,CAAmB,eAAA;EAAA,UAK3B,sBAAA;;;;;;;;;;;;;;;;;;;YAmCA,sBAAA;;;;;;YAOA,gBAAA;;;;;;YAOA,iBAAA,CACR,KAAA,UACA,MAAA,EAAQ,qBAAA;IACL,OAAA;IAAkB,MAAA;IAAiB,KAAA,GAAQ,aAAA;EAAA;EAAA,QA4BlC,aAAA;EAAA,QAgCC,YAAA;EAAA,QAgLD,WAAA;EAAA,QAiCA,UAAA;EAAA,QAiCA,sBAAA;EAAA,QAwCA,aAAA;EAAA,QA2GA,cAAA;EAAA,QAyBN,4BAAA;AAAA"}
@@ -1,19 +1,18 @@
1
- import * as _aigne_core0 from "@aigne/core";
2
- import { AgentInvokeOptions, AgentProcessResult, ChatModel, ChatModelInput, ChatModelInputOptions, ChatModelOptions, ChatModelOutput } from "@aigne/core";
3
- import { PromiseOrValue } from "@aigne/core/utils/type-utils";
1
+ import { ChatModel, ChatModelInput, ChatModelInputOptions, ChatModelOptions, ChatModelOutput, ModelInvokeOptions, ModelProcessResult } from "@aigne/model-base";
2
+ import { PromiseOrValue } from "@aigne/model-base/utils/type-utils";
4
3
  import { GoogleGenAI, GoogleGenAIOptions, ThinkingLevel } from "@google/genai";
5
4
 
6
5
  //#region src/gemini-chat-model.d.ts
7
6
  interface GeminiChatModelOptions extends ChatModelOptions {
8
7
  /**
9
- * API key for Gemini API
10
- *
11
- * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables
12
- */
8
+ * API key for Gemini API
9
+ *
10
+ * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables
11
+ */
13
12
  apiKey?: string;
14
13
  /**
15
- * Optional client options for the Gemini SDK
16
- */
14
+ * Optional client options for the Gemini SDK
15
+ */
17
16
  clientOptions?: Partial<GoogleGenAIOptions>;
18
17
  }
19
18
  /**
@@ -37,42 +36,10 @@ declare class GeminiChatModel extends ChatModel {
37
36
  apiKey: string | undefined;
38
37
  model: string;
39
38
  };
40
- get modelOptions(): Partial<{
41
- [x: string]: unknown;
42
- model?: string | {
43
- $get: string;
44
- } | undefined;
45
- temperature?: number | {
46
- $get: string;
47
- } | undefined;
48
- topP?: number | {
49
- $get: string;
50
- } | undefined;
51
- frequencyPenalty?: number | {
52
- $get: string;
53
- } | undefined;
54
- presencePenalty?: number | {
55
- $get: string;
56
- } | undefined;
57
- parallelToolCalls?: boolean | {
58
- $get: string;
59
- } | undefined;
60
- modalities?: {
61
- $get: string;
62
- } | _aigne_core0.Modality[] | undefined;
63
- preferInputFileType?: "url" | {
64
- $get: string;
65
- } | "file" | undefined;
66
- reasoningEffort?: number | {
67
- $get: string;
68
- } | "minimal" | "low" | "medium" | "high" | undefined;
69
- cacheConfig?: {
70
- $get: string;
71
- } | _aigne_core0.CacheConfig | undefined;
72
- }> | undefined;
39
+ get modelOptions(): ChatModelInputOptions | undefined;
73
40
  countTokens(input: ChatModelInput): Promise<number>;
74
41
  private contentUnionToContent;
75
- process(input: ChatModelInput, options: AgentInvokeOptions): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
42
+ process(input: ChatModelInput, options: ModelInvokeOptions): PromiseOrValue<ModelProcessResult<ChatModelOutput>>;
76
43
  protected thinkingBudgetModelMap: ({
77
44
  pattern: RegExp;
78
45
  support: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-chat-model.d.mts","names":[],"sources":["../src/gemini-chat-model.ts"],"mappings":";;;;;;UA+CiB,sBAAA,SAA+B,gBAAA;EAAA;;AAyBhD;;;EAzBgD,MAAA;EAAA;;AAyBhD;EAzBgD,aAAA,GAW9B,OAAA,CAAQ,kBAAA;AAAA;AAAA;;;;AAc1B;;;;;;;AAd0B,cAcb,eAAA,SAAwB,SAAA;EAAA,OAAA,GACG,sBAAA;EAAA,YAAA,OAAA,GAAA,sBAAA;EAAA,UAAA,aAAA;EAAA,UAAA,aAAA,GASZ,WAAA;EAAA,IAAA,aAAA,GAEV,WAAA;EAAA,IAAA,WAAA;IAAA,MAAA;IAAA,KAAA;EAAA;EAAA,IAAA,aAAA,GA+BA,OAAA;IAAA,CAAA,CAAA;IAAA,KAAA;MAAA,IAAA;IAAA;IAAA,WAAA;MAAA,IAAA;IAAA;IAAA,IAAA;MAAA,IAAA;IAAA;IAAA,gBAAA;MAAA,IAAA;IAAA;IAAA,eAAA;MAAA,IAAA;IAAA;IAAA,iBAAA;MAAA,IAAA;IAAA;IAAA,UAAA;MAAA,IAAA;IAAA,IA/BA,YAAA,CAAA,QAAA;IAAA,mBAAA;MAAA,IAAA;IAAA;IAAA,eAAA;MAAA,IAAA;IAAA;IAAA,WAAA;MAAA,IAAA;IAAA;;qBAmCkB,cAAA,GAAiB,OAAA;EAAA,QAAA,qBAAA;EAAA,QAAA,KAAA,EAwC1C,cAAA,EAAA,OAAA,EACE,kBAAA,GACR,cAAA,CAAe,kBAAA,CAAmB,eAAA;EAAA,UAAA,sBAAA;IAAA,OAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qDAwD3B,qBAAA;IAAA,OAAA;IAAA,MAAA;IAAA,KAAA,GACsC,aAAA;EAAA;EAAA,QAAA,aAAA;EAAA,QAAA,YAAA;EAAA,QAAA,WAAA;EAAA,QAAA,UAAA;EAAA,QAAA,sBAAA;EAAA,QAAA,aAAA;EAAA,QAAA,cAAA;EAAA,QAAA,4BAAA;AAAA"}
1
+ {"version":3,"file":"gemini-chat-model.d.mts","names":[],"sources":["../src/gemini-chat-model.ts"],"mappings":";;;;;UAoDiB,sBAAA,SAA+B,gBAAA;;AAAhD;;;;EAME,MAAA;EAN8C;;;EAW9C,aAAA,GAAgB,OAAA,CAAQ,kBAAA;AAAA;;;;;;AAc1B;;;;;;cAAa,eAAA,SAAwB,SAAA;EACP,OAAA,GAAU,sBAAA;cAAV,OAAA,GAAU,sBAAA;EAAA,UAO5B,aAAA;EAAA,UAEA,aAAA,GAAgB,WAAA;EAAA,IAEtB,YAAA,CAAA,GAAY,WAAA;EAAA,IAkBH,UAAA,CAAA;;;;MAaT,YAAA,CAAA,GAAY,qBAAA;EAID,WAAA,CAAY,KAAA,EAAO,cAAA,GAAiB,OAAA;EAAA,QAwB3C,qBAAA;EAeC,OAAA,CACP,KAAA,EAAO,cAAA,EACP,OAAA,EAAS,kBAAA,GACR,cAAA,CAAe,kBAAA,CAAmB,eAAA;EAAA,UAK3B,sBAAA;;;;;;;;;;;;;;;;;;;YAmCA,sBAAA;;;;;;YAOA,gBAAA;;;;;;YAOA,iBAAA,CACR,KAAA,UACA,MAAA,EAAQ,qBAAA;IACL,OAAA;IAAkB,MAAA;IAAiB,KAAA,GAAQ,aAAA;EAAA;EAAA,QA4BlC,aAAA;EAAA,QAgCC,YAAA;EAAA,QAgLD,WAAA;EAAA,QAiCA,UAAA;EAAA,QAiCA,sBAAA;EAAA,QAwCA,aAAA;EAAA,QA2GA,cAAA;EAAA,QAyBN,4BAAA;AAAA"}
@@ -1,8 +1,8 @@
1
- import { ChatModel, StructuredOutputError, agentProcessResultToObject, safeParseJSON } from "@aigne/core";
2
- import { logger } from "@aigne/core/utils/logger";
3
- import { mergeUsage } from "@aigne/core/utils/model-utils";
4
- import { isNil, isNonNullable, isRecord } from "@aigne/core/utils/type-utils";
5
- import { nodejs } from "@aigne/utils/nodejs";
1
+ import { ChatModel, StructuredOutputError, modelProcessResultToObject, safeParseJSON } from "@aigne/model-base";
2
+ import { logger } from "@aigne/model-base/utils/logger";
3
+ import { mergeUsage } from "@aigne/model-base/utils/model-utils";
4
+ import { nodejs } from "@aigne/model-base/utils/nodejs";
5
+ import { isNil, isNonNullable, isRecord } from "@aigne/model-base/utils/type-utils";
6
6
  import { v7 } from "@aigne/uuid";
7
7
  import { FunctionCallingConfigMode, GoogleGenAI, ThinkingLevel, createPartFromUri, createUserContent } from "@google/genai";
8
8
  import { parse } from "yaml";
@@ -240,7 +240,7 @@ var GeminiChatModel = class extends ChatModel {
240
240
  logger.warn("Empty response from Gemini, retrying with structured output mode");
241
241
  try {
242
242
  const outputSchema = z.object({ output: z.string().describe("The final answer from the model") });
243
- const result = await agentProcessResultToObject(await this.process({
243
+ const result = await modelProcessResultToObject(await this.process({
244
244
  ...input,
245
245
  responseFormat: {
246
246
  type: "json_schema",
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-chat-model.mjs","names":[],"sources":["../src/gemini-chat-model.ts"],"sourcesContent":["import {\n type AgentInvokeOptions,\n type AgentProcessAsyncGenerator,\n type AgentProcessResult,\n agentProcessResultToObject,\n ChatModel,\n type ChatModelInput,\n type ChatModelInputMessageContent,\n type ChatModelInputOptions,\n type ChatModelOptions,\n type ChatModelOutput,\n type ChatModelOutputToolCall,\n type ChatModelOutputUsage,\n type FileUnionContent,\n StructuredOutputError,\n safeParseJSON,\n} from \"@aigne/core\";\nimport { logger } from \"@aigne/core/utils/logger\";\nimport { mergeUsage } from \"@aigne/core/utils/model-utils\";\nimport { isNil, isNonNullable, isRecord, type PromiseOrValue } from \"@aigne/core/utils/type-utils\";\nimport { nodejs } from \"@aigne/utils/nodejs\";\nimport { v7 } from \"@aigne/uuid\";\nimport {\n type Content,\n type ContentUnion,\n createPartFromUri,\n createUserContent,\n type FunctionCallingConfig,\n FunctionCallingConfigMode,\n type FunctionResponse,\n type GenerateContentConfig,\n type GenerateContentParameters,\n GoogleGenAI,\n type GoogleGenAIOptions,\n type Part,\n ThinkingLevel,\n type ToolListUnion,\n} from \"@google/genai\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nconst GEMINI_DEFAULT_CHAT_MODEL = \"gemini-2.0-flash\";\n\nconst OUTPUT_FUNCTION_NAME = \"output\";\nconst NEED_UPLOAD_MAX_FILE_SIZE_MB = 20;\n\nexport interface GeminiChatModelOptions extends ChatModelOptions {\n /**\n * API key for Gemini API\n *\n * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables\n */\n apiKey?: string;\n\n /**\n * Optional client options for the Gemini SDK\n */\n clientOptions?: Partial<GoogleGenAIOptions>;\n}\n\n/**\n * Implementation of the ChatModel interface for Google's Gemini API\n *\n * @example\n * Here's how to create and use a Gemini chat model:\n * {@includeCode ../test/gemini-chat-model.test.ts#example-gemini-chat-model}\n *\n * @example\n * Here's an example with streaming response:\n * {@includeCode ../test/gemini-chat-model.test.ts#example-gemini-chat-model-streaming}\n */\nexport class GeminiChatModel extends ChatModel {\n constructor(public override options?: GeminiChatModelOptions) {\n super({\n ...options,\n model: options?.model || GEMINI_DEFAULT_CHAT_MODEL,\n });\n }\n\n protected apiKeyEnvName = \"GEMINI_API_KEY\";\n\n protected _googleClient?: GoogleGenAI;\n\n get googleClient() {\n if (this._googleClient) return this._googleClient;\n\n const { apiKey } = this.credential;\n\n if (!apiKey)\n throw new Error(\n `${this.name} requires an API key. Please provide it via \\`options.apiKey\\`, or set the \\`${this.apiKeyEnvName}\\` environment variable`,\n );\n\n this._googleClient ??= new GoogleGenAI({\n apiKey,\n ...this.options?.clientOptions,\n });\n\n return this._googleClient;\n }\n\n override get credential() {\n const apiKey =\n this.options?.apiKey ||\n process.env[this.apiKeyEnvName] ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY;\n\n return {\n apiKey,\n model: this.options?.model || GEMINI_DEFAULT_CHAT_MODEL,\n };\n }\n\n get modelOptions() {\n return this.options?.modelOptions;\n }\n\n override async countTokens(input: ChatModelInput): Promise<number> {\n const { model, ...request } = await this.getParameters(input);\n\n const contents: Content[] = [];\n\n const { systemInstruction, tools } = request.config ?? {};\n\n if (systemInstruction) contents.push(this.contentUnionToContent(systemInstruction));\n if (tools?.length) contents.push({ role: \"system\", parts: [{ text: JSON.stringify(tools) }] });\n\n contents.push(...[request.contents].flat().map(this.contentUnionToContent));\n\n const tokens = (\n await this.googleClient.models.countTokens({\n model,\n contents,\n })\n ).totalTokens;\n\n if (!isNil(tokens)) return tokens;\n\n return super.countTokens(input);\n }\n\n private contentUnionToContent(content: ContentUnion): Content {\n if (typeof content === \"object\" && \"parts\" in content) {\n return { role: \"system\", parts: content.parts };\n } else if (typeof content === \"string\") {\n return { role: \"system\", parts: [{ text: content }] };\n } else if (Array.isArray(content)) {\n return {\n role: \"system\",\n parts: content.map((i) => (typeof i === \"string\" ? { text: i } : i)),\n };\n } else {\n return { role: \"system\", parts: [content as Part] };\n }\n }\n\n override process(\n input: ChatModelInput,\n options: AgentInvokeOptions,\n ): PromiseOrValue<AgentProcessResult<ChatModelOutput>> {\n return this.processInput(input, options);\n }\n\n // References: https://ai.google.dev/gemini-api/docs/thinking#set-budget\n protected thinkingBudgetModelMap = [\n // 注意:gemini-2.5-flash-image-preview 模型并不支持 thinking。see: https://github.com/CherryHQ/cherry-studio/issues/9614\n {\n pattern: /gemini-2.5-flash-image-preview/,\n support: false,\n },\n {\n pattern: /gemini-3(?!.*-image-)/,\n support: true,\n type: \"level\",\n },\n {\n pattern: /gemini-2.5-pro/,\n support: true,\n min: 128,\n max: 32768,\n },\n {\n pattern: /gemini-2.5-flash/,\n support: true,\n min: 0,\n max: 24576,\n },\n {\n pattern: /2.5-flash-lite/,\n support: true,\n min: 512,\n max: 24576,\n },\n {\n pattern: /.*/,\n support: false,\n },\n ];\n\n protected thinkingBudgetLevelMap = {\n high: 100000, // use 100k for high, finally capped by model max\n medium: 10000,\n low: 5000,\n minimal: 200,\n };\n\n protected thinkingLevelMap = {\n high: ThinkingLevel.HIGH,\n medium: ThinkingLevel.HIGH,\n low: ThinkingLevel.LOW,\n minimal: ThinkingLevel.LOW,\n };\n\n protected getThinkingBudget(\n model: string,\n effort: ChatModelInputOptions[\"reasoningEffort\"],\n ): { support: boolean; budget?: number; level?: ThinkingLevel } {\n const m = this.thinkingBudgetModelMap.find((i) => i.pattern.test(model));\n\n if (!m?.support) return { support: false };\n\n if (m.type === \"level\") {\n let level = ThinkingLevel.THINKING_LEVEL_UNSPECIFIED;\n\n if (typeof effort === \"string\") {\n level = this.thinkingLevelMap[effort];\n } else if (typeof effort === \"number\") {\n level =\n effort >= this.thinkingBudgetLevelMap[\"medium\"] ? ThinkingLevel.HIGH : ThinkingLevel.LOW;\n }\n\n return { support: true, level };\n }\n\n let budget =\n typeof effort === \"string\" ? this.thinkingBudgetLevelMap[effort] || undefined : effort;\n if (typeof budget === \"undefined\") return { support: true };\n\n if (typeof m.min === \"number\") budget = Math.max(m.min, budget);\n if (typeof m.max === \"number\") budget = Math.min(m.max, budget);\n\n return { support: true, budget };\n }\n\n private async getParameters(input: ChatModelInput): Promise<GenerateContentParameters> {\n const { modelOptions = {} } = input;\n\n const model = modelOptions.model || this.credential.model;\n const { contents, config } = await this.buildContents(input);\n\n const thinkingBudget = this.getThinkingBudget(model, modelOptions.reasoningEffort);\n\n const parameters: GenerateContentParameters = {\n model,\n contents,\n config: {\n thinkingConfig: thinkingBudget.support\n ? {\n includeThoughts: true,\n thinkingBudget: thinkingBudget.budget,\n thinkingLevel: thinkingBudget.level,\n }\n : undefined,\n responseModalities: modelOptions.modalities,\n temperature: modelOptions.temperature,\n topP: modelOptions.topP,\n frequencyPenalty: modelOptions.frequencyPenalty,\n presencePenalty: modelOptions.presencePenalty,\n ...config,\n ...(await this.buildConfig(input)),\n },\n };\n\n return parameters;\n }\n\n private async *processInput(\n input: ChatModelInput,\n options: AgentInvokeOptions,\n ): AgentProcessAsyncGenerator<ChatModelOutput> {\n const parameters = await this.getParameters(input);\n\n const response = await this.googleClient.models.generateContentStream(parameters);\n\n let usage: ChatModelOutputUsage = {\n inputTokens: 0,\n outputTokens: 0,\n };\n let responseModel: string | undefined;\n\n const files: FileUnionContent[] = [];\n const toolCalls: ChatModelOutputToolCall[] = [];\n let text = \"\";\n let json: any;\n\n for await (const chunk of response) {\n if (!responseModel && chunk.modelVersion) {\n responseModel = chunk.modelVersion;\n yield { delta: { json: { model: responseModel } } };\n }\n\n for (const { content } of chunk.candidates ?? []) {\n if (content?.parts) {\n for (const part of content.parts) {\n if (part.text) {\n if (part.thought) {\n yield { delta: { text: { thoughts: part.text } } };\n } else {\n text += part.text;\n if (input.responseFormat?.type !== \"json_schema\") {\n yield { delta: { text: { text: part.text } } };\n }\n }\n }\n if (part.inlineData?.data) {\n files.push({\n type: \"file\",\n data: part.inlineData.data,\n filename: part.inlineData.displayName,\n mimeType: part.inlineData.mimeType,\n });\n }\n\n if (part.functionCall?.name) {\n if (part.functionCall.name === OUTPUT_FUNCTION_NAME) {\n json = part.functionCall.args;\n } else {\n const toolCall: ChatModelOutputToolCall = {\n id: part.functionCall.id || v7(),\n type: \"function\",\n function: {\n name: part.functionCall.name,\n arguments: part.functionCall.args || {},\n },\n };\n\n // Preserve thought_signature for 3.x models\n if (part.thoughtSignature && parameters.model.includes(\"gemini-3\")) {\n toolCall.metadata = {\n thoughtSignature: part.thoughtSignature,\n };\n }\n\n toolCalls.push(toolCall);\n }\n }\n }\n }\n }\n\n if (chunk.usageMetadata) {\n if (chunk.usageMetadata.promptTokenCount)\n usage.inputTokens = chunk.usageMetadata.promptTokenCount;\n if (chunk.usageMetadata.candidatesTokenCount || chunk.usageMetadata.thoughtsTokenCount)\n usage.outputTokens =\n (chunk.usageMetadata.candidatesTokenCount || 0) +\n (chunk.usageMetadata.thoughtsTokenCount || 0);\n // Parse cache statistics if available\n if (chunk.usageMetadata.cachedContentTokenCount) {\n usage.cacheReadInputTokens = chunk.usageMetadata.cachedContentTokenCount;\n }\n }\n }\n\n if (toolCalls.length) {\n yield { delta: { json: { toolCalls } } };\n }\n if (input.responseFormat?.type === \"json_schema\") {\n if (json) {\n yield { delta: { json: { json } } };\n } else if (text) {\n yield { delta: { json: { json: safeParseJSON(text) } } };\n } else if (!toolCalls.length) {\n throw new StructuredOutputError(\"No JSON response from the model\");\n }\n } else if (!toolCalls.length) {\n // NOTE: gemini-2.5-pro sometimes returns an empty response,\n // so we check here and retry with structured output mode (empty responses occur less frequently with tool calls)\n if (!text && !files.length) {\n logger.warn(\"Empty response from Gemini, retrying with structured output mode\");\n\n try {\n const outputSchema = z.object({\n output: z.string().describe(\"The final answer from the model\"),\n });\n\n const response = await this.process(\n {\n ...input,\n responseFormat: {\n type: \"json_schema\",\n jsonSchema: {\n name: \"output\",\n schema: zodToJsonSchema(outputSchema),\n },\n },\n },\n options,\n );\n\n const result = await agentProcessResultToObject(response);\n\n // Merge retry usage with the original usage\n usage = mergeUsage(usage, result.usage);\n\n // Return the tool calls if retry has tool calls\n if (result.toolCalls?.length) {\n toolCalls.push(...result.toolCalls);\n yield { delta: { json: { toolCalls } } };\n }\n // Return the text from structured output of retry\n else {\n if (!result.json)\n throw new Error(\"Retrying with structured output mode got no json response\");\n\n const parsed = outputSchema.safeParse(result.json);\n\n if (!parsed.success)\n throw new Error(\"Retrying with structured output mode got invalid json response\");\n\n text = parsed.data.output;\n yield { delta: { text: { text } } };\n\n logger.warn(\n \"Empty response from Gemini, retried with structured output mode successfully\",\n );\n }\n } catch (error) {\n logger.error(\n \"Empty response from Gemini, retrying with structured output mode failed\",\n error,\n );\n throw new StructuredOutputError(\"No response from the model\");\n }\n }\n }\n\n yield {\n delta: {\n json: {\n usage,\n files: files.length ? files : undefined,\n modelOptions: {\n reasoningEffort:\n parameters.config?.thinkingConfig?.thinkingLevel ||\n parameters.config?.thinkingConfig?.thinkingBudget,\n },\n },\n },\n };\n }\n\n private async buildConfig(input: ChatModelInput): Promise<GenerateContentParameters[\"config\"]> {\n const config: GenerateContentParameters[\"config\"] = {};\n\n const { tools, toolConfig } = await this.buildTools(input);\n\n config.tools = tools;\n config.toolConfig = toolConfig;\n\n if (input.responseFormat?.type === \"json_schema\") {\n if (config.tools?.length) {\n config.tools.push({\n functionDeclarations: [\n {\n name: OUTPUT_FUNCTION_NAME,\n description: \"Output the final response\",\n parametersJsonSchema: input.responseFormat.jsonSchema.schema,\n },\n ],\n });\n\n config.toolConfig = {\n ...config.toolConfig,\n functionCallingConfig: { mode: FunctionCallingConfigMode.ANY },\n };\n } else {\n config.responseJsonSchema = input.responseFormat.jsonSchema.schema;\n config.responseMimeType = \"application/json\";\n }\n }\n\n return config;\n }\n\n private async buildTools(\n input: ChatModelInput,\n ): Promise<Pick<GenerateContentConfig, \"tools\" | \"toolConfig\">> {\n const tools: ToolListUnion = [];\n\n for (const tool of input.tools ?? []) {\n tools.push({\n functionDeclarations: [\n {\n name: tool.function.name,\n description: tool.function.description,\n parametersJsonSchema: tool.function.parameters,\n },\n ],\n });\n }\n\n const functionCallingConfig: FunctionCallingConfig | undefined = !input.toolChoice\n ? undefined\n : input.toolChoice === \"auto\"\n ? { mode: FunctionCallingConfigMode.AUTO }\n : input.toolChoice === \"none\"\n ? { mode: FunctionCallingConfigMode.NONE }\n : input.toolChoice === \"required\"\n ? { mode: FunctionCallingConfigMode.ANY }\n : {\n mode: FunctionCallingConfigMode.ANY,\n allowedFunctionNames: [input.toolChoice.function.name],\n };\n\n return { tools, toolConfig: { functionCallingConfig } };\n }\n\n private async buildVideoContentParts(media: FileUnionContent): Promise<Part | undefined> {\n const { path: filePath, mimeType: fileMimeType } = await this.transformFileType(\"local\", media);\n\n if (filePath) {\n const stats = await nodejs.fs.stat(filePath);\n const fileSizeInBytes = stats.size;\n const fileSizeMB = fileSizeInBytes / (1024 * 1024);\n\n if (fileSizeMB > NEED_UPLOAD_MAX_FILE_SIZE_MB) {\n const uploadedFile = await this.googleClient.files.upload({\n file: filePath,\n config: { mimeType: fileMimeType },\n });\n\n let file = uploadedFile;\n while (file.state === \"PROCESSING\") {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n if (file.name) {\n file = await this.googleClient.files.get({ name: file.name });\n }\n }\n\n if (file.state !== \"ACTIVE\") {\n throw new Error(`File ${file.name} failed to process: ${file.state}`);\n }\n\n if (file.uri && file.mimeType) {\n const result = createUserContent([createPartFromUri(file.uri, file.mimeType), \"\"]);\n const part = result.parts?.find((x) => x.fileData);\n\n if (part) {\n await nodejs.fs.rm(filePath);\n return part;\n }\n }\n }\n }\n }\n\n private async buildContents(\n input: ChatModelInput,\n ): Promise<Omit<GenerateContentParameters, \"model\">> {\n const result: Omit<GenerateContentParameters, \"model\"> = {\n contents: [],\n };\n\n const systemParts: Part[] = [];\n\n result.contents = (\n await Promise.all(\n input.messages.map(async (msg) => {\n if (msg.role === \"system\") {\n if (typeof msg.content === \"string\") {\n systemParts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n systemParts.push(\n ...msg.content.map<Part>((item) => {\n if (item.type === \"text\") return { text: item.text };\n throw new Error(`Unsupported content type: ${item.type}`);\n }),\n );\n }\n\n return;\n }\n\n const content: Content = {\n role: msg.role === \"agent\" ? \"model\" : msg.role === \"user\" ? \"user\" : undefined,\n };\n\n if (msg.toolCalls) {\n content.parts = msg.toolCalls.map((call) => {\n const part: Part = {\n functionCall: {\n id: call.id,\n name: call.function.name,\n args: call.function.arguments,\n },\n };\n\n // Restore thought_signature for 3.x models\n if (call.metadata?.thoughtSignature) {\n part.thoughtSignature = call.metadata.thoughtSignature;\n }\n\n return part;\n });\n } else if (msg.toolCallId) {\n const call = input.messages\n .flatMap((i) => i.toolCalls)\n .find((c) => c?.id === msg.toolCallId);\n if (!call) throw new Error(`Tool call not found: ${msg.toolCallId}`);\n if (!msg.content) throw new Error(\"Tool call must have content\");\n\n // parse tool result as a record\n let toolResult: Record<string, unknown> | undefined;\n {\n let text: string | undefined;\n if (typeof msg.content === \"string\") text = msg.content;\n else if (msg.content?.length === 1) {\n const first = msg.content[0];\n if (first?.type === \"text\") text = first.text;\n }\n\n if (text) {\n try {\n const obj = parse(text);\n if (isRecord(obj)) toolResult = obj;\n } catch {\n // ignore\n }\n if (!toolResult) toolResult = { result: text };\n }\n }\n\n const functionResponse: FunctionResponse = {\n id: msg.toolCallId,\n name: call.function.name,\n };\n\n if (toolResult) {\n functionResponse.response = toolResult;\n } else {\n functionResponse.parts = await this.contentToParts(msg.content);\n }\n\n content.parts = [{ functionResponse }];\n } else if (msg.content) {\n content.parts = await this.contentToParts(msg.content);\n }\n\n return content;\n }),\n )\n ).filter(isNonNullable);\n\n this.ensureMessagesHasUserMessage(systemParts, result.contents);\n\n if (systemParts.length) {\n result.config ??= {};\n result.config.systemInstruction = systemParts;\n }\n\n return result;\n }\n\n private async contentToParts(content: ChatModelInputMessageContent): Promise<Part[]> {\n if (typeof content === \"string\") return [{ text: content }];\n\n return Promise.all(\n content.map<Promise<Part>>(async (item) => {\n switch (item.type) {\n case \"text\":\n return { text: item.text };\n case \"url\":\n return { fileData: { fileUri: item.url, mimeType: item.mimeType } };\n case \"file\": {\n const part = await this.buildVideoContentParts(item);\n if (part) return part;\n\n return { inlineData: { data: item.data, mimeType: item.mimeType } };\n }\n case \"local\":\n throw new Error(\n `Unsupported local file: ${item.path}, it should be converted to base64 at ChatModel`,\n );\n }\n }),\n );\n }\n\n private ensureMessagesHasUserMessage(systems: Part[], contents: Content[]) {\n // no messages but system messages\n if (!contents.length && systems.length) {\n const system = systems.pop();\n if (system) contents.push({ role: \"user\", parts: [system] });\n }\n\n // first message is from model\n if (contents[0]?.role === \"model\") {\n const system = systems.pop();\n if (system) contents.unshift({ role: \"user\", parts: [system] });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"gemini-chat-model.mjs","names":[],"sources":["../src/gemini-chat-model.ts"],"sourcesContent":["import {\n ChatModel,\n type ChatModelInput,\n type ChatModelInputMessageContent,\n type ChatModelInputOptions,\n type ChatModelOptions,\n type ChatModelOutput,\n type ChatModelOutputToolCall,\n type ChatModelOutputUsage,\n type FileUnionContent,\n type ModelInvokeOptions,\n type ModelProcessAsyncGenerator,\n type ModelProcessResult,\n modelProcessResultToObject,\n StructuredOutputError,\n safeParseJSON,\n} from \"@aigne/model-base\";\nimport { logger } from \"@aigne/model-base/utils/logger\";\nimport { mergeUsage } from \"@aigne/model-base/utils/model-utils\";\nimport { nodejs } from \"@aigne/model-base/utils/nodejs\";\nimport {\n isNil,\n isNonNullable,\n isRecord,\n type PromiseOrValue,\n} from \"@aigne/model-base/utils/type-utils\";\nimport { v7 } from \"@aigne/uuid\";\nimport {\n type Content,\n type ContentUnion,\n createPartFromUri,\n createUserContent,\n type FunctionCallingConfig,\n FunctionCallingConfigMode,\n type FunctionResponse,\n type GenerateContentConfig,\n type GenerateContentParameters,\n GoogleGenAI,\n type GoogleGenAIOptions,\n type Part,\n ThinkingLevel,\n type ToolListUnion,\n} from \"@google/genai\";\nimport { parse } from \"yaml\";\nimport { z } from \"zod\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\n\nconst GEMINI_DEFAULT_CHAT_MODEL = \"gemini-2.0-flash\";\n\nconst OUTPUT_FUNCTION_NAME = \"output\";\nconst NEED_UPLOAD_MAX_FILE_SIZE_MB = 20;\n\nexport interface GeminiChatModelOptions extends ChatModelOptions {\n /**\n * API key for Gemini API\n *\n * If not provided, will look for GEMINI_API_KEY or GOOGLE_API_KEY in environment variables\n */\n apiKey?: string;\n\n /**\n * Optional client options for the Gemini SDK\n */\n clientOptions?: Partial<GoogleGenAIOptions>;\n}\n\n/**\n * Implementation of the ChatModel interface for Google's Gemini API\n *\n * @example\n * Here's how to create and use a Gemini chat model:\n * {@includeCode ../test/gemini-chat-model.test.ts#example-gemini-chat-model}\n *\n * @example\n * Here's an example with streaming response:\n * {@includeCode ../test/gemini-chat-model.test.ts#example-gemini-chat-model-streaming}\n */\nexport class GeminiChatModel extends ChatModel {\n constructor(public override options?: GeminiChatModelOptions) {\n super({\n ...options,\n model: options?.model || GEMINI_DEFAULT_CHAT_MODEL,\n });\n }\n\n protected apiKeyEnvName = \"GEMINI_API_KEY\";\n\n protected _googleClient?: GoogleGenAI;\n\n get googleClient() {\n if (this._googleClient) return this._googleClient;\n\n const { apiKey } = this.credential;\n\n if (!apiKey)\n throw new Error(\n `${this.name} requires an API key. Please provide it via \\`options.apiKey\\`, or set the \\`${this.apiKeyEnvName}\\` environment variable`,\n );\n\n this._googleClient ??= new GoogleGenAI({\n apiKey,\n ...this.options?.clientOptions,\n });\n\n return this._googleClient;\n }\n\n override get credential() {\n const apiKey =\n this.options?.apiKey ||\n process.env[this.apiKeyEnvName] ||\n process.env.GEMINI_API_KEY ||\n process.env.GOOGLE_API_KEY;\n\n return {\n apiKey,\n model: this.options?.model || GEMINI_DEFAULT_CHAT_MODEL,\n };\n }\n\n get modelOptions() {\n return this.options?.modelOptions;\n }\n\n override async countTokens(input: ChatModelInput): Promise<number> {\n const { model, ...request } = await this.getParameters(input);\n\n const contents: Content[] = [];\n\n const { systemInstruction, tools } = request.config ?? {};\n\n if (systemInstruction) contents.push(this.contentUnionToContent(systemInstruction));\n if (tools?.length) contents.push({ role: \"system\", parts: [{ text: JSON.stringify(tools) }] });\n\n contents.push(...[request.contents].flat().map(this.contentUnionToContent));\n\n const tokens = (\n await this.googleClient.models.countTokens({\n model,\n contents,\n })\n ).totalTokens;\n\n if (!isNil(tokens)) return tokens;\n\n return super.countTokens(input);\n }\n\n private contentUnionToContent(content: ContentUnion): Content {\n if (typeof content === \"object\" && \"parts\" in content) {\n return { role: \"system\", parts: content.parts };\n } else if (typeof content === \"string\") {\n return { role: \"system\", parts: [{ text: content }] };\n } else if (Array.isArray(content)) {\n return {\n role: \"system\",\n parts: content.map((i) => (typeof i === \"string\" ? { text: i } : i)),\n };\n } else {\n return { role: \"system\", parts: [content as Part] };\n }\n }\n\n override process(\n input: ChatModelInput,\n options: ModelInvokeOptions,\n ): PromiseOrValue<ModelProcessResult<ChatModelOutput>> {\n return this.processInput(input, options);\n }\n\n // References: https://ai.google.dev/gemini-api/docs/thinking#set-budget\n protected thinkingBudgetModelMap = [\n // 注意:gemini-2.5-flash-image-preview 模型并不支持 thinking。see: https://github.com/CherryHQ/cherry-studio/issues/9614\n {\n pattern: /gemini-2.5-flash-image-preview/,\n support: false,\n },\n {\n pattern: /gemini-3(?!.*-image-)/,\n support: true,\n type: \"level\",\n },\n {\n pattern: /gemini-2.5-pro/,\n support: true,\n min: 128,\n max: 32768,\n },\n {\n pattern: /gemini-2.5-flash/,\n support: true,\n min: 0,\n max: 24576,\n },\n {\n pattern: /2.5-flash-lite/,\n support: true,\n min: 512,\n max: 24576,\n },\n {\n pattern: /.*/,\n support: false,\n },\n ];\n\n protected thinkingBudgetLevelMap = {\n high: 100000, // use 100k for high, finally capped by model max\n medium: 10000,\n low: 5000,\n minimal: 200,\n };\n\n protected thinkingLevelMap = {\n high: ThinkingLevel.HIGH,\n medium: ThinkingLevel.HIGH,\n low: ThinkingLevel.LOW,\n minimal: ThinkingLevel.LOW,\n };\n\n protected getThinkingBudget(\n model: string,\n effort: ChatModelInputOptions[\"reasoningEffort\"],\n ): { support: boolean; budget?: number; level?: ThinkingLevel } {\n const m = this.thinkingBudgetModelMap.find((i) => i.pattern.test(model));\n\n if (!m?.support) return { support: false };\n\n if (m.type === \"level\") {\n let level = ThinkingLevel.THINKING_LEVEL_UNSPECIFIED;\n\n if (typeof effort === \"string\") {\n level = this.thinkingLevelMap[effort];\n } else if (typeof effort === \"number\") {\n level =\n effort >= this.thinkingBudgetLevelMap[\"medium\"] ? ThinkingLevel.HIGH : ThinkingLevel.LOW;\n }\n\n return { support: true, level };\n }\n\n let budget =\n typeof effort === \"string\" ? this.thinkingBudgetLevelMap[effort] || undefined : effort;\n if (typeof budget === \"undefined\") return { support: true };\n\n if (typeof m.min === \"number\") budget = Math.max(m.min, budget);\n if (typeof m.max === \"number\") budget = Math.min(m.max, budget);\n\n return { support: true, budget };\n }\n\n private async getParameters(input: ChatModelInput): Promise<GenerateContentParameters> {\n const { modelOptions = {} } = input;\n\n const model = modelOptions.model || this.credential.model;\n const { contents, config } = await this.buildContents(input);\n\n const thinkingBudget = this.getThinkingBudget(model, modelOptions.reasoningEffort);\n\n const parameters: GenerateContentParameters = {\n model,\n contents,\n config: {\n thinkingConfig: thinkingBudget.support\n ? {\n includeThoughts: true,\n thinkingBudget: thinkingBudget.budget,\n thinkingLevel: thinkingBudget.level,\n }\n : undefined,\n responseModalities: modelOptions.modalities,\n temperature: modelOptions.temperature,\n topP: modelOptions.topP,\n frequencyPenalty: modelOptions.frequencyPenalty,\n presencePenalty: modelOptions.presencePenalty,\n ...config,\n ...(await this.buildConfig(input)),\n },\n };\n\n return parameters;\n }\n\n private async *processInput(\n input: ChatModelInput,\n options: ModelInvokeOptions,\n ): ModelProcessAsyncGenerator<ChatModelOutput> {\n const parameters = await this.getParameters(input);\n\n const response = await this.googleClient.models.generateContentStream(parameters);\n\n let usage: ChatModelOutputUsage = {\n inputTokens: 0,\n outputTokens: 0,\n };\n let responseModel: string | undefined;\n\n const files: FileUnionContent[] = [];\n const toolCalls: ChatModelOutputToolCall[] = [];\n let text = \"\";\n let json: any;\n\n for await (const chunk of response) {\n if (!responseModel && chunk.modelVersion) {\n responseModel = chunk.modelVersion;\n yield { delta: { json: { model: responseModel } } };\n }\n\n for (const { content } of chunk.candidates ?? []) {\n if (content?.parts) {\n for (const part of content.parts) {\n if (part.text) {\n if (part.thought) {\n yield { delta: { text: { thoughts: part.text } } };\n } else {\n text += part.text;\n if (input.responseFormat?.type !== \"json_schema\") {\n yield { delta: { text: { text: part.text } } };\n }\n }\n }\n if (part.inlineData?.data) {\n files.push({\n type: \"file\",\n data: part.inlineData.data,\n filename: part.inlineData.displayName,\n mimeType: part.inlineData.mimeType,\n });\n }\n\n if (part.functionCall?.name) {\n if (part.functionCall.name === OUTPUT_FUNCTION_NAME) {\n json = part.functionCall.args;\n } else {\n const toolCall: ChatModelOutputToolCall = {\n id: part.functionCall.id || v7(),\n type: \"function\",\n function: {\n name: part.functionCall.name,\n arguments: part.functionCall.args || {},\n },\n };\n\n // Preserve thought_signature for 3.x models\n if (part.thoughtSignature && parameters.model.includes(\"gemini-3\")) {\n toolCall.metadata = {\n thoughtSignature: part.thoughtSignature,\n };\n }\n\n toolCalls.push(toolCall);\n }\n }\n }\n }\n }\n\n if (chunk.usageMetadata) {\n if (chunk.usageMetadata.promptTokenCount)\n usage.inputTokens = chunk.usageMetadata.promptTokenCount;\n if (chunk.usageMetadata.candidatesTokenCount || chunk.usageMetadata.thoughtsTokenCount)\n usage.outputTokens =\n (chunk.usageMetadata.candidatesTokenCount || 0) +\n (chunk.usageMetadata.thoughtsTokenCount || 0);\n // Parse cache statistics if available\n if (chunk.usageMetadata.cachedContentTokenCount) {\n usage.cacheReadInputTokens = chunk.usageMetadata.cachedContentTokenCount;\n }\n }\n }\n\n if (toolCalls.length) {\n yield { delta: { json: { toolCalls } } };\n }\n if (input.responseFormat?.type === \"json_schema\") {\n if (json) {\n yield { delta: { json: { json } } };\n } else if (text) {\n yield { delta: { json: { json: safeParseJSON(text) } } };\n } else if (!toolCalls.length) {\n throw new StructuredOutputError(\"No JSON response from the model\");\n }\n } else if (!toolCalls.length) {\n // NOTE: gemini-2.5-pro sometimes returns an empty response,\n // so we check here and retry with structured output mode (empty responses occur less frequently with tool calls)\n if (!text && !files.length) {\n logger.warn(\"Empty response from Gemini, retrying with structured output mode\");\n\n try {\n const outputSchema = z.object({\n output: z.string().describe(\"The final answer from the model\"),\n });\n\n const response = await this.process(\n {\n ...input,\n responseFormat: {\n type: \"json_schema\",\n jsonSchema: {\n name: \"output\",\n schema: zodToJsonSchema(outputSchema),\n },\n },\n },\n options,\n );\n\n const result = await modelProcessResultToObject(response);\n\n // Merge retry usage with the original usage\n usage = mergeUsage(usage, result.usage);\n\n // Return the tool calls if retry has tool calls\n if (result.toolCalls?.length) {\n toolCalls.push(...result.toolCalls);\n yield { delta: { json: { toolCalls } } };\n }\n // Return the text from structured output of retry\n else {\n if (!result.json)\n throw new Error(\"Retrying with structured output mode got no json response\");\n\n const parsed = outputSchema.safeParse(result.json);\n\n if (!parsed.success)\n throw new Error(\"Retrying with structured output mode got invalid json response\");\n\n text = parsed.data.output;\n yield { delta: { text: { text } } };\n\n logger.warn(\n \"Empty response from Gemini, retried with structured output mode successfully\",\n );\n }\n } catch (error) {\n logger.error(\n \"Empty response from Gemini, retrying with structured output mode failed\",\n error,\n );\n throw new StructuredOutputError(\"No response from the model\");\n }\n }\n }\n\n yield {\n delta: {\n json: {\n usage,\n files: files.length ? files : undefined,\n modelOptions: {\n reasoningEffort:\n parameters.config?.thinkingConfig?.thinkingLevel ||\n parameters.config?.thinkingConfig?.thinkingBudget,\n },\n },\n },\n };\n }\n\n private async buildConfig(input: ChatModelInput): Promise<GenerateContentParameters[\"config\"]> {\n const config: GenerateContentParameters[\"config\"] = {};\n\n const { tools, toolConfig } = await this.buildTools(input);\n\n config.tools = tools;\n config.toolConfig = toolConfig;\n\n if (input.responseFormat?.type === \"json_schema\") {\n if (config.tools?.length) {\n config.tools.push({\n functionDeclarations: [\n {\n name: OUTPUT_FUNCTION_NAME,\n description: \"Output the final response\",\n parametersJsonSchema: input.responseFormat.jsonSchema.schema,\n },\n ],\n });\n\n config.toolConfig = {\n ...config.toolConfig,\n functionCallingConfig: { mode: FunctionCallingConfigMode.ANY },\n };\n } else {\n config.responseJsonSchema = input.responseFormat.jsonSchema.schema;\n config.responseMimeType = \"application/json\";\n }\n }\n\n return config;\n }\n\n private async buildTools(\n input: ChatModelInput,\n ): Promise<Pick<GenerateContentConfig, \"tools\" | \"toolConfig\">> {\n const tools: ToolListUnion = [];\n\n for (const tool of input.tools ?? []) {\n tools.push({\n functionDeclarations: [\n {\n name: tool.function.name,\n description: tool.function.description,\n parametersJsonSchema: tool.function.parameters,\n },\n ],\n });\n }\n\n const functionCallingConfig: FunctionCallingConfig | undefined = !input.toolChoice\n ? undefined\n : input.toolChoice === \"auto\"\n ? { mode: FunctionCallingConfigMode.AUTO }\n : input.toolChoice === \"none\"\n ? { mode: FunctionCallingConfigMode.NONE }\n : input.toolChoice === \"required\"\n ? { mode: FunctionCallingConfigMode.ANY }\n : {\n mode: FunctionCallingConfigMode.ANY,\n allowedFunctionNames: [input.toolChoice.function.name],\n };\n\n return { tools, toolConfig: { functionCallingConfig } };\n }\n\n private async buildVideoContentParts(media: FileUnionContent): Promise<Part | undefined> {\n const { path: filePath, mimeType: fileMimeType } = await this.transformFileType(\"local\", media);\n\n if (filePath) {\n const stats = await nodejs.fs.stat(filePath);\n const fileSizeInBytes = stats.size;\n const fileSizeMB = fileSizeInBytes / (1024 * 1024);\n\n if (fileSizeMB > NEED_UPLOAD_MAX_FILE_SIZE_MB) {\n const uploadedFile = await this.googleClient.files.upload({\n file: filePath,\n config: { mimeType: fileMimeType },\n });\n\n let file = uploadedFile;\n while (file.state === \"PROCESSING\") {\n await new Promise((resolve) => setTimeout(resolve, 1000));\n\n if (file.name) {\n file = await this.googleClient.files.get({ name: file.name });\n }\n }\n\n if (file.state !== \"ACTIVE\") {\n throw new Error(`File ${file.name} failed to process: ${file.state}`);\n }\n\n if (file.uri && file.mimeType) {\n const result = createUserContent([createPartFromUri(file.uri, file.mimeType), \"\"]);\n const part = result.parts?.find((x) => x.fileData);\n\n if (part) {\n await nodejs.fs.rm(filePath);\n return part;\n }\n }\n }\n }\n }\n\n private async buildContents(\n input: ChatModelInput,\n ): Promise<Omit<GenerateContentParameters, \"model\">> {\n const result: Omit<GenerateContentParameters, \"model\"> = {\n contents: [],\n };\n\n const systemParts: Part[] = [];\n\n result.contents = (\n await Promise.all(\n input.messages.map(async (msg) => {\n if (msg.role === \"system\") {\n if (typeof msg.content === \"string\") {\n systemParts.push({ text: msg.content });\n } else if (Array.isArray(msg.content)) {\n systemParts.push(\n ...msg.content.map<Part>((item) => {\n if (item.type === \"text\") return { text: item.text };\n throw new Error(`Unsupported content type: ${item.type}`);\n }),\n );\n }\n\n return;\n }\n\n const content: Content = {\n role: msg.role === \"agent\" ? \"model\" : msg.role === \"user\" ? \"user\" : undefined,\n };\n\n if (msg.toolCalls) {\n content.parts = msg.toolCalls.map((call) => {\n const part: Part = {\n functionCall: {\n id: call.id,\n name: call.function.name,\n args: call.function.arguments,\n },\n };\n\n // Restore thought_signature for 3.x models\n if (call.metadata?.thoughtSignature) {\n part.thoughtSignature = call.metadata.thoughtSignature;\n }\n\n return part;\n });\n } else if (msg.toolCallId) {\n const call = input.messages\n .flatMap((i) => i.toolCalls)\n .find((c) => c?.id === msg.toolCallId);\n if (!call) throw new Error(`Tool call not found: ${msg.toolCallId}`);\n if (!msg.content) throw new Error(\"Tool call must have content\");\n\n // parse tool result as a record\n let toolResult: Record<string, unknown> | undefined;\n {\n let text: string | undefined;\n if (typeof msg.content === \"string\") text = msg.content;\n else if (msg.content?.length === 1) {\n const first = msg.content[0];\n if (first?.type === \"text\") text = first.text;\n }\n\n if (text) {\n try {\n const obj = parse(text);\n if (isRecord(obj)) toolResult = obj;\n } catch {\n // ignore\n }\n if (!toolResult) toolResult = { result: text };\n }\n }\n\n const functionResponse: FunctionResponse = {\n id: msg.toolCallId,\n name: call.function.name,\n };\n\n if (toolResult) {\n functionResponse.response = toolResult;\n } else {\n functionResponse.parts = await this.contentToParts(msg.content);\n }\n\n content.parts = [{ functionResponse }];\n } else if (msg.content) {\n content.parts = await this.contentToParts(msg.content);\n }\n\n return content;\n }),\n )\n ).filter(isNonNullable);\n\n this.ensureMessagesHasUserMessage(systemParts, result.contents);\n\n if (systemParts.length) {\n result.config ??= {};\n result.config.systemInstruction = systemParts;\n }\n\n return result;\n }\n\n private async contentToParts(content: ChatModelInputMessageContent): Promise<Part[]> {\n if (typeof content === \"string\") return [{ text: content }];\n\n return Promise.all(\n content.map<Promise<Part>>(async (item) => {\n switch (item.type) {\n case \"text\":\n return { text: item.text };\n case \"url\":\n return { fileData: { fileUri: item.url, mimeType: item.mimeType } };\n case \"file\": {\n const part = await this.buildVideoContentParts(item);\n if (part) return part;\n\n return { inlineData: { data: item.data, mimeType: item.mimeType } };\n }\n case \"local\":\n throw new Error(\n `Unsupported local file: ${item.path}, it should be converted to base64 at ChatModel`,\n );\n }\n }),\n );\n }\n\n private ensureMessagesHasUserMessage(systems: Part[], contents: Content[]) {\n // no messages but system messages\n if (!contents.length && systems.length) {\n const system = systems.pop();\n if (system) contents.push({ role: \"user\", parts: [system] });\n }\n\n // first message is from model\n if (contents[0]?.role === \"model\") {\n const system = systems.pop();\n if (system) contents.unshift({ role: \"user\", parts: [system] });\n }\n }\n}\n"],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- let _aigne_core = require("@aigne/core");
2
- let _aigne_core_utils_type_utils = require("@aigne/core/utils/type-utils");
1
+ let _aigne_model_base = require("@aigne/model-base");
2
+ let _aigne_model_base_utils_type_utils = require("@aigne/model-base/utils/type-utils");
3
3
  let _google_genai = require("@google/genai");
4
4
  let zod = require("zod");
5
5
 
6
6
  //#region src/gemini-image-model.ts
7
7
  const DEFAULT_MODEL = "imagen-4.0-generate-001";
8
- const geminiImageModelInputSchema = _aigne_core.imageModelInputSchema.extend({});
8
+ const geminiImageModelInputSchema = _aigne_model_base.imageModelInputSchema.extend({});
9
9
  const geminiImageModelOptionsSchema = zod.z.object({
10
10
  apiKey: zod.z.string().optional(),
11
11
  baseURL: zod.z.string().optional(),
@@ -13,7 +13,7 @@ const geminiImageModelOptionsSchema = zod.z.object({
13
13
  modelOptions: zod.z.object({}).optional(),
14
14
  clientOptions: zod.z.object({}).optional()
15
15
  });
16
- var GeminiImageModel = class extends _aigne_core.ImageModel {
16
+ var GeminiImageModel = class extends _aigne_model_base.ImageModel {
17
17
  constructor(options) {
18
18
  super({
19
19
  ...options,
@@ -21,7 +21,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
21
21
  description: options?.description ?? "Draw or edit image by Gemini image models"
22
22
  });
23
23
  this.options = options;
24
- if (options) (0, _aigne_core_utils_type_utils.checkArguments)(this.name, geminiImageModelOptionsSchema, options);
24
+ if (options) (0, _aigne_model_base_utils_type_utils.checkArguments)(this.name, geminiImageModelOptionsSchema, options);
25
25
  }
26
26
  _client;
27
27
  apiKeyEnvName = "GEMINI_API_KEY";
@@ -66,7 +66,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
66
66
  prompt: mergedInput.prompt,
67
67
  config: {
68
68
  numberOfImages: mergedInput.n || 1,
69
- ...(0, _aigne_core_utils_type_utils.pick)(mergedInput, [
69
+ ...(0, _aigne_model_base_utils_type_utils.pick)(mergedInput, [
70
70
  "seed",
71
71
  "safetyFilterLevel",
72
72
  "personGeneration",
@@ -87,7 +87,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
87
87
  type: "file",
88
88
  data: image.imageBytes,
89
89
  mimeType: image.mimeType
90
- } : void 0).filter(_aigne_core_utils_type_utils.isNonNullable) || [],
90
+ } : void 0).filter(_aigne_model_base_utils_type_utils.isNonNullable) || [],
91
91
  usage: {
92
92
  inputTokens: 0,
93
93
  outputTokens: 0
@@ -133,7 +133,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
133
133
  "topP",
134
134
  "imageConfig"
135
135
  ];
136
- const images = await Promise.all((0, _aigne_core_utils_type_utils.flat)(input.image).map(async (image) => {
136
+ const images = await Promise.all((0, _aigne_model_base_utils_type_utils.flat)(input.image).map(async (image) => {
137
137
  const { data, mimeType } = await this.transformFileType("file", image);
138
138
  return { inlineData: {
139
139
  data,
@@ -146,7 +146,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
146
146
  config: {
147
147
  responseModalities: [_google_genai.Modality.TEXT, _google_genai.Modality.IMAGE],
148
148
  candidateCount: input.n || 1,
149
- ...(0, _aigne_core_utils_type_utils.pick)(mergedInput, inputKeys)
149
+ ...(0, _aigne_model_base_utils_type_utils.pick)(mergedInput, inputKeys)
150
150
  }
151
151
  });
152
152
  return {
@@ -155,7 +155,7 @@ var GeminiImageModel = class extends _aigne_core.ImageModel {
155
155
  data: part.inlineData.data,
156
156
  filename: part.inlineData.displayName,
157
157
  mimeType: part.inlineData.mimeType
158
- } : null).filter(_aigne_core_utils_type_utils.isNonNullable),
158
+ } : null).filter(_aigne_model_base_utils_type_utils.isNonNullable),
159
159
  usage: {
160
160
  inputTokens: response.usageMetadata?.promptTokenCount || 0,
161
161
  outputTokens: response.usageMetadata?.candidatesTokenCount || 0
@@ -1,4 +1,4 @@
1
- import { AgentInvokeOptions, ImageModel, ImageModelInput, ImageModelOptions, ImageModelOutput } from "@aigne/core";
1
+ import { ImageModel, ImageModelInput, ImageModelOptions, ImageModelOutput, ModelInvokeOptions } from "@aigne/model-base";
2
2
  import { GenerateContentConfig, GenerateImagesConfig, GoogleGenAI } from "@google/genai";
3
3
 
4
4
  //#region src/gemini-image-model.d.ts
@@ -24,11 +24,11 @@ declare class GeminiImageModel extends ImageModel<GeminiImageModelInput, GeminiI
24
24
  };
25
25
  get modelOptions(): Omit<Partial<GeminiImageModelInput>, "model"> | undefined;
26
26
  /**
27
- * Process the input and generate a response
28
- * @param input The input to process
29
- * @returns The generated response
30
- */
31
- process(input: GeminiImageModelInput, _options: AgentInvokeOptions): Promise<ImageModelOutput>;
27
+ * Process the input and generate a response
28
+ * @param input The input to process
29
+ * @returns The generated response
30
+ */
31
+ process(input: GeminiImageModelInput, _options: ModelInvokeOptions): Promise<ImageModelOutput>;
32
32
  private generateImageByImagenModel;
33
33
  private generateImageByGeminiModel;
34
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-image-model.d.cts","names":[],"sources":["../src/gemini-image-model.ts"],"mappings":";;;;UAqBiB,qBAAA,SACP,eAAA,EACN,oBAAA,EACA,qBAAA;AAAA,UACa,sBAAA,SAA+B,gBAAA;AAAA,UAE/B,uBAAA,SACP,iBAAA,CAAkB,qBAAA,EAAuB,sBAAA;EAAA,MAAA;EAAA,OAAA;EAAA,KAAA;EAAA,YAAA,GAIlC,IAAA,CAAK,OAAA,CAAQ,qBAAA;EAAA,aAAA,GACZ,MAAA;AAAA;AAAA,cAaL,gBAAA,SAAyB,UAAA,CAAW,qBAAA,EAAuB,sBAAA;EAAA,OAAA,GAChC,uBAAA;EAAA,YAAA,OAAA,GAAA,uBAAA;EAAA,UAAA,OAAA,GASlB,WAAA;EAAA,UAAA,aAAA;EAAA,IAAA,OAAA,GAIV,WAAA;EAAA,IAAA,WAAA;IAAA,GAAA;IAAA,MAAA;IAAA,KAAA;EAAA;EAAA,IAAA,aAAA,GAuBM,IAAA,CAAA,OAAA,CAAA,qBAAA;EAAA;;;;;EAAA,QAAA,KAAA,EAUP,qBAAA,EAAA,QAAA,EACG,kBAAA,GACT,OAAA,CAAQ,gBAAA;EAAA,QAAA,0BAAA;EAAA,QAAA,0BAAA;AAAA"}
1
+ {"version":3,"file":"gemini-image-model.d.cts","names":[],"sources":["../src/gemini-image-model.ts"],"mappings":";;;;UAqBiB,qBAAA,SACP,eAAA,EACN,oBAAA,EACA,qBAAA;AAAA,UACa,sBAAA,SAA+B,gBAAA;AAAA,UAE/B,uBAAA,SACP,iBAAA,CAAkB,qBAAA,EAAuB,sBAAA;EACjD,MAAA;EACA,OAAA;EACA,KAAA;EACA,YAAA,GAAe,IAAA,CAAK,OAAA,CAAQ,qBAAA;EAC5B,aAAA,GAAgB,MAAA;AAAA;AAAA,cAaL,gBAAA,SAAyB,UAAA,CAAW,qBAAA,EAAuB,sBAAA;EAC1C,OAAA,GAAU,uBAAA;cAAV,OAAA,GAAU,uBAAA;EAAA,UAS5B,OAAA,GAAU,WAAA;EAAA,UAEV,aAAA;EAAA,IAEN,MAAA,CAAA,GAAM,WAAA;EAAA,IAeG,UAAA,CAAA;;;;;MAQT,YAAA,CAAA,GAAY,IAAA,CAAA,OAAA,CAAA,qBAAA;EAvDU;;;;;EAgEX,OAAA,CACb,KAAA,EAAO,qBAAA,EACP,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,gBAAA;EAAA,QAcG,0BAAA;EAAA,QA+CA,0BAAA;AAAA"}
@@ -1,4 +1,4 @@
1
- import { AgentInvokeOptions, ImageModel, ImageModelInput, ImageModelOptions, ImageModelOutput } from "@aigne/core";
1
+ import { ImageModel, ImageModelInput, ImageModelOptions, ImageModelOutput, ModelInvokeOptions } from "@aigne/model-base";
2
2
  import { GenerateContentConfig, GenerateImagesConfig, GoogleGenAI } from "@google/genai";
3
3
 
4
4
  //#region src/gemini-image-model.d.ts
@@ -24,11 +24,11 @@ declare class GeminiImageModel extends ImageModel<GeminiImageModelInput, GeminiI
24
24
  };
25
25
  get modelOptions(): Omit<Partial<GeminiImageModelInput>, "model"> | undefined;
26
26
  /**
27
- * Process the input and generate a response
28
- * @param input The input to process
29
- * @returns The generated response
30
- */
31
- process(input: GeminiImageModelInput, _options: AgentInvokeOptions): Promise<ImageModelOutput>;
27
+ * Process the input and generate a response
28
+ * @param input The input to process
29
+ * @returns The generated response
30
+ */
31
+ process(input: GeminiImageModelInput, _options: ModelInvokeOptions): Promise<ImageModelOutput>;
32
32
  private generateImageByImagenModel;
33
33
  private generateImageByGeminiModel;
34
34
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gemini-image-model.d.mts","names":[],"sources":["../src/gemini-image-model.ts"],"mappings":";;;;UAqBiB,qBAAA,SACP,eAAA,EACN,oBAAA,EACA,qBAAA;AAAA,UACa,sBAAA,SAA+B,gBAAA;AAAA,UAE/B,uBAAA,SACP,iBAAA,CAAkB,qBAAA,EAAuB,sBAAA;EAAA,MAAA;EAAA,OAAA;EAAA,KAAA;EAAA,YAAA,GAIlC,IAAA,CAAK,OAAA,CAAQ,qBAAA;EAAA,aAAA,GACZ,MAAA;AAAA;AAAA,cAaL,gBAAA,SAAyB,UAAA,CAAW,qBAAA,EAAuB,sBAAA;EAAA,OAAA,GAChC,uBAAA;EAAA,YAAA,OAAA,GAAA,uBAAA;EAAA,UAAA,OAAA,GASlB,WAAA;EAAA,UAAA,aAAA;EAAA,IAAA,OAAA,GAIV,WAAA;EAAA,IAAA,WAAA;IAAA,GAAA;IAAA,MAAA;IAAA,KAAA;EAAA;EAAA,IAAA,aAAA,GAuBM,IAAA,CAAA,OAAA,CAAA,qBAAA;EAAA;;;;;EAAA,QAAA,KAAA,EAUP,qBAAA,EAAA,QAAA,EACG,kBAAA,GACT,OAAA,CAAQ,gBAAA;EAAA,QAAA,0BAAA;EAAA,QAAA,0BAAA;AAAA"}
1
+ {"version":3,"file":"gemini-image-model.d.mts","names":[],"sources":["../src/gemini-image-model.ts"],"mappings":";;;;UAqBiB,qBAAA,SACP,eAAA,EACN,oBAAA,EACA,qBAAA;AAAA,UACa,sBAAA,SAA+B,gBAAA;AAAA,UAE/B,uBAAA,SACP,iBAAA,CAAkB,qBAAA,EAAuB,sBAAA;EACjD,MAAA;EACA,OAAA;EACA,KAAA;EACA,YAAA,GAAe,IAAA,CAAK,OAAA,CAAQ,qBAAA;EAC5B,aAAA,GAAgB,MAAA;AAAA;AAAA,cAaL,gBAAA,SAAyB,UAAA,CAAW,qBAAA,EAAuB,sBAAA;EAC1C,OAAA,GAAU,uBAAA;cAAV,OAAA,GAAU,uBAAA;EAAA,UAS5B,OAAA,GAAU,WAAA;EAAA,UAEV,aAAA;EAAA,IAEN,MAAA,CAAA,GAAM,WAAA;EAAA,IAeG,UAAA,CAAA;;;;;MAQT,YAAA,CAAA,GAAY,IAAA,CAAA,OAAA,CAAA,qBAAA;EAvDU;;;;;EAgEX,OAAA,CACb,KAAA,EAAO,qBAAA,EACP,QAAA,EAAU,kBAAA,GACT,OAAA,CAAQ,gBAAA;EAAA,QAcG,0BAAA;EAAA,QA+CA,0BAAA;AAAA"}