@masons/agent-network 0.4.13 → 0.4.14

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAmHA,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CACnE;AAED,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;kBA4BI,iBAAiB;CA2RhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAoHA,UAAU,iBAAiB;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjD,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,GAAG,IAAI,CAAC;CACnE;AAED,QAAA,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;;kBA4BI,iBAAiB;CA+ShC,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/plugin.js CHANGED
@@ -6,6 +6,7 @@ import { configureInteractive } from "./cli-setup.js";
6
6
  import { detectPendingState, getConversationManager, getStateCacheGeneration, initPluginRuntime, } from "./config.js";
7
7
  import { ownerNotesQueue } from "./owner-notes.js";
8
8
  import { consumeCurrentTurnIsOwner } from "./owner-session-state.js";
9
+ import { sentMessageBuffer } from "./sent-message-buffer.js";
9
10
  import { registerTools } from "./tools.js";
10
11
  import { consumeCurrentTurnSender } from "./turn-context.js";
11
12
  import { getUpdateInfo } from "./update-check.js";
@@ -300,6 +301,24 @@ const plugin = {
300
301
  if (interactionCtx) {
301
302
  dynamicContext += `\n\n${interactionCtx}`;
302
303
  }
304
+ // Append sent message context — cross-session bridge (#918).
305
+ // When the LLM sent a message from the owner session via
306
+ // masons_send_message, inject the content here so the LLM
307
+ // knows what it previously said to this contact.
308
+ if (turnSender) {
309
+ const sentMsgs = sentMessageBuffer.getRecent(turnSender);
310
+ if (sentMsgs.length > 0) {
311
+ const lines = sentMsgs.map((m) => {
312
+ const preview = m.content.length > 100
313
+ ? `${m.content.slice(0, 100)}...`
314
+ : m.content;
315
+ return `• (${formatTimeAgo(m.timestamp)}): "${preview}"`;
316
+ });
317
+ dynamicContext +=
318
+ `\n\n[Your recent messages to @${turnSender}]\n` +
319
+ lines.join("\n");
320
+ }
321
+ }
303
322
  }
304
323
  }
