ctod 1.0.7 → 1.1.1

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.
@@ -1,11 +1,13 @@
1
1
  import { json } from 'power-helper'
2
2
  import { parseJSONStream } from '../../utils/json.js'
3
3
  import { OpenAICtodService } from './index.js'
4
+ import { PolymorphicMessage } from '../../broker/chat.js'
4
5
 
5
6
  export type ChatGPTMessage = {
6
7
  role: 'system' | 'user' | 'assistant' | string
7
8
  name?: string
8
- content: string
9
+ content?: string
10
+ contents?: PolymorphicMessage[]
9
11
  }
10
12
 
11
13
  type ApiResponse = {
@@ -194,6 +196,39 @@ export class OpenAIChat {
194
196
  this.openai = openai
195
197
  }
196
198
 
199
+ static toApiMessages(messages: ChatGPTMessage[]) {
200
+ return messages.map(message => {
201
+ const output = []
202
+ if (message.content) {
203
+ output.push({
204
+ type: 'input_text',
205
+ text: message.content
206
+ })
207
+ }
208
+ if (message.contents) {
209
+ for (const item of message.contents) {
210
+ if (item.type === 'text') {
211
+ output.push({
212
+ type: 'input_text',
213
+ text: item.content
214
+ })
215
+ } else if (item.type === 'image') {
216
+ const url = item.content || ''
217
+ output.push({
218
+ type: 'input_image',
219
+ image_url: url
220
+ })
221
+ }
222
+ }
223
+ }
224
+ return {
225
+ role: message.role,
226
+ name: message.name,
227
+ content: output
228
+ }
229
+ })
230
+ }
231
+
197
232
  /**
198
233
  * @zh 改變對話的一些設定
199
234
  * @en Change some settings of the conversation
@@ -242,7 +277,7 @@ export class OpenAIChat {
242
277
  }
243
278
  const result = await this.openai._axios.post<ApiResponse>(`${this.openai._baseUrl}/v1/responses`, {
244
279
  model: this.config.model,
245
- input: newMessages,
280
+ input: OpenAIChat.toApiMessages(newMessages),
246
281
  temperature: this.config.temperature,
247
282
  max_output_tokens: this.config.maxTokens,
248
283
  reasoning: this.config.reasoning,
@@ -280,17 +315,20 @@ export class OpenAIChat {
280
315
  talkStream(params: {
281
316
  messages: any[]
282
317
  onMessage: (_message: string) => void
283
- onEnd: () => void
318
+ onEnd: (_params: { isManualCancelled: boolean }) => void
284
319
  onError: (_error: any) => void
285
320
  onWarn?: (_warn: any) => void
286
321
  onThinking?: (_message: string) => void
287
322
  }) {
288
323
  let endFlag = false
324
+ let isManualCancelled = false
289
325
  const controller = new AbortController()
290
326
  const end = () => {
291
327
  if (endFlag) return
292
328
  endFlag = true
293
- params.onEnd()
329
+ params.onEnd({
330
+ isManualCancelled
331
+ })
294
332
  }
295
333
  fetch(`${this.openai._baseUrl}/v1/responses`, {
296
334
  method: 'POST',
@@ -355,7 +393,11 @@ export class OpenAIChat {
355
393
  }
356
394
  })
357
395
  return {
358
- cancel: () => controller.abort()
396
+ isManualCancelled: () => isManualCancelled,
397
+ cancel: () => {
398
+ isManualCancelled = true
399
+ controller.abort()
400
+ }
359
401
  }
360
402
  }
361
403
 
@@ -1,11 +1,13 @@
1
1
  import { json } from 'power-helper'
2
2
  import { XCtodService } from './index.js'
3
3
  import { parseJSONStream } from '../../utils/json.js'
4
+ import { PolymorphicMessage } from '../../broker/chat.js'
4
5
 
5
6
  export type XMessage = {
6
7
  role: 'system' | 'user' | 'assistant'
7
8
  name?: string
8
- content: string
9
+ content?: string
10
+ contents?: PolymorphicMessage[]
9
11
  }
10
12
 
11
13
  type ApiResponse = {
@@ -190,6 +192,39 @@ export class XChat {
190
192
  maxTokens: undefined
191
193
  }
192
194
 
195
+ static toApiMessages(messages: XMessage[]) {
196
+ return messages.map(message => {
197
+ const output = []
198
+ if (message.content) {
199
+ output.push({
200
+ type: 'input_text',
201
+ text: message.content
202
+ })
203
+ }
204
+ if (message.contents) {
205
+ for (const item of message.contents) {
206
+ if (item.type === 'text') {
207
+ output.push({
208
+ type: 'input_text',
209
+ text: item.content
210
+ })
211
+ } else if (item.type === 'image') {
212
+ const url = item.content || ''
213
+ output.push({
214
+ type: 'input_image',
215
+ image_url: url
216
+ })
217
+ }
218
+ }
219
+ }
220
+ return {
221
+ role: message.role,
222
+ name: message.name,
223
+ content: output
224
+ }
225
+ })
226
+ }
227
+
193
228
  constructor(xAi: XCtodService) {
194
229
  this.xAi = xAi
195
230
  }
@@ -223,7 +258,7 @@ export class XChat {
223
258
  }
224
259
  const result = await this.xAi._axios.post<ApiResponse>('https://api.x.ai/v1/responses', {
225
260
  model: this.config.model,
226
- input: newMessages,
261
+ input: XChat.toApiMessages(newMessages),
227
262
  temperature: this.config.temperature,
228
263
  max_output_tokens: this.config.maxTokens,
229
264
  reasoning: this.config.reasoning,
@@ -261,17 +296,20 @@ export class XChat {
261
296
  talkStream(params: {
262
297
  messages: any[]
263
298
  onMessage: (_message: string) => void
264
- onEnd: () => void
299
+ onEnd: (_params: { isManualCancelled: boolean }) => void
265
300
  onWarn?: (_warn: any) => void
266
301
  onThinking?: (_message: string) => void
267
302
  onError: (_error: any) => void
268
303
  }) {
269
304
  let endFlag = false
305
+ let isManualCancelled = false
270
306
  const controller = new AbortController()
271
307
  const end = () => {
272
308
  if (endFlag) return
273
309
  endFlag = true
274
- params.onEnd()
310
+ params.onEnd({
311
+ isManualCancelled
312
+ })
275
313
  }
276
314
  fetch('https://api.x.ai/v1/responses', {
277
315
  method: 'POST',
@@ -336,7 +374,11 @@ export class XChat {
336
374
  }
337
375
  })
338
376
  return {
339
- cancel: () => controller.abort()
377
+ isManualCancelled: () => isManualCancelled,
378
+ cancel: () => {
379
+ isManualCancelled = true
380
+ controller.abort()
381
+ }
340
382
  }
341
383
  }
342
384
 
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @zh 將陣列的多行文字合併為一個字串。
3
+ * @en Join multiple lines of text from an array into a single string.
4
+ */
5
+ export const paragraph = (texts: string | string[]): string => {
6
+ if (typeof texts === 'string') {
7
+ return texts
8
+ }
9
+ return texts.join('\n')
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctod",
3
- "version": "1.0.7",
3
+ "version": "1.1.1",
4
4
  "description": "CtoD Is Chat To Data Utils.",
5
5
  "main": "./dist/index.js",
6
6
  "type": "module",
@@ -62,6 +62,6 @@
62
62
  "json5": "^2.2.3",
63
63
  "opencc-js": "^1.0.5",
64
64
  "power-helper": "^0.9.0",
65
- "zod": "^4.1.12"
65
+ "zod": "^4.3.6"
66
66
  }
67
67
  }
