adp-openclaw 0.0.71 → 0.0.73
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 +103 -104
- package/package.json +6 -1
- package/src/monitor.ts +48 -40
- package/tsconfig.json +23 -0
package/index.ts
CHANGED
|
@@ -1,84 +1,93 @@
|
|
|
1
1
|
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
2
|
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
3
|
+
|
|
4
|
+
// ============================================================================
|
|
5
|
+
// PERFORMANCE NOTE: This file is the plugin entry point loaded by openclaw at
|
|
6
|
+
// startup. Everything imported at the top level is evaluated **synchronously**
|
|
7
|
+
// during plugin discovery, blocking the entire startup sequence.
|
|
8
|
+
//
|
|
9
|
+
// Heavy modules (session-history, adp-upload-tool, tool-result-message-blocks)
|
|
10
|
+
// are therefore NOT imported at the top level. Instead they are:
|
|
11
|
+
// 1. Lazily re-exported via getter helpers (for external consumers).
|
|
12
|
+
// 2. Dynamically imported inside register() / tool-execute callbacks.
|
|
13
|
+
//
|
|
14
|
+
// This keeps register() fast (< 50 ms) and avoids blocking the scan phase.
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
// ---- Lightweight imports (tiny modules, no heavy deps) ----
|
|
3
18
|
import { adpOpenclawPlugin, type AdpOpenclawChannelConfig } from "./src/channel.js";
|
|
4
19
|
import { setAdpOpenclawRuntime } from "./src/runtime.js";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
20
|
+
// Type-only imports are erased at runtime — zero overhead
|
|
21
|
+
import type { AdpUploadToolResult, UploadedFileInfo } from "./src/adp-upload-tool.js";
|
|
22
|
+
|
|
23
|
+
// ---- Tool name / schema constants (inlined to avoid loading full upload module) ----
|
|
24
|
+
const ADP_UPLOAD_TOOL_NAME = "adp_upload_file";
|
|
25
|
+
const ADP_UPLOAD_TOOL_SCHEMA = {
|
|
26
|
+
type: "object" as const,
|
|
27
|
+
properties: {
|
|
28
|
+
paths: {
|
|
29
|
+
type: "array" as const,
|
|
30
|
+
items: { type: "string" as const },
|
|
31
|
+
description: "Array of 1-10 local file paths to upload",
|
|
32
|
+
minItems: 1,
|
|
33
|
+
maxItems: 10,
|
|
34
|
+
},
|
|
35
|
+
fileType: {
|
|
36
|
+
type: "string" as const,
|
|
37
|
+
description: "Optional MIME type hint for uploaded files",
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
required: ["paths"] as const,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Track whether register() has been called at least once (for log dedup)
|
|
44
|
+
let _registerCallCount = 0;
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Lazy re-exports for external consumers
|
|
48
|
+
// These are loaded on first access, not at plugin startup.
|
|
49
|
+
// ============================================================================
|
|
15
50
|
|
|
16
|
-
//
|
|
17
|
-
export {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// Auto-selecting functions
|
|
29
|
-
getChatHistory,
|
|
30
|
-
listSessions,
|
|
31
|
-
type OpenClawSession,
|
|
32
|
-
type OpenClawMessage,
|
|
33
|
-
type ChatHistoryResponse,
|
|
34
|
-
type SessionsListResponse,
|
|
35
|
-
type SessionFileConfig,
|
|
51
|
+
// Session history (heavy: node:child_process, node:fs, 1100+ lines)
|
|
52
|
+
export async function getSessionHistoryModule() {
|
|
53
|
+
return import("./src/session-history.js");
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Re-export types (type-only imports are free at runtime)
|
|
57
|
+
export type {
|
|
58
|
+
OpenClawSession,
|
|
59
|
+
OpenClawMessage,
|
|
60
|
+
ChatHistoryResponse,
|
|
61
|
+
SessionsListResponse,
|
|
62
|
+
SessionFileConfig,
|
|
36
63
|
} from "./src/session-history.js";
|
|
37
64
|
|
|
38
|
-
//
|
|
39
|
-
export {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
getStorageCredential,
|
|
53
|
-
uploadFileToCos,
|
|
54
|
-
resolveClientToken,
|
|
55
|
-
// Class
|
|
56
|
-
AdpUploader,
|
|
57
|
-
// Tool execution functions
|
|
58
|
-
parseAdpUploadToolParams,
|
|
59
|
-
uploadFilesToAdpEndpoint,
|
|
60
|
-
executeAdpUploadTool,
|
|
61
|
-
// Types
|
|
62
|
-
type UploadResult,
|
|
63
|
-
type AdpUploadToolParams,
|
|
64
|
-
type AdpUploadToolResult,
|
|
65
|
-
type UploadedFileInfo,
|
|
66
|
-
type AdpUploadOptions,
|
|
67
|
-
type DescribeRemoteBotStorageCredentialReq,
|
|
68
|
-
type DescribeRemoteBotStorageCredentialRsp,
|
|
69
|
-
type Credentials,
|
|
65
|
+
// ADP upload tool
|
|
66
|
+
export async function getAdpUploadToolModule() {
|
|
67
|
+
return import("./src/adp-upload-tool.js");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type {
|
|
71
|
+
UploadResult,
|
|
72
|
+
AdpUploadToolParams,
|
|
73
|
+
AdpUploadToolResult,
|
|
74
|
+
UploadedFileInfo,
|
|
75
|
+
AdpUploadOptions,
|
|
76
|
+
DescribeRemoteBotStorageCredentialReq,
|
|
77
|
+
DescribeRemoteBotStorageCredentialRsp,
|
|
78
|
+
Credentials,
|
|
70
79
|
} from "./src/adp-upload-tool.js";
|
|
71
80
|
|
|
72
|
-
//
|
|
73
|
-
export {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
81
|
+
// Tool result message blocks
|
|
82
|
+
export async function getToolResultMessageBlocksModule() {
|
|
83
|
+
return import("./src/tool-result-message-blocks.js");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type {
|
|
87
|
+
ResourceLinkBlock,
|
|
88
|
+
TextBlock,
|
|
89
|
+
ContentBlock,
|
|
90
|
+
MessageBlock,
|
|
82
91
|
} from "./src/tool-result-message-blocks.js";
|
|
83
92
|
|
|
84
93
|
// Helper to format tool result as JSON string
|
|
@@ -91,23 +100,19 @@ const plugin = {
|
|
|
91
100
|
description: "ADP channel plugin backed by a Go WebSocket server",
|
|
92
101
|
configSchema: emptyPluginConfigSchema(),
|
|
93
102
|
register(api: OpenClawPluginApi) {
|
|
94
|
-
|
|
95
|
-
console.log("[adp-openclaw] register() called - starting plugin registration");
|
|
96
|
-
api.logger.info?.("[adp-openclaw] Plugin register() called");
|
|
103
|
+
_registerCallCount++;
|
|
97
104
|
|
|
98
|
-
|
|
105
|
+
// Only log on first registration to avoid flooding logs
|
|
106
|
+
if (_registerCallCount === 1) {
|
|
107
|
+
api.logger.info?.("[adp-openclaw] Plugin register() called");
|
|
108
|
+
}
|
|
99
109
|
|
|
100
|
-
|
|
101
|
-
// Using a factory so the tool is only available when the message originates from the ADP channel.
|
|
102
|
-
// This prevents other channels (e.g. DingTalk) with multimodal models from picking up this tool.
|
|
103
|
-
console.log(`[adp-openclaw] Registering tool factory: ${ADP_UPLOAD_TOOL_NAME}`);
|
|
104
|
-
api.logger.info?.(`[adp-openclaw] Registering tool factory: ${ADP_UPLOAD_TOOL_NAME}`);
|
|
110
|
+
setAdpOpenclawRuntime(api.runtime);
|
|
105
111
|
|
|
106
112
|
api.registerTool((ctx: { messageChannel?: string; [key: string]: unknown }) => {
|
|
107
113
|
// Only expose this tool when the message comes from the adp-openclaw channel
|
|
108
114
|
const channel = ctx.messageChannel ?? "";
|
|
109
115
|
if (channel && channel !== "adp-openclaw") {
|
|
110
|
-
api.logger.debug?.(`[adp-openclaw] Skipping ${ADP_UPLOAD_TOOL_NAME} for channel: ${channel}`);
|
|
111
116
|
return null;
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -122,6 +127,14 @@ const plugin = {
|
|
|
122
127
|
"Parameters must be local filesystem paths only.",
|
|
123
128
|
parameters: ADP_UPLOAD_TOOL_SCHEMA,
|
|
124
129
|
async execute(toolCallId: string, params: unknown) {
|
|
130
|
+
// Lazy-load the heavy upload module only when the tool is actually invoked
|
|
131
|
+
const {
|
|
132
|
+
parseAdpUploadToolParams,
|
|
133
|
+
uploadFilesToAdpEndpoint,
|
|
134
|
+
uploadResultEmitter,
|
|
135
|
+
UPLOAD_RESULT_EVENT,
|
|
136
|
+
} = await import("./src/adp-upload-tool.js");
|
|
137
|
+
|
|
125
138
|
// Get bot token from channel config
|
|
126
139
|
const getClientToken = (): string | undefined => {
|
|
127
140
|
try {
|
|
@@ -157,7 +170,6 @@ const plugin = {
|
|
|
157
170
|
ok: false,
|
|
158
171
|
error: "missing bot token for file upload - please configure clientToken in adp-openclaw channel settings",
|
|
159
172
|
};
|
|
160
|
-
api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] token missing toolCallId=${toolCallId} paths=${JSON.stringify(parsed.value.paths)}`);
|
|
161
173
|
return {
|
|
162
174
|
output: errorResult,
|
|
163
175
|
result: errorResult,
|
|
@@ -178,7 +190,7 @@ const plugin = {
|
|
|
178
190
|
ok: false,
|
|
179
191
|
error: formatToolResultJson(uploadResult.error),
|
|
180
192
|
};
|
|
181
|
-
api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] upload failed toolCallId=${toolCallId}
|
|
193
|
+
api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] upload failed toolCallId=${toolCallId} error=${errorResult.error}`);
|
|
182
194
|
return {
|
|
183
195
|
output: errorResult,
|
|
184
196
|
result: errorResult,
|
|
@@ -194,14 +206,8 @@ const plugin = {
|
|
|
194
206
|
files: uploadResult.files,
|
|
195
207
|
};
|
|
196
208
|
|
|
197
|
-
api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] upload success toolCallId=${toolCallId} count=${successResult.files?.length ?? 0}
|
|
209
|
+
api.logger.debug?.(`[${ADP_UPLOAD_TOOL_NAME}] upload success toolCallId=${toolCallId} count=${successResult.files?.length ?? 0}`);
|
|
198
210
|
|
|
199
|
-
// Debug: print full downloadUrl for each file
|
|
200
|
-
for (const file of (successResult.files || [])) {
|
|
201
|
-
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.downloadUrl: ${file.downloadUrl}`);
|
|
202
|
-
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] file.uri: ${file.uri}`);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
211
|
// 发射上传结果事件,让 monitor.ts 能够直接获取完整的下载链接
|
|
206
212
|
uploadResultEmitter.emit(UPLOAD_RESULT_EVENT, {
|
|
207
213
|
toolCallId,
|
|
@@ -215,25 +221,21 @@ const plugin = {
|
|
|
215
221
|
for (const file of (successResult.files || [])) {
|
|
216
222
|
content.push({
|
|
217
223
|
type: "resource_link",
|
|
218
|
-
uri: file.downloadUrl || file.uri,
|
|
224
|
+
uri: file.downloadUrl || file.uri,
|
|
219
225
|
name: file.name,
|
|
220
226
|
mimeType: file.mimeType,
|
|
221
|
-
downloadUrl: file.downloadUrl,
|
|
227
|
+
downloadUrl: file.downloadUrl,
|
|
222
228
|
});
|
|
223
229
|
}
|
|
224
230
|
|
|
225
231
|
// Add a text summary with download URLs for AI to include in response
|
|
226
|
-
// 注意:URL 包含签名参数,必须完整保留,不能截断或修改
|
|
227
232
|
const urlSummary = (successResult.files || [])
|
|
228
233
|
.map((f: UploadedFileInfo) => {
|
|
229
234
|
const url = f.downloadUrl || f.uri;
|
|
230
|
-
// 把完整 URL 作为代码块,防止 AI 截断或修改
|
|
231
235
|
return `- **${f.name}**: \`${url}\``;
|
|
232
236
|
})
|
|
233
237
|
.join("\n");
|
|
234
238
|
|
|
235
|
-
api.logger.info?.(`[${ADP_UPLOAD_TOOL_NAME}] urlSummary: ${urlSummary}`);
|
|
236
|
-
|
|
237
239
|
content.push({
|
|
238
240
|
type: "text",
|
|
239
241
|
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.`,
|
|
@@ -249,16 +251,13 @@ const plugin = {
|
|
|
249
251
|
},
|
|
250
252
|
}; // end of tool object
|
|
251
253
|
}); // end of factory function passed to registerTool
|
|
252
|
-
|
|
253
|
-
// Log tool registration success
|
|
254
|
-
console.log(`[adp-openclaw] Tool ${ADP_UPLOAD_TOOL_NAME} registered successfully`);
|
|
255
|
-
api.logger.info?.(`[adp-openclaw] Tool ${ADP_UPLOAD_TOOL_NAME} registered successfully`);
|
|
256
254
|
|
|
257
|
-
// Register the channel plugin
|
|
255
|
+
// Register the channel plugin (channel.ts + onboarding.ts are lightweight config-only modules)
|
|
258
256
|
api.registerChannel({ plugin: adpOpenclawPlugin });
|
|
259
257
|
|
|
260
|
-
|
|
261
|
-
|
|
258
|
+
if (_registerCallCount === 1) {
|
|
259
|
+
api.logger.info?.("[adp-openclaw] Plugin registration complete");
|
|
260
|
+
}
|
|
262
261
|
},
|
|
263
262
|
};
|
|
264
263
|
|
package/package.json
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "adp-openclaw",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.73",
|
|
4
4
|
"description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"main": "index.ts",
|
|
6
7
|
"dependencies": {
|
|
7
8
|
"ws": "^8.16.0",
|
|
8
9
|
"zod": "^3.22.4"
|
|
9
10
|
},
|
|
11
|
+
"peerDependencies": {
|
|
12
|
+
"openclaw": "*"
|
|
13
|
+
},
|
|
10
14
|
"devDependencies": {
|
|
11
15
|
"@types/node": "^20.11.0",
|
|
12
16
|
"@types/ws": "^8.5.10",
|
|
17
|
+
"openclaw": ">=2026.3.0",
|
|
13
18
|
"typescript": "^5.9.3"
|
|
14
19
|
},
|
|
15
20
|
"openclaw": {
|
package/src/monitor.ts
CHANGED
|
@@ -25,11 +25,19 @@ import {
|
|
|
25
25
|
} from "./tool-result-message-blocks.js";
|
|
26
26
|
import crypto from "crypto";
|
|
27
27
|
import fs from "fs";
|
|
28
|
-
|
|
29
|
-
import
|
|
30
|
-
|
|
31
|
-
//
|
|
32
|
-
|
|
28
|
+
import { fileURLToPath } from "node:url";
|
|
29
|
+
import { dirname, join } from "node:path";
|
|
30
|
+
|
|
31
|
+
// Read plugin version from package.json (lazy, at module load time — not at register() time)
|
|
32
|
+
let PLUGIN_VERSION = "unknown";
|
|
33
|
+
try {
|
|
34
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
35
|
+
const __dirname = dirname(__filename);
|
|
36
|
+
const pkg = JSON.parse(fs.readFileSync(join(__dirname, "..", "package.json"), "utf-8"));
|
|
37
|
+
PLUGIN_VERSION = pkg.version || "unknown";
|
|
38
|
+
} catch {
|
|
39
|
+
// Fallback — version string is cosmetic only
|
|
40
|
+
}
|
|
33
41
|
|
|
34
42
|
// WebSocket reconnect delay (fixed at 1 second)
|
|
35
43
|
const RECONNECT_DELAY_MS = 1000;
|
|
@@ -153,14 +161,14 @@ async function markSessionAborted(params: {
|
|
|
153
161
|
}
|
|
154
162
|
|
|
155
163
|
if (!matchedKey) {
|
|
156
|
-
log?.
|
|
164
|
+
log?.debug?.(`[adp-openclaw] Session key not found in store for abort marking: ${sessionKey}`);
|
|
157
165
|
return;
|
|
158
166
|
}
|
|
159
167
|
|
|
160
168
|
store[matchedKey].abortedLastRun = true;
|
|
161
169
|
store[matchedKey].updatedAt = Date.now();
|
|
162
170
|
fs.writeFileSync(storePath, JSON.stringify(store, null, 2), "utf-8");
|
|
163
|
-
log?.
|
|
171
|
+
log?.debug?.(`[adp-openclaw] Marked session ${matchedKey} as abortedLastRun=true`);
|
|
164
172
|
} catch (err) {
|
|
165
173
|
log?.error?.(`[adp-openclaw] Failed to mark session aborted: ${err}`);
|
|
166
174
|
}
|
|
@@ -238,7 +246,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
238
246
|
const socket = (ws as any)._socket;
|
|
239
247
|
if (socket && typeof socket.setKeepAlive === 'function') {
|
|
240
248
|
socket.setKeepAlive(true, 30000); // 30秒
|
|
241
|
-
log?.
|
|
249
|
+
log?.debug?.(`[adp-openclaw] TCP keepalive enabled`);
|
|
242
250
|
}
|
|
243
251
|
|
|
244
252
|
// Save active WebSocket for outbound messaging
|
|
@@ -310,10 +318,10 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
310
318
|
setStatus?.({ lastEventAt: inboundAt, lastInboundAt: inboundAt });
|
|
311
319
|
|
|
312
320
|
// Debug: log raw payload to verify recordId is received
|
|
313
|
-
log?.
|
|
321
|
+
log?.debug?.(`[adp-openclaw] Raw payload: ${JSON.stringify(msg.payload)}`);
|
|
314
322
|
|
|
315
323
|
const inMsg = msg.payload as InboundMessage;
|
|
316
|
-
log?.info(`[adp-openclaw] Received: ${inMsg.from}: ${inMsg.text} (conv=${inMsg.conversationId}
|
|
324
|
+
log?.info(`[adp-openclaw] Received: ${inMsg.from}: ${inMsg.text.slice(0, 80)} (conv=${inMsg.conversationId})`);
|
|
317
325
|
|
|
318
326
|
// Process the message with full user identity
|
|
319
327
|
const convIdForCleanup = inMsg.conversationId || `fallback-${Date.now()}`;
|
|
@@ -458,12 +466,12 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
458
466
|
|
|
459
467
|
// 监听上传结果事件
|
|
460
468
|
const uploadResultHandler = (event: { toolCallId: string; result: AdpUploadToolResult }) => {
|
|
461
|
-
log?.
|
|
469
|
+
log?.debug?.(`[adp-openclaw] Received upload result event for toolCallId=${event.toolCallId}`);
|
|
462
470
|
if (event.result.ok && event.result.files && event.result.files.length > 0) {
|
|
463
471
|
pendingUploadResults.push(event.result);
|
|
464
472
|
// 打印完整的下载链接
|
|
465
473
|
for (const file of event.result.files) {
|
|
466
|
-
log?.
|
|
474
|
+
log?.debug?.(`[adp-openclaw] Upload result - file.downloadUrl: ${file.downloadUrl}`);
|
|
467
475
|
}
|
|
468
476
|
}
|
|
469
477
|
};
|
|
@@ -507,7 +515,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
507
515
|
const before = finalText;
|
|
508
516
|
finalText = finalText.replace(pattern, correctUrl);
|
|
509
517
|
if (finalText !== before) {
|
|
510
|
-
log?.
|
|
518
|
+
log?.debug?.(`[adp-openclaw] Fixed LLM-corrupted URL for: ${basePath.substring(basePath.lastIndexOf("/") + 1)}`);
|
|
511
519
|
}
|
|
512
520
|
}
|
|
513
521
|
}
|
|
@@ -518,18 +526,18 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
518
526
|
if (file.downloadUrl) {
|
|
519
527
|
// 使用完整的下载链接,包括签名参数
|
|
520
528
|
uploadLinks.push(`📎 [${file.name}](${file.downloadUrl})`);
|
|
521
|
-
log?.
|
|
529
|
+
log?.debug?.(`[adp-openclaw] Appending download link: ${file.downloadUrl.substring(0, 100)}...`);
|
|
522
530
|
}
|
|
523
531
|
}
|
|
524
532
|
}
|
|
525
533
|
if (uploadLinks.length > 0) {
|
|
526
534
|
finalText += `\n\n**文件下载链接(24小时有效):**\n${uploadLinks.join("\n")}`;
|
|
527
|
-
log?.
|
|
535
|
+
log?.debug?.(`[adp-openclaw] Added ${uploadLinks.length} download links to final response`);
|
|
528
536
|
}
|
|
529
537
|
}
|
|
530
538
|
|
|
531
539
|
if (chunkIndex > 0) {
|
|
532
|
-
log?.
|
|
540
|
+
log?.debug?.(`[adp-openclaw] Sending outbound_end to ${displayName}: ${finalText.slice(0, 50)}... (chunks=${chunkIndex})`);
|
|
533
541
|
const endMsg: WSMessage = {
|
|
534
542
|
type: MsgType.OutboundEnd,
|
|
535
543
|
requestId: generateRequestId(),
|
|
@@ -547,7 +555,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
547
555
|
ws.send(JSON.stringify(endMsg));
|
|
548
556
|
} else {
|
|
549
557
|
// No streaming chunks were sent, send as regular outbound message
|
|
550
|
-
log?.
|
|
558
|
+
log?.debug?.(`[adp-openclaw] Sending outbound to ${displayName}: ${finalText.slice(0, 50)}...`);
|
|
551
559
|
const outMsg: WSMessage = {
|
|
552
560
|
type: MsgType.Outbound,
|
|
553
561
|
requestId: generateRequestId(),
|
|
@@ -564,7 +572,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
564
572
|
}
|
|
565
573
|
};
|
|
566
574
|
|
|
567
|
-
log?.
|
|
575
|
+
log?.debug?.(`[adp-openclaw] Starting dispatchReplyWithBufferedBlockDispatcher for ${displayName}`);
|
|
568
576
|
await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
569
577
|
ctx,
|
|
570
578
|
cfg: cfg ?? {},
|
|
@@ -625,8 +633,8 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
625
633
|
const text = payload.text || "";
|
|
626
634
|
const kind = info?.kind;
|
|
627
635
|
|
|
628
|
-
// Debug log for all deliver calls
|
|
629
|
-
log?.
|
|
636
|
+
// Debug log for all deliver calls
|
|
637
|
+
log?.debug?.(`[adp-openclaw] deliver called: kind=${kind}, text.length=${text.length}, toolName=${payload.toolName || 'none'}`);
|
|
630
638
|
|
|
631
639
|
// Handle streaming block - IGNORE because handlePartial already sent deltas
|
|
632
640
|
// The "block" callback contains cumulative text (same as final), not incremental delta
|
|
@@ -641,7 +649,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
641
649
|
const toolName = payload.toolName;
|
|
642
650
|
const toolResult = payload.toolResult;
|
|
643
651
|
|
|
644
|
-
log?.
|
|
652
|
+
log?.debug?.(`[adp-openclaw] Tool result received: toolName=${toolName}, result=${JSON.stringify(toolResult)?.slice(0, 200)}`);
|
|
645
653
|
|
|
646
654
|
// If it's our upload tool and it succeeded, send file links to user
|
|
647
655
|
if (toolName === ADP_UPLOAD_TOOL_NAME && toolResult && typeof toolResult === "object") {
|
|
@@ -649,13 +657,13 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
649
657
|
if (result.ok && result.files && result.files.length > 0) {
|
|
650
658
|
// Debug: print full downloadUrl before formatting
|
|
651
659
|
for (const file of result.files) {
|
|
652
|
-
log?.
|
|
660
|
+
log?.debug?.(`[adp-openclaw] File downloadUrl (full): ${file.downloadUrl}`);
|
|
653
661
|
}
|
|
654
662
|
|
|
655
663
|
// Format upload result as user-readable message
|
|
656
664
|
const uploadMessage = formatUploadResultAsMarkdown(result);
|
|
657
665
|
|
|
658
|
-
log?.
|
|
666
|
+
log?.debug?.(`[adp-openclaw] Sending upload result to user: ${uploadMessage.slice(0, 100)}...`);
|
|
659
667
|
|
|
660
668
|
// Send the file links as a message chunk
|
|
661
669
|
const chunkMsg: WSMessage = {
|
|
@@ -688,8 +696,8 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
688
696
|
// Handle final reply or undefined kind - send outbound_end
|
|
689
697
|
// SDK may call deliver without kind when streaming ends
|
|
690
698
|
if (kind === "final" || kind === undefined) {
|
|
691
|
-
log?.
|
|
692
|
-
log?.
|
|
699
|
+
log?.debug?.(`[adp-openclaw] deliver triggering sendOutboundEnd (kind=${kind})`);
|
|
700
|
+
log?.debug?.(`[adp-openclaw] Final text content: ${text?.slice(0, 100)}`);
|
|
693
701
|
sendOutboundEnd(text || lastPartialText);
|
|
694
702
|
}
|
|
695
703
|
},
|
|
@@ -699,7 +707,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
699
707
|
},
|
|
700
708
|
});
|
|
701
709
|
|
|
702
|
-
log?.
|
|
710
|
+
log?.debug?.(`[adp-openclaw] dispatchReplyWithBufferedBlockDispatcher returned (finalSent=${finalSent}, chunkIndex=${chunkIndex})`);
|
|
703
711
|
|
|
704
712
|
// Clean up active generation tracking
|
|
705
713
|
activeGenerations.delete(convId);
|
|
@@ -707,7 +715,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
707
715
|
// If generation was cancelled (aborted), send outbound_end with partial text
|
|
708
716
|
if (generationController.signal.aborted && !finalSent) {
|
|
709
717
|
const cancelText = lastPartialText ? `${lastPartialText}\n\n[已停止生成]` : "[已停止生成]";
|
|
710
|
-
log?.
|
|
718
|
+
log?.debug?.(`[adp-openclaw] Generation cancelled, sending outbound_end with partial text`);
|
|
711
719
|
sendOutboundEnd(cancelText);
|
|
712
720
|
|
|
713
721
|
// Mark the session as aborted so the SDK injects an "abort hint"
|
|
@@ -728,7 +736,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
728
736
|
if (!finalSent && chunkIndex > 0) {
|
|
729
737
|
// Use the last accumulated partial text as the final text
|
|
730
738
|
const finalText = lastPartialText || "";
|
|
731
|
-
log?.
|
|
739
|
+
log?.debug?.(`[adp-openclaw] dispatchReply completed without final, sending outbound_end (chunks=${chunkIndex})`);
|
|
732
740
|
sendOutboundEnd(finalText);
|
|
733
741
|
}
|
|
734
742
|
} catch (err) {
|
|
@@ -755,17 +763,17 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
755
763
|
if (!authenticated) break;
|
|
756
764
|
const cancelPayload = msg.payload as { conversationId?: string; streamId?: string };
|
|
757
765
|
const cancelConvId = cancelPayload.conversationId || cancelPayload.streamId;
|
|
758
|
-
log?.
|
|
766
|
+
log?.debug?.(`[adp-openclaw] Received cancel request for conv=${cancelConvId}`);
|
|
759
767
|
|
|
760
768
|
if (cancelConvId && activeGenerations.has(cancelConvId)) {
|
|
761
769
|
activeGenerations.get(cancelConvId)!.abort();
|
|
762
|
-
log?.
|
|
770
|
+
log?.debug?.(`[adp-openclaw] Generation cancelled for conv=${cancelConvId}`);
|
|
763
771
|
} else {
|
|
764
772
|
// If no specific convId, cancel all active generations
|
|
765
773
|
if (!cancelConvId && activeGenerations.size > 0) {
|
|
766
774
|
for (const [id, controller] of activeGenerations) {
|
|
767
775
|
controller.abort();
|
|
768
|
-
log?.
|
|
776
|
+
log?.debug?.(`[adp-openclaw] Generation cancelled for conv=${id} (cancel-all)`);
|
|
769
777
|
}
|
|
770
778
|
} else {
|
|
771
779
|
log?.warn(`[adp-openclaw] No active generation found for conv=${cancelConvId}`);
|
|
@@ -784,7 +792,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
784
792
|
limit?: number;
|
|
785
793
|
};
|
|
786
794
|
|
|
787
|
-
log?.
|
|
795
|
+
log?.debug?.(`[adp-openclaw] Received conv_history request: sessionKey=${historyPayload.sessionKey}, conversationId=${historyPayload.conversationId}`);
|
|
788
796
|
|
|
789
797
|
try {
|
|
790
798
|
const limit = historyPayload.limit ?? 200;
|
|
@@ -800,15 +808,15 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
800
808
|
// Old: agent:main:direct:{conversationId}
|
|
801
809
|
// New: agent:main:adp-openclaw:direct:{conversationId}
|
|
802
810
|
const extractedId = oldFormatMatch[1];
|
|
803
|
-
log?.
|
|
804
|
-
log?.
|
|
811
|
+
log?.debug?.(`[adp-openclaw] Old format sessionKey detected, extracting id: ${extractedId}`);
|
|
812
|
+
log?.debug?.(`[adp-openclaw] Merging old and new session histories for id: ${extractedId}`);
|
|
805
813
|
result = await getMergedChatHistory(extractedId, {
|
|
806
814
|
limit,
|
|
807
815
|
log,
|
|
808
816
|
});
|
|
809
817
|
} else if (historyPayload.sessionKey) {
|
|
810
818
|
// Non-old-format sessionKey, use directly
|
|
811
|
-
log?.
|
|
819
|
+
log?.debug?.(`[adp-openclaw] Using provided sessionKey: ${historyPayload.sessionKey}`);
|
|
812
820
|
result = await getChatHistory(historyPayload.sessionKey, {
|
|
813
821
|
limit,
|
|
814
822
|
log,
|
|
@@ -817,21 +825,21 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
817
825
|
// If conversationId is provided, merge old and new session histories
|
|
818
826
|
// Old format: agent:main:direct:{conversationId}
|
|
819
827
|
// New format: agent:main:adp-openclaw:direct:{conversationId}
|
|
820
|
-
log?.
|
|
828
|
+
log?.debug?.(`[adp-openclaw] Merging old and new session histories for conversationId: ${historyPayload.conversationId}`);
|
|
821
829
|
result = await getMergedChatHistory(historyPayload.conversationId, {
|
|
822
830
|
limit,
|
|
823
831
|
log,
|
|
824
832
|
});
|
|
825
833
|
} else {
|
|
826
834
|
// Default to "main" session
|
|
827
|
-
log?.
|
|
835
|
+
log?.debug?.(`[adp-openclaw] Using default session: main`);
|
|
828
836
|
result = await getChatHistory("main", {
|
|
829
837
|
limit,
|
|
830
838
|
log,
|
|
831
839
|
});
|
|
832
840
|
}
|
|
833
841
|
|
|
834
|
-
log?.
|
|
842
|
+
log?.debug?.(`[adp-openclaw] Sending conv_response: ${result.messages.length} messages (backend=cli)`);
|
|
835
843
|
|
|
836
844
|
// Send response back to GoServer
|
|
837
845
|
const responseMsg: WSMessage = {
|
|
@@ -871,7 +879,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
871
879
|
|
|
872
880
|
const backend = sessionsPayload.backend || "auto";
|
|
873
881
|
|
|
874
|
-
log?.
|
|
882
|
+
log?.debug?.(`[adp-openclaw] Received fetch_openclaw_sessions request: limit=${sessionsPayload.limit}, backend=${backend}`);
|
|
875
883
|
|
|
876
884
|
try {
|
|
877
885
|
// Use unified listSessions with backend selection
|
|
@@ -882,7 +890,7 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
|
|
|
882
890
|
backend,
|
|
883
891
|
});
|
|
884
892
|
|
|
885
|
-
log?.
|
|
893
|
+
log?.debug?.(`[adp-openclaw] Sending openclaw_sessions_response: ${result.sessions.length} sessions (backend=${backend})`);
|
|
886
894
|
|
|
887
895
|
// Send response back to GoServer
|
|
888
896
|
const responseMsg: WSMessage = {
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"noEmit": true,
|
|
7
|
+
"strict": false,
|
|
8
|
+
"noImplicitAny": false,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true
|
|
14
|
+
},
|
|
15
|
+
"include": [
|
|
16
|
+
"index.ts",
|
|
17
|
+
"src/**/*.ts"
|
|
18
|
+
],
|
|
19
|
+
"exclude": [
|
|
20
|
+
"node_modules",
|
|
21
|
+
"**/*.test.ts"
|
|
22
|
+
]
|
|
23
|
+
}
|