@masons/agent-network 0.5.14 → 0.5.16
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 +0 -7
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +3 -174
- package/dist/cli-setup.d.ts +0 -109
- package/dist/cli-setup.d.ts.map +1 -1
- package/dist/cli-setup.js +16 -570
- package/dist/config-fs.d.ts +4 -0
- package/dist/config-fs.d.ts.map +1 -0
- package/dist/config-fs.js +23 -0
- package/dist/config-schema.js +2 -2
- package/dist/config.d.ts +2 -210
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -334
- package/dist/connector-client.d.ts +0 -32
- package/dist/connector-client.d.ts.map +1 -1
- package/dist/connector-client.js +1 -89
- package/dist/constants.d.ts +0 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +2 -3
- package/dist/conversation-manager.d.ts +0 -106
- package/dist/conversation-manager.d.ts.map +1 -1
- package/dist/conversation-manager.js +2 -131
- package/dist/environment-context.d.ts +0 -24
- package/dist/environment-context.d.ts.map +1 -1
- package/dist/environment-context.js +0 -42
- package/dist/handle-utils.d.ts +0 -14
- package/dist/handle-utils.d.ts.map +1 -1
- package/dist/handle-utils.js +0 -14
- package/dist/index.js +0 -9
- package/dist/owner-notes.d.ts +0 -33
- package/dist/owner-notes.d.ts.map +1 -1
- package/dist/owner-notes.js +2 -41
- package/dist/owner-session-state.d.ts +0 -26
- package/dist/owner-session-state.d.ts.map +1 -1
- package/dist/owner-session-state.js +0 -37
- package/dist/platform-client.d.ts +13 -202
- package/dist/platform-client.d.ts.map +1 -1
- package/dist/platform-client.js +22 -171
- package/dist/plugin.d.ts +5 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +3 -167
- package/dist/sent-message-buffer.d.ts +0 -36
- package/dist/sent-message-buffer.d.ts.map +1 -1
- package/dist/sent-message-buffer.js +1 -45
- package/dist/tools.d.ts +0 -28
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +36 -240
- package/dist/turn-context.d.ts +0 -45
- package/dist/turn-context.d.ts.map +1 -1
- package/dist/turn-context.js +0 -57
- package/dist/types.d.ts +0 -67
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +0 -7
- package/dist/update-cache.d.ts +0 -17
- package/dist/update-cache.d.ts.map +1 -1
- package/dist/update-cache.js +1 -21
- package/dist/update-check.d.ts +1 -40
- package/dist/update-check.d.ts.map +1 -1
- package/dist/update-check.js +7 -66
- package/dist/version.d.ts +1 -2
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -2
- package/openclaw.plugin.json +94 -3
- package/package.json +11 -10
- package/skills/agent-network/SKILL.md +21 -47
- package/skills/agent-network/references/troubleshooting.md +5 -5
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Conversation Manager — maps contacts to conversations.
|
|
3
|
-
*
|
|
4
|
-
* Owns the identity-based API that the Tool Interface and Inbound Dispatcher
|
|
5
|
-
* call. Sends messages directly to routable addresses via ConnectorClient.send().
|
|
6
|
-
*
|
|
7
|
-
* Contact resolution: handle → `mstps://${connectorHost}/${handle}`
|
|
8
|
-
* Address schemes: MSTP (`mstps://`), handle (bare), passport (`passport:@`)
|
|
9
|
-
* Internal key: routable address.
|
|
10
|
-
* One conversation per contact, in-memory only (D3).
|
|
11
|
-
*
|
|
12
|
-
* @see docs/connector/gateway-v2-consumer-adaptation-plan.md PR 2
|
|
13
|
-
*/
|
|
14
1
|
import createDebug from "debug";
|
|
15
2
|
import { ConnectorError } from "./connector-client.js";
|
|
16
3
|
import { extractHandleFromAddress } from "./handle-utils.js";
|
|
17
4
|
const dbg = createDebug("agent-network:conversation-manager");
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Error code → tool result mapping
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
5
|
const ERROR_MESSAGES = {
|
|
22
6
|
ADDRESS_NOT_FOUND: "Cannot find agent '{to}'. Check the handle.",
|
|
23
7
|
ACCESS_DENIED: "No connection to '{to}'. Send a connection request first.",
|
|
@@ -29,50 +13,19 @@ function formatErrorMessage(code, to) {
|
|
|
29
13
|
const template = ERROR_MESSAGES[code] ?? `Send failed: ${code}`;
|
|
30
14
|
return to ? template.replace(/\{to\}/g, to) : template;
|
|
31
15
|
}
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
// ConversationManager
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
16
|
export class ConversationManager {
|
|
36
17
|
client;
|
|
37
18
|
connectorHost;
|
|
38
|
-
/** Conversations keyed by routable address */
|
|
39
19
|
conversations = new Map();
|
|
40
20
|
constructor(client, connectorHost) {
|
|
41
21
|
this.client = client;
|
|
42
22
|
this.connectorHost = connectorHost;
|
|
43
23
|
}
|
|
44
|
-
// -------------------------------------------------------------------------
|
|
45
|
-
// Public API — identity-based
|
|
46
|
-
// -------------------------------------------------------------------------
|
|
47
|
-
/**
|
|
48
|
-
* Send a message to a contact. Sends directly to the resolved address —
|
|
49
|
-
* no session management needed.
|
|
50
|
-
*
|
|
51
|
-
* Returns a structured result with status and optional error.
|
|
52
|
-
* ConnectorError codes (ADDRESS_NOT_FOUND, ACCESS_DENIED, etc.) are
|
|
53
|
-
* mapped to human-readable messages for LLM tool results.
|
|
54
|
-
*
|
|
55
|
-
* @param contact - Handle, MSTP address, or passport address of the target.
|
|
56
|
-
* @param content - Message content to send.
|
|
57
|
-
*/
|
|
58
24
|
async send(contact, content) {
|
|
59
25
|
const address = this.resolveAddress(contact);
|
|
60
|
-
// Ensure conversation entry exists
|
|
61
|
-
if (!this.conversations.has(address)) {
|
|
62
|
-
this.conversations.set(address, {
|
|
63
|
-
contact: this.extractHandle(address),
|
|
64
|
-
address,
|
|
65
|
-
lastMessageAt: Date.now(),
|
|
66
|
-
initiatedBy: "local",
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
26
|
try {
|
|
70
27
|
const ack = await this.client.send(address, content, "text");
|
|
71
|
-
|
|
72
|
-
const entry = this.conversations.get(address);
|
|
73
|
-
if (entry) {
|
|
74
|
-
entry.lastMessageAt = Date.now();
|
|
75
|
-
}
|
|
28
|
+
this.ensureConversationEntry(this.extractHandle(address), address, "local");
|
|
76
29
|
dbg("send contact=%s address=%s status=%s", contact, address, ack.status);
|
|
77
30
|
return { status: "sent" };
|
|
78
31
|
}
|
|
@@ -87,35 +40,20 @@ export class ConversationManager {
|
|
|
87
40
|
return { status: "failed", error: message };
|
|
88
41
|
}
|
|
89
42
|
}
|
|
90
|
-
/**
|
|
91
|
-
* Register an inbound conversation (remote agent or visitor initiated).
|
|
92
|
-
* Called by the channel adapter when a message arrives from a new address.
|
|
93
|
-
*/
|
|
94
43
|
registerInbound(contact, address) {
|
|
95
44
|
this.ensureConversationEntry(contact, address, "remote");
|
|
96
45
|
dbg("registerInbound contact=%s address=%s", contact, address);
|
|
97
46
|
}
|
|
98
|
-
/**
|
|
99
|
-
* Resolve a routable address to a contact handle.
|
|
100
|
-
* Used by the inbound dispatcher to derive sender identity from MESSAGE_RECEIVED.from.
|
|
101
|
-
*/
|
|
102
47
|
getContactByAddress(address) {
|
|
103
48
|
const entry = this.conversations.get(address);
|
|
104
49
|
if (entry)
|
|
105
50
|
return entry.contact;
|
|
106
|
-
// Try resolving — the address might be a full MSTP address while conversations
|
|
107
|
-
// are keyed by a different form. Extract handle as fallback.
|
|
108
51
|
for (const [, e] of this.conversations) {
|
|
109
52
|
if (e.address === address)
|
|
110
53
|
return e.contact;
|
|
111
54
|
}
|
|
112
55
|
return undefined;
|
|
113
56
|
}
|
|
114
|
-
/**
|
|
115
|
-
* List all conversations with metadata.
|
|
116
|
-
* `active` is always true for address-based protocol — there is no session
|
|
117
|
-
* lifecycle. Conversations persist until explicitly ended or Plugin restarts.
|
|
118
|
-
*/
|
|
119
57
|
listConversations() {
|
|
120
58
|
const result = [];
|
|
121
59
|
for (const [, entry] of this.conversations) {
|
|
@@ -129,32 +67,10 @@ export class ConversationManager {
|
|
|
129
67
|
}
|
|
130
68
|
return result;
|
|
131
69
|
}
|
|
132
|
-
/**
|
|
133
|
-
* Check if a conversation entry exists for a contact.
|
|
134
|
-
*
|
|
135
|
-
* Returns true for entries that are marked `ended` but not yet committed —
|
|
136
|
-
* this allows the deliver callback to flush buffered text from the same
|
|
137
|
-
* dispatch cycle as end_conversation (#999).
|
|
138
|
-
*
|
|
139
|
-
* Straggler text from *subsequent* dispatch cycles is still suppressed
|
|
140
|
-
* because `commitEndedConversations()` removes entries between cycles.
|
|
141
|
-
*/
|
|
142
70
|
hasConversation(contact) {
|
|
143
71
|
const address = this.resolveAddress(contact);
|
|
144
72
|
return this.conversations.has(address);
|
|
145
73
|
}
|
|
146
|
-
/**
|
|
147
|
-
* Mark the conversation with a contact as ended (deferred deletion).
|
|
148
|
-
*
|
|
149
|
-
* The entry is NOT removed immediately — it is flagged `ended` and stays
|
|
150
|
-
* in the Map until `commitEndedConversations()` is called after the
|
|
151
|
-
* current dispatch cycle completes. This prevents the "last-message-
|
|
152
|
-
* before-close" race where the dispatcher executes end_conversation
|
|
153
|
-
* before flushing buffered text (#999).
|
|
154
|
-
*
|
|
155
|
-
* No END_SESSION needed — the Connector manages connection lifecycle
|
|
156
|
-
* (idle timeout).
|
|
157
|
-
*/
|
|
158
74
|
endConversation(contact) {
|
|
159
75
|
const address = this.resolveAddress(contact);
|
|
160
76
|
const entry = this.conversations.get(address);
|
|
@@ -166,19 +82,6 @@ export class ConversationManager {
|
|
|
166
82
|
dbg("endConversation (no-op) contact=%s address=%s", contact, address);
|
|
167
83
|
}
|
|
168
84
|
}
|
|
169
|
-
/**
|
|
170
|
-
* Remove all conversations marked as `ended`.
|
|
171
|
-
*
|
|
172
|
-
* Call this after the dispatch cycle completes (in the `finally` block
|
|
173
|
-
* of `handleAddressedMessage`). Deferred deletion ensures that text
|
|
174
|
-
* buffered in the same dispatch cycle as end_conversation is delivered
|
|
175
|
-
* before the entry disappears.
|
|
176
|
-
*
|
|
177
|
-
* Pattern: React 18 batched updates / Qt `deleteLater()` — mutations
|
|
178
|
-
* during a dispatch cycle are committed only when the cycle ends.
|
|
179
|
-
*
|
|
180
|
-
* @see https://github.com/MASONS-ai/masons.ai/issues/999
|
|
181
|
-
*/
|
|
182
85
|
commitEndedConversations() {
|
|
183
86
|
let count = 0;
|
|
184
87
|
for (const [address, entry] of this.conversations) {
|
|
@@ -191,23 +94,6 @@ export class ConversationManager {
|
|
|
191
94
|
dbg("commitEndedConversations removed=%d", count);
|
|
192
95
|
}
|
|
193
96
|
}
|
|
194
|
-
// -------------------------------------------------------------------------
|
|
195
|
-
// Contact resolution
|
|
196
|
-
// -------------------------------------------------------------------------
|
|
197
|
-
/**
|
|
198
|
-
* Resolve a contact (handle, MSTP address, or passport address) to a
|
|
199
|
-
* routable address.
|
|
200
|
-
*
|
|
201
|
-
* Resolution order:
|
|
202
|
-
* 1. MSTP address (starts with mstps:// or mstp://) → return as-is.
|
|
203
|
-
* 2. Passport address (starts with passport:) → return as-is (already routable).
|
|
204
|
-
* 3. Already a key in the conversations map → return as-is.
|
|
205
|
-
* 4. Reverse lookup: if any existing conversation has this handle as its
|
|
206
|
-
* contact, use that conversation's address. This ensures replies to a
|
|
207
|
-
* cross-Connector sender route to the sender's original address, not to
|
|
208
|
-
* a locally-constructed address.
|
|
209
|
-
* 5. Otherwise treat as handle → construct `mstps://${connectorHost}/${handle}`.
|
|
210
|
-
*/
|
|
211
97
|
resolveAddress(contact) {
|
|
212
98
|
if (contact.startsWith("mstps://") || contact.startsWith("mstp://")) {
|
|
213
99
|
return contact;
|
|
@@ -218,26 +104,15 @@ export class ConversationManager {
|
|
|
218
104
|
if (this.conversations.has(contact)) {
|
|
219
105
|
return contact;
|
|
220
106
|
}
|
|
221
|
-
// Reverse lookup: handle → existing conversation address.
|
|
222
|
-
// Handles the case where inbound arrived from a remote Connector
|
|
223
|
-
// (e.g., "mstps://remote-host/mason") but the LLM replies using
|
|
224
|
-
// the bare handle "mason".
|
|
225
107
|
for (const [addr, entry] of this.conversations) {
|
|
226
108
|
if (entry.contact === contact)
|
|
227
109
|
return addr;
|
|
228
110
|
}
|
|
229
111
|
return `mstps://${this.connectorHost}/${contact}`;
|
|
230
112
|
}
|
|
231
|
-
/**
|
|
232
|
-
* Extract a display-friendly handle from any address scheme.
|
|
233
|
-
* Delegates to shared utility — single source of truth.
|
|
234
|
-
*/
|
|
235
113
|
extractHandle(address) {
|
|
236
114
|
return extractHandleFromAddress(address);
|
|
237
115
|
}
|
|
238
|
-
// -------------------------------------------------------------------------
|
|
239
|
-
// Internal
|
|
240
|
-
// -------------------------------------------------------------------------
|
|
241
116
|
ensureConversationEntry(contact, address, initiatedBy) {
|
|
242
117
|
if (!this.conversations.has(address)) {
|
|
243
118
|
this.conversations.set(address, {
|
|
@@ -251,14 +126,10 @@ export class ConversationManager {
|
|
|
251
126
|
const entry = this.conversations.get(address);
|
|
252
127
|
if (entry) {
|
|
253
128
|
entry.lastMessageAt = Date.now();
|
|
254
|
-
entry.ended = false;
|
|
129
|
+
entry.ended = false;
|
|
255
130
|
}
|
|
256
131
|
}
|
|
257
132
|
}
|
|
258
|
-
// -------------------------------------------------------------------------
|
|
259
|
-
// Test helpers
|
|
260
|
-
// -------------------------------------------------------------------------
|
|
261
|
-
/** @internal Reset for test isolation. */
|
|
262
133
|
_resetForTesting() {
|
|
263
134
|
this.conversations.clear();
|
|
264
135
|
}
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Environment Context — self-identity and owner identity.
|
|
3
|
-
*
|
|
4
|
-
* Populated from REGISTER_ACK when the Connector includes agent/owner fields
|
|
5
|
-
* (#969). Connection-scoped: cleared on disconnect, refreshed on reconnect.
|
|
6
|
-
*
|
|
7
|
-
* Module-level singleton — shared between connector-client.ts (write) and
|
|
8
|
-
* plugin.ts (read). Follows the same pattern as owner-session-state.ts.
|
|
9
|
-
*
|
|
10
|
-
* **Trust model**: Identity is Connector-asserted, not cryptographically
|
|
11
|
-
* verified. The Plugin trusts the Connector because they communicate over an
|
|
12
|
-
* authenticated WebSocket channel. A self-hosted Connector could assert
|
|
13
|
-
* arbitrary identity — this is the same trust level as the `from` field on
|
|
14
|
-
* MESSAGE_RECEIVED. Do not build security-critical logic on these values.
|
|
15
|
-
*/
|
|
16
1
|
export interface AgentIdentity {
|
|
17
2
|
handle: string;
|
|
18
3
|
name?: string;
|
|
@@ -21,12 +6,6 @@ export interface OwnerIdentity {
|
|
|
21
6
|
handle: string;
|
|
22
7
|
displayName?: string;
|
|
23
8
|
}
|
|
24
|
-
/**
|
|
25
|
-
* Store agent and owner identity from an enriched REGISTER_ACK.
|
|
26
|
-
*
|
|
27
|
-
* Either parameter may be undefined (old Connector, or agent without
|
|
28
|
-
* a bound owner). Undefined values leave the corresponding state as null.
|
|
29
|
-
*/
|
|
30
9
|
export declare function setEnvironmentContext(agent?: {
|
|
31
10
|
handle: string;
|
|
32
11
|
name?: string;
|
|
@@ -36,10 +15,7 @@ export declare function setEnvironmentContext(agent?: {
|
|
|
36
15
|
}): void;
|
|
37
16
|
export declare function getAgentIdentity(): AgentIdentity | null;
|
|
38
17
|
export declare function getOwnerIdentity(): OwnerIdentity | null;
|
|
39
|
-
/** Convenience: get the owner's handle (used by auto-link in channel.ts). */
|
|
40
18
|
export declare function getOwnerHandle(): string | null;
|
|
41
|
-
/** Clear all environment context (connection lost — identity invalid). */
|
|
42
19
|
export declare function clearEnvironmentContext(): void;
|
|
43
|
-
/** @internal Reset module state for test isolation. */
|
|
44
20
|
export declare function _resetForTesting(): void;
|
|
45
21
|
//# sourceMappingURL=environment-context.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment-context.d.ts","sourceRoot":"","sources":["../src/environment-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"environment-context.d.ts","sourceRoot":"","sources":["../src/environment-context.ts"],"names":[],"mappings":"AAoBA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmBD,wBAAgB,qBAAqB,CACnC,KAAK,CAAC,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,EACzC,KAAK,CAAC,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,IAAI,CAkBN;AAMD,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAEvD;AAED,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,IAAI,CAEvD;AAGD,wBAAgB,cAAc,IAAI,MAAM,GAAG,IAAI,CAE9C;AAOD,wBAAgB,uBAAuB,IAAI,IAAI,CAG9C;AAOD,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
|
|
@@ -1,36 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent Environment Context — self-identity and owner identity.
|
|
3
|
-
*
|
|
4
|
-
* Populated from REGISTER_ACK when the Connector includes agent/owner fields
|
|
5
|
-
* (#969). Connection-scoped: cleared on disconnect, refreshed on reconnect.
|
|
6
|
-
*
|
|
7
|
-
* Module-level singleton — shared between connector-client.ts (write) and
|
|
8
|
-
* plugin.ts (read). Follows the same pattern as owner-session-state.ts.
|
|
9
|
-
*
|
|
10
|
-
* **Trust model**: Identity is Connector-asserted, not cryptographically
|
|
11
|
-
* verified. The Plugin trusts the Connector because they communicate over an
|
|
12
|
-
* authenticated WebSocket channel. A self-hosted Connector could assert
|
|
13
|
-
* arbitrary identity — this is the same trust level as the `from` field on
|
|
14
|
-
* MESSAGE_RECEIVED. Do not build security-critical logic on these values.
|
|
15
|
-
*/
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
// State
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
1
|
let agentIdentity = null;
|
|
20
2
|
let ownerIdentity = null;
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Write API (called from connector-client.ts on REGISTER_ACK)
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
/**
|
|
25
|
-
* Store agent and owner identity from an enriched REGISTER_ACK.
|
|
26
|
-
*
|
|
27
|
-
* Either parameter may be undefined (old Connector, or agent without
|
|
28
|
-
* a bound owner). Undefined values leave the corresponding state as null.
|
|
29
|
-
*/
|
|
30
3
|
export function setEnvironmentContext(agent, owner) {
|
|
31
|
-
// Defensive: validate handle is a string even though types say so.
|
|
32
|
-
// A malformed REGISTER_ACK from an untrusted Connector could send
|
|
33
|
-
// non-string values; guard prevents storing garbage in module state.
|
|
34
4
|
if (agent && typeof agent.handle === "string") {
|
|
35
5
|
const identity = { handle: agent.handle };
|
|
36
6
|
if (agent.name)
|
|
@@ -50,31 +20,19 @@ export function setEnvironmentContext(agent, owner) {
|
|
|
50
20
|
ownerIdentity = null;
|
|
51
21
|
}
|
|
52
22
|
}
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
|
-
// Read API (called from plugin.ts in before_prompt_build)
|
|
55
|
-
// ---------------------------------------------------------------------------
|
|
56
23
|
export function getAgentIdentity() {
|
|
57
24
|
return agentIdentity;
|
|
58
25
|
}
|
|
59
26
|
export function getOwnerIdentity() {
|
|
60
27
|
return ownerIdentity;
|
|
61
28
|
}
|
|
62
|
-
/** Convenience: get the owner's handle (used by auto-link in channel.ts). */
|
|
63
29
|
export function getOwnerHandle() {
|
|
64
30
|
return ownerIdentity?.handle ?? null;
|
|
65
31
|
}
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
// Lifecycle
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
|
-
/** Clear all environment context (connection lost — identity invalid). */
|
|
70
32
|
export function clearEnvironmentContext() {
|
|
71
33
|
agentIdentity = null;
|
|
72
34
|
ownerIdentity = null;
|
|
73
35
|
}
|
|
74
|
-
// ---------------------------------------------------------------------------
|
|
75
|
-
// Test-only reset
|
|
76
|
-
// ---------------------------------------------------------------------------
|
|
77
|
-
/** @internal Reset module state for test isolation. */
|
|
78
36
|
export function _resetForTesting() {
|
|
79
37
|
agentIdentity = null;
|
|
80
38
|
ownerIdentity = null;
|
package/dist/handle-utils.d.ts
CHANGED
|
@@ -1,16 +1,2 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared handle extraction utility.
|
|
3
|
-
*
|
|
4
|
-
* Used by ConversationManager (contact resolution) and Channel (sender name derivation).
|
|
5
|
-
* Single source of truth for address → display handle mapping.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Extract a display-friendly handle from any address scheme.
|
|
9
|
-
*
|
|
10
|
-
* - `mstps://preview.masons.ai/alice` → `alice`
|
|
11
|
-
* - `passport:@luomingke` → `luomingke`
|
|
12
|
-
* - `passport:user_abc` → `user_abc`
|
|
13
|
-
* - `mason` → `mason` (bare handle passthrough)
|
|
14
|
-
*/
|
|
15
1
|
export declare function extractHandleFromAddress(address: string): string;
|
|
16
2
|
//# sourceMappingURL=handle-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handle-utils.d.ts","sourceRoot":"","sources":["../src/handle-utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"handle-utils.d.ts","sourceRoot":"","sources":["../src/handle-utils.ts"],"names":[],"mappings":"AAeA,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUhE"}
|
package/dist/handle-utils.js
CHANGED
|
@@ -1,17 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared handle extraction utility.
|
|
3
|
-
*
|
|
4
|
-
* Used by ConversationManager (contact resolution) and Channel (sender name derivation).
|
|
5
|
-
* Single source of truth for address → display handle mapping.
|
|
6
|
-
*/
|
|
7
|
-
/**
|
|
8
|
-
* Extract a display-friendly handle from any address scheme.
|
|
9
|
-
*
|
|
10
|
-
* - `mstps://preview.masons.ai/alice` → `alice`
|
|
11
|
-
* - `passport:@luomingke` → `luomingke`
|
|
12
|
-
* - `passport:user_abc` → `user_abc`
|
|
13
|
-
* - `mason` → `mason` (bare handle passthrough)
|
|
14
|
-
*/
|
|
15
1
|
export function extractHandleFromAddress(address) {
|
|
16
2
|
if (address.startsWith("passport:@")) {
|
|
17
3
|
return address.slice("passport:@".length);
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
// Main entry point for @masons/agent-network.
|
|
2
|
-
//
|
|
3
|
-
// This file MUST NOT import modules that depend on Node.js-only packages (ws,
|
|
4
|
-
// etc.) because some consumers import from here in Next.js builds that include
|
|
5
|
-
// client bundles.
|
|
6
|
-
//
|
|
7
|
-
// The OpenClaw Plugin entry is in ./plugin.ts (loaded via openclaw.extensions).
|
|
8
|
-
// The ConnectorClient and protocol types are available via dedicated sub-exports.
|
|
9
|
-
// --- Shared constants ---
|
|
10
1
|
export { AUTHORIZED_TOKEN_TTL_MS, SETUP_CODE_CHARSET, SETUP_CODE_LENGTH, SETUP_CODE_TTL_MS, } from "./constants.js";
|
package/dist/owner-notes.d.ts
CHANGED
|
@@ -1,48 +1,15 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owner Notes Queue — in-memory queue for Principal notifications.
|
|
3
|
-
*
|
|
4
|
-
* When the LLM receives information from a remote agent that the owner
|
|
5
|
-
* should know about, it calls `masons_note_for_owner` which enqueues
|
|
6
|
-
* a note here. The `before_prompt_build` hook drains the queue on the
|
|
7
|
-
* owner's next turn and injects the notes into prependContext.
|
|
8
|
-
*
|
|
9
|
-
* Module-level singleton — shared between plugin.ts (drain) and tools.ts (enqueue).
|
|
10
|
-
* Same pattern as Mkclaw's PendingEventsQueue (see ref_mkclaw_cross_session.md).
|
|
11
|
-
*
|
|
12
|
-
* Lifecycle: in-memory only. Lost on Gateway restart. Layer 2 (MASONS backend)
|
|
13
|
-
* will add persistence — this queue is the Layer 1 implementation.
|
|
14
|
-
*
|
|
15
|
-
* @see docs/openclaw/interop-routing-system-design.md §7.1
|
|
16
|
-
*/
|
|
17
1
|
export interface OwnerNote {
|
|
18
|
-
/** The note content — summarized by the LLM. */
|
|
19
2
|
content: string;
|
|
20
|
-
/** When the note was created (Date.now()). */
|
|
21
3
|
timestamp: number;
|
|
22
|
-
/** Handle of the remote agent this note is about (e.g. "nikoko"). */
|
|
23
4
|
from?: string;
|
|
24
5
|
}
|
|
25
6
|
export declare class OwnerNotesQueue {
|
|
26
7
|
private notes;
|
|
27
8
|
static readonly MAX_SIZE = 50;
|
|
28
9
|
static readonly TTL_MS: number;
|
|
29
|
-
/**
|
|
30
|
-
* Enqueue a note. FIFO: if at MAX_SIZE after TTL eviction, drops oldest.
|
|
31
|
-
* Always accepts the new note.
|
|
32
|
-
*/
|
|
33
10
|
enqueue(note: OwnerNote): void;
|
|
34
|
-
/**
|
|
35
|
-
* Drain all non-stale notes. Destructive — drained notes are removed.
|
|
36
|
-
* Returns notes in chronological order (oldest first).
|
|
37
|
-
*/
|
|
38
11
|
drain(): OwnerNote[];
|
|
39
|
-
/**
|
|
40
|
-
* Current queue size (after TTL eviction).
|
|
41
|
-
*/
|
|
42
12
|
size(): number;
|
|
43
|
-
/**
|
|
44
|
-
* Clear all notes. For testing only.
|
|
45
|
-
*/
|
|
46
13
|
clear(): void;
|
|
47
14
|
private evictStale;
|
|
48
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"owner-notes.d.ts","sourceRoot":"","sources":["../src/owner-notes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"owner-notes.d.ts","sourceRoot":"","sources":["../src/owner-notes.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,SAAS;IAExB,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,EAAE,MAAM,CAAC;IAElB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,qBAAa,eAAe;IAC1B,OAAO,CAAC,KAAK,CAAmB;IAEhC,MAAM,CAAC,QAAQ,CAAC,QAAQ,MAAM;IAC9B,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAuB;IAM7C,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAY9B,KAAK,IAAI,SAAS,EAAE;IAUpB,IAAI,IAAI,MAAM;IAQd,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,UAAU;CAInB;AAMD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
package/dist/owner-notes.js
CHANGED
|
@@ -1,69 +1,30 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owner Notes Queue — in-memory queue for Principal notifications.
|
|
3
|
-
*
|
|
4
|
-
* When the LLM receives information from a remote agent that the owner
|
|
5
|
-
* should know about, it calls `masons_note_for_owner` which enqueues
|
|
6
|
-
* a note here. The `before_prompt_build` hook drains the queue on the
|
|
7
|
-
* owner's next turn and injects the notes into prependContext.
|
|
8
|
-
*
|
|
9
|
-
* Module-level singleton — shared between plugin.ts (drain) and tools.ts (enqueue).
|
|
10
|
-
* Same pattern as Mkclaw's PendingEventsQueue (see ref_mkclaw_cross_session.md).
|
|
11
|
-
*
|
|
12
|
-
* Lifecycle: in-memory only. Lost on Gateway restart. Layer 2 (MASONS backend)
|
|
13
|
-
* will add persistence — this queue is the Layer 1 implementation.
|
|
14
|
-
*
|
|
15
|
-
* @see docs/openclaw/interop-routing-system-design.md §7.1
|
|
16
|
-
*/
|
|
17
|
-
// ---------------------------------------------------------------------------
|
|
18
|
-
// Queue
|
|
19
|
-
// ---------------------------------------------------------------------------
|
|
20
1
|
export class OwnerNotesQueue {
|
|
21
2
|
notes = [];
|
|
22
3
|
static MAX_SIZE = 50;
|
|
23
|
-
static TTL_MS = 24 * 60 * 60 * 1000;
|
|
24
|
-
/**
|
|
25
|
-
* Enqueue a note. FIFO: if at MAX_SIZE after TTL eviction, drops oldest.
|
|
26
|
-
* Always accepts the new note.
|
|
27
|
-
*/
|
|
4
|
+
static TTL_MS = 24 * 60 * 60 * 1000;
|
|
28
5
|
enqueue(note) {
|
|
29
6
|
this.evictStale();
|
|
30
7
|
if (this.notes.length >= OwnerNotesQueue.MAX_SIZE) {
|
|
31
|
-
this.notes.shift();
|
|
8
|
+
this.notes.shift();
|
|
32
9
|
}
|
|
33
10
|
this.notes.push(note);
|
|
34
11
|
}
|
|
35
|
-
/**
|
|
36
|
-
* Drain all non-stale notes. Destructive — drained notes are removed.
|
|
37
|
-
* Returns notes in chronological order (oldest first).
|
|
38
|
-
*/
|
|
39
12
|
drain() {
|
|
40
13
|
this.evictStale();
|
|
41
14
|
const drained = [...this.notes];
|
|
42
15
|
this.notes = [];
|
|
43
16
|
return drained;
|
|
44
17
|
}
|
|
45
|
-
/**
|
|
46
|
-
* Current queue size (after TTL eviction).
|
|
47
|
-
*/
|
|
48
18
|
size() {
|
|
49
19
|
this.evictStale();
|
|
50
20
|
return this.notes.length;
|
|
51
21
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Clear all notes. For testing only.
|
|
54
|
-
*/
|
|
55
22
|
clear() {
|
|
56
23
|
this.notes = [];
|
|
57
24
|
}
|
|
58
|
-
// -------------------------------------------------------------------------
|
|
59
|
-
// Internal
|
|
60
|
-
// -------------------------------------------------------------------------
|
|
61
25
|
evictStale() {
|
|
62
26
|
const cutoff = Date.now() - OwnerNotesQueue.TTL_MS;
|
|
63
27
|
this.notes = this.notes.filter((n) => n.timestamp > cutoff);
|
|
64
28
|
}
|
|
65
29
|
}
|
|
66
|
-
// ---------------------------------------------------------------------------
|
|
67
|
-
// Singleton
|
|
68
|
-
// ---------------------------------------------------------------------------
|
|
69
30
|
export const ownerNotesQueue = new OwnerNotesQueue();
|
|
@@ -1,32 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owner Identity State — tracks which addresses belong to the agent's owner.
|
|
3
|
-
*
|
|
4
|
-
* When the Connector detects that a Passport visitor is the agent's owner
|
|
5
|
-
* (deterministic userId comparison, #836), it includes `is_owner: true` in
|
|
6
|
-
* MESSAGE_RECEIVED metadata. This module maintains the Plugin-side state:
|
|
7
|
-
*
|
|
8
|
-
* - `ownerAddresses`: Set of routable addresses where the visitor is the owner.
|
|
9
|
-
* Populated on first MESSAGE_RECEIVED with is_owner=true, cleared on disconnect.
|
|
10
|
-
*
|
|
11
|
-
* - `currentTurnIsOwner`: Per-turn flag set in the message_received handler
|
|
12
|
-
* and read in before_prompt_build. Reset after each read to avoid stale state.
|
|
13
|
-
*
|
|
14
|
-
* Module-level singleton — shared between channel.ts (write) and plugin.ts (read).
|
|
15
|
-
*/
|
|
16
|
-
/** Mark an address as belonging to the owner. */
|
|
17
1
|
export declare function markOwnerAddress(address: string): void;
|
|
18
|
-
/** Check if an address belongs to the owner. */
|
|
19
2
|
export declare function isOwnerAddress(address: string): boolean;
|
|
20
|
-
/** Clear all owner state (connection lost — all addresses invalid). */
|
|
21
3
|
export declare function clearOwnerState(): void;
|
|
22
|
-
/**
|
|
23
|
-
* Set the per-turn owner flag. Called in message_received before dispatch.
|
|
24
|
-
* The flag is consumed (read + reset) by before_prompt_build.
|
|
25
|
-
*/
|
|
26
4
|
export declare function setCurrentTurnIsOwner(value: boolean): void;
|
|
27
|
-
/**
|
|
28
|
-
* Consume the per-turn owner flag. Returns the value and resets to false.
|
|
29
|
-
* Consuming prevents stale state from leaking into subsequent turns.
|
|
30
|
-
*/
|
|
31
5
|
export declare function consumeCurrentTurnIsOwner(): boolean;
|
|
32
6
|
//# sourceMappingURL=owner-session-state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"owner-session-state.d.ts","sourceRoot":"","sources":["../src/owner-session-state.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"owner-session-state.d.ts","sourceRoot":"","sources":["../src/owner-session-state.ts"],"names":[],"mappings":"AA+BA,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEtD;AAGD,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAGD,wBAAgB,eAAe,IAAI,IAAI,CAGtC;AAMD,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE1D;AAUD,wBAAgB,yBAAyB,IAAI,OAAO,CAInD"}
|
|
@@ -1,55 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Owner Identity State — tracks which addresses belong to the agent's owner.
|
|
3
|
-
*
|
|
4
|
-
* When the Connector detects that a Passport visitor is the agent's owner
|
|
5
|
-
* (deterministic userId comparison, #836), it includes `is_owner: true` in
|
|
6
|
-
* MESSAGE_RECEIVED metadata. This module maintains the Plugin-side state:
|
|
7
|
-
*
|
|
8
|
-
* - `ownerAddresses`: Set of routable addresses where the visitor is the owner.
|
|
9
|
-
* Populated on first MESSAGE_RECEIVED with is_owner=true, cleared on disconnect.
|
|
10
|
-
*
|
|
11
|
-
* - `currentTurnIsOwner`: Per-turn flag set in the message_received handler
|
|
12
|
-
* and read in before_prompt_build. Reset after each read to avoid stale state.
|
|
13
|
-
*
|
|
14
|
-
* Module-level singleton — shared between channel.ts (write) and plugin.ts (read).
|
|
15
|
-
*/
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
// State
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
/** Routable addresses where the visitor has been identified as the owner. */
|
|
20
1
|
const ownerAddresses = new Set();
|
|
21
|
-
/** Whether the current LLM turn was triggered by an owner. */
|
|
22
2
|
let currentTurnIsOwner = false;
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
// Write API (called from channel.ts)
|
|
25
|
-
// ---------------------------------------------------------------------------
|
|
26
|
-
/** Mark an address as belonging to the owner. */
|
|
27
3
|
export function markOwnerAddress(address) {
|
|
28
4
|
ownerAddresses.add(address);
|
|
29
5
|
}
|
|
30
|
-
/** Check if an address belongs to the owner. */
|
|
31
6
|
export function isOwnerAddress(address) {
|
|
32
7
|
return ownerAddresses.has(address);
|
|
33
8
|
}
|
|
34
|
-
/** Clear all owner state (connection lost — all addresses invalid). */
|
|
35
9
|
export function clearOwnerState() {
|
|
36
10
|
ownerAddresses.clear();
|
|
37
11
|
currentTurnIsOwner = false;
|
|
38
12
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Set the per-turn owner flag. Called in message_received before dispatch.
|
|
41
|
-
* The flag is consumed (read + reset) by before_prompt_build.
|
|
42
|
-
*/
|
|
43
13
|
export function setCurrentTurnIsOwner(value) {
|
|
44
14
|
currentTurnIsOwner = value;
|
|
45
15
|
}
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
// Read API (called from plugin.ts)
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
/**
|
|
50
|
-
* Consume the per-turn owner flag. Returns the value and resets to false.
|
|
51
|
-
* Consuming prevents stale state from leaking into subsequent turns.
|
|
52
|
-
*/
|
|
53
16
|
export function consumeCurrentTurnIsOwner() {
|
|
54
17
|
const value = currentTurnIsOwner;
|
|
55
18
|
currentTurnIsOwner = false;
|