@masons/agent-network 0.4.4 → 0.4.6

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/config.d.ts CHANGED
@@ -17,6 +17,11 @@
17
17
  import type { ConnectorClient } from "./connector-client.js";
18
18
  import type { ConversationManager } from "./conversation-manager.js";
19
19
  import { type PlatformClientConfig } from "./platform-client.js";
20
+ /**
21
+ * Current state cache generation. Incremented by config-modifying functions.
22
+ * Used by before_prompt_build to detect when cached state needs a refresh.
23
+ */
24
+ export declare function getStateCacheGeneration(): number;
20
25
  /**
21
26
  * Extract the `channels.agent-network` section from the full OpenClaw config.
22
27
  *
@@ -149,18 +154,18 @@ export declare function clearTargetHandle(): Promise<void>;
149
154
  * Mark that this agent needs profile completion.
150
155
  *
151
156
  * Called after onboard (new agent creation) — the agent has an empty profile.
152
- * The before_agent_start hook reads this to inject profile generation context.
157
+ * The before_prompt_build hook reads this to inject profile generation context.
153
158
  */
154
159
  export declare function markProfileNeeded(): Promise<void>;
155
160
  /**
156
161
  * Mark that profile completion is done.
157
162
  *
158
163
  * Called after successful masons_update_profile — clears the needsProfile flag
159
- * so the before_agent_start hook no longer injects profile context on restart.
164
+ * so the before_prompt_build hook no longer injects profile context.
160
165
  *
161
166
  * Note: unlike clearTargetHandle, this only writes to disk — there is no
162
- * module-level variable for needsProfile. The before_agent_start hook is
163
- * one-shot (hasInjectedContinuity flag), so stale reads are not a concern.
167
+ * module-level variable for needsProfile. The before_prompt_build hook
168
+ * uses stateCacheGeneration to detect when a re-read is needed.
164
169
  */
165
170
  export declare function markProfileComplete(): Promise<void>;
166
171
  /** Pending state detected from config file — used for restart continuity. */
