@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.
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +19 -0
- package/dist/sent-message-buffer.d.ts +51 -0
- package/dist/sent-message-buffer.d.ts.map +1 -0
- package/dist/sent-message-buffer.js +90 -0
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +8 -4
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +11 -10
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"
|
|
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();
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;
|
|
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
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.
|
|
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.
|
|
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
|
+
}
|