@maiyunnet/kebab 3.2.30 → 3.2.32

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/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * --- 本文件用来定义每个目录实体地址的常量 ---
6
6
  */
7
7
  /** --- 当前系统版本号 --- */
8
- export declare const VER = "3.2.30";
8
+ export declare const VER = "3.2.32";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  export declare const LIB_PATH: string;
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '3.2.30';
9
+ export const VER = '3.2.32';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/ai.d.ts CHANGED
@@ -4,6 +4,7 @@
4
4
  * Last: 2025-10-27 21:31:08
5
5
  */
6
6
  import * as openai from 'openai';
7
+ import * as streaming from 'openai/streaming';
7
8
  import * as sCtr from '#kebab/sys/ctr.js';
8
9
  /**
9
10
  * --- 参考:https://help.aliyun.com/zh/model-studio/what-is-model-studio ---
@@ -16,7 +17,11 @@ export declare enum ESERVICE {
16
17
  /** --- 阿里国际区 --- */
17
18
  'ALIAS' = 1,
18
19
  /** --- 微软 Azure --- */
19
- 'AZURE' = 2
20
+ 'AZURE' = 2,
21
+ /** --- 微软 Azure 2 --- */
22
+ 'AZURE2' = 3,
23
+ /** --- 微软 Azure 3 --- */
24
+ 'AZURE3' = 4
20
25
  }
21
26
  /** --- 选项 --- */
22
27
  export interface IOptions {
@@ -32,7 +37,12 @@ export interface IOptions {
32
37
  export declare class Ai {
33
38
  /** --- openai 原生对象,建议只读 --- */
34
39
  readonly link: openai.OpenAI;
40
+ private readonly _ctr;
35
41
  constructor(ctr: sCtr.Ctr, opt: IOptions);
42
+ /** --- 创建非流式对话 --- */
43
+ chat(body: openai.default.Chat.Completions.ChatCompletionCreateParamsNonStreaming): openai.APIPromise<openai.default.Chat.ChatCompletion> | false;
44
+ /** --- 创建流式对话 --- */
45
+ chat(body: openai.default.Chat.Completions.ChatCompletionCreateParamsStreaming): openai.APIPromise<streaming.Stream<openai.default.Chat.ChatCompletionChunk>> | false;
36
46
  }
37
47
  /**
38
48
  * --- 创建一个 AI 对象 ---
package/lib/ai.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * Last: 2025-10-27 21:31:08
5
5
  */
6
6
  import * as openai from 'openai';
7
+ import * as lCore from '#kebab/lib/core.js';
7
8
  /**
8
9
  * --- 参考:https://help.aliyun.com/zh/model-studio/what-is-model-studio ---
9
10
  * --- 阿里模型:https://help.aliyun.com/zh/model-studio/getting-started/models ---
@@ -17,11 +18,16 @@ export var ESERVICE;
17
18
  ESERVICE[ESERVICE["ALIAS"] = 1] = "ALIAS";
18
19
  /** --- 微软 Azure --- */
19
20
  ESERVICE[ESERVICE["AZURE"] = 2] = "AZURE";
21
+ /** --- 微软 Azure 2 --- */
22
+ ESERVICE[ESERVICE["AZURE2"] = 3] = "AZURE2";
23
+ /** --- 微软 Azure 3 --- */
24
+ ESERVICE[ESERVICE["AZURE3"] = 4] = "AZURE3";
20
25
  })(ESERVICE || (ESERVICE = {}));
21
26
  /** --- openai 的连接对象 --- */
22
27
  const links = [];
23
28
  export class Ai {
24
29
  constructor(ctr, opt) {
30
+ this._ctr = ctr;
25
31
  const config = ctr.getPrototype('_config');
26
32
  const secretKey = opt.secretKey ?? config.ai?.[ESERVICE[opt.service]]?.skey ?? '';
27
33
  let endpoint;
@@ -38,6 +44,14 @@ export class Ai {
38
44
  endpoint = opt.endpoint ?? config.ai?.[ESERVICE[opt.service]]?.endpoint ?? '';
39
45
  break;
40
46
  }
47
+ case ESERVICE.AZURE2: {
48
+ endpoint = opt.endpoint ?? config.ai?.[ESERVICE[opt.service]]?.endpoint ?? '';
49
+ break;
50
+ }
51
+ case ESERVICE.AZURE3: {
52
+ endpoint = opt.endpoint ?? config.ai?.[ESERVICE[opt.service]]?.endpoint ?? '';
53
+ break;
54
+ }
41
55
  default: {
42
56
  endpoint = undefined;
43
57
  }
@@ -58,6 +72,17 @@ export class Ai {
58
72
  'link': this.link,
59
73
  });
60
74
  }
