@maiyunnet/kebab 7.6.3 → 7.7.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.
- package/doc/kebab-rag.md +323 -244
- package/index.d.ts +1 -1
- package/index.js +1 -1
- package/lib/crypto.js +1 -0
- package/lib/fs.js +0 -5
- package/lib/net.d.ts +9 -9
- package/lib/net.js +19 -19
- package/lib/s3.d.ts +1 -0
- package/lib/text.d.ts +9 -0
- package/lib/text.js +27 -11
- package/lib/ws.js +13 -5
- package/package.json +12 -12
- package/sys/child.js +6 -1
- package/sys/ctr.d.ts +11 -2
- package/sys/ctr.js +8 -1
- package/sys/master.js +4 -4
- package/sys/mod.js +8 -2
- package/sys/route.js +2 -2
- package/www/example/ctr/agent.d.ts +8 -0
- package/www/example/ctr/agent.js +68 -0
- package/www/example/ctr/test.js +9 -4
- package/www/example/skill/weather.d.ts +15 -0
- package/www/example/skill/weather.js +36 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import * as sCtr from '#kebab/sys/ctr.js';
|
|
2
|
+
import * as lAi from '#kebab/lib/ai.js';
|
|
3
|
+
import * as lFs from '#kebab/lib/fs.js';
|
|
4
|
+
import * as lText from '#kebab/lib/text.js';
|
|
5
|
+
/** --- Skill 导入 --- */
|
|
6
|
+
import sWeather from '../skill/weather.js';
|
|
7
|
+
export default class extends sCtr.Ctr {
|
|
8
|
+
/**
|
|
9
|
+
* --- Agent 示例接口 ---
|
|
10
|
+
* --- 访问:/agent?q=上海天气怎么样? ---
|
|
11
|
+
*/
|
|
12
|
+
async index() {
|
|
13
|
+
// --- 1. 获取用户问题 ---
|
|
14
|
+
const userPrompt = this._get['q'] ?? '你好';
|
|
15
|
+
// --- 2. 加载系统提示词 ---
|
|
16
|
+
const systemPrompt = await lFs.getContent(`${this._config.const.rootPath}www/example/prompt/agent.txt`, 'utf8') ?? '';
|
|
17
|
+
// --- 3. 初始化 AI ---
|
|
18
|
+
const ai = lAi.get(this, {
|
|
19
|
+
'service': lAi.ESERVICE.ALICN,
|
|
20
|
+
});
|
|
21
|
+
// --- 4. 准备消息 ---
|
|
22
|
+
const messages = [
|
|
23
|
+
{ 'role': 'system', 'content': systemPrompt },
|
|
24
|
+
{ 'role': 'user', 'content': userPrompt },
|
|
25
|
+
];
|
|
26
|
+
// --- 5. 第一次对话,传入 Skills 定义 ---
|
|
27
|
+
const res = await ai.chat({
|
|
28
|
+
'model': 'qwen-plus',
|
|
29
|
+
'messages': messages,
|
|
30
|
+
'tools': [sWeather.definition],
|
|
31
|
+
});
|
|
32
|
+
if (!res) {
|
|
33
|
+
return '系统错误';
|
|
34
|
+
}
|
|
35
|
+
const message = res.choices[0].message;
|
|
36
|
+
// --- 6. 如果 AI 决定调用工具 ---
|
|
37
|
+
if (message.tool_calls && message.tool_calls.length > 0) {
|
|
38
|
+
messages.push(message);
|
|
39
|
+
for (const toolCall of message.tool_calls) {
|
|
40
|
+
if (toolCall.function.name === 'get_weather') {
|
|
41
|
+
// --- 解析参数并执行 ---
|
|
42
|
+
const args = lText.parseJson(toolCall.function.arguments);
|
|
43
|
+
if (args === false) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
const result = await sWeather.execute(args);
|
|
47
|
+
// --- 将结果反馈给消息流 ---
|
|
48
|
+
messages.push({
|
|
49
|
+
'role': 'tool',
|
|
50
|
+
'tool_call_id': toolCall.id,
|
|
51
|
+
'name': 'get_weather',
|
|
52
|
+
'content': result,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// --- 7. 第二次对话,获取最终文本回复 ---
|
|
57
|
+
const finalRes = await ai.chat({
|
|
58
|
+
'model': 'qwen-plus',
|
|
59
|
+
'messages': messages,
|
|
60
|
+
});
|
|
61
|
+
if (finalRes) {
|
|
62
|
+
return finalRes.choices[0].message.content ?? '未能生成回复';
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// --- 如果不需要工具调用,直接返回内容 ---
|
|
66
|
+
return message.content ?? '未能生成回复';
|
|
67
|
+
}
|
|
68
|
+
}
|
package/www/example/ctr/test.js
CHANGED
|
@@ -206,6 +206,7 @@ export default class extends sCtr.Ctr {
|
|
|
206
206
|
`<br><a href="${this._config.const.urlBase}test/ws-server?ac=rproxy2">View ws rproxy2 (handler)</a>`,
|
|
207
207
|
`<br><a href="${this._config.const.urlBase}test/ws-client">View "test/ws-client"</a>`,
|
|
208
208
|
`<br><a href="${this._config.const.urlBase}test/ws-client?ac=mproxy">View ws mproxy</a>`,
|
|
209
|
+
`<br><a href="${this._config.const.urlBase}test/ws-client?ac=hosts">View ws hosts</a>`,
|
|
209
210
|
'<br><br><b>Ssh:</b>',
|
|
210
211
|
`<br><br><a href="${this._config.const.urlBase}test/ssh?type=shell">View "test/ssh?type=shell"</a>`,
|
|
211
212
|
`<br><a href="${this._config.const.urlBase}test/ssh?type=sftp">View "test/ssh?type=sftp"</a>`,
|
|
@@ -2877,6 +2878,8 @@ const rtn = cons.migration(rows, newTables);</pre>`);
|
|
|
2877
2878
|
async text() {
|
|
2878
2879
|
const echo = `<pre>json_encode(lText.parseUrl('HtTp://uSer:pAss@sUBDom.TopdOm23.CoM:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe'))</pre>
|
|
2879
2880
|
${lText.htmlescape(JSON.stringify(lText.parseUrl('HtTp://uSer:pAss@sUBDom.TopdOm23.CoM:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe')))}
|
|
2881
|
+
<pre>json_encode(lText.parseUrl('HtTp://uSer:pAss@[::1]:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe'))</pre>
|
|
2882
|
+
${lText.htmlescape(JSON.stringify(lText.parseUrl('HtTp://uSer:pAss@[::1]:29819/Adm@xw2Ksiz/dszas?Mdi=KdiMs1&a=JDd#hehHe')))}
|
|
2880
2883
|
<pre>json_encode(lText.parseUrl('HtTp://uSer@sUBDom.TopdOm23.CoM/Admx%20w2Ksiz/dszas'))</pre>
|
|
2881
2884
|
${lText.htmlescape(JSON.stringify(lText.parseUrl('HtTp://uSer@sUBDom.TopdOm23.CoM/Admx%20w2Ksiz/dszas')))}
|
|
2882
2885
|
<pre>json_encode(lText.parseUrl('C:\\Windows\\Mi@sc'))</pre>
|
|
@@ -3064,16 +3067,18 @@ setInterval(() => {
|
|
|
3064
3067
|
return echo + '<br>' + this._getEnd();
|
|
3065
3068
|
}
|
|
3066
3069
|
async wsClient() {
|
|
3067
|
-
const
|
|
3070
|
+
const host = (this._get['ac'] === 'hosts') ? 'www.maiyun.net:' + this._config.const.hostport : this._config.const.host;
|
|
3071
|
+
const ws = await lWs.connect('ws' + (this._config.const.https ? 's' : '') + '://' + host + '/test', {
|
|
3068
3072
|
'mproxy': this._get['ac'] === 'mproxy' ? {
|
|
3069
3073
|
'url': `ws${this._config.const.https ? 's' : ''}://${this._config.const.host}/mproxy`,
|
|
3070
3074
|
'auth': '123456'
|
|
3071
|
-
} : undefined
|
|
3075
|
+
} : undefined,
|
|
3076
|
+
'hosts': (this._get['ac'] === 'hosts') ? '127.0.0.1' : undefined
|
|
3072
3077
|
});
|
|
3073
3078
|
if (!ws) {
|
|
3074
|
-
return '<div>Connect "ws' + (this._config.const.https ? 's' : '') + '://' +
|
|
3079
|
+
return '<div>Connect "ws' + (this._config.const.https ? 's' : '') + '://' + host + '/test" failed.</div><br>' + this._getEnd();
|
|
3075
3080
|
}
|
|
3076
|
-
const echo = ['<div>Connected "ws' + (this._config.const.https ? 's' : '') + '://' +
|
|
3081
|
+
const echo = ['<div>Connected "ws' + (this._config.const.https ? 's' : '') + '://' + host + '/test".</div>'];
|
|
3077
3082
|
// --- 绑定事件 ---
|
|
3078
3083
|
await new Promise((resolve) => {
|
|
3079
3084
|
(async () => {
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type * as openai from 'openai';
|
|
2
|
+
/**
|
|
3
|
+
* --- 获取天气预报的 Skill ---
|
|
4
|
+
*/
|
|
5
|
+
export default class {
|
|
6
|
+
/** --- Skill 的定义,供 AI 模型识别 --- */
|
|
7
|
+
static definition: openai.default.Chat.ChatCompletionTool;
|
|
8
|
+
/**
|
|
9
|
+
* --- 执行获取天气的逻辑 ---
|
|
10
|
+
* @param args AI 传过来的参数
|
|
11
|
+
*/
|
|
12
|
+
static execute(args: {
|
|
13
|
+
'city': string;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* --- 获取天气预报的 Skill ---
|
|
3
|
+
*/
|
|
4
|
+
export default class default_1 {
|
|
5
|
+
/** --- Skill 的定义,供 AI 模型识别 --- */
|
|
6
|
+
static definition = {
|
|
7
|
+
'type': 'function',
|
|
8
|
+
'function': {
|
|
9
|
+
'name': 'get_weather',
|
|
10
|
+
'description': '获取指定城市的天气信息',
|
|
11
|
+
'parameters': {
|
|
12
|
+
'type': 'object',
|
|
13
|
+
'properties': {
|
|
14
|
+
'city': {
|
|
15
|
+
'type': 'string',
|
|
16
|
+
'description': '城市名称,例如“上海”、“北京”',
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
'required': ['city'],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* --- 执行获取天气的逻辑 ---
|
|
25
|
+
* @param args AI 传过来的参数
|
|
26
|
+
*/
|
|
27
|
+
static async execute(args) {
|
|
28
|
+
// --- 这里是模拟获取天气的逻辑,实际开发中可以调用第三方 API ---
|
|
29
|
+
const weathers = {
|
|
30
|
+
'上海': '晴朗,25℃',
|
|
31
|
+
'北京': '多云,20℃',
|
|
32
|
+
'广州': '阵雨,28℃',
|
|
33
|
+
};
|
|
34
|
+
return weathers[args.city] ?? `抱歉,暂不支持查询 ${args.city} 的天气。`;
|
|
35
|
+
}
|
|
36
|
+
}
|