@efengx/openclaw-channel-dragon 0.5.30 → 0.5.32
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/dist/components/sync/SseComponent.d.ts +14 -1
- package/dist/components/sync/SseComponent.js +165 -19
- package/dist/index.js +74 -16
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -5,17 +5,30 @@ export declare class SseComponent implements IComponent {
|
|
|
5
5
|
private http;
|
|
6
6
|
private channel;
|
|
7
7
|
private options;
|
|
8
|
-
private eventSource;
|
|
9
8
|
private shouldReconnect;
|
|
10
9
|
private reconnectTimer;
|
|
10
|
+
private idleTimer;
|
|
11
|
+
private fetchAbort;
|
|
12
|
+
private reader;
|
|
13
|
+
private reconnectAttempts;
|
|
14
|
+
private connectionSeq;
|
|
15
|
+
private lastTransportActivityAt;
|
|
11
16
|
constructor(http: HttpComponent, channel: ChannelComponent, options: {
|
|
12
17
|
agentId: string;
|
|
18
|
+
accountId: string;
|
|
13
19
|
version: string;
|
|
14
20
|
logger?: any;
|
|
21
|
+
abortSignal?: AbortSignal;
|
|
22
|
+
setStatus?: (next: Record<string, unknown>) => void;
|
|
23
|
+
reconnectMs?: number;
|
|
24
|
+
idleTimeoutMs?: number;
|
|
15
25
|
});
|
|
16
26
|
start(): Promise<void>;
|
|
17
27
|
stop(): Promise<void>;
|
|
18
28
|
private connect;
|
|
29
|
+
private touchTransport;
|
|
30
|
+
private armIdleWatchdog;
|
|
31
|
+
private markDisconnected;
|
|
19
32
|
private startSseReader;
|
|
20
33
|
private handleEvent;
|
|
21
34
|
private scheduleReconnect;
|
|
@@ -2,44 +2,117 @@ export class SseComponent {
|
|
|
2
2
|
http;
|
|
3
3
|
channel;
|
|
4
4
|
options;
|
|
5
|
-
eventSource;
|
|
6
5
|
shouldReconnect = true;
|
|
7
6
|
reconnectTimer;
|
|
7
|
+
idleTimer;
|
|
8
|
+
fetchAbort;
|
|
9
|
+
reader;
|
|
10
|
+
reconnectAttempts = 0;
|
|
11
|
+
connectionSeq = 0;
|
|
12
|
+
lastTransportActivityAt = 0;
|
|
8
13
|
constructor(http, channel, options) {
|
|
9
14
|
this.http = http;
|
|
10
15
|
this.channel = channel;
|
|
11
16
|
this.options = options;
|
|
12
17
|
}
|
|
13
18
|
async start() {
|
|
19
|
+
this.options.logger?.info?.(`[dragon channels][SSE] component start: version=${this.options.version}, agent=${this.options.agentId}, account=${this.options.accountId}, baseUrl=${this.http.options.baseURL}`);
|
|
20
|
+
this.options.setStatus?.({
|
|
21
|
+
accountId: this.options.accountId,
|
|
22
|
+
connected: false,
|
|
23
|
+
lastError: null,
|
|
24
|
+
});
|
|
25
|
+
this.options.abortSignal?.addEventListener('abort', () => {
|
|
26
|
+
this.options.logger?.info?.(`[dragon channels][SSE] upstream abort received: agent=${this.options.agentId}, account=${this.options.accountId}`);
|
|
27
|
+
void this.stop();
|
|
28
|
+
}, { once: true });
|
|
14
29
|
this.connect();
|
|
15
30
|
}
|
|
16
31
|
async stop() {
|
|
17
32
|
this.shouldReconnect = false;
|
|
18
33
|
if (this.reconnectTimer)
|
|
19
34
|
clearTimeout(this.reconnectTimer);
|
|
20
|
-
this.
|
|
35
|
+
this.reconnectTimer = undefined;
|
|
36
|
+
if (this.idleTimer)
|
|
37
|
+
clearTimeout(this.idleTimer);
|
|
38
|
+
this.idleTimer = undefined;
|
|
39
|
+
this.fetchAbort?.abort();
|
|
40
|
+
this.fetchAbort = undefined;
|
|
41
|
+
try {
|
|
42
|
+
await this.reader?.cancel?.();
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Reader cancellation can race with fetch abort.
|
|
46
|
+
}
|
|
47
|
+
this.reader = undefined;
|
|
48
|
+
this.options.setStatus?.({
|
|
49
|
+
accountId: this.options.accountId,
|
|
50
|
+
connected: false,
|
|
51
|
+
lastStopAt: Date.now(),
|
|
52
|
+
});
|
|
53
|
+
this.options.logger?.info?.(`[dragon channels][SSE] component stopped: agent=${this.options.agentId}, account=${this.options.accountId}`);
|
|
21
54
|
}
|
|
22
55
|
connect() {
|
|
23
56
|
if (!this.shouldReconnect)
|
|
24
57
|
return;
|
|
25
58
|
const { agentId, logger } = this.options;
|
|
26
59
|
const url = `${this.http.options.baseURL}/api/agents/events`;
|
|
27
|
-
|
|
60
|
+
const connectionId = `${Date.now()}-${++this.connectionSeq}`;
|
|
61
|
+
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}`);
|
|
28
62
|
try {
|
|
29
|
-
|
|
30
|
-
// but for simplicity we'll use the same pattern as Bridge if possible.
|
|
31
|
-
// Actually, standard EventSource is not in Node globals yet.
|
|
32
|
-
// We'll use a simple fetch-based stream reader.
|
|
33
|
-
this.startSseReader(url);
|
|
63
|
+
void this.startSseReader(url, connectionId);
|
|
34
64
|
}
|
|
35
65
|
catch (err) {
|
|
36
|
-
logger?.error?.(`[dragon channels][
|
|
37
|
-
this.
|
|
66
|
+
logger?.error?.(`[dragon channels][SSE] connect init failed: connection=${connectionId}, error=${err.message}`);
|
|
67
|
+
this.markDisconnected(err?.message || String(err));
|
|
68
|
+
this.scheduleReconnect('init_failed');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
touchTransport(connectionId, reason) {
|
|
72
|
+
const now = Date.now();
|
|
73
|
+
this.lastTransportActivityAt = now;
|
|
74
|
+
this.options.setStatus?.({
|
|
75
|
+
accountId: this.options.accountId,
|
|
76
|
+
connected: true,
|
|
77
|
+
lastEventAt: now,
|
|
78
|
+
lastTransportActivityAt: now,
|
|
79
|
+
lastError: null,
|
|
80
|
+
});
|
|
81
|
+
this.options.logger?.debug?.(`[dragon channels][SSE] transport activity: connection=${connectionId}, reason=${reason}, at=${now}`);
|
|
82
|
+
this.armIdleWatchdog(connectionId);
|
|
83
|
+
}
|
|
84
|
+
armIdleWatchdog(connectionId) {
|
|
85
|
+
if (this.idleTimer)
|
|
86
|
+
clearTimeout(this.idleTimer);
|
|
87
|
+
const timeoutMs = this.options.idleTimeoutMs ?? 90_000;
|
|
88
|
+
this.idleTimer = setTimeout(() => {
|
|
89
|
+
if (!this.shouldReconnect)
|
|
90
|
+
return;
|
|
91
|
+
const idleMs = Date.now() - this.lastTransportActivityAt;
|
|
92
|
+
this.options.logger?.warn?.(`[dragon channels][SSE] idle timeout: connection=${connectionId}, idleMs=${idleMs}, timeoutMs=${timeoutMs}; aborting fetch for reconnect`);
|
|
93
|
+
this.markDisconnected(`SSE idle timeout after ${idleMs}ms`);
|
|
94
|
+
this.fetchAbort?.abort();
|
|
95
|
+
}, timeoutMs);
|
|
96
|
+
if (typeof this.idleTimer === 'object' && 'unref' in this.idleTimer) {
|
|
97
|
+
this.idleTimer.unref();
|
|
38
98
|
}
|
|
39
99
|
}
|
|
40
|
-
|
|
100
|
+
markDisconnected(error) {
|
|
101
|
+
this.options.setStatus?.({
|
|
102
|
+
accountId: this.options.accountId,
|
|
103
|
+
connected: false,
|
|
104
|
+
lastError: error,
|
|
105
|
+
lastTransportActivityAt: this.lastTransportActivityAt || null,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
async startSseReader(url, connectionId) {
|
|
109
|
+
const abort = new AbortController();
|
|
110
|
+
this.fetchAbort = abort;
|
|
111
|
+
const upstreamAbort = () => abort.abort();
|
|
112
|
+
this.options.abortSignal?.addEventListener('abort', upstreamAbort, { once: true });
|
|
41
113
|
try {
|
|
42
114
|
const response = await fetch(url, {
|
|
115
|
+
signal: abort.signal,
|
|
43
116
|
headers: {
|
|
44
117
|
'Accept': 'text/event-stream',
|
|
45
118
|
'Authorization': `Bearer ${this.http.options.authToken || ''}`
|
|
@@ -51,38 +124,87 @@ export class SseComponent {
|
|
|
51
124
|
const reader = response.body?.getReader();
|
|
52
125
|
if (!reader)
|
|
53
126
|
throw new Error("Response body is null");
|
|
54
|
-
this.
|
|
127
|
+
this.reader = reader;
|
|
128
|
+
this.reconnectAttempts = 0;
|
|
129
|
+
const now = Date.now();
|
|
130
|
+
this.lastTransportActivityAt = now;
|
|
131
|
+
this.options.setStatus?.({
|
|
132
|
+
accountId: this.options.accountId,
|
|
133
|
+
connected: true,
|
|
134
|
+
lastConnectedAt: now,
|
|
135
|
+
lastTransportActivityAt: now,
|
|
136
|
+
lastError: null,
|
|
137
|
+
reconnectAttempts: 0,
|
|
138
|
+
});
|
|
139
|
+
this.options.logger?.info?.(`[dragon channels][SSE] stream established: connection=${connectionId}, agent=${this.options.agentId}, account=${this.options.accountId}`);
|
|
140
|
+
this.armIdleWatchdog(connectionId);
|
|
55
141
|
const decoder = new TextDecoder();
|
|
56
142
|
let buffer = "";
|
|
57
143
|
while (this.shouldReconnect) {
|
|
58
144
|
const { value, done } = await reader.read();
|
|
59
|
-
if (done)
|
|
145
|
+
if (done) {
|
|
146
|
+
this.options.logger?.warn?.(`[dragon channels][SSE] stream ended by remote: connection=${connectionId}`);
|
|
60
147
|
break;
|
|
148
|
+
}
|
|
149
|
+
this.touchTransport(connectionId, 'chunk');
|
|
61
150
|
buffer += decoder.decode(value, { stream: true });
|
|
62
151
|
const lines = buffer.split("\n");
|
|
63
152
|
buffer = lines.pop() || "";
|
|
64
153
|
for (const line of lines) {
|
|
65
154
|
const cleanLine = line.trim();
|
|
155
|
+
if (!cleanLine || cleanLine.startsWith(':')) {
|
|
156
|
+
this.touchTransport(connectionId, cleanLine.startsWith(':') ? 'heartbeat' : 'blank_line');
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
66
159
|
if (cleanLine.startsWith("data: ")) {
|
|
67
160
|
try {
|
|
68
161
|
const data = JSON.parse(cleanLine.slice(6));
|
|
162
|
+
this.options.logger?.debug?.(`[dragon channels][SSE] event received: connection=${connectionId}, type=${data?.type || 'unknown'}, agent=${data?.agentId || 'unknown'}`);
|
|
69
163
|
void this.handleEvent(data).catch((err) => {
|
|
70
|
-
this.options.logger?.error?.(`[dragon channels][
|
|
164
|
+
this.options.logger?.error?.(`[dragon channels][SSE] event handling failed: connection=${connectionId}, error=${err?.message || err}`);
|
|
71
165
|
});
|
|
72
166
|
}
|
|
73
167
|
catch (e) {
|
|
74
|
-
this.options.logger?.error?.(`[dragon channels][
|
|
168
|
+
this.options.logger?.error?.(`[dragon channels][SSE] event JSON parse failed: connection=${connectionId}, line="${cleanLine}", error=${e?.message || e}`);
|
|
75
169
|
}
|
|
76
170
|
}
|
|
77
171
|
}
|
|
78
172
|
}
|
|
173
|
+
if (this.shouldReconnect) {
|
|
174
|
+
const message = 'SSE stream ended';
|
|
175
|
+
this.markDisconnected(message);
|
|
176
|
+
this.scheduleReconnect(message);
|
|
177
|
+
}
|
|
79
178
|
}
|
|
80
179
|
catch (err) {
|
|
81
180
|
if (this.shouldReconnect) {
|
|
82
|
-
|
|
83
|
-
|
|
181
|
+
const message = err?.name === 'AbortError'
|
|
182
|
+
? 'SSE fetch aborted'
|
|
183
|
+
: (err?.message || String(err));
|
|
184
|
+
this.options.logger?.warn?.(`[dragon channels][SSE] stream disconnected: connection=${connectionId}, error=${message}`);
|
|
185
|
+
this.markDisconnected(message);
|
|
186
|
+
this.scheduleReconnect(message);
|
|
84
187
|
}
|
|
85
188
|
}
|
|
189
|
+
finally {
|
|
190
|
+
this.options.abortSignal?.removeEventListener('abort', upstreamAbort);
|
|
191
|
+
if (this.reader) {
|
|
192
|
+
try {
|
|
193
|
+
await this.reader.cancel?.();
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Ignore cancellation races.
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (this.fetchAbort === abort) {
|
|
200
|
+
this.fetchAbort = undefined;
|
|
201
|
+
}
|
|
202
|
+
if (this.idleTimer) {
|
|
203
|
+
clearTimeout(this.idleTimer);
|
|
204
|
+
this.idleTimer = undefined;
|
|
205
|
+
}
|
|
206
|
+
this.reader = undefined;
|
|
207
|
+
}
|
|
86
208
|
}
|
|
87
209
|
async handleEvent(data) {
|
|
88
210
|
const { agentId, logger } = this.options;
|
|
@@ -101,9 +223,33 @@ export class SseComponent {
|
|
|
101
223
|
// Handle history sync if needed, but deliverToOpenClaw usually handles normal chat
|
|
102
224
|
}
|
|
103
225
|
}
|
|
104
|
-
scheduleReconnect() {
|
|
226
|
+
scheduleReconnect(reason) {
|
|
227
|
+
if (!this.shouldReconnect)
|
|
228
|
+
return;
|
|
105
229
|
if (this.reconnectTimer)
|
|
106
230
|
clearTimeout(this.reconnectTimer);
|
|
107
|
-
this.
|
|
231
|
+
this.reconnectAttempts += 1;
|
|
232
|
+
const baseMs = this.options.reconnectMs ?? 5_000;
|
|
233
|
+
const delayMs = Math.min(60_000, baseMs * Math.max(1, this.reconnectAttempts));
|
|
234
|
+
this.options.setStatus?.({
|
|
235
|
+
accountId: this.options.accountId,
|
|
236
|
+
connected: false,
|
|
237
|
+
restartPending: true,
|
|
238
|
+
reconnectAttempts: this.reconnectAttempts,
|
|
239
|
+
lastError: reason,
|
|
240
|
+
});
|
|
241
|
+
this.options.logger?.info?.(`[dragon channels][SSE] reconnect scheduled: attempt=${this.reconnectAttempts}, delayMs=${delayMs}, reason=${reason}, agent=${this.options.agentId}, account=${this.options.accountId}`);
|
|
242
|
+
this.reconnectTimer = setTimeout(() => {
|
|
243
|
+
this.reconnectTimer = undefined;
|
|
244
|
+
this.options.setStatus?.({
|
|
245
|
+
accountId: this.options.accountId,
|
|
246
|
+
restartPending: false,
|
|
247
|
+
reconnectAttempts: this.reconnectAttempts,
|
|
248
|
+
});
|
|
249
|
+
this.connect();
|
|
250
|
+
}, delayMs);
|
|
251
|
+
if (typeof this.reconnectTimer === 'object' && 'unref' in this.reconnectTimer) {
|
|
252
|
+
this.reconnectTimer.unref();
|
|
253
|
+
}
|
|
108
254
|
}
|
|
109
255
|
}
|
package/dist/index.js
CHANGED
|
@@ -22,10 +22,16 @@ function resolveAccountIdFromSessionKey(sessionKey) {
|
|
|
22
22
|
}
|
|
23
23
|
return "default";
|
|
24
24
|
}
|
|
25
|
+
function containerKey(account) {
|
|
26
|
+
return `${account.accountId}:${account.agentId}:${account.orchestratorUrl}`;
|
|
27
|
+
}
|
|
25
28
|
async function getOrCreateContainer(account, ctx) {
|
|
26
|
-
const key =
|
|
27
|
-
if (containers.has(key))
|
|
29
|
+
const key = containerKey(account);
|
|
30
|
+
if (containers.has(key)) {
|
|
31
|
+
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
32
|
+
logger?.debug?.(`[dragon channels][Dragon Plugin] Reusing channel container: key=${key}, agent=${account.agentId}, account=${account.accountId}`);
|
|
28
33
|
return containers.get(key);
|
|
34
|
+
}
|
|
29
35
|
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
30
36
|
const container = new ServiceContainer();
|
|
31
37
|
logger?.info?.(`[dragon channels][Dragon Plugin] Starting channel plugin v${dragonChannelPluginVersion} for agent=${account.agentId}, account=${account.accountId}, orchestrator=${account.orchestratorUrl}`);
|
|
@@ -51,13 +57,43 @@ async function getOrCreateContainer(account, ctx) {
|
|
|
51
57
|
// 3. Sync Infrastructure
|
|
52
58
|
container.register('sse', new SseComponent(http, channel, {
|
|
53
59
|
agentId: account.agentId,
|
|
60
|
+
accountId: account.accountId,
|
|
54
61
|
version: dragonChannelPluginVersion,
|
|
55
|
-
logger
|
|
62
|
+
logger,
|
|
63
|
+
abortSignal: ctx.abortSignal,
|
|
64
|
+
setStatus: ctx.setStatus,
|
|
65
|
+
reconnectMs: 5_000,
|
|
66
|
+
idleTimeoutMs: 90_000,
|
|
56
67
|
}));
|
|
57
68
|
await container.startAll();
|
|
58
69
|
containers.set(key, container);
|
|
70
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] Channel container started: key=${key}, agent=${account.agentId}, account=${account.accountId}`);
|
|
59
71
|
return container;
|
|
60
72
|
}
|
|
73
|
+
async function stopContainer(account, ctx) {
|
|
74
|
+
const key = containerKey(account);
|
|
75
|
+
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
76
|
+
const container = containers.get(key);
|
|
77
|
+
if (!container) {
|
|
78
|
+
logger?.debug?.(`[dragon channels][Dragon Plugin] No channel container to stop: key=${key}, agent=${account.agentId}, account=${account.accountId}`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] Stopping channel container: key=${key}, agent=${account.agentId}, account=${account.accountId}`);
|
|
82
|
+
try {
|
|
83
|
+
await container.stopAll();
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
containers.delete(key);
|
|
87
|
+
ctx?.setStatus?.({
|
|
88
|
+
accountId: account.accountId,
|
|
89
|
+
connected: false,
|
|
90
|
+
running: false,
|
|
91
|
+
restartPending: false,
|
|
92
|
+
lastStopAt: Date.now(),
|
|
93
|
+
});
|
|
94
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] Channel container stopped: key=${key}, agent=${account.agentId}, account=${account.accountId}`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
61
97
|
const base = createChannelPluginBase({
|
|
62
98
|
id: channelId,
|
|
63
99
|
meta: {
|
|
@@ -80,7 +116,7 @@ const base = createChannelPluginBase({
|
|
|
80
116
|
return {
|
|
81
117
|
accountId,
|
|
82
118
|
agentId: accountConfig.agentId || accountId,
|
|
83
|
-
orchestratorUrl: accountConfig.orchestratorUrl
|
|
119
|
+
orchestratorUrl: accountConfig.orchestratorUrl,
|
|
84
120
|
orchestratorAuthToken: accountConfig.orchestratorAuthToken || accountConfig.authToken,
|
|
85
121
|
};
|
|
86
122
|
},
|
|
@@ -93,13 +129,35 @@ const plugin = createChatChannelPlugin({
|
|
|
93
129
|
gateway: {
|
|
94
130
|
startAccount: async (ctx) => {
|
|
95
131
|
const account = base.config.resolveAccount(ctx.cfg, ctx.accountId);
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
132
|
+
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
133
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] startAccount begin: agent=${account.agentId}, account=${account.accountId}, orchestrator=${account.orchestratorUrl}`);
|
|
134
|
+
ctx.setStatus?.({
|
|
135
|
+
accountId: account.accountId,
|
|
136
|
+
enabled: true,
|
|
137
|
+
configured: true,
|
|
138
|
+
running: true,
|
|
139
|
+
connected: false,
|
|
140
|
+
lastStartAt: Date.now(),
|
|
141
|
+
lastError: null,
|
|
102
142
|
});
|
|
143
|
+
try {
|
|
144
|
+
await getOrCreateContainer(account, ctx);
|
|
145
|
+
if (ctx.abortSignal.aborted)
|
|
146
|
+
return;
|
|
147
|
+
await new Promise((resolve) => {
|
|
148
|
+
ctx.abortSignal.addEventListener('abort', resolve, { once: true });
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] startAccount exiting: agent=${account.agentId}, account=${account.accountId}, aborted=${ctx.abortSignal.aborted}`);
|
|
153
|
+
await stopContainer(account, ctx);
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
stopAccount: async (ctx) => {
|
|
157
|
+
const account = base.config.resolveAccount(ctx.cfg, ctx.accountId);
|
|
158
|
+
const logger = ctx?.logger ?? ctx?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
159
|
+
logger?.info?.(`[dragon channels][Dragon Plugin] stopAccount requested: agent=${account.agentId}, account=${account.accountId}`);
|
|
160
|
+
await stopContainer(account, ctx);
|
|
103
161
|
}
|
|
104
162
|
},
|
|
105
163
|
messaging: {
|
|
@@ -272,12 +330,12 @@ const entry = defineChannelPluginEntry({
|
|
|
272
330
|
return;
|
|
273
331
|
const accountId = resolveAccountIdFromSessionKey(sessionKey);
|
|
274
332
|
const account = base.config.resolveAccount(api?.runtime?.cfg, accountId);
|
|
275
|
-
const
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
333
|
+
const logger = api?.runtime?.logger ?? api?.runtime?.log ?? cachedRuntime?.logger ?? cachedRuntime?.log;
|
|
334
|
+
const container = containers.get(containerKey(account));
|
|
335
|
+
if (!container) {
|
|
336
|
+
logger?.warn?.(`[dragon channels][Dragon Plugin] agent event skipped because managed container is not running: sessionKey=${sessionKey}, account=${account.accountId}, agent=${account.agentId}`);
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
281
339
|
const channel = container.get('channel');
|
|
282
340
|
await channel.handleAgentEvent(evt);
|
|
283
341
|
});
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const dragonChannelPluginVersion = "0.5.
|
|
1
|
+
export declare const dragonChannelPluginVersion = "0.5.32";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const dragonChannelPluginVersion = "0.5.
|
|
1
|
+
export const dragonChannelPluginVersion = "0.5.32";
|