305
324
  else {
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Sent Message Buffer — per-contact ring buffer of outgoing messages.
3
+ *
4
+ * When the LLM calls `masons_send_message`, the outgoing content is recorded
5
+ * here. On the next agent-network turn from that contact, `before_prompt_build`
6
+ * reads the buffer and injects the sent messages into `prependContext` so the
7
+ * LLM knows what it previously said.
8
+ *
9
+ * This is the reverse of `OwnerNotesQueue`:
10
+ * - OwnerNotesQueue: agent-network session → owner session
11
+ * - SentMessageBuffer: owner session → agent-network session
12
+ *
13
+ * Module-level singleton — shared between plugin.ts (read) and tools.ts (write).
14
+ *
15
+ * Lifecycle: in-memory only (D3). Lost on Gateway restart.
16
+ *
17
+ * @see docs/openclaw/interop-routing-system-design.md §7.1
18
+ */
19
+ export interface SentMessage {
20
+ /** The message content that was sent. */
21
+ content: string;
22
+ /** When the message was sent (Date.now()). */
23
+ timestamp: number;
24
+ }
25
+ export declare class SentMessageBuffer {
26
+ private entries;
27
+ /** Max messages retained per contact. */
28
+ static readonly MAX_PER_CONTACT = 5;
29
+ /** Messages older than this are evicted. */
30
+ static readonly TTL_MS: number;
31
+ /** Max content length stored per message. Longer content is truncated at record time. */
32
+ static readonly MAX_CONTENT_LENGTH = 500;
33
+ /**
34
+ * Record an outgoing message to a contact.
35
+ * Called by `masons_send_message` after successful send.
36
+ */
37
+ record(contact: string, content: string): void;
38
+ /**
39
+ * Get recent sent messages for a contact. Non-destructive — the same
40
+ * messages may be relevant across multiple turns with the same contact.
41
+ * Returns messages in chronological order (oldest first). Returns empty
42
+ * array if no messages exist or all are stale.
43
+ */
44
+ getRecent(contact: string): SentMessage[];
45
+ /**
46
+ * Clear all entries. For testing only.
47
+ */
48
+ clear(): void;
49
+ }
50
+ export declare const sentMessageBuffer: SentMessageBuffer;
51
+ //# sourceMappingURL=sent-message-buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sent-message-buffer.d.ts","sourceRoot":"","sources":["../src/sent-message-buffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,MAAM,WAAW,WAAW;IAC1B,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAoC;IAEnD,yCAAyC;IACzC,MAAM,CAAC,QAAQ,CAAC,eAAe,KAAK;IACpC,4CAA4C;IAC5C,MAAM,CAAC,QAAQ,CAAC,MAAM,SAAkB;IACxC,yFAAyF;IACzF,MAAM,CAAC,QAAQ,CAAC,kBAAkB,OAAO;IAEzC;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI;IA2B9C;;;;;OAKG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;IAoBzC;;OAEG;IACH,KAAK,IAAI,IAAI;CAGd;AAMD,eAAO,MAAM,iBAAiB,mBAA0B,CAAC"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Sent Message Buffer — per-contact ring buffer of outgoing messages.
3
+ *
4
+ * When the LLM calls `masons_send_message`, the outgoing content is recorded
5
+ * here. On the next agent-network turn from that contact, `before_prompt_build`
6
+ * reads the buffer and injects the sent messages into `prependContext` so the
7
+ * LLM knows what it previously said.
8
+ *
9
+ * This is the reverse of `OwnerNotesQueue`:
10
+ * - OwnerNotesQueue: agent-network session → owner session
11
+ * - SentMessageBuffer: owner session → agent-network session
12
+ *
13
+ * Module-level singleton — shared between plugin.ts (read) and tools.ts (write).
14
+ *
15
+ * Lifecycle: in-memory only (D3). Lost on Gateway restart.
16
+ *
17
+ * @see docs/openclaw/interop-routing-system-design.md §7.1
18
+ */
19
+ // ---------------------------------------------------------------------------
20
+ // Buffer
21
+ // ---------------------------------------------------------------------------
22
+ export class SentMessageBuffer {
23
+ entries = new Map();
24
+ /** Max messages retained per contact. */
25
+ static MAX_PER_CONTACT = 5;
26
+ /** Messages older than this are evicted. */
27
+ static TTL_MS = 30 * 60 * 1000; // 30 minutes
28
+ /** Max content length stored per message. Longer content is truncated at record time. */
29
+ static MAX_CONTENT_LENGTH = 500;
30
+ /**
31
+ * Record an outgoing message to a contact.
32
+ * Called by `masons_send_message` after successful send.
33
+ */
34
+ record(contact, content) {
35
+ const now = Date.now();
36
+ const key = contact.toLowerCase();
37
+ let list = this.entries.get(key);
38
+ if (!list) {
39
+ list = [];
40
+ this.entries.set(key, list);
41
+ }
42
+ // Evict stale entries
43
+ const cutoff = now - SentMessageBuffer.TTL_MS;
44
+ const fresh = list.filter((m) => m.timestamp > cutoff);
45
+ // Cap at MAX_PER_CONTACT (drop oldest)
46
+ if (fresh.length >= SentMessageBuffer.MAX_PER_CONTACT) {
47
+ fresh.shift();
48
+ }
49
+ // Truncate content to prevent unbounded memory growth
50
+ const stored = content.length > SentMessageBuffer.MAX_CONTENT_LENGTH
51
+ ? `${content.slice(0, SentMessageBuffer.MAX_CONTENT_LENGTH)}...`
52
+ : content;
53
+ fresh.push({ content: stored, timestamp: now });
54
+ this.entries.set(key, fresh);
55
+ }
56
+ /**
57
+ * Get recent sent messages for a contact. Non-destructive — the same
58
+ * messages may be relevant across multiple turns with the same contact.
59
+ * Returns messages in chronological order (oldest first). Returns empty
60
+ * array if no messages exist or all are stale.
61
+ */
62
+ getRecent(contact) {
63
+ const key = contact.toLowerCase();
64
+ const list = this.entries.get(key);
65
+ if (!list)
66
+ return [];
67
+ const cutoff = Date.now() - SentMessageBuffer.TTL_MS;
68
+ const fresh = list.filter((m) => m.timestamp > cutoff);
69
+ if (fresh.length !== list.length) {
70
+ // Evict stale in place
71
+ if (fresh.length === 0) {
72
+ this.entries.delete(key);
73
+ }
74
+ else {
75
+ this.entries.set(key, fresh);
76
+ }
77
+ }
78
+ return fresh;
79
+ }
80
+ /**
81
+ * Clear all entries. For testing only.
82
+ */
83
+ clear() {
84
+ this.entries.clear();
85
+ }
86
+ }
87
+ // ---------------------------------------------------------------------------
88
+ // Singleton
89
+ // ---------------------------------------------------------------------------
90
+ export const sentMessageBuffer = new SentMessageBuffer();
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA2CH,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,OAAO;IACf,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACzE;AA0CD,uDAAuD;AACvD,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C;AAsFD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAk2BhD"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA4CH,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,OAAO;IACf,YAAY,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CACzE;AA0CD,uDAAuD;AACvD,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C;AAsFD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAq2BhD"}
package/dist/tools.js CHANGED
@@ -22,6 +22,7 @@ import { tmpdir } from "node:os";
22
22
  import { Type } from "@sinclair/typebox";
