adp-openclaw 0.0.46 → 0.0.47
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.ts +15 -2
- package/package.json +1 -1
- package/src/adp-upload-tool.ts +9 -0
- package/src/monitor.ts +45 -4
package/index.ts
CHANGED
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
ADP_UPLOAD_TOOL_SCHEMA,
|
|
8
8
|
parseAdpUploadToolParams,
|
|
9
9
|
uploadFilesToAdpEndpoint,
|
|
10
|
+
uploadResultEmitter,
|
|
11
|
+
UPLOAD_RESULT_EVENT,
|
|
10
12
|
type AdpUploadToolResult,
|
|
11
13
|
type UploadedFileInfo,
|
|
12
14
|
} from "./src/adp-upload-tool.js";
|
|
@@ -184,6 +186,12 @@ const plugin = {
|
|
|
184
186
|
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.downloadUrl: ${file.downloadUrl}`);
|
|
185
187
|
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.uri: ${file.uri}`);
|
|
186
188
|
}
|
|
189
|
+
|
|
190
|
+
// 发射上传结果事件,让 monitor.ts 能够直接获取完整的下载链接
|
|
191
|
+
uploadResultEmitter.emit(UPLOAD_RESULT_EVENT, {
|
|
192
|
+
toolCallId,
|
|
193
|
+
result: successResult,
|
|
194
|
+
});
|
|
187
195
|
|
|
188
196
|
// Build content with resource links and download URLs
|
|
189
197
|
const content: Array<{ type: string; uri?: string; name?: string; mimeType?: string; text?: string; downloadUrl?: string }> = [];
|
|
@@ -200,15 +208,20 @@ const plugin = {
|
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
// Add a text summary with download URLs for AI to include in response
|
|
211
|
+
// 注意:URL 包含签名参数,必须完整保留,不能截断或修改
|
|
203
212
|
const urlSummary = (successResult.files || [])
|
|
204
|
-
.map((f: UploadedFileInfo) =>
|
|
213
|
+
.map((f: UploadedFileInfo) => {
|
|
214
|
+
const url = f.downloadUrl || f.uri;
|
|
215
|
+
// 把完整 URL 作为代码块,防止 AI 截断或修改
|
|
216
|
+
return `- **${f.name}**: \`${url}\``;
|
|
217
|
+
})
|
|
205
218
|
.join("\n");
|
|
206
219
|
|
|
207
220
|
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] urlSummary: ${urlSummary}`);
|
|
208
221
|
|
|
209
222
|
content.push({
|
|
210
223
|
type: "text",
|
|
211
|
-
text: `Files uploaded successfully:\n${urlSummary}\n\n⚠️
|
|
224
|
+
text: `Files uploaded successfully:\n${urlSummary}\n\n⚠️ IMPORTANT: The URLs above contain authentication signatures. You MUST copy the ENTIRE URL exactly as shown (including all query parameters after the "?"). Do NOT truncate or modify the URLs in any way. The links are valid for 24 hours.`,
|
|
212
225
|
});
|
|
213
226
|
|
|
214
227
|
return {
|
package/package.json
CHANGED
package/src/adp-upload-tool.ts
CHANGED
|
@@ -12,8 +12,17 @@
|
|
|
12
12
|
import { constants } from "node:fs";
|
|
13
13
|
import { access, readFile, stat } from "node:fs/promises";
|
|
14
14
|
import { basename, extname } from "node:path";
|
|
15
|
+
import { EventEmitter } from "node:events";
|
|
15
16
|
import type { AdpOpenclawChannelConfig } from "./channel.js";
|
|
16
17
|
|
|
18
|
+
// ==================== 上传结果事件 ====================
|
|
19
|
+
|
|
20
|
+
/** 上传结果事件发射器,用于通知其他模块上传完成 */
|
|
21
|
+
export const uploadResultEmitter = new EventEmitter();
|
|
22
|
+
|
|
23
|
+
/** 上传结果事件名称 */
|
|
24
|
+
export const UPLOAD_RESULT_EVENT = "adp-upload-result";
|
|
25
|
+
|
|
17
26
|
// ==================== 类型定义 ====================
|
|
18
27
|
|
|
19
28
|
/** 存储凭证请求参数 */
|
package/src/monitor.ts
CHANGED
|
@@ -14,6 +14,8 @@ import {
|
|
|
14
14
|
ADP_UPLOAD_TOOL_NAME,
|
|
15
15
|
ADP_UPLOAD_TOOL_SCHEMA,
|
|
16
16
|
executeAdpUploadTool,
|
|
17
|
+
uploadResultEmitter,
|
|
18
|
+
UPLOAD_RESULT_EVENT,
|
|
17
19
|
type AdpUploadToolResult,
|
|
18
20
|
} from "./adp-upload-tool.js";
|
|
19
21
|
import {
|
|
@@ -328,20 +330,58 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
328
330
|
let lastPartialText = ""; // Track last sent text for delta calculation
|
|
329
331
|
let finalSent = false; // Track if outbound_end has been sent
|
|
330
332
|
const displayName = inMsg.user?.username || inMsg.from;
|
|
333
|
+
|
|
334
|
+
// 收集上传结果,在发送最终回复时追加完整的下载链接
|
|
335
|
+
let pendingUploadResults: AdpUploadToolResult[] = [];
|
|
336
|
+
|
|
337
|
+
// 监听上传结果事件
|
|
338
|
+
const uploadResultHandler = (event: { toolCallId: string; result: AdpUploadToolResult }) => {
|
|
339
|
+
log?.info(`[adp-openclaw] Received upload result event for toolCallId=${event.toolCallId}`);
|
|
340
|
+
if (event.result.ok && event.result.files && event.result.files.length > 0) {
|
|
341
|
+
pendingUploadResults.push(event.result);
|
|
342
|
+
// 打印完整的下载链接
|
|
343
|
+
for (const file of event.result.files) {
|
|
344
|
+
log?.info(`[adp-openclaw] Upload result - file.downloadUrl: ${file.downloadUrl}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
uploadResultEmitter.on(UPLOAD_RESULT_EVENT, uploadResultHandler);
|
|
331
349
|
|
|
332
350
|
// Helper function to send outbound_end message
|
|
333
351
|
const sendOutboundEnd = (text: string) => {
|
|
334
352
|
if (finalSent) return; // Prevent duplicate sends
|
|
335
353
|
finalSent = true;
|
|
336
354
|
|
|
355
|
+
// 移除事件监听
|
|
356
|
+
uploadResultEmitter.off(UPLOAD_RESULT_EVENT, uploadResultHandler);
|
|
357
|
+
|
|
358
|
+
// 如果有上传结果,追加完整的下载链接到回复中
|
|
359
|
+
let finalText = text;
|
|
360
|
+
if (pendingUploadResults.length > 0) {
|
|
361
|
+
const uploadLinks: string[] = [];
|
|
362
|
+
for (const result of pendingUploadResults) {
|
|
363
|
+
for (const file of (result.files || [])) {
|
|
364
|
+
if (file.downloadUrl) {
|
|
365
|
+
// 使用完整的下载链接,包括签名参数
|
|
366
|
+
uploadLinks.push(`📎 [${file.name}](${file.downloadUrl})`);
|
|
367
|
+
log?.info(`[adp-openclaw] Appending download link: ${file.downloadUrl.substring(0, 100)}...`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (uploadLinks.length > 0) {
|
|
372
|
+
finalText = `${text}\n\n**文件下载链接(24小时有效):**\n${uploadLinks.join("\n")}`;
|
|
373
|
+
log?.info(`[adp-openclaw] Added ${uploadLinks.length} download links to final response`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
337
377
|
if (chunkIndex > 0) {
|
|
338
|
-
log?.info(`[adp-openclaw] Sending outbound_end to ${displayName}: ${
|
|
378
|
+
log?.info(`[adp-openclaw] Sending outbound_end to ${displayName}: ${finalText.slice(0, 50)}... (chunks=${chunkIndex})`);
|
|
339
379
|
const endMsg: WSMessage = {
|
|
340
380
|
type: MsgType.OutboundEnd,
|
|
341
381
|
requestId: generateRequestId(),
|
|
342
382
|
payload: {
|
|
343
383
|
to: inMsg.from,
|
|
344
|
-
text:
|
|
384
|
+
text: finalText,
|
|
345
385
|
conversationId: inMsg.conversationId,
|
|
346
386
|
recordId: inMsg.recordId, // Pass recordId back to server
|
|
347
387
|
streamId: streamId,
|
|
@@ -353,13 +393,13 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
353
393
|
ws.send(JSON.stringify(endMsg));
|
|
354
394
|
} else {
|
|
355
395
|
// No streaming chunks were sent, send as regular outbound message
|
|
356
|
-
log?.info(`[adp-openclaw] Sending outbound to ${displayName}: ${
|
|
396
|
+
log?.info(`[adp-openclaw] Sending outbound to ${displayName}: ${finalText.slice(0, 50)}...`);
|
|
357
397
|
const outMsg: WSMessage = {
|
|
358
398
|
type: MsgType.Outbound,
|
|
359
399
|
requestId: generateRequestId(),
|
|
360
400
|
payload: {
|
|
361
401
|
to: inMsg.from,
|
|
362
|
-
text:
|
|
402
|
+
text: finalText,
|
|
363
403
|
conversationId: inMsg.conversationId,
|
|
364
404
|
recordId: inMsg.recordId, // Pass recordId back to server
|
|
365
405
|
user: inMsg.user,
|
|
@@ -494,6 +534,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
494
534
|
// SDK may call deliver without kind when streaming ends
|
|
495
535
|
if (kind === "final" || kind === undefined) {
|
|
496
536
|
log?.info(`[adp-openclaw] deliver triggering sendOutboundEnd (kind=${kind})`);
|
|
537
|
+
log?.info(`[adp-openclaw] Final text content: ${text}`);
|
|
497
538
|
sendOutboundEnd(text || lastPartialText);
|
|
498
539
|
}
|
|
499
540
|
},
|