@aria-cli/tools 1.0.12 → 1.0.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/dist/index.js +378 -70
  2. package/dist/network-runtime/index.js +8 -12
  3. package/dist-cjs/index.js +400 -435
  4. package/dist-cjs/network-runtime/index.js +8 -172
  5. package/package.json +8 -6
  6. package/dist/.tsbuildinfo +0 -1
  7. package/dist/ask-user-interaction.js +0 -22
  8. package/dist/cache/web-cache.js +0 -66
  9. package/dist/definitions/arion.js +0 -104
  10. package/dist/definitions/browser/browser.js +0 -418
  11. package/dist/definitions/browser/index.js +0 -4
  12. package/dist/definitions/browser/pw-downloads.js +0 -114
  13. package/dist/definitions/browser/pw-interactions.js +0 -199
  14. package/dist/definitions/browser/pw-responses.js +0 -76
  15. package/dist/definitions/browser/pw-session.js +0 -310
  16. package/dist/definitions/browser/pw-shared.js +0 -66
  17. package/dist/definitions/browser/pw-snapshot.js +0 -301
  18. package/dist/definitions/browser/pw-state.js +0 -62
  19. package/dist/definitions/browser/types.js +0 -4
  20. package/dist/definitions/code-intelligence.js +0 -470
  21. package/dist/definitions/core.js +0 -109
  22. package/dist/definitions/delegation.js +0 -512
  23. package/dist/definitions/deploy.js +0 -65
  24. package/dist/definitions/filesystem.js +0 -196
  25. package/dist/definitions/frg.js +0 -63
  26. package/dist/definitions/index.js +0 -20
  27. package/dist/definitions/memory.js +0 -123
  28. package/dist/definitions/messaging.js +0 -625
  29. package/dist/definitions/meta.js +0 -349
  30. package/dist/definitions/network.js +0 -159
  31. package/dist/definitions/outlook.js +0 -277
  32. package/dist/definitions/patch/apply-patch.js +0 -184
  33. package/dist/definitions/patch/fuzzy-match.js +0 -166
  34. package/dist/definitions/patch/index.js +0 -1
  35. package/dist/definitions/patch/patch-parser.js +0 -207
  36. package/dist/definitions/patch/sandbox-paths.js +0 -105
  37. package/dist/definitions/process/index.js +0 -4
  38. package/dist/definitions/process/process-registry.js +0 -213
  39. package/dist/definitions/process/process.js +0 -386
  40. package/dist/definitions/process/pty-keys.js +0 -254
  41. package/dist/definitions/process/session-slug.js +0 -142
  42. package/dist/definitions/quip.js +0 -195
  43. package/dist/definitions/search.js +0 -60
  44. package/dist/definitions/session-history.js +0 -69
  45. package/dist/definitions/shell.js +0 -181
  46. package/dist/definitions/slack.js +0 -180
  47. package/dist/definitions/web.js +0 -109
  48. package/dist/executors/apply-patch.js +0 -901
  49. package/dist/executors/arion.js +0 -119
  50. package/dist/executors/code-intelligence.js +0 -882
  51. package/dist/executors/deploy.js +0 -848
  52. package/dist/executors/filesystem.js +0 -1122
  53. package/dist/executors/frg-freshness.js +0 -576
  54. package/dist/executors/frg.js +0 -298
  55. package/dist/executors/index.js +0 -46
  56. package/dist/executors/learning-meta.js +0 -1146
  57. package/dist/executors/lsp-client.js +0 -296
  58. package/dist/executors/memory.js +0 -750
  59. package/dist/executors/meta.js +0 -220
  60. package/dist/executors/process-registry.js +0 -465
  61. package/dist/executors/pty-session-store.js +0 -30
  62. package/dist/executors/pty.js +0 -271
  63. package/dist/executors/restart.js +0 -119
  64. package/dist/executors/search-freshness.js +0 -195
  65. package/dist/executors/search-types.js +0 -52
  66. package/dist/executors/search.js +0 -66
  67. package/dist/executors/self-diagnose.js +0 -398
  68. package/dist/executors/session-history.js +0 -283
  69. package/dist/executors/shell-safety.js +0 -473
  70. package/dist/executors/shell.js +0 -954
  71. package/dist/executors/utils.js +0 -33
  72. package/dist/executors/web.js +0 -542
  73. package/dist/extraction/content-extraction.js +0 -235
  74. package/dist/extraction/index.js +0 -4
  75. package/dist/headless-control-contract.js +0 -967
  76. package/dist/local-control-http-auth.js +0 -2
  77. package/dist/mcp/client.js +0 -181
  78. package/dist/mcp/connection.js +0 -480
  79. package/dist/mcp/index.js +0 -10
  80. package/dist/mcp/jsonrpc.js +0 -144
  81. package/dist/mcp/types.js +0 -7
  82. package/dist/network-control-adapter.js +0 -72
  83. package/dist/network-runtime/address-types.js +0 -165
  84. package/dist/network-runtime/db-owner-fencing.js +0 -69
  85. package/dist/network-runtime/delivery-receipts.js +0 -267
  86. package/dist/network-runtime/direct-endpoint-authority.js +0 -25
  87. package/dist/network-runtime/local-control-contract.js +0 -627
  88. package/dist/network-runtime/node-store-contract.js +0 -34
  89. package/dist/network-runtime/pair-route-contract.js +0 -77
  90. package/dist/network-runtime/peer-capabilities.js +0 -28
  91. package/dist/network-runtime/peer-principal-ref.js +0 -12
  92. package/dist/network-runtime/peer-state-machine.js +0 -121
  93. package/dist/network-runtime/protocol-schemas.js +0 -205
  94. package/dist/network-runtime/runtime-bootstrap-contract.js +0 -60
  95. package/dist/outlook/desktop-session.js +0 -279
  96. package/dist/policy.js +0 -149
  97. package/dist/providers/brave.js +0 -62
  98. package/dist/providers/duckduckgo.js +0 -176
  99. package/dist/providers/exa.js +0 -63
  100. package/dist/providers/firecrawl.js +0 -55
  101. package/dist/providers/index.js +0 -7
  102. package/dist/providers/jina.js +0 -49
  103. package/dist/providers/router.js +0 -96
  104. package/dist/providers/search-provider.js +0 -32
  105. package/dist/providers/tavily.js +0 -54
  106. package/dist/quip/desktop-session.js +0 -317
  107. package/dist/registry/index.js +0 -1
  108. package/dist/registry/registry.js +0 -756
  109. package/dist/runtime-socket-local-control-client.js +0 -330
  110. package/dist/security/dns-normalization.js +0 -19
  111. package/dist/security/dns-pinning.js +0 -123
  112. package/dist/security/external-content.js +0 -91
  113. package/dist/security/ssrf.js +0 -181
  114. package/dist/slack/desktop-session.js +0 -324
  115. package/dist/tool-factory.js +0 -47
  116. package/dist/types.js +0 -7
  117. package/dist/utils/retry.js +0 -132
  118. package/dist/utils/safe-parse-json.js +0 -160
  119. package/dist/utils/url.js +0 -19
  120. package/dist-cjs/.tsbuildinfo +0 -1
  121. package/dist-cjs/ask-user-interaction.js +0 -27
  122. package/dist-cjs/cache/web-cache.js +0 -70
  123. package/dist-cjs/definitions/arion.js +0 -107
  124. package/dist-cjs/definitions/browser/browser.js +0 -421
  125. package/dist-cjs/definitions/browser/index.js +0 -8
  126. package/dist-cjs/definitions/browser/pw-downloads.js +0 -117
  127. package/dist-cjs/definitions/browser/pw-interactions.js +0 -213
  128. package/dist-cjs/definitions/browser/pw-responses.js +0 -84
  129. package/dist-cjs/definitions/browser/pw-session.js +0 -326
  130. package/dist-cjs/definitions/browser/pw-shared.js +0 -72
  131. package/dist-cjs/definitions/browser/pw-snapshot.js +0 -307
  132. package/dist-cjs/definitions/browser/pw-state.js +0 -70
  133. package/dist-cjs/definitions/browser/types.js +0 -5
  134. package/dist-cjs/definitions/code-intelligence.js +0 -473
  135. package/dist-cjs/definitions/core.js +0 -133
  136. package/dist-cjs/definitions/delegation.js +0 -515
  137. package/dist-cjs/definitions/deploy.js +0 -68
  138. package/dist-cjs/definitions/filesystem.js +0 -199
  139. package/dist-cjs/definitions/frg.js +0 -66
  140. package/dist-cjs/definitions/index.js +0 -43
  141. package/dist-cjs/definitions/memory.js +0 -126
  142. package/dist-cjs/definitions/messaging.js +0 -631
  143. package/dist-cjs/definitions/meta.js +0 -352
  144. package/dist-cjs/definitions/network.js +0 -162
  145. package/dist-cjs/definitions/outlook.js +0 -280
  146. package/dist-cjs/definitions/patch/apply-patch.js +0 -191
  147. package/dist-cjs/definitions/patch/fuzzy-match.js +0 -172
  148. package/dist-cjs/definitions/patch/index.js +0 -5
  149. package/dist-cjs/definitions/patch/patch-parser.js +0 -215
  150. package/dist-cjs/definitions/patch/sandbox-paths.js +0 -113
  151. package/dist-cjs/definitions/process/index.js +0 -8
  152. package/dist-cjs/definitions/process/process-registry.js +0 -231
  153. package/dist-cjs/definitions/process/process.js +0 -389
  154. package/dist-cjs/definitions/process/pty-keys.js +0 -259
  155. package/dist-cjs/definitions/process/session-slug.js +0 -145
  156. package/dist-cjs/definitions/quip.js +0 -198
  157. package/dist-cjs/definitions/search.js +0 -63
  158. package/dist-cjs/definitions/session-history.js +0 -72
  159. package/dist-cjs/definitions/shell.js +0 -184
  160. package/dist-cjs/definitions/slack.js +0 -183
  161. package/dist-cjs/definitions/web.js +0 -112
  162. package/dist-cjs/executors/apply-patch.js +0 -938
  163. package/dist-cjs/executors/arion.js +0 -125
  164. package/dist-cjs/executors/code-intelligence.js +0 -925
  165. package/dist-cjs/executors/deploy.js +0 -869
  166. package/dist-cjs/executors/filesystem.js +0 -1167
  167. package/dist-cjs/executors/frg-freshness.js +0 -627
  168. package/dist-cjs/executors/frg.js +0 -334
  169. package/dist-cjs/executors/index.js +0 -143
  170. package/dist-cjs/executors/learning-meta.js +0 -1165
  171. package/dist-cjs/executors/lsp-client.js +0 -310
  172. package/dist-cjs/executors/memory.js +0 -796
  173. package/dist-cjs/executors/meta.js +0 -226
  174. package/dist-cjs/executors/process-registry.js +0 -469
  175. package/dist-cjs/executors/pty-session-store.js +0 -34
  176. package/dist-cjs/executors/pty.js +0 -312
  177. package/dist-cjs/executors/restart.js +0 -155
  178. package/dist-cjs/executors/search-freshness.js +0 -234
  179. package/dist-cjs/executors/search-types.js +0 -56
  180. package/dist-cjs/executors/search.js +0 -102
  181. package/dist-cjs/executors/self-diagnose.js +0 -434
  182. package/dist-cjs/executors/session-history.js +0 -320
  183. package/dist-cjs/executors/shell-safety.js +0 -478
  184. package/dist-cjs/executors/shell.js +0 -1001
  185. package/dist-cjs/executors/utils.js +0 -73
  186. package/dist-cjs/executors/web.js +0 -547
  187. package/dist-cjs/extraction/content-extraction.js +0 -243
  188. package/dist-cjs/extraction/index.js +0 -8
  189. package/dist-cjs/headless-control-contract.js +0 -972
  190. package/dist-cjs/local-control-http-auth.js +0 -5
  191. package/dist-cjs/mcp/client.js +0 -185
  192. package/dist-cjs/mcp/connection.js +0 -484
  193. package/dist-cjs/mcp/index.js +0 -30
  194. package/dist-cjs/mcp/jsonrpc.js +0 -148
  195. package/dist-cjs/mcp/types.js +0 -8
  196. package/dist-cjs/network-control-adapter.js +0 -77
  197. package/dist-cjs/network-runtime/address-types.js +0 -168
  198. package/dist-cjs/network-runtime/db-owner-fencing.js +0 -76
  199. package/dist-cjs/network-runtime/delivery-receipts.js +0 -276
  200. package/dist-cjs/network-runtime/direct-endpoint-authority.js +0 -29
  201. package/dist-cjs/network-runtime/local-control-contract.js +0 -633
  202. package/dist-cjs/network-runtime/node-store-contract.js +0 -38
  203. package/dist-cjs/network-runtime/pair-route-contract.js +0 -80
  204. package/dist-cjs/network-runtime/peer-capabilities.js +0 -37
  205. package/dist-cjs/network-runtime/peer-principal-ref.js +0 -15
  206. package/dist-cjs/network-runtime/peer-state-machine.js +0 -129
  207. package/dist-cjs/network-runtime/protocol-schemas.js +0 -212
  208. package/dist-cjs/network-runtime/runtime-bootstrap-contract.js +0 -63
  209. package/dist-cjs/outlook/desktop-session.js +0 -318
  210. package/dist-cjs/policy.js +0 -155
  211. package/dist-cjs/providers/brave.js +0 -66
  212. package/dist-cjs/providers/duckduckgo.js +0 -180
  213. package/dist-cjs/providers/exa.js +0 -67
  214. package/dist-cjs/providers/firecrawl.js +0 -59
  215. package/dist-cjs/providers/index.js +0 -17
  216. package/dist-cjs/providers/jina.js +0 -53
  217. package/dist-cjs/providers/router.js +0 -100
  218. package/dist-cjs/providers/search-provider.js +0 -36
  219. package/dist-cjs/providers/tavily.js +0 -58
  220. package/dist-cjs/quip/desktop-session.js +0 -353
  221. package/dist-cjs/registry/index.js +0 -6
  222. package/dist-cjs/registry/registry.js +0 -761
  223. package/dist-cjs/runtime-socket-local-control-client.js +0 -367
  224. package/dist-cjs/security/dns-normalization.js +0 -22
  225. package/dist-cjs/security/dns-pinning.js +0 -160
  226. package/dist-cjs/security/external-content.js +0 -95
  227. package/dist-cjs/security/ssrf.js +0 -221
  228. package/dist-cjs/slack/desktop-session.js +0 -366
  229. package/dist-cjs/tool-factory.js +0 -50
  230. package/dist-cjs/types.js +0 -8
  231. package/dist-cjs/utils/retry.js +0 -169
  232. package/dist-cjs/utils/safe-parse-json.js +0 -164
  233. package/dist-cjs/utils/url.js +0 -23
