@efengx/openclaw-channel-dragon 0.5.28 → 0.5.30

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.
@@ -125,7 +125,7 @@ export class ChannelComponent {
125
125
  const current = previous
126
126
  .catch(() => { })
127
127
  .then(async () => {
128
- logger?.info?.(`[Dragon Plugin] v${dragonChannelPluginVersion} Sending to OpenClaw: "${content.substring(0, 50)}${content.length > 50 ? '...' : ''}" [WorkbenchSession: ${sessionId}] [OpenClawSessionKey: ${sessionKey}]`);
128
+ logger?.info?.(`[dragon channels][Dragon Plugin] v${dragonChannelPluginVersion} Sending to OpenClaw: "${content.substring(0, 50)}${content.length > 50 ? '...' : ''}" [WorkbenchSession: ${sessionId}] [OpenClawSessionKey: ${sessionKey}]`);
129
129
  const progress = (payload) => this.telemetry.reportProgress({
130
130
  sessionId,
131
131
  msgId: replyMsgId,
@@ -284,7 +284,7 @@ export class ChannelComponent {
284
284
  });
285
285
  }
286
286
  catch (err) {
287
- logger?.error?.(`[Dragon Plugin] Error during replyDispatcher: ${err?.message || err}`);
287
+ logger?.error?.(`[dragon channels][Dragon Plugin] Error during replyDispatcher: ${err?.message || err}`);
288
288
  let resolvedErrorMessage = err?.message || String(err);
289
289
  const isTakeoverError = resolvedErrorMessage.includes("session file changed while embedded prompt lock was released");
290
290
  if (isTakeoverError) {
@@ -303,7 +303,7 @@ export class ChannelComponent {
303
303
  const item = JSON.parse(lines[i]);
304
304
  if (item.type === "message" && item.stopReason === "error" && item.errorMessage) {
305
305
  resolvedErrorMessage = item.errorMessage;
306
- logger?.warn?.(`[Dragon Plugin] Extracted real underlying error from session file: ${resolvedErrorMessage}`);
306
+ logger?.warn?.(`[dragon channels][Dragon Plugin] Extracted real underlying error from session file: ${resolvedErrorMessage}`);
307
307
  break;
308
308
  }
309
309
  }
@@ -314,7 +314,7 @@ export class ChannelComponent {
314
314
  }
315
315
  }
316
316
  catch (fsErr) {
317
- logger?.error?.(`[Dragon Plugin] Failed to read real error from session file: ${fsErr}`);
317
+ logger?.error?.(`[dragon channels][Dragon Plugin] Failed to read real error from session file: ${fsErr}`);
318
318
  }
319
319
  }
320
320
  // Check for insufficient spending cap/quota error and provide a friendly Chinese message
@@ -355,7 +355,7 @@ export class ChannelComponent {
355
355
  handleOutboundText = async (ctx) => {
356
356
  const text = ctx?.text || "";
357
357
  const { logger } = this.options;
358
- logger?.info?.(`[Dragon Plugin] Outbound Text (Action): "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`);
358
+ logger?.info?.(`[dragon channels][Dragon Plugin] Outbound Text (Action): "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}"`);
359
359
  await this.telemetry.reportReply({ content: text, sessionId: ctx?.peer?.id || "default", source: "channel_outbound" });
360
360
  return { ok: true, messageId: Date.now().toString() };
361
361
  };
@@ -4,7 +4,7 @@ export class HttpComponent {
4
4
  this.options = options;
5
5
  }
6
6
  async start() {
7
- this.options.logger?.info?.(`[Dragon-Channel] HttpComponent started for ${this.options.baseURL}`);
7
+ this.options.logger?.info?.(`[dragon channels][Dragon-Channel] HttpComponent started for ${this.options.baseURL}`);
8
8
  }
9
9
  async stop() { }
10
10
  async fetch(path, init) {
@@ -20,7 +20,7 @@ export class HttpComponent {
20
20
  headers
21
21
  });
22
22
  if (!res.ok && res.status !== 404) {
23
- this.options.logger?.warn?.(`[Dragon-Channel] HTTP Request failed: ${res.status} ${url}`);
23
+ this.options.logger?.warn?.(`[dragon channels][Dragon-Channel] HTTP Request failed: ${res.status} ${url}`);
24
24
  }
25
25
  return res;
26
26
  }
@@ -24,7 +24,7 @@ export class SseComponent {
24
24
  return;
25
25
  const { agentId, logger } = this.options;
26
26
  const url = `${this.http.options.baseURL}/api/agents/events`;
27
- logger?.info?.(`[Dragon Plugin] v${this.options.version} connecting to Orchestrator SSE: ${url} (agent=${agentId})`);
27
+ logger?.info?.(`[dragon channels][Dragon Plugin] v${this.options.version} connecting to Orchestrator SSE: ${url} (agent=${agentId})`);
28
28
  try {
29
29
  // In Node 22, we might need a fetch-based SSE or a library,
30
30
  // but for simplicity we'll use the same pattern as Bridge if possible.
@@ -33,7 +33,7 @@ export class SseComponent {
33
33
  this.startSseReader(url);
34
34
  }
35
35
  catch (err) {
36
- logger?.error?.(`[Dragon Plugin] SSE Init Failed: ${err.message}`);
36
+ logger?.error?.(`[dragon channels][Dragon Plugin] SSE Init Failed: ${err.message}`);
37
37
  this.scheduleReconnect();
38
38
  }
39
39
  }
@@ -51,7 +51,7 @@ export class SseComponent {
51
51
  const reader = response.body?.getReader();
52
52
  if (!reader)
53
53
  throw new Error("Response body is null");
54
- this.options.logger?.debug?.(`[Dragon Plugin] SSE Stream Established.`);
54
+ this.options.logger?.debug?.(`[dragon channels][Dragon Plugin] SSE Stream Established.`);
55
55
  const decoder = new TextDecoder();
56
56
  let buffer = "";
57
57
  while (this.shouldReconnect) {
@@ -62,21 +62,24 @@ export class SseComponent {
62
62
  const lines = buffer.split("\n");
63
63
  buffer = lines.pop() || "";
64
64
  for (const line of lines) {
65
- if (line.startsWith("data: ")) {
65
+ const cleanLine = line.trim();
66
+ if (cleanLine.startsWith("data: ")) {
66
67
  try {
67
- const data = JSON.parse(line.slice(6));
68
+ const data = JSON.parse(cleanLine.slice(6));
68
69
  void this.handleEvent(data).catch((err) => {
69
- this.options.logger?.error?.(`[Dragon Plugin] SSE event handling failed: ${err?.message || err}`);
70
+ this.options.logger?.error?.(`[dragon channels][Dragon Plugin] SSE event handling failed: ${err?.message || err}`);
70
71
  });
71
72
  }
72
- catch (e) { }
73
+ catch (e) {
74
+ this.options.logger?.error?.(`[dragon channels][Dragon Plugin] SSE event JSON parse failed for line: "${cleanLine}", error: ${e?.message || e}`);
75
+ }
73
76
  }
74
77
  }
75
78
  }
76
79
  }
77
80
  catch (err) {
78
81
  if (this.shouldReconnect) {
79
- this.options.logger?.warn?.(`[Dragon Plugin] SSE Stream Disconnected: ${err.message}`);
82
+ this.options.logger?.warn?.(`[dragon channels][Dragon Plugin] SSE Stream Disconnected: ${err.message}`);
80
83
  this.scheduleReconnect();
81
84
  }
82
85
  }
@@ -89,12 +92,12 @@ export class SseComponent {
89
92
  // 2. Handle specific types
90
93
  if (data.type === 'WORKBENCH_MESSAGE') {
91
94
  const { content, sessionId, attachments, id, msgId } = data.payload || {};
92
- logger?.info?.(`[Dragon Plugin] v${this.options.version} [SSE] Received from Workbench: "${content?.substring(0, 50)}${content?.length > 50 ? '...' : ''}" [Session: ${sessionId}]`);
95
+ logger?.info?.(`[dragon channels][Dragon Plugin] v${this.options.version} [SSE] Received from Workbench: "${content?.substring(0, 50)}${content?.length > 50 ? '...' : ''}" [Session: ${sessionId}]`);
93
96
  await this.channel.deliverToOpenClaw(content, sessionId, undefined, attachments, msgId || id);
94
97
  }
95
98
  else if (data.type === 'FETCH_HISTORY') {
96
99
  const { sessionId } = data.payload || {};
97
- logger?.info?.(`[Dragon Plugin] Triggering history sync for session: ${sessionId}`);
100
+ logger?.info?.(`[dragon channels][Dragon Plugin] Triggering history sync for session: ${sessionId}`);
98
101
  // Handle history sync if needed, but deliverToOpenClaw usually handles normal chat
99
102
  }
100
103
  }
package/dist/index.js CHANGED
@@ -28,11 +28,15 @@ async function getOrCreateContainer(account, ctx) {
28
28
  return containers.get(key);
29
29
  const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
30
30
  const container = new ServiceContainer();
31
- logger?.info?.(`[Dragon Plugin] Starting channel plugin v${dragonChannelPluginVersion} for agent=${account.agentId}, account=${account.accountId}, orchestrator=${account.orchestratorUrl}`);
31
+ logger?.info?.(`[dragon channels][Dragon Plugin] Starting channel plugin v${dragonChannelPluginVersion} for agent=${account.agentId}, account=${account.accountId}, orchestrator=${account.orchestratorUrl}`);
32
32
  // 1. Core Infrastructure
33
33
  const http = container.register('http', new HttpComponent({
34
34
  baseURL: account.orchestratorUrl,
35
- authToken: account.orchestratorAuthToken || process.env.DRAGON_ORCHESTRATOR_AUTH_TOKEN || process.env.DRAGON_GATEWAY_TOKEN,
35
+ authToken: account.orchestratorAuthToken ||
36
+ process.env.DRAGON_ORCHESTRATOR_AUTH_TOKEN ||
37
+ process.env.DRAGON_GATEWAY_TOKEN ||
38
+ process.env.GATEWAY_TOKEN ||
39
+ process.env.OPENCLAW_GATEWAY_AUTH_TOKEN,
36
40
  logger
37
41
  }));
38
42
  const telemetry = container.register('telemetry', new TelemetryComponent(http, account.agentId));
@@ -159,46 +163,57 @@ const plugin = createChatChannelPlugin({
159
163
  },
160
164
  handleAction: async (ctx) => {
161
165
  const { action, params, cfg, accountId } = ctx;
166
+ const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
167
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction start: action=${action}, accountId=${accountId}, paramsKeys=${Object.keys(params || {})}`);
162
168
  if (action === "send") {
163
169
  const account = base.config.resolveAccount(cfg, accountId);
164
170
  const container = await getOrCreateContainer(account, ctx);
165
171
  const channel = container.get('channel');
166
172
  let target = params.to || params.target || ctx.toolContext?.currentChannelId || "default";
173
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolution input: ${target}`);
167
174
  for (const prefix of ["dragon-workbench-", "dragon-workbench:", "dragon-", "dragon:"]) {
168
175
  if (target.startsWith(prefix)) {
169
176
  target = target.substring(prefix.length);
170
177
  }
171
178
  }
172
179
  const sessionId = target || "default";
180
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolved: sessionId=${sessionId}, rawTarget=${target}`);
173
181
  // Collect ALL media URLs from the params (mirrors what OpenClaw tracks internally
174
182
  // via collectMessagingMediaUrlsFromRecord when the tool call starts, so that
175
183
  // hasGatewayAgentDeliveredExpectedMedia can match them against expectedMediaUrls).
176
184
  const sentMediaUrls = [];
177
- const pushMedia = (v) => {
178
- if (typeof v === 'string' && v.trim())
179
- sentMediaUrls.push(v.trim());
185
+ const pushMedia = (v, source) => {
186
+ if (typeof v === 'string' && v.trim()) {
187
+ const url = v.trim();
188
+ sentMediaUrls.push(url);
189
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction extracted media URL from ${source}: ${url}`);
190
+ }
180
191
  };
181
- pushMedia(params.media);
182
- pushMedia(params.mediaUrl);
183
- pushMedia(params.path);
184
- pushMedia(params.filePath);
185
- pushMedia(params.fileUrl);
192
+ pushMedia(params.media, "params.media");
193
+ pushMedia(params.mediaUrl, "params.mediaUrl");
194
+ pushMedia(params.path, "params.path");
195
+ pushMedia(params.filePath, "params.filePath");
196
+ pushMedia(params.fileUrl, "params.fileUrl");
186
197
  if (Array.isArray(params.mediaUrls)) {
198
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction found params.mediaUrls array, size=${params.mediaUrls.length}`);
187
199
  for (const u of params.mediaUrls)
188
- pushMedia(u);
200
+ pushMedia(u, "params.mediaUrls");
189
201
  }
190
202
  if (Array.isArray(params.attachments)) {
203
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction found params.attachments array, size=${params.attachments.length}`);
191
204
  for (const a of params.attachments) {
192
205
  if (a && typeof a === 'object') {
193
- pushMedia(a.media);
194
- pushMedia(a.mediaUrl);
195
- pushMedia(a.path);
196
- pushMedia(a.filePath);
197
- pushMedia(a.fileUrl);
206
+ pushMedia(a.media, "attachment.media");
207
+ pushMedia(a.mediaUrl, "attachment.mediaUrl");
208
+ pushMedia(a.path, "attachment.path");
209
+ pushMedia(a.filePath, "attachment.filePath");
210
+ pushMedia(a.fileUrl, "attachment.fileUrl");
198
211
  }
199
212
  }
200
213
  }
214
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction total media URLs extracted: count=${sentMediaUrls.length}, urls=${JSON.stringify(sentMediaUrls)}`);
201
215
  let text = params.message || params.text || "";
216
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction base message text length: ${text.length}`);
202
217
  // Append media path to text so the Workbench can render the image
203
218
  for (const url of sentMediaUrls) {
204
219
  const mediaLine = `MEDIA: ${url}`;
@@ -206,11 +221,13 @@ const plugin = createChatChannelPlugin({
206
221
  text = text ? `${text}\n${mediaLine}` : mediaLine;
207
222
  }
208
223
  }
224
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction sending text over channel: text_len=${text.length}, targetSession=${sessionId}`);
209
225
  const result = await channel.handleOutboundText({
210
226
  text,
211
227
  peer: { id: sessionId }
212
228
  });
213
- return {
229
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction channel send result: ok=${result.ok}, messageId=${result.messageId || "none"}`);
230
+ const evidence = {
214
231
  ok: result.ok,
215
232
  ...result.messageId ? { messageId: result.messageId } : {},
216
233
  // Evidence fields that OpenClaw checks via hasMessagingToolDeliveryEvidence
@@ -220,7 +237,10 @@ const plugin = createChatChannelPlugin({
220
237
  messagingToolSentMediaUrls: sentMediaUrls,
221
238
  messagingToolSentTargets: [{ to: target, ...(sentMediaUrls.length > 0 ? { mediaUrls: sentMediaUrls } : {}) }],
222
239
  };
240
+ logger?.info?.(`[dragon channels][Dragon Plugin] handleAction returning evidence to OpenClaw: didSendViaMessagingTool=${evidence.didSendViaMessagingTool}, sentMediaUrlsCount=${evidence.messagingToolSentMediaUrls.length}`);
241
+ return evidence;
223
242
  }
243
+ logger?.warn?.(`[dragon channels][Dragon Plugin] handleAction action "${action}" is not supported. Ignoring.`);
224
244
  throw new Error(`Action "${action}" is not supported by the dragon channel plugin.`);
225
245
  }
226
246
  }
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const dragonChannelPluginVersion = "0.5.28";
1
+ export declare const dragonChannelPluginVersion = "0.5.30";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const dragonChannelPluginVersion = "0.5.28";
1
+ export const dragonChannelPluginVersion = "0.5.30";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@efengx/openclaw-channel-dragon",
3
- "version": "0.5.28",
3
+ "version": "0.5.30",
4
4
  "description": "Dragon workbench channel for OpenClaw",
5
5
  "author": "feng xiang <ofengx@gmail.com>",
6
6
  "type": "module",