@animalabs/agent-framework 0.19.0 → 0.21.0

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 (214) hide show
  1. package/README.md +29 -0
  2. package/dist/src/agent.d.ts +22 -0
  3. package/dist/src/agent.d.ts.map +1 -1
  4. package/dist/src/agent.js +128 -10
  5. package/dist/src/agent.js.map +1 -1
  6. package/dist/src/api/types.d.ts +1 -1
  7. package/dist/src/api/types.d.ts.map +1 -1
  8. package/dist/src/code-execution/py-runner.d.ts +10 -1
  9. package/dist/src/code-execution/py-runner.d.ts.map +1 -1
  10. package/dist/src/code-execution/py-runner.js +27 -2
  11. package/dist/src/code-execution/py-runner.js.map +1 -1
  12. package/dist/src/code-execution/tool-definition.d.ts +21 -0
  13. package/dist/src/code-execution/tool-definition.d.ts.map +1 -1
  14. package/dist/src/code-execution/tool-definition.js +34 -0
  15. package/dist/src/code-execution/tool-definition.js.map +1 -1
  16. package/dist/src/framework.d.ts +153 -2
  17. package/dist/src/framework.d.ts.map +1 -1
  18. package/dist/src/framework.js +1175 -76
  19. package/dist/src/framework.js.map +1 -1
  20. package/dist/src/index.d.ts +2 -0
  21. package/dist/src/index.d.ts.map +1 -1
  22. package/dist/src/index.js +4 -0
  23. package/dist/src/index.js.map +1 -1
  24. package/dist/src/mcpl/capability-grant.d.ts +1 -1
  25. package/dist/src/mcpl/capability-grant.d.ts.map +1 -1
  26. package/dist/src/mcpl/capability-grant.js +49 -5
  27. package/dist/src/mcpl/capability-grant.js.map +1 -1
  28. package/dist/src/mcpl/channel-registry.d.ts +59 -2
  29. package/dist/src/mcpl/channel-registry.d.ts.map +1 -1
  30. package/dist/src/mcpl/channel-registry.js +106 -6
  31. package/dist/src/mcpl/channel-registry.js.map +1 -1
  32. package/dist/src/mcpl/conversation-router.d.ts +8 -6
  33. package/dist/src/mcpl/conversation-router.d.ts.map +1 -1
  34. package/dist/src/mcpl/conversation-router.js +12 -6
  35. package/dist/src/mcpl/conversation-router.js.map +1 -1
  36. package/dist/src/mcpl/index.d.ts +3 -0
  37. package/dist/src/mcpl/index.d.ts.map +1 -1
  38. package/dist/src/mcpl/index.js +3 -0
  39. package/dist/src/mcpl/index.js.map +1 -1
  40. package/dist/src/mcpl/push-coalescer.d.ts +318 -0
  41. package/dist/src/mcpl/push-coalescer.d.ts.map +1 -0
  42. package/dist/src/mcpl/push-coalescer.js +709 -0
  43. package/dist/src/mcpl/push-coalescer.js.map +1 -0
  44. package/dist/src/mcpl/push-handler.d.ts +7 -2
  45. package/dist/src/mcpl/push-handler.d.ts.map +1 -1
  46. package/dist/src/mcpl/push-handler.js +43 -4
  47. package/dist/src/mcpl/push-handler.js.map +1 -1
  48. package/dist/src/mcpl/references.d.ts.map +1 -1
  49. package/dist/src/mcpl/references.js +9 -4
  50. package/dist/src/mcpl/references.js.map +1 -1
  51. package/dist/src/mcpl/server-connection.d.ts +18 -0
  52. package/dist/src/mcpl/server-connection.d.ts.map +1 -1
  53. package/dist/src/mcpl/server-connection.js +44 -1
  54. package/dist/src/mcpl/server-connection.js.map +1 -1
  55. package/dist/src/mcpl/tool-classes.d.ts +71 -0
  56. package/dist/src/mcpl/tool-classes.d.ts.map +1 -0
  57. package/dist/src/mcpl/tool-classes.js +170 -0
  58. package/dist/src/mcpl/tool-classes.js.map +1 -0
  59. package/dist/src/mcpl/tool-glob.d.ts +16 -0
  60. package/dist/src/mcpl/tool-glob.d.ts.map +1 -0
  61. package/dist/src/mcpl/tool-glob.js +41 -0
  62. package/dist/src/mcpl/tool-glob.js.map +1 -0
  63. package/dist/src/mcpl/tool-lifecycle.d.ts +253 -0
  64. package/dist/src/mcpl/tool-lifecycle.d.ts.map +1 -0
  65. package/dist/src/mcpl/tool-lifecycle.js +607 -0
  66. package/dist/src/mcpl/tool-lifecycle.js.map +1 -0
  67. package/dist/src/mcpl/transport.d.ts +15 -0
  68. package/dist/src/mcpl/transport.d.ts.map +1 -1
  69. package/dist/src/mcpl/transport.js +65 -1
  70. package/dist/src/mcpl/transport.js.map +1 -1
  71. package/dist/src/mcpl/types.d.ts +68 -1
  72. package/dist/src/mcpl/types.d.ts.map +1 -1
  73. package/dist/src/mcpl/types.js +6 -0
  74. package/dist/src/mcpl/types.js.map +1 -1
  75. package/dist/src/modules/discord/index.js +1 -1
  76. package/dist/src/modules/discord/index.js.map +1 -1
  77. package/dist/src/modules/history/index.d.ts +85 -0
  78. package/dist/src/modules/history/index.d.ts.map +1 -1
  79. package/dist/src/modules/history/index.js +1019 -24
  80. package/dist/src/modules/history/index.js.map +1 -1
  81. package/dist/src/modules/history/semantic.d.ts +202 -0
  82. package/dist/src/modules/history/semantic.d.ts.map +1 -0
  83. package/dist/src/modules/history/semantic.js +418 -0
  84. package/dist/src/modules/history/semantic.js.map +1 -0
  85. package/dist/src/modules/index.d.ts +2 -1
  86. package/dist/src/modules/index.d.ts.map +1 -1
  87. package/dist/src/modules/index.js.map +1 -1
  88. package/dist/src/tool-result-guard.d.ts +82 -0
  89. package/dist/src/tool-result-guard.d.ts.map +1 -0
  90. package/dist/src/tool-result-guard.js +306 -0
  91. package/dist/src/tool-result-guard.js.map +1 -0
  92. package/dist/src/types/agent.d.ts +14 -0
  93. package/dist/src/types/agent.d.ts.map +1 -1
  94. package/dist/src/types/framework.d.ts +21 -0
  95. package/dist/src/types/framework.d.ts.map +1 -1
  96. package/dist/src/types/trace.d.ts +17 -0
  97. package/dist/src/types/trace.d.ts.map +1 -1
  98. package/dist/test/channel-registry-routing.test.js +59 -0
  99. package/dist/test/channel-registry-routing.test.js.map +1 -1
  100. package/dist/test/code-execution.test.js +139 -0
  101. package/dist/test/code-execution.test.js.map +1 -1
  102. package/dist/test/conversation-router.test.js +33 -19
  103. package/dist/test/conversation-router.test.js.map +1 -1
  104. package/dist/test/conversation-routing.test.js +89 -0
  105. package/dist/test/conversation-routing.test.js.map +1 -1
  106. package/dist/test/helpers/coalescing-fixture.d.ts +72 -0
  107. package/dist/test/helpers/coalescing-fixture.d.ts.map +1 -0
  108. package/dist/test/helpers/coalescing-fixture.js +145 -0
  109. package/dist/test/helpers/coalescing-fixture.js.map +1 -0
  110. package/dist/test/helpers/coalescing-kill-child.d.ts +2 -0
  111. package/dist/test/helpers/coalescing-kill-child.d.ts.map +1 -0
  112. package/dist/test/helpers/coalescing-kill-child.js +24 -0
  113. package/dist/test/helpers/coalescing-kill-child.js.map +1 -0
  114. package/dist/test/history-module-realstore.test.d.ts +2 -0
  115. package/dist/test/history-module-realstore.test.d.ts.map +1 -0
  116. package/dist/test/history-module-realstore.test.js +363 -0
  117. package/dist/test/history-module-realstore.test.js.map +1 -0
  118. package/dist/test/history-module-semantic.test.d.ts +2 -0
  119. package/dist/test/history-module-semantic.test.d.ts.map +1 -0
  120. package/dist/test/history-module-semantic.test.js +213 -0
  121. package/dist/test/history-module-semantic.test.js.map +1 -0
  122. package/dist/test/history-module-ux.test.d.ts +2 -0
  123. package/dist/test/history-module-ux.test.d.ts.map +1 -0
  124. package/dist/test/history-module-ux.test.js +304 -0
  125. package/dist/test/history-module-ux.test.js.map +1 -0
  126. package/dist/test/history-module.test.js +25 -1
  127. package/dist/test/history-module.test.js.map +1 -1
  128. package/dist/test/history-semantic-review-findings.test.d.ts +2 -0
  129. package/dist/test/history-semantic-review-findings.test.d.ts.map +1 -0
  130. package/dist/test/history-semantic-review-findings.test.js +338 -0
  131. package/dist/test/history-semantic-review-findings.test.js.map +1 -0
  132. package/dist/test/history-semantic-sync-converges.test.d.ts +2 -0
  133. package/dist/test/history-semantic-sync-converges.test.d.ts.map +1 -0
  134. package/dist/test/history-semantic-sync-converges.test.js +109 -0
  135. package/dist/test/history-semantic-sync-converges.test.js.map +1 -0
  136. package/dist/test/mcpl-capability-grant.test.js +3 -1
  137. package/dist/test/mcpl-capability-grant.test.js.map +1 -1
  138. package/dist/test/mcpl-child-env.test.d.ts +2 -0
  139. package/dist/test/mcpl-child-env.test.d.ts.map +1 -0
  140. package/dist/test/mcpl-child-env.test.js +158 -0
  141. package/dist/test/mcpl-child-env.test.js.map +1 -0
  142. package/dist/test/mcpl-coalescing.test.d.ts +2 -0
  143. package/dist/test/mcpl-coalescing.test.d.ts.map +1 -0
  144. package/dist/test/mcpl-coalescing.test.js +1050 -0
  145. package/dist/test/mcpl-coalescing.test.js.map +1 -0
  146. package/dist/test/mcpl-list-status.test.js +4 -0
  147. package/dist/test/mcpl-list-status.test.js.map +1 -1
  148. package/dist/test/mcpl-reference-fields.test.d.ts +2 -0
  149. package/dist/test/mcpl-reference-fields.test.d.ts.map +1 -0
  150. package/dist/test/mcpl-reference-fields.test.js +82 -0
  151. package/dist/test/mcpl-reference-fields.test.js.map +1 -0
  152. package/dist/test/mcpl-tool-class-listing.test.d.ts +2 -0
  153. package/dist/test/mcpl-tool-class-listing.test.d.ts.map +1 -0
  154. package/dist/test/mcpl-tool-class-listing.test.js +147 -0
  155. package/dist/test/mcpl-tool-class-listing.test.js.map +1 -0
  156. package/dist/test/mcpl-tool-classes.test.d.ts +7 -0
  157. package/dist/test/mcpl-tool-classes.test.d.ts.map +1 -0
  158. package/dist/test/mcpl-tool-classes.test.js +80 -0
  159. package/dist/test/mcpl-tool-classes.test.js.map +1 -0
  160. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts +2 -0
  161. package/dist/test/mcpl-tool-lifecycle-e2e.test.d.ts.map +1 -0
  162. package/dist/test/mcpl-tool-lifecycle-e2e.test.js +237 -0
  163. package/dist/test/mcpl-tool-lifecycle-e2e.test.js.map +1 -0
  164. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts +11 -0
  165. package/dist/test/mcpl-tool-lifecycle-emitter.test.d.ts.map +1 -0
  166. package/dist/test/mcpl-tool-lifecycle-emitter.test.js +307 -0
  167. package/dist/test/mcpl-tool-lifecycle-emitter.test.js.map +1 -0
  168. package/dist/test/mcpl-tool-lifecycle.test.d.ts +11 -0
  169. package/dist/test/mcpl-tool-lifecycle.test.d.ts.map +1 -0
  170. package/dist/test/mcpl-tool-lifecycle.test.js +270 -0
  171. package/dist/test/mcpl-tool-lifecycle.test.js.map +1 -0
  172. package/dist/test/silent-heartbeat.test.d.ts +2 -0
  173. package/dist/test/silent-heartbeat.test.d.ts.map +1 -0
  174. package/dist/test/silent-heartbeat.test.js +154 -0
  175. package/dist/test/silent-heartbeat.test.js.map +1 -0
  176. package/dist/test/tool-result-guard.test.d.ts +2 -0
  177. package/dist/test/tool-result-guard.test.d.ts.map +1 -0
  178. package/dist/test/tool-result-guard.test.js +1081 -0
  179. package/dist/test/tool-result-guard.test.js.map +1 -0
  180. package/dist/test/tools-observe-parser-conformance.test.d.ts +2 -0
  181. package/dist/test/tools-observe-parser-conformance.test.d.ts.map +1 -0
  182. package/dist/test/tools-observe-parser-conformance.test.js +129 -0
  183. package/dist/test/tools-observe-parser-conformance.test.js.map +1 -0
  184. package/dist/test/trunk-channel-routing.test.js +67 -0
  185. package/dist/test/trunk-channel-routing.test.js.map +1 -1
  186. package/dist/tsconfig.tsbuildinfo +1 -1
  187. package/package.json +2 -2
  188. package/src/agent.ts +128 -10
  189. package/src/api/types.ts +2 -0
  190. package/src/code-execution/py-runner.ts +34 -2
  191. package/src/code-execution/tool-definition.ts +46 -0
  192. package/src/framework.ts +1207 -80
  193. package/src/index.ts +13 -0
  194. package/src/mcpl/capability-grant.ts +54 -6
  195. package/src/mcpl/channel-registry.ts +115 -7
  196. package/src/mcpl/conversation-router.ts +12 -8
  197. package/src/mcpl/index.ts +29 -0
  198. package/src/mcpl/push-coalescer.ts +821 -0
  199. package/src/mcpl/push-handler.ts +40 -4
  200. package/src/mcpl/references.ts +11 -3
  201. package/src/mcpl/server-connection.ts +48 -2
  202. package/src/mcpl/tool-classes.ts +188 -0
  203. package/src/mcpl/tool-glob.ts +36 -0
  204. package/src/mcpl/tool-lifecycle.ts +745 -0
  205. package/src/mcpl/transport.ts +67 -1
  206. package/src/mcpl/types.ts +71 -1
  207. package/src/modules/discord/index.ts +1 -1
  208. package/src/modules/history/index.ts +1089 -24
  209. package/src/modules/history/semantic.ts +473 -0
  210. package/src/modules/index.ts +2 -1
  211. package/src/tool-result-guard.ts +318 -0
  212. package/src/types/agent.ts +15 -0
  213. package/src/types/framework.ts +23 -0
  214. package/src/types/trace.ts +17 -0
