@maiyunnet/kebab 3.2.21 → 3.2.23

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.21";
8
+ export declare const VER = "3.2.23";
9
9
  /** --- 框架根目录,以 / 结尾 --- */
10
10
  export declare const ROOT_PATH: string;
11
11
  export declare const LIB_PATH: string;
@@ -51,6 +51,8 @@ export interface IConfig {
51
51
  'lang': IConfigLang;
52
52
  's3': Record<string, IConfigS3>;
53
53
  'turnstile': IConfigTurnstile;
54
+ 'ai': Record<string, IConfigAi>;
55
+ 'vector': IConfigVector;
54
56
  [key: string]: Record<string, Json>;
55
57
  }
56
58
  export interface IUrlParse {
@@ -80,6 +82,18 @@ export interface IConfigS3 {
80
82
  'region': string;
81
83
  'bucket': string;
82
84
  }
85
+ /** --- AI --- */
86
+ export interface IConfigAi {
87
+ 'skey': string;
88
+ }
89
+ /** --- 向量数据库 --- */
90
+ export interface IConfigVector {
91
+ 'host': string;
92
+ 'port': number;
93
+ 'name': string;
94
+ 'user': string;
95
+ 'pwd': string;
96
+ }
83
97
  /** --- 人机码信息 --- */
84
98
  export interface IConfigTurnstile {
85
99
  'CF': {
package/index.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * --- 本文件用来定义每个目录实体地址的常量 ---
7
7
  */
8
8
  /** --- 当前系统版本号 --- */
9
- export const VER = '3.2.21';
9
+ export const VER = '3.2.23';
10
10
  // --- 服务端用的路径 ---
11
11
  const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
12
12
  /** --- /xxx/xxx --- */
package/lib/ai.d.ts ADDED
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Project: Kebab, User: Tang Rukun, JianSuoQiYue
3
+ * Date: 2025-10-27 21:31:06
4
+ * Last: 2025-10-27 21:31:08
5
+ */
6
+ import * as openai from 'openai';
7
+ import * as sCtr from '#kebab/sys/ctr.js';
8
+ /**
9
+ * --- 参考:https://help.aliyun.com/zh/model-studio/what-is-model-studio ---
10
+ * --- 阿里模型:https://help.aliyun.com/zh/model-studio/getting-started/models ---
11
+ */
12
+ /** --- 服务商定义 --- */
13
+ export declare enum ESERVICE {
14
+ /** --- 阿里中国大陆区 --- */
15
+ 'ALICN' = 0,
16
+ /** --- 阿里国际区 --- */
17
+ 'ALIAS' = 1
18
+ }
19
+ /** --- 选项 --- */
20
+ export interface IOptions {
21
+ /** --- 服务商 ---- */
22
+ 'service': ESERVICE;
23
+ /** --- 密钥值 --- */
24
+ 'secretKey'?: string;
25
+ }
26
+ export declare class Ai {
27
+ /** --- openai 原生对象,建议只读 --- */
28
+ readonly link: openai.OpenAI;
29
+ constructor(ctr: sCtr.Ctr, opt: IOptions);
30
+ }
31
+ /**
32
+ * --- 创建一个 AI 对象 ---
33
+ * @param opt 选项
34
+ */
35
+ export declare function get(ctr: sCtr.Ctr, opt: IOptions): Ai;
package/lib/ai.js ADDED
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Project: Kebab, User: Tang Rukun, JianSuoQiYue
3
+ * Date: 2025-10-27 21:31:06
4
+ * Last: 2025-10-27 21:31:08
5
+ */
6
+ import * as openai from 'openai';
7
+ /**
8
+ * --- 参考:https://help.aliyun.com/zh/model-studio/what-is-model-studio ---
9
+ * --- 阿里模型:https://help.aliyun.com/zh/model-studio/getting-started/models ---
10
+ */
11
+ /** --- 服务商定义 --- */
12
+ export var ESERVICE;
13
+ (function (ESERVICE) {
14
+ /** --- 阿里中国大陆区 --- */
15
+ ESERVICE[ESERVICE["ALICN"] = 0] = "ALICN";
16
+ /** --- 阿里国际区 --- */
17
+ ESERVICE[ESERVICE["ALIAS"] = 1] = "ALIAS";
18
+ })(ESERVICE || (ESERVICE = {}));
19
+ /** --- openai 的连接对象 --- */
20
+ const links = [];
21
+ export class Ai {
22
+ constructor(ctr, opt) {
23
+ const config = ctr.getPrototype('_config');
24
+ const secretKey = opt.secretKey ?? config.ai?.[ESERVICE[opt.service]]?.skey ?? '';
25
+ let endpoint;
26
+ switch (opt.service) {
27
+ case ESERVICE.ALICN: {
28
+ endpoint = `https://dashscope.aliyuncs.com/compatible-mode/v1`;
29
+ break;
30
+ }
31
+ case ESERVICE.ALIAS: {
32
+ endpoint = `https://dashscope-intl.aliyuncs.com/compatible-mode/v1`;
33
+ break;
34
+ }
35
+ default: {
36
+ endpoint = undefined;
37
+ }
38
+ }
39
+ const token = `${opt.service}-${secretKey}`;
40
+ const link = links.find((item) => item.token === token);
41
+ if (link) {
42
+ this.link = link.link;
43
+ return;
44
+ }
45
+ this.link = new openai.OpenAI({
46
+ 'apiKey': secretKey,
47
+ 'baseURL': endpoint,
48
+ });
49
+ links.push({
50
+ 'token': token,
51
+ 'link': this.link,
52
+ });
53
+ }
54
+ }
55
+ /**
56
+ * --- 创建一个 AI 对象 ---
57
+ * @param opt 选项
58
+ */
59
+ export function get(ctr, opt) {
60
+ return new Ai(ctr, opt);
61
+ }
package/lib/kv.d.ts CHANGED
@@ -18,7 +18,7 @@ export interface IConnectionInfo {
18
18
  export declare class Pool {
19
19
  /** --- 当前 Pool 对象的 kv 连接信息 --- */
20
20
  private readonly _etc;
21
- constructor(ctr: sCtr.Ctr, etc?: kebab.IConfigKv);
21
+ constructor(ctr: sCtr.Ctr, etc?: IOptions);
22
22
  /**
23
23
  * --- 设定一个值 ---
24
24
  * @param key
@@ -467,8 +467,17 @@ export declare class Connection {
467
467
  * --- 获取 Kv Pool 对象 ---
468
468
  * @param etc 配置信息可留空
469
469
  */
470
- export declare function get(ctr: sCtr.Ctr, etc?: kebab.IConfigKv): Pool;
470
+ export declare function get(ctr: sCtr.Ctr, etc?: IOptions): Pool;
471
471
  /**
472
472
  * --- 获取当前连接池中所有连接的信息 ---
473
473
  */
474
474
  export declare function getConnectionList(): IConnectionInfo[];
475
+ /** --- 选项 --- */
476
+ export interface IOptions {
477
+ 'host'?: string;
478
+ 'port'?: number;
479
+ 'index'?: number;
480
+ 'pre'?: string;
481
+ 'user'?: string;
482
+ 'pwd'?: string;
483
+ }
package/lib/kv.js CHANGED
@@ -65,12 +65,15 @@ setTimeout(function () {
65
65
  }, 10_000);
66
66
  export class Pool {
67
67
  constructor(ctr, etc) {
68
- if (etc) {
69
- this._etc = etc;
70
- }
71
- else {
72
- this._etc = ctr.getPrototype('_config').kv;
73
- }
68
+ const configKv = ctr.getPrototype('_config').kv;
69
+ this._etc = {
70
+ 'host': etc?.host ?? configKv.host,
71
+ 'port': etc?.port ?? configKv.port,
72
+ 'index': etc?.index ?? configKv.index,
73
+ 'pre': etc?.pre ?? configKv.pre,
74
+ 'user': etc?.user ?? configKv.user,
75
+ 'pwd': etc?.pwd ?? configKv.pwd,
76
+ };
74
77
  }
75
78
  /**
76
79
  * --- 设定一个值 ---
package/lib/net.js CHANGED
@@ -155,7 +155,7 @@ export async function request(u, data, opt = {}) {
155
155
  const res = new lResponse.Response(null);
156
156
  res.error = {
157
157
  'name': 'Possible mProxy error',
158
- 'message': 'host not found'
158
+ 'message': 'host not found',
159
159
  };
160
160
  return res;
161
161
  }
@@ -165,7 +165,7 @@ export async function request(u, data, opt = {}) {
165
165
  const res = new lResponse.Response(null);
166
166
  res.error = {
167
167
  'name': 'hosts error',
168
- 'message': 'hosts param error'
168
+ 'message': 'hosts param error',
169
169
  };
170
170
  return res;
171
171
  }
@@ -176,7 +176,7 @@ export async function request(u, data, opt = {}) {
176
176
  'url': opt.mproxy ? opt.mproxy.url + (opt.mproxy.url.includes('?') ? '&' : '?') + lText.queryStringify({
177
177
  'url': u,
178
178
  'auth': opt.mproxy.auth,
179
- 'data': opt.mproxy.data ? lText.stringifyJson(opt.mproxy.data) : '{}'
179
+ 'data': opt.mproxy.data ? lText.stringifyJson(opt.mproxy.data) : '{}',
180
180
  }) : u,
181
181
  'method': method,
182
182
  'data': data,
package/lib/s3.d.ts CHANGED
@@ -7,7 +7,7 @@ import * as s3 from '@aws-sdk/client-s3';
7
7
  import * as stream from 'stream';
8
8
  import * as sCtr from '#kebab/sys/ctr.js';
9
9
  /**
10
- * s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
10
+ * --- s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/ ---
11
11
  */
12
12
  /** --- 服务商定义 --- */
13
13
  export declare enum ESERVICE {
package/lib/s3.js CHANGED
@@ -11,7 +11,7 @@ import * as lText from '#kebab/lib/text.js';
11
11
  /** --- s3 的连接对象 --- */
12
12
  const links = [];
13
13
  /**
14
- * s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/
14
+ * --- s3 文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/s3/ ---
15
15
  */
16
16
  /** --- 服务商定义 --- */
17
17
  export var ESERVICE;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * Date: 2025-10-28 15:18:41
4
+ * Last: 2025-10-28 15:18:44
5
+ */
6
+ import * as milvus from '@zilliz/milvus2-sdk-node';
7
+ import * as sCtr from '#kebab/sys/ctr.js';
8
+ /** --- 选项 --- */
9
+ export interface IOptions {
10
+ /** --- 主机地址 --- */
11
+ 'host'?: string;
12
+ /** --- 端口号 --- */
13
+ 'port'?: number;
14
+ /** --- 数据库名称 --- */
15
+ 'name'?: string;
16
+ /** --- 用户名 --- */
17
+ 'user'?: string;
18
+ /** --- 密码 --- */
19
+ 'pwd'?: string;
20
+ }
21
+ export declare class Vector {
22
+ /** --- milvus 原生对象,建议只读 --- */
23
+ readonly link: milvus.MilvusClient;
24
+ constructor(ctr: sCtr.Ctr, opt?: IOptions);
25
+ /** --- 搜索 --- */
26
+ seach(data: {
27
+ /** --- 表名 --- */
28
+ 'collection': string;
29
+ /** --- 查询的向量 --- */
30
+ 'data': number[];
31
+ /** --- 过滤器,如 word_count > 0 --- */
32
+ 'filter'?: string;
33
+ /** --- 返回的结果数量,默认为 20 --- */
34
+ 'limit'?: number;
35
+ /** --- 计算两个向量相似度的度量,默认 L2 --- */
36
+ 'metric'?: 'L2' | 'IP' | 'COSINE';
37
+ /** --- 输出的字段,如 ['book_id', 'word_count'],默认全部 --- */
38
+ 'fields'?: string[];
39
+ }): Promise<false | milvus.SearchResults<{
40
+ collection_name: string;
41
+ data: number[];
42
+ filter: string | undefined;
43
+ limit: number;
44
+ metric_type: "L2" | "IP" | "COSINE";
45
+ output_fields: string[] | undefined;
46
+ }>>;
47
+ }
48
+ /**
49
+ * --- 创建一个 Vector 对象 ---
50
+ * @param opt 选项
51
+ */
52
+ export declare function get(ctr: sCtr.Ctr, opt?: IOptions): Vector;
package/lib/vector.js ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Project: Kebab, User: JianSuoQiYue
3
+ * Date: 2025-10-28 15:18:41
4
+ * Last: 2025-10-28 15:18:44
5
+ */
6
+ import * as milvus from '@zilliz/milvus2-sdk-node';
7
+ /** --- milvus 的连接对象 --- */
8
+ const links = [];
9
+ export class Vector {
10
+ constructor(ctr, opt) {
11
+ const config = ctr.getPrototype('_config');
12
+ const host = opt?.host ?? config.vector?.host ?? '127.0.0.1';
13
+ const port = opt?.port ?? config.vector?.port ?? 19530;
14
+ const name = opt?.name ?? config.vector?.name ?? 'default';
15
+ const user = opt?.user ?? config.vector?.user ?? 'root';
16
+ const pwd = opt?.pwd ?? config.vector?.pwd ?? 'Milvue';
17
+ const token = `${host}-${port}-${name}-${user}`;
18
+ const link = links.find((item) => item.token === token);
19
+ if (link) {
20
+ this.link = link.link;
21
+ return;
22
+ }
23
+ this.link = new milvus.MilvusClient({
24
+ 'address': `${host}:${port}`,
25
+ 'ssl': false,
26
+ 'database': name,
27
+ 'username': user,
28
+ 'password': pwd,
29
+ });
30
+ links.push({
31
+ 'token': token,
32
+ 'link': this.link,
33
+ });
34
+ }
35
+ /** --- 搜索 --- */
36
+ // eslint-disable-next-line @typescript-eslint/explicit-function-return-type
37
+ async seach(data) {
38
+ try {
39
+ return await this.link.search({
40
+ 'collection_name': data.collection,
41
+ 'data': data.data,
42
+ 'filter': data.filter,
43
+ 'limit': data.limit ?? 20,
44
+ 'metric_type': data.metric ?? 'L2',
45
+ 'output_fields': data.fields,
46
+ });
47
+ }
48
+ catch {
49
+ return false;
50
+ }
51
+ }
52
+ }
53
+ /**
54
+ * --- 创建一个 Vector 对象 ---
55
+ * @param opt 选项
56
+ */
57
+ export function get(ctr, opt) {
58
+ return new Vector(ctr, opt);
59
+ }
package/lib/ws.js CHANGED
@@ -48,6 +48,9 @@ export class Socket {
48
48
  },
49
49
  end: () => {
50
50
  // --- nothing ---
51
+ },
52
+ timeout: () => {
53
+ // --- nothing ---
51
54
  }
52
55
  };
53
56
  if (!request || !socket) {
@@ -159,6 +162,8 @@ export class Socket {
159
162
  this._on.end();
160
163
  }).on('close', () => {
161
164
  this._on.close();
165
+ }).on('timeout', () => {
166
+ this._on.timeout();
162
167
  });
163
168
  }
164
169
  on(event, cb) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@maiyunnet/kebab",
3
- "version": "3.2.21",
3
+ "version": "3.2.23",
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": [
@@ -19,19 +19,21 @@
19
19
  "#kebab/*": "./*"
20
20
  },
21
21
  "dependencies": {
22
- "@aws-sdk/client-s3": "^3.913.0",
23
- "@aws-sdk/lib-storage": "^3.913.0",
22
+ "@aws-sdk/client-s3": "^3.917.0",
23
+ "@aws-sdk/lib-storage": "^3.917.0",
24
24
  "@litert/http-client": "^1.1.2",
25
25
  "@litert/mime": "^0.1.3",
26
26
  "@litert/redis": "^3.0.5",
27
27
  "@litert/websocket": "^0.2.7",
28
28
  "@types/ssh2": "^1.15.5",
29
+ "@zilliz/milvus2-sdk-node": "^2.6.2",
29
30
  "ejs": "^3.1.10",
30
31
  "jszip": "^3.10.1",
31
- "mysql2": "^3.15.2",
32
+ "mysql2": "^3.15.3",
33
+ "openai": "^6.7.0",
32
34
  "ssh2": "^1.17.0",
33
35
  "svg-captcha": "^1.4.0",
34
- "tencentcloud-sdk-nodejs": "^4.1.133"
36
+ "tencentcloud-sdk-nodejs": "^4.1.135"
35
37
  },
36
38
  "devDependencies": {
37
39
  "@litert/eslint-plugin-rules": "^0.3.1",
package/sys/child.js CHANGED
@@ -554,7 +554,7 @@ process.on('message', function (msg) {
554
554
  str.push(key + ':' + linkCount[key].toString());
555
555
  }
556
556
  lCore.display(`[CHILD] Worker ${process.pid} busy: ${str.join(',')}.`);
557
- lCore.log({}, `[CHILD] Worker ${process.pid} busy: ${str.join(',')}.`, '-error');
557
+ lCore.log({}, `[CHILD] Worker ${process.pid} busy: ${str.join(',')}.`, '-warning');
558
558
  await lCore.sleep(30_000);
559
559
  waiting += 30_000;
560
560
  if (waiting > 3600_000) {
package/sys/cmd.js CHANGED
@@ -146,6 +146,19 @@ async function run() {
146
146
  config.turnstile['TENCENT'].skey ??= '';
147
147
  config.turnstile['TENCENT'].aid ??= '';
148
148
  config.turnstile['TENCENT'].akey ??= '';
149
+ // --- config - ai ---
150
+ config.ai ??= {};
151
+ config.ai['ALICN'] ??= {};
152
+ config.ai['ALICN'].skey ??= '';
153
+ config.ai['ALIAS'] ??= {};
154
+ config.ai['ALIAS'].skey ??= '';
155
+ // --- config - vector ---
156
+ config.vector ??= {};
157
+ config.vector.host ??= '127.0.0.1';
158
+ config.vector.port ??= 19530;
159
+ config.vector.name ??= 'default';
160
+ config.vector.user ??= 'root';
161
+ config.vector.pwd ??= 'Milvue';
149
162
  // --- 保存 config.json ---
150
163
  if (!await lFs.putContent(kebab.CONF_CWD + 'config.json', lText.stringifyJson(config, 4))) {
151
164
  lCore.display('KEBAB', 'CREATE', 'FILE', kebab.CONF_CWD + 'config.json', '[FAILED]');
@@ -49,6 +49,7 @@ export default class extends sCtr.Ctr {
49
49
  crypto(): Promise<string>;
50
50
  db(): Promise<kebab.Json>;
51
51
  private _dbTable;
52
+ vector(): Promise<any>;
52
53
  kv(): Promise<kebab.Json>;
53
54
  net(): Promise<string>;
54
55
  netPipe(): Promise<kebab.Json>;
@@ -72,6 +73,7 @@ export default class extends sCtr.Ctr {
72
73
  netHosts(): Promise<string>;
73
74
  netMproxy(): Promise<string | boolean>;
74
75
  netMproxy1(): Promise<string | boolean>;
76
+ netMproxy2(): any[];
75
77
  netFilterheaders(): string;
76
78
  scan(): Promise<kebab.Json>;
77
79
  scan1(): Promise<kebab.Json>;
@@ -96,6 +98,7 @@ export default class extends sCtr.Ctr {
96
98
  buffer(): string;
97
99
  lan(): Promise<string>;
98
100
  cron(): Promise<string>;
101
+ ai(): Promise<string>;
99
102
  /**
100
103
  * --- END ---
101
104
  */
@@ -3,6 +3,7 @@ import * as kebab from '#kebab/index.js';
3
3
  import * as lCore from '#kebab/lib/core.js';
4
4
  import * as lNet from '#kebab/lib/net.js';
5
5
  import * as lDb from '#kebab/lib/db.js';
6
+ import * as lVector from '#kebab/lib/vector.js';
6
7
  import * as lFs from '#kebab/lib/fs.js';
7
8
  import * as lText from '#kebab/lib/text.js';
8
9
  import * as lCrypto from '#kebab/lib/crypto.js';
@@ -20,6 +21,7 @@ import * as lZip from '#kebab/lib/zip.js';
20
21
  import * as lBuffer from '#kebab/lib/buffer.js';
21
22
  import * as lLan from '#kebab/lib/lan.js';
22
23
  import * as lCron from '#kebab/lib/cron.js';
24
+ import * as lAi from '#kebab/lib/ai.js';
23
25
  import * as sCtr from '#kebab/sys/ctr.js';
24
26
  // --- mod ---
25
27
  import mTest from '../mod/test.js';
@@ -124,9 +126,8 @@ export default class extends sCtr.Ctr {
124
126
  `<br><a href="${this._config.const.urlBase}test/mod-split">View "test/mod-split"</a>`,
125
127
  `<br><a href="${this._config.const.urlBase}test/mod-insert">View "test/mod-insert"</a>`,
126
128
  '<br><br><b>Library test:</b>',
127
- '<br><br><b>Captcha:</b>',
128
- `<br><br><a href="${this._config.const.urlBase}test/captcha-fastbuild">View "test/captcha-fastbuild"</a>`,
129
- `<br><a href="${this._config.const.urlBase}test/captcha-base64">View "test/captcha-base64"</a>`,
129
+ `<br><br><b>Ai:</b>`,
130
+ `<br><br><a href="${this._config.const.urlBase}test/ai">View "test/ai"</a>`,
130
131
  '<br><br><b>Core:</b>',
131
132
  `<br><br><a href="${this._config.const.urlBase}test/core-random">View "test/core-random"</a>`,
132
133
  `<br><a href="${this._config.const.urlBase}test/core-rand">View "test/core-rand"</a>`,
@@ -144,6 +145,8 @@ export default class extends sCtr.Ctr {
144
145
  `<br><br><a href="${this._config.const.urlBase}test/crypto">View "test/crypto"</a>`,
145
146
  '<br><br><b>Db:</b>',
146
147
  `<br><br><a href="${this._config.const.urlBase}test/db">View "test/db"</a>`,
148
+ `<br><br><b>Vector:</b>`,
149
+ `<br><br><a href="${this._config.const.urlBase}test/vector">View "test/vector"</a>`,
147
150
  '<br><br><b>Kv:</b>',
148
151
  `<br><br><a href="${this._config.const.urlBase}test/kv">View "test/kv"</a>`,
149
152
  '<br><br><b>Net:</b>',
@@ -171,10 +174,9 @@ export default class extends sCtr.Ctr {
171
174
  `<br><a href="${this._config.const.urlBase}test/session?s=kv">View "test/session?s=kv"</a>`,
172
175
  `<br><a href="${this._config.const.urlBase}test/session?s=db&auth=1">View "test/session?s=db&auth=1" Header Authorization</a>`,
173
176
  `<br><a href="${this._config.const.urlBase}test/session?s=kv&auth=1">View "test/session?s=kv&auth=1" Header Authorization</a>`,
174
- '<br><br><b>Jwt:</b>',
175
- `<br><br><a href="${this._config.const.urlBase}test/jwt">View "test/jwt"</a>`,
176
- `<br><a href="${this._config.const.urlBase}test/jwt?type=kv">View "test/jwt?type=kv"</a>`,
177
- `<br><a href="${this._config.const.urlBase}test/jwt?type=auth">View "test/jwt?type=auth" Header Authorization</a>`,
177
+ '<br><br><b>Captcha:</b>',
178
+ `<br><br><a href="${this._config.const.urlBase}test/captcha-fastbuild">View "test/captcha-fastbuild"</a>`,
179
+ `<br><a href="${this._config.const.urlBase}test/captcha-base64">View "test/captcha-base64"</a>`,
178
180
  '<br><br><b>Sql:</b>',
179
181
  `<br><br><a href="${this._config.const.urlBase}test/sql?type=insert">View "test/sql?type=insert"</a>`,
180
182
  `<br><a href="${this._config.const.urlBase}test/sql?type=select">View "test/sql?type=select"</a>`,
@@ -184,6 +186,10 @@ export default class extends sCtr.Ctr {
184
186
  `<br><a href="${this._config.const.urlBase}test/sql?type=having">View "test/sql?type=having"</a>`,
185
187
  `<br><a href="${this._config.const.urlBase}test/sql?type=by">View "test/sql?type=by"</a>`,
186
188
  `<br><a href="${this._config.const.urlBase}test/sql?type=field">View "test/sql?type=field"</a>`,
189
+ '<br><br><b>Jwt:</b>',
190
+ `<br><br><a href="${this._config.const.urlBase}test/jwt">View "test/jwt"</a>`,
191
+ `<br><a href="${this._config.const.urlBase}test/jwt?type=kv">View "test/jwt?type=kv"</a>`,
192
+ `<br><a href="${this._config.const.urlBase}test/jwt?type=auth">View "test/jwt?type=auth" Header Authorization</a>`,
187
193
  '<br><br><b>Consistent:</b>',
188
194
  `<br><br><a href="${this._config.const.urlBase}test/consistent-hash">View "test/consistent-hash"</a>`,
189
195
  `<br><a href="${this._config.const.urlBase}test/consistent-distributed">View "test/consistent-distributed"</a>`,
@@ -1334,6 +1340,20 @@ exec: ${JSON.stringify(exec)}<br><br>`);
1334
1340
  }
1335
1341
  echo.push('</table>');
1336
1342
  }
1343
+ async vector() {
1344
+ const vector = lVector.get(this);
1345
+ const res = await vector.seach({
1346
+ 'collection': 'oas_wiki',
1347
+ 'metric': 'COSINE',
1348
+ 'data': [0.4100031323819555, 0.7188991736586672, 0.32890290245747833, 0.9187961849628559, 0.023142186415922916, 0.45239563148580797, 0.23537591588175988, 0.6848990771759962, 0.9865744633216178, 0.8239142304110896, 0.997768380245414, 0.3012929412655765, 0.13731236076734943, 0.5126131685642945, 0.9806290097015617, 0.1870468071764284, 0.17178642706602143, 0.4016660911946244, 0.15484433366942607, 0.29719222215610386, 0.3103748731148619, 0.6892950176658315, 0.01785695346759608, 0.08539564964986557, 0.2655959514380064, 0.9964617086704073, 0.2838371937684081, 0.14987010598298633, 0.6228479079557896, 0.8080833516756243, 0.15438562173495285, 0.5078008662168574, 0.27262149922940804, 0.23104911473240675, 0.6266656488428926, 0.8553958245035254, 0.11699454830789868, 0.2300336351244865, 0.3042943975707315, 0.20182231286864427, 0.14334825938359863, 0.5272057735967806, 0.6568390179350452, 0.11388912236667226, 0.4916225414998463, 0.4913046496135085, 0.6301252401085475, 0.26051075673874036, 0.17023441587522825, 0.371755148312803, 0.5831318953846139, 0.9756820442368113, 0.6818893859710211, 0.5188330204766185, 0.7868335112863099, 0.7263293211859105, 0.15777067513918275, 0.25071428052177835, 0.9055952502390328, 0.39066574162485046, 0.6694768856781026, 0.904527206408617, 0.5359679189729842, 0.42923033393177423, 0.6959492373261136, 0.4721197667950616, 0.6861043448179791, 0.05188999799541438, 0.7346607591003518, 0.1574483630625012, 0.9141756884547747, 0.9116789303557802, 0.7609450526832306, 0.7763073356227885, 0.7334996162535046, 0.8036447394427264, 0.21291521237560262, 0.4628513517221038, 0.005054981316060525, 0.6289756103407573, 0.9376033918403373, 0.79713161153396, 0.1795021378890418, 0.32421299215073773, 0.5585715705291334, 0.1964507020528392, 0.9170965358836494, 0.44199069294404825, 0.46924875851341463, 0.005915168915280544, 0.4519648598811945, 0.7817208441823769, 0.39630447274483926, 0.874803477246406, 0.02593537985516514, 0.03494415508402371, 0.6948556600612117, 0.02531235612016558, 0.3252859275909026, 0.6124602304575255, 0.6662991517754546, 0.054786469959723805, 0.09541281916656552, 0.047971618444194286, 0.9888851535738363, 0.09923862294731634, 0.37389883211204245, 0.0510449762242422, 0.5140187522339308, 0.9165108670272317, 0.473682888066292, 0.7553395418192084, 0.48450479101753663, 0.22080081972551513, 0.8461012374988566, 0.32711442729081885, 0.46740436391036244, 0.9330234279632854, 0.7456194346850014, 0.8575560505025164, 0.2617623984893922, 0.6418053194775086, 0.607749877895083, 0.2176063100000032, 0.5366633111896186, 0.9689538808794083, 0.8226310778269623, 0.4813948057818185]
1349
+ });
1350
+ const echo = [`<pre>const res = await vector.seach({
1351
+ 'collection': 'oas_wiki',
1352
+ 'metric': 'COSINE',
1353
+ 'data': [0.4100031323819555, 0.7188991736586672, 0.32890290245747833, ...]
1354
+ });</pre>res:<pre>${JSON.stringify(res, null, 4)}</pre>`];
1355
+ return echo.join('') + '<br>' + this._getEnd();
1356
+ }
1337
1357
  async kv() {
1338
1358
  const kv = lKv.get(this);
1339
1359
  if (!await kv.ping()) {
@@ -1799,14 +1819,16 @@ error: <pre>${JSON.stringify(res.error, null, 4)}</pre>`);
1799
1819
  }
1800
1820
  async netMproxy() {
1801
1821
  const echo = [];
1802
- const res = await lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1822
+ const res = await lNet.postJson(this._internalUrl + 'test/net-mproxy2', {
1823
+ 'abc': 'ok',
1824
+ }, {
1803
1825
  'mproxy': {
1804
1826
  'url': this._internalUrl + 'test/net-mproxy1',
1805
1827
  'auth': '123456',
1806
1828
  'data': { 'test': '123' },
1807
1829
  }
1808
1830
  });
1809
- echo.push(`<pre>lNet.get('https://cdn.jsdelivr.net/npm/deskrt@2.0.10/package.json', {
1831
+ echo.push(`<pre>lNet.get('${this._internalUrl}test/net-mproxy2', {
1810
1832
  'mproxy': {
1811
1833
  'url': '${this._internalUrl}test/net-mproxy1',
1812
1834
  'auth': '123456',
@@ -1827,6 +1849,11 @@ error: <pre>${JSON.stringify(res.error, null, 4)}</pre>`);
1827
1849
  }
1828
1850
  return 'Nothing(' + rtn + ')';
1829
1851
  }
1852
+ netMproxy2() {
1853
+ return [1, {
1854
+ 'data': this._post,
1855
+ }];
1856
+ }
1830
1857
  netFilterheaders() {
1831
1858
  const echo = [];
1832
1859
  const headers = {
@@ -3027,6 +3054,29 @@ rtn.push(reader.readBCDString());</pre>${JSON.stringify(rtn)}`);
3027
3054
  <pre>${JSON.stringify(lCron.getRegulars(), null, 4)}</pre>`);
3028
3055
  return echo.join('') + '<br>' + this._getEnd();
3029
3056
  }
3057
+ async ai() {
3058
+ const ai = lAi.get(this, {
3059
+ 'service': lAi.ESERVICE.ALICN,
3060
+ });
3061
+ const echo = [`<pre>const ai = lAi.get(this, {
3062
+ 'service': lAi.ESERVICE.ALICN,
3063
+ });</pre>`];
3064
+ const completion = await ai.link.chat.completions.create({
3065
+ 'model': 'qwen-plus',
3066
+ 'messages': [
3067
+ { '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.' },
3068
+ { 'role': 'user', 'content': '你是谁?' }
3069
+ ],
3070
+ });
3071
+ echo.push(`<pre>await ai.link.chat.completions.create({
3072
+ 'model': 'qwen-plus',
3073
+ 'messages': [
3074
+ { '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.' },
3075
+ { 'role': 'user', 'content': '你是谁?' }
3076
+ ],
3077
+ });</pre>` + JSON.stringify(completion.choices[0].message.content));
3078
+ return echo.join('') + '<br><br>' + this._getEnd();
3079
+ }
3030
3080
  /**
3031
3081
  * --- END ---
3032
3082
  */