@masons/agent-network 0.4.7 → 0.4.8

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":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAc9D,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,oBAAoB,CAAC,CAAC;IAC9B,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAAC;IACvD,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;IACpE,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IACjE,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CAC/D;AAED,UAAU,sBAAsB;IAC9B,EAAE,EAAE,OAAO,CAAC;CACb;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,sBAAsB;IAC9B,YAAY,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9C,QAAQ,CAAC,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACzE;AAED,UAAU,qBAAqB,CAAC,CAAC,GAAG,OAAO;IACzC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAsDD,UAAU,qBAAqB,CAAC,CAAC,GAAG,OAAO;IACzC,YAAY,CAAC,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,WAAW,CAAC,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,UAAU,yBAAyB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,mBAAmB,CAAC;IAClC,MAAM,EAAE,oBAAoB,CAAC,mBAAmB,CAAC,CAAC;IAClD,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;CACrD;AAkED,eAAO,MAAM,mBAAmB,EAAE,yBAkXjC,CAAC"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAqB9D,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,OAAO,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,UAAU,oBAAoB,CAAC,CAAC;IAC9B,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,EAAE,CAAC;IACvD,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC;IACpE,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;IACjE,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;CAC/D;AAED,UAAU,sBAAsB;IAC9B,EAAE,EAAE,OAAO,CAAC;CACb;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,sBAAsB;IAC9B,YAAY,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9C,QAAQ,CAAC,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAC;CACzE;AAED,UAAU,qBAAqB,CAAC,CAAC,GAAG,OAAO;IACzC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,WAAW,CAAC;CAC1B;AAsDD,UAAU,qBAAqB,CAAC,CAAC,GAAG,OAAO;IACzC,YAAY,CAAC,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,WAAW,CAAC,CAAC,GAAG,EAAE,qBAAqB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,UAAU,yBAAyB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,mBAAmB,CAAC;IAClC,MAAM,EAAE,oBAAoB,CAAC,mBAAmB,CAAC,CAAC;IAClD,QAAQ,EAAE,sBAAsB,CAAC;IACjC,OAAO,EAAE,qBAAqB,CAAC,mBAAmB,CAAC,CAAC;CACrD;AAkED,eAAO,MAAM,mBAAmB,EAAE,yBAsYjC,CAAC"}
package/dist/channel.js CHANGED
@@ -3,6 +3,7 @@ import createDebug from "debug";
3
3
  import { clearConnectorClient, clearConversationManager, extractNetworkConfig, initConnectorClient, initConversationManager, initToolConfig, requirePluginRuntime, } from "./config.js";
4
4
  import { ConnectorClient } from "./connector-client.js";
5
5
  import { ConversationManager } from "./conversation-manager.js";
6
+ import { clearOwnerSessions, isOwnerSession, markOwnerSession, removeOwnerSession, setCurrentTurnIsOwner, } from "./owner-session-state.js";
6
7
  import { checkForUpdate } from "./update-check.js";
7
8
  const dbg = createDebug("agent-network:channel");
8
9
  // --- Sender identity ---