23
23
  import { clearTargetHandle, getOpenClawHome, getPendingTarget, isProfileNeeded, markProfileComplete, markProfileNeeded, requireApiKey, requireConversationManager, requirePlatformConfig, writeCredentials, } from "./config.js";
24
24
  import { ownerNotesQueue } from "./owner-notes.js";
25
+ import { sentMessageBuffer } from "./sent-message-buffer.js";
25
26
  import { acceptRequest, declineRequest, getConnectionStatus, initSetup, listConnections, listRequests, onboard, PlatformApiError, pollSetup, reconnect, requestConnection, SetupExpiredError, SetupPendingError, updateProfile, } from "./platform-client.js";
26
27
  import { fetchLatestVersion, getPluginVersion, getUpdateInfo, } from "./update-check.js";
27
28
  // ---------------------------------------------------------------------------
@@ -605,14 +606,14 @@ export function registerTools(api) {
605
606
  const cm = requireConversationManager();
606
607
  const to = params.to;
607
608
  const content = params.content;
609
+ // Extract handle once — shared by pre-flight check and sent message buffer.
610
+ const handle = to.startsWith("mstps://") || to.startsWith("mstp://")
611
+ ? to.replace(/^mstps?:\/\/[^/]+\//, "").replace(/\/+$/, "")
612
+ : to;
608
613
  // --- Pre-flight: check connection status (advisory, not gate) ---
609
614
  // If the check fails (network error, API down), proceed anyway —
610
615
  // the Connector gate (Layer 2) is the authoritative enforcement.
611
616
  try {
612
- // Extract handle for connection check
613
- const handle = to.startsWith("mstps://") || to.startsWith("mstp://")
614
- ? to.replace(/^mstps?:\/\/[^/]+\//, "").replace(/\/+$/, "")
615
- : to;
616
617
  if (handle) {
617
618
  const cfg = requirePlatformConfig();
618
619
  const apiKey = requireApiKey();
@@ -630,6 +631,9 @@ export function registerTools(api) {
630
631
  }
631
632
  const result = await cm.send(to, content);
632
633
  if (result.status === "sent") {
634
+ // Record in sent message buffer so the agent-network session has
635
+ // context when the remote agent replies (cross-session bridge, #918).
636
+ sentMessageBuffer.record(handle, content);
633
637
  return textResult("Message sent.");
634
638
  }
635
639
  return textResult(result.error ??
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  /** Plugin version — must match package.json. Validated by prepublishOnly. */
2
- export declare const PLUGIN_VERSION = "0.4.13";
2
+ export declare const PLUGIN_VERSION = "0.4.14";
3
3
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Plugin version — must match package.json. Validated by prepublishOnly. */
2
- export const PLUGIN_VERSION = "0.4.13";
2
+ export const PLUGIN_VERSION = "0.4.14";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masons/agent-network",
3
- "version": "0.4.13",
3
+ "version": "0.4.14",
4
4
  "description": "MASONS plugin for OpenClaw — connect your agent to the agent network",
5
5
  "license": "MIT",
6
6
  "author": "MASONS.ai <hello@masons.ai> (https://masons.ai)",
@@ -19,6 +19,15 @@
19
19
  "publishConfig": {
20
20
  "access": "public"
21
21
  },
22
+ "scripts": {
23
+ "build": "tsc",
24
+ "dev": "tsc --watch",
25
+ "test": "tsc -p test/tsconfig.json && node --test --loader ts-node/esm test/**/*.test.ts",
26
+ "lint": "biome check",
27
+ "format": "biome format --write",
28
+ "prepublishOnly": "bash scripts/check-version.sh && npm run build && npm run test",
29
+ "release": "pnpm publish --access public"
30
+ },
22
31
  "files": [
23
32
  "dist/",
24
33
  "openclaw.plugin.json",
@@ -68,13 +77,5 @@
68
77
  "@types/ws": "^8",
69
78
  "ts-node": "^10",
70
79
  "typescript": "^5"
71
- },
72
- "scripts": {
73
- "build": "tsc",
74
- "dev": "tsc --watch",
75
- "test": "tsc -p test/tsconfig.json && node --test --loader ts-node/esm test/**/*.test.ts",
76
- "lint": "biome check",
77
- "format": "biome format --write",
78
- "release": "pnpm publish --access public"
79
80
  }
80
- }
81
+ }