@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.
Files changed (66) hide show
  1. package/dist/channel.d.ts +0 -7
  2. package/dist/channel.d.ts.map +1 -1
  3. package/dist/channel.js +3 -174
  4. package/dist/cli-setup.d.ts +0 -109
  5. package/dist/cli-setup.d.ts.map +1 -1
  6. package/dist/cli-setup.js +16 -570
  7. package/dist/config-fs.d.ts +4 -0
  8. package/dist/config-fs.d.ts.map +1 -0
  9. package/dist/config-fs.js +23 -0
  10. package/dist/config-schema.js +2 -2
  11. package/dist/config.d.ts +2 -210
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +14 -334
  14. package/dist/connector-client.d.ts +0 -32
  15. package/dist/connector-client.d.ts.map +1 -1
  16. package/dist/connector-client.js +1 -89
  17. package/dist/constants.d.ts +0 -1
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/constants.js +2 -3
  20. package/dist/conversation-manager.d.ts +0 -106
  21. package/dist/conversation-manager.d.ts.map +1 -1
  22. package/dist/conversation-manager.js +2 -131
  23. package/dist/environment-context.d.ts +0 -24
  24. package/dist/environment-context.d.ts.map +1 -1
  25. package/dist/environment-context.js +0 -42
  26. package/dist/handle-utils.d.ts +0 -14
  27. package/dist/handle-utils.d.ts.map +1 -1
  28. package/dist/handle-utils.js +0 -14
  29. package/dist/index.js +0 -9
  30. package/dist/owner-notes.d.ts +0 -33
  31. package/dist/owner-notes.d.ts.map +1 -1
  32. package/dist/owner-notes.js +2 -41
  33. package/dist/owner-session-state.d.ts +0 -26
  34. package/dist/owner-session-state.d.ts.map +1 -1
  35. package/dist/owner-session-state.js +0 -37
  36. package/dist/platform-client.d.ts +13 -202
  37. package/dist/platform-client.d.ts.map +1 -1
  38. package/dist/platform-client.js +22 -171
  39. package/dist/plugin.d.ts +5 -0
  40. package/dist/plugin.d.ts.map +1 -1
  41. package/dist/plugin.js +3 -167
  42. package/dist/sent-message-buffer.d.ts +0 -36
  43. package/dist/sent-message-buffer.d.ts.map +1 -1
  44. package/dist/sent-message-buffer.js +1 -45
  45. package/dist/tools.d.ts +0 -28
  46. package/dist/tools.d.ts.map +1 -1
  47. package/dist/tools.js +36 -240
  48. package/dist/turn-context.d.ts +0 -45
  49. package/dist/turn-context.d.ts.map +1 -1
  50. package/dist/turn-context.js +0 -57
  51. package/dist/types.d.ts +0 -67
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js +0 -7
  54. package/dist/update-cache.d.ts +0 -17
  55. package/dist/update-cache.d.ts.map +1 -1
  56. package/dist/update-cache.js +1 -21
  57. package/dist/update-check.d.ts +1 -40
  58. package/dist/update-check.d.ts.map +1 -1
  59. package/dist/update-check.js +7 -66
  60. package/dist/version.d.ts +1 -2
  61. package/dist/version.d.ts.map +1 -1
  62. package/dist/version.js +1 -2
  63. package/openclaw.plugin.json +94 -3
  64. package/package.json +11 -10
  65. package/skills/agent-network/SKILL.md +21 -47
  66. package/skills/agent-network/references/troubleshooting.md +5 -5
