@chatluna/v1-shared-adapter 1.0.4 → 1.0.6

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
@@ -27,6 +27,7 @@ __export(index_exports, {
27
27
  convertMessageToMessageChunk: () => convertMessageToMessageChunk,
28
28
  createEmbeddings: () => createEmbeddings,
29
29
  createRequestContext: () => createRequestContext,
30
+ fetchImageUrl: () => fetchImageUrl,
30
31
  formatToolToOpenAITool: () => formatToolToOpenAITool,
31
32
  formatToolsToOpenAITools: () => formatToolsToOpenAITools,
32
33
  getModelMaxContextSize: () => getModelMaxContextSize,
@@ -38,6 +39,7 @@ __export(index_exports, {
38
39
  processReasoningContent: () => processReasoningContent,
39
40
  processResponse: () => processResponse,
40
41
  processStreamResponse: () => processStreamResponse,
42
+ removeAdditionalProperties: () => removeAdditionalProperties,
41
43
  supportImageInput: () => supportImageInput
42
44
  });
43
45
  module.exports = __toCommonJS(index_exports);
@@ -135,12 +137,14 @@ var import_sse = require("koishi-plugin-chatluna/utils/sse");
135
137
  // src/utils.ts
136
138
  var import_messages = require("@langchain/core/messages");
137
139
  var import_zod_to_json_schema = require("zod-to-json-schema");
138
- function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, removeSystemMessage) {
140
+ var import_string = require("koishi-plugin-chatluna/utils/string");
141
+ var import_zod = require("zod");
142
+ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInput2, removeSystemMessage) {
139
143
  const result = [];
140
144
  for (const rawMessage of messages) {
141
145
  const role = messageTypeToOpenAIRole(rawMessage.getType());
142
146
  const msg = {
143
- content: rawMessage.content || null,
147
+ content: rawMessage.content,
144
148
  name: role === "assistant" || role === "tool" ? rawMessage.name : void 0,
145
149
  role,
146
150
  // function_call: rawMessage.additional_kwargs.function_call,
@@ -180,6 +184,24 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
180
184
  }
181
185
  });
182
186
  }
187
+ } else if (Array.isArray(msg.content) && msg.content.length > 0) {
188
+ msg.content = await Promise.all(
189
+ msg.content.map(async (content) => {
190
+ if (!(0, import_string.isMessageContentImageUrl)(content)) return content;
191
+ try {
192
+ const url = await fetchImageUrl(plugin, content);
193
+ return {
194
+ type: "image_url",
195
+ image_url: {
196
+ url,
197
+ detail: "low"
198
+ }
199
+ };
200
+ } catch {
201
+ return content;
202
+ }
203
+ })
204
+ );
183
205
  }
184
206
  result.push(msg);
185
207
  }
@@ -226,6 +248,17 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
226
248
  return result;
227
249
  }
228
250
  __name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
