@masons/agent-network 0.6.20 → 0.6.21
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/channel.d.ts.map +1 -1
- package/dist/channel.js +54 -44
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +6 -0
- package/dist/connector-client.d.ts +35 -4
- package/dist/connector-client.d.ts.map +1 -1
- package/dist/connector-client.js +126 -19
- package/dist/conversation-manager-context.d.ts +4 -0
- package/dist/conversation-manager-context.d.ts.map +1 -0
- package/dist/conversation-manager-context.js +8 -0
- package/dist/conversation-manager.d.ts +29 -4
- package/dist/conversation-manager.d.ts.map +1 -1
- package/dist/conversation-manager.js +163 -14
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/platform-client.d.ts +1 -0
- package/dist/platform-client.d.ts.map +1 -1
- package/dist/platform-client.js +12 -0
- package/dist/plugin.d.ts +2 -1
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +49 -30
- package/dist/sent-message-buffer.d.ts +2 -3
- package/dist/sent-message-buffer.d.ts.map +1 -1
- package/dist/sent-message-buffer.js +8 -11
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +101 -7
- package/dist/turn-context.d.ts +0 -4
- package/dist/turn-context.d.ts.map +1 -1
- package/dist/turn-context.js +0 -18
- package/dist/types.d.ts +10 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +3 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/ws-heartbeat.d.ts +23 -0
- package/dist/ws-heartbeat.d.ts.map +1 -0
- package/dist/ws-heartbeat.js +63 -0
- package/openclaw.plugin.json +2 -1
- package/package.json +1 -1
- package/skills/agent-network/SKILL.md +9 -0
package/dist/channel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACd,MAAM,kCAAkC,CAAC;AAa1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACd,MAAM,kCAAkC,CAAC;AAa1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAwD9D,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAOD,wBAAgB,2BAA2B,IAAI,OAAO,CAIrD;AAGD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE/D;AAeD,wBAAgB,sCAAsC,CACpD,oBAAoB,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,sBAAsB,CAAC,EACjF,MAAM,EAAE;IACN,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB,GACA,MAAM,CAiBR;AAED,iBAAS,iCAAiC,CACxC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,gBAAgB,UAAQ,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CA8CzB;AAED,eAAO,MAAM,4CAA4C,0CACtB,CAAC;AAkkBpC,eAAO,MAAM,mBAAmB,EAAE,aAAa,CAAC,mBAAmB,CAkSlE,CAAC"}
|
package/dist/channel.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import createDebug from "debug";
|
|
3
3
|
import { clearConnectorClient, clearConversationManager, extractNetworkConfig, getDmScope, initConnectorClient, initConversationManager, initToolConfig, isIdentityLinksConfigured, requirePlatformConfig, requirePluginRuntime, } from "./config.js";
|
|
4
|
-
import { ConnectorClient } from "./connector-client.js";
|
|
4
|
+
import { ConnectorClient, ConnectorError, SendOutcomeUnknownError, } from "./connector-client.js";
|
|
5
5
|
import { ConversationManager } from "./conversation-manager.js";
|
|
6
|
+
import { runWithConversationManagerContext } from "./conversation-manager-context.js";
|
|
6
7
|
import { clearEnvironmentContext } from "./environment-context.js";
|
|
7
8
|
import { extractHandleFromAddress } from "./handle-utils.js";
|
|
8
9
|
import { clearOwnerState, isOwnerAddress, markOwnerAddress, setCurrentTurnIsOwner, setCurrentTurnOwnerSignal, } from "./owner-session-state.js";
|
|
@@ -10,7 +11,6 @@ import { ServicesRetainedRecipientConsumer, } from "./services-retained-recipien
|
|
|
10
11
|
import { isServicesRetainedReplyContext, runWithServicesRetainedReplyContext, } from "./services-retained-reply-context.js";
|
|
11
12
|
import { runWithServicesRetainedToolPolicy } from "./services-retained-tool-policy.js";
|
|
12
13
|
import { createReplyTraceMetadata, ensureTraceMetadata, } from "./trace-metadata.js";
|
|
13
|
-
import { setCurrentTurnSender, setCurrentTurnSenderAddress, } from "./turn-context.js";
|
|
14
14
|
import { checkForUpdate } from "./update-check.js";
|
|
15
15
|
const dbg = createDebug("agent-network:channel");
|
|
16
16
|
const SERVICES_RETAINED_INBOX_PEER = "agent-network:services-retained-node-inbox";
|
|
@@ -115,34 +115,27 @@ function deriveSenderName(event) {
|
|
|
115
115
|
if (visitorName && typeof visitorName === "string") {
|
|
116
116
|
return visitorName;
|
|
117
117
|
}
|
|
118
|
-
return
|
|
118
|
+
return event.from;
|
|
119
119
|
}
|
|
120
120
|
function deriveNodeName(nodeRef, fromAddress) {
|
|
121
121
|
if (nodeRef.displayName)
|
|
122
122
|
return nodeRef.displayName;
|
|
123
123
|
if (nodeRef.handle)
|
|
124
124
|
return nodeRef.handle;
|
|
125
|
-
return
|
|
125
|
+
return fromAddress;
|
|
126
126
|
}
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
if (recentMessages.size > 200) {
|
|
140
|
-
for (const [k, ts] of recentMessages) {
|
|
141
|
-
if (now - ts > DEDUP_WINDOW_MS)
|
|
142
|
-
recentMessages.delete(k);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return false;
|
|
127
|
+
function agentReadableAddressedBody(event) {
|
|
128
|
+
const facts = [
|
|
129
|
+
...(event.messageId === undefined
|
|
130
|
+
? []
|
|
131
|
+
: [`message_id=${JSON.stringify(event.messageId)}`]),
|
|
132
|
+
...(event.sentAt === undefined
|
|
133
|
+
? []
|
|
134
|
+
: [`sent_at=${JSON.stringify(event.sentAt)}`]),
|
|
135
|
+
];
|
|
136
|
+
if (facts.length === 0)
|
|
137
|
+
return event.content;
|
|
138
|
+
return [`[MASONS message facts: ${facts.join("; ")}]`, event.content].join("\n\n");
|
|
146
139
|
}
|
|
147
140
|
async function handleAddressedMessage(event, conversationManager, client, ctx, options = {}) {
|
|
148
141
|
const fromAddress = event.from;
|
|
@@ -155,11 +148,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx, o
|
|
|
155
148
|
console.warn(`[agent-network:channel] invalid traceparent from=${fromAddress} traceId=${inboundTrace.traceId} spanName=receive`);
|
|
156
149
|
}
|
|
157
150
|
}
|
|
158
|
-
if (options.servicesRetained === undefined &&
|
|
159
|
-
isDuplicate(fromAddress, event.content, event.sentAt)) {
|
|
160
|
-
dbg("duplicate message suppressed from=%s sentAt=%s", fromAddress, event.sentAt);
|
|
161
|
-
return true;
|
|
162
|
-
}
|
|
163
151
|
const inboundCorrelationId = typeof metadata.correlation_id === "string"
|
|
164
152
|
? metadata.correlation_id
|
|
165
153
|
: undefined;
|
|
@@ -204,11 +192,10 @@ async function handleAddressedMessage(event, conversationManager, client, ctx, o
|
|
|
204
192
|
(nodeRef ? deriveNodeName(nodeRef, fromAddress) : deriveSenderName(event));
|
|
205
193
|
const replyAddress = options.routableReplyAddress ??
|
|
206
194
|
(options.servicesRetained ? undefined : fromAddress);
|
|
207
|
-
if (replyAddress &&
|
|
195
|
+
if (replyAddress &&
|
|
196
|
+
!conversationManager.refreshInboundPortrayal(contact, replyAddress)) {
|
|
208
197
|
conversationManager.registerInbound(contact, replyAddress);
|
|
209
198
|
}
|
|
210
|
-
setCurrentTurnSender(contact);
|
|
211
|
-
setCurrentTurnSenderAddress(replyAddress ?? null);
|
|
212
199
|
let runtime;
|
|
213
200
|
try {
|
|
214
201
|
runtime = requirePluginRuntime();
|
|
@@ -247,7 +234,9 @@ async function handleAddressedMessage(event, conversationManager, client, ctx, o
|
|
|
247
234
|
})
|
|
248
235
|
: route.sessionKey;
|
|
249
236
|
const msgCtx = runtime.channel.reply.finalizeInboundContext({
|
|
250
|
-
Body:
|
|
237
|
+
Body: options.servicesRetained === undefined
|
|
238
|
+
? agentReadableAddressedBody(event)
|
|
239
|
+
: event.content,
|
|
251
240
|
RawBody: event.content,
|
|
252
241
|
CommandBody: event.content,
|
|
253
242
|
From: senderId,
|
|
@@ -321,25 +310,39 @@ async function handleAddressedMessage(event, conversationManager, client, ctx, o
|
|
|
321
310
|
messageId: inboundMessageId,
|
|
322
311
|
});
|
|
323
312
|
const deliverResult = await conversationManager.send(replyAddress, text, replyTrace.metadata);
|
|
313
|
+
dbg("deliver reply senderId=%s status=%s ackStatus=%s contentLength=%d traceId=%s originalTraceId=%s spanName=send", senderId, deliverResult.status, deliverResult.status === "sent"
|
|
314
|
+
? deliverResult.acknowledgementStatus
|
|
315
|
+
: "(none)", text.length, replyTrace.traceId, replyTrace.originalTraceId ?? "(absent)");
|
|
324
316
|
if (deliverResult.status === "sent") {
|
|
325
317
|
replyRouted = true;
|
|
326
318
|
}
|
|
319
|
+
else if (deliverResult.status === "unknown") {
|
|
320
|
+
throw new SendOutcomeUnknownError(deliverResult.messageId, deliverResult.reason);
|
|
321
|
+
}
|
|
327
322
|
else {
|
|
328
|
-
|
|
323
|
+
throw new ConnectorError(deliverResult.error ?? "Agent Network send failed", deliverResult.errorCode ?? "SEND_FAILED", replyAddress);
|
|
329
324
|
}
|
|
330
|
-
dbg("deliver reply senderId=%s status=%s contentLength=%d traceId=%s originalTraceId=%s spanName=send", senderId, deliverResult.status, text.length, replyTrace.traceId, replyTrace.originalTraceId ?? "(absent)");
|
|
331
325
|
},
|
|
332
326
|
onError: (err) => {
|
|
333
327
|
dispatchError = err;
|
|
334
|
-
|
|
328
|
+
if (err instanceof SendOutcomeUnknownError) {
|
|
329
|
+
console.warn(`[agent-network:${ctx.accountId}] reply send OUTCOME UNKNOWN to=${senderId} messageId=${err.messageId} reason=${err.reason}`);
|
|
330
|
+
}
|
|
331
|
+
else if (err instanceof ConnectorError) {
|
|
332
|
+
console.warn(`[agent-network:${ctx.accountId}] reply send FAILED to=${senderId} code=${err.code} error=${err.message}`);
|
|
333
|
+
}
|
|
334
|
+
else {
|
|
335
|
+
console.error(`[agent-network:${ctx.accountId}] dispatch error:`, err);
|
|
336
|
+
}
|
|
335
337
|
},
|
|
336
338
|
},
|
|
337
339
|
});
|
|
340
|
+
const dispatchInConversationManagerContext = () => runWithConversationManagerContext(conversationManager, dispatch);
|
|
338
341
|
if (options.servicesRetained) {
|
|
339
|
-
await runWithServicesRetainedToolPolicy(runtimeSessionKey, () => runWithServicesRetainedReplyContext(
|
|
342
|
+
await runWithServicesRetainedToolPolicy(runtimeSessionKey, () => runWithServicesRetainedReplyContext(dispatchInConversationManagerContext));
|
|
340
343
|
}
|
|
341
344
|
else {
|
|
342
|
-
await
|
|
345
|
+
await dispatchInConversationManagerContext();
|
|
343
346
|
}
|
|
344
347
|
if (dispatchError)
|
|
345
348
|
throw dispatchError;
|
|
@@ -383,8 +386,9 @@ function servicesRetainedBody(message) {
|
|
|
383
386
|
const sender = servicesRetainedSenderName(message);
|
|
384
387
|
const displayName = message.envelope.sender.display_name;
|
|
385
388
|
const handle = message.envelope.sender.handle;
|
|
389
|
+
const sentAt = message.envelope.sent_at;
|
|
386
390
|
return [
|
|
387
|
-
`[MASONS canonical message_ref=${JSON.stringify(message.envelope.message_ref)}; sender_display_name=${displayName === undefined ? "absent" : JSON.stringify(displayName)}; sender_handle=${handle === undefined ? "absent" : JSON.stringify(handle)}; sender_label=${JSON.stringify(sender)}; content_type=${JSON.stringify(message.contentType)}]`,
|
|
391
|
+
`[MASONS canonical message_ref=${JSON.stringify(message.envelope.message_ref)}; sent_at=${sentAt === undefined ? "absent" : JSON.stringify(sentAt)}; sender_display_name=${displayName === undefined ? "absent" : JSON.stringify(displayName)}; sender_handle=${handle === undefined ? "absent" : JSON.stringify(handle)}; sender_label=${JSON.stringify(sender)}; content_type=${JSON.stringify(message.contentType)}]`,
|
|
388
392
|
message.envelope.content,
|
|
389
393
|
].join("\n\n");
|
|
390
394
|
}
|
|
@@ -444,13 +448,19 @@ export const agentNetworkChannel = {
|
|
|
444
448
|
}
|
|
445
449
|
const state = ctx.accountId ? accounts.get(ctx.accountId) : undefined;
|
|
446
450
|
if (!state)
|
|
447
|
-
|
|
451
|
+
throw new Error("Agent Network account unavailable");
|
|
448
452
|
const result = await state.conversationManager.send(ctx.to, ctx.text);
|
|
449
|
-
dbg("sendText to=%s status=%s contentLength=%d", ctx.to, result.status, ctx.text.length);
|
|
450
|
-
|
|
451
|
-
channel: "agent-network",
|
|
452
|
-
|
|
453
|
-
|
|
453
|
+
dbg("sendText to=%s status=%s ackStatus=%s contentLength=%d", ctx.to, result.status, result.status === "sent" ? result.acknowledgementStatus : "(none)", ctx.text.length);
|
|
454
|
+
if (result.status === "sent") {
|
|
455
|
+
return { channel: "agent-network", messageId: result.messageId };
|
|
456
|
+
}
|
|
457
|
+
if (result.status === "unknown") {
|
|
458
|
+
throw new SendOutcomeUnknownError(result.messageId, result.reason);
|
|
459
|
+
}
|
|
460
|
+
if (result.errorCode) {
|
|
461
|
+
throw new ConnectorError(result.error ?? result.errorCode, result.errorCode, ctx.to);
|
|
462
|
+
}
|
|
463
|
+
throw new Error(result.error ?? "Agent Network send failed");
|
|
454
464
|
},
|
|
455
465
|
},
|
|
456
466
|
gateway: {
|
package/dist/config.d.ts
CHANGED
|
@@ -18,9 +18,11 @@ export declare function clearPluginRuntime(): void;
|
|
|
18
18
|
export declare function requirePluginRuntime(): unknown;
|
|
19
19
|
export declare function requirePlatformConfig(): PlatformClientConfig;
|
|
20
20
|
export declare function requireApiKey(): string;
|
|
21
|
+
export declare function hasApiKey(): boolean;
|
|
21
22
|
export declare function getPendingTarget(): string | null;
|
|
22
23
|
export declare function isProfileNeeded(): boolean;
|
|
23
24
|
export declare function requireConnectorClient(): ConnectorClient;
|
|
25
|
+
export declare function getConnectorClient(): ConnectorClient | null;
|
|
24
26
|
export interface NetworkCredentials {
|
|
25
27
|
connectorUrl: string;
|
|
26
28
|
token: string;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAoCjD,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAsBD,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMhC;AAYD,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAyCjE;AAuCD,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AAWD,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAeD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAOjE;AAQD,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAYD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAE1E;AASD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAKD,wBAAgB,0BAA0B,IAAI,mBAAmB,CAOhE;AASD,wBAAgB,sBAAsB,IAAI,mBAAmB,GAAG,IAAI,CAEnE;AAgBD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAKD,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAQD,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAcD,wBAAgB,qBAAqB,IAAI,oBAAoB,CAE5D;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAKD,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AASD,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AASD,wBAAgB,sBAAsB,IAAI,eAAe,CAOxD;AAyBD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAQD,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAW5E;AAoBD,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,kBAAkB,EACzB,OAAO,CAAC,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,EACnB,aAAa,CAAC,EAAE,MAAM,EACtB,gBAAgB,CAAC,EAAE,MAAM,IAAI,GAC5B,OAAO,CAAC,IAAI,CAAC,CA0Cf;AAUD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrE;AASD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CASvD;AAYD,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAOvD;AAUD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAOzD;AAwCD,wBAAsB,kBAAkB,CACtC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EAAE,GAChB,OAAO,CAAC,IAAI,CAAC,CAsBf;AAQD,wBAAsB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA4B1E;AAOD,MAAM,WAAW,YAAY;IAE3B,cAAc,EAAE,OAAO,CAAC;IAExB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B,YAAY,EAAE,OAAO,CAAC;CACvB;AASD,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA2BhE;AAOD,wBAAgB,gBAAgB,IAAI,IAAI,CAWvC"}
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -108,6 +108,9 @@ export function requireApiKey() {
|
|
|
108
108
|
}
|
|
109
109
|
return storedApiKey;
|
|
110
110
|
}
|
|
111
|
+
export function hasApiKey() {
|
|
112
|
+
return Boolean(storedApiKey);
|
|
113
|
+
}
|
|
111
114
|
export function getPendingTarget() {
|
|
112
115
|
return storedPendingTarget;
|
|
113
116
|
}
|
|
@@ -120,6 +123,9 @@ export function requireConnectorClient() {
|
|
|
120
123
|
}
|
|
121
124
|
return storedConnectorClient;
|
|
122
125
|
}
|
|
126
|
+
export function getConnectorClient() {
|
|
127
|
+
return storedConnectorClient;
|
|
128
|
+
}
|
|
123
129
|
function ensureNetworkSection(config) {
|
|
124
130
|
if (typeof config.channels !== "object" || config.channels === null) {
|
|
125
131
|
config.channels = {};
|
|
@@ -1,14 +1,24 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
|
-
import { type AddressedMessageEvent, type CustodyPendingEvent, type DeliveryPendingEvent, type DeliveryStatusEvent, type
|
|
2
|
+
import { type AddressedMessageEvent, type CustodyPendingEvent, type DeliveryPendingEvent, type DeliveryStatusEvent, type ObservedSendAckEvent, type StructuredErrorEvent } from "./types.js";
|
|
3
|
+
import { type WsHeartbeatOptions } from "./ws-heartbeat.js";
|
|
3
4
|
export declare class ConnectorError extends Error {
|
|
4
5
|
readonly code: string;
|
|
5
6
|
readonly to?: string;
|
|
6
7
|
constructor(message: string, code: string, to?: string);
|
|
7
8
|
}
|
|
9
|
+
export type SendOutcomeUnknownReason = "ack_timeout" | "connection_closed";
|
|
10
|
+
export declare class SendOutcomeUnknownError extends Error {
|
|
11
|
+
readonly code: "SEND_OUTCOME_UNKNOWN";
|
|
12
|
+
readonly retryable: false;
|
|
13
|
+
readonly attempts: 1;
|
|
14
|
+
readonly messageId: string;
|
|
15
|
+
readonly reason: SendOutcomeUnknownReason;
|
|
16
|
+
constructor(messageId: string, reason: SendOutcomeUnknownReason);
|
|
17
|
+
}
|
|
8
18
|
type ConnectorClientEvents = {
|
|
9
19
|
message_received: (event: AddressedMessageEvent) => void;
|
|
10
20
|
custody_pending: (event: CustodyPendingEvent) => void;
|
|
11
|
-
send_ack: (event:
|
|
21
|
+
send_ack: (event: ObservedSendAckEvent) => void;
|
|
12
22
|
delivery_pending: (event: DeliveryPendingEvent) => void;
|
|
13
23
|
delivery_status: (event: DeliveryStatusEvent) => void;
|
|
14
24
|
structured_error: (event: StructuredErrorEvent) => void;
|
|
@@ -16,6 +26,20 @@ type ConnectorClientEvents = {
|
|
|
16
26
|
connected: () => void;
|
|
17
27
|
disconnected: () => void;
|
|
18
28
|
};
|
|
29
|
+
export interface ConnectorClientOptions {
|
|
30
|
+
keepalive?: Pick<WsHeartbeatOptions, "intervalMs" | "probeTimeoutMs" | "missesBeforeDisconnect">;
|
|
31
|
+
}
|
|
32
|
+
export type ChannelState = "connecting" | "connected" | "reconnecting" | "disconnected";
|
|
33
|
+
export type RegistrationOutcome = {
|
|
34
|
+
state: "accepted";
|
|
35
|
+
} | {
|
|
36
|
+
state: "refused";
|
|
37
|
+
reason: string;
|
|
38
|
+
} | {
|
|
39
|
+
state: "replaced";
|
|
40
|
+
} | {
|
|
41
|
+
state: "none";
|
|
42
|
+
};
|
|
19
43
|
export declare class ConnectorClient extends EventEmitter {
|
|
20
44
|
private readonly url;
|
|
21
45
|
private readonly token;
|
|
@@ -24,18 +48,24 @@ export declare class ConnectorClient extends EventEmitter {
|
|
|
24
48
|
private backoffMs;
|
|
25
49
|
private alreadyConnectedRetries;
|
|
26
50
|
private reconnectTimer;
|
|
51
|
+
private keepalive;
|
|
52
|
+
private readonly keepaliveOptions;
|
|
27
53
|
private registerResolve;
|
|
28
54
|
private registerReject;
|
|
29
55
|
private registerTimer;
|
|
56
|
+
private registration;
|
|
57
|
+
private everDropped;
|
|
30
58
|
private lastKnownSeq;
|
|
31
59
|
private readonly pendingSeqMessages;
|
|
32
60
|
private readonly seenPayloadIds;
|
|
33
61
|
private readonly seenPayloadIdOrder;
|
|
34
62
|
private pendingSends;
|
|
35
|
-
constructor(url: string, token: string);
|
|
63
|
+
constructor(url: string, token: string, options?: ConnectorClientOptions);
|
|
36
64
|
connect(): Promise<void>;
|
|
37
65
|
disconnect(): void;
|
|
38
|
-
|
|
66
|
+
getChannelState(): ChannelState;
|
|
67
|
+
getRegistration(): RegistrationOutcome;
|
|
68
|
+
send(to: string, content: string, contentType?: string, metadata?: Record<string, unknown>): Promise<ObservedSendAckEvent>;
|
|
39
69
|
sendTyping(to: string, isTyping: boolean): boolean;
|
|
40
70
|
ackDelivery(upToSeq: number): boolean;
|
|
41
71
|
requestGapFill(sinceSeq: number): boolean;
|
|
@@ -70,6 +100,7 @@ export declare class ConnectorClient extends EventEmitter {
|
|
|
70
100
|
private clearReconnectTimer;
|
|
71
101
|
private cleanupConnection;
|
|
72
102
|
private sendEvent;
|
|
103
|
+
private sendSerializedEvent;
|
|
73
104
|
}
|
|
74
105
|
export {};
|
|
75
106
|
//# sourceMappingURL=connector-client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI3C,OAAO,EAEL,KAAK,qBAAqB,EAI1B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EAEzB,KAAK,mBAAmB,
|
|
1
|
+
{"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"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"}
|
package/dist/connector-client.js
CHANGED
|
@@ -5,6 +5,7 @@ import WebSocket from "ws";
|
|
|
5
5
|
import { setEnvironmentContext } from "./environment-context.js";
|
|
6
6
|
import { CURRENT_PROTOCOL_VERSION, isAddressedMessage, isCustodyPending, isDeliveryCursor, isDeliveryPending, isDeliverySkip, isDeliveryStatus, isRegisterAck, isSendAck, isStructuredError, REGISTER_ACK_TIMEOUT_MS, SEND_ACK_TIMEOUT_MS, } from "./types.js";
|
|
7
7
|
import { PLUGIN_VERSION } from "./version.js";
|
|
8
|
+
import { startWsHeartbeat, } from "./ws-heartbeat.js";
|
|
8
9
|
const dbg = createDebug("agent-network:connector");
|
|
9
10
|
const dbgMsg = createDebug("agent-network:connector:msg");
|
|
10
11
|
const BACKOFF_INITIAL_MS = 1_000;
|
|
@@ -24,6 +25,23 @@ export class ConnectorError extends Error {
|
|
|
24
25
|
this.to = to;
|
|
25
26
|
}
|
|
26
27
|
}
|
|
28
|
+
export class SendOutcomeUnknownError extends Error {
|
|
29
|
+
code = "SEND_OUTCOME_UNKNOWN";
|
|
30
|
+
retryable = false;
|
|
31
|
+
attempts = 1;
|
|
32
|
+
messageId;
|
|
33
|
+
reason;
|
|
34
|
+
constructor(messageId, reason) {
|
|
35
|
+
const detail = reason === "ack_timeout"
|
|
36
|
+
? "no SEND_ACK was observed before the acknowledgement deadline"
|
|
37
|
+
: "the connection closed before a SEND_ACK was observed";
|
|
38
|
+
super(`Send outcome unknown for message ${messageId}: ${detail}. ` +
|
|
39
|
+
"It may have been sent. Do not send it again as a new message.");
|
|
40
|
+
this.name = "SendOutcomeUnknownError";
|
|
41
|
+
this.messageId = messageId;
|
|
42
|
+
this.reason = reason;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
27
45
|
export class ConnectorClient extends EventEmitter {
|
|
28
46
|
url;
|
|
29
47
|
token;
|
|
@@ -32,25 +50,32 @@ export class ConnectorClient extends EventEmitter {
|
|
|
32
50
|
backoffMs = BACKOFF_INITIAL_MS;
|
|
33
51
|
alreadyConnectedRetries = 0;
|
|
34
52
|
reconnectTimer = null;
|
|
53
|
+
keepalive = null;
|
|
54
|
+
keepaliveOptions;
|
|
35
55
|
registerResolve = null;
|
|
36
56
|
registerReject = null;
|
|
37
57
|
registerTimer = null;
|
|
58
|
+
registration = { state: "none" };
|
|
59
|
+
everDropped = false;
|
|
38
60
|
lastKnownSeq;
|
|
39
61
|
pendingSeqMessages = new Map();
|
|
40
62
|
seenPayloadIds = new Set();
|
|
41
63
|
seenPayloadIdOrder = [];
|
|
42
64
|
pendingSends = new Map();
|
|
43
|
-
constructor(url, token) {
|
|
65
|
+
constructor(url, token, options = {}) {
|
|
44
66
|
super();
|
|
45
67
|
this.url = url;
|
|
46
68
|
this.token = token;
|
|
69
|
+
this.keepaliveOptions = options.keepalive;
|
|
47
70
|
}
|
|
48
71
|
connect() {
|
|
49
72
|
if (this.ws) {
|
|
50
73
|
return Promise.reject(new Error("Already connecting or connected"));
|
|
51
74
|
}
|
|
75
|
+
this.clearReconnectTimer();
|
|
52
76
|
dbg("connecting to %s", this.url);
|
|
53
77
|
this.intentionalClose = false;
|
|
78
|
+
this.everDropped = false;
|
|
54
79
|
return this.doConnect();
|
|
55
80
|
}
|
|
56
81
|
disconnect() {
|
|
@@ -65,6 +90,17 @@ export class ConnectorClient extends EventEmitter {
|
|
|
65
90
|
wsToClose.close(1000, "Client disconnect");
|
|
66
91
|
}
|
|
67
92
|
}
|
|
93
|
+
getChannelState() {
|
|
94
|
+
if (this.ws?.readyState === WebSocket.OPEN)
|
|
95
|
+
return "connected";
|
|
96
|
+
if (this.ws !== null || this.reconnectTimer !== null) {
|
|
97
|
+
return this.everDropped ? "reconnecting" : "connecting";
|
|
98
|
+
}
|
|
99
|
+
return "disconnected";
|
|
100
|
+
}
|
|
101
|
+
getRegistration() {
|
|
102
|
+
return this.registration;
|
|
103
|
+
}
|
|
68
104
|
send(to, content, contentType = "text", metadata) {
|
|
69
105
|
const messageId = randomUUID();
|
|
70
106
|
const event = {
|
|
@@ -75,13 +111,29 @@ export class ConnectorClient extends EventEmitter {
|
|
|
75
111
|
contentType,
|
|
76
112
|
metadata,
|
|
77
113
|
};
|
|
114
|
+
let serializedEvent;
|
|
115
|
+
try {
|
|
116
|
+
serializedEvent = JSON.stringify(event);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
return Promise.reject(err instanceof Error ? err : new Error(String(err)));
|
|
120
|
+
}
|
|
78
121
|
return new Promise((resolve, reject) => {
|
|
79
122
|
const timer = setTimeout(() => {
|
|
80
123
|
this.pendingSends.delete(messageId);
|
|
81
|
-
reject(new
|
|
124
|
+
reject(new SendOutcomeUnknownError(messageId, "ack_timeout"));
|
|
82
125
|
}, SEND_ACK_TIMEOUT_MS);
|
|
83
126
|
this.pendingSends.set(messageId, { resolve, reject, timer });
|
|
84
|
-
|
|
127
|
+
let sent = false;
|
|
128
|
+
try {
|
|
129
|
+
sent = this.sendSerializedEvent(serializedEvent, event.event);
|
|
130
|
+
}
|
|
131
|
+
catch (err) {
|
|
132
|
+
clearTimeout(timer);
|
|
133
|
+
this.pendingSends.delete(messageId);
|
|
134
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
85
137
|
if (!sent) {
|
|
86
138
|
clearTimeout(timer);
|
|
87
139
|
this.pendingSends.delete(messageId);
|
|
@@ -120,18 +172,42 @@ export class ConnectorClient extends EventEmitter {
|
|
|
120
172
|
return super.emit(event, ...args);
|
|
121
173
|
}
|
|
122
174
|
doConnect() {
|
|
175
|
+
if (this.ws) {
|
|
176
|
+
return Promise.reject(new Error("Already connecting or connected"));
|
|
177
|
+
}
|
|
123
178
|
return new Promise((resolve, reject) => {
|
|
124
179
|
this.registerResolve = resolve;
|
|
125
180
|
this.registerReject = reject;
|
|
126
181
|
const ws = new WebSocket(this.url, { handshakeTimeout: 10_000 });
|
|
127
182
|
this.ws = ws;
|
|
128
183
|
ws.on("open", () => {
|
|
184
|
+
if (this.ws !== ws) {
|
|
185
|
+
ws.terminate();
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
this.keepalive = startWsHeartbeat(ws, {
|
|
189
|
+
...this.keepaliveOptions,
|
|
190
|
+
onDead: () => {
|
|
191
|
+
dbg("keepalive: silent Gateway socket terminated");
|
|
192
|
+
},
|
|
193
|
+
onPingError: (error) => {
|
|
194
|
+
dbg("keepalive: ping failed: %s", error.message);
|
|
195
|
+
},
|
|
196
|
+
});
|
|
129
197
|
this.sendRegister();
|
|
130
198
|
this.startRegisterTimeout();
|
|
131
199
|
});
|
|
132
|
-
ws.on("message",
|
|
133
|
-
|
|
134
|
-
|
|
200
|
+
ws.on("message", (data) => {
|
|
201
|
+
if (this.ws === ws)
|
|
202
|
+
this.handleMessage(data);
|
|
203
|
+
});
|
|
204
|
+
ws.on("close", (code, reason) => {
|
|
205
|
+
this.handleClose(ws, code, reason);
|
|
206
|
+
});
|
|
207
|
+
ws.on("error", (error) => {
|
|
208
|
+
if (this.ws === ws)
|
|
209
|
+
this.handleError(error);
|
|
210
|
+
});
|
|
135
211
|
});
|
|
136
212
|
}
|
|
137
213
|
sendRegister() {
|
|
@@ -322,11 +398,13 @@ export class ConnectorClient extends EventEmitter {
|
|
|
322
398
|
}
|
|
323
399
|
this.backoffMs = BACKOFF_INITIAL_MS;
|
|
324
400
|
this.alreadyConnectedRetries = 0;
|
|
401
|
+
this.registration = { state: "accepted" };
|
|
325
402
|
this.resolveRegister();
|
|
326
403
|
this.emit("connected");
|
|
327
404
|
}
|
|
328
405
|
else {
|
|
329
406
|
const reason = ack.reason ?? "Unknown registration error";
|
|
407
|
+
this.registration = { state: "refused", reason };
|
|
330
408
|
if (reason === "Unsupported protocol version") {
|
|
331
409
|
this.intentionalClose = true;
|
|
332
410
|
this.rejectRegister(new Error(reason));
|
|
@@ -342,28 +420,46 @@ export class ConnectorClient extends EventEmitter {
|
|
|
342
420
|
}
|
|
343
421
|
}
|
|
344
422
|
handleSendAck(ack) {
|
|
345
|
-
this.emit("send_ack", ack);
|
|
346
423
|
const pending = this.pendingSends.get(ack.messageId);
|
|
347
424
|
if (pending) {
|
|
348
425
|
clearTimeout(pending.timer);
|
|
349
426
|
this.pendingSends.delete(ack.messageId);
|
|
350
|
-
pending.resolve(ack);
|
|
427
|
+
pending.resolve(structuredClone(ack));
|
|
428
|
+
}
|
|
429
|
+
try {
|
|
430
|
+
this.emit("send_ack", ack);
|
|
431
|
+
}
|
|
432
|
+
catch (err) {
|
|
433
|
+
console.error("[agent-network:connector-client] send_ack listener failed:", err);
|
|
351
434
|
}
|
|
352
435
|
}
|
|
353
436
|
handleStructuredError(event) {
|
|
354
|
-
this.emit("structured_error", event);
|
|
355
437
|
if (event.messageId) {
|
|
356
438
|
const pending = this.pendingSends.get(event.messageId);
|
|
357
439
|
if (pending) {
|
|
358
440
|
clearTimeout(pending.timer);
|
|
359
441
|
this.pendingSends.delete(event.messageId);
|
|
360
442
|
pending.reject(new ConnectorError(event.message, event.code, event.to));
|
|
361
|
-
return;
|
|
362
443
|
}
|
|
444
|
+
try {
|
|
445
|
+
this.emit("structured_error", event);
|
|
446
|
+
}
|
|
447
|
+
catch (err) {
|
|
448
|
+
console.error("[agent-network:connector-client] structured_error listener failed:", err);
|
|
449
|
+
}
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
try {
|
|
453
|
+
this.emit("structured_error", event);
|
|
454
|
+
}
|
|
455
|
+
catch (err) {
|
|
456
|
+
console.error("[agent-network:connector-client] structured_error listener failed:", err);
|
|
363
457
|
}
|
|
364
458
|
this.emit("error", new Error(`[${event.code}] ${event.message}`));
|
|
365
459
|
}
|
|
366
|
-
handleClose
|
|
460
|
+
handleClose(ws, code, reason) {
|
|
461
|
+
if (this.ws !== ws)
|
|
462
|
+
return;
|
|
367
463
|
const reasonStr = reason
|
|
368
464
|
? typeof reason === "string"
|
|
369
465
|
? reason
|
|
@@ -371,11 +467,13 @@ export class ConnectorClient extends EventEmitter {
|
|
|
371
467
|
: "";
|
|
372
468
|
dbg("connection closed code=%s reason=%s intentional=%s", code ?? "?", reasonStr, this.intentionalClose);
|
|
373
469
|
const wasRegistering = this.registerReject !== null;
|
|
470
|
+
this.everDropped = true;
|
|
374
471
|
this.cleanupConnection();
|
|
375
472
|
const replacedByNewRuntime = code === REPLACED_BY_NEW_RUNTIME_CODE &&
|
|
376
473
|
reasonStr === REPLACED_BY_NEW_RUNTIME_REASON;
|
|
377
474
|
if (replacedByNewRuntime) {
|
|
378
475
|
this.intentionalClose = true;
|
|
476
|
+
this.registration = { state: "replaced" };
|
|
379
477
|
const msg = "This agent was claimed by another Runtime " +
|
|
380
478
|
"(this Runtime disconnected). " +
|
|
381
479
|
"Re-run `openclaw channels login --channel agent-network` " +
|
|
@@ -396,17 +494,21 @@ export class ConnectorClient extends EventEmitter {
|
|
|
396
494
|
if (!this.intentionalClose) {
|
|
397
495
|
this.scheduleReconnect();
|
|
398
496
|
}
|
|
399
|
-
}
|
|
497
|
+
}
|
|
400
498
|
handleError = (err) => {
|
|
401
499
|
dbg("websocket error: %s", err.message);
|
|
402
500
|
this.emit("error", err);
|
|
403
501
|
};
|
|
404
502
|
scheduleReconnect() {
|
|
503
|
+
if (this.intentionalClose || this.ws)
|
|
504
|
+
return;
|
|
405
505
|
this.clearReconnectTimer();
|
|
406
506
|
const delay = this.calculateBackoff();
|
|
407
507
|
dbg("reconnecting in %dms", Math.round(delay));
|
|
408
508
|
this.reconnectTimer = setTimeout(() => {
|
|
409
509
|
this.reconnectTimer = null;
|
|
510
|
+
if (this.intentionalClose || this.ws)
|
|
511
|
+
return;
|
|
410
512
|
this.doConnect().catch(() => {
|
|
411
513
|
});
|
|
412
514
|
}, delay);
|
|
@@ -434,28 +536,33 @@ export class ConnectorClient extends EventEmitter {
|
|
|
434
536
|
}
|
|
435
537
|
}
|
|
436
538
|
cleanupConnection() {
|
|
539
|
+
this.registration = { state: "none" };
|
|
540
|
+
if (this.keepalive) {
|
|
541
|
+
this.keepalive.stop();
|
|
542
|
+
this.keepalive = null;
|
|
543
|
+
}
|
|
437
544
|
if (this.ws) {
|
|
438
|
-
this.ws.off("message", this.handleMessage);
|
|
439
|
-
this.ws.off("close", this.handleClose);
|
|
440
|
-
this.ws.off("error", this.handleError);
|
|
441
545
|
this.ws = null;
|
|
442
546
|
}
|
|
443
547
|
if (this.registerTimer) {
|
|
444
548
|
clearTimeout(this.registerTimer);
|
|
445
549
|
this.registerTimer = null;
|
|
446
550
|
}
|
|
447
|
-
for (const [, pending] of this.pendingSends) {
|
|
551
|
+
for (const [messageId, pending] of this.pendingSends) {
|
|
448
552
|
clearTimeout(pending.timer);
|
|
449
|
-
pending.reject(new
|
|
553
|
+
pending.reject(new SendOutcomeUnknownError(messageId, "connection_closed"));
|
|
450
554
|
}
|
|
451
555
|
this.pendingSends.clear();
|
|
452
556
|
}
|
|
453
557
|
sendEvent(event) {
|
|
558
|
+
return this.sendSerializedEvent(JSON.stringify(event), event.event);
|
|
559
|
+
}
|
|
560
|
+
sendSerializedEvent(serializedEvent, eventName) {
|
|
454
561
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
455
|
-
this.ws.send(
|
|
562
|
+
this.ws.send(serializedEvent);
|
|
456
563
|
return true;
|
|
457
564
|
}
|
|
458
|
-
dbg("send failed: ws not open event=%s",
|
|
565
|
+
dbg("send failed: ws not open event=%s", eventName);
|
|
459
566
|
return false;
|
|
460
567
|
}
|
|
461
568
|
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConversationManager } from "./conversation-manager.js";
|
|
2
|
+
export declare function runWithConversationManagerContext<T>(manager: ConversationManager, callback: () => T): T;
|
|
3
|
+
export declare function getInvocationConversationManager(): ConversationManager | null;
|
|
4
|
+
//# sourceMappingURL=conversation-manager-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-manager-context.d.ts","sourceRoot":"","sources":["../src/conversation-manager-context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAIrE,wBAAgB,iCAAiC,CAAC,CAAC,EACjD,OAAO,EAAE,mBAAmB,EAC5B,QAAQ,EAAE,MAAM,CAAC,GAChB,CAAC,CAEH;AAED,wBAAgB,gCAAgC,IAAI,mBAAmB,GAAG,IAAI,CAE7E"}
|