@@ -101,6 +101,72 @@ export abstract class McplTransport extends EventEmitter {
101
101
  // stdio
102
102
  // ---------------------------------------------------------------------------
103
103
 
104
+ /**
105
+ * Host variables a stdio child gets by default: just enough for an ordinary
106
+ * process to run (find binaries, a home dir, temp dir, locale, TLS roots,
107
+ * network proxies, a display for GUI helpers). Everything else in the host env — notably API
108
+ * keys and bot tokens — is NOT passed on; a server that needs a variable must
109
+ * declare it in its `env` (recipes can `${VAR}`-substitute from .env), or set
110
+ * `inheritEnv: true` to get the whole host env as before. Proxy URLs may include
111
+ * credentials. This limits accidental inheritance, not access by a hostile
112
+ * same-user child process; it is not a process isolation boundary.
113
+ */
114
+ export const CHILD_ENV_ALLOWLIST = [
115
+ 'PATH', 'HOME', 'USER', 'LOGNAME', 'SHELL', 'TERM', 'LANG', 'TZ',
116
+ 'TMPDIR', 'TMP', 'TEMP',
117
+ 'DISPLAY', 'WAYLAND_DISPLAY',
118
+ 'XDG_RUNTIME_DIR', 'XDG_CONFIG_HOME', 'XDG_CACHE_HOME', 'XDG_DATA_HOME',
119
+ 'SSL_CERT_FILE', 'SSL_CERT_DIR', 'NODE_EXTRA_CA_CERTS',
120
+ 'REQUESTS_CA_BUNDLE', 'CURL_CA_BUNDLE',
121
+ 'HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY',
122
+ 'http_proxy', 'https_proxy', 'no_proxy',
123
+ '__CF_USER_TEXT_ENCODING',
124
+ // Windows equivalents, harmless elsewhere.
125
+ 'SYSTEMROOT', 'WINDIR', 'COMSPEC', 'PATHEXT', 'APPDATA', 'LOCALAPPDATA', 'USERPROFILE',
126
+ ];
127
+
128
+ /** Environment for a stdio child: allowlisted host vars (+ LC_*), then the
129
+ * server's declared `env` on top. Windows names merge case-insensitively;
130
+ * POSIX names remain case-sensitive. `inheritEnv: true` restores full inheritance. */
131
+ export function buildChildEnv(
132
+ config: Pick<McplServerConfig, 'env' | 'inheritEnv'>,
133
+ hostEnv: NodeJS.ProcessEnv = process.env,
134
+ platform: NodeJS.Platform = process.platform,
135
+ ): NodeJS.ProcessEnv {
136
+ const win = platform === 'win32';
137
+ const env: NodeJS.ProcessEnv = config.inheritEnv ? { ...hostEnv } : {};
138
+ if (!config.inheritEnv) {
139
+ for (const [key, value] of Object.entries(hostEnv)) {
140
+ if (value === undefined) continue;
141
+ // Windows commonly enumerates Path/SystemRoot rather than PATH/SYSTEMROOT.
142
+ const probe = win ? key.toUpperCase() : key;
143
+ if (CHILD_ENV_ALLOWLIST.includes(probe) || probe.startsWith('LC_')) env[key] = value;
144
+ }
145
+ }
146
+ if (!win) return { ...env, ...config.env };
147
+
148
+ // Windows spawn folds environment names case-insensitively and may choose
149
+ // an earlier host spelling over a differently cased declared override.
150
+ // Select Node's first lexicographic spelling within each source, then layer
151
+ // declared values (including '') over host values. Source precedence and
152
+ // duplicate-name resolution are separate decisions.
153
+ const merged: NodeJS.ProcessEnv = {};
154
+ const spellings = new Map<string, string>();
155
+ for (const source of [env, config.env ?? {}]) {
156
+ const seen = new Set<string>();
157
+ for (const key of Object.keys(source).sort()) {
158
+ const canonical = key.toUpperCase();
159
+ if (seen.has(canonical)) continue;
160
+ seen.add(canonical);
161
+ const previous = spellings.get(canonical);
162
+ if (previous !== undefined && previous !== key) delete merged[previous];
163
+ merged[key] = source[key];
164
+ spellings.set(canonical, key);
165
+ }
166
+ }
167
+ return merged;
168
+ }
169
+
104
170
  export class StdioTransport extends McplTransport {
105
171
  readonly kind = 'stdio' as const;
106
172
 
@@ -139,7 +205,7 @@ export class StdioTransport extends McplTransport {
139
205
  }
140
206
  const child = spawn(config.command, config.args ?? [], {
141
207
  stdio: ['pipe', 'pipe', 'pipe'],
142
- env: { ...process.env, ...config.env },
208
+ env: buildChildEnv(config),
143
209
  });
144
210
  const rl = createInterface({ input: child.stdout! });
145
211
  return new StdioTransport(child, rl);
package/src/mcpl/types.ts CHANGED
@@ -145,6 +145,10 @@ export interface McplCapabilities {
145
145
  /** Server consumes inference/lifecycle notifications (§10.5). */
146
146
  inferenceLifecycle?: boolean;
147
147
 
148
+ /** RFC-007 tool lifecycle: observe (metadata) and inputs (requested
149
+ * argument fields). `true` = both leaves. */
150
+ toolLifecycle?: boolean | { observe?: boolean; inputs?: boolean };
151
+
148
152
  /** Server supports model/info requests */
149
153
  modelInfo?: boolean;
150
154
 
@@ -161,6 +165,15 @@ export interface McplCapabilities {
161
165
  */
162
166
  export interface McplHostCapabilities {
163
167
  version: string;
168
+ /** RFC-006 support, independent of capability grants. */
169
+ eventCoalescing?: boolean | {
170
+ pushEvents?: boolean;
171
+ channelsIncoming?: boolean;
172
+ deferred?: boolean;
173
+ channelScopedPush?: boolean;
174
+ /** Retry-window guarantee in ms (integer ≥ 3,600,000; default 3,600,000). */
175
+ retryWindowMs?: number;
176
+ };
164
177
  pushEvents?: boolean;
165
178
  contextHooks?: {
166
179
  beforeInference?: boolean | {
@@ -170,6 +183,10 @@ export interface McplHostCapabilities {
170
183
  };
171
184
  inferenceRequest?: boolean | { streaming?: boolean };
172
185
  inferenceLifecycle?: boolean;
186
+
187
+ /** RFC-007 tool lifecycle: observe (metadata) and inputs (requested
188
+ * argument fields). `true` = both leaves. */
189
+ toolLifecycle?: boolean | { observe?: boolean; inputs?: boolean };
173
190
  modelInfo?: boolean;
174
191
  featureSets?: boolean;
175
192
  channels?: boolean | McplChannelCapabilities;
@@ -209,9 +226,22 @@ export interface McplServerConfig {
209
226
  /** Arguments for the command */
210
227
  args?: string[];
211
228
 
212
- /** Environment variables for the child process */
229
+ /**
230
+ * Environment variables for the child process. Stdio children do NOT inherit
231
+ * the host environment wholesale: they get a small allowlist (PATH, HOME,
232
+ * LANG, LC_*, TMPDIR, TLS CA bundles, and HTTP(S) proxy settings — see
233
+ * CHILD_ENV_ALLOWLIST) plus exactly these. Proxy URLs can contain credentials.
234
+ * This limits accidental inheritance; it does not isolate a hostile child.
235
+ */
213
236
  env?: Record<string, string>;
214
237
 
238
+ /**
239
+ * Escape hatch: pass the host's entire environment (including secrets) to
240
+ * the stdio child, as older versions did. Only for servers that genuinely
241
+ * need it. Default false.
242
+ */
243
+ inheritEnv?: boolean;
244
+
215
245
  /**
216
246
  * WebSocket URL for the network transport (`ws://` or `wss://`). Mutually
217
247
  * exclusive with `command`. When set (or `transport: 'websocket'`), the host
@@ -378,6 +408,17 @@ export interface McplServerConfig {
378
408
  * cumulative per-server byte budget (reference-fetcher.ts defaults apply
379
409
  * when absent). */
380
410
  autofetch?: { maxBytes?: number; maxTotalBytes?: number };
411
+
412
+ /**
413
+ * RFC-007 tool lifecycle policy for this server: narrowing for the
414
+ * `toolLifecycle.observe` and `toolLifecycle.inputs` grants, and the
415
+ * `input` size bound. Both paths are DENIED BY DEFAULT; stating a key here
416
+ * (or naming the path in enabledCapabilities) is the explicit grant.
417
+ * `inputs` without a `tools` or `classes` term delivers no arguments, and
418
+ * `comms` or unclassed tools never carry arguments whatever it says.
419
+ * See src/mcpl/tool-lifecycle.ts.
420
+ */
421
+ toolLifecycle?: import('./tool-lifecycle.js').ToolLifecycleConfig;
381
422
  }
382
423
 
383
424
  // ============================================================================
@@ -623,6 +664,21 @@ export interface StateRollbackResult {
623
664
  * Spec Section 9.1.
624
665
  */
625
666
  export interface PushEventParams {
667
+ /** RFC-006 event coalescing (mcpl PR #5, revision 7). */
668
+ coalesce?: {
669
+ /** Subject key, 1..256 UTF-8 bytes, opaque to the host. */
670
+ key: string;
671
+ /** push/event only: address a registered channel's subject namespace. */
672
+ channelId?: string;
673
+ /** push/event only: deferred mode — the host calls push/render at assembly. */
674
+ deferred?: boolean;
675
+ /** The subject ceased to exist; `payload.content` is the deletion notice. */
676
+ retract?: boolean;
677
+ /** No earlier occurrence of this subject was ever sent (§3.3). */
678
+ initial?: boolean;
679
+ /** deferred only; ≤ 4 KiB serialized; server-private, echoed by push/render. */
680
+ data?: unknown;
681
+ };
626
682
  /** Declaring feature set */
627
683
  featureSet: string;
628
684
 
@@ -650,6 +706,10 @@ export interface PushEventParams {
650
706
  * Spec Section 9.3.
651
707
  */
652
708
  export interface PushEventResult {
709
+ coalesce?: {
710
+ outcome: 'first' | 'replaced' | 'appended' | 'retracted' | 'noted' | 'consumed';
711
+ priorEventId?: string;
712
+ };
653
713
  /** Whether the event was accepted */
654
714
  accepted: boolean;
655
715
 
@@ -1086,6 +1146,8 @@ export interface ChannelsPublishResult {
1086
1146
  * Spec Section 14.3.
1087
1147
  */
1088
1148
  export interface ChannelIncomingMessage {
1149
+ eventId?: string;
1150
+ coalesce?: Omit<NonNullable<PushEventParams['coalesce']>, 'channelId' | 'deferred'>;
1089
1151
  /** Channel this message came from */
1090
1152
  channelId: string;
1091
1153
 
@@ -1133,6 +1195,7 @@ export interface ChannelsIncomingResult {
1133
1195
 
1134
1196
  /** Result for a single incoming message. */
1135
1197
  export interface ChannelIncomingMessageResult {
1198
+ coalesce?: PushEventResult['coalesce'];
1136
1199
  messageId: string;
1137
1200
  accepted: boolean;
1138
1201
  conversationId?: string;
@@ -1190,6 +1253,13 @@ export const McplMethod = {
1190
1253
  // context/afterInference. Metadata only; BEST-EFFORT delivery.
1191
1254
  InferenceLifecycle: 'inference/lifecycle',
1192
1255
 
1256
+ // Tool lifecycle (RFC-007). tools/lifecycle is Host → Server,
1257
+ // Notification, metadata plus (under its own grant) requested argument
1258
+ // fields — never results. tools/observe is Server → Host, Request: the
1259
+ // server's filter over what it is sent (interest, never authority).
1260
+ ToolsLifecycle: 'tools/lifecycle',
1261
+ ToolsObserve: 'tools/observe',
1262
+
1193
1263
  // Server manifest changes (§17). manifestChanged is S→H Notification —
1194
1264
  // an opaque revision plus changed domains, NO payload, deliberately
1195
1265
  // ungated (§17.3: gating it would silence exactly the servers whose
@@ -153,7 +153,7 @@ export class DiscordModule implements Module {
153
153
  this.unsubscribeTrace = ctx.onTrace((event: TraceEvent) => {
154
154
  const agentName = (event as { agentName?: string }).agentName;
155
155
  if (!agentName) return;
156
- if (event.type === 'inference:started') {
156
+ if (event.type === 'inference:started' && !event.silent) {
157
157
  this.startTypingLoop(agentName);
158
158
  } else if (TURN_TERMINAL_TRACES.has(event.type)) {
159
159
  this.stopTypingLoop(agentName);