adp-openclaw 0.0.45 → 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 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";
@@ -179,27 +181,47 @@ const plugin = {
179
181
 
180
182
  api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] upload success toolCallId=${toolCallId} count=${successResult.files?.length ?? 0} paths=${JSON.stringify(parsed.value.paths)}`);
181
183
 
184
+ // Debug: print full downloadUrl for each file
185
+ for (const file of (successResult.files || [])) {
186
+ api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.downloadUrl: ${file.downloadUrl}`);
187
+ api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.uri: ${file.uri}`);
188
+ }
189
+
190
+ // 发射上传结果事件,让 monitor.ts 能够直接获取完整的下载链接
191
+ uploadResultEmitter.emit(UPLOAD_RESULT_EVENT, {
192
+ toolCallId,
193
+ result: successResult,
194
+ });
195
+
182
196
  // Build content with resource links and download URLs
183
- const content: Array<{ type: string; uri?: string; name?: string; mimeType?: string; text?: string }> = [];
197
+ const content: Array<{ type: string; uri?: string; name?: string; mimeType?: string; text?: string; downloadUrl?: string }> = [];
184
198
 
185
199
  // Add resource links for each file
186
200
  for (const file of (successResult.files || [])) {
187
201
  content.push({
188
202
  type: "resource_link",
189
- uri: file.uri,
203
+ uri: file.downloadUrl || file.uri, // 使用带签名的下载链接
190
204
  name: file.name,
191
205
  mimeType: file.mimeType,
206
+ downloadUrl: file.downloadUrl, // 也包含 downloadUrl 字段
192
207
  });
193
208
  }
194
209
 
195
210
  // Add a text summary with download URLs for AI to include in response
211
+ // 注意:URL 包含签名参数,必须完整保留,不能截断或修改
196
212
  const urlSummary = (successResult.files || [])
197
- .map((f: UploadedFileInfo) => `- [${f.name}](${f.downloadUrl || f.uri})`)
213
+ .map((f: UploadedFileInfo) => {
214
+ const url = f.downloadUrl || f.uri;
215
+ // 把完整 URL 作为代码块,防止 AI 截断或修改
216
+ return `- **${f.name}**: \`${url}\``;
217
+ })
198
218
  .join("\n");
199
219
 
220
+ api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] urlSummary: ${urlSummary}`);
221
+
200
222
  content.push({
201
223
  type: "text",
202
- text: `Files uploaded successfully:\n${urlSummary}\n\n⚠️ Note: Please include these download links in your response to the user and remind them that the links are valid for 24 hours.`,
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.`,
203
225
  });
204
226
 
205
227
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.45",
3
+ "version": "0.0.47",
4
4
  "description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
@@ -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}: ${text.slice(0, 50)}... (chunks=${chunkIndex})`);
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: 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}: ${text.slice(0, 50)}...`);
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: 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
  },