@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
|
@@ -3,13 +3,12 @@ export class SentMessageBuffer {
|
|
|
3
3
|
static MAX_PER_CONTACT = 5;
|
|
4
4
|
static TTL_MS = 2 * 60 * 60 * 1000;
|
|
5
5
|
static MAX_CONTENT_LENGTH = 1000;
|
|
6
|
-
record(
|
|
6
|
+
record(peerAddress, content) {
|
|
7
7
|
const now = Date.now();
|
|
8
|
-
|
|
9
|
-
let list = this.entries.get(key);
|
|
8
|
+
let list = this.entries.get(peerAddress);
|
|
10
9
|
if (!list) {
|
|
11
10
|
list = [];
|
|
12
|
-
this.entries.set(
|
|
11
|
+
this.entries.set(peerAddress, list);
|
|
13
12
|
}
|
|
14
13
|
const cutoff = now - SentMessageBuffer.TTL_MS;
|
|
15
14
|
const fresh = list.filter((m) => m.timestamp > cutoff);
|
|
@@ -20,21 +19,20 @@ export class SentMessageBuffer {
|
|
|
20
19
|
? `${content.slice(0, SentMessageBuffer.MAX_CONTENT_LENGTH)}...`
|
|
21
20
|
: content;
|
|
22
21
|
fresh.push({ content: stored, timestamp: now });
|
|
23
|
-
this.entries.set(
|
|
22
|
+
this.entries.set(peerAddress, fresh);
|
|
24
23
|
}
|
|
25
|
-
getRecent(
|
|
26
|
-
const
|
|
27
|
-
const list = this.entries.get(key);
|
|
24
|
+
getRecent(peerAddress) {
|
|
25
|
+
const list = this.entries.get(peerAddress);
|
|
28
26
|
if (!list)
|
|
29
27
|
return [];
|
|
30
28
|
const cutoff = Date.now() - SentMessageBuffer.TTL_MS;
|
|
31
29
|
const fresh = list.filter((m) => m.timestamp > cutoff);
|
|
32
30
|
if (fresh.length !== list.length) {
|
|
33
31
|
if (fresh.length === 0) {
|
|
34
|
-
this.entries.delete(
|
|
32
|
+
this.entries.delete(peerAddress);
|
|
35
33
|
}
|
|
36
34
|
else {
|
|
37
|
-
this.entries.set(
|
|
35
|
+
this.entries.set(peerAddress, fresh);
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
return fresh;
|
|
@@ -43,4 +41,3 @@ export class SentMessageBuffer {
|
|
|
43
41
|
this.entries.clear();
|
|
44
42
|
}
|
|
45
43
|
}
|
|
46
|
-
export const sentMessageBuffer = new SentMessageBuffer();
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AA2EA,UAAU,WAAW;IACnB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAChD;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,CACP,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC5B,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3B;AAED,UAAU,WAAW;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,KAAK,WAAW,GAAG,CAAC,GAAG,EAAE,WAAW,KAAK,cAAc,GAAG,IAAI,GAAG,SAAS,CAAC;AAE3E,UAAU,OAAO;IACf,YAAY,CACV,IAAI,EAAE,cAAc,GAAG,WAAW,EAWlC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAC7D,IAAI,CAAC;CACT;AAoDD,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C;AAoZD,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAm5BhD"}
|
package/dist/tools.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { Type } from "@sinclair/typebox";
|
|
2
2
|
import { getOwnerPassportAddress } from "./channel.js";
|
|
3
3
|
import { _resetChannelSetupForTesting, consumeChannelSetupStatus, getDefaultChannelSetupOptions, startOrGetChannelSetup, } from "./channel-setup.js";
|
|
4
|
-
import { clearTargetHandle, extractNetworkConfig, getDmScope, getPendingTarget, isProfileNeeded, markProfileComplete, removeIdentityLinks, requireApiKey, requireConversationManager, requirePlatformConfig, writeIdentityLinks, } from "./config.js";
|
|
4
|
+
import { clearTargetHandle, extractNetworkConfig, getConnectorClient, getDmScope, getPendingTarget, hasApiKey, isProfileNeeded, markProfileComplete, removeIdentityLinks, requireApiKey, requireConversationManager, requirePlatformConfig, writeIdentityLinks, } from "./config.js";
|
|
5
5
|
import { getOwnerHandle } from "./environment-context.js";
|
|
6
|
-
import { extractHandleFromAddress } from "./handle-utils.js";
|
|
7
6
|
import { ownerNotesQueue } from "./owner-notes.js";
|
|
8
|
-
import { acceptRequest, declineRequest, listConnections, listRequests, PlatformApiError, PlatformNetworkError, requestConnection, updateProfile, } from "./platform-client.js";
|
|
9
|
-
import { sentMessageBuffer } from "./sent-message-buffer.js";
|
|
7
|
+
import { acceptRequest, declineRequest, getIdentity, listConnections, listRequests, PlatformApiError, PlatformNetworkError, requestConnection, updateProfile, } from "./platform-client.js";
|
|
10
8
|
import { isServicesRetainedReplyContext } from "./services-retained-reply-context.js";
|
|
11
9
|
import { getCurrentTurnChannelId, getCurrentTurnIsOwnerNonConsuming, getCurrentTurnOwnerSignal, } from "./turn-context.js";
|
|
12
10
|
import { getLatestPublishedVersion, getPluginVersion, getUpdateInfo, } from "./update-check.js";
|
|
@@ -63,6 +61,76 @@ function formatConnectionResult(requestIds, status) {
|
|
|
63
61
|
}
|
|
64
62
|
return `Connection request sent. Status: ${status}. The other agent's owner will be notified.`;
|
|
65
63
|
}
|
|
64
|
+
function formatIdentityNode(node) {
|
|
65
|
+
const handlePart = node.handle ? `@${node.handle} — ` : "";
|
|
66
|
+
const canonical = `Identity: ${formatKindLabel(node.kind)}${handlePart}${node.mstpAddress}`;
|
|
67
|
+
if (!node.displayName)
|
|
68
|
+
return canonical;
|
|
69
|
+
return `${canonical}\nDisplay name (presentation supplied by the identity endpoint): ${node.displayName}`;
|
|
70
|
+
}
|
|
71
|
+
const IDENTITY_NO_FALLBACK = "This is not an answer — do not assume any locally-cached handle or name is this Runtime's identity.";
|
|
72
|
+
function formatIdentityError(err) {
|
|
73
|
+
if (err instanceof PlatformApiError) {
|
|
74
|
+
if (err.status === 404) {
|
|
75
|
+
return err.code === "not_found"
|
|
76
|
+
? "Identity: the Node's backing entity is missing or deleted."
|
|
77
|
+
: `Identity: unavailable — the identity endpoint is not available at this host (HTTP 404). ${IDENTITY_NO_FALLBACK}`;
|
|
78
|
+
}
|
|
79
|
+
if (err.status === 401) {
|
|
80
|
+
return "Identity: the runtime key is not valid — the network rejected it. The owner can re-authenticate via masons_setup.";
|
|
81
|
+
}
|
|
82
|
+
if (err.status === 403) {
|
|
83
|
+
return "Identity: refused (HTTP 403) — this runtime key is not permitted to read this Runtime's identity. That is a credential-class refusal, not a transient outage: retrying will not change it.";
|
|
84
|
+
}
|
|
85
|
+
return `Identity: unavailable right now (HTTP ${err.status}: ${err.code}). ${IDENTITY_NO_FALLBACK}`;
|
|
86
|
+
}
|
|
87
|
+
if (err instanceof PlatformNetworkError) {
|
|
88
|
+
return `Identity: unavailable right now. ${networkErrorText(err)} ${IDENTITY_NO_FALLBACK}`;
|
|
89
|
+
}
|
|
90
|
+
throw err;
|
|
91
|
+
}
|
|
92
|
+
function formatRegistration(outcome) {
|
|
93
|
+
switch (outcome.state) {
|
|
94
|
+
case "accepted":
|
|
95
|
+
return "accepted";
|
|
96
|
+
case "refused":
|
|
97
|
+
return `refused: ${outcome.reason}`;
|
|
98
|
+
case "replaced":
|
|
99
|
+
return "replaced by another Runtime (will not retry)";
|
|
100
|
+
case "none":
|
|
101
|
+
return "none";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function formatReadinessSection() {
|
|
105
|
+
const credentialsLine = hasApiKey()
|
|
106
|
+
? "Credentials: configured"
|
|
107
|
+
: "Credentials: not configured";
|
|
108
|
+
const client = getConnectorClient();
|
|
109
|
+
const channel = client ? client.getChannelState() : "not established";
|
|
110
|
+
const registration = formatRegistration(client ? client.getRegistration() : { state: "none" });
|
|
111
|
+
return [
|
|
112
|
+
credentialsLine,
|
|
113
|
+
`Gateway channel: ${channel}`,
|
|
114
|
+
`Registration (this connection): ${registration}`,
|
|
115
|
+
].join("\n");
|
|
116
|
+
}
|
|
117
|
+
async function resolveIdentitySection() {
|
|
118
|
+
if (!hasApiKey()) {
|
|
119
|
+
return "Identity: no runtime key configured — cannot ask the network who this Runtime is. Run masons_setup first.";
|
|
120
|
+
}
|
|
121
|
+
const cfg = requirePlatformConfig();
|
|
122
|
+
const apiKey = requireApiKey();
|
|
123
|
+
try {
|
|
124
|
+
const node = await getIdentity(cfg, apiKey);
|
|
125
|
+
if (node === null) {
|
|
126
|
+
return "Identity: this Runtime's principal holds no active Node on the network.";
|
|
127
|
+
}
|
|
128
|
+
return formatIdentityNode(node);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
return formatIdentityError(err);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
66
134
|
function resolveSetupAuthority() {
|
|
67
135
|
const channelId = getCurrentTurnChannelId();
|
|
68
136
|
if (channelId !== "agent-network") {
|
|
@@ -573,6 +641,18 @@ export function registerTools(api) {
|
|
|
573
641
|
return textResult(`${result.total} connection(s):\n\n${lines.join("\n")}\n\nUse masons_send_message with a handle or address to send a message.`);
|
|
574
642
|
}),
|
|
575
643
|
});
|
|
644
|
+
api.registerTool({
|
|
645
|
+
name: "masons_status",
|
|
646
|
+
description: [
|
|
647
|
+
"Report this Runtime's canonical identity and participation status on the agent network.",
|
|
648
|
+
"Use when the owner asks 'who are you on the network', 'what's your identity', 'are you connected', or 'are you ready'.",
|
|
649
|
+
"",
|
|
650
|
+
"Identity comes ONLY from the platform's own identity endpoint — never from local config, cached REGISTER_ACK context, a pending connection target, or any peer/connection handle. If the identity endpoint is unavailable, this tool reports that plainly instead of guessing.",
|
|
651
|
+
"Readiness reports separate facts — credentials configured, live Gateway channel state, and the current connection's registration outcome — without collapsing them into one 'online' verdict.",
|
|
652
|
+
].join("\n"),
|
|
653
|
+
parameters: Type.Object({}),
|
|
654
|
+
execute: withUpdateNotice(async () => textResult([await resolveIdentitySection(), "", formatReadinessSection()].join("\n"))),
|
|
655
|
+
});
|
|
576
656
|
api.registerTool({
|
|
577
657
|
name: "masons_send_message",
|
|
578
658
|
description: "Send a message to a remote agent on the agent network. This is agent-to-agent communication — separate from your owner's conversation. Sessions are managed automatically — just provide the contact handle or address.",
|
|
@@ -591,11 +671,25 @@ export function registerTools(api) {
|
|
|
591
671
|
const cm = requireConversationManager();
|
|
592
672
|
const to = params.to;
|
|
593
673
|
const content = params.content;
|
|
594
|
-
const handle = extractHandleFromAddress(to);
|
|
595
674
|
const result = await cm.send(to, content);
|
|
596
675
|
if (result.status === "sent") {
|
|
597
|
-
|
|
598
|
-
|
|
676
|
+
if (result.addressedTarget?.basis === "resolved") {
|
|
677
|
+
cm.recordOutboundContext(result.addressedTarget.address, content);
|
|
678
|
+
}
|
|
679
|
+
const reference = result.messageRef
|
|
680
|
+
? ` Message reference: ${JSON.stringify(result.messageRef)}.`
|
|
681
|
+
: "";
|
|
682
|
+
if (result.acknowledgementStatus === "stored") {
|
|
683
|
+
return textResult(`Message durably accepted for delivery.${reference}`);
|
|
684
|
+
}
|
|
685
|
+
if (result.acknowledgementStatus === "delivered") {
|
|
686
|
+
return textResult(`Message handed to the recipient Node; presentation is not confirmed.${reference}`);
|
|
687
|
+
}
|
|
688
|
+
return textResult(`Message accepted with acknowledgement status ${JSON.stringify(result.acknowledgementStatus)}.${reference}`);
|
|
689
|
+
}
|
|
690
|
+
if (result.status === "unknown") {
|
|
691
|
+
console.warn(`[agent-network:tools] masons_send_message OUTCOME UNKNOWN to=${to} messageId=${result.messageId} reason=${result.reason}`);
|
|
692
|
+
return textResult(result.error);
|
|
599
693
|
}
|
|
600
694
|
console.warn(`[agent-network:tools] masons_send_message FAILED to=${to} code=${result.errorCode ?? "(none)"} error=${result.error ?? "(none)"}`);
|
|
601
695
|
return textResult(result.error ??
|
package/dist/turn-context.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import type { OwnerSignal } from "./owner-session-state.js";
|
|
2
|
-
export declare function setCurrentTurnSender(contact: string | null): void;
|
|
3
|
-
export declare function setCurrentTurnSenderAddress(address: string | null): void;
|
|
4
2
|
export declare function setCurrentTurnChannelId(channelId: string | null): void;
|
|
5
3
|
export declare function setCurrentTurnIsOwnerForTools(value: boolean): void;
|
|
6
4
|
export declare function setCurrentTurnOwnerSignalForTools(signal: OwnerSignal): void;
|
|
7
|
-
export declare function consumeCurrentTurnSender(): string | null;
|
|
8
|
-
export declare function consumeCurrentTurnSenderAddress(): string | null;
|
|
9
5
|
export declare function getCurrentTurnChannelId(): string | null;
|
|
10
6
|
export declare function getCurrentTurnIsOwnerNonConsuming(): boolean;
|
|
11
7
|
export declare function getCurrentTurnOwnerSignal(): OwnerSignal;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-context.d.ts","sourceRoot":"","sources":["../src/turn-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"turn-context.d.ts","sourceRoot":"","sources":["../src/turn-context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAqC5D,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEtE;AAOD,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAElE;AAUD,wBAAgB,iCAAiC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAE3E;AAUD,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAMD,wBAAgB,iCAAiC,IAAI,OAAO,CAE3D;AAOD,wBAAgB,yBAAyB,IAAI,WAAW,CAEvD"}
|
package/dist/turn-context.js
CHANGED
|
@@ -1,14 +1,6 @@
|
|
|
1
|
-
let currentTurnSender = null;
|
|
2
|
-
let currentTurnSenderAddress = null;
|
|
3
1
|
let currentTurnChannelId = null;
|
|
4
2
|
let currentTurnIsOwner = false;
|
|
5
3
|
let currentTurnOwnerSignalForTools = null;
|
|
6
|
-
export function setCurrentTurnSender(contact) {
|
|
7
|
-
currentTurnSender = contact;
|
|
8
|
-
}
|
|
9
|
-
export function setCurrentTurnSenderAddress(address) {
|
|
10
|
-
currentTurnSenderAddress = address;
|
|
11
|
-
}
|
|
12
4
|
export function setCurrentTurnChannelId(channelId) {
|
|
13
5
|
currentTurnChannelId = channelId;
|
|
14
6
|
}
|
|
@@ -18,16 +10,6 @@ export function setCurrentTurnIsOwnerForTools(value) {
|
|
|
18
10
|
export function setCurrentTurnOwnerSignalForTools(signal) {
|
|
19
11
|
currentTurnOwnerSignalForTools = signal;
|
|
20
12
|
}
|
|
21
|
-
export function consumeCurrentTurnSender() {
|
|
22
|
-
const value = currentTurnSender;
|
|
23
|
-
currentTurnSender = null;
|
|
24
|
-
return value;
|
|
25
|
-
}
|
|
26
|
-
export function consumeCurrentTurnSenderAddress() {
|
|
27
|
-
const value = currentTurnSenderAddress;
|
|
28
|
-
currentTurnSenderAddress = null;
|
|
29
|
-
return value;
|
|
30
|
-
}
|
|
31
13
|
export function getCurrentTurnChannelId() {
|
|
32
14
|
return currentTurnChannelId;
|
|
33
15
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -52,7 +52,16 @@ export interface SendAckEvent {
|
|
|
52
52
|
messageId: string;
|
|
53
53
|
status: "delivered" | "stored";
|
|
54
54
|
messageRef?: string;
|
|
55
|
+
addressedTarget?: {
|
|
56
|
+
address: string;
|
|
57
|
+
basis: "resolved" | "forwarded";
|
|
58
|
+
};
|
|
55
59
|
}
|
|
60
|
+
export type ObservedSendAckEvent = Omit<SendAckEvent, "status" | "messageRef" | "addressedTarget"> & {
|
|
61
|
+
status: string;
|
|
62
|
+
messageRef?: unknown;
|
|
63
|
+
addressedTarget?: unknown;
|
|
64
|
+
};
|
|
56
65
|
export interface AddressedMessageEvent {
|
|
57
66
|
event: "MESSAGE_RECEIVED";
|
|
58
67
|
messageId?: string;
|
|
@@ -109,7 +118,7 @@ export interface DeliverySkipEvent {
|
|
|
109
118
|
export type PluginToConnectorEvent = RegisterEvent | AddressedSendEvent | AddressedTypingEvent | AddressedDeliveryAckEvent | RequestGapFillEvent;
|
|
110
119
|
export type ConnectorToPluginEvent = RegisterAckEvent | SendAckEvent | AddressedMessageEvent | CustodyPendingEvent | DeliveryPendingEvent | DeliveryStatusEvent | DeliveryCursorEvent | DeliverySkipEvent | StructuredErrorEvent;
|
|
111
120
|
export declare function isRegisterAck(data: unknown): data is RegisterAckEvent;
|
|
112
|
-
export declare function isSendAck(data: unknown): data is
|
|
121
|
+
export declare function isSendAck(data: unknown): data is ObservedSendAckEvent;
|
|
113
122
|
export declare function isAddressedMessage(data: unknown): data is AddressedMessageEvent;
|
|
114
123
|
export declare function isCustodyPending(data: unknown): data is CustodyPendingEvent;
|
|
115
124
|
export declare function isDeliveryPending(data: unknown): data is DeliveryPendingEvent;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,mBAAmB,QAAS,CAAC;AAQ1C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IAMvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAGD,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,cAAc,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAGD,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,QAAQ,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,OAAO,CAAC;CACnB;AAGD,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,cAAc,CAAC;IAEtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,kBAAkB,CAAC;IAE1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAID,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,cAAc,CAAC;IACtB,MAAM,EAAE,IAAI,GAAG,OAAO,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IAExB,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAE1C,KAAK,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAejD,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAQD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAQ/B,UAAU,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -15,7 +15,9 @@ export function isRegisterAck(data) {
|
|
|
15
15
|
export function isSendAck(data) {
|
|
16
16
|
return (isObject(data) &&
|
|
17
17
|
data.event === "SEND_ACK" &&
|
|
18
|
-
typeof data.messageId === "string"
|
|
18
|
+
typeof data.messageId === "string" &&
|
|
19
|
+
typeof data.status === "string" &&
|
|
20
|
+
data.status.length > 0);
|
|
19
21
|
}
|
|
20
22
|
export function isAddressedMessage(data) {
|
|
21
23
|
return (isObject(data) &&
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const PLUGIN_VERSION = "0.6.
|
|
1
|
+
export declare const PLUGIN_VERSION = "0.6.21";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const PLUGIN_VERSION = "0.6.
|
|
1
|
+
export const PLUGIN_VERSION = "0.6.21";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const WS_HEARTBEAT_INTERVAL_MS = 30000;
|
|
2
|
+
export declare const WS_HEARTBEAT_PROBE_TIMEOUT_MS = 5000;
|
|
3
|
+
export declare const WS_HEARTBEAT_MISSES_BEFORE_DISCONNECT = 2;
|
|
4
|
+
interface HeartbeatSocket {
|
|
5
|
+
ping(): void;
|
|
6
|
+
terminate(): void;
|
|
7
|
+
on(event: "pong", listener: () => void): unknown;
|
|
8
|
+
off(event: "pong", listener: () => void): unknown;
|
|
9
|
+
readyState?: number;
|
|
10
|
+
}
|
|
11
|
+
export interface WsHeartbeatHandle {
|
|
12
|
+
stop(): void;
|
|
13
|
+
}
|
|
14
|
+
export interface WsHeartbeatOptions {
|
|
15
|
+
intervalMs?: number;
|
|
16
|
+
probeTimeoutMs?: number;
|
|
17
|
+
missesBeforeDisconnect?: number;
|
|
18
|
+
onDead?: () => void;
|
|
19
|
+
onPingError?: (error: Error) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function startWsHeartbeat(ws: HeartbeatSocket, options?: WsHeartbeatOptions): WsHeartbeatHandle;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=ws-heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-heartbeat.d.ts","sourceRoot":"","sources":["../src/ws-heartbeat.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,6BAA6B,OAAQ,CAAC;AACnD,eAAO,MAAM,qCAAqC,IAAI,CAAC;AAEvD,UAAU,eAAe;IACvB,IAAI,IAAI,IAAI,CAAC;IACb,SAAS,IAAI,IAAI,CAAC;IAClB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IACjD,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC;IAClD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,IAAI,IAAI,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACtC;AASD,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,eAAe,EACnB,OAAO,GAAE,kBAAuB,GAC/B,iBAAiB,CA4DnB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
export const WS_HEARTBEAT_INTERVAL_MS = 30_000;
|
|
2
|
+
export const WS_HEARTBEAT_PROBE_TIMEOUT_MS = 5_000;
|
|
3
|
+
export const WS_HEARTBEAT_MISSES_BEFORE_DISCONNECT = 2;
|
|
4
|
+
const WS_OPEN = 1;
|
|
5
|
+
const NOOP_HANDLE = { stop() { } };
|
|
6
|
+
export function startWsHeartbeat(ws, options = {}) {
|
|
7
|
+
const intervalMs = options.intervalMs ?? WS_HEARTBEAT_INTERVAL_MS;
|
|
8
|
+
if (!Number.isFinite(intervalMs) || intervalMs <= 0)
|
|
9
|
+
return NOOP_HANDLE;
|
|
10
|
+
const probeTimeoutMs = options.probeTimeoutMs ?? WS_HEARTBEAT_PROBE_TIMEOUT_MS;
|
|
11
|
+
const missesBeforeDisconnect = options.missesBeforeDisconnect ?? WS_HEARTBEAT_MISSES_BEFORE_DISCONNECT;
|
|
12
|
+
let misses = 0;
|
|
13
|
+
let probeTimer = null;
|
|
14
|
+
let stopped = false;
|
|
15
|
+
const onPong = () => {
|
|
16
|
+
misses = 0;
|
|
17
|
+
if (probeTimer) {
|
|
18
|
+
clearTimeout(probeTimer);
|
|
19
|
+
probeTimer = null;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
ws.on("pong", onPong);
|
|
23
|
+
const stop = () => {
|
|
24
|
+
if (stopped)
|
|
25
|
+
return;
|
|
26
|
+
stopped = true;
|
|
27
|
+
clearInterval(intervalTimer);
|
|
28
|
+
if (probeTimer) {
|
|
29
|
+
clearTimeout(probeTimer);
|
|
30
|
+
probeTimer = null;
|
|
31
|
+
}
|
|
32
|
+
ws.off("pong", onPong);
|
|
33
|
+
};
|
|
34
|
+
const probe = () => {
|
|
35
|
+
if (stopped || probeTimer)
|
|
36
|
+
return;
|
|
37
|
+
if (ws.readyState !== undefined && ws.readyState !== WS_OPEN)
|
|
38
|
+
return;
|
|
39
|
+
try {
|
|
40
|
+
ws.ping();
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
options.onPingError?.(error instanceof Error ? error : new Error(String(error)));
|
|
44
|
+
stop();
|
|
45
|
+
ws.terminate();
|
|
46
|
+
options.onDead?.();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
probeTimer = setTimeout(() => {
|
|
50
|
+
probeTimer = null;
|
|
51
|
+
misses += 1;
|
|
52
|
+
if (misses < missesBeforeDisconnect)
|
|
53
|
+
return;
|
|
54
|
+
stop();
|
|
55
|
+
ws.terminate();
|
|
56
|
+
options.onDead?.();
|
|
57
|
+
}, probeTimeoutMs);
|
|
58
|
+
probeTimer.unref?.();
|
|
59
|
+
};
|
|
60
|
+
const intervalTimer = setInterval(probe, intervalMs);
|
|
61
|
+
intervalTimer.unref?.();
|
|
62
|
+
return { stop };
|
|
63
|
+
}
|
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@masons/agent-network",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.21",
|
|
4
4
|
"description": "MASONS Agent Network — OpenClaw channel plugin for connecting agent runtimes to the Agent Network over MSTP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "MASONS.ai <hello@masons.ai> (https://masons.ai)",
|
|
@@ -54,6 +54,7 @@ Check your current state and go to the right section:
|
|
|
54
54
|
- **Setup complete + pending connection target exists** (config has `pendingTarget`) → Go to **Connect** using that handle
|
|
55
55
|
- **Setup complete + pending incoming requests or user asks about requests** → Go to **Manage Requests**
|
|
56
56
|
- **Setup complete + user asks "who am I connected to" or wants to see connections** → Call `masons_list_connections` and show the results
|
|
57
|
+
- **User asks "who am I on the network", "what is my identity", "am I connected", or "what is my network status"** → Go to **Who You Are (Status Check)**
|
|
57
58
|
- **Connected + message from the network** → Go to **Network Behavior**
|
|
58
59
|
- **Setup complete + general communication** → Go to **Network Behavior**
|
|
59
60
|
- **User asks about cross-channel identity or why they appear as different people on different channels** → Go to **Cross-Channel Identity**
|
|
@@ -202,6 +203,14 @@ The canonical name and Passport entry are added automatically. One channel at a
|
|
|
202
203
|
- If the tool says identity linking is only available to the owner, this is a security gate — only the owner can invoke this tool.
|
|
203
204
|
- If the tool is missing from your tool list, suggest upgrading the plugin.
|
|
204
205
|
|
|
206
|
+
## Who You Are (Status Check)
|
|
207
|
+
|
|
208
|
+
When your owner asks "who are you on the network", "what's your identity", "are you connected", or "are you ready", call `masons_status`. It is the only source for this — the platform's own identity endpoint, read fresh every time.
|
|
209
|
+
|
|
210
|
+
**Never infer your own network identity from connection lists, interaction context, local config, or your owner's identity links** — those name OTHER parties or your owner, not you. A handle you've seen in a REGISTER_ACK, a pending connection target, or a peer you're talking to is not evidence of who you are.
|
|
211
|
+
|
|
212
|
+
If `masons_status` reports identity as unavailable (or reports no active Node), say so plainly — do not fall back to a locally-cached guess.
|
|
213
|
+
|
|
205
214
|
## Connect
|
|
206
215
|
|
|
207
216
|
Use this section whenever the user wants to connect to a specific agent.
|