251
+ async function fetchImageUrl(plugin, content) {
252
+ const url = typeof content.image_url === "string" ? content.image_url : content.image_url.url;
253
+ if (url.includes("data:image") && url.includes("base64")) {
254
+ return url;
255
+ }
256
+ const ext = url.match(/\.([^.?#]+)(?:[?#]|$)/)?.[1]?.toLowerCase();
257
+ const imageType = (0, import_string.getImageMimeType)(ext);
258
+ const buffer = await plugin.fetch(url).then((res) => res.arrayBuffer()).then(Buffer.from);
259
+ return `data:${imageType};base64,${buffer.toString("base64")}`;
260
+ }
261
+ __name(fetchImageUrl, "fetchImageUrl");
229
262
  function messageTypeToOpenAIRole(type) {
230
263
  switch (type) {
231
264
  case "system":
@@ -261,10 +294,9 @@ function formatToolsToOpenAITools(tools, includeGoogleSearch) {
261
294
  __name(formatToolsToOpenAITools, "formatToolsToOpenAITools");
262
295
  function formatToolToOpenAITool(tool) {
263
296
  const parameters = removeAdditionalProperties(
264
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
265
- (0, import_zod_to_json_schema.zodToJsonSchema)(tool.schema, {
297
+ tool.schema instanceof import_zod.ZodSchema ? (0, import_zod_to_json_schema.zodToJsonSchema)(tool.schema, {
266
298
  allowedAdditionalProperties: void 0
267
- })
299
+ }) : tool.schema
268
300
  );
269
301
  return {
270
302
  type: "function",
@@ -412,12 +444,13 @@ __name(convertDeltaToMessageChunk, "convertDeltaToMessageChunk");
412
444
 
413
445
  // src/requester.ts
414
446
  var import_messages2 = require("@langchain/core/messages");
415
- var import_string = require("koishi-plugin-chatluna/utils/string");
416
- function buildChatCompletionParams(params, enableGoogleSearch, supportImageInput2) {
447
+ var import_string2 = require("koishi-plugin-chatluna/utils/string");
448
+ async function buildChatCompletionParams(params, plugin, enableGoogleSearch, supportImageInput2) {
417
449
  const base = {
418
450
  model: params.model,
419
- messages: langchainMessageToOpenAIMessage(
451
+ messages: await langchainMessageToOpenAIMessage(
420
452
  params.input,
453
+ plugin,
421
454
  params.model,
422
455
  supportImageInput2
423
456
  ),
@@ -553,7 +586,7 @@ async function processResponse(requestContext, response) {
553
586
  const messageChunk = convertMessageToMessageChunk(choice.message);
554
587
  return new import_outputs.ChatGenerationChunk({
555
588
  message: messageChunk,
556
- text: (0, import_string.getMessageContent)(messageChunk.content),
589
+ text: (0, import_string2.getMessageContent)(messageChunk.content),
557
590
  generationInfo: {
558
591
  tokenUsage: data.usage
559
592
  }
@@ -577,8 +610,9 @@ async function* completionStream(requestContext, params, completionUrl = "chat/c
577
610
  try {
578
611
  const response = await modelRequester.post(
579
612
  completionUrl,
580
- buildChatCompletionParams(
613
+ await buildChatCompletionParams(
581
614
  params,
615
+ requestContext.plugin,
582
616
  enableGoogleSearch ?? false,
583
617
  supportImageInput2 ?? true
584
618
  ),
@@ -599,8 +633,9 @@ async function* completionStream(requestContext, params, completionUrl = "chat/c
599
633
  __name(completionStream, "completionStream");
600
634
  async function completion(requestContext, params, completionUrl = "chat/completions", enableGoogleSearch, supportImageInput2) {
601
635
  const { modelRequester } = requestContext;
602
- const chatCompletionParams = buildChatCompletionParams(
636
+ const chatCompletionParams = await buildChatCompletionParams(
603
637
  params,
638
+ requestContext.plugin,
604
639
  enableGoogleSearch ?? false,
605
640
  supportImageInput2 ?? true
606
641
  );
@@ -672,6 +707,7 @@ __name(createRequestContext, "createRequestContext");
672
707
  convertMessageToMessageChunk,
673
708
  createEmbeddings,
674
709
  createRequestContext,
710
+ fetchImageUrl,
675
711
  formatToolToOpenAITool,
676
712
  formatToolsToOpenAITools,
677
713
  getModelMaxContextSize,
@@ -683,5 +719,6 @@ __name(createRequestContext, "createRequestContext");
683
719
  processReasoningContent,
684
720
  processResponse,
685
721
  processStreamResponse,
722
+ removeAdditionalProperties,
686
723
  supportImageInput
687
724
  });
package/lib/index.mjs CHANGED
@@ -104,12 +104,17 @@ import {
104
104
  ToolMessageChunk
105
105
  } from "@langchain/core/messages";
106
106
  import { zodToJsonSchema } from "zod-to-json-schema";
107
- function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, removeSystemMessage) {
107
+ import {
108
+ getImageMimeType,
109
+ isMessageContentImageUrl
110
+ } from "koishi-plugin-chatluna/utils/string";
111
+ import { ZodSchema } from "zod";
112
+ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInput2, removeSystemMessage) {
108
113
  const result = [];
109
114
  for (const rawMessage of messages) {
110
115
  const role = messageTypeToOpenAIRole(rawMessage.getType());
111
116
  const msg = {
112
- content: rawMessage.content || null,
117
+ content: rawMessage.content,
113
118
  name: role === "assistant" || role === "tool" ? rawMessage.name : void 0,
114
119
  role,
115
120
  // function_call: rawMessage.additional_kwargs.function_call,
@@ -149,6 +154,24 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
149
154
  }
150
155
  });
151
156
  }
157
+ } else if (Array.isArray(msg.content) && msg.content.length > 0) {
158
+ msg.content = await Promise.all(
159
+ msg.content.map(async (content) => {
160
+ if (!isMessageContentImageUrl(content)) return content;
161
+ try {
162
+ const url = await fetchImageUrl(plugin, content);
163
+ return {
164
+ type: "image_url",
165
+ image_url: {
166
+ url,
167
+ detail: "low"
168
+ }
169
+ };
170
+ } catch {
171
+ return content;
172
+ }
173
+ })
174
+ );
152
175
  }
153
176
  result.push(msg);
154
177
  }
@@ -195,6 +218,17 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
195
218
  return result;
196
219
  }
197
220
  __name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
221
+ async function fetchImageUrl(plugin, content) {
222
+ const url = typeof content.image_url === "string" ? content.image_url : content.image_url.url;
223
+ if (url.includes("data:image") && url.includes("base64")) {
224
+ return url;
225
+ }
226
+ const ext = url.match(/\.([^.?#]+)(?:[?#]|$)/)?.[1]?.toLowerCase();
227
+ const imageType = getImageMimeType(ext);
228
+ const buffer = await plugin.fetch(url).then((res) => res.arrayBuffer()).then(Buffer.from);
229
+ return `data:${imageType};base64,${buffer.toString("base64")}`;
230
+ }
231
+ __name(fetchImageUrl, "fetchImageUrl");
198
232
  function messageTypeToOpenAIRole(type) {
199
233
  switch (type) {
200
234
  case "system":
@@ -230,10 +264,9 @@ function formatToolsToOpenAITools(tools, includeGoogleSearch) {
230
264
  __name(formatToolsToOpenAITools, "formatToolsToOpenAITools");
231
265
  function formatToolToOpenAITool(tool) {
232
266
  const parameters = removeAdditionalProperties(
233
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
234
- zodToJsonSchema(tool.schema, {
267
+ tool.schema instanceof ZodSchema ? zodToJsonSchema(tool.schema, {
235
268
  allowedAdditionalProperties: void 0
236
- })
269
+ }) : tool.schema
237
270
  );
238
271
  return {
239
272
  type: "function",
@@ -382,11 +415,12 @@ __name(convertDeltaToMessageChunk, "convertDeltaToMessageChunk");
382
415
  // src/requester.ts
383
416
  import { AIMessageChunk as AIMessageChunk2 } from "@langchain/core/messages";
384
417
  import { getMessageContent } from "koishi-plugin-chatluna/utils/string";
385
- function buildChatCompletionParams(params, enableGoogleSearch, supportImageInput2) {
418
+ async function buildChatCompletionParams(params, plugin, enableGoogleSearch, supportImageInput2) {
386
419
  const base = {
387
420
  model: params.model,
388
- messages: langchainMessageToOpenAIMessage(
421
+ messages: await langchainMessageToOpenAIMessage(
389
422
  params.input,
423
+ plugin,
390
424
  params.model,
391
425
  supportImageInput2
392
426
  ),
@@ -546,8 +580,9 @@ async function* completionStream(requestContext, params, completionUrl = "chat/c
546
580
  try {
547
581
  const response = await modelRequester.post(
548
582
  completionUrl,
549
- buildChatCompletionParams(
583
+ await buildChatCompletionParams(
550
584
  params,
585
+ requestContext.plugin,
551
586
  enableGoogleSearch ?? false,
552
587
  supportImageInput2 ?? true
553
588
  ),
@@ -568,8 +603,9 @@ async function* completionStream(requestContext, params, completionUrl = "chat/c
568
603
  __name(completionStream, "completionStream");
569
604
  async function completion(requestContext, params, completionUrl = "chat/completions", enableGoogleSearch, supportImageInput2) {
570
605
  const { modelRequester } = requestContext;
571
- const chatCompletionParams = buildChatCompletionParams(
606
+ const chatCompletionParams = await buildChatCompletionParams(
572
607
  params,
608
+ requestContext.plugin,
573
609
  enableGoogleSearch ?? false,
574
610
  supportImageInput2 ?? true
575
611
  );
@@ -640,6 +676,7 @@ export {
640
676
  convertMessageToMessageChunk,
641
677
  createEmbeddings,
642
678
  createRequestContext,
679
+ fetchImageUrl,
643
680
  formatToolToOpenAITool,
644
681
  formatToolsToOpenAITools,
645
682
  getModelMaxContextSize,
@@ -651,5 +688,6 @@ export {
651
688
  processReasoningContent,
652
689
  processResponse,
653
690
  processStreamResponse,
691
+ removeAdditionalProperties,
654
692
  supportImageInput
655
693
  };
@@ -12,7 +12,7 @@ interface RequestContext<T extends ClientConfig = ClientConfig, R extends ChatLu
12
12
  plugin: ChatLunaPlugin;
13
13
  modelRequester: ModelRequester<T, R>;
14
14
  }
15
- export declare function buildChatCompletionParams(params: ModelRequestParams, enableGoogleSearch: boolean, supportImageInput?: boolean): {
15
+ export declare function buildChatCompletionParams(params: ModelRequestParams, plugin: ChatLunaPlugin, enableGoogleSearch: boolean, supportImageInput?: boolean): Promise<{
16
16
  model: string;
17
17
  messages: import("./types").ChatCompletionResponseMessage[];
18
18
  tools: import("./types").ChatCompletionTool[];
@@ -29,7 +29,7 @@ export declare function buildChatCompletionParams(params: ModelRequestParams, en
29
29
  stream_options: {
30
30
  include_usage: boolean;
31
31
  };
32
- };
32
+ }>;
33
33
  export declare function processReasoningContent(delta: {
34
34
  reasoning_content?: string;
35
35
  content?: string;
package/lib/types.d.ts CHANGED
@@ -20,18 +20,23 @@ export interface ChatCompletionResponse {
20
20
  total_tokens: number;
21
21
  };
22
22
  }
23
+ export interface ChatCompletionTextPart {
24
+ type: 'text';
25
+ text: string;
26
+ }
27
+ export interface ChatCompletionImagePart {
28
+ type: 'image_url';
29
+ image_url: string | {
30
+ url: string;
31
+ detail?: 'low' | 'high';
32
+ };
33
+ }
34
+ export type ChatCompletionParts = ChatCompletionTextPart | ChatCompletionImagePart | (Record<string, unknown> & {
35
+ type: string;
36
+ });
23
37
  export interface ChatCompletionResponseMessage {
24
38
  role: string;
25
- content?: string | ({
26
- type: 'text';
27
- text: string;
28
- } | {
29
- type: 'image_url';
30
- image_url: {
31
- url: string;
32
- detail?: 'low' | 'high';
33
- };
34
- })[];
39
+ content?: string | ChatCompletionParts[];
35
40
  reasoning_content?: string;
36
41
  name?: string;
37
42
  tool_calls?: ChatCompletionRequestMessageToolCall[];
package/lib/utils.d.ts CHANGED
@@ -1,9 +1,13 @@
1
- import { AIMessageChunk, BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, MessageType, SystemMessageChunk, ToolMessageChunk } from '@langchain/core/messages';
1
+ import { AIMessageChunk, BaseMessage, ChatMessageChunk, FunctionMessageChunk, HumanMessageChunk, MessageContentImageUrl, MessageType, SystemMessageChunk, ToolMessageChunk } from '@langchain/core/messages';
2
2
  import { StructuredTool } from '@langchain/core/tools';
3
+ import { JsonSchema7Type } from 'zod-to-json-schema';
3
4
  import { ChatCompletionResponseMessage, ChatCompletionResponseMessageRoleEnum, ChatCompletionTool } from './types';
4
- export declare function langchainMessageToOpenAIMessage(messages: BaseMessage[], model?: string, supportImageInput?: boolean, removeSystemMessage?: boolean): ChatCompletionResponseMessage[];
5
+ import { ChatLunaPlugin } from 'koishi-plugin-chatluna/services/chat';
6
+ export declare function langchainMessageToOpenAIMessage(messages: BaseMessage[], plugin: ChatLunaPlugin, model?: string, supportImageInput?: boolean, removeSystemMessage?: boolean): Promise<ChatCompletionResponseMessage[]>;
7
+ export declare function fetchImageUrl(plugin: ChatLunaPlugin, content: MessageContentImageUrl): Promise<string>;
5
8
  export declare function messageTypeToOpenAIRole(type: MessageType): ChatCompletionResponseMessageRoleEnum;
6
9
  export declare function formatToolsToOpenAITools(tools: StructuredTool[], includeGoogleSearch: boolean): ChatCompletionTool[];
7
10
  export declare function formatToolToOpenAITool(tool: StructuredTool): ChatCompletionTool;
11
+ export declare function removeAdditionalProperties(schema: JsonSchema7Type): JsonSchema7Type;
8
12
  export declare function convertMessageToMessageChunk(message: ChatCompletionResponseMessage): HumanMessageChunk | AIMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk;
9
13
  export declare function convertDeltaToMessageChunk(delta: Record<string, any>, defaultRole?: ChatCompletionResponseMessageRoleEnum): HumanMessageChunk | AIMessageChunk | SystemMessageChunk | FunctionMessageChunk | ToolMessageChunk | ChatMessageChunk;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chatluna/v1-shared-adapter",
3
3
  "description": "chatluna shared adapter",
4
- "version": "1.0.4",
4
+ "version": "1.0.6",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "typings": "lib/index.d.ts",
@@ -36,16 +36,16 @@
36
36
  "node": ">=18.0.0"
37
37
  },
38
38
  "resolutions": {
39
- "@langchain/core": "0.3.43",
39
+ "@langchain/core": "0.3.62",
40
40
  "js-tiktoken": "npm:@dingyi222666/js-tiktoken@^1.0.19"
41
41
  },
42
42
  "overrides": {
43
- "@langchain/core": "0.3.43",
43
+ "@langchain/core": "0.3.62",
44
44
  "js-tiktoken": "npm:@dingyi222666/js-tiktoken@^1.0.19"
45
45
  },
46
46
  "pnpm": {
47
47
  "overrides": {
48
- "@langchain/core": "0.3.43",
48
+ "@langchain/core": "0.3.62",
49
49
  "js-tiktoken": "npm:@dingyi222666/js-tiktoken@^1.0.19"
50
50
  }
51
51
  },
@@ -60,7 +60,7 @@
60
60
  "adapter"
61
61
  ],
62
62
  "dependencies": {
63
- "@langchain/core": "^0.3.43",
63
+ "@langchain/core": "0.3.62",
64
64
  "zod": "^3.25.0-canary.20250211T214501",
65
65
  "zod-to-json-schema": "^3.24.5"
66
66
  },
@@ -70,6 +70,6 @@
70
70
  },
71
71
  "peerDependencies": {
72
72
  "koishi": "^4.18.7",
73
- "koishi-plugin-chatluna": "^1.3.0-alpha.16"
73
+ "koishi-plugin-chatluna": "^1.3.0-alpha.26"
74
74
  }
75
75
  }