@@ -7,23 +7,12 @@ import { CURRENT_PROTOCOL_VERSION, isAddressedMessage, isDeliveryPending, isDeli
7
7
  import { PLUGIN_VERSION } from "./version.js";
8
8
  const dbg = createDebug("agent-network:connector");
9
9
  const dbgMsg = createDebug("agent-network:connector:msg");
10
- // --- Reconnection constants ---
11
10
  const BACKOFF_INITIAL_MS = 1_000;
12
11
  const BACKOFF_MAX_MS = 30_000;
13
12
  const ALREADY_CONNECTED_RETRY_MS = 2_000;
14
13
  const ALREADY_CONNECTED_MAX_RETRIES = 30;
15
- // --- Single-driver Node semantic (#1264) ---
16
- // The connector closes with WS code 4001 + this reason when a new Runtime
17
- // REGISTERs for the same agentId. The current api_key may have been rotated
18
- // by /runtime/v1/onboard select mode, so reconnecting with the cached token
19
- // is futile (would 401 forever).
20
14
  const REPLACED_BY_NEW_RUNTIME_REASON = "Replaced by new Runtime";
21
15
  const REPLACED_BY_NEW_RUNTIME_CODE = 4001;
22
- // --- Error class for structured errors ---
23
- /**
24
- * Error with machine-readable `code` from Connector structured errors.
25
- * Thrown by `send()` when the Connector responds with ERROR { code }.
26
- */
27
16
  export class ConnectorError extends Error {
28
17
  code;
29
18
  to;
@@ -34,7 +23,6 @@ export class ConnectorError extends Error {
34
23
  this.to = to;
35
24
  }
36
25
  }
37
- // --- ConnectorClient ---
38
26
  export class ConnectorClient extends EventEmitter {
39
27
  url;
40
28
  token;
@@ -46,19 +34,13 @@ export class ConnectorClient extends EventEmitter {
46
34
  registerResolve = null;
47
35
  registerReject = null;
48
36
  registerTimer = null;
49
- /** Delivery cursor — highest recipientSeq received from Connector (#1133).
50
- * Sent on REGISTER so the Connector can fill any gap. In-memory only —
51
- * survives Connector restarts (Plugin stays alive), lost on Plugin restart
52
- * (graceful degradation: no gap fill, same as pre-#1133 behavior). */
53
37
  lastKnownSeq;
54
- /** Pending SEND_ACK correlation map for address-based sends. */
55
38
  pendingSends = new Map();
56
39
  constructor(url, token) {
57
40
  super();
58
41
  this.url = url;
59
42
  this.token = token;
60
43
  }
61
- // --- Public API ---
62
44
  connect() {
63
45
  if (this.ws) {
64
46
  return Promise.reject(new Error("Already connecting or connected"));
@@ -79,14 +61,6 @@ export class ConnectorClient extends EventEmitter {
79
61
  wsToClose.close(1000, "Client disconnect");
80
62
  }
81
63
  }
82
- // --- Messaging ---
83
- /**
84
- * Send a message to a routable address. Returns a Promise that resolves
85
- * with the SEND_ACK from the Connector, or rejects with a ConnectorError
86
- * (structured error code) or a plain Error (timeout / disconnect).
87
- *
88
- * The messageId is generated internally and used for ACK correlation.
89
- */
90
64
  send(to, content, contentType = "text", metadata) {
91
65
  const messageId = randomUUID();
92
66
  const event = {
@@ -111,18 +85,12 @@ export class ConnectorClient extends EventEmitter {
111
85
  }
112
86
  });
113
87
  }
114
- /**
115
- * Send a typing indicator to a routable address.
116
- */
117
88
  sendTyping(to, isTyping) {
118
89
  const event = { event: "TYPING", to, isTyping };
119
90
  const sent = this.sendEvent(event);
120
91
  dbg("sendTyping to=%s isTyping=%s sent=%s", to, isTyping, sent);
121
92
  return sent;
122
93
  }
123
- /**
124
- * Acknowledge delivery of stored messages up to a timestamp.
125
- */
126
94
  ackDelivery(upTo) {
127
95
  const event = { event: "DELIVERY_ACK", upTo };
128
96
  const sent = this.sendEvent(event);
@@ -141,7 +109,6 @@ export class ConnectorClient extends EventEmitter {
141
109
  emit(event, ...args) {
142
110
  return super.emit(event, ...args);
143
111
  }
144
- // --- Connection lifecycle ---
145
112
  doConnect() {
146
113
  return new Promise((resolve, reject) => {
147
114
  this.registerResolve = resolve;
@@ -153,8 +120,6 @@ export class ConnectorClient extends EventEmitter {
153
120
  this.startRegisterTimeout();
154
121
  });
155
122
  ws.on("message", this.handleMessage);
156
- // ws's "close" event passes (code, reason) — handleClose accepts both.
157
- // Pass the bound arrow reference so cleanupConnection can `off()` it.
158
123
  ws.on("close", this.handleClose);
159
124
  ws.on("error", this.handleError);
160
125
  });
@@ -200,7 +165,6 @@ export class ConnectorClient extends EventEmitter {
200
165
  this.registerReject = null;
201
166
  }
202
167
  }
203
- // --- Message handling ---
204
168
  handleMessage = (data) => {
205
169
  let parsed;
206
170
  try {
@@ -210,14 +174,12 @@ export class ConnectorClient extends EventEmitter {
210
174
  this.emit("error", new Error("Received non-JSON message from Connector"));
211
175
  return;
212
176
  }
213
- // REGISTER_ACK is version-agnostic — always handled first
214
177
  if (isRegisterAck(parsed)) {
215
178
  this.handleRegisterAck(parsed);
216
179
  return;
217
180
  }
218
181
  this.dispatchAddressed(parsed);
219
182
  };
220
- /** Dispatch inbound address-based events. */
221
183
  dispatchAddressed(parsed) {
222
184
  if (isSendAck(parsed)) {
223
185
  dbg("SEND_ACK messageId=%s status=%s", parsed.messageId, parsed.status);
@@ -226,7 +188,6 @@ export class ConnectorClient extends EventEmitter {
226
188
  }
227
189
  if (isAddressedMessage(parsed)) {
228
190
  dbgMsg("MESSAGE_RECEIVED from=%s contentLength=%d seq=%s", parsed.from, parsed.content.length, parsed.seq ?? "none");
229
- // Advance delivery cursor (#1133)
230
191
  if (typeof parsed.seq === "number" &&
231
192
  (this.lastKnownSeq === undefined || parsed.seq > this.lastKnownSeq)) {
232
193
  this.lastKnownSeq = parsed.seq;
@@ -249,23 +210,14 @@ export class ConnectorClient extends EventEmitter {
249
210
  this.handleStructuredError(parsed);
250
211
  return;
251
212
  }
252
- // Unknown event type — silently ignore (forward compatibility)
253
213
  }
254
214
  handleRegisterAck(ack) {
255
215
  dbg("REGISTER_ACK status=%s protocolVersion=%d", ack.status, ack.protocolVersion);
256
216
  if (ack.status === "ok") {
257
- // Defensive: verify the negotiated version matches what we requested.
258
- // Current Connector rejects unsupported versions outright (no downgrade),
259
- // so this check is future-proofing against silent protocol desync.
260
217
  if (ack.protocolVersion !== CURRENT_PROTOCOL_VERSION) {
261
218
  dbg("WARN: server negotiated protocolVersion=%d, expected=%d", ack.protocolVersion, CURRENT_PROTOCOL_VERSION);
262
219
  }
263
- // Store agent + owner identity from enriched REGISTER_ACK (#969).
264
- // Old Connectors omit these fields — setEnvironmentContext handles undefined.
265
220
  setEnvironmentContext(ack.agent, ack.owner);
266
- // Initialize delivery cursor from server (#1133).
267
- // Only set on first connect (lastKnownSeq === undefined). On reconnect,
268
- // the Plugin already has a cursor from previous MESSAGE_RECEIVED events.
269
221
  if (typeof ack.deliverySeq === "number" &&
270
222
  this.lastKnownSeq === undefined) {
271
223
  this.lastKnownSeq = ack.deliverySeq;
@@ -278,7 +230,6 @@ export class ConnectorClient extends EventEmitter {
278
230
  }
279
231
  else {
280
232
  const reason = ack.reason ?? "Unknown registration error";
281
- // "Unsupported protocol version" — do not reconnect
282
233
  if (reason === "Unsupported protocol version") {
283
234
  this.intentionalClose = true;
284
235
  this.rejectRegister(new Error(reason));
@@ -286,13 +237,6 @@ export class ConnectorClient extends EventEmitter {
286
237
  this.ws?.close(4001, reason);
287
238
  return;
288
239
  }
289
- // "Already connected" — track retries for short backoff.
290
- // As of connector #1264 the server flips this to single-driver
291
- // eviction (close code 4001 + reason "Replaced by new Runtime",
292
- // handled in handleClose). The REGISTER_ACK error path with this
293
- // reason is now only reachable against pre-#1264 connector
294
- // deployments during a rollout window — kept for that compat,
295
- // safe to remove in 0.7.0 once preview/production are upgraded.
296
240
  if (reason === "Already connected") {
297
241
  this.alreadyConnectedRetries++;
298
242
  }
@@ -300,11 +244,6 @@ export class ConnectorClient extends EventEmitter {
300
244
  this.ws?.close(4001, reason);
301
245
  }
302
246
  }
303
- // --- Address-based handlers ---
304
- /**
305
- * Resolve the pending send promise matching this SEND_ACK.
306
- * Also emits `send_ack` for listeners that want to observe all ACKs.
307
- */
308
247
  handleSendAck(ack) {
309
248
  this.emit("send_ack", ack);
310
249
  const pending = this.pendingSends.get(ack.messageId);
@@ -314,13 +253,8 @@ export class ConnectorClient extends EventEmitter {
314
253
  pending.resolve(ack);
315
254
  }
316
255
  }
317
- /**
318
- * Structured ERROR: message-scoped errors reject pending sends,
319
- * connection-scoped errors emit generic event.
320
- */
321
256
  handleStructuredError(event) {
322
257
  this.emit("structured_error", event);
323
- // Message-scoped: reject the pending send for this messageId
324
258
  if (event.messageId) {
325
259
  const pending = this.pendingSends.get(event.messageId);
326
260
  if (pending) {
@@ -330,10 +264,8 @@ export class ConnectorClient extends EventEmitter {
330
264
  return;
331
265
  }
332
266
  }
333
- // Connection-scoped: emit generic error
334
267
  this.emit("error", new Error(`[${event.code}] ${event.message}`));
335
268
  }
336
- // --- Connection close ---
337
269
  handleClose = (code, reason) => {
338
270
  const reasonStr = reason
339
271
  ? typeof reason === "string"
@@ -343,18 +275,12 @@ export class ConnectorClient extends EventEmitter {
343
275
  dbg("connection closed code=%s reason=%s intentional=%s", code ?? "?", reasonStr, this.intentionalClose);
344
276
  const wasRegistering = this.registerReject !== null;
345
277
  this.cleanupConnection();
346
- // Single-driver eviction (#1264) — connector closes us with code 4001
347
- // and reason "Replaced by new Runtime" when a new REGISTER claims our
348
- // agentId. The api_key we hold may have been rotated by the new
349
- // Runtime's /runtime/v1/onboard call; reconnecting would 401 forever.
350
- // Treat as terminal: stop reconnects, surface an actionable message,
351
- // emit a distinct event so consumers (channel.ts, etc.) can react.
352
278
  const replacedByNewRuntime = code === REPLACED_BY_NEW_RUNTIME_CODE &&
353
279
  reasonStr === REPLACED_BY_NEW_RUNTIME_REASON;
354
280
  if (replacedByNewRuntime) {
355
281
  this.intentionalClose = true;
356
282
  const msg = "This agent was claimed by another Runtime " +
357
- "(api_key rotated, this Runtime disconnected). " +
283
+ "(this Runtime disconnected). " +
358
284
  "Re-run `openclaw channels login --channel agent-network` " +
359
285
  "to drive this agent from here again.";
360
286
  this.emit("error", new Error(msg));
@@ -365,15 +291,10 @@ export class ConnectorClient extends EventEmitter {
365
291
  return;
366
292
  }
367
293
  if (wasRegistering) {
368
- // Connection closed during REGISTER — check for special retry logic
369
- // (handled by rejectRegister which was already called if ACK error came first)
370
294
  if (this.registerReject) {
371
295
  this.rejectRegister(new Error("Connection closed during registration"));
372
296
  }
373
297
  }
374
- // "disconnected" is emitted on every close, including intermediate closes
375
- // during reconnect cycles. This is intentional — channel adapter uses this
376
- // to clear stale session state before a fresh REGISTER re-creates sessions.
377
298
  this.emit("disconnected");
378
299
  if (!this.intentionalClose) {
379
300
  this.scheduleReconnect();
@@ -381,10 +302,8 @@ export class ConnectorClient extends EventEmitter {
381
302
  };
382
303
  handleError = (err) => {
383
304
  dbg("websocket error: %s", err.message);
384
- // WebSocket errors are followed by a close event, so just emit
385
305
  this.emit("error", err);
386
306
  };
387
- // --- Reconnection ---
388
307
  scheduleReconnect() {
389
308
  this.clearReconnectTimer();
390
309
  const delay = this.calculateBackoff();
@@ -392,15 +311,12 @@ export class ConnectorClient extends EventEmitter {
392
311
  this.reconnectTimer = setTimeout(() => {
393
312
  this.reconnectTimer = null;
394
313
  this.doConnect().catch(() => {
395
- // connect rejection is expected during reconnect — handled by close event
396
314
  });
397
315
  }, delay);
398
316
  }
399
317
  calculateBackoff() {
400
- // "Already connected" — short fixed retry with limit
401
318
  if (this.alreadyConnectedRetries > 0) {
402
319
  if (this.alreadyConnectedRetries >= ALREADY_CONNECTED_MAX_RETRIES) {
403
- // Exceeded max retries, fall back to normal exponential backoff
404
320
  this.alreadyConnectedRetries = 0;
405
321
  return this.nextExponentialBackoff();
406
322
  }
@@ -420,7 +336,6 @@ export class ConnectorClient extends EventEmitter {
420
336
  this.reconnectTimer = null;
421
337
  }
422
338
  }
423
- // --- Cleanup ---
424
339
  cleanupConnection() {
425
340
  if (this.ws) {
426
341
  this.ws.off("message", this.handleMessage);
@@ -432,15 +347,12 @@ export class ConnectorClient extends EventEmitter {
432
347
  clearTimeout(this.registerTimer);
433
348
  this.registerTimer = null;
434
349
  }
435
- // Reject all pending address-based sends on disconnect
436
350
  for (const [, pending] of this.pendingSends) {
437
351
  clearTimeout(pending.timer);
438
352
  pending.reject(new Error("Connection closed"));
439
353
  }
440
354
  this.pendingSends.clear();
441
355
  }
442
- // --- Wire helpers ---
443
- /** Send an event over the WebSocket. */
444
356
  sendEvent(event) {
445
357
  if (this.ws?.readyState === WebSocket.OPEN) {
446
358
  this.ws.send(JSON.stringify(event));
@@ -1,4 +1,3 @@
1
- /** Unambiguous characters: A-H J-N P-Z 2-9 (excludes I/O/1/0) */
2
1
  export declare const SETUP_CODE_CHARSET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
3
2
  export declare const SETUP_CODE_LENGTH = 8;
4
3
  export declare const SETUP_CODE_TTL_MS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AACrE,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAChD,eAAO,MAAM,uBAAuB,QAAiB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,qCAAqC,CAAC;AACrE,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,iBAAiB,QAAiB,CAAC;AAChD,eAAO,MAAM,uBAAuB,QAAiB,CAAC"}
package/dist/constants.js CHANGED
@@ -1,5 +1,4 @@
1
- /** Unambiguous characters: A-H J-N P-Z 2-9 (excludes I/O/1/0) */
2
1
  export const SETUP_CODE_CHARSET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
3
2
  export const SETUP_CODE_LENGTH = 8;
4
- export const SETUP_CODE_TTL_MS = 15 * 60 * 1000; // 15 minutes
5
- export const AUTHORIZED_TOKEN_TTL_MS = 60 * 60 * 1000; // 1 hour
3
+ export const SETUP_CODE_TTL_MS = 15 * 60 * 1000;
4
+ export const AUTHORIZED_TOKEN_TTL_MS = 60 * 60 * 1000;
@@ -1,21 +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 { type ConnectorClient } from "./connector-client.js";
15
2
  export interface SendResult {
16
3
  status: "sent" | "failed";
17
4
  error?: string;
18
- /** Machine-readable error code from Connector (when status === "failed"). */
19
5
  errorCode?: string;
20
6
  }
21
7
  export interface ConversationEntry {
@@ -23,19 +9,6 @@ export interface ConversationEntry {
23
9
  address: string;
24
10
  lastMessageAt: number;
25
11
  initiatedBy: "local" | "remote";
26
- /**
27
- * Deferred deletion flag (#999).
28
- *
29
- * When `masons_end_conversation` runs during a dispatch cycle, the entry
30
- * is marked `ended` but NOT removed from the Map. This keeps
31
- * `hasConversation()` returning true so the deliver callback can still
32
- * flush buffered text from the same LLM turn.
33
- *
34
- * Call `commitEndedConversations()` after the dispatch cycle completes
35
- * to actually remove ended entries.
36
- *
37
- * @see https://github.com/MASONS-ai/masons.ai/issues/999
38
- */
39
12
  ended?: boolean;
40
13
  }
41
14
  export interface ConversationSummary {
@@ -48,97 +21,18 @@ export interface ConversationSummary {
48
21
  export declare class ConversationManager {
49
22
  private readonly client;
50
23
  private readonly connectorHost;
51
- /** Conversations keyed by routable address */
52
24
  private readonly conversations;
53
25
  constructor(client: ConnectorClient, connectorHost: string);
54
- /**
55
- * Send a message to a contact. Sends directly to the resolved address —
56
- * no session management needed.
57
- *
58
- * Returns a structured result with status and optional error.
59
- * ConnectorError codes (ADDRESS_NOT_FOUND, ACCESS_DENIED, etc.) are
60
- * mapped to human-readable messages for LLM tool results.
61
- *
62
- * @param contact - Handle, MSTP address, or passport address of the target.
63
- * @param content - Message content to send.
64
- */
65
26
  send(contact: string, content: string): Promise<SendResult>;
66
- /**
67
- * Register an inbound conversation (remote agent or visitor initiated).
68
- * Called by the channel adapter when a message arrives from a new address.
69
- */
70
27
  registerInbound(contact: string, address: string): void;
71
- /**
72
- * Resolve a routable address to a contact handle.
73
- * Used by the inbound dispatcher to derive sender identity from MESSAGE_RECEIVED.from.
74
- */
75
28
  getContactByAddress(address: string): string | undefined;
76
- /**
77
- * List all conversations with metadata.
78
- * `active` is always true for address-based protocol — there is no session
79
- * lifecycle. Conversations persist until explicitly ended or Plugin restarts.
80
- */
81
29
  listConversations(): ConversationSummary[];
82
- /**
83
- * Check if a conversation entry exists for a contact.
84
- *
85
- * Returns true for entries that are marked `ended` but not yet committed —
86
- * this allows the deliver callback to flush buffered text from the same
87
- * dispatch cycle as end_conversation (#999).
88
- *
89
- * Straggler text from *subsequent* dispatch cycles is still suppressed
90
- * because `commitEndedConversations()` removes entries between cycles.
91
- */
92
30
  hasConversation(contact: string): boolean;
93
- /**
94
- * Mark the conversation with a contact as ended (deferred deletion).
95
- *
96
- * The entry is NOT removed immediately — it is flagged `ended` and stays
97
- * in the Map until `commitEndedConversations()` is called after the
98
- * current dispatch cycle completes. This prevents the "last-message-
99
- * before-close" race where the dispatcher executes end_conversation
100
- * before flushing buffered text (#999).
101
- *
102
- * No END_SESSION needed — the Connector manages connection lifecycle
103
- * (idle timeout).
104
- */
105
31
  endConversation(contact: string): void;
106
- /**
107
- * Remove all conversations marked as `ended`.
108
- *
109
- * Call this after the dispatch cycle completes (in the `finally` block
110
- * of `handleAddressedMessage`). Deferred deletion ensures that text
111
- * buffered in the same dispatch cycle as end_conversation is delivered
112
- * before the entry disappears.
113
- *
114
- * Pattern: React 18 batched updates / Qt `deleteLater()` — mutations
115
- * during a dispatch cycle are committed only when the cycle ends.
116
- *
117
- * @see https://github.com/MASONS-ai/masons.ai/issues/999
118
- */
119
32
  commitEndedConversations(): void;
120
- /**
121
- * Resolve a contact (handle, MSTP address, or passport address) to a
122
- * routable address.
123
- *
124
- * Resolution order:
125
- * 1. MSTP address (starts with mstps:// or mstp://) → return as-is.
126
- * 2. Passport address (starts with passport:) → return as-is (already routable).
127
- * 3. Already a key in the conversations map → return as-is.
128
- * 4. Reverse lookup: if any existing conversation has this handle as its
129
- * contact, use that conversation's address. This ensures replies to a
130
- * cross-Connector sender route to the sender's original address, not to
131
- * a locally-constructed address.
132
- * 5. Otherwise treat as handle → construct `mstps://${connectorHost}/${handle}`.
133
- */
134
33
  resolveAddress(contact: string): string;
135
- /**
136
- * Extract a display-friendly handle from any address scheme.
137
- * Delegates to shared utility — single source of truth.
138
- */
139
34
  extractHandle(address: string): string;
140
35
  private ensureConversationEntry;
141
- /** @internal Reset for test isolation. */
142
36
  _resetForTesting(): void;
143
37
  }
144
38
  //# sourceMappingURL=conversation-manager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-manager.d.ts","sourceRoot":"","sources":["../src/conversation-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,uBAAuB,CAAC;AAS7E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;IAChC;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;CACjC;AAwBD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAEvC,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwC;gBAE1D,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM;IAS1D;;;;;;;;;;OAUG;IACG,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IA0CjE;;;OAGG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IAKvD;;;OAGG;IACH,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAaxD;;;;OAIG;IACH,iBAAiB,IAAI,mBAAmB,EAAE;IAc1C;;;;;;;;;OASG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAKzC;;;;;;;;;;;OAWG;IACH,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAWtC;;;;;;;;;;;;OAYG;IACH,wBAAwB,IAAI,IAAI;IAiBhC;;;;;;;;;;;;;OAaG;IACH,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAoBvC;;;OAGG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAQtC,OAAO,CAAC,uBAAuB;IAyB/B,0CAA0C;IAC1C,gBAAgB,IAAI,IAAI;CAGzB"}
1
+ {"version":3,"file":"conversation-manager.d.ts","sourceRoot":"","sources":["../src/conversation-manager.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,KAAK,eAAe,EAAkB,MAAM,uBAAuB,CAAC;AAS7E,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;IAchC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,OAAO,GAAG,QAAQ,CAAC;CACjC;AAwBD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IAGvC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAwC;gBAE1D,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM;IAoBpD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAoCjE,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IASvD,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAkBxD,iBAAiB,IAAI,mBAAmB,EAAE;IAwB1C,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAiBzC,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAwBtC,wBAAwB,IAAI,IAAI;IA+BhC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAwBvC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAQtC,OAAO,CAAC,uBAAuB;IA0B/B,gBAAgB,IAAI,IAAI;CAGzB"}