@dcrays/dcgchat-test 0.1.9 → 0.1.10
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/README.md +83 -83
- package/index.ts +24 -24
- package/openclaw.plugin.json +9 -9
- package/package.json +58 -58
- package/src/api.ts +62 -62
- package/src/bot.ts +272 -272
- package/src/channel.ts +192 -192
- package/src/connection.ts +11 -11
- package/src/log.ts +46 -46
- package/src/monitor.ts +191 -190
- package/src/oss.ts +72 -72
- package/src/request.ts +194 -194
- package/src/runtime.ts +38 -38
- package/src/skill.ts +110 -110
- package/src/tool.ts +74 -64
- package/src/types.ts +103 -103
- package/src/userInfo.ts +97 -97
package/src/skill.ts
CHANGED
|
@@ -1,111 +1,111 @@
|
|
|
1
|
-
/** skill utils */
|
|
2
|
-
import axios from 'axios';
|
|
3
|
-
/** @ts-ignore */
|
|
4
|
-
import unzipper from 'unzipper';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import { logDcgchat } from './log.js';
|
|
8
|
-
import { getWorkspaceDir } from './runtime.js';
|
|
9
|
-
import { getWsConnection } from './connection.js';
|
|
10
|
-
|
|
11
|
-
type ISkillParams = {
|
|
12
|
-
path: string;
|
|
13
|
-
code: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function sendEvent(msgContent: Record<string, any>) {
|
|
17
|
-
const ws = getWsConnection()
|
|
18
|
-
if (ws?.readyState === WebSocket.OPEN) {
|
|
19
|
-
ws.send(JSON.stringify({
|
|
20
|
-
messageType: "openclaw_bot_event",
|
|
21
|
-
source: "client",
|
|
22
|
-
content: msgContent
|
|
23
|
-
}));
|
|
24
|
-
logDcgchat.info(`技能安装: ${JSON.stringify(msgContent)}`);
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export async function installSkill(params: ISkillParams, msgContent: Record<string, any>) {
|
|
30
|
-
const { path: cdnUrl, code } = params;
|
|
31
|
-
const workspacePath = getWorkspaceDir();
|
|
32
|
-
|
|
33
|
-
const skillDir = path.join(workspacePath, 'skills', code);
|
|
34
|
-
|
|
35
|
-
// 确保 skills 目录存在
|
|
36
|
-
const skillsDir = path.join(workspacePath, 'skills');
|
|
37
|
-
if (!fs.existsSync(skillsDir)) {
|
|
38
|
-
fs.mkdirSync(skillsDir, { recursive: true });
|
|
39
|
-
}
|
|
40
|
-
// 如果目标目录已存在,先删除
|
|
41
|
-
if (fs.existsSync(skillDir)) {
|
|
42
|
-
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
try {
|
|
46
|
-
// 下载 zip 文件
|
|
47
|
-
const response = await axios({
|
|
48
|
-
method: 'get',
|
|
49
|
-
url: cdnUrl,
|
|
50
|
-
responseType: 'stream'
|
|
51
|
-
});
|
|
52
|
-
// 创建目标目录
|
|
53
|
-
fs.mkdirSync(skillDir, { recursive: true });
|
|
54
|
-
// 解压文件到目标目录,跳过顶层文件夹
|
|
55
|
-
await new Promise((resolve, reject) => {
|
|
56
|
-
response.data
|
|
57
|
-
.pipe(unzipper.Parse())
|
|
58
|
-
.on('entry', (entry: any) => {
|
|
59
|
-
const entryPath = entry.path;
|
|
60
|
-
// 跳过顶层目录,只处理子文件和文件夹
|
|
61
|
-
const pathParts = entryPath.split('/');
|
|
62
|
-
if (pathParts.length > 1) {
|
|
63
|
-
// 移除第一级目录
|
|
64
|
-
const newPath = pathParts.slice(1).join('/');
|
|
65
|
-
const targetPath = path.join(skillDir, newPath);
|
|
66
|
-
|
|
67
|
-
if (entry.type === 'Directory') {
|
|
68
|
-
fs.mkdirSync(targetPath, { recursive: true });
|
|
69
|
-
entry.autodrain();
|
|
70
|
-
} else {
|
|
71
|
-
// 确保父目录存在
|
|
72
|
-
const parentDir = path.dirname(targetPath);
|
|
73
|
-
if (!fs.existsSync(parentDir)) {
|
|
74
|
-
fs.mkdirSync(parentDir, { recursive: true });
|
|
75
|
-
}
|
|
76
|
-
entry.pipe(fs.createWriteStream(targetPath));
|
|
77
|
-
}
|
|
78
|
-
} else {
|
|
79
|
-
entry.autodrain();
|
|
80
|
-
}
|
|
81
|
-
})
|
|
82
|
-
.on('close', resolve)
|
|
83
|
-
.on('error', reject);
|
|
84
|
-
});
|
|
85
|
-
sendEvent({ ...msgContent, status: 'ok' })
|
|
86
|
-
} catch (error) {
|
|
87
|
-
// 如果安装失败,清理目录
|
|
88
|
-
if (fs.existsSync(skillDir)) {
|
|
89
|
-
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
90
|
-
}
|
|
91
|
-
sendEvent({ ...msgContent, status: 'fail' })
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export function uninstallSkill(params: Omit<ISkillParams, 'path'>, msgContent: Record<string, any>) {
|
|
96
|
-
const { code } = params;
|
|
97
|
-
|
|
98
|
-
const workspacePath = getWorkspaceDir();
|
|
99
|
-
if (!workspacePath) {
|
|
100
|
-
throw new Error('未找到工作区路径');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const skillDir = path.join(workspacePath, 'skills', code);
|
|
104
|
-
|
|
105
|
-
if (fs.existsSync(skillDir)) {
|
|
106
|
-
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
107
|
-
sendEvent({ ...msgContent, status: 'ok' })
|
|
108
|
-
} else {
|
|
109
|
-
sendEvent({ ...msgContent, status: 'fail' })
|
|
110
|
-
}
|
|
1
|
+
/** skill utils */
|
|
2
|
+
import axios from 'axios';
|
|
3
|
+
/** @ts-ignore */
|
|
4
|
+
import unzipper from 'unzipper';
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { logDcgchat } from './log.js';
|
|
8
|
+
import { getWorkspaceDir } from './runtime.js';
|
|
9
|
+
import { getWsConnection } from './connection.js';
|
|
10
|
+
|
|
11
|
+
type ISkillParams = {
|
|
12
|
+
path: string;
|
|
13
|
+
code: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function sendEvent(msgContent: Record<string, any>) {
|
|
17
|
+
const ws = getWsConnection()
|
|
18
|
+
if (ws?.readyState === WebSocket.OPEN) {
|
|
19
|
+
ws.send(JSON.stringify({
|
|
20
|
+
messageType: "openclaw_bot_event",
|
|
21
|
+
source: "client",
|
|
22
|
+
content: msgContent
|
|
23
|
+
}));
|
|
24
|
+
logDcgchat.info(`技能安装: ${JSON.stringify(msgContent)}`);
|
|
25
|
+
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function installSkill(params: ISkillParams, msgContent: Record<string, any>) {
|
|
30
|
+
const { path: cdnUrl, code } = params;
|
|
31
|
+
const workspacePath = getWorkspaceDir();
|
|
32
|
+
|
|
33
|
+
const skillDir = path.join(workspacePath, 'skills', code);
|
|
34
|
+
|
|
35
|
+
// 确保 skills 目录存在
|
|
36
|
+
const skillsDir = path.join(workspacePath, 'skills');
|
|
37
|
+
if (!fs.existsSync(skillsDir)) {
|
|
38
|
+
fs.mkdirSync(skillsDir, { recursive: true });
|
|
39
|
+
}
|
|
40
|
+
// 如果目标目录已存在,先删除
|
|
41
|
+
if (fs.existsSync(skillDir)) {
|
|
42
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// 下载 zip 文件
|
|
47
|
+
const response = await axios({
|
|
48
|
+
method: 'get',
|
|
49
|
+
url: cdnUrl,
|
|
50
|
+
responseType: 'stream'
|
|
51
|
+
});
|
|
52
|
+
// 创建目标目录
|
|
53
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
54
|
+
// 解压文件到目标目录,跳过顶层文件夹
|
|
55
|
+
await new Promise((resolve, reject) => {
|
|
56
|
+
response.data
|
|
57
|
+
.pipe(unzipper.Parse())
|
|
58
|
+
.on('entry', (entry: any) => {
|
|
59
|
+
const entryPath = entry.path;
|
|
60
|
+
// 跳过顶层目录,只处理子文件和文件夹
|
|
61
|
+
const pathParts = entryPath.split('/');
|
|
62
|
+
if (pathParts.length > 1) {
|
|
63
|
+
// 移除第一级目录
|
|
64
|
+
const newPath = pathParts.slice(1).join('/');
|
|
65
|
+
const targetPath = path.join(skillDir, newPath);
|
|
66
|
+
|
|
67
|
+
if (entry.type === 'Directory') {
|
|
68
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
69
|
+
entry.autodrain();
|
|
70
|
+
} else {
|
|
71
|
+
// 确保父目录存在
|
|
72
|
+
const parentDir = path.dirname(targetPath);
|
|
73
|
+
if (!fs.existsSync(parentDir)) {
|
|
74
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
entry.pipe(fs.createWriteStream(targetPath));
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
entry.autodrain();
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
.on('close', resolve)
|
|
83
|
+
.on('error', reject);
|
|
84
|
+
});
|
|
85
|
+
sendEvent({ ...msgContent, status: 'ok' })
|
|
86
|
+
} catch (error) {
|
|
87
|
+
// 如果安装失败,清理目录
|
|
88
|
+
if (fs.existsSync(skillDir)) {
|
|
89
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
90
|
+
}
|
|
91
|
+
sendEvent({ ...msgContent, status: 'fail' })
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function uninstallSkill(params: Omit<ISkillParams, 'path'>, msgContent: Record<string, any>) {
|
|
96
|
+
const { code } = params;
|
|
97
|
+
|
|
98
|
+
const workspacePath = getWorkspaceDir();
|
|
99
|
+
if (!workspacePath) {
|
|
100
|
+
throw new Error('未找到工作区路径');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const skillDir = path.join(workspacePath, 'skills', code);
|
|
104
|
+
|
|
105
|
+
if (fs.existsSync(skillDir)) {
|
|
106
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
107
|
+
sendEvent({ ...msgContent, status: 'ok' })
|
|
108
|
+
} else {
|
|
109
|
+
sendEvent({ ...msgContent, status: 'fail' })
|
|
110
|
+
}
|
|
111
111
|
}
|
package/src/tool.ts
CHANGED
|
@@ -1,65 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
3
|
-
import { getWsConnection } from "./connection.js";
|
|
4
|
-
import { logDcgchat } from "./log.js";
|
|
5
|
-
|
|
6
|
-
let msgParams = {} as {
|
|
7
|
-
userId: number;
|
|
8
|
-
token: string
|
|
9
|
-
sessionId: string
|
|
10
|
-
messageId: string
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
1
|
+
|
|
2
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
3
|
+
import { getWsConnection } from "./connection.js";
|
|
4
|
+
import { logDcgchat } from "./log.js";
|
|
5
|
+
|
|
6
|
+
let msgParams = {} as {
|
|
7
|
+
userId: number;
|
|
8
|
+
token: string
|
|
9
|
+
sessionId: string
|
|
10
|
+
messageId: string
|
|
11
|
+
}
|
|
12
|
+
let msgStatus: 'running' | 'finished' | '' = '';
|
|
13
|
+
export function setMsgParams(params: any) {
|
|
14
|
+
msgParams = params;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function getMsgParams() {
|
|
18
|
+
return msgParams;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function setMsgStatus(status: 'running' | 'finished' | '') {
|
|
22
|
+
msgStatus = status;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function getMsgStatus() {
|
|
26
|
+
return msgStatus;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function monitoringToolMessage(api: OpenClawPluginApi) {
|
|
30
|
+
api.on("after_tool_call", (event, payload) => {
|
|
31
|
+
const ws = getWsConnection()
|
|
32
|
+
const params = getMsgParams();
|
|
33
|
+
const status = getMsgStatus();
|
|
34
|
+
//
|
|
35
|
+
if (ws?.readyState === WebSocket.OPEN && status === 'running') {
|
|
36
|
+
ws.send(JSON.stringify({
|
|
37
|
+
messageType: "openclaw_bot_chat",
|
|
38
|
+
_userId: params?.userId,
|
|
39
|
+
source: "client",
|
|
40
|
+
content: {
|
|
41
|
+
bot_token: params?.token,
|
|
42
|
+
response: 'all_finished',
|
|
43
|
+
session_id:params?.sessionId,
|
|
44
|
+
message_id: params?.messageId || Date.now().toString()
|
|
45
|
+
},
|
|
46
|
+
}));
|
|
47
|
+
ws.send(JSON.stringify({
|
|
48
|
+
messageType: "openclaw_bot_chat",
|
|
49
|
+
_userId: params?.userId,
|
|
50
|
+
source: "client",
|
|
51
|
+
content: {
|
|
52
|
+
bot_token: params?.token,
|
|
53
|
+
response: JSON.stringify({
|
|
54
|
+
type: 'tool_call',
|
|
55
|
+
...event
|
|
56
|
+
}),
|
|
57
|
+
session_id:params?.sessionId,
|
|
58
|
+
message_id: params?.messageId || Date.now().toString()
|
|
59
|
+
},
|
|
60
|
+
}));
|
|
61
|
+
ws.send(JSON.stringify({
|
|
62
|
+
messageType: "openclaw_bot_chat",
|
|
63
|
+
_userId: params?.userId,
|
|
64
|
+
source: "client",
|
|
65
|
+
content: {
|
|
66
|
+
bot_token: params?.token,
|
|
67
|
+
response: 'all_finished',
|
|
68
|
+
session_id:params?.sessionId,
|
|
69
|
+
message_id: params?.messageId || Date.now().toString()
|
|
70
|
+
},
|
|
71
|
+
}));
|
|
72
|
+
logDcgchat.info(`dcgchat: tool message to ${params?.sessionId}, ${JSON.stringify(event)}`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
65
75
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,103 +1,103 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 插件配置(channels.dcgchat 下的字段)
|
|
3
|
-
*/
|
|
4
|
-
export type DcgchatConfig = {
|
|
5
|
-
enabled?: boolean;
|
|
6
|
-
/** 后端 WebSocket 地址,例如 ws://localhost:8080/openclaw/ws */
|
|
7
|
-
wsUrl?: string;
|
|
8
|
-
/** 连接认证 token */
|
|
9
|
-
botToken?: string;
|
|
10
|
-
/** 用户标识 */
|
|
11
|
-
userId?: string;
|
|
12
|
-
domainId?: string;
|
|
13
|
-
appId?: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export type ResolvedDcgchatAccount = {
|
|
17
|
-
accountId: string;
|
|
18
|
-
enabled: boolean;
|
|
19
|
-
configured: boolean;
|
|
20
|
-
wsUrl: string;
|
|
21
|
-
botToken: string;
|
|
22
|
-
userId: string;
|
|
23
|
-
domainId?: string;
|
|
24
|
-
appId?: string;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* 下行消息:后端 → OpenClaw(用户发的消息)
|
|
29
|
-
*/
|
|
30
|
-
// export type InboundMessage = {
|
|
31
|
-
// type: "message";
|
|
32
|
-
// userId: string;
|
|
33
|
-
// text: string;
|
|
34
|
-
// };
|
|
35
|
-
export type InboundMessage = {
|
|
36
|
-
messageType: string; // "openclaw_bot_chat",
|
|
37
|
-
_userId: number;
|
|
38
|
-
source: string; // 'server',
|
|
39
|
-
// content: string;
|
|
40
|
-
content: {
|
|
41
|
-
bot_token: string;
|
|
42
|
-
session_id: string;
|
|
43
|
-
message_id: string;
|
|
44
|
-
text: string;
|
|
45
|
-
file_urls?: string[];
|
|
46
|
-
};
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// {"_userId":40,"content":"{\"bot_token\":\"sk_b7f8a3e1c5d24e6f8a1b3c4d5e6f7a8b\",\"session_id\":\"1\",\"message_id\":\"1\",\"text\":\"你好\"}","messageType":"openclaw_bot_chat","msgId":398599,"source":"server","title":"OPENCLAW机器人对话"}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* 上行消息:OpenClaw → 后端(Agent 回复)
|
|
53
|
-
*/
|
|
54
|
-
// export type OutboundReply = {
|
|
55
|
-
// type: "reply";
|
|
56
|
-
// userId: string;
|
|
57
|
-
// text: string;
|
|
58
|
-
// };
|
|
59
|
-
|
|
60
|
-
export type OutboundReply = {
|
|
61
|
-
messageType: string; // "openclaw_bot_chat",
|
|
62
|
-
_userId: number; // 100
|
|
63
|
-
source: string; // 'client',
|
|
64
|
-
// content: string;
|
|
65
|
-
content: {
|
|
66
|
-
bot_token: string; // ""
|
|
67
|
-
session_id: string; // ""
|
|
68
|
-
message_id: string; // ""
|
|
69
|
-
response: string; // ""
|
|
70
|
-
state: string; // final, chunk
|
|
71
|
-
};
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
export interface IResponse<T = unknown> {
|
|
75
|
-
/** 响应状态码 */
|
|
76
|
-
code?: number | string;
|
|
77
|
-
/** 响应数据 */
|
|
78
|
-
data?: T;
|
|
79
|
-
/** 响应消息 */
|
|
80
|
-
message?: string;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export interface IStsToken {
|
|
84
|
-
bucket: string;
|
|
85
|
-
endPoint: string;
|
|
86
|
-
expiration: string;
|
|
87
|
-
ossFileKey: string;
|
|
88
|
-
policy: string;
|
|
89
|
-
region: string;
|
|
90
|
-
signature: string;
|
|
91
|
-
sourceFileName: string;
|
|
92
|
-
stsEndPoint: string;
|
|
93
|
-
tempAccessKeyId: string;
|
|
94
|
-
tempAccessKeySecret: string;
|
|
95
|
-
tempSecurityToken: string;
|
|
96
|
-
uploadDir: string;
|
|
97
|
-
protocol: string;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export interface IStsTokenReq {
|
|
101
|
-
sourceFileName: string
|
|
102
|
-
isPrivate: number
|
|
103
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* 插件配置(channels.dcgchat 下的字段)
|
|
3
|
+
*/
|
|
4
|
+
export type DcgchatConfig = {
|
|
5
|
+
enabled?: boolean;
|
|
6
|
+
/** 后端 WebSocket 地址,例如 ws://localhost:8080/openclaw/ws */
|
|
7
|
+
wsUrl?: string;
|
|
8
|
+
/** 连接认证 token */
|
|
9
|
+
botToken?: string;
|
|
10
|
+
/** 用户标识 */
|
|
11
|
+
userId?: string;
|
|
12
|
+
domainId?: string;
|
|
13
|
+
appId?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type ResolvedDcgchatAccount = {
|
|
17
|
+
accountId: string;
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
configured: boolean;
|
|
20
|
+
wsUrl: string;
|
|
21
|
+
botToken: string;
|
|
22
|
+
userId: string;
|
|
23
|
+
domainId?: string;
|
|
24
|
+
appId?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* 下行消息:后端 → OpenClaw(用户发的消息)
|
|
29
|
+
*/
|
|
30
|
+
// export type InboundMessage = {
|
|
31
|
+
// type: "message";
|
|
32
|
+
// userId: string;
|
|
33
|
+
// text: string;
|
|
34
|
+
// };
|
|
35
|
+
export type InboundMessage = {
|
|
36
|
+
messageType: string; // "openclaw_bot_chat",
|
|
37
|
+
_userId: number;
|
|
38
|
+
source: string; // 'server',
|
|
39
|
+
// content: string;
|
|
40
|
+
content: {
|
|
41
|
+
bot_token: string;
|
|
42
|
+
session_id: string;
|
|
43
|
+
message_id: string;
|
|
44
|
+
text: string;
|
|
45
|
+
file_urls?: string[];
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// {"_userId":40,"content":"{\"bot_token\":\"sk_b7f8a3e1c5d24e6f8a1b3c4d5e6f7a8b\",\"session_id\":\"1\",\"message_id\":\"1\",\"text\":\"你好\"}","messageType":"openclaw_bot_chat","msgId":398599,"source":"server","title":"OPENCLAW机器人对话"}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 上行消息:OpenClaw → 后端(Agent 回复)
|
|
53
|
+
*/
|
|
54
|
+
// export type OutboundReply = {
|
|
55
|
+
// type: "reply";
|
|
56
|
+
// userId: string;
|
|
57
|
+
// text: string;
|
|
58
|
+
// };
|
|
59
|
+
|
|
60
|
+
export type OutboundReply = {
|
|
61
|
+
messageType: string; // "openclaw_bot_chat",
|
|
62
|
+
_userId: number; // 100
|
|
63
|
+
source: string; // 'client',
|
|
64
|
+
// content: string;
|
|
65
|
+
content: {
|
|
66
|
+
bot_token: string; // ""
|
|
67
|
+
session_id: string; // ""
|
|
68
|
+
message_id: string; // ""
|
|
69
|
+
response: string; // ""
|
|
70
|
+
state: string; // final, chunk
|
|
71
|
+
};
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export interface IResponse<T = unknown> {
|
|
75
|
+
/** 响应状态码 */
|
|
76
|
+
code?: number | string;
|
|
77
|
+
/** 响应数据 */
|
|
78
|
+
data?: T;
|
|
79
|
+
/** 响应消息 */
|
|
80
|
+
message?: string;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface IStsToken {
|
|
84
|
+
bucket: string;
|
|
85
|
+
endPoint: string;
|
|
86
|
+
expiration: string;
|
|
87
|
+
ossFileKey: string;
|
|
88
|
+
policy: string;
|
|
89
|
+
region: string;
|
|
90
|
+
signature: string;
|
|
91
|
+
sourceFileName: string;
|
|
92
|
+
stsEndPoint: string;
|
|
93
|
+
tempAccessKeyId: string;
|
|
94
|
+
tempAccessKeySecret: string;
|
|
95
|
+
tempSecurityToken: string;
|
|
96
|
+
uploadDir: string;
|
|
97
|
+
protocol: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface IStsTokenReq {
|
|
101
|
+
sourceFileName: string
|
|
102
|
+
isPrivate: number
|
|
103
|
+
}
|