@efengx/openclaw-channel-dragon 0.5.32 → 0.5.33
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.
|
@@ -16,6 +16,8 @@ export declare class ChannelComponent implements IComponent {
|
|
|
16
16
|
start(): Promise<void>;
|
|
17
17
|
stop(): Promise<void>;
|
|
18
18
|
private normalizeSessionSegment;
|
|
19
|
+
private encodeWorkbenchTarget;
|
|
20
|
+
private decodeWorkbenchTarget;
|
|
19
21
|
private resolveOpenClawAgentId;
|
|
20
22
|
private buildOpenClawSessionKey;
|
|
21
23
|
private resolveWorkbenchSessionIdFromOpenClawSessionKey;
|
|
@@ -27,6 +29,12 @@ export declare class ChannelComponent implements IComponent {
|
|
|
27
29
|
handleOutboundText: (ctx: any) => Promise<{
|
|
28
30
|
ok: boolean;
|
|
29
31
|
messageId: string;
|
|
32
|
+
error: any;
|
|
33
|
+
} | {
|
|
34
|
+
ok: boolean;
|
|
35
|
+
messageId: string;
|
|
36
|
+
error?: undefined;
|
|
30
37
|
}>;
|
|
38
|
+
reportTargetProtocolError: (message: string, rawTarget: unknown) => Promise<void>;
|
|
31
39
|
handleAgentEvent: (evt: any) => Promise<void>;
|
|
32
40
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { dragonChannelPluginVersion } from "../../version.js";
|
|
2
2
|
const channelId = "dragon";
|
|
3
|
+
const workbenchTargetPrefix = "dragon-workbench:";
|
|
3
4
|
export class ChannelComponent {
|
|
4
5
|
options;
|
|
5
6
|
telemetry;
|
|
@@ -20,6 +21,21 @@ export class ChannelComponent {
|
|
|
20
21
|
.slice(0, 64);
|
|
21
22
|
return normalized || fallback;
|
|
22
23
|
}
|
|
24
|
+
encodeWorkbenchTarget(sessionId) {
|
|
25
|
+
const value = String(sessionId || 'default').trim() || 'default';
|
|
26
|
+
return `${workbenchTargetPrefix}${value}`;
|
|
27
|
+
}
|
|
28
|
+
decodeWorkbenchTarget(value) {
|
|
29
|
+
const target = String(value || '').trim();
|
|
30
|
+
if (!target.startsWith(workbenchTargetPrefix)) {
|
|
31
|
+
throw new Error(`Invalid dragon workbench target "${target || '<empty>'}"; expected "${workbenchTargetPrefix}<sessionId>"`);
|
|
32
|
+
}
|
|
33
|
+
const sessionId = target.slice(workbenchTargetPrefix.length).trim();
|
|
34
|
+
if (!sessionId) {
|
|
35
|
+
throw new Error(`Invalid dragon workbench target "${target}"; sessionId is empty`);
|
|
36
|
+
}
|
|
37
|
+
return sessionId;
|
|
38
|
+
}
|
|
23
39
|
resolveOpenClawAgentId() {
|
|
24
40
|
const agents = this.options.cfg?.agents?.list;
|
|
25
41
|
if (Array.isArray(agents)) {
|
|
@@ -136,7 +152,7 @@ export class ChannelComponent {
|
|
|
136
152
|
ctx: {
|
|
137
153
|
Body: content,
|
|
138
154
|
From: sessionId === 'default' ? "workbench-user" : `workbench-user-${sessionId}`,
|
|
139
|
-
To: sessionId
|
|
155
|
+
To: this.encodeWorkbenchTarget(sessionId),
|
|
140
156
|
ChatType: "direct",
|
|
141
157
|
Provider: channelId,
|
|
142
158
|
ChannelId: channelId,
|
|
@@ -355,10 +371,34 @@ export class ChannelComponent {
|
|
|
355
371
|
handleOutboundText = async (ctx) => {
|
|
356
372
|
const text = ctx?.text || "";
|
|
357
373
|
const { logger } = this.options;
|
|
358
|
-
|
|
359
|
-
|
|
374
|
+
let sessionId;
|
|
375
|
+
try {
|
|
376
|
+
sessionId = this.decodeWorkbenchTarget(ctx?.peer?.id);
|
|
377
|
+
}
|
|
378
|
+
catch (error) {
|
|
379
|
+
const message = error?.message || String(error);
|
|
380
|
+
logger?.error?.(`[dragon channels][Dragon Plugin] outbound target protocol error: ${message}`);
|
|
381
|
+
await this.reportTargetProtocolError(message, ctx?.peer?.id);
|
|
382
|
+
return { ok: false, messageId: Date.now().toString(), error: message };
|
|
383
|
+
}
|
|
384
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] Outbound Text (Action): "${text.substring(0, 50)}${text.length > 50 ? '...' : ''}" [Session: ${sessionId}] [RawPeer: ${ctx?.peer?.id || 'none'}]`);
|
|
385
|
+
await this.telemetry.reportReply({ content: text, sessionId, source: "channel_outbound" });
|
|
360
386
|
return { ok: true, messageId: Date.now().toString() };
|
|
361
387
|
};
|
|
388
|
+
reportTargetProtocolError = async (message, rawTarget) => {
|
|
389
|
+
const content = [
|
|
390
|
+
'⚠️ Dragon channel target 协议错误。',
|
|
391
|
+
`错误信息:${message}`,
|
|
392
|
+
`收到的 target:${String(rawTarget || '<empty>')}`,
|
|
393
|
+
`期望格式:${workbenchTargetPrefix}<sessionId>`,
|
|
394
|
+
].join('\n');
|
|
395
|
+
await this.telemetry.reportReply({
|
|
396
|
+
content,
|
|
397
|
+
sessionId: 'default',
|
|
398
|
+
source: 'target_protocol_error',
|
|
399
|
+
msgId: `dragon_target_error_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
|
|
400
|
+
});
|
|
401
|
+
};
|
|
362
402
|
handleAgentEvent = async (evt) => {
|
|
363
403
|
const sessionId = evt?.sessionId ||
|
|
364
404
|
this.resolveWorkbenchSessionIdFromOpenClawSessionKey(evt?.sessionKey);
|
|
@@ -56,7 +56,13 @@ export class SseComponent {
|
|
|
56
56
|
if (!this.shouldReconnect)
|
|
57
57
|
return;
|
|
58
58
|
const { agentId, logger } = this.options;
|
|
59
|
-
const
|
|
59
|
+
const params = new URLSearchParams({
|
|
60
|
+
client: 'dragon-channel',
|
|
61
|
+
agentId,
|
|
62
|
+
accountId: this.options.accountId,
|
|
63
|
+
version: this.options.version,
|
|
64
|
+
});
|
|
65
|
+
const url = `${this.http.options.baseURL}/api/agents/events?${params.toString()}`;
|
|
60
66
|
const connectionId = `${Date.now()}-${++this.connectionSeq}`;
|
|
61
67
|
logger?.info?.(`[dragon channels][SSE] connect start: connection=${connectionId}, attempt=${this.reconnectAttempts + 1}, version=${this.options.version}, url=${url}, agent=${agentId}, account=${this.options.accountId}`);
|
|
62
68
|
try {
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ChannelComponent } from "./components/channel/ChannelComponent.js";
|
|
|
8
8
|
import { SseComponent } from "./components/sync/SseComponent.js";
|
|
9
9
|
import { dragonChannelPluginVersion } from "./version.js";
|
|
10
10
|
const channelId = "dragon";
|
|
11
|
+
const workbenchTargetPrefix = "dragon-workbench:";
|
|
11
12
|
let cachedRuntime;
|
|
12
13
|
const containers = new Map();
|
|
13
14
|
function isDragonSessionKey(sessionKey) {
|
|
@@ -22,6 +23,21 @@ function resolveAccountIdFromSessionKey(sessionKey) {
|
|
|
22
23
|
}
|
|
23
24
|
return "default";
|
|
24
25
|
}
|
|
26
|
+
function encodeWorkbenchTarget(sessionId) {
|
|
27
|
+
const value = String(sessionId || "default").trim() || "default";
|
|
28
|
+
return `${workbenchTargetPrefix}${value}`;
|
|
29
|
+
}
|
|
30
|
+
function decodeWorkbenchTarget(raw) {
|
|
31
|
+
const target = String(raw || "").trim();
|
|
32
|
+
if (!target.startsWith(workbenchTargetPrefix)) {
|
|
33
|
+
throw new Error(`Invalid dragon workbench target "${target || "<empty>"}"; expected "${workbenchTargetPrefix}<sessionId>"`);
|
|
34
|
+
}
|
|
35
|
+
const sessionId = target.slice(workbenchTargetPrefix.length).trim();
|
|
36
|
+
if (!sessionId) {
|
|
37
|
+
throw new Error(`Invalid dragon workbench target "${target}"; sessionId is empty`);
|
|
38
|
+
}
|
|
39
|
+
return sessionId;
|
|
40
|
+
}
|
|
25
41
|
function containerKey(account) {
|
|
26
42
|
return `${account.accountId}:${account.agentId}:${account.orchestratorUrl}`;
|
|
27
43
|
}
|
|
@@ -161,25 +177,13 @@ const plugin = createChatChannelPlugin({
|
|
|
161
177
|
}
|
|
162
178
|
},
|
|
163
179
|
messaging: {
|
|
164
|
-
targetPrefixes: [
|
|
180
|
+
targetPrefixes: [workbenchTargetPrefix],
|
|
165
181
|
normalizeTarget: (raw) => {
|
|
166
|
-
|
|
167
|
-
for (const prefix of ["dragon-workbench-", "dragon-workbench:", "dragon-", "dragon:"]) {
|
|
168
|
-
if (target.startsWith(prefix)) {
|
|
169
|
-
target = target.substring(prefix.length);
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
return target ? `dragon-workbench-${target}` : "";
|
|
182
|
+
return encodeWorkbenchTarget(decodeWorkbenchTarget(raw));
|
|
173
183
|
},
|
|
174
184
|
resolveOutboundSessionRoute: (params) => {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if (target.startsWith(prefix)) {
|
|
178
|
-
target = target.substring(prefix.length);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (!target)
|
|
182
|
-
return null;
|
|
185
|
+
const sessionId = decodeWorkbenchTarget(params.target);
|
|
186
|
+
const target = encodeWorkbenchTarget(sessionId);
|
|
183
187
|
return buildChannelOutboundSessionRoute({
|
|
184
188
|
cfg: params.cfg,
|
|
185
189
|
agentId: params.agentId,
|
|
@@ -187,27 +191,22 @@ const plugin = createChatChannelPlugin({
|
|
|
187
191
|
accountId: params.accountId,
|
|
188
192
|
peer: {
|
|
189
193
|
kind: "direct",
|
|
190
|
-
id:
|
|
194
|
+
id: sessionId
|
|
191
195
|
},
|
|
192
196
|
chatType: "direct",
|
|
193
|
-
from:
|
|
194
|
-
to:
|
|
197
|
+
from: target,
|
|
198
|
+
to: target
|
|
195
199
|
});
|
|
196
200
|
},
|
|
197
201
|
targetResolver: {
|
|
198
202
|
looksLikeId: (raw) => {
|
|
199
|
-
return raw.startsWith(
|
|
203
|
+
return raw.startsWith(workbenchTargetPrefix);
|
|
200
204
|
},
|
|
201
|
-
hint: "
|
|
205
|
+
hint: "dragon-workbench:<sessionId>",
|
|
202
206
|
resolveTarget: async ({ input }) => {
|
|
203
|
-
|
|
204
|
-
for (const prefix of ["dragon-workbench-", "dragon-workbench:", "dragon-", "dragon:"]) {
|
|
205
|
-
if (sessionId.startsWith(prefix)) {
|
|
206
|
-
sessionId = sessionId.substring(prefix.length);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
207
|
+
const sessionId = decodeWorkbenchTarget(input);
|
|
209
208
|
return {
|
|
210
|
-
to:
|
|
209
|
+
to: encodeWorkbenchTarget(sessionId),
|
|
211
210
|
kind: "direct",
|
|
212
211
|
display: `Dragon Workbench User (${sessionId})`,
|
|
213
212
|
source: "normalized"
|
|
@@ -227,15 +226,28 @@ const plugin = createChatChannelPlugin({
|
|
|
227
226
|
const account = base.config.resolveAccount(cfg, accountId);
|
|
228
227
|
const container = await getOrCreateContainer(account, ctx);
|
|
229
228
|
const channel = container.get('channel');
|
|
230
|
-
|
|
231
|
-
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolution input: ${
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
229
|
+
const rawTarget = params.to || params.target || ctx.toolContext?.currentChannelId || "default";
|
|
230
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolution input: ${rawTarget}`);
|
|
231
|
+
let sessionId;
|
|
232
|
+
let target;
|
|
233
|
+
try {
|
|
234
|
+
sessionId = decodeWorkbenchTarget(rawTarget);
|
|
235
|
+
target = encodeWorkbenchTarget(sessionId);
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
const message = error?.message || String(error);
|
|
239
|
+
logger?.error?.(`[dragon channels][Dragon Plugin] handleAction target protocol error: ${message}`);
|
|
240
|
+
await channel.reportTargetProtocolError(message, rawTarget);
|
|
241
|
+
return {
|
|
242
|
+
ok: false,
|
|
243
|
+
error: message,
|
|
244
|
+
didSendViaMessagingTool: false,
|
|
245
|
+
messagingToolSentTexts: [],
|
|
246
|
+
messagingToolSentMediaUrls: [],
|
|
247
|
+
messagingToolSentTargets: [],
|
|
248
|
+
};
|
|
236
249
|
}
|
|
237
|
-
|
|
238
|
-
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolved: sessionId=${sessionId}, rawTarget=${target}`);
|
|
250
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction target resolved: sessionId=${sessionId}, target=${target}, rawTarget=${rawTarget}`);
|
|
239
251
|
// Collect ALL media URLs from the params (mirrors what OpenClaw tracks internally
|
|
240
252
|
// via collectMessagingMediaUrlsFromRecord when the tool call starts, so that
|
|
241
253
|
// hasGatewayAgentDeliveredExpectedMedia can match them against expectedMediaUrls).
|
|
@@ -282,7 +294,7 @@ const plugin = createChatChannelPlugin({
|
|
|
282
294
|
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction sending text over channel: text_len=${text.length}, targetSession=${sessionId}`);
|
|
283
295
|
const result = await channel.handleOutboundText({
|
|
284
296
|
text,
|
|
285
|
-
peer: { id:
|
|
297
|
+
peer: { id: target }
|
|
286
298
|
});
|
|
287
299
|
logger?.info?.(`[dragon channels][Dragon Plugin] handleAction channel send result: ok=${result.ok}, messageId=${result.messageId || "none"}`);
|
|
288
300
|
const evidence = {
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const dragonChannelPluginVersion = "0.5.
|
|
1
|
+
export declare const dragonChannelPluginVersion = "0.5.33";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const dragonChannelPluginVersion = "0.5.
|
|
1
|
+
export const dragonChannelPluginVersion = "0.5.33";
|