@@ -3,10 +3,16 @@ import { Event, Hook, Log } from 'power-helper';
3
3
  import { Translator, TranslatorParams } from '../core/translator.js';
4
4
  import { ValidateCallback, ValidateCallbackOutputs } from '../utils/validate.js';
5
5
  import { z } from 'zod';
6
+ import { CtoD } from '../ctod.js';
7
+ export type PolymorphicMessage = {
8
+ type: 'text' | 'image';
9
+ content: string;
10
+ };
6
11
  export type Message = {
7
12
  role: 'system' | 'user' | 'assistant' | (string & Record<string, unknown>);
8
13
  name?: string;
9
- content: string;
14
+ content?: string;
15
+ contents?: PolymorphicMessage[];
10
16
  };
11
17
  export type ChatBrokerHooks<S extends ValidateCallback<any>, O extends ValidateCallback<any>, P extends ChatBrokerPlugin<any, any>, PS extends Record<string, ReturnType<P['use']>>> = {
12
18
  /**
@@ -28,7 +34,9 @@ export type ChatBrokerHooks<S extends ValidateCallback<any>, O extends ValidateC
28
34
  };
29
35
  messages: Message[];
30
36
  setPreMessages: (messages: (Omit<Message, 'content'> & {
31
- content: string | string[];
37
+ content?: string | string[];
38
+ } & {
39
+ contents?: PolymorphicMessage[];
32
40
  })[]) => void;
33
41
  changeMessages: (messages: Message[]) => void;
34
42
  changeOutputSchema: (output: O) => void;
@@ -140,6 +148,7 @@ export declare class ChatBroker<S extends ValidateCallback<any>, O extends Valid
140
148
  constructor(params: Params<S, O, C, P, PS>);
141
149
  protected _install(): any;
142
150
  cancel(requestId?: string): Promise<void>;
151
+ cloneFrom(ctod: CtoD<any, any>): ChatBroker<S, O, P, PS, C>;
143
152
  requestWithId<T extends Translator<S, O>>(data: T['__schemeType']): {
144
153
  id: string;
145
154
  request: Promise<T['__outputType']>;
@@ -157,7 +166,9 @@ export declare class ChatBroker<S extends ValidateCallback<any>, O extends Valid
157
166
  outputSchema: {
158
167
  [x: string]: any;
159
168
  };
160
- outputJsonSchema: z.core.JSONSchema.JSONSchema;
169
+ outputJsonSchema: z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{
170
+ [x: string]: any;
171
+ }, z.core.$strip>>;
161
172
  requestMessages: Message[];
162
173
  }>;
163
174
  }
@@ -1,4 +1,4 @@
1
- import { ChatBroker, Message, Params as ChatBrokerParams, ChatBrokerHooks, RequestContext } from './broker/chat.js';
1
+ import { PolymorphicMessage, ChatBroker, Message, Params as ChatBrokerParams, ChatBrokerHooks, RequestContext } from './broker/chat.js';
2
2
  import { ChatBrokerPlugin } from './core/plugin.js';
3
3
  import * as z from 'zod';
4
4
  type IO = any;
@@ -22,7 +22,9 @@ export declare class CtoD<P extends ChatBrokerPlugin<IO, IO>, PS extends Record<
22
22
  send: (data: PS[K]["__receiveData"]) => void;
23
23
  }; };
24
24
  setMessages: (messages: (Omit<Message, "content"> & {
25
- content: string | string[];
25
+ content?: string | string[];
26
+ } & {
27
+ contents?: PolymorphicMessage[];
26
28
  })[]) => void;
27
29
  metadata: Map<string, any>;
28
30
  }) => Promise<O>) => ChatBroker<() => I, () => O, P, PS, ChatBrokerHooks<() => I, () => O, P, PS>>;
@@ -4,6 +4,7 @@ export * as chineseConverter from './utils/chinese-conv.js';
4
4
  export { CtoD } from './ctod.js';
5
5
  export { validateToJsonSchema } from './utils/validate.js';
6
6
  export { parseJSONStream } from './utils/json.js';
7
+ export { paragraph } from './utils/paragraph.js';
7
8
  export { OpenAICtodService } from './service/openai/index.js';
8
9
  export { LlamaCppCtodService } from './service/llama-cpp/index.js';
9
10
  export { GoogleCtodService } from './service/google/index.js';
@@ -18,3 +19,4 @@ export { Translator } from './core/translator.js';
18
19
  export type { ValidateCallback } from './utils/validate.js';
19
20
  export type { TranslatorParams } from './core/translator.js';
20
21
  export type { ChatGPTMessage } from './service/openai/chat.js';
22
+ export type { PolymorphicMessage } from './broker/chat.js';
@@ -1,8 +1,10 @@
1
1
  import { AnthropicCtodService } from './index.js';
2
+ import { PolymorphicMessage } from '../../broker/chat.js';
2
3
  type AnthropicSdk = AnthropicCtodService['anthropicSdk'];
3
4
  export type Message = {
4
5
  role: string;
5
- content: string;
6
+ content?: string;
7
+ contents?: PolymorphicMessage[];
6
8
  };
7
9
  export type Config = {
8
10
  /**
@@ -76,9 +78,12 @@ export declare class AnthropicChat {
76
78
  messages: Message[];
77
79
  onMessage: (_message: string) => void;
78
80
  onThinking?: (_thinking: string) => void;
79
- onEnd: () => void;
81
+ onEnd: (_params: {
82
+ isManualCancelled: boolean;
83
+ }) => void;
80
84
  onError: (_error: any) => void;
81
85
  }): {
86
+ isManualCancelled: () => boolean;
82
87
  cancel: () => void;
83
88
  };
84
89
  }
@@ -11,6 +11,10 @@ type Part = {
11
11
  data: string;
12
12
  mimeType: string;
13
13
  };
14
+ } | {
15
+ fileData: {
16
+ fileUri: string;
17
+ };
14
18
  };
15
19
  export type GoogleMessage = {
16
20
  role: 'model' | 'user';
@@ -67,10 +71,13 @@ export declare class GoogleChat {
67
71
  system?: string;
68
72
  messages: GoogleMessage[];
69
73
  onMessage: (_message: string) => void;
70
- onEnd: () => void;
74
+ onEnd: (_params: {
75
+ isManualCancelled: boolean;
76
+ }) => void;
71
77
  onThinking?: (_thinking: string) => void;
72
78
  onError: (_error: any) => void;
73
79
  }): {
80
+ isManualCancelled: () => boolean;
74
81
  cancel: () => void;
75
82
  };
76
83
  }
@@ -2,9 +2,9 @@ import { GoogleMessage, GoogleChat, Config } from './chat.js';
2
2
  import { GoogleImagesGeneration } from './images-generation.js';
3
3
  import type { GoogleGenAI } from '@google/genai';
4
4
  type GPTContent = {
5
- type: 'image_url' | 'text';
5
+ type: 'image_url' | 'text' | 'input_text' | 'input_image';
6
6
  text?: string;
7
- image_url?: {
7
+ image_url?: string | {
8
8
  url: string;
9
9
  detail?: string;
10
10
  };
@@ -1,7 +1,9 @@
1
1
  import { LlamaCppCtodService } from './index.js';
2
+ import { PolymorphicMessage } from '../../broker/chat.js';
2
3
  type Message = {
3
4
  role: string;
4
- content: string;
5
+ content?: string;
6
+ contents?: PolymorphicMessage[];
5
7
  };
6
8
  type Options = any;
7
9
  export type Config = {
@@ -11,7 +13,9 @@ export type Config = {
11
13
  };
12
14
  type Stream = {
13
15
  onMessage: (message: string) => void;
14
- onEnd?: () => void;
16
+ onEnd?: (params: {
17
+ isManualCancelled: boolean;
18
+ }) => void;
15
19
  onWarn?: (error: any) => void;
16
20
  onError?: (error: any) => void;
17
21
  };
@@ -1,8 +1,10 @@
1
1
  import { OpenAICtodService } from './index.js';
2
+ import { PolymorphicMessage } from '../../broker/chat.js';
2
3
  export type ChatGPTMessage = {
3
4
  role: 'system' | 'user' | 'assistant' | string;
4
5
  name?: string;
5
- content: string;
6
+ content?: string;
7
+ contents?: PolymorphicMessage[];
6
8
  };
7
9
  type ApiResponse = {
8
10
  id: string;
@@ -90,6 +92,19 @@ export declare class OpenAIChat {
90
92
  openai: OpenAICtodService;
91
93
  config: Config;
92
94
  constructor(openai: OpenAICtodService);
95
+ static toApiMessages(messages: ChatGPTMessage[]): {
96
+ role: string;
97
+ name: string | undefined;
98
+ content: ({
99
+ type: string;
100
+ text: string;
101
+ image_url?: undefined;
102
+ } | {
103
+ type: string;
104
+ image_url: string;
105
+ text?: undefined;
106
+ })[];
107
+ }[];
93
108
  /**
94
109
  * @zh 改變對話的一些設定
95
110
  * @en Change some settings of the conversation
@@ -120,11 +135,14 @@ export declare class OpenAIChat {
120
135
  talkStream(params: {
121
136
  messages: any[];
122
137
  onMessage: (_message: string) => void;
123
- onEnd: () => void;
138
+ onEnd: (_params: {
139
+ isManualCancelled: boolean;
140
+ }) => void;
124
141
  onError: (_error: any) => void;
125
142
  onWarn?: (_warn: any) => void;
126
143
  onThinking?: (_message: string) => void;
127
144
  }): {
145
+ isManualCancelled: () => boolean;
128
146
  cancel: () => void;
129
147
  };
130
148
  /**
@@ -1,8 +1,10 @@
1
1
  import { XCtodService } from './index.js';
2
+ import { PolymorphicMessage } from '../../broker/chat.js';
2
3
  export type XMessage = {
3
4
  role: 'system' | 'user' | 'assistant';
4
5
  name?: string;
5
- content: string;
6
+ content?: string;
7
+ contents?: PolymorphicMessage[];
6
8
  };
7
9
  type ApiResponse = {
8
10
  id: string;
@@ -89,6 +91,19 @@ export type Config = {
89
91
  export declare class XChat {
90
92
  xAi: XCtodService;
91
93
  config: Config;
94
+ static toApiMessages(messages: XMessage[]): {
95
+ role: "system" | "user" | "assistant";
96
+ name: string | undefined;
97
+ content: ({
98
+ type: string;
99
+ text: string;
100
+ image_url?: undefined;
101
+ } | {
102
+ type: string;
103
+ image_url: string;
104
+ text?: undefined;
105
+ })[];
106
+ }[];
92
107
  constructor(xAi: XCtodService);
93
108
  /**
94
109
  * @zh 改變對話的一些設定
@@ -113,11 +128,14 @@ export declare class XChat {
113
128
  talkStream(params: {
114
129
  messages: any[];
115
130
  onMessage: (_message: string) => void;
116
- onEnd: () => void;
131
+ onEnd: (_params: {
132
+ isManualCancelled: boolean;
133
+ }) => void;
117
134
  onWarn?: (_warn: any) => void;
118
135
  onThinking?: (_message: string) => void;
119
136
  onError: (_error: any) => void;
120
137
  }): {
138
+ isManualCancelled: () => boolean;
121
139
  cancel: () => void;
122
140
  };
123
141
  /**
@@ -0,0 +1,5 @@
1
+ /**
2
+ * @zh 將陣列的多行文字合併為一個字串。
3
+ * @en Join multiple lines of text from an array into a single string.
4
+ */
5
+ export declare const paragraph: (texts: string | string[]) => string;
@@ -7,4 +7,4 @@ export type ValidateCallbackOutputs<T extends ValidateCallback<any>, R = ReturnT
7
7
  };
8
8
  export declare function definedValidateSchema<T extends ValidateCallback<any>>(cb: T): T;
9
9
  export declare function validate<T extends ValidateCallback<any>, R = ReturnType<T>>(target: any, schemaCallback: T): { [K in keyof R]: R[K] extends z.ZodTypeAny ? z.infer<R[K]> : R[K]; };
10
- export declare function validateToJsonSchema<T extends ValidateCallback<any>>(target: () => T): z.core.JSONSchema.JSONSchema;
10
+ export declare function validateToJsonSchema<T extends ValidateCallback<any>>(target: () => T): z.core.ZodStandardJSONSchemaPayload<z.ZodObject<{ -readonly [P in keyof T]: T[P]; }, z.core.$strip>>;