koishi-plugin-chatluna-google-gemini-adapter 1.2.20 → 1.2.22

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/lib/index.cjs CHANGED
@@ -65,97 +65,28 @@ var import_stream = require("koishi-plugin-chatluna/utils/stream");
65
65
  // src/utils.ts
66
66
  var import_messages = require("@langchain/core/messages");
67
67
  var import_zod_to_json_schema = require("zod-to-json-schema");
68
- async function langchainMessageToGeminiMessage(messages, model) {
69
- const mappedMessages = await Promise.all(
70
- messages.map(async (rawMessage) => {
71
- const role = messageTypeToGeminiRole(rawMessage.getType());
72
- if (role === "function" || rawMessage.additional_kwargs?.function_call != null) {
73
- return {
74
- role: "function",
75
- parts: [
76
- {
77
- functionResponse: rawMessage.additional_kwargs?.function_call != null ? void 0 : {
78
- name: rawMessage.name,
79
- response: {
80
- name: rawMessage.name,
81
- content: (() => {
82
- try {
83
- const result2 = JSON.parse(
84
- rawMessage.content
85
- );
86
- if (typeof result2 === "string") {
87
- return {
88
- response: result2
89
- };
90
- } else {
91
- return result2;
92
- }
93
- } catch (e) {
94
- return {
95
- response: rawMessage.content
96
- };
97
- }
98
- })()
99
- }
100
- },
101
- functionCall: rawMessage.additional_kwargs?.function_call != null ? {
102
- name: rawMessage.additional_kwargs.function_call.name,
103
- args: (() => {
104
- try {
105
- const result2 = JSON.parse(
106
- rawMessage.additional_kwargs.function_call.arguments
107
- );
108
- if (typeof result2 === "string") {
109
- return {
110
- input: result2
111
- };
112
- } else {
113
- return result2;
114
- }
115
- } catch (e) {
116
- return {
117
- input: rawMessage.additional_kwargs.function_call.arguments
118
- };
119
- }
120
- })()
121
- } : void 0
122
- }
123
- ]
124
- };
68
+ var import_v1_shared_adapter = require("@chatluna/v1-shared-adapter");
69
+ var import_string = require("koishi-plugin-chatluna/utils/string");
70
+ async function langchainMessageToGeminiMessage(messages, plugin, model) {
71
+ return Promise.all(
72
+ messages.map(async (message) => {
73
+ const role = messageTypeToGeminiRole(message.getType());
74
+ const hasFunctionCall = message.additional_kwargs?.function_call != null;
75
+ if (role === "function" || hasFunctionCall) {
76
+ return processFunctionMessage(message);
125
77
  }
126
- const images = rawMessage.additional_kwargs.images;
127
78
  const result = {
128
79
  role,
129
- parts: [
130
- {
131
- text: rawMessage.content
132
- }
133
- ]
80
+ parts: []
134
81
  };
135
- if ((model.includes("vision") || model.includes("gemini") || model.includes("gemma")) && images != null && !model.includes("gemini-1.0")) {
136
- for (const image of images) {
137
- const mineType = image.split(";")?.[0]?.split(":")?.[1];
138
- const data = image.replace(/^data:image\/\w+;base64,/, "");
139
- result.parts.push({
140
- inline_data: {
141
- // base64 image match type
142
- data,
143
- mime_type: mineType ?? "image/jpeg"
144
- }
145
- });
146
- }
147
- result.parts = result.parts.filter((uncheckedPart) => {
148
- const part = partAsTypeCheck(
149
- uncheckedPart,
150
- (part2) => part2["text"] != null
151
- );
152
- return part == null || part.text.length > 0;
153
- });
82
+ result.parts = typeof message.content === "string" ? [{ text: message.content }] : await processGeminiContentParts(plugin, message.content);
83
+ const images = message.additional_kwargs.images;
84
+ if (images) {
85
+ processImageParts(result, images, model);
154
86
  }
155
87
  return result;
156
88
  })
157
89
  );
158
- return mappedMessages;
159
90
  }
160
91
  __name(langchainMessageToGeminiMessage, "langchainMessageToGeminiMessage");
161
92
  function extractSystemMessages(messages) {
@@ -188,6 +119,105 @@ function extractSystemMessages(messages) {
188
119
  ];
189
120
  }
190
121
  __name(extractSystemMessages, "extractSystemMessages");
122
+ function parseJsonSafely(content) {
123
+ try {
124
+ const result = JSON.parse(content);
125
+ return typeof result === "string" ? { response: result } : result;
126
+ } catch {
127
+ return { response: content };
128
+ }
129
+ }
130
+ __name(parseJsonSafely, "parseJsonSafely");
131
+ function parseJsonArgs(args) {
132
+ try {
133
+ const result = JSON.parse(args);
134
+ return typeof result === "string" ? { input: result } : result;
135
+ } catch {
136
+ return { input: args };
137
+ }
138
+ }
139
+ __name(parseJsonArgs, "parseJsonArgs");
140
+ function processFunctionMessage(message) {
141
+ const hasFunctionCall = message.additional_kwargs?.function_call != null;
142
+ if (hasFunctionCall) {
143
+ const functionCall = message.additional_kwargs.function_call;
144
+ return {
145
+ role: "function",
146
+ parts: [
147
+ {
148
+ functionCall: {
149
+ name: functionCall.name,
150
+ args: parseJsonArgs(functionCall.arguments)
151
+ }
152
+ }
153
+ ]
154
+ };
155
+ }
156
+ return {
157
+ role: "function",
158
+ parts: [
159
+ {
160
+ functionResponse: {
161
+ name: message.name,
162
+ response: {
163
+ name: message.name,
164
+ content: parseJsonSafely(message.content)
165
+ }
166
+ }
167
+ }
168
+ ]
169
+ };
170
+ }
171
+ __name(processFunctionMessage, "processFunctionMessage");
172
+ function processImageParts(result, images, model) {
173
+ if (!((model.includes("vision") || model.includes("gemini") || model.includes("gemma")) && !model.includes("gemini-1.0"))) {
174
+ return;
175
+ }
176
+ for (const image of images) {
177
+ const mineType = image.split(";")?.[0]?.split(":")?.[1] ?? "image/jpeg";
178
+ const data = image.replace(/^data:image\/\w+;base64,/, "");
179
+ result.parts.push({
180
+ inline_data: { data, mime_type: mineType }
181
+ });
182
+ }
183
+ result.parts = result.parts.filter((uncheckedPart) => {
184
+ const part = partAsTypeCheck(
185
+ uncheckedPart,
186
+ (part2) => part2["text"] != null
187
+ );
188
+ return part == null || part.text.length > 0;
189
+ });
190
+ }
191
+ __name(processImageParts, "processImageParts");
192
+ async function processGeminiImageContent(plugin, part) {
193
+ let url;
194
+ try {
195
+ url = await (0, import_v1_shared_adapter.fetchImageUrl)(plugin, part);
196
+ } catch (e) {
197
+ url = typeof part.image_url === "string" ? part.image_url : part.image_url.url;
198
+ logger.warn(`Failed to fetch image url: ${url}`, e);
199
+ }
200
+ const mineType = url.match(/^data:([^;]+);base64,/)?.[1] ?? "image/jpeg";
201
+ const data = url.replace(/^data:image\/\w+;base64,/, "");
202
+ return {
203
+ inline_data: { data, mime_type: mineType }
204
+ };
205
+ }
206
+ __name(processGeminiImageContent, "processGeminiImageContent");
207
+ async function processGeminiContentParts(plugin, content) {
208
+ return Promise.all(
209
+ content.map(async (part) => {
210
+ if ((0, import_string.isMessageContentText)(part)) {
211
+ return { text: part.text };
212
+ }
213
+ if ((0, import_string.isMessageContentImageUrl)(part)) {
214
+ return await processGeminiImageContent(plugin, part);
215
+ }
216
+ return part;
217
+ })
218
+ );
219
+ }
220
+ __name(processGeminiContentParts, "processGeminiContentParts");
191
221
  function partAsType(part) {
192
222
  return part;
193
223
  }
@@ -265,7 +295,7 @@ function formatToolsToGeminiAITools(tools, config, model) {
265
295
  }
266
296
  __name(formatToolsToGeminiAITools, "formatToolsToGeminiAITools");
267
297
  function formatToolToGeminiAITool(tool) {
268
- const parameters = removeAdditionalProperties(
298
+ const parameters = (0, import_v1_shared_adapter.removeAdditionalProperties)(
269
299
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
270
300
  (0, import_zod_to_json_schema.zodToJsonSchema)(tool.schema, {
271
301
  allowedAdditionalProperties: void 0
@@ -279,28 +309,6 @@ function formatToolToGeminiAITool(tool) {
279
309
  };
280
310
  }
281
311
  __name(formatToolToGeminiAITool, "formatToolToGeminiAITool");
282
- function removeAdditionalProperties(schema) {
283
- if (!schema || typeof schema !== "object") return schema;
284
- const stack = [[schema, null]];
285
- while (stack.length > 0) {
286
- const [current] = stack.pop();
287
- if (typeof current !== "object" || current === null) continue;
288
- if (Object.hasOwn(current, "additionalProperties")) {
289
- delete current["additionalProperties"];
290
- }
291
- if (Object.hasOwn(current, "$schema")) {
292
- delete current["$schema"];
293
- }
294
- for (const key of Object.keys(current)) {
295
- const value = current[key];
296
- if (value && typeof value === "object") {
297
- stack.push([value, key]);
298
- }
299
- }
300
- }
301
- return schema;
302
- }
303
- __name(removeAdditionalProperties, "removeAdditionalProperties");
304
312
  function messageTypeToGeminiRole(type) {
305
313
  switch (type) {
306
314
  case "system":
@@ -376,9 +384,10 @@ function createGenerationConfig(params, modelConfig, pluginConfig) {
376
384
  };
377
385
  }
378
386
  __name(createGenerationConfig, "createGenerationConfig");
379
- async function createChatGenerationParams(params, modelConfig, pluginConfig) {
387
+ async function createChatGenerationParams(params, plugin, modelConfig, pluginConfig) {
380
388
  const geminiMessages = await langchainMessageToGeminiMessage(
381
389
  params.input,
390
+ plugin,
382
391
  modelConfig.model
383
392
  );
384
393
  const [systemInstruction, modelMessages] = extractSystemMessages(geminiMessages);
@@ -405,7 +414,7 @@ function isChatResponse(response) {
405
414
  __name(isChatResponse, "isChatResponse");
406
415
 
407
416
  // src/requester.ts
408
- var import_string = require("koishi-plugin-chatluna/utils/string");
417
+ var import_string2 = require("koishi-plugin-chatluna/utils/string");
409
418
  var GeminiRequester = class extends import_api.ModelRequester {
410
419
  constructor(ctx, _configPool, _pluginConfig, _plugin) {
411
420
  super(ctx, _configPool, _pluginConfig, _plugin);
@@ -437,6 +446,7 @@ var GeminiRequester = class extends import_api.ModelRequester {
437
446
  `models/${modelConfig.model}:streamGenerateContent?alt=sse`,
438
447
  await createChatGenerationParams(
439
448
  params,
449
+ this._plugin,
440
450
  modelConfig,
441
451
  this._pluginConfig
442
452
  ),
@@ -458,9 +468,10 @@ var GeminiRequester = class extends import_api.ModelRequester {
458
468
  const modelConfig = prepareModelConfig(params, this._pluginConfig);
459
469
  try {
460
470
  const response = await this._post(
461
- `models/${modelConfig.model}:generateContent?alt=sse`,
471
+ `models/${modelConfig.model}:generateContent`,
462
472
  await createChatGenerationParams(
463
473
  params,
474
+ this._plugin,
464
475
  modelConfig,
465
476
  this._pluginConfig
466
477
  ),
@@ -618,7 +629,10 @@ var GeminiRequester = class extends import_api.ModelRequester {
618
629
  yield chunk.generation;
619
630
  }
620
631
  }
621
- const finalContent = this._handleFinalContent(reasoningContent, groundingContent.value);
632
+ const finalContent = this._handleFinalContent(
633
+ reasoningContent,
634
+ groundingContent.value
635
+ );
622
636
  if (finalContent != null) {
623
637
  yield finalContent;
624
638
  }
@@ -723,7 +737,7 @@ var GeminiRequester = class extends import_api.ModelRequester {
723
737
  );
724
738
  const generationChunk = new import_outputs.ChatGenerationChunk({
725
739
  message: messageChunk,
726
- text: (0, import_string.getMessageContent)(messageChunk.content) ?? ""
740
+ text: (0, import_string2.getMessageContent)(messageChunk.content) ?? ""
727
741
  });
728
742
  yield { type: "generation", generation: generationChunk };
729
743
  }
@@ -906,8 +920,10 @@ var GeminiClient = class extends import_client.PlatformModelAndEmbeddingsClient
906
920
  name: model.name,
907
921
  maxTokens: model.inputTokenLimit,
908
922
  type: model.name.includes("embedding") ? import_types.ModelType.embeddings : import_types.ModelType.llm,
909
- functionCall: !model.name.includes("vision"),
910
- supportMode: ["all"]
923
+ capabilities: [
924
+ import_types.ModelCapabilities.ImageInput,
925
+ import_types.ModelCapabilities.ToolCall
926
+ ]
911
927
  };
912
928
  if (model.name.includes("gemini-2.5") && !model.name.includes("pro") && !model.name.includes("image")) {
913
929
  if (!model.name.includes("-thinking")) {
package/lib/index.mjs CHANGED
@@ -30,6 +30,7 @@ import {
30
30
  ChatLunaEmbeddings
31
31
  } from "koishi-plugin-chatluna/llm-core/platform/model";
32
32
  import {
33
+ ModelCapabilities,
33
34
  ModelType
34
35
  } from "koishi-plugin-chatluna/llm-core/platform/types";
35
36
  import {
@@ -60,97 +61,34 @@ import {
60
61
  SystemMessageChunk
61
62
  } from "@langchain/core/messages";
62
63
  import { zodToJsonSchema } from "zod-to-json-schema";
63
- async function langchainMessageToGeminiMessage(messages, model) {
64
- const mappedMessages = await Promise.all(
65
- messages.map(async (rawMessage) => {
66
- const role = messageTypeToGeminiRole(rawMessage.getType());
67
- if (role === "function" || rawMessage.additional_kwargs?.function_call != null) {
68
- return {
69
- role: "function",
70
- parts: [
71
- {
72
- functionResponse: rawMessage.additional_kwargs?.function_call != null ? void 0 : {
73
- name: rawMessage.name,
74
- response: {
75
- name: rawMessage.name,
76
- content: (() => {
77
- try {
78
- const result2 = JSON.parse(
79
- rawMessage.content
80
- );
81
- if (typeof result2 === "string") {
82
- return {
83
- response: result2
84
- };
85
- } else {
86
- return result2;
87
- }
88
- } catch (e) {
89
- return {
90
- response: rawMessage.content
91
- };
92
- }
93
- })()
94
- }
95
- },
96
- functionCall: rawMessage.additional_kwargs?.function_call != null ? {
97
- name: rawMessage.additional_kwargs.function_call.name,
98
- args: (() => {
99
- try {
100
- const result2 = JSON.parse(
101
- rawMessage.additional_kwargs.function_call.arguments
102
- );
103
- if (typeof result2 === "string") {
104
- return {
105
- input: result2
106
- };
107
- } else {
108
- return result2;
109
- }
110
- } catch (e) {
111
- return {
112
- input: rawMessage.additional_kwargs.function_call.arguments
113
- };
114
- }
115
- })()
116
- } : void 0
117
- }
118
- ]
119
- };
64
+ import {
65
+ fetchImageUrl,
66
+ removeAdditionalProperties
67
+ } from "@chatluna/v1-shared-adapter";
68
+ import {
69
+ isMessageContentImageUrl,
70
+ isMessageContentText
71
+ } from "koishi-plugin-chatluna/utils/string";
72
+ async function langchainMessageToGeminiMessage(messages, plugin, model) {
73
+ return Promise.all(
74
+ messages.map(async (message) => {
75
+ const role = messageTypeToGeminiRole(message.getType());
76
+ const hasFunctionCall = message.additional_kwargs?.function_call != null;
77
+ if (role === "function" || hasFunctionCall) {
78
+ return processFunctionMessage(message);
120
79
  }
121
- const images = rawMessage.additional_kwargs.images;
122
80
  const result = {
123
81
  role,
124
- parts: [
125
- {
126
- text: rawMessage.content
127
- }
128
- ]
82
+ parts: []
129
83
  };
130
- if ((model.includes("vision") || model.includes("gemini") || model.includes("gemma")) && images != null && !model.includes("gemini-1.0")) {
131
- for (const image of images) {
132
- const mineType = image.split(";")?.[0]?.split(":")?.[1];
133
- const data = image.replace(/^data:image\/\w+;base64,/, "");
134
- result.parts.push({
135
- inline_data: {
136
- // base64 image match type
137
- data,
138
- mime_type: mineType ?? "image/jpeg"
139
- }
140
- });
141
- }
142
- result.parts = result.parts.filter((uncheckedPart) => {
143
- const part = partAsTypeCheck(
144
- uncheckedPart,
145
- (part2) => part2["text"] != null
146
- );
147
- return part == null || part.text.length > 0;
148
- });
84
+ result.parts = typeof message.content === "string" ? [{ text: message.content }] : await processGeminiContentParts(plugin, message.content);
85
+ const images = message.additional_kwargs.images;
86
+ if (images) {
87
+ processImageParts(result, images, model);
149
88
  }
150
89
  return result;
151
90
  })
152
91
  );
153
- return mappedMessages;
154
92
  }
155
93
  __name(langchainMessageToGeminiMessage, "langchainMessageToGeminiMessage");
156
94
  function extractSystemMessages(messages) {
@@ -183,6 +121,105 @@ function extractSystemMessages(messages) {
183
121
  ];
184
122
  }
185
123
  __name(extractSystemMessages, "extractSystemMessages");
124
+ function parseJsonSafely(content) {
125
+ try {
126
+ const result = JSON.parse(content);
127
+ return typeof result === "string" ? { response: result } : result;
128
+ } catch {
129
+ return { response: content };
130
+ }
131
+ }
132
+ __name(parseJsonSafely, "parseJsonSafely");
133
+ function parseJsonArgs(args) {
134
+ try {
135
+ const result = JSON.parse(args);
136
+ return typeof result === "string" ? { input: result } : result;
137
+ } catch {
138
+ return { input: args };
139
+ }
140
+ }
141
+ __name(parseJsonArgs, "parseJsonArgs");
142
+ function processFunctionMessage(message) {
143
+ const hasFunctionCall = message.additional_kwargs?.function_call != null;
144
+ if (hasFunctionCall) {
145
+ const functionCall = message.additional_kwargs.function_call;
146
+ return {
147
+ role: "function",
148
+ parts: [
149
+ {
150
+ functionCall: {
151
+ name: functionCall.name,
152
+ args: parseJsonArgs(functionCall.arguments)
153
+ }
154
+ }
155
+ ]
156
+ };
157
+ }
158
+ return {
159
+ role: "function",
160
+ parts: [
161
+ {
162
+ functionResponse: {
163
+ name: message.name,
164
+ response: {
165
+ name: message.name,
166
+ content: parseJsonSafely(message.content)
167
+ }
168
+ }
169
+ }
170
+ ]
171
+ };
172
+ }
173
+ __name(processFunctionMessage, "processFunctionMessage");
174
+ function processImageParts(result, images, model) {
175
+ if (!((model.includes("vision") || model.includes("gemini") || model.includes("gemma")) && !model.includes("gemini-1.0"))) {
176
+ return;
177
+ }
178
+ for (const image of images) {
179
+ const mineType = image.split(";")?.[0]?.split(":")?.[1] ?? "image/jpeg";
180
+ const data = image.replace(/^data:image\/\w+;base64,/, "");
181
+ result.parts.push({
182
+ inline_data: { data, mime_type: mineType }
183
+ });
184
+ }
185
+ result.parts = result.parts.filter((uncheckedPart) => {
186
+ const part = partAsTypeCheck(
187
+ uncheckedPart,
188
+ (part2) => part2["text"] != null
189
+ );
190
+ return part == null || part.text.length > 0;
191
+ });
192
+ }
193
+ __name(processImageParts, "processImageParts");
194
+ async function processGeminiImageContent(plugin, part) {
195
+ let url;
196
+ try {
197
+ url = await fetchImageUrl(plugin, part);
198
+ } catch (e) {
199
+ url = typeof part.image_url === "string" ? part.image_url : part.image_url.url;
200
+ logger.warn(`Failed to fetch image url: ${url}`, e);
201
+ }
202
+ const mineType = url.match(/^data:([^;]+);base64,/)?.[1] ?? "image/jpeg";
203
+ const data = url.replace(/^data:image\/\w+;base64,/, "");
204
+ return {
205
+ inline_data: { data, mime_type: mineType }
206
+ };
207
+ }
208
+ __name(processGeminiImageContent, "processGeminiImageContent");
209
+ async function processGeminiContentParts(plugin, content) {
210
+ return Promise.all(
211
+ content.map(async (part) => {
212
+ if (isMessageContentText(part)) {
213
+ return { text: part.text };
214
+ }
215
+ if (isMessageContentImageUrl(part)) {
216
+ return await processGeminiImageContent(plugin, part);
217
+ }
218
+ return part;
219
+ })
220
+ );
221
+ }
222
+ __name(processGeminiContentParts, "processGeminiContentParts");
186
223
  function partAsType(part) {
187
224
  return part;
188
225
  }
@@ -274,28 +311,6 @@ function formatToolToGeminiAITool(tool) {
274
311
  };
275
312
  }
276
313
  __name(formatToolToGeminiAITool, "formatToolToGeminiAITool");
277
- function removeAdditionalProperties(schema) {
278
- if (!schema || typeof schema !== "object") return schema;
279
- const stack = [[schema, null]];
280
- while (stack.length > 0) {
281
- const [current] = stack.pop();
282
- if (typeof current !== "object" || current === null) continue;
283
- if (Object.hasOwn(current, "additionalProperties")) {
284
- delete current["additionalProperties"];
285
- }
286
- if (Object.hasOwn(current, "$schema")) {
287
- delete current["$schema"];
288
- }
289
- for (const key of Object.keys(current)) {
290
- const value = current[key];
291
- if (value && typeof value === "object") {
292
- stack.push([value, key]);
293
- }
294
- }
295
- }
296
- return schema;
297
- }
298
- __name(removeAdditionalProperties, "removeAdditionalProperties");
299
314
  function messageTypeToGeminiRole(type) {
300
315
  switch (type) {
301
316
  case "system":
@@ -371,9 +386,10 @@ function createGenerationConfig(params, modelConfig, pluginConfig) {
371
386
  };
372
387
  }
373
388
  __name(createGenerationConfig, "createGenerationConfig");
374
- async function createChatGenerationParams(params, modelConfig, pluginConfig) {
389
+ async function createChatGenerationParams(params, plugin, modelConfig, pluginConfig) {
375
390
  const geminiMessages = await langchainMessageToGeminiMessage(
376
391
  params.input,
392
+ plugin,
377
393
  modelConfig.model
378
394
  );
379
395
  const [systemInstruction, modelMessages] = extractSystemMessages(geminiMessages);
@@ -432,6 +448,7 @@ var GeminiRequester = class extends ModelRequester {
432
448
  `models/${modelConfig.model}:streamGenerateContent?alt=sse`,
433
449
  await createChatGenerationParams(
434
450
  params,
451
+ this._plugin,
435
452
  modelConfig,
436
453
  this._pluginConfig
437
454
  ),
@@ -453,9 +470,10 @@ var GeminiRequester = class extends ModelRequester {
453
470
  const modelConfig = prepareModelConfig(params, this._pluginConfig);
454
471
  try {
455
472
  const response = await this._post(
456
- `models/${modelConfig.model}:generateContent?alt=sse`,
473
+ `models/${modelConfig.model}:generateContent`,
457
474
  await createChatGenerationParams(
458
475
  params,
476
+ this._plugin,
459
477
  modelConfig,
460
478
  this._pluginConfig
461
479
  ),
@@ -613,7 +631,10 @@ var GeminiRequester = class extends ModelRequester {
613
631
  yield chunk.generation;
614
632
  }
615
633
  }
616
- const finalContent = this._handleFinalContent(reasoningContent, groundingContent.value);
634
+ const finalContent = this._handleFinalContent(
635
+ reasoningContent,
636
+ groundingContent.value
637
+ );
617
638
  if (finalContent != null) {
618
639
  yield finalContent;
619
640
  }
@@ -901,8 +922,10 @@ var GeminiClient = class extends PlatformModelAndEmbeddingsClient {
901
922
  name: model.name,
902
923
  maxTokens: model.inputTokenLimit,
903
924
  type: model.name.includes("embedding") ? ModelType.embeddings : ModelType.llm,
904
- functionCall: !model.name.includes("vision"),
905
- supportMode: ["all"]
925
+ capabilities: [
926
+ ModelCapabilities.ImageInput,
927
+ ModelCapabilities.ToolCall
928
+ ]
906
929
  };
907
930
  if (model.name.includes("gemini-2.5") && !model.name.includes("pro") && !model.name.includes("image")) {
908
931
  if (!model.name.includes("-thinking")) {
package/lib/utils.d.ts CHANGED
@@ -3,7 +3,8 @@ import { StructuredTool } from '@langchain/core/tools';
3
3
  import { ChatCompletionFunction, ChatCompletionResponseMessage, ChatCompletionResponseMessageRoleEnum, ChatPart, ChatResponse } from './types';
4
4
  import { Config } from '.';
5
5
  import { ModelRequestParams } from 'koishi-plugin-chatluna/llm-core/platform/api';
6
- export declare function langchainMessageToGeminiMessage(messages: BaseMessage[], model?: string): Promise<ChatCompletionResponseMessage[]>;
6
+ import { ChatLunaPlugin } from 'koishi-plugin-chatluna/services/chat';
7
+ export declare function langchainMessageToGeminiMessage(messages: BaseMessage[], plugin: ChatLunaPlugin, model?: string): Promise<ChatCompletionResponseMessage[]>;
7
8
  export declare function extractSystemMessages(messages: ChatCompletionResponseMessage[]): [ChatCompletionResponseMessage, ChatCompletionResponseMessage[]];
8
9
  export declare function partAsType<T extends ChatPart>(part: ChatPart): T;
9
10
  export declare function partAsTypeCheck<T extends ChatPart>(part: ChatPart, check: (part: ChatPart & unknown) => boolean): T | undefined;
@@ -31,7 +32,7 @@ export declare function createGenerationConfig(params: ModelRequestParams, model
31
32
  includeThoughts: boolean;
32
33
  };
33
34
  };
34
- export declare function createChatGenerationParams(params: ModelRequestParams, modelConfig: ReturnType<typeof prepareModelConfig>, pluginConfig: Config): Promise<{
35
+ export declare function createChatGenerationParams(params: ModelRequestParams, plugin: ChatLunaPlugin, modelConfig: ReturnType<typeof prepareModelConfig>, pluginConfig: Config): Promise<{
35
36
  contents: ChatCompletionResponseMessage[];
36
37
  safetySettings: {
37
38
  category: string;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-chatluna-google-gemini-adapter",
3
3
  "description": "google-gemini adapter for chatluna",
4
- "version": "1.2.20",
4
+ "version": "1.2.22",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "typings": "lib/index.d.ts",
@@ -62,7 +62,7 @@
62
62
  "adapter"
63
63
  ],
64
64
  "dependencies": {
65
- "@chatluna/v1-shared-adapter": "^1.0.3",
65
+ "@chatluna/v1-shared-adapter": "^1.0.5",
66
66
  "@langchain/core": "^0.3.43",
67
67
  "zod": "^3.25.0-canary.20250211T214501",
68
68
  "zod-to-json-schema": "^3.24.5"
@@ -73,7 +73,7 @@
73
73
  },
74
74
  "peerDependencies": {
75
75
  "koishi": "^4.18.7",
76
- "koishi-plugin-chatluna": "^1.3.0-alpha.15"
76
+ "koishi-plugin-chatluna": "^1.3.0-alpha.17"
77
77
  },
78
78
  "koishi": {
79
79
  "description": {