@chatluna/v1-shared-adapter 1.0.4 → 1.0.5

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,13 @@ 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
+ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInput2, removeSystemMessage) {
139
142
  const result = [];
140
143
  for (const rawMessage of messages) {
141
144
  const role = messageTypeToOpenAIRole(rawMessage.getType());
142
145
  const msg = {
143
- content: rawMessage.content || null,
146
+ content: rawMessage.content,
144
147
  name: role === "assistant" || role === "tool" ? rawMessage.name : void 0,
145
148
  role,
146
149
  // function_call: rawMessage.additional_kwargs.function_call,
@@ -180,6 +183,24 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
180
183
  }
181
184
  });
182
185
  }
186
+ } else if (Array.isArray(msg.content) && msg.content.length > 0) {
187
+ msg.content = await Promise.all(
188
+ msg.content.map(async (content) => {
189
+ if (!(0, import_string.isMessageContentImageUrl)(content)) return content;
190
+ try {
191
+ const url = await fetchImageUrl(plugin, content);
192
+ return {
193
+ type: "image_url",
194
+ image_url: {
195
+ url,
196
+ detail: "low"
197
+ }
198
+ };
199
+ } catch {
200
+ return content;
201
+ }
202
+ })
203
+ );
183
204
  }
184
205
  result.push(msg);
185
206
  }
@@ -226,6 +247,17 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
226
247
  return result;
227
248
  }
228
249
  __name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
250
+ async function fetchImageUrl(plugin, content) {
251
+ const url = typeof content.image_url === "string" ? content.image_url : content.image_url.url;
252
+ if (url.includes("data:image") && url.includes("base64")) {
253
+ return url;
254
+ }
255
+ const ext = url.match(/\.([^.?#]+)(?:[?#]|$)/)?.[1]?.toLowerCase();
256
+ const imageType = (0, import_string.getImageMimeType)(ext);
257
+ const buffer = await plugin.fetch(url).then((res) => res.arrayBuffer()).then(Buffer.from);
258
+ return `data:${imageType};base64,${buffer.toString("base64")}`;
259
+ }
260
+ __name(fetchImageUrl, "fetchImageUrl");
229
261
  function messageTypeToOpenAIRole(type) {
230
262
  switch (type) {
231
263
  case "system":
@@ -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,16 @@ 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
+ async function langchainMessageToOpenAIMessage(messages, plugin, model, supportImageInput2, removeSystemMessage) {
108
112
  const result = [];
109
113
  for (const rawMessage of messages) {
110
114
  const role = messageTypeToOpenAIRole(rawMessage.getType());
111
115
  const msg = {
112
- content: rawMessage.content || null,
116
+ content: rawMessage.content,
113
117
  name: role === "assistant" || role === "tool" ? rawMessage.name : void 0,
114
118
  role,
115
119
  // function_call: rawMessage.additional_kwargs.function_call,
@@ -149,6 +153,24 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
149
153
  }
150
154
  });
151
155
  }
156
+ } else if (Array.isArray(msg.content) && msg.content.length > 0) {
157
+ msg.content = await Promise.all(
158
+ msg.content.map(async (content) => {
159
+ if (!isMessageContentImageUrl(content)) return content;
160
+ try {
161
+ const url = await fetchImageUrl(plugin, content);
162
+ return {
163
+ type: "image_url",
164
+ image_url: {
165
+ url,
166
+ detail: "low"
167
+ }
168
+ };
169
+ } catch {
170
+ return content;
171
+ }
172
+ })
173
+ );
152
174
  }
153
175
  result.push(msg);
154
176
  }
@@ -195,6 +217,17 @@ function langchainMessageToOpenAIMessage(messages, model, supportImageInput2, re
195
217
  return result;
196
218
  }
197
219
  __name(langchainMessageToOpenAIMessage, "langchainMessageToOpenAIMessage");
220
+ async function fetchImageUrl(plugin, content) {
221
+ const url = typeof content.image_url === "string" ? content.image_url : content.image_url.url;
222
+ if (url.includes("data:image") && url.includes("base64")) {
223
+ return url;
224
+ }
225
+ const ext = url.match(/\.([^.?#]+)(?:[?#]|$)/)?.[1]?.toLowerCase();
226
+ const imageType = getImageMimeType(ext);
227
+ const buffer = await plugin.fetch(url).then((res) => res.arrayBuffer()).then(Buffer.from);
228
+ return `data:${imageType};base64,${buffer.toString("base64")}`;
229
+ }
230
+ __name(fetchImageUrl, "fetchImageUrl");
198
231
  function messageTypeToOpenAIRole(type) {
199
232
  switch (type) {
200
233
  case "system":
@@ -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.5",
5
5
  "main": "lib/index.cjs",
6
6
  "module": "lib/index.mjs",
7
7
  "typings": "lib/index.d.ts",
@@ -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.17"
74
74
  }
75
75
  }