adp-openclaw 0.0.62 → 0.0.64

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adp-openclaw",
3
- "version": "0.0.62",
3
+ "version": "0.0.64",
4
4
  "description": "ADP-OpenClaw demo channel plugin (Go WebSocket backend)",
5
5
  "type": "module",
6
6
  "dependencies": {
package/src/channel.ts CHANGED
@@ -216,6 +216,7 @@ export const adpOpenclawPlugin: ChannelPlugin<ResolvedAdpOpenclawAccount> = {
216
216
  abortSignal: ctx.abortSignal,
217
217
  log: ctx.log,
218
218
  cfg: ctx.cfg,
219
+ setStatus: ctx.setStatus,
219
220
  });
220
221
  },
221
222
  },
package/src/monitor.ts CHANGED
@@ -40,6 +40,7 @@ export type MonitorParams = {
40
40
  abortSignal?: AbortSignal;
41
41
  log?: PluginLogger;
42
42
  cfg?: ClawdbotConfig; // OpenClaw config for model settings
43
+ setStatus?: (next: Record<string, unknown>) => void; // SDK health-monitor status reporter
43
44
  };
44
45
 
45
46
  // WebSocket message types
@@ -165,7 +166,7 @@ async function markSessionAborted(params: {
165
166
  }
166
167
 
167
168
  export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
168
- const { wsUrl, clientToken, signKey, abortSignal, log, cfg } = params;
169
+ const { wsUrl, clientToken, signKey, abortSignal, log, cfg, setStatus } = params;
169
170
  const runtime = getAdpOpenclawRuntime();
170
171
 
171
172
  log?.info(`[adp-openclaw] WebSocket monitor started, connecting to ${wsUrl}`);
@@ -180,6 +181,7 @@ export async function monitorAdpOpenclaw(params: MonitorParams): Promise<void> {
180
181
  log,
181
182
  runtime,
182
183
  cfg,
184
+ setStatus,
183
185
  });
184
186
  } catch (err) {
185
187
  if (abortSignal?.aborted) break;
@@ -204,10 +206,11 @@ type ConnectParams = {
204
206
  log?: PluginLogger;
205
207
  runtime: ReturnType<typeof getAdpOpenclawRuntime>;
206
208
  cfg?: ClawdbotConfig;
209
+ setStatus?: (next: Record<string, unknown>) => void;
207
210
  };
208
211
 
209
212
  async function connectAndHandle(params: ConnectParams): Promise<void> {
210
- const { wsUrl, clientToken, signKey, abortSignal, log, runtime, cfg } = params;
213
+ const { wsUrl, clientToken, signKey, abortSignal, log, runtime, cfg, setStatus } = params;
211
214
 
212
215
  // Dynamic import for WebSocket (works in both Node.js and browser)
213
216
  const WebSocket = (await import("ws")).default;
@@ -272,6 +275,10 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
272
275
  authenticated = true;
273
276
  log?.info(`[adp-openclaw] Plugin v${PLUGIN_VERSION} authenticated as client ${result.clientId}`);
274
277
 
278
+ // Report connected status to SDK health-monitor
279
+ const now = Date.now();
280
+ setStatus?.({ connected: true, lastConnectedAt: now, lastEventAt: now });
281
+
275
282
  // Start ping interval
276
283
  pingInterval = setInterval(() => {
277
284
  if (ws.readyState === WebSocket.OPEN) {
@@ -290,12 +297,17 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
290
297
  }
291
298
 
292
299
  case MsgType.Pong:
293
- // Heartbeat response, connection is alive
300
+ // Heartbeat response — update lastEventAt so health-monitor knows connection is alive
301
+ setStatus?.({ lastEventAt: Date.now() });
294
302
  break;
295
303
 
296
304
  case MsgType.Inbound: {
297
305
  if (!authenticated) break;
298
306
 
307
+ // Report inbound event to SDK health-monitor
308
+ const inboundAt = Date.now();
309
+ setStatus?.({ lastEventAt: inboundAt, lastInboundAt: inboundAt });
310
+
299
311
  // Debug: log raw payload to verify recordId is received
300
312
  log?.info(`[adp-openclaw] Raw payload: ${JSON.stringify(msg.payload)}`);
301
313
 
@@ -326,15 +338,27 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
326
338
 
327
339
  // Use resolveAgentRoute to get proper sessionKey (like QQBot does)
328
340
  // This ensures session history is correctly associated
329
- const peerId = inMsg.conversationId;
341
+ //
342
+ // Use "per-channel-peer" so the session key includes the channel name:
343
+ // agent:main:adp-openclaw:direct:{userId}
344
+ // This is critical for cron job delivery inference — inferDeliveryFromSessionKey()
345
+ // parses the session key to extract channel and target user:
346
+ // channel = "adp-openclaw", to = "{userId}"
347
+ // Without the channel in the key, cron delivery defaults to channel:"last" which
348
+ // fails when multiple channels (adp-openclaw, wecom, etc.) are configured.
349
+ //
350
+ // We use the user identifier (not conversationId) as peerId because:
351
+ // 1. The outbound delivery target is the userId (inMsg.from), not the conversationId
352
+ // 2. inferDeliveryFromSessionKey extracts peerId as the delivery "to" field
353
+ const peerId = userIdentifier;
330
354
  const route = runtime.channel.routing.resolveAgentRoute({
331
355
  cfg: {
332
356
  ...(cfg ?? {}),
333
357
  session: {
334
358
  ...(cfg?.session ?? {}),
335
- // Override dmScope to "per-peer" so each user gets their own session
336
- // This prevents all DM users from sharing the same "main" session
337
- dmScope: "per-peer",
359
+ // Override dmScope to "per-channel-peer" so session key encodes channel + userId
360
+ // Session key format: agent:main:adp-openclaw:direct:{userId}
361
+ dmScope: "per-channel-peer",
338
362
  },
339
363
  },
340
364
  channel: "adp-openclaw",
@@ -849,6 +873,8 @@ async function connectAndHandle(params: ConnectParams): Promise<void> {
849
873
  abortSignal?.removeEventListener("abort", abortHandler);
850
874
  // Clear active WebSocket when connection closes
851
875
  setActiveWebSocket(null);
876
+ // Report disconnected status to SDK health-monitor
877
+ setStatus?.({ connected: false, lastEventAt: Date.now() });
852
878
  log?.info(`[adp-openclaw] WebSocket closed: ${code} ${reason.toString()}`);
853
879
  resolve();
854
880
  });
@@ -243,8 +243,13 @@ function readSessionTranscript(
243
243
  if (parsed.type === "session") {
244
244
  continue;
245
245
  }
246
- // Extract message if present
246
+ // Extract message if present, skip tool-related roles (toolResult, tool)
247
247
  if (parsed.message && parsed.message.role && parsed.message.content) {
248
+ // Filter out tool-related messages for cleaner display
249
+ const role = parsed.message.role;
250
+ if (role === "toolResult" || role === "tool") {
251
+ continue;
252
+ }
248
253
  const msg: OpenClawMessage = {
249
254
  role: parsed.message.role,
250
255
  content: extractMessageContent(parsed.message.content),