adp-openclaw 0.0.49 → 0.0.51
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 +1 -1
- package/src/adp-upload-tool.ts +10 -1
- package/src/channel.ts +62 -26
- package/src/monitor.ts +7 -0
package/package.json
CHANGED
package/src/adp-upload-tool.ts
CHANGED
|
@@ -518,7 +518,7 @@ export const ADP_UPLOAD_TOOL_NAME = "adp_upload_file";
|
|
|
518
518
|
|
|
519
519
|
const ADP_UPLOAD_TOOL_SCHEMA_TITLE = "ADP file upload";
|
|
520
520
|
const ADP_UPLOAD_TOOL_SCHEMA_DESCRIPTION =
|
|
521
|
-
"Upload local files from this machine to ADP storage. If the call succeeds, the files are uploaded and signed download URLs are returned. The user can access the files via these URLs.";
|
|
521
|
+
"Upload local files from this machine to ADP storage. If the call succeeds, the files are uploaded and signed download URLs are returned. The user can access the files via these URLs. IMPORTANT: When presenting download links to users, format them as clickable Markdown links like [filename](url), do NOT wrap URLs in code blocks or backticks.";
|
|
522
522
|
const ADP_UPLOAD_TOOL_PATHS_DESCRIPTION =
|
|
523
523
|
"Local filesystem paths only (1-10 total). Any file type is accepted, including text, images, documents, PDFs, archives, and binary files. Use absolute or workspace-relative local paths that are readable files.";
|
|
524
524
|
|
|
@@ -659,6 +659,8 @@ export interface UploadedFileInfo {
|
|
|
659
659
|
export interface AdpUploadToolResult {
|
|
660
660
|
ok: boolean;
|
|
661
661
|
files?: UploadedFileInfo[];
|
|
662
|
+
/** 预格式化的消息,AI 可以直接展示给用户(不要用代码块包装) */
|
|
663
|
+
message?: string;
|
|
662
664
|
error?: {
|
|
663
665
|
code: number;
|
|
664
666
|
message: string;
|
|
@@ -769,9 +771,16 @@ export const uploadFilesToAdpEndpoint = async (
|
|
|
769
771
|
}
|
|
770
772
|
);
|
|
771
773
|
|
|
774
|
+
// 构建预格式化的消息,告诉 AI 如何展示给用户
|
|
775
|
+
const formattedLinks = uploadResults.map(f =>
|
|
776
|
+
`- [${f.name}](${f.downloadUrl})`
|
|
777
|
+
).join("\n");
|
|
778
|
+
const message = `Files uploaded successfully. Present these download links to the user as clickable Markdown links (do NOT use code blocks):\n${formattedLinks}`;
|
|
779
|
+
|
|
772
780
|
return {
|
|
773
781
|
ok: true,
|
|
774
782
|
files: uploadResults,
|
|
783
|
+
message,
|
|
775
784
|
};
|
|
776
785
|
} catch (error) {
|
|
777
786
|
return {
|
package/src/channel.ts
CHANGED
|
@@ -219,42 +219,78 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
|
|
|
219
219
|
});
|
|
220
220
|
},
|
|
221
221
|
},
|
|
222
|
-
// Outbound message support for the "message" tool
|
|
222
|
+
// Outbound message support for the "message" tool and cron tasks
|
|
223
223
|
outbound: {
|
|
224
|
-
|
|
224
|
+
deliveryMode: "direct",
|
|
225
|
+
|
|
226
|
+
// Send text message
|
|
227
|
+
sendText: async (ctx) => {
|
|
228
|
+
const { to, text } = ctx;
|
|
225
229
|
const ws = getActiveWebSocket();
|
|
230
|
+
|
|
226
231
|
if (!ws) {
|
|
227
|
-
|
|
228
|
-
|
|
232
|
+
console.error("[adp-openclaw] No active WebSocket connection for outbound message");
|
|
233
|
+
throw new Error("No active WebSocket connection");
|
|
229
234
|
}
|
|
230
235
|
|
|
231
|
-
// Parse target: expected format is "adp-openclaw:{userId}" or "
|
|
232
|
-
// The "to" parameter comes from the message tool with format like "adp-openclaw:user123"
|
|
236
|
+
// Parse target: expected format is "adp-openclaw:{userId}" or just "{userId}"
|
|
233
237
|
const targetParts = to.split(":");
|
|
234
238
|
const targetUserId = targetParts.length > 1 ? targetParts.slice(1).join(":") : to;
|
|
235
239
|
|
|
236
|
-
log
|
|
240
|
+
console.log(`[adp-openclaw] Sending outbound text to ${targetUserId}: ${text.slice(0, 50)}...`);
|
|
241
|
+
|
|
242
|
+
// Generate unique request ID
|
|
243
|
+
const requestId = `outbound-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
244
|
+
|
|
245
|
+
const outMsg = {
|
|
246
|
+
type: "outbound",
|
|
247
|
+
requestId,
|
|
248
|
+
payload: {
|
|
249
|
+
to: targetUserId,
|
|
250
|
+
text: text,
|
|
251
|
+
},
|
|
252
|
+
timestamp: Date.now(),
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
ws.send(JSON.stringify(outMsg));
|
|
256
|
+
return { channel: "adp-openclaw", messageId: requestId };
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
// Send media message (text with optional media URL)
|
|
260
|
+
sendMedia: async (ctx) => {
|
|
261
|
+
const { to, text, mediaUrl } = ctx;
|
|
262
|
+
const ws = getActiveWebSocket();
|
|
237
263
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
const outMsg = {
|
|
243
|
-
type: "outbound",
|
|
244
|
-
requestId,
|
|
245
|
-
payload: {
|
|
246
|
-
to: targetUserId,
|
|
247
|
-
text: text,
|
|
248
|
-
},
|
|
249
|
-
timestamp: Date.now(),
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
ws.send(JSON.stringify(outMsg));
|
|
253
|
-
return { ok: true };
|
|
254
|
-
} catch (err) {
|
|
255
|
-
log?.error?.(`[adp-openclaw] Failed to send outbound message: ${err}`);
|
|
256
|
-
return { ok: false, error: String(err) };
|
|
264
|
+
if (!ws) {
|
|
265
|
+
console.error("[adp-openclaw] No active WebSocket connection for outbound media");
|
|
266
|
+
throw new Error("No active WebSocket connection");
|
|
257
267
|
}
|
|
268
|
+
|
|
269
|
+
// Parse target
|
|
270
|
+
const targetParts = to.split(":");
|
|
271
|
+
const targetUserId = targetParts.length > 1 ? targetParts.slice(1).join(":") : to;
|
|
272
|
+
|
|
273
|
+
console.log(`[adp-openclaw] Sending outbound media to ${targetUserId}: ${text.slice(0, 50)}... (media: ${mediaUrl || "none"})`);
|
|
274
|
+
|
|
275
|
+
// Generate unique request ID
|
|
276
|
+
const requestId = `outbound-media-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
277
|
+
|
|
278
|
+
// Combine text and media URL if present
|
|
279
|
+
const finalText = mediaUrl ? `${text}\n\n📎 ${mediaUrl}` : text;
|
|
280
|
+
|
|
281
|
+
const outMsg = {
|
|
282
|
+
type: "outbound",
|
|
283
|
+
requestId,
|
|
284
|
+
payload: {
|
|
285
|
+
to: targetUserId,
|
|
286
|
+
text: finalText,
|
|
287
|
+
mediaUrl: mediaUrl,
|
|
288
|
+
},
|
|
289
|
+
timestamp: Date.now(),
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
ws.send(JSON.stringify(outMsg));
|
|
293
|
+
return { channel: "adp-openclaw", messageId: requestId };
|
|
258
294
|
},
|
|
259
295
|
},
|
|
260
296
|
};
|
package/src/monitor.ts
CHANGED
|
@@ -177,6 +177,13 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
177
177
|
ws.on("open", () => {
|
|
178
178
|
log?.info(`[adp-openclaw] WebSocket connected, authenticating...`);
|
|
179
179
|
|
|
180
|
+
// 设置 TCP keepalive(作为额外保障)
|
|
181
|
+
const socket = (ws as any)._socket;
|
|
182
|
+
if (socket && typeof socket.setKeepAlive === 'function') {
|
|
183
|
+
socket.setKeepAlive(true, 30000); // 30秒
|
|
184
|
+
log?.info(`[adp-openclaw] TCP keepalive enabled`);
|
|
185
|
+
}
|
|
186
|
+
|
|
180
187
|
// Save active WebSocket for outbound messaging
|
|
181
188
|
setActiveWebSocket(ws);
|
|
182
189
|
|