@@ -144,6 +145,9 @@ export const agentNetworkChannel = {
144
145
  // structured multi-step interactions, add a per-session dispatch queue.
145
146
  client.on("message_received", async (event) => {
146
147
  dbg("routing inbound message sessionId=%s contentLength=%d", event.sessionId, event.content.length);
148
+ // --- Owner turn detection (#836) ---
149
+ // Set BEFORE dispatch so before_prompt_build can read it.
150
+ setCurrentTurnIsOwner(isOwnerSession(event.sessionId));
147
151
  // --- Runtime guard ---
148
152
  let runtime;
149
153
  try {
@@ -253,6 +257,13 @@ export const agentNetworkChannel = {
253
257
  client.on("session_created", (event) => {
254
258
  dbg("session created sessionId=%s direction=%s", event.sessionId, event.direction);
255
259
  if (event.direction === "inbound") {
260
+ // --- Owner identity binding (#836) ---
261
+ // Connector sets `is_owner: true` when visitor_user_id === agent.userId.
262
+ // Track this session so message_received can set the per-turn flag.
263
+ if (event.metadata?.is_owner === true) {
264
+ markOwnerSession(event.sessionId);
265
+ dbg("owner session detected sessionId=%s", event.sessionId);
266
+ }
256
267
  const from = event.metadata?.from;
257
268
  const remoteAddress = typeof from === "string" && from.length > 0 ? from : null;
258
269
  if (remoteAddress) {
@@ -281,6 +292,14 @@ export const agentNetworkChannel = {
281
292
  // --- Session ended + disconnect ---
282
293
  // SessionLifecycle handles session state transitions (session_ended, disconnected)
283
294
  // via its own event subscriptions. No CM calls needed here.
295
+ // Owner session cleanup (#836): remove from ownerSessionIds on session_ended.
296
+ client.on("session_ended", (event) => {
297
+ removeOwnerSession(event.sessionId);
298
+ });
299
+ // On disconnect, all sessions are invalid — clear owner state.
300
+ client.on("disconnected", () => {
301
+ clearOwnerSessions();
302
+ });
284
303
  // --- Error handling ---
285
304
  // Must register before connect() — unhandled "error" events crash the process.
286
305
  client.on("error", (err) => {
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Owner Session State — tracks which MSTP sessions 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 sets `is_owner: true` in the
6
+ * SESSION_CREATED metadata. This module maintains the Plugin-side state:
7
+ *
8
+ * - `ownerSessionIds`: Set of session IDs where the visitor is the owner.
9
+ * Populated on session_created, cleaned up on session_ended / disconnected.
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
+ * Race condition note (from design review): if two messages arrive on
14
+ * different sessions concurrently, the flag may reflect the wrong session.
15
+ * Fail-safe: owner gets the routing warning (same as today's behavior).
16
+ * Acceptable for Phase 1 — OpenClaw processes turns sequentially per agent.
17
+ *
18
+ * Module-level singleton — shared between channel.ts (write) and plugin.ts (read).
19
+ * Same pattern as owner-notes.ts.
20
+ */
21
+ /** Mark a session as belonging to the owner. */
22
+ export declare function markOwnerSession(sessionId: string): void;
23
+ /** Remove a session from owner tracking (session ended or disconnected). */
24
+ export declare function removeOwnerSession(sessionId: string): void;
25
+ /** Clear all owner sessions (connection lost — all sessions are invalid). */
26
+ export declare function clearOwnerSessions(): void;
27
+ /** Check if a session belongs to the owner. */
28
+ export declare function isOwnerSession(sessionId: string): boolean;
29
+ /**
30
+ * Set the per-turn owner flag. Called in message_received before dispatch.
31
+ * The flag is consumed (read + reset) by before_prompt_build.
32
+ */
33
+ export declare function setCurrentTurnIsOwner(value: boolean): void;
34
+ /**
35
+ * Consume the per-turn owner flag. Returns the value and resets to false.
36
+ * Consuming prevents stale state from leaking into subsequent turns.
37
+ */
38
+ export declare function consumeCurrentTurnIsOwner(): boolean;
39
+ //# sourceMappingURL=owner-session-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-session-state.d.ts","sourceRoot":"","sources":["../src/owner-session-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgBH,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAExD;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAE1D;AAED,6EAA6E;AAC7E,wBAAgB,kBAAkB,IAAI,IAAI,CAGzC;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE1D;AAMD;;;GAGG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAInD"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Owner Session State — tracks which MSTP sessions 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 sets `is_owner: true` in the
6
+ * SESSION_CREATED metadata. This module maintains the Plugin-side state:
7
+ *
8
+ * - `ownerSessionIds`: Set of session IDs where the visitor is the owner.
9
+ * Populated on session_created, cleaned up on session_ended / disconnected.
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
+ * Race condition note (from design review): if two messages arrive on
14
+ * different sessions concurrently, the flag may reflect the wrong session.
15
+ * Fail-safe: owner gets the routing warning (same as today's behavior).
16
+ * Acceptable for Phase 1 — OpenClaw processes turns sequentially per agent.
17
+ *
18
+ * Module-level singleton — shared between channel.ts (write) and plugin.ts (read).
19
+ * Same pattern as owner-notes.ts.
20
+ */
21
+ // ---------------------------------------------------------------------------
22
+ // State
23
+ // ---------------------------------------------------------------------------
24
+ /** Session IDs where the visitor has been identified as the agent's owner. */
25
+ const ownerSessionIds = new Set();
26
+ /** Whether the current LLM turn was triggered by an owner session. */
27
+ let currentTurnIsOwner = false;
28
+ // ---------------------------------------------------------------------------
29
+ // Write API (called from channel.ts)
30
+ // ---------------------------------------------------------------------------
31
+ /** Mark a session as belonging to the owner. */
32
+ export function markOwnerSession(sessionId) {
33
+ ownerSessionIds.add(sessionId);
34
+ }
35
+ /** Remove a session from owner tracking (session ended or disconnected). */
36
+ export function removeOwnerSession(sessionId) {
37
+ ownerSessionIds.delete(sessionId);
38
+ }
39
+ /** Clear all owner sessions (connection lost — all sessions are invalid). */
40
+ export function clearOwnerSessions() {
41
+ ownerSessionIds.clear();
42
+ currentTurnIsOwner = false;
43
+ }
44
+ /** Check if a session belongs to the owner. */
45
+ export function isOwnerSession(sessionId) {
46
+ return ownerSessionIds.has(sessionId);
47
+ }
48
+ /**
49
+ * Set the per-turn owner flag. Called in message_received before dispatch.
50
+ * The flag is consumed (read + reset) by before_prompt_build.
51
+ */
52
+ export function setCurrentTurnIsOwner(value) {
53
+ currentTurnIsOwner = value;
54
+ }
55
+ // ---------------------------------------------------------------------------
56
+ // Read API (called from plugin.ts)
57
+ // ---------------------------------------------------------------------------
58
+ /**
59
+ * Consume the per-turn owner flag. Returns the value and resets to false.
60
+ * Consuming prevents stale state from leaking into subsequent turns.
61
+ */
62
+ export function consumeCurrentTurnIsOwner() {
63
+ const value = currentTurnIsOwner;
64
+ currentTurnIsOwner = false;
65
+ return value;
66
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAkCA,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;CAiNhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAmCA,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;CAqPhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
package/dist/plugin.js CHANGED
@@ -5,6 +5,7 @@ import { agentNetworkChannel } from "./channel.js";
5
5
  import { configureInteractive } from "./cli-setup.js";
6
6
  import { detectPendingState, getStateCacheGeneration, initPluginRuntime, } from "./config.js";
7
7
  import { ownerNotesQueue } from "./owner-notes.js";
8
+ import { consumeCurrentTurnIsOwner } from "./owner-session-state.js";
8
9
  import { registerTools } from "./tools.js";
9
10
  import { getUpdateInfo } from "./update-check.js";
10
11
  import { PLUGIN_VERSION } from "./version.js";
@@ -173,13 +174,46 @@ const plugin = {
173
174
  !state.needsProfile &&
174
175
  !state.pendingTarget) {
175
176
  if (channelId === "agent-network") {
176
- // Turn triggered by a remote agent — warn about routing.
177
- // The LLM's text reply will go to that agent via deliver callback.
178
- dynamicContext =
179
- "[Agent Network Routing] This turn was triggered by a message " +
180
- "on the agent network. Your text reply will be sent to that sender — " +
181
- "your owner (Principal) will NOT see it. To report something to your owner, " +
182
- "call masons_note_for_owner.";
177
+ // --- Owner identity binding (#836) ---
178
+ // Consume the per-turn owner flag set by channel.ts message_received.
179
+ // Must consume on every agent-network turn to prevent stale state.
180
+ const turnIsOwner = consumeCurrentTurnIsOwner();
181
+ if (turnIsOwner) {
182
+ // Owner visiting via Passport no routing warning needed.
183
+ // The LLM's text reply goes to the owner (the visitor IS the owner).
184
+ // Drain pending notes: owner is here, deliver them directly.
185
+ const notes = ownerNotesQueue.drain();
186
+ const notesBlock = notes.length > 0
187
+ ? "\n\nPending updates from the agent network:\n" +
188
+ notes
189
+ .map((n) => {
190
+ const fromStr = n.from ? `@${n.from}` : "agent";
191
+ const timeStr = formatTimeAgo(n.timestamp);
192
+ const preview = n.content.length > 100
193
+ ? `${n.content.slice(0, 100)}...`
194
+ : n.content;
195
+ return `• ${fromStr} (${timeStr}): "${preview}"`;
196
+ })
197
+ .join("\n")
198
+ : "";
199
+ dynamicContext =
200
+ "[Agent Network — Owner via Passport] Your owner (Principal) is talking to you " +
201
+ "via Passport (your public web chat page where visitors can reach you). " +
202
+ "This IS your owner — respond naturally, no need to ask who they are. " +
203
+ "Your text reply goes directly to your owner. " +
204
+ "You can share information freely — no information boundary applies. " +
205
+ "Do NOT use masons_note_for_owner — your owner is right here." +
206
+ notesBlock;
207
+ }
208
+ else {
209
+ // Turn triggered by a remote agent/stranger — warn about routing.
210
+ // The LLM's text reply will go to that sender via deliver callback.
211
+ dynamicContext =
212
+ "[Agent Network — Routing] This turn was triggered by a message " +
213
+ "on the agent network. Your text reply will be sent to that sender — " +
214
+ "your owner (Principal) will NOT see it. To report something to your owner, " +
215
+ "call masons_note_for_owner.";
216
+ }
183
217
  }
184
218
  else {
185
219
  // Owner turn (or other channel) — drain pending notes if any.
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.7";
2
+ export declare const PLUGIN_VERSION = "0.4.8";
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.7";
2
+ export const PLUGIN_VERSION = "0.4.8";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masons/agent-network",
3
- "version": "0.4.7",
3
+ "version": "0.4.8",
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)",