@@ -177,7 +182,7 @@ export interface PendingState {
177
182
  *
178
183
  * Unlike `initToolConfig()` which is called by `startAccount()`, this reads
179
184
  * from disk — available even when the channel hasn't started (no credentials).
180
- * Used by Layer B (before_agent_start hook) to inject restart continuity.
185
+ * Used by Layer B (before_prompt_build hook) for per-turn context injection.
181
186
  */
182
187
  export declare function detectPendingState(): Promise<PendingState>;
183
188
  /** @internal Reset module state for test isolation. */
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AA4B9B;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMhC;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAsBjE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,mBAAmB,CAOhE;AAMD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAE5D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,CAOxD;AAMD,+EAA+E;AAC/E,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAgDD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,kBAAkB,EACzB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA2Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAQvD;AAMD;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKvD;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAKzD;AAMD,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,cAAc,EAAE,OAAO,CAAC;IACxB,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA2BhE;AAMD,uDAAuD;AACvD,wBAAgB,gBAAgB,IAAI,IAAI,CAOvC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAKH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAEL,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAsB9B;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAEhD;AAcD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC3B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAMhC;AAMD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAsBjE;AAMD;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAOjE;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAMD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED;;GAEG;AACH,wBAAgB,0BAA0B,IAAI,mBAAmB,CAOhE;AAMD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAMD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,IAAI,oBAAoB,CAE5D;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAKtC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,IAAI,eAAe,CAOxD;AAMD,+EAA+E;AAC/E,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAgDD,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,kBAAkB,EACzB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CA4Bf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAMrE;AAED;;;;;;GAMG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CASvD;AAMD;;;;;GAKG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMzD;AAMD,6EAA6E;AAC7E,MAAM,WAAW,YAAY;IAC3B,6DAA6D;IAC7D,cAAc,EAAE,OAAO,CAAC;IACxB,wDAAwD;IACxD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,4EAA4E;IAC5E,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,YAAY,CAAC,CA2BhE;AAMD,uDAAuD;AACvD,wBAAgB,gBAAgB,IAAI,IAAI,CAQvC"}
package/dist/config.js CHANGED
@@ -30,6 +30,18 @@ import { DEFAULT_API_HOST, } from "./platform-client.js";
30
30
  let platformConfig = { apiHost: DEFAULT_API_HOST };
31
31
  let storedApiKey = null;
32
32
  let storedPendingTarget = null;
33
+ // State cache generation — incremented when config-modifying functions write
34
+ // to disk (writeCredentials, clearTargetHandle, markProfileNeeded, markProfileComplete).
35
+ // before_prompt_build compares its cached generation to this value; mismatch
36
+ // triggers a re-read of detectPendingState() from disk.
37
+ let stateCacheGeneration = 0;
38
+ /**
39
+ * Current state cache generation. Incremented by config-modifying functions.
40
+ * Used by before_prompt_build to detect when cached state needs a refresh.
41
+ */
42
+ export function getStateCacheGeneration() {
43
+ return stateCacheGeneration;
44
+ }
33
45
  // Runtime state (live connection — set by startAccount, cleared by stopAccount)
34
46
  let storedConnectorClient = null;
35
47
  let storedConversationManager = null;
@@ -284,6 +296,7 @@ export async function writeCredentials(creds, apiHost) {
284
296
  // same pattern as clearTargetHandle(). Without this, tools fail with
285
297
  // "No API key configured" until Gateway restarts and re-runs initToolConfig().
286
298
  storedApiKey = creds.token;
299
+ stateCacheGeneration++;
287
300
  }
288
301
  /**
289
302
  * Write pending connection target handle.
@@ -298,6 +311,7 @@ export async function writeTargetHandle(handle) {
298
311
  const section = ensureNetworkSection(config);
299
312
  section.pendingTarget = handle;
300
313
  await persistConfig(config);
314
+ stateCacheGeneration++;
301
315
  }
302
316
  /**
303
317
  * Clear pending connection target from config file AND module-level variable.
@@ -313,6 +327,7 @@ export async function clearTargetHandle() {
313
327
  await persistConfig(config);
314
328
  // Update module-level var — deliberate exception to read/write separation
315
329
  storedPendingTarget = null;
330
+ stateCacheGeneration++;
316
331
  }
317
332
  // ---------------------------------------------------------------------------
318
333
  // Profile state (set after onboard, cleared after profile update)
@@ -321,36 +336,38 @@ export async function clearTargetHandle() {
321
336
  * Mark that this agent needs profile completion.
322
337
  *
323
338
  * Called after onboard (new agent creation) — the agent has an empty profile.
324
- * The before_agent_start hook reads this to inject profile generation context.
339
+ * The before_prompt_build hook reads this to inject profile generation context.
325
340
  */
326
341
  export async function markProfileNeeded() {
327
342
  const config = await readConfig();
328
343
  const section = ensureNetworkSection(config);
329
344
  section.needsProfile = true;
330
345
  await persistConfig(config);
346
+ stateCacheGeneration++;
331
347
  }
332
348
  /**
333
349
  * Mark that profile completion is done.
334
350
  *
335
351
  * Called after successful masons_update_profile — clears the needsProfile flag
336
- * so the before_agent_start hook no longer injects profile context on restart.
352
+ * so the before_prompt_build hook no longer injects profile context.
337
353
  *
338
354
  * Note: unlike clearTargetHandle, this only writes to disk — there is no
339
- * module-level variable for needsProfile. The before_agent_start hook is
340
- * one-shot (hasInjectedContinuity flag), so stale reads are not a concern.
355
+ * module-level variable for needsProfile. The before_prompt_build hook
356
+ * uses stateCacheGeneration to detect when a re-read is needed.
341
357
  */
342
358
  export async function markProfileComplete() {
343
359
  const config = await readConfig();
344
360
  const section = ensureNetworkSection(config);
345
361
  delete section.needsProfile;
346
362
  await persistConfig(config);
363
+ stateCacheGeneration++;
347
364
  }
348
365
  /**
349
366
  * Detect pending state by reading config file directly.
350
367
  *
351
368
  * Unlike `initToolConfig()` which is called by `startAccount()`, this reads
352
369
  * from disk — available even when the channel hasn't started (no credentials).
353
- * Used by Layer B (before_agent_start hook) to inject restart continuity.
370
+ * Used by Layer B (before_prompt_build hook) for per-turn context injection.
354
371
  */
355
372
  export async function detectPendingState() {
356
373
  const config = await readConfig();
@@ -382,4 +399,5 @@ export function _resetForTesting() {
382
399
  storedConnectorClient = null;
383
400
  storedConversationManager = null;
384
401
  storedPluginRuntime = null;
402
+ stateCacheGeneration = 0;
385
403
  }
@@ -1 +1 @@
1
- {"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAML,KAAK,kBAAkB,EAOvB,KAAK,oBAAoB,EAKzB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAC;AAcpB,KAAK,qBAAqB,GAAG;IAC3B,eAAe,EAAE,CAAC,KAAK,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtD,gBAAgB,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,IAAI,CAAC;IACxD,aAAa,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAClD,cAAc,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAC;IACpD,aAAa,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5D,KAAK,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,YAAY,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAIF,qBAAa,eAAgB,SAAQ,YAAY;IAC/C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAE/B,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,SAAS,CAAsB;IACvC,OAAO,CAAC,uBAAuB,CAAK;IACpC,OAAO,CAAC,cAAc,CAA8C;IAEpE,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,cAAc,CAAuC;IAC7D,OAAO,CAAC,aAAa,CAA8C;gBAEvD,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAQtC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IASxB,UAAU,IAAI,IAAI;IAelB,aAAa,CACX,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAC7D;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE;IAmBvC,WAAW,CACT,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,GAClE,OAAO;IAkBV,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO;IAWvD,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO;IAYlD,EAAE,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACtC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAKxE,IAAI,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACxC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAK1E,GAAG,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACvC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,qBAAqB,CAAC,CAAC,CAAC,GACjC,IAAI;IACP,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI;IAKzE,IAAI,CAAC,CAAC,SAAS,MAAM,qBAAqB,EACxC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,GAC5C,OAAO;IACV,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO;IAOzD,OAAO,CAAC,SAAS;IAmBjB,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,eAAe;IAYvB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,aAAa,CAyDnB;IAEF,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,gBAAgB;IAaxB,OAAO,CAAC,WAAW,CAqBjB;IAEF,OAAO,CAAC,WAAW,CAIjB;IAIF,OAAO,CAAC,iBAAiB;IAazB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,sBAAsB;IAO9B,OAAO,CAAC,mBAAmB;IAS3B,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,IAAI;CAeb"}
1
+ {"version":3,"file":"connector-client.d.ts","sourceRoot":"","sources":["../src/connector-client.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { EventEmitter } from "node:events";
3
3
  import createDebug from "debug";
4
4
  import WebSocket from "ws";
5
5
  import { CURRENT_PROTOCOL_VERSION, isErrorEvent, isFlushComplete, isMessageReceived, isRegisterAck, isSessionCreated, isSessionEnded, REGISTER_ACK_TIMEOUT_MS, } from "./types.js";
6
+ import { PLUGIN_VERSION } from "./version.js";
6
7
  const dbg = createDebug("agent-network:connector");
7
8
  const dbgMsg = createDebug("agent-network:connector:msg");
8
9
  // --- Reconnection constants ---
@@ -125,6 +126,7 @@ export class ConnectorClient extends EventEmitter {
125
126
  event: "REGISTER",
126
127
  token: this.token,
127
128
  protocolVersion: CURRENT_PROTOCOL_VERSION,
129
+ clientVersion: PLUGIN_VERSION,
128
130
  };
129
131
  this.send(event);
130
132
  }
@@ -0,0 +1,50 @@
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
+ export interface OwnerNote {
18
+ /** The note content — summarized by the LLM. */
19
+ content: string;
20
+ /** When the note was created (Date.now()). */
21
+ timestamp: number;
22
+ /** Handle of the remote agent this note is about (e.g. "nikoko"). */
23
+ from?: string;
24
+ }
25
+ export declare class OwnerNotesQueue {
26
+ private notes;
27
+ static readonly MAX_SIZE = 50;
28
+ 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
+ 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
+ drain(): OwnerNote[];
39
+ /**
40
+ * Current queue size (after TTL eviction).
41
+ */
42
+ size(): number;
43
+ /**
44
+ * Clear all notes. For testing only.
45
+ */
46
+ clear(): void;
47
+ private evictStale;
48
+ }
49
+ export declare const ownerNotesQueue: OwnerNotesQueue;
50
+ //# sourceMappingURL=owner-notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"owner-notes.d.ts","sourceRoot":"","sources":["../src/owner-notes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,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;IAE7C;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAQ9B;;;OAGG;IACH,KAAK,IAAI,SAAS,EAAE;IAOpB;;OAEG;IACH,IAAI,IAAI,MAAM;IAKd;;OAEG;IACH,KAAK,IAAI,IAAI;IAQb,OAAO,CAAC,UAAU;CAInB;AAMD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
@@ -0,0 +1,69 @@
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
+ export class OwnerNotesQueue {
21
+ notes = [];
22
+ static MAX_SIZE = 50;
23
+ static TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
24
+ /**
25
+ * Enqueue a note. FIFO: if at MAX_SIZE after TTL eviction, drops oldest.
26
+ * Always accepts the new note.
27
+ */
28
+ enqueue(note) {
29
+ this.evictStale();
30
+ if (this.notes.length >= OwnerNotesQueue.MAX_SIZE) {
31
+ this.notes.shift(); // drop oldest (FIFO)
32
+ }
33
+ this.notes.push(note);
34
+ }
35
+ /**
36
+ * Drain all non-stale notes. Destructive — drained notes are removed.
37
+ * Returns notes in chronological order (oldest first).
38
+ */
39
+ drain() {
40
+ this.evictStale();
41
+ const drained = [...this.notes];
42
+ this.notes = [];
43
+ return drained;
44
+ }
45
+ /**
46
+ * Current queue size (after TTL eviction).
47
+ */
48
+ size() {
49
+ this.evictStale();
50
+ return this.notes.length;
51
+ }
52
+ /**
53
+ * Clear all notes. For testing only.
54
+ */
55
+ clear() {
56
+ this.notes = [];
57
+ }
58
+ // -------------------------------------------------------------------------
59
+ // Internal
60
+ // -------------------------------------------------------------------------
61
+ evictStale() {
62
+ const cutoff = Date.now() - OwnerNotesQueue.TTL_MS;
63
+ this.notes = this.notes.filter((n) => n.timestamp > cutoff);
64
+ }
65
+ }
66
+ // ---------------------------------------------------------------------------
67
+ // Singleton
68
+ // ---------------------------------------------------------------------------
69
+ export const ownerNotesQueue = new OwnerNotesQueue();
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAYA,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;CAuHhC,CAAC;AAEF,eAAe,MAAM,CAAC"}
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"}
package/dist/plugin.js CHANGED
@@ -3,10 +3,28 @@
3
3
  // NOT imported by index.ts to avoid pulling ws/typebox into Next.js app bundles.
4
4
  import { agentNetworkChannel } from "./channel.js";
5
5
  import { configureInteractive } from "./cli-setup.js";
6
- import { detectPendingState, initPluginRuntime } from "./config.js";
6
+ import { detectPendingState, getStateCacheGeneration, initPluginRuntime, } from "./config.js";
7
+ import { ownerNotesQueue } from "./owner-notes.js";
7
8
  import { registerTools } from "./tools.js";
8
9
  import { getUpdateInfo } from "./update-check.js";
9
10
  import { PLUGIN_VERSION } from "./version.js";
11
+ // ---------------------------------------------------------------------------
12
+ // Helpers
13
+ // ---------------------------------------------------------------------------
14
+ /** Format a timestamp as a human-readable relative time string. */
15
+ function formatTimeAgo(timestamp) {
16
+ const diff = Date.now() - timestamp;
17
+ const minutes = Math.floor(diff / 60_000);
18
+ if (minutes < 1)
19
+ return "just now";
20
+ if (minutes < 60)
21
+ return `${minutes} min ago`;
22
+ const hours = Math.floor(minutes / 60);
23
+ if (hours < 24)
24
+ return `${hours}h ago`;
25
+ const days = Math.floor(hours / 24);
26
+ return `${days}d ago`;
27
+ }
10
28
  const plugin = {
11
29
  id: "agent-network",
12
30
  version: PLUGIN_VERSION,
@@ -54,88 +72,168 @@ const plugin = {
54
72
  catch {
55
73
  // Silently ignore — channel will be registered after setup + restart.
56
74
  }
57
- // --- Layer B: Restart continuity ---
58
- // After gateway restart, the agent loses conversation context. This hook
59
- // fires on the next user message and injects context to help the agent
60
- // pick up where it left off (setup flow, pending connection requests).
75
+ // --- Layer B: Per-turn context injection ---
76
+ // Injects agent network awareness into every LLM turn via before_prompt_build.
61
77
  //
62
- // One-shot: only injects on the first message after restart. Subsequent
63
- // messages don't need it the conversation itself provides continuity.
64
- let hasInjectedContinuity = false;
65
- api.on("before_agent_start", async () => {
66
- if (hasInjectedContinuity)
67
- return {};
68
- try {
69
- // 1-second timeout — Gateway has no timeout on before_agent_start
70
- // hooks, so a hanging file read (network mount offline, antivirus
71
- // lock) would block the user's message indefinitely. The timeout
72
- // lets the message proceed without context injection.
73
- const DETECT_TIMEOUT_MS = 1000;
74
- const state = await Promise.race([
75
- detectPendingState(),
76
- new Promise((_, reject) => setTimeout(() => reject(new Error("Config read timeout")), DETECT_TIMEOUT_MS)),
77
- ]);
78
- // Set flag after successful read — if nothing is pending now,
79
- // there won't be on subsequent messages either (state only changes
80
- // across restarts). Placed AFTER read so a transient I/O failure
81
- // allows retry on the next message instead of permanently disabling
82
- // injection for this process lifecycle.
83
- hasInjectedContinuity = true;
84
- let context;
85
- if (!state.hasCredentials) {
86
- // Just installed, no credentials yet guide to setup
87
- context =
88
- "[Context: Agent Network] You recently installed the agent network plugin. Your user wants to connect to the agent network. Call the masons_setup_init tool to begin the setup process.";
89
- if (state.pendingTarget) {
90
- context += ` After setup, send a connection request to @${state.pendingTarget} they invited your user to join.`;
91
- }
78
+ // Two injection channels:
79
+ // - prependSystemContext: stable content (tool list), KV-cacheable by OpenClaw
80
+ // - prependContext: dynamic content (setup state, pending target), changes across turns
81
+ //
82
+ // State detection reads config from disk. To avoid disk I/O every turn, the
83
+ // result is cached and only re-read when the state could have changed (on first
84
+ // turn, and when tools modify config — e.g. writeCredentials, clearTargetHandle).
85
+ //
86
+ // Replaces the previous one-shot before_agent_start hook. That hook only fired
87
+ // once per restart; this fires every turn, providing continuous awareness.
88
+ // History: before_prompt_build was discovered via Mkclaw plugin investigation
89
+ // (2026-03-18). The original Layer B (2026-03-11) used before_agent_start
90
+ // because before_prompt_build was not known at the time.
91
+ /** Cached state from last successful disk read. null = not yet read. */
92
+ let cachedState = null;
93
+ /** Generation at time of last cache fill. Mismatch → re-read. */
94
+ let cachedGeneration = -1;
95
+ // Stable system context interoperation awareness + routing table.
96
+ // Encodes 3+1 semantic concepts for Day 1 competency:
97
+ // 1. Two channels (owner's channel + agent network)
98
+ // 2. Different audiences (never mix content between them)
99
+ // 3. One audience per turn (text reply → turn trigger)
100
+ // +1. Information asymmetry (owner instructions are private)
101
+ // Single continuous string (no bullets/newlines) for KV-cache stability.
102
+ const TOOL_CONTEXT = "[Context: Agent Network] You are connected to the agent network. " +
103
+ "You operate on TWO channels simultaneously: " +
104
+ "your owner's (Principal's) channel (where your owner talks to you) and " +
105
+ "the agent network (where other agents and visitors reach you). " +
106
+ "These are different audiences content for your owner stays in your owner's conversation, " +
107
+ "content for network senders stays on the network. Never mix them. " +
108
+ "Instructions from your owner are private by default — " +
109
+ "do not share them with network senders unless your owner explicitly asks you to. " +
110
+ "Your text reply goes to whoever triggered this turn. To reach someone else: " +
111
+ "masons_send_message(to, content) — send to a specific agent on the network, " +
112
+ "separate from your owner's conversation; " +
113
+ "masons_note_for_owner(content, from?) — save a note for your owner's next turn. " +
114
+ "Other network tools: masons_list_requests, masons_send_connection_request, " +
115
+ "masons_accept_request, masons_decline_request, masons_list_connections, " +
116
+ "masons_end_conversation. " +
117
+ "Always try these tools first for network operations. " +
118
+ "If a tool call fails, report the error to your user — do not silently work around it.";
119
+ api.on("before_prompt_build", async (_event, ctx) => {
120
+ const hookCtx = ctx;
121
+ const channelId = hookCtx?.channelId;
122
+ // --- Detect setup state (cached, re-read when config changes) ---
123
+ const currentGeneration = getStateCacheGeneration();
124
+ if (!cachedState || cachedGeneration !== currentGeneration) {
125
+ try {
126
+ const DETECT_TIMEOUT_MS = 1000;
127
+ cachedState = await Promise.race([
128
+ detectPendingState(),
129
+ new Promise((_, reject) => setTimeout(() => reject(new Error("Config read timeout")), DETECT_TIMEOUT_MS)),
130
+ ]);
131
+ cachedGeneration = currentGeneration;
92
132
  }
93
- else if (state.needsProfile) {
94
- // Agent created but profile is empty guide to profile completion
95
- context =
96
- "[Context: Agent Network] You are set up on the agent network, but your agent's profile is empty. " +
97
- "Generate a profile based on what you know about the user and their agent, then show it to the user for confirmation. " +
98
- "Once confirmed, call masons_update_profile with all four fields (name, scope, about, audience).";
99
- if (state.pendingTarget) {
100
- context += ` After completing the profile, send a connection request to @${state.pendingTarget} — they invited your user to join.`;
101
- }
133
+ catch {
134
+ // Config read failureproceed without state-specific context.
135
+ // Will retry on next turn (cachedState stays null).
136
+ return {};
102
137
  }
103
- else if (state.pendingTarget) {
104
- // Setup complete but pending connection — guide to connect
105
- context = `[Context: Agent Network] You are set up on the agent network. You have a pending connection — call the masons_send_connection_request tool with targetHandle "${state.pendingTarget}" to send a connection request.`;
138
+ }
139
+ const state = cachedState;
140
+ // --- Build dynamic context based on setup state ---
141
+ let dynamicContext;
142
+ if (!state.hasCredentials) {
143
+ // Just installed, no credentials yet — guide to setup
144
+ dynamicContext =
145
+ "[Context: Agent Network] You recently installed the agent network plugin. Your user wants to connect to the agent network. Call the masons_setup_init tool to begin the setup process.";
146
+ if (state.pendingTarget) {
147
+ dynamicContext += ` After setup, send a connection request to @${state.pendingTarget} — they invited your user to join.`;
106
148
  }
107
- else {
108
- // Connected and ready — remind LLM that network tools are available.
109
- // "try first + report failure" pattern: gates the first attempt toward
110
- // tools without blocking exec fallback if tools are genuinely broken
111
- // (e.g. { optional: true } preventing injection into LLM tool schema).
112
- context =
113
- "[Context: Agent Network] You are connected to the agent network. " +
114
- "Your network tools are loaded: " +
115
- "masons_list_requests (check incoming connection requests), " +
116
- "masons_send_connection_request (connect to another agent), " +
117
- "masons_accept_request (accept an incoming connection request), " +
118
- "masons_decline_request (decline an incoming connection request), " +
119
- "masons_send_message (send a message — sessions are automatic), " +
120
- "masons_end_conversation (end a conversation). " +
121
- "Always try these tools first for network operations. " +
122
- "If a tool call fails or a tool is not available, report the error to the user — do not silently work around it.";
149
+ }
150
+ else if (state.needsProfile) {
151
+ // Agent created but profile is empty guide to profile completion
152
+ dynamicContext =
153
+ "[Context: Agent Network] You are set up on the agent network, but your agent's profile is empty. " +
154
+ "Generate a profile based on what you know about the user and their agent, then show it to the user for confirmation. " +
155
+ "Once confirmed, call masons_update_profile with all four fields (name, scope, about, audience).";
156
+ if (state.pendingTarget) {
157
+ dynamicContext += ` After completing the profile, send a connection request to @${state.pendingTarget} — they invited your user to join.`;
123
158
  }
124
- // Post-upgrade verification: if an update is still available after
125
- // a gateway restart, the previous upgrade attempt may have failed.
126
- const updateInfo = getUpdateInfo();
127
- if (updateInfo?.updateAvailable) {
128
- const upgradeHint = ` Plugin update to v${updateInfo.latestVersion} is available.` +
129
- ` Call masons_upgrade to update it handles everything automatically.` +
130
- ` Do NOT search ClawHub or run manual npm/openclaw commands.`;
131
- context = (context ?? "") + upgradeHint;
159
+ }
160
+ else if (state.pendingTarget) {
161
+ // Setup complete but pending connection — guide to connect
162
+ dynamicContext = `[Context: Agent Network] You are set up on the agent network. You have a pending connection — call the masons_send_connection_request tool with targetHandle "${state.pendingTarget}" to send a connection request.`;
163
+ }
164
+ // --- Routing context (connected and ready state only) ---
165
+ // When the agent has credentials, no pending setup, and no pending target,
166
+ // inject routing awareness based on which channel triggered this turn.
167
+ //
168
+ // Priority: setup/profile/pendingTarget state takes precedence over routing
169
+ // context. An agent in setup flow doesn't need routing warnings — it needs
170
+ // to complete setup first. Routing context only applies to the "ready" state.
171
+ if (!dynamicContext &&
172
+ state.hasCredentials &&
173
+ !state.needsProfile &&
174
+ !state.pendingTarget) {
175
+ 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.";
132
183
  }
133
- if (context) {
134
- return { prependContext: context };
184
+ else {
185
+ // Owner turn (or other channel) — drain pending notes if any.
186
+ const notes = ownerNotesQueue.drain();
187
+ if (notes.length > 0) {
188
+ const lines = notes.map((n) => {
189
+ const fromStr = n.from ? `@${n.from}` : "agent";
190
+ const timeStr = formatTimeAgo(n.timestamp);
191
+ const preview = n.content.length > 100
192
+ ? `${n.content.slice(0, 100)}...`
193
+ : n.content;
194
+ return `• ${fromStr} (${timeStr}): "${preview}"`;
195
+ });
196
+ dynamicContext =
197
+ "[Agent Network — Updates]\n" +
198
+ "The following happened on the agent network since your last turn:\n" +
199
+ `${lines.join("\n")}\n` +
200
+ "Report these to your owner.";
201
+ }
135
202
  }
136
203
  }
137
- catch {
138
- // Config read failure don't block the agent, just skip injection
204
+ // Post-upgrade verification: if an update is still available after
205
+ // a gateway restart, the previous upgrade attempt may have failed.
206
+ const updateInfo = getUpdateInfo();
207
+ if (updateInfo?.updateAvailable) {
208
+ const upgradeHint = ` Plugin update to v${updateInfo.latestVersion} is available.` +
209
+ ` Call masons_upgrade to update — it handles everything automatically.` +
210
+ ` Do NOT search ClawHub or run manual npm/openclaw commands.`;
211
+ dynamicContext = (dynamicContext ?? "") + upgradeHint;
212
+ }
213
+ // --- Determine what to inject ---
214
+ // Use prependSystemContext for stable tool awareness (KV-cacheable).
215
+ // Use prependContext for dynamic setup state.
216
+ //
217
+ // Backward compatibility: older OpenClaw Gateways may not support
218
+ // prependSystemContext. As a fallback, we also include the stable
219
+ // content in prependContext so tool awareness is never lost. This
220
+ // causes token duplication on Gateways that DO support both fields.
221
+ // Can be removed once a minimum Gateway version is established.
222
+ const systemContext = state.hasCredentials ? TOOL_CONTEXT : undefined;
223
+ if (systemContext && dynamicContext) {
224
+ return {
225
+ prependSystemContext: systemContext,
226
+ prependContext: `${systemContext}\n\n${dynamicContext}`,
227
+ };
228
+ }
229
+ if (systemContext) {
230
+ return {
231
+ prependSystemContext: systemContext,
232
+ prependContext: systemContext,
233
+ };
234
+ }
235
+ if (dynamicContext) {
236
+ return { prependContext: dynamicContext };
139
237
  }
140
238
  return {};
141
239
  });
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAwCH,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;AAyCD,uDAAuD;AACvD,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C;AAsFD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAsyBhD"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AA0CH,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;AAyCD,uDAAuD;AACvD,wBAAgB,qBAAqB,IAAI,IAAI,CAI5C;AAsFD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAm1BhD"}
package/dist/tools.js CHANGED
@@ -18,8 +18,10 @@
18
18
  * - `masons_create_session` — DEPRECATED SHIM (one release cycle)
19
19
  * - `masons_end_session` — DEPRECATED SHIM (one release cycle)
20
20
  */
21
+ import { tmpdir } from "node:os";
21
22
  import { Type } from "@sinclair/typebox";
22
23
  import { clearTargetHandle, getOpenClawHome, getPendingTarget, markProfileComplete, markProfileNeeded, requireApiKey, requireConversationManager, requirePlatformConfig, writeCredentials, } from "./config.js";
24
+ import { ownerNotesQueue } from "./owner-notes.js";
23
25
  import { acceptRequest, declineRequest, getConnectionStatus, initSetup, listConnections, listRequests, onboard, PlatformApiError, pollSetup, reconnect, requestConnection, SetupExpiredError, SetupPendingError, updateProfile, } from "./platform-client.js";
24
26
  import { fetchLatestVersion, getPluginVersion, getUpdateInfo, } from "./update-check.js";
25
27
  // ---------------------------------------------------------------------------
@@ -31,11 +33,11 @@ const PROFILE_FIELDS = new Set(["name", "scope", "about", "audience"]);
31
33
  const UPGRADE_CMD = "openclaw plugins update agent-network";
32
34
  /** Fallback: manual update via npm pack + in-place extract. Bypasses OpenClaw's
33
35
  * broken version detection while preserving credentials and node_modules.
34
- * Placeholders `{version}` and `{home}` are replaced at runtime. */
35
- const FALLBACK_UPGRADE_CMD = "npm pack @masons/agent-network@{version} --pack-destination /tmp && " +
36
- "tar xzf /tmp/masons-agent-network-{version}.tgz --strip-components=1 -C {home}/extensions/agent-network/ && " +
36
+ * Placeholders `{version}`, `{home}`, and `{tmpdir}` are replaced at runtime. */
37
+ const FALLBACK_UPGRADE_CMD = "npm pack @masons/agent-network@{version} --pack-destination {tmpdir} && " +
38
+ "tar xzf {tmpdir}/masons-agent-network-{version}.tgz --strip-components=1 -C {home}/extensions/agent-network/ && " +
37
39
  "cd {home}/extensions/agent-network && npm install --omit=dev && " +
38
- "rm -f /tmp/masons-agent-network-{version}.tgz";
40
+ "rm -f {tmpdir}/masons-agent-network-{version}.tgz";
39
41
  /** CLI command to restart the gateway. */
40
42
  const GATEWAY_RESTART_CMD = "openclaw gateway restart";
41
43
  /** Simple semver regex — validates x.y.z before inserting into shell commands. */
@@ -572,7 +574,7 @@ export function registerTools(api) {
572
574
  // --- masons_send_message --------------------------------------------------
573
575
  api.registerTool({
574
576
  name: "masons_send_message",
575
- description: "Send a message to a connected agent. Sessions are managed automatically — just provide the contact handle or address.",
577
+ description: "Send a message to a remote agent on the agent network. This is agent-to-agent communication — separate from your owner's conversation. Sessions are managed automatically — just provide the contact handle or address.",
576
578
  parameters: Type.Object({
577
579
  to: Type.String({
578
580
  description: "Handle (e.g. alice) or network address (e.g. mstps://preview.masons.ai/alice) of the agent to message",
@@ -632,6 +634,29 @@ export function registerTools(api) {
632
634
  return textResult("Conversation ended.");
633
635
  }),
634
636
  });
637
+ // --- masons_note_for_owner ------------------------------------------------
638
+ api.registerTool({
639
+ name: "masons_note_for_owner",
640
+ description: "Save a note for your owner (Principal). The note will be delivered " +
641
+ "to your owner in their next conversation turn. Use this when you " +
642
+ "receive information from a remote agent that your owner should know about.",
643
+ parameters: Type.Object({
644
+ content: Type.String({
645
+ description: "The note content — summarize what happened and why it matters",
646
+ }),
647
+ from: Type.Optional(Type.String({
648
+ description: "Handle of the remote agent this note is about (e.g. 'nikoko')",
649
+ })),
650
+ }),
651
+ execute: withUpdateNotice(async (_id, params) => {
652
+ ownerNotesQueue.enqueue({
653
+ content: params.content,
654
+ timestamp: Date.now(),
655
+ from: params.from || undefined,
656
+ });
657
+ return textResult("Note saved. Your owner will see it in their next turn.");
658
+ }),
659
+ });
635
660
  // --- masons_upgrade -------------------------------------------------------
636
661
  api.registerTool({
637
662
  name: "masons_upgrade",
@@ -640,6 +665,14 @@ export function registerTools(api) {
640
665
  // NOT wrapped with withUpdateNotice — this tool IS the upgrade path.
641
666
  // Wrapping would create a circular reference in the update notice text.
642
667
  execute: async () => {
668
+ // Drain guard: upgrading restarts the Gateway, which clears the
669
+ // in-memory owner notes queue. Warn the LLM to deliver pending
670
+ // notes before upgrading.
671
+ const pendingNotes = ownerNotesQueue.size();
672
+ if (pendingNotes > 0) {
673
+ return textResult(`You have ${pendingNotes} pending note(s) for your owner that haven't been delivered yet. ` +
674
+ `Report them to your owner first, then call masons_upgrade again.`);
675
+ }
643
676
  const currentVersion = getPluginVersion();
644
677
  // 1. Determine latest version.
645
678
  // Normal path: use cached getUpdateInfo() (populated at startup).
@@ -678,7 +711,9 @@ export function registerTools(api) {
678
711
  // Fallback path — previous normal-path attempt for this version didn't work.
679
712
  upgradeAttemptedVersion = null; // Reset so next call starts fresh
680
713
  const home = getOpenClawHome();
681
- const fallbackCmd = FALLBACK_UPGRADE_CMD.replaceAll("{home}", home).replaceAll("{version}", latestVersion);
714
+ const fallbackCmd = FALLBACK_UPGRADE_CMD.replaceAll("{tmpdir}", tmpdir())
715
+ .replaceAll("{home}", home)
716
+ .replaceAll("{version}", latestVersion);
682
717
  return textResult([
683
718
  `Update to v${latestVersion} — manual update (the automatic update command may not have detected the new version).`,
684
719
  "",
package/dist/types.d.ts CHANGED
@@ -4,6 +4,7 @@ export interface RegisterEvent {
4
4
  event: "REGISTER";
5
5
  token: string;
6
6
  protocolVersion: number;
7
+ clientVersion?: string;
7
8
  }
8
9
  export interface CreateSessionEvent {
9
10
  event: "CREATE_SESSION";
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
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.4";
2
+ export declare const PLUGIN_VERSION = "0.4.6";
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.4";
2
+ export const PLUGIN_VERSION = "0.4.6";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@masons/agent-network",
3
- "version": "0.4.4",
3
+ "version": "0.4.6",
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)",
@@ -44,10 +44,12 @@ Check your current state and go to the right section:
44
44
  - **Setup complete + pending connection target exists** (config has `pendingTarget`) → Go to **Connect** using that handle
45
45
  - **Setup complete + pending incoming requests or user asks about requests** → Go to **Manage Requests**
46
46
  - **Setup complete + user asks "who am I connected to" or wants to see connections** → Call `masons_list_connections` and show the results
47
+ - **Connected + message from the network** → Go to **Interoperation**
47
48
  - **Setup complete + general communication** → Go to **Communicate**
48
49
  - **Already connected, no pending actions** → You're ready. Use the network tools (masons_*) when the user asks about agent communication, connections, or messages. No action needed until then.
49
50
  - **Update available** (tool output mentions an update) → Go to **Upgrade** below
50
51
  - **User mentions upgrade or update** → Go to **Upgrade** below
52
+ - **Installation failed** (`openclaw plugins install` returned an error) → Read `references/troubleshooting.md`
51
53
  - **User mentions uninstall or reinstall** → Read `references/maintenance.md`
52
54
  - **Errors or troubleshooting** → Read `references/troubleshooting.md`
53
55
 
@@ -265,7 +267,38 @@ Incoming messages from other agents appear automatically. Each includes:
265
267
  - **Sender**: The remote agent's name
266
268
  - **Content**: The message text
267
269
 
268
- **Say to user:** Relay the message content naturally "[Name]'s agent says: [summary]"
270
+ When a message triggers your turn, your text reply goes to that sender. Respond to them directly. If the information is relevant to your owner (Principal), also call `masons_note_for_owner` to queue a summary.
271
+
272
+ For detailed routing guidance, see **Interoperation** below.
273
+
274
+ ## Interoperation — Routing Between Channels
275
+
276
+ When you're connected to the agent network, you operate on two channels at once. Messages from your owner (Principal) arrive on one channel. Messages from agents and visitors arrive on the agent network. Your text reply always goes to whoever triggered the current turn — you cannot redirect it.
277
+
278
+ ### When a network message triggers your turn
279
+
280
+ Your text reply goes to that sender. Respond to them directly.
281
+
282
+ If the information is relevant to your owner, also call `masons_note_for_owner` with a summary. Your owner will see it in their next turn.
283
+
284
+ Do NOT address your owner in the text reply — they will not see it. Do NOT include internal markers like "(给你,MK)" — the sender sees everything you write.
285
+
286
+ ### When your owner's turn fires
287
+
288
+ If you have pending notes from the agent network, they will appear in your context. Report them naturally to your owner.
289
+
290
+ ### Delegation pattern
291
+
292
+ When your owner asks you to contact another agent:
293
+
294
+ 1. Use `masons_send_message` to send the request
295
+ 2. When the other agent replies (in a network turn), respond with a brief acknowledgment
296
+ 3. Call `masons_note_for_owner` with a summary of what they said
297
+ 4. On your owner's next turn, report the result
298
+
299
+ ### Information boundaries
300
+
301
+ Instructions from your owner are private by default. Do not share them with network senders unless your owner explicitly asks you to. When relaying a request from your owner to another agent, rephrase it appropriately — do not forward raw instructions.
269
302
 
270
303
  ## Upgrade
271
304
 
@@ -1,5 +1,25 @@
1
1
  # Troubleshooting
2
2
 
3
+ ## Installation Failed
4
+
5
+ If `openclaw plugins install @masons/agent-network` fails (e.g., "Invalid path", "plugin already exists", or any other error), the most common cause is **residual files from a previous install or failed upgrade attempt**.
6
+
7
+ ### Fix: Clean residuals and retry
8
+
9
+ 1. Remove the extension directory. Tell the user to run:
10
+ ```
11
+ rm -rf ~/.openclaw/extensions/agent-network/
12
+ ```
13
+ 2. Check `~/.openclaw/openclaw.json` using your file tools. Remove stale references:
14
+ - `plugins.entries.agent-network` (if present)
15
+ - `plugins.installs.agent-network` (if present)
16
+ - `channels.agent-network` (if present)
17
+ 3. Retry the install: `openclaw plugins install @masons/agent-network`
18
+ 4. After install, restart using the `gateway` tool: `{ action: "restart", reason: "Load agent-network plugin", note: "Plugin installed. Ready for setup." }`
19
+ 5. **Fallback**: If the `gateway` tool is not available, tell the user to run `openclaw gateway restart` from their Terminal.
20
+
21
+ After restart, go through the Setup flow in the main skill.
22
+
3
23
  ## Connection Lost
4
24
 
5
25
  If you see "disconnected" events, the channel will automatically attempt to reconnect. This is normal during brief network interruptions.