75
+ /** --- 创建对话 --- */
76
+ chat(body) {
77
+ try {
78
+ return this.link.chat.completions.create(body);
79
+ }
80
+ catch (e) {
81
+ lCore.debug('[AI][CHAT]', e);
82
+ lCore.log(this._ctr, `[AI][CHAT] ${e.message}`, '-error');
83
+ return false;
84
+ }
85
+ }
61
86
  }
62
87
  /**
63
88
  * --- 创建一个 AI 对象 ---
package/lib/core.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as http from 'http';
2
2
  import * as http2 from 'http2';
3
3
  import * as stream from 'stream';
4
+ import * as net from 'net';
4
5
  import * as kebab from '#kebab/index.js';
5
6
  import * as lResponse from '#kebab/lib/net/response.js';
6
7
  import * as sCtr from '#kebab/sys/ctr.js';
@@ -255,4 +256,4 @@ export declare function writeEventStreamHead(res: http2.Http2ServerResponse | ht
255
256
  * @param res 响应对象
256
257
  * @param data 数据
257
258
  */
258
- export declare function write(res: http2.Http2ServerResponse | http.ServerResponse, data: string | Buffer): void;
259
+ export declare function write(res: http2.Http2ServerResponse | http.ServerResponse | net.Socket, data: string | Buffer): void;
package/lib/core.js CHANGED
@@ -7,6 +7,7 @@ import * as cp from 'child_process';
7
7
  import * as http2 from 'http2';
8
8
  import * as stream from 'stream';
9
9
  import * as os from 'os';
10
+ import * as net from 'net';
10
11
  import * as kebab from '#kebab/index.js';
11
12
  import * as lTime from '#kebab/lib/time.js';
12
13
  import * as lFs from '#kebab/lib/fs.js';
