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 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
- import {
6
- ADP_UPLOAD_TOOL_NAME,
7
- ADP_UPLOAD_TOOL_SCHEMA,
8
- parseAdpUploadToolParams,
9
- uploadFilesToAdpEndpoint,
10
- uploadResultEmitter,
11
- UPLOAD_RESULT_EVENT,
12
- type AdpUploadToolResult,
13
- type UploadedFileInfo,
14
- } from "./src/adp-upload-tool.js";
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
- // Export session history functions for external use
17
- export {
18
- getOpenClawChatHistory,
19
- listOpenClawSessions,
20
- getSessionPreviews,
21
- getChatHistoryByConversationId,
22
- resolveSessionKey,
23
- configureSessionFileReader,
24
- getSessionFileConfig,
25
- // CLI-based functions
26
- getOpenClawChatHistoryViaCli,
27
- listOpenClawSessionsViaCli,
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
- // Export ADP upload tool functions and types
39
- export {
40
- // Tool name and schema
41
- ADP_UPLOAD_TOOL_NAME,
42
- ADP_UPLOAD_TOOL_SCHEMA,
43
- ADP_UPLOAD_TOOL_MAX_PATHS,
44
- ADP_UPLOAD_TOOL_MIN_PATHS,
45
- ADP_UPLOAD_TOOL_MAX_CONCURRENCY,
46
- ADP_UPLOAD_VALIDATION_MESSAGE,
47
- // Main functions
48
- adpUploadFile,
49
- adpUploadFiles,
50
- adpUploadFileWithConfig,
51
- adpUploadFilesWithConfig,
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
- // Export tool result message blocks functions
73
- export {
74
- dispatchToolResultToMessageBlocks,
75
- buildToolResultSessionContentBlocks,
76
- formatUploadResultForUser,
77
- formatUploadResultAsMarkdown,
78
- type ResourceLinkBlock,
79
- type TextBlock,
80
- type ContentBlock,
81
- type MessageBlock,
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
- // Log registration for debugging
95
- console.log("[adp-openclaw] register() called - starting plugin registration");
96
- api.logger.info?.("[adp-openclaw] Plugin register() called");
103
+ _registerCallCount++;
97
104
 
98
- setAdpOpenclawRuntime(api.runtime);
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
- // Register the ADP file upload tool as a factory function
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} paths=${JSON.stringify(parsed.value.paths)} error=${errorResult.error}`);
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} paths=${JSON.stringify(parsed.value.paths)}`);
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, // 也包含 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
- console.log("[adp-openclaw] Plugin registration complete");
261
- api.logger.info?.("[adp-openclaw] Plugin registration complete");
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.71",
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
- // @ts-ignore - import JSON file
29
- import packageJson from "../package.json" with { type: "json" };
30
-
31
- // Plugin version from package.json
32
- const PLUGIN_VERSION = packageJson.version;
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?.info?.(`[adp-openclaw] Session key not found in store for abort marking: ${sessionKey}`);
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?.info?.(`[adp-openclaw] Marked session ${matchedKey} as abortedLastRun=true`);
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?.info(`[adp-openclaw] TCP keepalive enabled`);
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?.info(`[adp-openclaw] Raw payload: ${JSON.stringify(msg.payload)}`);
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}, rec=${inMsg.recordId || 'none'}, user=${JSON.stringify(inMsg.user || {})})`);
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?.info(`[adp-openclaw] Received upload result event for toolCallId=${event.toolCallId}`);
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?.info(`[adp-openclaw] Upload result - file.downloadUrl: ${file.downloadUrl}`);
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?.info(`[adp-openclaw] Fixed LLM-corrupted URL for: ${basePath.substring(basePath.lastIndexOf("/") + 1)}`);
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?.info(`[adp-openclaw] Appending download link: ${file.downloadUrl.substring(0, 100)}...`);
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?.info(`[adp-openclaw] Added ${uploadLinks.length} download links to final response`);
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?.info(`[adp-openclaw] Sending outbound_end to ${displayName}: ${finalText.slice(0, 50)}... (chunks=${chunkIndex})`);
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?.info(`[adp-openclaw] Sending outbound to ${displayName}: ${finalText.slice(0, 50)}...`);
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?.info(`[adp-openclaw] Starting dispatchReplyWithBufferedBlockDispatcher for ${displayName}`);
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 - log the actual info object
629
- log?.info(`[adp-openclaw] deliver called: kind=${kind}, text.length=${text.length}, toolName=${payload.toolName || 'none'}, info=${JSON.stringify(info)}`);
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?.info(`[adp-openclaw] Tool result received: toolName=${toolName}, result=${JSON.stringify(toolResult)?.slice(0, 200)}`);
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?.info(`[adp-openclaw] File downloadUrl (full): ${file.downloadUrl}`);
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?.info(`[adp-openclaw] Sending upload result to user: ${uploadMessage.slice(0, 100)}...`);
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?.info(`[adp-openclaw] deliver triggering sendOutboundEnd (kind=${kind})`);
692
- log?.info(`[adp-openclaw] Final text content: ${text}`);
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?.info(`[adp-openclaw] dispatchReplyWithBufferedBlockDispatcher returned (finalSent=${finalSent}, chunkIndex=${chunkIndex})`);
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?.info(`[adp-openclaw] Generation cancelled, sending outbound_end with partial text`);
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?.info(`[adp-openclaw] dispatchReply completed without final, sending outbound_end (chunks=${chunkIndex})`);
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?.info(`[adp-openclaw] Received cancel request for conv=${cancelConvId}`);
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?.info(`[adp-openclaw] Generation cancelled for conv=${cancelConvId}`);
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?.info(`[adp-openclaw] Generation cancelled for conv=${id} (cancel-all)`);
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?.info(`[adp-openclaw] Received conv_history request: sessionKey=${historyPayload.sessionKey}, conversationId=${historyPayload.conversationId}`);
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?.info(`[adp-openclaw] Old format sessionKey detected, extracting id: ${extractedId}`);
804
- log?.info(`[adp-openclaw] Merging old and new session histories for id: ${extractedId}`);
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?.info(`[adp-openclaw] Using provided sessionKey: ${historyPayload.sessionKey}`);
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?.info(`[adp-openclaw] Merging old and new session histories for conversationId: ${historyPayload.conversationId}`);
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?.info(`[adp-openclaw] Using default session: main`);
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?.info(`[adp-openclaw] Sending conv_response: ${result.messages.length} messages (backend=cli)`);
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?.info(`[adp-openclaw] Received fetch_openclaw_sessions request: limit=${sessionsPayload.limit}, backend=${backend}`);
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?.info(`[adp-openclaw] Sending openclaw_sessions_response: ${result.sessions.length} sessions (backend=${backend})`);
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
+ }