@@ -1,625 +0,0 @@
1
- /**
2
- * Messaging tool definitions
3
- *
4
- * Tools: send_message, check_messages, search_messages, get_thread (4 tools)
5
- *
6
- * Inter-agent messaging for arions, workers, and leaders.
7
- * All tools use context.messageStore (injected by runner when Memoria is available).
8
- * When the message store isn't wired, tools return a clear error.
9
- */
10
- import crypto from "node:crypto";
11
- import { z } from "zod";
12
- import { tool } from "../tool-factory.js";
13
- import { canonicalizeDeliveryReceipt, InboxAddressSchema } from "../network-runtime/index.js";
14
- const SENDER_INBOX_METADATA_KEY = "senderInbox";
15
- /**
16
- * Resolve the local inbox address from ToolContext.
17
- *
18
- * Throws instead of returning null — a missing inbox address is a wiring bug
19
- * (the entrypoint failed to set nodeId), not a user error. Silent message
20
- * drops are structurally impossible: tools either route correctly or crash loudly.
21
- */
22
- function resolveInboxAddress(context) {
23
- if (context.inboxAddress) {
24
- return context.inboxAddress;
25
- }
26
- if (context.nodeId) {
27
- return { kind: "node", nodeId: context.nodeId };
28
- }
29
- throw new Error("Inbox address not available: neither context.inboxAddress nor context.nodeId is set. " +
30
- "The entrypoint must wire nodeId into ToolContext (via RunOptions.nodeId or direct inboxAddress). " +
31
- "This is a wiring bug — check tool-executor.ts and RunSession.toRunOptions().");
32
- }
33
- /**
34
- * Resolve ALL inbox addresses the caller should see.
35
- *
36
- * When the runner is an attached client ({kind: "client", clientId}), remote
37
- * peer messages still land in the node inbox ({kind: "node", nodeId}). The TUI
38
- * status bar already polls both — this helper lets the read tools do the same
39
- * so the LLM sees everything the user sees.
40
- */
41
- function resolveAllInboxAddresses(context) {
42
- const primary = resolveInboxAddress(context);
43
- if (primary.kind === "client" && context.nodeId) {
44
- return [primary, { kind: "node", nodeId: context.nodeId }];
45
- }
46
- return [primary];
47
- }
48
- function resolveSenderIdentity(context, inboxAddress) {
49
- const senderType = context.arion
50
- ? "arion"
51
- : (context.senderType ?? "leader");
52
- if (context.arion) {
53
- return {
54
- id: context.arion.id,
55
- name: context.arion.name,
56
- type: senderType,
57
- };
58
- }
59
- return {
60
- id: context.nodeId ??
61
- (inboxAddress.kind === "client" ? inboxAddress.clientId : inboxAddress.nodeId),
62
- name: "ARIA",
63
- type: senderType,
64
- };
65
- }
66
- async function listAttachedClients(context) {
67
- return Promise.resolve(context.networkControl?.listAttachedClients?.() ?? []);
68
- }
69
- function buildUnknownRecipientError(context, recipientRef) {
70
- const localRecipientHint = context.manager
71
- ? "registered local mailbox id or arion name"
72
- : "registered local mailbox id or alias";
73
- const sameHomeHint = context.networkControl?.listAttachedClients
74
- ? "exact same-home clientId from list_clients"
75
- : "exact same-home clientId";
76
- return (`Unknown recipient "${recipientRef}". ` +
77
- `send_message requires an exact recipient identity: ${localRecipientHint}, exact remote nodeId, or ${sameHomeHint}.`);
78
- }
79
- async function resolveManagedLocalRecipient(context, recipientRef) {
80
- const manager = context.manager;
81
- if (!manager) {
82
- return null;
83
- }
84
- const [directByName, listed] = await Promise.all([
85
- manager.get(recipientRef).catch(() => null),
86
- manager.list().catch(() => []),
87
- ]);
88
- const exactMatch = directByName ??
89
- listed.find((candidate) => candidate.id === recipientRef || candidate.name === recipientRef) ??
90
- null;
91
- if (!exactMatch) {
92
- return null;
93
- }
94
- return {
95
- kind: "local",
96
- mailboxId: exactMatch.id,
97
- recipientName: exactMatch.name,
98
- };
99
- }
100
- function extractSenderInboxFromMetadata(metadata) {
101
- if (!metadata) {
102
- return undefined;
103
- }
104
- try {
105
- const parsed = JSON.parse(metadata);
106
- if (!(SENDER_INBOX_METADATA_KEY in parsed)) {
107
- return undefined;
108
- }
109
- return InboxAddressSchema.parse(parsed[SENDER_INBOX_METADATA_KEY]);
110
- }
111
- catch {
112
- return undefined;
113
- }
114
- }
115
- async function resolveRecipientFromReplyTarget(context, replyTo, inboxAddress) {
116
- if (typeof context.messageStore?.getMessageForInbox !== "function") {
117
- return {
118
- ok: false,
119
- error: "Reply routing is unavailable: the message store cannot resolve inbox-scoped message ids.",
120
- };
121
- }
122
- const original = context.messageStore.getMessageForInbox(inboxAddress, replyTo);
123
- if (!original) {
124
- return {
125
- ok: false,
126
- error: `Cannot reply to message "${replyTo}" because it is not present in the current inbox.`,
127
- };
128
- }
129
- const senderInbox = extractSenderInboxFromMetadata(original.metadata);
130
- if (senderInbox?.kind === "client") {
131
- return {
132
- ok: true,
133
- recipient: {
134
- kind: "client",
135
- clientId: senderInbox.clientId,
136
- recipientName: original.sender_name,
137
- self: inboxAddress.kind === "client" && senderInbox.clientId === inboxAddress.clientId,
138
- },
139
- };
140
- }
141
- return resolveRecipientIdentity(context, original.sender_id, inboxAddress);
142
- }
143
- async function resolveRecipientIdentity(context, recipientRef, inboxAddress) {
144
- const localMailbox = context.mailbox;
145
- const peers = context.networkControl?.listPeers() ?? [];
146
- const attachedClients = await listAttachedClients(context);
147
- const exactClient = attachedClients.find((client) => client.clientId === recipientRef);
148
- if (exactClient) {
149
- return {
150
- ok: true,
151
- recipient: {
152
- kind: "client",
153
- clientId: exactClient.clientId,
154
- recipientName: exactClient.displayLabel.trim() || exactClient.clientId,
155
- self: exactClient.self,
156
- },
157
- };
158
- }
159
- const exactPeer = peers.find((peer) => peer.nodeId === recipientRef);
160
- if (exactPeer) {
161
- if (exactPeer.routeOwnership === "superseded" ||
162
- exactPeer.deliveryReadiness === "cannot_address") {
163
- return {
164
- ok: false,
165
- error: `Peer "${recipientRef}" is not currently addressable` +
166
- (exactPeer.routeOwnership === "superseded"
167
- ? " because its direct route claim has been superseded."
168
- : "."),
169
- };
170
- }
171
- return {
172
- ok: true,
173
- recipient: {
174
- kind: "remote",
175
- nodeId: exactPeer.nodeId,
176
- recipientName: exactPeer.displayNameSnapshot ?? exactPeer.nodeId,
177
- },
178
- };
179
- }
180
- const hasLocalRecipientId = typeof localMailbox?.has === "function" && localMailbox.has(recipientRef);
181
- if (hasLocalRecipientId) {
182
- return {
183
- ok: true,
184
- recipient: {
185
- kind: "local",
186
- mailboxId: recipientRef,
187
- recipientName: recipientRef,
188
- },
189
- };
190
- }
191
- const hasLocalRecipientAlias = typeof localMailbox?.hasByName === "function" && localMailbox.hasByName(recipientRef);
192
- if (hasLocalRecipientAlias) {
193
- const canonicalLocalRecipientId = typeof localMailbox?.resolveId === "function"
194
- ? localMailbox.resolveId(recipientRef)
195
- : undefined;
196
- if (!canonicalLocalRecipientId) {
197
- return {
198
- ok: false,
199
- error: `Registered local alias "${recipientRef}" is missing a canonical mailbox id`,
200
- };
201
- }
202
- return {
203
- ok: true,
204
- recipient: {
205
- kind: "local",
206
- mailboxId: canonicalLocalRecipientId,
207
- recipientName: recipientRef,
208
- },
209
- };
210
- }
211
- const managedLocalRecipient = await resolveManagedLocalRecipient(context, recipientRef);
212
- if (managedLocalRecipient) {
213
- return {
214
- ok: true,
215
- recipient: managedLocalRecipient,
216
- };
217
- }
218
- // Resolve by display name — allows @mentioning peers by name instead of nodeId.
219
- const recipientRefLower = recipientRef.toLowerCase().replace(/^@/, "");
220
- const displayMatches = peers.filter((peer) => peer.displayNameSnapshot?.toLowerCase() === recipientRefLower ||
221
- peer.displayNameSnapshot?.toLowerCase() === recipientRef.toLowerCase());
222
- if (displayMatches.length > 1) {
223
- return { ok: false, error: `Ambiguous peer display name "${recipientRef}"` };
224
- }
225
- if (displayMatches.length === 1) {
226
- const matchedPeer = displayMatches[0];
227
- if (matchedPeer.routeOwnership === "superseded" ||
228
- matchedPeer.deliveryReadiness === "cannot_address") {
229
- return {
230
- ok: false,
231
- error: `Peer "${matchedPeer.displayNameSnapshot}" is not currently addressable.`,
232
- };
233
- }
234
- return {
235
- ok: true,
236
- recipient: {
237
- kind: "remote",
238
- nodeId: matchedPeer.nodeId,
239
- recipientName: matchedPeer.displayNameSnapshot ?? matchedPeer.nodeId,
240
- },
241
- };
242
- }
243
- const clientDisplayMatches = attachedClients.filter((client) => client.displayLabel?.toLowerCase() === recipientRefLower ||
244
- client.displayLabel?.toLowerCase() === recipientRef.toLowerCase());
245
- if (clientDisplayMatches.length > 1) {
246
- return { ok: false, error: `Ambiguous same-home client label "${recipientRef}"` };
247
- }
248
- if (clientDisplayMatches.length === 1) {
249
- const matchedClient = clientDisplayMatches[0];
250
- return {
251
- ok: true,
252
- recipient: {
253
- kind: "client",
254
- clientId: matchedClient.clientId,
255
- recipientName: matchedClient.displayLabel?.trim() || matchedClient.clientId,
256
- self: matchedClient.self,
257
- },
258
- };
259
- }
260
- if (inboxAddress.kind === "client") {
261
- return {
262
- ok: false,
263
- error: buildUnknownRecipientError(context, recipientRef),
264
- };
265
- }
266
- return {
267
- ok: true,
268
- recipient: {
269
- kind: "local",
270
- mailboxId: recipientRef,
271
- recipientName: recipientRef,
272
- },
273
- };
274
- }
275
- /**
276
- * Send a message to any agent (arion, worker, or leader).
277
- * Messages are persisted and can be threaded via replyTo or correlated via correlationId.
278
- */
279
- const send_message = tool({
280
- name: "send_message",
281
- description: "Send a message to any agent (arion, worker, or leader). " +
282
- "Use @name or display name to address peers and clients (e.g. @vm1, @local-machine), " +
283
- "or use an exact nodeId/clientId for precision. " +
284
- "When replying to a received message, prefer replyTo and omit to so the tool routes back to the original sender automatically. " +
285
- "Messages are persisted and can be threaded via replyTo or correlated via correlationId.",
286
- parameters: z
287
- .object({
288
- to: z
289
- .string()
290
- .optional()
291
- .describe("Recipient: @name or display name of a peer/client (e.g. @vm1, @local-machine), " +
292
- "or exact nodeId/clientId for precision"),
293
- type: z
294
- .enum([
295
- "quest",
296
- "quest_update",
297
- "progress",
298
- "finding",
299
- "question",
300
- "answer",
301
- "review_request",
302
- "review_result",
303
- "approval",
304
- "directive",
305
- "context",
306
- "announcement",
307
- "error",
308
- ])
309
- .describe("Message type"),
310
- content: z.string().describe("Message content"),
311
- replyTo: z
312
- .string()
313
- .optional()
314
- .describe("Message ID to reply to. When provided without to, the tool replies to the original sender automatically."),
315
- correlationId: z
316
- .string()
317
- .optional()
318
- .describe("Correlation ID for sub-thread conversations within a quest"),
319
- questId: z
320
- .string()
321
- .optional()
322
- .describe("Quest ID this message belongs to (e.g. quest_abc123)"),
323
- priority: z
324
- .number()
325
- .min(0)
326
- .max(4)
327
- .optional()
328
- .describe("Priority: 0=critical, 2=normal (default), 4=backlog"),
329
- })
330
- .superRefine((input, ctx) => {
331
- if (!input.to && !input.replyTo) {
332
- ctx.addIssue({
333
- code: z.ZodIssueCode.custom,
334
- path: ["to"],
335
- message: 'Either "to" or "replyTo" is required.',
336
- });
337
- }
338
- }),
339
- category: "messaging",
340
- riskLevel: "moderate",
341
- isReadOnly: false,
342
- execute: async (input, context) => {
343
- if (!context.messageStore) {
344
- return {
345
- success: false,
346
- message: "Message store not available. Messaging requires Memoria.",
347
- };
348
- }
349
- const inboxAddress = resolveInboxAddress(context);
350
- const recipient = input.to && input.to.trim().length > 0
351
- ? await resolveRecipientIdentity(context, input.to, inboxAddress)
352
- : input.replyTo
353
- ? await resolveRecipientFromReplyTarget(context, input.replyTo, inboxAddress)
354
- : { ok: false, error: 'Either "to" or "replyTo" is required.' };
355
- if (!recipient.ok) {
356
- return {
357
- success: false,
358
- message: recipient.error,
359
- };
360
- }
361
- if (recipient.recipient.kind === "client" && recipient.recipient.self) {
362
- return {
363
- success: false,
364
- message: "Cannot send a same-home message to yourself.",
365
- };
366
- }
367
- const recipientId = recipient.recipient.kind === "remote"
368
- ? recipient.recipient.nodeId
369
- : recipient.recipient.kind === "client"
370
- ? recipient.recipient.clientId
371
- : recipient.recipient.mailboxId;
372
- const sender = resolveSenderIdentity(context, inboxAddress);
373
- const resolvedTargetLabel = input.to ?? recipient.recipient.recipientName;
374
- const msg = {
375
- id: crypto.randomUUID(),
376
- version: 1,
377
- sender,
378
- recipient: { id: recipientId, name: recipient.recipient.recipientName },
379
- replyTo: input.replyTo,
380
- correlationId: input.correlationId,
381
- questId: input.questId,
382
- type: input.type,
383
- content: input.content,
384
- metadata: inboxAddress.kind === "client"
385
- ? {
386
- [SENDER_INBOX_METADATA_KEY]: inboxAddress,
387
- }
388
- : undefined,
389
- timestamp: Date.now(),
390
- priority: (input.priority ?? 2),
391
- ...(recipient.recipient.kind === "client"
392
- ? {
393
- recipientInbox: {
394
- kind: "client",
395
- clientId: recipient.recipient.clientId,
396
- },
397
- }
398
- : {}),
399
- };
400
- // Route through Mailbox if available (handles delivery + persistence)
401
- if (context.mailbox) {
402
- try {
403
- const receipt = canonicalizeDeliveryReceipt(await context.mailbox.sendDurable(msg));
404
- const receiptSummary = receipt.deliveryState === "queued_for_route"
405
- ? `accepted and queued for route establishment`
406
- : receipt.deliveryState === "dispatching"
407
- ? `sent and awaiting remote acknowledgement`
408
- : receipt.delivered
409
- ? `delivered`
410
- : `sent`;
411
- const routeSummary = receipt.sessionState
412
- ? ` session=${receipt.sessionState}, delivery=${receipt.deliveryReadiness ?? "unknown"}`
413
- : "";
414
- const reasonSummary = receipt.queuedReason ? ` reason=${receipt.queuedReason}` : "";
415
- return {
416
- success: true,
417
- message: `Message ${receiptSummary} for "${resolvedTargetLabel}" via ${receipt.transport}` +
418
- `${routeSummary}${reasonSummary} (type: ${input.type}, id: ${msg.id})`,
419
- data: {
420
- id: msg.id,
421
- to: recipientId,
422
- type: input.type,
423
- delivered: receipt.delivered,
424
- queued: receipt.queued,
425
- transport: receipt.transport,
426
- accepted: receipt.accepted ?? true,
427
- deliveryState: receipt.deliveryState,
428
- sessionState: receipt.sessionState,
429
- deliveryReadiness: receipt.deliveryReadiness,
430
- queuedReason: receipt.queuedReason,
431
- },
432
- };
433
- }
434
- catch (e) {
435
- // Fail closed for known remote peers — a local fallback is not delivery.
436
- if (recipient.recipient.kind === "remote") {
437
- context.messageStore.store(msg, "sent", inboxAddress);
438
- return {
439
- success: false,
440
- message: `Message delivery failed for "${resolvedTargetLabel}": ${e.message}`,
441
- data: {
442
- id: msg.id,
443
- to: recipient.recipient.nodeId,
444
- type: input.type,
445
- delivered: false,
446
- },
447
- };
448
- }
449
- // Local fallback only makes sense when no remote peer principal was resolved.
450
- context.messageStore.store(msg, "sent", inboxAddress);
451
- return {
452
- success: true,
453
- message: `Message stored locally for "${resolvedTargetLabel}" but delivery failed: ${e.message}`,
454
- data: { id: msg.id, to: recipientId, type: input.type, delivered: false },
455
- };
456
- }
457
- }
458
- // No Mailbox — store locally only (single-process mode)
459
- context.messageStore.store(msg, "sent", inboxAddress);
460
- return {
461
- success: true,
462
- message: `Message sent to "${resolvedTargetLabel}" (type: ${input.type}, id: ${msg.id})`,
463
- data: { id: msg.id, to: recipientId, type: input.type, delivered: false },
464
- };
465
- },
466
- });
467
- /**
468
- * Check your message inbox.
469
- * Returns unread messages by default, with optional filters.
470
- */
471
- const check_messages = tool({
472
- name: "check_messages",
473
- description: "Check your message inbox. Returns unread messages by default, with optional filters.",
474
- parameters: z.object({
475
- unreadOnly: z.boolean().optional().describe("Only show unread messages (default: true)"),
476
- from: z.string().optional().describe("Filter by sender name"),
477
- type: z.string().optional().describe("Filter by message type"),
478
- correlationId: z.string().optional().describe("Filter by correlation ID"),
479
- limit: z.number().optional().describe("Max messages to return (default: 20)"),
480
- }),
481
- category: "messaging",
482
- riskLevel: "safe",
483
- isReadOnly: true,
484
- execute: async (input, context) => {
485
- if (!context.messageStore) {
486
- return { success: false, message: "Message store not available." };
487
- }
488
- const inboxAddresses = resolveAllInboxAddresses(context);
489
- const unreadOnly = input.unreadOnly ?? true;
490
- const limit = input.limit ?? 20;
491
- if (unreadOnly) {
492
- const seen = new Set();
493
- const messages = inboxAddresses
494
- .flatMap((addr) => context.messageStore.getUnreadForInbox(addr, limit))
495
- .filter((m) => {
496
- if (seen.has(m.id))
497
- return false;
498
- seen.add(m.id);
499
- return true;
500
- })
501
- .slice(0, limit);
502
- if (messages.length === 0) {
503
- return { success: true, message: "No unread messages.", data: { messages: [] } };
504
- }
505
- // Auto-mark as read
506
- context.messageStore.markRead(messages.map((m) => m.id));
507
- return {
508
- success: true,
509
- message: `${messages.length} message(s) received`,
510
- data: { messages },
511
- };
512
- }
513
- // Search with filters
514
- const seen = new Set();
515
- const messages = inboxAddresses
516
- .flatMap((addr) => context.messageStore.searchInbox(addr, "", {
517
- from: input.from,
518
- type: input.type,
519
- correlationId: input.correlationId,
520
- limit,
521
- }))
522
- .filter((m) => {
523
- if (seen.has(m.id))
524
- return false;
525
- seen.add(m.id);
526
- return true;
527
- })
528
- .slice(0, limit);
529
- return {
530
- success: true,
531
- message: `${messages.length} message(s) found`,
532
- data: { messages },
533
- };
534
- },
535
- });
536
- /**
537
- * Search message history by content with optional filters.
538
- */
539
- const search_messages = tool({
540
- name: "search_messages",
541
- description: "Search message history by content with optional filters.",
542
- parameters: z.object({
543
- query: z.string().describe("Search text (matched against message content)"),
544
- from: z.string().optional().describe("Filter by sender name"),
545
- type: z.string().optional().describe("Filter by message type"),
546
- correlationId: z.string().optional().describe("Filter by correlation ID"),
547
- after: z.number().optional().describe("Only messages after this timestamp (epoch ms)"),
548
- limit: z.number().optional().describe("Max results (default: 20)"),
549
- }),
550
- category: "messaging",
551
- riskLevel: "safe",
552
- isReadOnly: true,
553
- execute: async (input, context) => {
554
- if (!context.messageStore) {
555
- return { success: false, message: "Message store not available." };
556
- }
557
- const inboxAddresses = resolveAllInboxAddresses(context);
558
- const limit = input.limit ?? 20;
559
- const seen = new Set();
560
- const messages = inboxAddresses
561
- .flatMap((addr) => context.messageStore.searchInbox(addr, input.query, {
562
- from: input.from,
563
- type: input.type,
564
- correlationId: input.correlationId,
565
- after: input.after,
566
- limit,
567
- }))
568
- .filter((m) => {
569
- if (seen.has(m.id))
570
- return false;
571
- seen.add(m.id);
572
- return true;
573
- })
574
- .slice(0, limit);
575
- return {
576
- success: true,
577
- message: `${messages.length} message(s) found`,
578
- data: { messages },
579
- };
580
- },
581
- });
582
- /**
583
- * Reconstruct a conversation thread from any message ID in the chain.
584
- * Follows replyTo links to build the full thread.
585
- */
586
- const get_thread = tool({
587
- name: "get_thread",
588
- description: "Reconstruct a conversation thread from any message ID in the chain. Follows replyTo links to build the full thread.",
589
- parameters: z.object({
590
- messageId: z.string().describe("Any message ID in the thread"),
591
- }),
592
- category: "messaging",
593
- riskLevel: "safe",
594
- isReadOnly: true,
595
- execute: async (input, context) => {
596
- if (!context.messageStore) {
597
- return { success: false, message: "Message store not available." };
598
- }
599
- const inboxAddresses = resolveAllInboxAddresses(context);
600
- const seen = new Set();
601
- const thread = inboxAddresses
602
- .flatMap((addr) => context.messageStore.getThreadForInbox(addr, input.messageId))
603
- .filter((m) => {
604
- if (seen.has(m.id))
605
- return false;
606
- seen.add(m.id);
607
- return true;
608
- });
609
- if (thread.length === 0) {
610
- return { success: false, message: `No thread found for message ${input.messageId}` };
611
- }
612
- return {
613
- success: true,
614
- message: `Thread with ${thread.length} message(s)`,
615
- data: { thread },
616
- };
617
- },
618
- });
619
- /** Messaging tool definitions (4) */
620
- export const MESSAGING_TOOL_DEFINITIONS = [
621
- send_message,
622
- check_messages,
623
- search_messages,
624
- get_thread,
625
- ];