@@ -821,6 +822,9 @@ export function write(res, data) {
821
822
  if (res instanceof http2.Http2ServerResponse) {
822
823
  res.write(data);
823
824
  }
825
+ else if (res instanceof net.Socket) {
826
+ res.write(data);
827
+ }
824
828
  else {
825
829
  res.write(data);
826
830
  }
package/lib/db.js CHANGED
@@ -156,36 +156,44 @@ export class Pool {
156
156
  }
157
157
  if (!conn) {
158
158
  // --- 没有找到合适的连接,创建一个 ---
159
- try {
160
- const link = await mysql2.createConnection({
161
- 'host': this._etc.host,
162
- 'port': this._etc.port,
163
- 'charset': this._etc.charset,
164
- 'database': this._etc.name,
165
- 'user': this._etc.user,
166
- 'password': this._etc.pwd,
167
- 'connectTimeout': 3_000,
168
- });
169
- const c = new Connection(this._etc, link);
170
- c.using();
171
- link.on('error', function (err) {
172
- c.setLost();
173
- if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
174
- lCore.debug('[DB][_getConnection][error]', err.message);
159
+ for (let i = 0; i < 3; ++i) {
160
+ try {
161
+ const link = await mysql2.createConnection({
162
+ 'host': this._etc.host,
163
+ 'port': this._etc.port,
164
+ 'charset': this._etc.charset,
165
+ 'database': this._etc.name,
166
+ 'user': this._etc.user,
167
+ 'password': this._etc.pwd,
168
+ 'connectTimeout': 3_000,
169
+ });
170
+ const c = new Connection(this._etc, link);
171
+ c.using();
172
+ link.on('error', function (err) {
173
+ c.setLost();
174
+ if (err.code !== 'PROTOCOL_CONNECTION_LOST') {
175
+ lCore.debug('[DB][_getConnection][error]', err);
176
+ lCore.log({}, '[DB][_getConnection][error] ' + err.message, '-error');
177
+ }
178
+ }).on('end', () => {
179
+ // lCore.debug('[DB][_getConnection] connection end.');
180
+ c.setLost();
181
+ }).on('close', () => {
182
+ c.setLost();
183
+ });
184
+ conn = c;
185
+ connections.push(conn);
186
+ }
187
+ catch (err) {
188
+ if (err.message === 'ETIMEOUT') {
189
+ lCore.debug('[DB][_getConnection][ETIMEOUT]', err);
190
+ continue;
175
191
  }
176
- }).on('end', () => {
177
- // lCore.debug('[DB][_getConnection] connection end.');
178
- c.setLost();
179
- }).on('close', () => {
180
- c.setLost();
181
- });
182
- conn = c;
183
- connections.push(conn);
184
- }
185
- catch (e) {
186
- const msg = '[DB][_getConnection] ' + e.message;
187
- lCore.debug(msg);
188
- lCore.log({}, msg, '-error');
192
+ const msg = `[DB][_getConnection] ${err.message}(${this._etc.host}:${this._etc.port})`;
193
+ lCore.debug(msg);
194
+ lCore.log({}, msg, '-error');
195
+ break;
196
+ }
189
197
  }
190
198
  }
191
199
  return conn;
package/lib/kv.js CHANGED
@@ -597,7 +597,7 @@ export class Pool {
597
597
  // --- 没有找到合适的连接,创建一个 ---
598
598
  const link = redis.createCommandClient({
599
599
  'host': this._etc.host,
600
- 'port': this._etc.port
600
+ 'port': this._etc.port,
601
601
  });
602
602
  // --- 开始连接 ---
603
603
  try {
@@ -622,7 +622,7 @@ export class Pool {
622
622
  link.on('error', function (err) {
623
623
  conn.setLost();
624
624
  // console.log(`--- redis [${conn._etc.host}:${conn._etc.port}] error ---`);
625
- lCore.debug('[KV][ERROR]', err.message);
625
+ lCore.debug('[KV][_getConnection][error]', err);
626
626
  }).on('end', () => {
627
627
  conn.setLost();
628
628
  }).on('close', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maiyunnet/kebab",
3
- "version": "3.2.30",
3
+ "version": "3.2.32",
4
4
  "description": "Simple, easy-to-use, and fully-featured Node.js framework that is ready-to-use out of the box.",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -24,13 +24,13 @@
24
24
  "@litert/http-client": "^1.1.2",
25
25
  "@litert/mime": "^0.1.3",
26
26
  "@litert/redis": "^3.0.5",
27
- "@litert/websocket": "^0.2.7",
27
+ "@litert/websocket": "^0.2.8",
28
28
  "@types/ssh2": "^1.15.5",
29
- "@zilliz/milvus2-sdk-node": "^2.6.3",
29
+ "@zilliz/milvus2-sdk-node": "^2.6.4",
30
30
  "ejs": "^3.1.10",
31
31
  "jszip": "^3.10.1",
32
32
  "mysql2": "^3.15.3",
33
- "openai": "^6.7.0",
33
+ "openai": "^6.8.0",
34
34
  "ssh2": "^1.17.0",
35
35
  "svg-captcha": "^1.4.0",
36
36
  "tencentcloud-sdk-nodejs": "^4.1.136"
@@ -38,7 +38,7 @@
38
38
  "devDependencies": {
39
39
  "@litert/eslint-plugin-rules": "^0.3.1",
40
40
  "@types/ejs": "^3.1.5",
41
- "@types/node": "^24.9.2",
41
+ "@types/node": "^24.10.0",
42
42
  "tsc-alias": "^1.8.16",
43
43
  "typescript": "^5.9.3"
44
44
  }
package/sys/cmd.js CHANGED
@@ -155,6 +155,12 @@ async function run() {
155
155
  config.ai['AZURE'] ??= {};
156
156
  config.ai['AZURE'].endpoint ??= '';
157
157
  config.ai['AZURE'].skey ??= '';
158
+ config.ai['AZURE2'] ??= {};
159
+ config.ai['AZURE2'].endpoint ??= '';
160
+ config.ai['AZURE2'].skey ??= '';
161
+ config.ai['AZURE3'] ??= {};
162
+ config.ai['AZURE3'].endpoint ??= '';
163
+ config.ai['AZURE3'].skey ??= '';
158
164
  // --- config - vector ---
159
165
  config.vector ??= {};
160
166
  config.vector.host ??= '127.0.0.1';
package/sys/mod.js CHANGED
@@ -45,7 +45,17 @@ class Rows {
45
45
  /**
46
46
  * --- 开启软更需要在表添加字段:ALTER TABLE `table_name` ADD `time_remove` bigint NOT NULL DEFAULT '0' AFTER `xxx`; ---
47
47
  */
48
- class Mod {
48
+ export default class Mod {
49
+ /** --- 表名 --- */
50
+ static { this._$table = ''; }
51
+ /** --- 主键字段名 --- */
52
+ static { this._$primary = 'id'; }
53
+ /** --- 设置后将由 _keyGenerator 函数生成唯一字段 --- */
54
+ static { this._$key = ''; }
55
+ /** --- 若使用 _$key 并且有多个 unique 索引,这里指定 _$key 的索引名 --- */
56
+ static { this._$index = ''; }
57
+ /** ---- 可开启软删软更新软新增 --- */
58
+ static { this._$soft = false; }
49
59
  /**
50
60
  * --- 构造函数 ---
51
61
  * @param ctr Ctr 对象
@@ -1427,14 +1437,3 @@ class Mod {
1427
1437
  return '';
1428
1438
  }
1429
1439
  }
1430
- /** --- 表名 --- */
1431
- Mod._$table = '';
1432
- /** --- 主键字段名 --- */
1433
- Mod._$primary = 'id';
1434
- /** --- 设置后将由 _keyGenerator 函数生成唯一字段 --- */
1435
- Mod._$key = '';
1436
- /** --- 若使用 _$key 并且有多个 unique 索引,这里指定 _$key 的索引名 --- */
1437
- Mod._$index = '';
1438
- /** ---- 可开启软删软更新软新增 --- */
1439
- Mod._$soft = false;
1440
- export default Mod;
@@ -3125,20 +3125,26 @@ rtn.push(reader.readBCDString());</pre>${JSON.stringify(rtn)}`);
3125
3125
  const echo = [`<pre>const ai = lAi.get(this, {
3126
3126
  'service': lAi.ESERVICE.ALICN,
3127
3127
  });</pre>`];
3128
- const completion = await ai.link.chat.completions.create({
3128
+ const completion = await ai.chat({
3129
3129
  'model': 'qwen-plus',
3130
3130
  'messages': [
3131
3131
  { 'role': 'system', 'content': 'You are Kebab, a friendly and knowledgeable assistant based on an open-source Node framework. You do not mention any model names or AI identity. You can chat casually, answer questions, and provide guidance naturally. Respond in a human-like, approachable manner, as if you are a helpful companion rather than a traditional AI assistant.' },
3132
3132
  { 'role': 'user', 'content': '你是谁?' },
3133
3133
  ],
3134
3134
  });
3135
- echo.push(`<pre>await ai.link.chat.completions.create({
3135
+ echo.push(`<pre>await ai.chat({
3136
3136
  'model': 'qwen-plus',
3137
3137
  'messages': [
3138
3138
  { 'role': 'system', 'content': 'You are Kebab, a friendly and knowledgeable assistant based on an open-source Node framework. You do not mention any model names or AI identity. You can chat casually, answer questions, and provide guidance naturally. Respond in a human-like, approachable manner, as if you are a helpful companion rather than a traditional AI assistant.' },
3139
3139
  { 'role': 'user', 'content': '你是谁?' },
3140
3140
  ],
3141
- });</pre>` + JSON.stringify(completion.choices[0].message.content));
3141
+ });</pre>`);
3142
+ if (completion) {
3143
+ echo.push(JSON.stringify(completion.choices[0].message.content));
3144
+ }
3145
+ else {
3146
+ echo.push('Failed');
3147
+ }
3142
3148
  return echo.join('') + '<br><br>' + this._getEnd();
3143
3149
  }
3144
3150
  aiStream() {
@@ -3210,7 +3216,7 @@ send.addEventListener('click', async () => {
3210
3216
  const ai = lAi.get(this, {
3211
3217
  'service': lAi.ESERVICE.ALICN,
3212
3218
  });
3213
- const stream = await ai.link.chat.completions.create({
3219
+ const stream = await ai.chat({
3214
3220
  'model': 'qwen-plus',
3215
3221
  'stream': true,
3216
3222
  'messages': [
@@ -3222,6 +3228,10 @@ send.addEventListener('click', async () => {
3222
3228
  },
3223
3229
  });
3224
3230
  lCore.writeEventStreamHead(this._res);
3231
+ if (!stream) {
3232
+ lCore.write(this._res, 'data: ' + 'Faild\n\n');
3233
+ return '';
3234
+ }
3225
3235
  for await (const chunk of stream) {
3226
3236
  if (!this._isAvail) {
3227
3237
  lCore.debug('Client disconnect');
@@ -15,14 +15,13 @@ CREATE TABLE `m_test` (
15
15
  UNIQUE INDEX `uname`(`name` ASC) USING BTREE
16
16
  ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;
17
17
  */
18
- class default_1 extends sMod {
18
+ export default class default_1 extends sMod {
19
+ static { this._$table = 'test'; }
20
+ static { this._$primary = 'id'; }
21
+ static { this._$key = 'token'; }
22
+ static { this._$index = 'utoken'; }
19
23
  /* eslint-enable */
20
24
  _keyGenerator() {
21
25
  return 'test_' + lCore.rand(0, 3).toString();
22
26
  }
23
27
  }
24
- default_1._$table = 'test';
25
- default_1._$primary = 'id';
26
- default_1._$key = 'token';
27
- default_1._$index = 'utoken';
28
- export default default_1;
@@ -8,8 +8,7 @@ CREATE TABLE `m_test_data_0` (
8
8
  PRIMARY KEY (`id`)
9
9
  ) ENGINE=InnoDB DEFAULT CHARSET=ascii COLLATE=ascii_bin;
10
10
  */
11
- class default_1 extends sMod {
11
+ export default class default_1 extends sMod {
12
+ static { this._$table = 'test_data'; }
13
+ static { this._$primary = 'id'; }
12
14
  }
13
- default_1._$table = 'test_data';
14
- default_1._$primary = 'id';
15
- export default default_1;