@masons/agent-network 0.5.13 → 0.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/channel.d.ts +0 -7
  2. package/dist/channel.d.ts.map +1 -1
  3. package/dist/channel.js +3 -174
  4. package/dist/cli-setup.d.ts +0 -93
  5. package/dist/cli-setup.d.ts.map +1 -1
  6. package/dist/cli-setup.js +124 -741
  7. package/dist/config-fs.d.ts +4 -0
  8. package/dist/config-fs.d.ts.map +1 -0
  9. package/dist/config-fs.js +23 -0
  10. package/dist/config-schema.js +2 -2
  11. package/dist/config.d.ts +2 -210
  12. package/dist/config.d.ts.map +1 -1
  13. package/dist/config.js +14 -334
  14. package/dist/connector-client.d.ts +0 -32
  15. package/dist/connector-client.d.ts.map +1 -1
  16. package/dist/connector-client.js +1 -89
  17. package/dist/constants.d.ts +0 -1
  18. package/dist/constants.d.ts.map +1 -1
  19. package/dist/constants.js +2 -3
  20. package/dist/conversation-manager.d.ts +0 -106
  21. package/dist/conversation-manager.d.ts.map +1 -1
  22. package/dist/conversation-manager.js +2 -131
  23. package/dist/environment-context.d.ts +0 -24
  24. package/dist/environment-context.d.ts.map +1 -1
  25. package/dist/environment-context.js +0 -42
  26. package/dist/handle-utils.d.ts +0 -14
  27. package/dist/handle-utils.d.ts.map +1 -1
  28. package/dist/handle-utils.js +0 -14
  29. package/dist/index.js +0 -9
  30. package/dist/owner-notes.d.ts +0 -33
  31. package/dist/owner-notes.d.ts.map +1 -1
  32. package/dist/owner-notes.js +2 -41
  33. package/dist/owner-session-state.d.ts +0 -26
  34. package/dist/owner-session-state.d.ts.map +1 -1
  35. package/dist/owner-session-state.js +0 -37
  36. package/dist/platform-client.d.ts +13 -202
  37. package/dist/platform-client.d.ts.map +1 -1
  38. package/dist/platform-client.js +22 -171
  39. package/dist/plugin.d.ts +5 -0
  40. package/dist/plugin.d.ts.map +1 -1
  41. package/dist/plugin.js +3 -167
  42. package/dist/sent-message-buffer.d.ts +0 -36
  43. package/dist/sent-message-buffer.d.ts.map +1 -1
  44. package/dist/sent-message-buffer.js +1 -45
  45. package/dist/tools.d.ts +0 -28
  46. package/dist/tools.d.ts.map +1 -1
  47. package/dist/tools.js +36 -240
  48. package/dist/turn-context.d.ts +0 -45
  49. package/dist/turn-context.d.ts.map +1 -1
  50. package/dist/turn-context.js +0 -57
  51. package/dist/types.d.ts +0 -67
  52. package/dist/types.d.ts.map +1 -1
  53. package/dist/types.js +0 -7
  54. package/dist/update-cache.d.ts +0 -17
  55. package/dist/update-cache.d.ts.map +1 -1
  56. package/dist/update-cache.js +1 -21
  57. package/dist/update-check.d.ts +1 -40
  58. package/dist/update-check.d.ts.map +1 -1
  59. package/dist/update-check.js +7 -66
  60. package/dist/version.d.ts +1 -2
  61. package/dist/version.d.ts.map +1 -1
  62. package/dist/version.js +1 -2
  63. package/openclaw.plugin.json +57 -3
  64. package/package.json +11 -10
  65. package/skills/agent-network/SKILL.md +21 -47
  66. package/skills/agent-network/references/troubleshooting.md +5 -5
package/dist/channel.d.ts CHANGED
@@ -1,13 +1,6 @@
1
1
  import type { AgentNetworkAccount } from "./config-schema.js";
2
- /** Get the stored owner Passport address (first is_owner visit). */
3
2
  export declare function getOwnerPassportAddress(): string | null;
