@dcrays/dcgchat-test 0.2.1 → 0.2.2
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/package.json +3 -2
- package/src/api.ts +24 -1
- package/src/bot.ts +82 -61
- package/src/channel.ts +37 -75
- package/src/monitor.ts +3 -2
- package/src/oss.ts +2 -2
- package/src/request.ts +10 -3
- package/src/tool.ts +37 -30
- package/src/types.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dcrays/dcgchat-test",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenClaw channel plugin for 书灵墨宝 (WebSocket)",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -20,9 +20,10 @@
|
|
|
20
20
|
"typecheck": "tsc --noEmit"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"ali-oss": "file:src/libs/ali-oss-6.23.0.tgz",
|
|
23
24
|
"axios": "file:src/libs/axios-1.13.6.tgz",
|
|
24
25
|
"ws": "file:src/libs/ws-8.19.0.tgz",
|
|
25
|
-
"
|
|
26
|
+
"md5": "file:src/libs/md5-2.3.0.tgz",
|
|
26
27
|
"unzipper": "file:src/libs/unzipper-0.12.3.tgz"
|
|
27
28
|
},
|
|
28
29
|
"openclaw": {
|
package/src/api.ts
CHANGED
|
@@ -10,7 +10,7 @@ export const getStsToken = async (name: string, botToken: string) => {
|
|
|
10
10
|
"/user/getStsToken",
|
|
11
11
|
{
|
|
12
12
|
sourceFileName: name,
|
|
13
|
-
isPrivate:
|
|
13
|
+
isPrivate: 1,
|
|
14
14
|
},
|
|
15
15
|
{ botToken },
|
|
16
16
|
);
|
|
@@ -21,6 +21,29 @@ export const getStsToken = async (name: string, botToken: string) => {
|
|
|
21
21
|
|
|
22
22
|
return response.data;
|
|
23
23
|
};
|
|
24
|
+
export const generateSignUrl = async (file_url: string, botToken: string) => {
|
|
25
|
+
try {
|
|
26
|
+
// 确保 userToken 已缓存(如果未缓存会自动获取并缓存)
|
|
27
|
+
await getUserToken(botToken);
|
|
28
|
+
|
|
29
|
+
const response = await post<any>(
|
|
30
|
+
"/user/generateSignUrl",
|
|
31
|
+
{
|
|
32
|
+
loudPlatform: 0,
|
|
33
|
+
fileName: file_url
|
|
34
|
+
},
|
|
35
|
+
{ botToken },
|
|
36
|
+
);
|
|
37
|
+
if (response.code === 0 && response.data) {
|
|
38
|
+
// @ts-ignore
|
|
39
|
+
return response.data?.filePath
|
|
40
|
+
}
|
|
41
|
+
return ''
|
|
42
|
+
|
|
43
|
+
} catch (error) {
|
|
44
|
+
return ''
|
|
45
|
+
}
|
|
46
|
+
};
|
|
24
47
|
|
|
25
48
|
/**
|
|
26
49
|
* 通过 botToken 查询 userToken
|
package/src/bot.ts
CHANGED
|
@@ -6,9 +6,8 @@ import type { InboundMessage, OutboundReply } from "./types.js";
|
|
|
6
6
|
import { getDcgchatRuntime } from "./runtime.js";
|
|
7
7
|
import { resolveAccount } from "./channel.js";
|
|
8
8
|
import { setMsgStatus } from "./tool.js";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
const targetPath = path.join(os.homedir(), '../');
|
|
9
|
+
import { generateSignUrl } from "./api.js";
|
|
10
|
+
import { ossUpload } from "./oss.js";
|
|
12
11
|
|
|
13
12
|
type MediaInfo = {
|
|
14
13
|
path: string;
|
|
@@ -16,27 +15,49 @@ type MediaInfo = {
|
|
|
16
15
|
placeholder: string;
|
|
17
16
|
};
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
): Promise<MediaInfo[]> {
|
|
18
|
+
const mediaMaxBytes = 300 * 1024 * 1024;
|
|
19
|
+
async function resolveMediaFromUrls(files: { name: string, url: string }[], botToken: string, log: (message: string) => void): Promise<MediaInfo[]> {
|
|
20
|
+
const core = getDcgchatRuntime();
|
|
23
21
|
const out: MediaInfo[] = [];
|
|
22
|
+
log(`dcgchat media: starting resolve for ${files.length} file(s): ${JSON.stringify(files)}`);
|
|
23
|
+
|
|
24
24
|
for (let i = 0; i < files.length; i++) {
|
|
25
|
-
const
|
|
25
|
+
const file = files[i];
|
|
26
26
|
try {
|
|
27
|
-
const
|
|
28
|
-
|
|
27
|
+
const data = await generateSignUrl(file.url, botToken);
|
|
28
|
+
log(`dcgchat media: [${i + 1}/${files.length}] generateSignUrl: ${data}`);
|
|
29
|
+
const response = await fetch(data);
|
|
30
|
+
if (!response.ok) {
|
|
31
|
+
log?.(`dcgchat media: [${i + 1}/${files.length}] fetch failed with HTTP ${response.status}, skipping`);
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
35
|
+
|
|
36
|
+
let contentType = response.headers.get("content-type") || "";
|
|
37
|
+
if (!contentType) {
|
|
38
|
+
contentType = await core.media.detectMime({ buffer }) || "";
|
|
39
|
+
}
|
|
40
|
+
const fileName = file.name || path.basename(new URL(file.url).pathname) || "file";
|
|
41
|
+
const saved = await core.channel.media.saveMediaBuffer(
|
|
42
|
+
buffer,
|
|
43
|
+
contentType,
|
|
44
|
+
"inbound",
|
|
45
|
+
// maxByte: mediaMaxBytes,
|
|
46
|
+
fileName,
|
|
47
|
+
);
|
|
29
48
|
const isImage = contentType.startsWith("image/");
|
|
30
49
|
out.push({
|
|
31
|
-
path:
|
|
32
|
-
|
|
33
|
-
contentType: saved.contentType,
|
|
50
|
+
path: saved.path,
|
|
51
|
+
contentType: saved.contentType || "",
|
|
34
52
|
placeholder: isImage ? "<media:image>" : "<media:file>",
|
|
35
53
|
});
|
|
54
|
+
|
|
36
55
|
} catch (err) {
|
|
37
|
-
log
|
|
56
|
+
log(`dcgchat media: [${i + 1}/${files.length}] FAILED to process ${file.url}: ${String(err)}`);
|
|
38
57
|
}
|
|
39
58
|
}
|
|
59
|
+
log(`dcgchat media: resolve complete, ${out.length}/${files.length} file(s) succeeded`);
|
|
60
|
+
|
|
40
61
|
return out;
|
|
41
62
|
}
|
|
42
63
|
|
|
@@ -115,15 +136,7 @@ export async function handleDcgchatMessage(params: {
|
|
|
115
136
|
const files = msg.content.files ?? [];
|
|
116
137
|
let mediaPayload: Record<string, unknown> = {};
|
|
117
138
|
if (files.length > 0) {
|
|
118
|
-
const mediaList =
|
|
119
|
-
const contentType = mime.lookup(item.name) || "application/octet-stream";
|
|
120
|
-
const isImage = contentType.startsWith("image/");
|
|
121
|
-
return {
|
|
122
|
-
path: path.join(targetPath, item?.url),
|
|
123
|
-
contentType: contentType,
|
|
124
|
-
placeholder: isImage ? "<media:image>" : "<media:file>",
|
|
125
|
-
}
|
|
126
|
-
});
|
|
139
|
+
const mediaList = await resolveMediaFromUrls(files, msg.content.bot_token, log)
|
|
127
140
|
mediaPayload = buildMediaPayload(mediaList);
|
|
128
141
|
log(`dcgchat[${accountId}]: media resolved ${mediaList.length}/${files.length} file(s), payload=${JSON.stringify(mediaList)}`);
|
|
129
142
|
}
|
|
@@ -174,36 +187,10 @@ export async function handleDcgchatMessage(params: {
|
|
|
174
187
|
responsePrefixContextProvider: prefixContext.responsePrefixContextProvider,
|
|
175
188
|
humanDelay: core.channel.reply.resolveHumanDelayConfig(cfg, route.agentId),
|
|
176
189
|
onReplyStart: async () => {},
|
|
177
|
-
deliver: async (payload) => {
|
|
178
|
-
|
|
179
|
-
// const t = payload.text?.trim().replaceAll(
|
|
180
|
-
// "/root/.openclaw/workspace/moBooksAgentGenerate",
|
|
181
|
-
// "/upload"
|
|
182
|
-
// );
|
|
183
|
-
// if (t) {
|
|
184
|
-
// log(`dcgchat[${accountId}][deliver]: sending chunk to user ${msg._userId}, text="${t.slice(0, 50)}..."`);
|
|
185
|
-
// params.onChunk({
|
|
186
|
-
// messageType: "openclaw_bot_chat",
|
|
187
|
-
// _userId: msg._userId,
|
|
188
|
-
// source: "client",
|
|
189
|
-
// content: {
|
|
190
|
-
// bot_token: msg.content.bot_token,
|
|
191
|
-
// domain_id: msg.content.domain_id,
|
|
192
|
-
// app_id: msg.content.app_id,
|
|
193
|
-
// bot_id: msg.content.bot_id,
|
|
194
|
-
// agent_id: msg.content.agent_id,
|
|
195
|
-
// session_id: msg.content.session_id,
|
|
196
|
-
// message_id: msg.content.message_id,
|
|
197
|
-
// response: t,
|
|
198
|
-
// state: 'chunk',
|
|
199
|
-
// },
|
|
200
|
-
// });
|
|
201
|
-
// log(`dcgchat[${accountId}][deliver]: chunk sent successfully`);
|
|
202
|
-
// } else {
|
|
203
|
-
// log(`dcgchat[${accountId}][deliver]: skipping empty chunk`);
|
|
204
|
-
// }
|
|
190
|
+
deliver: async (payload: { text: string | any[]; }) => {
|
|
191
|
+
log(`dcgchat[${accountId}][deliver]: received chunk, text length=${payload.text?.length || 0}`);
|
|
205
192
|
},
|
|
206
|
-
onError: (err, info) => {
|
|
193
|
+
onError: (err: any, info: { kind: any; }) => {
|
|
207
194
|
error(`dcgchat[${accountId}] ${info.kind} reply failed: ${String(err)}`);
|
|
208
195
|
},
|
|
209
196
|
onIdle: () => {},
|
|
@@ -218,14 +205,25 @@ export async function handleDcgchatMessage(params: {
|
|
|
218
205
|
replyOptions: {
|
|
219
206
|
...replyOptions,
|
|
220
207
|
onModelSelected: prefixContext.onModelSelected,
|
|
221
|
-
onPartialReply: (payload: ReplyPayload) => {
|
|
208
|
+
onPartialReply: async (payload: ReplyPayload) => {
|
|
222
209
|
log(`dcgchat[${accountId}][deliver]: received chunk, text length=${payload.text?.length || 0}`);
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
210
|
+
const mediaList =
|
|
211
|
+
payload.mediaUrls && payload.mediaUrls.length > 0
|
|
212
|
+
? payload.mediaUrls
|
|
213
|
+
: payload.mediaUrl
|
|
214
|
+
? [payload.mediaUrl]
|
|
215
|
+
: [];
|
|
216
|
+
if (mediaList.length > 0) {
|
|
217
|
+
const files = []
|
|
218
|
+
for (let i = 0; i < mediaList.length; i++) {
|
|
219
|
+
const file = mediaList[i]
|
|
220
|
+
const fileName = file.split(/[\\/]/).pop() || ''
|
|
221
|
+
const url = await ossUpload(file, msg.content.bot_token)
|
|
222
|
+
files.push({
|
|
223
|
+
url: url,
|
|
224
|
+
name: fileName,
|
|
225
|
+
})
|
|
226
|
+
}
|
|
229
227
|
params.onChunk({
|
|
230
228
|
messageType: "openclaw_bot_chat",
|
|
231
229
|
_userId: msg._userId,
|
|
@@ -238,12 +236,35 @@ export async function handleDcgchatMessage(params: {
|
|
|
238
236
|
agent_id: msg.content.agent_id,
|
|
239
237
|
session_id: msg.content.session_id,
|
|
240
238
|
message_id: msg.content.message_id,
|
|
241
|
-
response:
|
|
239
|
+
response: '',
|
|
240
|
+
files: files,
|
|
242
241
|
state: 'chunk',
|
|
243
242
|
},
|
|
244
243
|
});
|
|
245
|
-
|
|
244
|
+
}
|
|
245
|
+
if (payload.text) {
|
|
246
|
+
log(`dcgchat[${accountId}][deliver]: sending chunk to user ${msg._userId}, text="${payload.text.slice(0, 50)}..."`);
|
|
247
|
+
params.onChunk({
|
|
248
|
+
messageType: "openclaw_bot_chat",
|
|
249
|
+
_userId: msg._userId,
|
|
250
|
+
source: "client",
|
|
251
|
+
content: {
|
|
252
|
+
bot_token: msg.content.bot_token,
|
|
253
|
+
domain_id: msg.content.domain_id,
|
|
254
|
+
app_id: msg.content.app_id,
|
|
255
|
+
bot_id: msg.content.bot_id,
|
|
256
|
+
agent_id: msg.content.agent_id,
|
|
257
|
+
session_id: msg.content.session_id,
|
|
258
|
+
message_id: msg.content.message_id,
|
|
259
|
+
response: payload.text.replace(textChunk, ''),
|
|
260
|
+
state: 'chunk',
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
textChunk = payload.text
|
|
246
264
|
log(`dcgchat[${accountId}][deliver]: chunk sent successfully`);
|
|
265
|
+
} else if (payload.mediaUrl && payload.mediaUrls) {
|
|
266
|
+
|
|
267
|
+
|
|
247
268
|
} else {
|
|
248
269
|
log(`dcgchat[${accountId}][deliver]: skipping empty chunk`);
|
|
249
270
|
}
|
package/src/channel.ts
CHANGED
|
@@ -1,50 +1,10 @@
|
|
|
1
|
-
import { copyFile, mkdir, rename, unlink } from "node:fs/promises";
|
|
2
|
-
import { basename, dirname, isAbsolute, relative, resolve } from "node:path";
|
|
3
|
-
import os from "node:os";
|
|
4
1
|
import type { ChannelPlugin, OpenClawConfig } from "openclaw/plugin-sdk";
|
|
5
2
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk";
|
|
6
3
|
import type { ResolvedDcgchatAccount, DcgchatConfig } from "./types.js";
|
|
7
|
-
import { logDcgchat } from "./log.js";
|
|
8
4
|
import { getWsConnection } from "./connection.js";
|
|
5
|
+
import { ossUpload } from "./oss.js";
|
|
9
6
|
import { getMsgParams } from "./tool.js";
|
|
10
7
|
|
|
11
|
-
const uploadRoot = resolve('/', "upload");
|
|
12
|
-
|
|
13
|
-
function isPathInside(parentPath: string, targetPath: string): boolean {
|
|
14
|
-
const relativePath = relative(parentPath, targetPath);
|
|
15
|
-
return relativePath === "" || (!relativePath.startsWith("..") && !isAbsolute(relativePath));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function ensureMediaInUploadDir(url: string): Promise<string> {
|
|
19
|
-
if (!url || /^([a-z][a-z\d+\-.]*):\/\//i.test(url) || !isAbsolute(url)) {
|
|
20
|
-
return url;
|
|
21
|
-
}
|
|
22
|
-
const sourcePath = resolve(url);
|
|
23
|
-
if (isPathInside(uploadRoot, sourcePath)) {
|
|
24
|
-
return sourcePath;
|
|
25
|
-
}
|
|
26
|
-
const fileName = basename(sourcePath);
|
|
27
|
-
if (!fileName) {
|
|
28
|
-
return sourcePath;
|
|
29
|
-
}
|
|
30
|
-
const targetPath = resolve(uploadRoot, fileName);
|
|
31
|
-
if (targetPath === sourcePath) {
|
|
32
|
-
return targetPath;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
await mkdir(uploadRoot, { recursive: true });
|
|
36
|
-
|
|
37
|
-
try {
|
|
38
|
-
await rename(sourcePath, targetPath);
|
|
39
|
-
} catch (error) {
|
|
40
|
-
if ((error as NodeJS.ErrnoException).code !== "EXDEV") {
|
|
41
|
-
throw error;
|
|
42
|
-
}
|
|
43
|
-
await copyFile(sourcePath, targetPath);
|
|
44
|
-
await unlink(sourcePath);
|
|
45
|
-
}
|
|
46
|
-
return targetPath;
|
|
47
|
-
}
|
|
48
8
|
|
|
49
9
|
export function resolveAccount(cfg: OpenClawConfig, accountId?: string | null): ResolvedDcgchatAccount {
|
|
50
10
|
const id = accountId ?? DEFAULT_ACCOUNT_ID;
|
|
@@ -145,6 +105,7 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
145
105
|
sendText: async (ctx) => {
|
|
146
106
|
const ws = getWsConnection()
|
|
147
107
|
const params = getMsgParams();
|
|
108
|
+
const log = ctx.runtime?.log ?? console.log;
|
|
148
109
|
if (ws?.readyState === WebSocket.OPEN) {
|
|
149
110
|
const {botToken} = resolveAccount(ctx.cfg, ctx.accountId);
|
|
150
111
|
const content = {
|
|
@@ -157,18 +118,15 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
157
118
|
app_id: params.appId,
|
|
158
119
|
bot_id: params.botId,
|
|
159
120
|
agent_id: params.agentId,
|
|
160
|
-
response: ctx.text
|
|
161
|
-
"/root/.openclaw/workspace/moBooksAgentGenerate",
|
|
162
|
-
"/upload"
|
|
163
|
-
),
|
|
121
|
+
response: ctx.text,
|
|
164
122
|
session_id: params.sessionId,
|
|
165
123
|
message_id: params.messageId || Date.now().toString(),
|
|
166
124
|
},
|
|
167
125
|
};
|
|
168
126
|
ws.send(JSON.stringify(content));
|
|
169
|
-
|
|
127
|
+
log(`dcgchat[${ctx.accountId}]: sendText to ${params.userId}, ${JSON.stringify(content)}`);
|
|
170
128
|
} else {
|
|
171
|
-
|
|
129
|
+
log(`[dcgchat][${ctx.accountId ?? DEFAULT_ACCOUNT_ID}] outbound -> ${ws?.readyState}: ${ctx.text}`);
|
|
172
130
|
}
|
|
173
131
|
return {
|
|
174
132
|
channel: "dcgchat-test",
|
|
@@ -179,13 +137,12 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
179
137
|
sendMedia: async (ctx) => {
|
|
180
138
|
const ws = getWsConnection()
|
|
181
139
|
const params = getMsgParams();
|
|
182
|
-
|
|
183
|
-
|
|
140
|
+
const log = ctx.runtime?.log ?? console.log;
|
|
141
|
+
if (ws?.readyState === WebSocket.OPEN) {
|
|
142
|
+
const fileName = ctx.mediaUrl?.split(/[\\/]/).pop() || ''
|
|
184
143
|
const {botToken} = resolveAccount(ctx.cfg, ctx.accountId);
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const url = await ensureMediaInUploadDir(ctx.mediaUrl ?? '');
|
|
188
|
-
const fileName = url?.split(/[\\/]/).pop() || ''
|
|
144
|
+
try {
|
|
145
|
+
const url = ctx.mediaUrl ? await ossUpload(ctx.mediaUrl, botToken) : '';
|
|
189
146
|
const content = {
|
|
190
147
|
messageType: "openclaw_bot_chat",
|
|
191
148
|
_userId: params.userId,
|
|
@@ -196,37 +153,42 @@ export const dcgchatPlugin: ChannelPlugin<ResolvedDcgchatAccount> = {
|
|
|
196
153
|
app_id: params.appId,
|
|
197
154
|
bot_id: params.botId,
|
|
198
155
|
agent_id: params.agentId,
|
|
199
|
-
response: ctx.text
|
|
200
|
-
"/root/.openclaw/workspace/moBooksAgentGenerate",
|
|
201
|
-
"/upload"
|
|
202
|
-
),
|
|
156
|
+
response: ctx.text,
|
|
203
157
|
files: [{
|
|
204
158
|
url: url,
|
|
205
159
|
name: fileName,
|
|
206
160
|
}],
|
|
207
161
|
session_id: params.sessionId,
|
|
208
|
-
message_id: params.messageId ||
|
|
162
|
+
message_id: params.messageId ||Date.now().toString(),
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
ws.send(JSON.stringify(content));
|
|
166
|
+
log(`dcgchat[${ctx.accountId}]: sendMedia alioss to ${params.userId}, ${JSON.stringify(content)}`);
|
|
167
|
+
} catch (error) {
|
|
168
|
+
const content = {
|
|
169
|
+
messageType: "openclaw_bot_chat",
|
|
170
|
+
_userId: params.userId,
|
|
171
|
+
source: "client",
|
|
172
|
+
content: {
|
|
173
|
+
bot_token: botToken,
|
|
174
|
+
domain_id: params.domainId,
|
|
175
|
+
app_id: params.appId,
|
|
176
|
+
bot_id: params.botId,
|
|
177
|
+
agent_id: params.agentId,
|
|
178
|
+
response: ctx.text,
|
|
179
|
+
files: [{
|
|
180
|
+
url: ctx.mediaUrl,
|
|
181
|
+
name: fileName,
|
|
182
|
+
}],
|
|
183
|
+
session_id: params.sessionId || Date.now().toString(),
|
|
184
|
+
message_id: params.messageId ||Date.now().toString(),
|
|
209
185
|
},
|
|
210
186
|
};
|
|
211
187
|
ws.send(JSON.stringify(content));
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
// const content = {
|
|
215
|
-
// messageType: "openclaw_bot_chat",
|
|
216
|
-
// _userId: target,
|
|
217
|
-
// source: "client",
|
|
218
|
-
// content: {
|
|
219
|
-
// bot_token: botToken,
|
|
220
|
-
// response: ctx.text + '\n' + ctx.mediaUrl,
|
|
221
|
-
// session_id: params.sessionId || Date.now().toString(),
|
|
222
|
-
// message_id: params.messageId ||Date.now().toString(),
|
|
223
|
-
// },
|
|
224
|
-
// };
|
|
225
|
-
// ws.send(JSON.stringify(content));
|
|
226
|
-
// logDcgchat.info(`dcgchat[${ctx.accountId}]: sendMedia to ${target}, ${JSON.stringify(content)}`);
|
|
227
|
-
// }
|
|
188
|
+
log(`dcgchat[${ctx.accountId}]: error sendMedia to ${params.userId}, ${JSON.stringify(content)}`);
|
|
189
|
+
}
|
|
228
190
|
} else {
|
|
229
|
-
|
|
191
|
+
log(`[dcgchat][${ctx.accountId ?? DEFAULT_ACCOUNT_ID}] outbound -> ${ws?.readyState}: ${ctx.text}`);
|
|
230
192
|
}
|
|
231
193
|
return {
|
|
232
194
|
channel: "dcgchat-test",
|
package/src/monitor.ts
CHANGED
|
@@ -112,13 +112,14 @@ export async function monitorDcgchatProvider(opts: MonitorDcgchatOpts): Promise<
|
|
|
112
112
|
if (parsed.messageType == "openclaw_bot_chat") {
|
|
113
113
|
const msg = parsed as unknown as InboundMessage;
|
|
114
114
|
setMsgStatus('running');
|
|
115
|
+
log(`dcgchat[${account.accountId}]: openclaw_bot_chat received, ${JSON.stringify(msg)}`);
|
|
115
116
|
setMsgParams({
|
|
116
117
|
userId: msg._userId,
|
|
117
118
|
token: msg.content.bot_token,
|
|
118
119
|
sessionId: msg.content.session_id,
|
|
119
120
|
messageId: msg.content.message_id,
|
|
120
|
-
domainId:
|
|
121
|
-
appId:
|
|
121
|
+
domainId: account.domainId || 1000,
|
|
122
|
+
appId: account.appId || '100',
|
|
122
123
|
botId: msg.content.bot_id,
|
|
123
124
|
agentId: msg.content.agent_id,
|
|
124
125
|
});
|
package/src/oss.ts
CHANGED
|
@@ -61,9 +61,9 @@ export const ossUpload = async (file: File | string | Buffer, botToken: string)
|
|
|
61
61
|
if (objectResult?.res?.status !== 200) {
|
|
62
62
|
throw new Error("OSS 上传失败");
|
|
63
63
|
}
|
|
64
|
-
console.log(objectResult
|
|
64
|
+
console.log(11111, JSON.stringify(objectResult));
|
|
65
65
|
// const url = `${data.protocol || 'http'}://${data.bucket}.${data.endPoint}/${data.uploadDir}${data.ossFileKey}`
|
|
66
|
-
return objectResult.url;
|
|
66
|
+
return objectResult.name || objectResult.url;
|
|
67
67
|
} catch (error) {
|
|
68
68
|
console.error("OSS 上传失败:", error);
|
|
69
69
|
throw error;
|
package/src/request.ts
CHANGED
|
@@ -2,6 +2,7 @@ import axios from "axios";
|
|
|
2
2
|
import md5 from "md5";
|
|
3
3
|
import type { IResponse } from "./types.js";
|
|
4
4
|
import { getUserTokenCache } from "./userInfo.js";
|
|
5
|
+
import { getMsgParams } from "./tool.js";
|
|
5
6
|
|
|
6
7
|
export const apiUrlMap = {
|
|
7
8
|
production: "https://api-gateway.shuwenda.com",
|
|
@@ -178,17 +179,23 @@ export function post<T = Record<string, unknown>, R = unknown>(
|
|
|
178
179
|
botToken?: string;
|
|
179
180
|
},
|
|
180
181
|
): Promise<IResponse<R>> {
|
|
182
|
+
const params = getMsgParams() || {}
|
|
181
183
|
const config: any = {
|
|
182
184
|
method: "POST",
|
|
183
185
|
url,
|
|
184
|
-
data
|
|
185
|
-
|
|
186
|
+
data: {
|
|
187
|
+
...data,
|
|
188
|
+
_appId: params.appId
|
|
189
|
+
},
|
|
190
|
+
headers: buildHeaders({
|
|
191
|
+
...data,
|
|
192
|
+
_appId: params.appId
|
|
193
|
+
} as Record<string, unknown>, url, options?.userToken),
|
|
186
194
|
};
|
|
187
195
|
|
|
188
196
|
// 将 botToken 附加到配置中,供请求拦截器使用
|
|
189
197
|
if (options?.botToken) {
|
|
190
198
|
config.__botToken = options.botToken;
|
|
191
199
|
}
|
|
192
|
-
|
|
193
200
|
return axiosInstance.request(config);
|
|
194
201
|
}
|
package/src/tool.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
|
|
2
2
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
3
3
|
import { getWsConnection } from "./connection.js";
|
|
4
|
-
import { logDcgchat } from "./log.js";
|
|
5
4
|
|
|
6
5
|
let msgParams = {} as {
|
|
7
6
|
userId: number;
|
|
@@ -29,32 +28,35 @@ export function setMsgStatus(status: 'running' | 'finished' | '') {
|
|
|
29
28
|
export function getMsgStatus() {
|
|
30
29
|
return msgStatus;
|
|
31
30
|
}
|
|
32
|
-
|
|
31
|
+
let runId = '';
|
|
32
|
+
let toolName = '';
|
|
33
33
|
export function monitoringToolMessage(api: OpenClawPluginApi) {
|
|
34
|
-
api.on("after_tool_call", (event
|
|
34
|
+
api.on("after_tool_call", (event) => {
|
|
35
35
|
const ws = getWsConnection()
|
|
36
36
|
const params = getMsgParams();
|
|
37
37
|
const status = getMsgStatus();
|
|
38
38
|
//
|
|
39
39
|
if (ws?.readyState === WebSocket.OPEN && status === 'running') {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
40
|
+
const log = api.runtime?.log ?? api.log;
|
|
41
|
+
// @ts-ignore
|
|
42
|
+
if (!runId || runId !== event.runId || !toolName || toolName !== event.toolName) {
|
|
43
|
+
ws.send(JSON.stringify({
|
|
44
|
+
messageType: "openclaw_bot_chat",
|
|
45
|
+
_userId: params?.userId,
|
|
46
|
+
source: "client",
|
|
47
|
+
content: {
|
|
48
|
+
bot_token: params?.token,
|
|
49
|
+
response: 'all_finished',
|
|
50
|
+
session_id:params?.sessionId,
|
|
51
|
+
message_id: params?.messageId || Date.now().toString()
|
|
52
|
+
},
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
51
55
|
const text = JSON.stringify({
|
|
52
56
|
type: 'tool_call',
|
|
57
|
+
specialIdentification: 'dcgchat_tool_call_special_identification',
|
|
53
58
|
...event
|
|
54
|
-
})
|
|
55
|
-
"/root/.openclaw/workspace/moBooksAgentGenerate",
|
|
56
|
-
"/upload"
|
|
57
|
-
);
|
|
59
|
+
});
|
|
58
60
|
ws.send(JSON.stringify({
|
|
59
61
|
messageType: "openclaw_bot_chat",
|
|
60
62
|
_userId: params?.userId,
|
|
@@ -70,18 +72,23 @@ export function monitoringToolMessage(api: OpenClawPluginApi) {
|
|
|
70
72
|
message_id: params?.messageId || Date.now().toString()
|
|
71
73
|
},
|
|
72
74
|
}));
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
if (!runId || runId !== event.runId || !toolName || toolName !== event.toolName) {
|
|
77
|
+
ws.send(JSON.stringify({
|
|
78
|
+
messageType: "openclaw_bot_chat",
|
|
79
|
+
_userId: params?.userId,
|
|
80
|
+
source: "client",
|
|
81
|
+
content: {
|
|
82
|
+
bot_token: params?.token,
|
|
83
|
+
response: 'all_finished',
|
|
84
|
+
session_id:params?.sessionId,
|
|
85
|
+
message_id: params?.messageId || Date.now().toString()
|
|
86
|
+
},
|
|
87
|
+
}));
|
|
88
|
+
}
|
|
89
|
+
runId = event.runId;
|
|
90
|
+
toolName = event.toolName;
|
|
91
|
+
log?.(`dcgchat[${params?.sessionId}]:11111111 tool message to ${params?.sessionId}, ${JSON.stringify(event)}`);
|
|
85
92
|
}
|
|
86
93
|
});
|
|
87
94
|
}
|