4
- /**
5
- * Consume the identity linking nudge flag. Destructive read — returns true
6
- * at most once per detection cycle. Called by before_prompt_build on
7
- * non-Passport owner turns to deliver the nudge where the action is relevant.
8
- */
9
3
  export declare function consumeIdentityLinkingNudge(): boolean;
10
- /** Test-only: set the nudge flag without going through the detection path. */
11
4
  export declare function _setNudgePendingForTesting(value: boolean): void;
12
5
  interface ChannelMeta {
13
6
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAkC9D,oEAAoE;AACpE,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAED;;;;GAIG;AACH,wBAAgB,2BAA2B,IAAI,OAAO,CAIrD;AAED,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE/D;AAUD,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,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,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;AAuDD,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;AA4WD,eAAO,MAAM,mBAAmB,EAAE,yBAyNjC,CAAC"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAmC9D,wBAAgB,uBAAuB,IAAI,MAAM,GAAG,IAAI,CAEvD;AAOD,wBAAgB,2BAA2B,IAAI,OAAO,CAIrD;AAGD,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAE/D;AAUD,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,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,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;AAuDD,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;AA4WD,eAAO,MAAM,mBAAmB,EAAE,yBAyNjC,CAAC"}
package/dist/channel.js CHANGED
@@ -9,79 +9,25 @@ import { clearOwnerState, isOwnerAddress, markOwnerAddress, setCurrentTurnIsOwne
9
9
  import { setCurrentTurnSender } from "./turn-context.js";
10
10
  import { checkForUpdate } from "./update-check.js";
11
11
  const dbg = createDebug("agent-network:channel");
12
- // Cross-channel identity notification: once per startAccount lifecycle.
13
- // Reset on startAccount(). isIdentityLinksConfigured() provides the
14
- // cross-restart idempotency (checks config file).
15
12
  let notificationAttempted = false;
16
- // Identity linking nudge — set when the owner first visits via Passport and
17
- // cross-channel linking is available. Delivered on the owner's next
18
- // non-Passport turn (Telegram/Feishu) where the linking action is relevant.
19
- // Separate from ownerNotesQueue to avoid the Passport drain deadlock (#1158):
20
- // the queue drains on ALL owner turns (including Passport), but this nudge
21
- // only fires on non-Passport owner turns.
22
13
  let identityLinkingNudgePending = false;
23
- // Owner's Passport address: recorded on first is_owner MESSAGE_RECEIVED.
24
- // Used by masons_link_identity tool to auto-include the Passport entry.
25
14
  let storedOwnerPassportAddress = null;
26
- /** Get the stored owner Passport address (first is_owner visit). */
27
15
  export function getOwnerPassportAddress() {
28
16
  return storedOwnerPassportAddress;
29
17
  }
30
- /**
31
- * Consume the identity linking nudge flag. Destructive read — returns true
32
- * at most once per detection cycle. Called by before_prompt_build on
33
- * non-Passport owner turns to deliver the nudge where the action is relevant.
34
- */
35
18
  export function consumeIdentityLinkingNudge() {
36
19
  if (!identityLinkingNudgePending)
37
20
  return false;
38
21
  identityLinkingNudgePending = false;
39
22
  return true;
40
23
  }
41
- /** Test-only: set the nudge flag without going through the detection path. */
42
24
  export function _setNudgePendingForTesting(value) {
43
25
  identityLinkingNudgePending = value;
44
26
  }
45
- // --- Sender identity ---
46
- /**
47
- * Project a NodeRef view from `MESSAGE_RECEIVED.metadata.sender` when the
48
- * Connector has projected a NodeRef onto the inbound envelope (Full Node
49
- * sender path per `docs/concepts/human-node-capability-obligations.md § 2`
50
- * + `apps/connector/src/routes/root.ts` § Piece 2 projection).
51
- *
52
- * Wire shape (the Connector's `metadata.sender = senderNodeRef` projection):
53
- * ```
54
- * metadata: {
55
- * visitor_name?: string; // legacy back-compat
56
- * is_owner?: boolean; // legacy back-compat
57
- * client_type?: string; // legacy back-compat
58
- * sender?: { // NEW under (b) Full Node
59
- * kind: string;
60
- * mstpAddress: string;
61
- * handle?: string;
62
- * displayName?: string;
63
- * avatarUrl?: string;
64
- * };
65
- * }
66
- * ```
67
- *
68
- * Returns the NodeRef view when `metadata.sender` is an object with
69
- * `kind` and `mstpAddress` both string. Returns null otherwise — the
70
- * caller falls back to the Client-side metadata shape (`visitor_name`,
71
- * `is_owner`, `client_type`).
72
- *
73
- * Per `human-node-capability-obligations.md § 5`, consumers MUST accept
74
- * future `kind` values (e.g., `"team"`); this projector treats `kind` as
75
- * opaque and surfaces the value as-is.
76
- */
77
27
  function tryProjectNodeRef(metadata) {
78
28
  if (!metadata)
79
29
  return null;
80
30
  const sender = metadata.sender;
81
- // Defensive: reject non-objects, null, and arrays. `typeof [] === "object"`
82
- // and `[] !== null`, so an array would otherwise pass the next guard and
83
- // produce undefined when indexed by `kind` / `mstpAddress`. Explicit
84
- // rejection makes the contract self-documenting.
85
31
  if (typeof sender !== "object" || sender === null || Array.isArray(sender))
86
32
  return null;
87
33
  const senderObj = sender;
@@ -96,36 +42,13 @@ function tryProjectNodeRef(metadata) {
96
42
  const avatarUrl = typeof senderObj.avatarUrl === "string" ? senderObj.avatarUrl : undefined;
97
43
  return { kind, mstpAddress, handle, displayName, avatarUrl };
98
44
  }
99
- /**
100
- * Derive the sender display name for the visitor / Identified-Client /
101
- * anonymous path (no NodeRef projection on metadata).
102
- *
103
- * Resolution order:
104
- * 1. `metadata.visitor_name` — display name for Passport browser visitors
105
- * 2. `event.from` — extract handle from routable address
106
- */
107
45
  function deriveSenderName(event) {
108
- // Account-level identity: Passport visitor with resolved display name
109
46
  const visitorName = event.metadata?.visitor_name;
110
47
  if (visitorName && typeof visitorName === "string") {
111
48
  return visitorName;
112
49
  }
113
- // Extract handle from `from` address
114
50
  return extractHandleFromAddress(event.from);
115
51
  }
116
- /**
117
- * Derive the sender display name for the Full Node sender path. Walks the
118
- * fallback chain `displayName → handle → mstpAddress`-derived handle per
119
- * `docs/concepts/human-node-capability-obligations.md § 2`.
120
- *
121
- * Note: the spec's terminal fallback is `mstpAddress` itself. This
122
- * implementation uses `extractHandleFromAddress(fromAddress)` instead —
123
- * the `from` field is already a routable address (the same one
124
- * `mstpAddress` would parse to a handle from), and a parsed handle is
125
- * higher-fidelity for display than the full URI. When `nodeRef.handle`
126
- * is absent and `from` does not parse to a handle, both forms degrade
127
- * equivalently to "unknown"-style strings.
128
- */
129
52
  function deriveNodeName(nodeRef, fromAddress) {
130
53
  if (nodeRef.displayName)
131
54
  return nodeRef.displayName;
@@ -133,28 +56,20 @@ function deriveNodeName(nodeRef, fromAddress) {
133
56
  return nodeRef.handle;
134
57
  return extractHandleFromAddress(fromAddress);
135
58
  }
136
- /**
137
- * Extract the Connector host from a connectorUrl.
138
- * `wss://preview.masons.ai/gw` -> `preview.masons.ai`
139
- */
140
59
  function extractConnectorHost(connectorUrl) {
141
60
  try {
142
61
  const url = new URL(connectorUrl);
143
62
  return url.hostname;
144
63
  }
145
64
  catch {
146
- // Fallback: strip protocol and path
147
65
  return connectorUrl.replace(/^wss?:\/\//, "").replace(/\/.*$/, "");
148
66
  }
149
67
  }
150
- // --- Duplicate message protection for at-least-once delivery ---
151
- // Short-window dedup: stored messages re-delivered on reconnect are
152
- // suppressed if the same (from, content, sentAt) was seen within 60 seconds.
153
68
  const DEDUP_WINDOW_MS = 60_000;
154
- const recentMessages = new Map(); // key → timestamp
69
+ const recentMessages = new Map();
155
70
  function isDuplicate(from, content, sentAt) {
156
71
  if (!sentAt)
157
- return false; // only dedup stored messages (have sentAt)
72
+ return false;
158
73
  const key = `${from}\0${content}\0${sentAt}`;
159
74
  const now = Date.now();
160
75
  const seen = recentMessages.get(key);
@@ -162,7 +77,6 @@ function isDuplicate(from, content, sentAt) {
162
77
  return true;
163
78
  }
164
79
  recentMessages.set(key, now);
165
- // Lazy cleanup: remove expired entries when map grows large
166
80
  if (recentMessages.size > 200) {
167
81
  for (const [k, ts] of recentMessages) {
168
82
  if (now - ts > DEDUP_WINDOW_MS)
@@ -171,58 +85,25 @@ function isDuplicate(from, content, sentAt) {
171
85
  }
172
86
  return false;
173
87
  }
174
- // --- Message dispatch helpers ---
175
- /**
176
- * Handle an address-based MESSAGE_RECEIVED { from, content, metadata }.
177
- * This is the primary path for the address-based protocol.
178
- */
179
88
  async function handleAddressedMessage(event, conversationManager, client, ctx) {
180
89
  const fromAddress = event.from;
181
90
  dbg("routing inbound message from=%s contentLength=%d", fromAddress, event.content.length);
182
- // Duplicate protection for at-least-once re-delivery (stored messages).
183
91
  if (isDuplicate(fromAddress, event.content, event.sentAt)) {
184
92
  dbg("duplicate message suppressed from=%s sentAt=%s", fromAddress, event.sentAt);
185
93
  return;
186
94
  }
187
- // Sender shape disambiguation per `docs/openclaw/program-demo-runbook.md § 4.2`:
188
- // - Full Node sender (Node ↔ Node): `metadata.sender` is a NodeRef
189
- // (`kind`, `mstpAddress`, optional `handle` / `displayName` /
190
- // `avatarUrl`) per `docs/concepts/human-node-capability-obligations.md
191
- // § 2` + Connector Piece 2 projection at
192
- // `apps/connector/src/routes/root.ts`.
193
- // Right-Fix lock per #1455 issuecomment-4354081096: route via standard
194
- // Node-peer path; do NOT consult `metadata.is_owner`. `is_owner` is an
195
- // ownership signal, not a routing signal — owner-self-chat walks the
196
- // same wire as stranger-chat.
197
- // - Visitor / Identified Client / Anonymous (Client → Node):
198
- // `metadata.sender` is absent; only `visitor_name`, `is_owner`,
199
- // `client_type` per
200
- // `docs/concepts/client-to-node-capability-obligations.md § 2`.
201
- // Existing visitor-mode owner-routing applies.
202
95
  const nodeRef = tryProjectNodeRef(event.metadata);
203
96
  if (nodeRef) {
204
- // Full Node sender — standard Node-peer path. Skip is_owner consultation,
205
- // owner-address marking, and the identity-linking nudge (those all key off
206
- // the visitor-mode owner concept).
207
97
  setCurrentTurnIsOwner(false);
208
98
  dbg("Full Node sender: kind=%s mstpAddress=%s handle=%s", nodeRef.kind, nodeRef.mstpAddress, nodeRef.handle ?? "(absent)");
209
99
  }
210
100
  else {
211
- // Visitor-mode path — preserved behavior.
212
- // Owner detection: first-message-sets, subsequent-inherits.
213
- // Connector includes is_owner in metadata for Passport visitors.
214
101
  if (event.metadata?.is_owner === true) {
215
102
  markOwnerAddress(fromAddress);
216
- // Record Passport address for tool auto-include (first visit only)
217
103
  if (!storedOwnerPassportAddress) {
218
104
  storedOwnerPassportAddress = fromAddress;
219
105
  dbg("recorded owner Passport address: %s", fromAddress);
220
106
  }
221
- // --- dmScope-aware identity linking nudge (#986 redesign, #1158 fix) ---
222
- // Detect that identity linking is available but not configured.
223
- // Sets a flag (NOT enqueued into ownerNotesQueue) for delivery on the
224
- // owner's next non-Passport turn, where the linking action is relevant.
225
- // Separated from the queue to avoid the Passport drain deadlock (#1158).
226
107
  if (getDmScope() !== "main" &&
227
108
  !isIdentityLinksConfigured() &&
228
109
  !notificationAttempted) {
@@ -233,7 +114,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
233
114
  }
234
115
  setCurrentTurnIsOwner(isOwnerAddress(fromAddress));
235
116
  }
236
- // Resolve contact from address. Register inbound conversation if new.
237
117
  const contact = nodeRef
238
118
  ? deriveNodeName(nodeRef, fromAddress)
239
119
  : deriveSenderName(event);
@@ -241,7 +121,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
241
121
  conversationManager.registerInbound(contact, fromAddress);
242
122
  }
243
123
  setCurrentTurnSender(conversationManager.getContactByAddress(fromAddress) ?? null);
244
- // Runtime guard
245
124
  let runtime;
246
125
  try {
247
126
  runtime = requirePluginRuntime();
@@ -254,7 +133,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
254
133
  dbg("channelRuntime not available, dropping message from=%s", fromAddress);
255
134
  return;
256
135
  }
257
- // senderId for OpenClaw routing: use the routable address
258
136
  const senderId = fromAddress;
259
137
  const senderName = contact;
260
138
  try {
@@ -297,7 +175,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
297
175
  console.error(`[agent-network:${ctx.accountId}] session record error:`, err);
298
176
  },
299
177
  });
300
- // Typing: address-based
301
178
  client.sendTyping(fromAddress, true);
302
179
  try {
303
180
  await runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
@@ -323,9 +200,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
323
200
  }
324
201
  finally {
325
202
  client.sendTyping(fromAddress, false);
326
- // Commit deferred deletions from end_conversation calls made during
327
- // this dispatch cycle. Must run after text buffer flush so that
328
- // hasConversation() returns true for the deliver callback (#999).
329
203
  conversationManager.commitEndedConversations();
330
204
  }
331
205
  }
@@ -334,7 +208,6 @@ async function handleAddressedMessage(event, conversationManager, client, ctx) {
334
208
  }
335
209
  }
336
210
  const accounts = new Map();
337
- // --- Channel Plugin ---
338
211
  export const agentNetworkChannel = {
339
212
  id: "agent-network",
340
213
  meta: {
@@ -349,9 +222,6 @@ export const agentNetworkChannel = {
349
222
  attachments: false,
350
223
  },
351
224
  config: {
352
- // Always return ["default"] — matches community convention (Telegram,
353
- // Slack, Feishu all do this). Gateway uses isConfigured() to decide
354
- // whether to start the account, not the presence of account IDs.
355
225
  listAccountIds() {
356
226
  return ["default"];
357
227
  },
@@ -378,9 +248,6 @@ export const agentNetworkChannel = {
378
248
  token: account.token,
379
249
  };
380
250
  },
381
- // Gateway calls this after resolveAccount(). Return false when
382
- // credentials are missing — Gateway marks the channel as "unmanaged"
383
- // and skips health checks + startAccount().
384
251
  isConfigured(account) {
385
252
  return account.connectorUrl !== "" && account.token !== "";
386
253
  },
@@ -392,8 +259,6 @@ export const agentNetworkChannel = {
392
259
  outbound: {
393
260
  deliveryMode: "direct",
394
261
  async sendText(ctx) {
395
- // ctx.to is the routable address (senderId from inbound dispatch).
396
- // ConversationManager.send() handles address resolution transparently.
397
262
  const state = accounts.get(ctx.accountId);
398
263
  if (!state)
399
264
  return { channel: "agent-network", messageId: "" };
@@ -408,14 +273,9 @@ export const agentNetworkChannel = {
408
273
  gateway: {
409
274
  async startAccount(ctx) {
410
275
  dbg("starting account %s", ctx.accountId);
411
- // Reset per-session state
412
276
  notificationAttempted = false;
413
277
  identityLinkingNudgePending = false;
414
278
  storedOwnerPassportAddress = null;
415
- // Defensive: clear stale singletons from a previous cycle.
416
- // The abort handler intentionally leaves them alive for in-flight tool
417
- // calls (#935). Clean up here at cycle start so initConnectorClient()
418
- // doesn't throw its double-init guard.
419
279
  clearConversationManager();
420
280
  clearConnectorClient();
421
281
  const { connectorUrl, token } = ctx.account;
@@ -427,64 +287,33 @@ export const agentNetworkChannel = {
427
287
  conversationManager,
428
288
  };
429
289
  accounts.set(ctx.accountId, state);
430
- // --- Inbound message routing (4-step channelRuntime dispatch) ---
431
- // Replaces the non-existent routeMessage() API. Uses PluginRuntime
432
- // captured in register() via config.ts module-level singleton.
433
- // Reference: DingTalk plugin (github.com/soimy/openclaw-channel-dingtalk).
434
- //
435
- // Concurrency model: this handler is async but EventEmitter fires it
436
- // synchronously per event. Multiple MESSAGE_RECEIVED on the same session
437
- // produce concurrent dispatches — replies may arrive out of order.
438
- // Acceptable for unstructured text conversation (Phase 1). If MSTP adds
439
- // structured multi-step interactions, add a per-session dispatch queue.
440
290
  client.on("message_received", async (event) => {
441
291
  if (!("from" in event))
442
- return; // address-based only
292
+ return;
443
293
  await handleAddressedMessage(event, conversationManager, client, ctx);
444
294
  });
445
- // --- Delivery ACK ---
446
- // ACK immediately on DELIVERY_PENDING — tells Connector it's safe
447
- // to delete delivered stored messages.
448
295
  client.on("delivery_pending", (event) => {
449
296
  client.ackDelivery(event.upTo);
450
297
  dbg("delivery_pending → ACK sent count=%d upTo=%s", event.count, event.upTo);
451
298
  });
452
- // --- Disconnect ---
453
- // On disconnect, all session state is invalid — clear owner + environment.
454
299
  client.on("disconnected", () => {
455
300
  clearOwnerState();
456
301
  clearEnvironmentContext();
457
302
  });
458
- // --- Error handling ---
459
- // Must register before connect() — unhandled "error" events crash the process.
460
303
  client.on("error", (err) => {
461
304
  console.error(`[agent-network:${ctx.accountId}]`, err.message);
462
305
  });
463
- // --- Abort signal ---
464
- // Do NOT clear ConversationManager or ConnectorClient here.
465
- // In-flight LLM dispatches may still be running — tools that call
466
- // requireConversationManager() would throw "Not connected" and trigger
467
- // LLM confidence collapse (#935). Instead, let the stale CM survive:
468
- // the disconnected WebSocket causes tools to graceful-fail ("Failed to
469
- // send message") rather than throw. stopAccount() handles final cleanup.
470
306
  ctx.abortSignal.addEventListener("abort", () => {
471
307
  client.disconnect();
472
308
  }, { once: true });
473
- // --- Inject config for LLM tools ---
474
309
  initToolConfig(ctx.cfg);
475
- // --- Check for plugin updates (non-blocking) ---
476
310
  const networkCfg = extractNetworkConfig(ctx.cfg);
477
311
  const updateCheckEnabled = networkCfg?.updateCheck !== false;
478
312
  checkForUpdate(updateCheckEnabled).catch(() => { });
479
- // --- Connect ---
480
313
  await client.connect();
481
314
  dbg("connected account=%s", ctx.accountId);
482
- // --- Expose client and conversation manager to tools (only after WS is connected) ---
483
315
  initConnectorClient(client);
484
316
  initConversationManager(conversationManager);
485
- // Park the Promise — DO NOT resolve/return.
486
- // Resolution signals "account stopped" to OpenClaw's orchestrator,
487
- // triggering auto-restart with exponential backoff (crash-loop).
488
317
  await new Promise((resolve) => {
489
318
  if (ctx.abortSignal.aborted) {
490
319
  resolve();
@@ -1,65 +1,3 @@
1
- /**
2
- * CLI Login Path — Stripe-style browser-mediated loopback handoff.
3
- *
4
- * Implements `login()` hook for OpenClaw's 2026.4.x channel-plugin contract:
5
- * api.registerChannel({ plugin: { ..., auth: { login } } })
6
- *
7
- * Invoked by `openclaw channels login --channel agent-network`. CLI dispatch
8
- * at `dist/channels-cli-Cc40S0aS.js:85` reads `plugin.auth?.login` and throws
9
- * `"Channel ... does not support login"` if absent. See WhatsApp + Feishu
10
- * bundled extensions for reference implementations of the same contract.
11
- *
12
- * Flow (W4 PR 3 — `loopbackHandoffFlow`):
13
- *
14
- * 1. Bind a one-shot HTTP listener on `127.0.0.1:0` (OS-assigned ephemeral
15
- * port). The listener serves a single `POST /handoff` plus the matching
16
- * CORS preflight, then closes.
17
- * 2. Generate a 24-byte (32-char base64url) URL-safe random nonce. The
18
- * nonce travels in the URL fragment (`#nonce=…`), never the query
19
- * string — fragments do not reach `apps/web` access logs nor referer
20
- * headers (Alt W4-B2 lock).
21
- * 3. Open the user's browser to the handoff URL (no-handle path uses
22
- * `${idpBaseUrl}/console/handoff?port=<port>#nonce=<nonce>`; with
23
- * `--handle` the per-handle deep-link variant is the entry).
24
- * 4. The user authenticates against Better Auth on `apps/web`, picks (or
25
- * creates) an agent, and the page POSTs `{token, agent, key, nonce}`
26
- * to the listener. The listener verifies the body's `nonce` matches
27
- * the value it placed in the fragment, accepts the token, and closes.
28
- * 5. Persist `{connectorUrl, token}` to `openclaw.json` via
29
- * `writeCredentials()`. `connectorUrl` is derived from `apiHost`
30
- * (`wss://<apiHost>/gateway`) for cloud / preview deployments; self-
31
- * hosted users keep an explicit `connectorUrl` in their `openclaw.json`
32
- * and the legacy value is preserved across the handoff (see
33
- * `loadExistingConnectorUrl()`).
34
- *
35
- * Why move off device flow:
36
- *
37
- * - One step shorter (no `user_code` to type into the browser).
38
- * - No periodic IdP polling (was 5s default, 5+s on `slow_down`).
39
- * - Browser remains fully authenticated across login and key issuance —
40
- * same Better Auth session is reused, so the user never re-types their
41
- * password mid-flow.
42
- * - The runtime API key carrier (`masons_rt_…`) replaces the legacy
43
- * connector-minted `sk-…` carrier; W4 PR 1 substrate plus the connector
44
- * mirror wiring earlier in this PR make both carriers verifiable through
45
- * plugin v0.5.13's life until the W6 cleanup retires the legacy path.
46
- *
47
- * The legacy device-flow helpers (`deviceCodeFlow`, `pollUntilAuthorized`,
48
- * `agentSetup`, `createAgentLoop`) remain in this file as
49
- * `@deprecated` references for the W6 cleanup window. They have no call
50
- * site after the migration and should not be invoked by any new code.
51
- *
52
- * See #1264 for original design rationale (single-driver Node semantic —
53
- * re-running this flow rotates the runtime key and evicts any previously-
54
- * connected Runtime); see the W4 strategic-pass at
55
- * `#1466 issuecomment-4362892782` for the loopback handoff lock.
56
- */
57
- /**
58
- * Minimal OpenClaw runtime surface passed to `auth.login`. Exposed as
59
- * `defaultRuntime` in `openclaw/dist/runtime-Dx7oeLYq.js` — plugins get
60
- * only the output/exit channel, not a prompter (plugins build their own
61
- * via @clack/prompts, which is what OpenClaw CLI uses internally too).
62
- */
63
1
  interface OpenClawRuntime {
64
2
  log(...args: unknown[]): void;
65
3
  error(...args: unknown[]): void;
@@ -67,11 +5,6 @@ interface OpenClawRuntime {
67
5
  writeJson(value: unknown, space?: number): void;
68
6
  exit(code: number): void;
69
7
  }
70
- /**
71
- * Context passed by OpenClaw CLI to `plugin.auth.login`. Matches the call
72
- * site at `dist/channels-cli-Cc40S0aS.js:89`:
73
- * await login({ cfg, accountId, runtime, verbose, channelInput });
74
- */
75
8
  interface AuthLoginContext {
76
9
  cfg: Record<string, unknown>;
77
10
  accountId?: string;
@@ -79,32 +12,6 @@ interface AuthLoginContext {
79
12
  verbose?: boolean;
80
13
  channelInput?: string;
81
14
  }
82
- /**
83
- * Channel login hook — invoked by `openclaw channels login --channel agent-network`.
84
- *
85
- * Unlike the legacy `configureInteractive` contract (which returned a config
86
- * object for the CLI to persist), the 2026.4.x `auth.login` contract returns
87
- * void and expects the plugin to persist any config changes itself. We use
88
- * `writeCredentials()` in config.ts, which writes `openclaw.json` atomically
89
- * and bumps the state-cache generation so Layer B's dynamic context re-reads
90
- * on the next turn.
91
- *
92
- * Flow (W4 PR 3):
93
- * 1. Run `loopbackHandoffFlow` against `apps/web` — a Stripe-style
94
- * browser-mediated runtime-key issuance that delivers the plaintext
95
- * `masons_rt_…` token to a one-shot loopback listener bound at
96
- * `127.0.0.1:0` with a fragment-nonce cross-origin discipline.
97
- * 2. Resolve the connector URL — preserve any user-set
98
- * `accounts.default.connectorUrl` from `openclaw.json` (for self-
99
- * hosted topologies); fall back to the cloud derivation
100
- * `wss://<apiHost>/gateway` matching the connector's
101
- * `CONNECTOR_PLUGIN_URL` env default.
102
- * 3. Persist `{connectorUrl, token}` atomically.
103
- *
104
- * Errors during the handoff are surfaced via `ctx.runtime.error` (not
105
- * thrown) so OpenClaw CLI doesn't display a stack trace — matches the
106
- * WhatsApp/Feishu pattern.
107
- */
108
15
  export declare function login(ctx: AuthLoginContext): Promise<void>;
109
16
  export {};
110
17
  //# sourceMappingURL=cli-setup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"cli-setup.d.ts","sourceRoot":"","sources":["../src/cli-setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AA2CH;;;;;GAKG;AACH,UAAU,eAAe;IACvB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;GAIG;AACH,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAw2BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAuDhE"}
1
+ {"version":3,"file":"cli-setup.d.ts","sourceRoot":"","sources":["../src/cli-setup.ts"],"names":[],"mappings":"AAqFA,UAAU,eAAe;IACvB,GAAG,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAC9B,KAAK,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;IAChC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAOD,UAAU,gBAAgB;IACxB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,eAAe,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAyWD,wBAAsB,KAAK,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqDhE"}