@mcpmesh/sdk 1.4.1 → 2.0.0-beta.1

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 (242) hide show
  1. package/dist/__tests__/a2a/a2a-bearer.spec.d.ts +2 -0
  2. package/dist/__tests__/a2a/a2a-bearer.spec.d.ts.map +1 -0
  3. package/dist/__tests__/a2a/a2a-bearer.spec.js +58 -0
  4. package/dist/__tests__/a2a/a2a-bearer.spec.js.map +1 -0
  5. package/dist/__tests__/a2a/a2a-client.spec.d.ts +2 -0
  6. package/dist/__tests__/a2a/a2a-client.spec.d.ts.map +1 -0
  7. package/dist/__tests__/a2a/a2a-client.spec.js +334 -0
  8. package/dist/__tests__/a2a/a2a-client.spec.js.map +1 -0
  9. package/dist/__tests__/a2a/a2a-job.spec.d.ts +2 -0
  10. package/dist/__tests__/a2a/a2a-job.spec.d.ts.map +1 -0
  11. package/dist/__tests__/a2a/a2a-job.spec.js +255 -0
  12. package/dist/__tests__/a2a/a2a-job.spec.js.map +1 -0
  13. package/dist/__tests__/a2a/a2a-stream.spec.d.ts +2 -0
  14. package/dist/__tests__/a2a/a2a-stream.spec.d.ts.map +1 -0
  15. package/dist/__tests__/a2a/a2a-stream.spec.js +278 -0
  16. package/dist/__tests__/a2a/a2a-stream.spec.js.map +1 -0
  17. package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts +2 -0
  18. package/dist/__tests__/a2a/agent-a2a-config.spec.d.ts.map +1 -0
  19. package/dist/__tests__/a2a/agent-a2a-config.spec.js +262 -0
  20. package/dist/__tests__/a2a/agent-a2a-config.spec.js.map +1 -0
  21. package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts +2 -0
  22. package/dist/__tests__/a2a/producer/auth-filter.spec.d.ts.map +1 -0
  23. package/dist/__tests__/a2a/producer/auth-filter.spec.js +127 -0
  24. package/dist/__tests__/a2a/producer/auth-filter.spec.js.map +1 -0
  25. package/dist/__tests__/a2a/producer/card-builder.spec.d.ts +2 -0
  26. package/dist/__tests__/a2a/producer/card-builder.spec.d.ts.map +1 -0
  27. package/dist/__tests__/a2a/producer/card-builder.spec.js +113 -0
  28. package/dist/__tests__/a2a/producer/card-builder.spec.js.map +1 -0
  29. package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts +2 -0
  30. package/dist/__tests__/a2a/producer/dispatcher.spec.d.ts.map +1 -0
  31. package/dist/__tests__/a2a/producer/dispatcher.spec.js +850 -0
  32. package/dist/__tests__/a2a/producer/dispatcher.spec.js.map +1 -0
  33. package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts +2 -0
  34. package/dist/__tests__/a2a/producer/mount-surface-push.spec.d.ts.map +1 -0
  35. package/dist/__tests__/a2a/producer/mount-surface-push.spec.js +164 -0
  36. package/dist/__tests__/a2a/producer/mount-surface-push.spec.js.map +1 -0
  37. package/dist/__tests__/a2a/producer/mount.spec.d.ts +2 -0
  38. package/dist/__tests__/a2a/producer/mount.spec.d.ts.map +1 -0
  39. package/dist/__tests__/a2a/producer/mount.spec.js +433 -0
  40. package/dist/__tests__/a2a/producer/mount.spec.js.map +1 -0
  41. package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts +2 -0
  42. package/dist/__tests__/a2a/producer/public-url-cache.spec.d.ts.map +1 -0
  43. package/dist/__tests__/a2a/producer/public-url-cache.spec.js +116 -0
  44. package/dist/__tests__/a2a/producer/public-url-cache.spec.js.map +1 -0
  45. package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts +2 -0
  46. package/dist/__tests__/a2a/producer/sse-emitter.spec.d.ts.map +1 -0
  47. package/dist/__tests__/a2a/producer/sse-emitter.spec.js +754 -0
  48. package/dist/__tests__/a2a/producer/sse-emitter.spec.js.map +1 -0
  49. package/dist/__tests__/a2a/producer/state-translator.spec.d.ts +2 -0
  50. package/dist/__tests__/a2a/producer/state-translator.spec.d.ts.map +1 -0
  51. package/dist/__tests__/a2a/producer/state-translator.spec.js +124 -0
  52. package/dist/__tests__/a2a/producer/state-translator.spec.js.map +1 -0
  53. package/dist/__tests__/a2a/producer/task-store.spec.d.ts +2 -0
  54. package/dist/__tests__/a2a/producer/task-store.spec.d.ts.map +1 -0
  55. package/dist/__tests__/a2a/producer/task-store.spec.js +180 -0
  56. package/dist/__tests__/a2a/producer/task-store.spec.js.map +1 -0
  57. package/dist/__tests__/agent-add-tool.spec.d.ts +2 -0
  58. package/dist/__tests__/agent-add-tool.spec.d.ts.map +1 -0
  59. package/dist/__tests__/agent-add-tool.spec.js +483 -0
  60. package/dist/__tests__/agent-add-tool.spec.js.map +1 -0
  61. package/dist/__tests__/api-runtime-race.spec.d.ts +2 -0
  62. package/dist/__tests__/api-runtime-race.spec.d.ts.map +1 -0
  63. package/dist/__tests__/api-runtime-race.spec.js +193 -0
  64. package/dist/__tests__/api-runtime-race.spec.js.map +1 -0
  65. package/dist/__tests__/claim-dispatcher.spec.d.ts +2 -0
  66. package/dist/__tests__/claim-dispatcher.spec.d.ts.map +1 -0
  67. package/dist/__tests__/claim-dispatcher.spec.js +408 -0
  68. package/dist/__tests__/claim-dispatcher.spec.js.map +1 -0
  69. package/dist/__tests__/inbound-job-dispatch.spec.d.ts +2 -0
  70. package/dist/__tests__/inbound-job-dispatch.spec.d.ts.map +1 -0
  71. package/dist/__tests__/inbound-job-dispatch.spec.js +185 -0
  72. package/dist/__tests__/inbound-job-dispatch.spec.js.map +1 -0
  73. package/dist/__tests__/job-controller-progress.spec.d.ts +2 -0
  74. package/dist/__tests__/job-controller-progress.spec.d.ts.map +1 -0
  75. package/dist/__tests__/job-controller-progress.spec.js +85 -0
  76. package/dist/__tests__/job-controller-progress.spec.js.map +1 -0
  77. package/dist/__tests__/jobs-cancel-route.spec.d.ts +2 -0
  78. package/dist/__tests__/jobs-cancel-route.spec.d.ts.map +1 -0
  79. package/dist/__tests__/jobs-cancel-route.spec.js +88 -0
  80. package/dist/__tests__/jobs-cancel-route.spec.js.map +1 -0
  81. package/dist/__tests__/llm-agent-stream.test.d.ts +14 -0
  82. package/dist/__tests__/llm-agent-stream.test.d.ts.map +1 -0
  83. package/dist/__tests__/llm-agent-stream.test.js +341 -0
  84. package/dist/__tests__/llm-agent-stream.test.js.map +1 -0
  85. package/dist/__tests__/mesh-job-submitter.spec.d.ts +2 -0
  86. package/dist/__tests__/mesh-job-submitter.spec.d.ts.map +1 -0
  87. package/dist/__tests__/mesh-job-submitter.spec.js +110 -0
  88. package/dist/__tests__/mesh-job-submitter.spec.js.map +1 -0
  89. package/dist/__tests__/proxy-stream.test.d.ts +9 -0
  90. package/dist/__tests__/proxy-stream.test.d.ts.map +1 -0
  91. package/dist/__tests__/proxy-stream.test.js +347 -0
  92. package/dist/__tests__/proxy-stream.test.js.map +1 -0
  93. package/dist/__tests__/resolver-meshjob.spec.d.ts +26 -0
  94. package/dist/__tests__/resolver-meshjob.spec.d.ts.map +1 -0
  95. package/dist/__tests__/resolver-meshjob.spec.js +201 -0
  96. package/dist/__tests__/resolver-meshjob.spec.js.map +1 -0
  97. package/dist/__tests__/schema-verdict-policy.test.d.ts +6 -0
  98. package/dist/__tests__/schema-verdict-policy.test.d.ts.map +1 -0
  99. package/dist/__tests__/schema-verdict-policy.test.js +126 -0
  100. package/dist/__tests__/schema-verdict-policy.test.js.map +1 -0
  101. package/dist/__tests__/sse-stream.test.d.ts +12 -0
  102. package/dist/__tests__/sse-stream.test.d.ts.map +1 -0
  103. package/dist/__tests__/sse-stream.test.js +170 -0
  104. package/dist/__tests__/sse-stream.test.js.map +1 -0
  105. package/dist/a2a/a2a-bearer.d.ts +27 -0
  106. package/dist/a2a/a2a-bearer.d.ts.map +1 -0
  107. package/dist/a2a/a2a-bearer.js +63 -0
  108. package/dist/a2a/a2a-bearer.js.map +1 -0
  109. package/dist/a2a/a2a-client.d.ts +114 -0
  110. package/dist/a2a/a2a-client.d.ts.map +1 -0
  111. package/dist/a2a/a2a-client.js +405 -0
  112. package/dist/a2a/a2a-client.js.map +1 -0
  113. package/dist/a2a/a2a-event.d.ts +25 -0
  114. package/dist/a2a/a2a-event.d.ts.map +1 -0
  115. package/dist/a2a/a2a-event.js +9 -0
  116. package/dist/a2a/a2a-event.js.map +1 -0
  117. package/dist/a2a/a2a-job.d.ts +58 -0
  118. package/dist/a2a/a2a-job.d.ts.map +1 -0
  119. package/dist/a2a/a2a-job.js +264 -0
  120. package/dist/a2a/a2a-job.js.map +1 -0
  121. package/dist/a2a/a2a-stream.d.ts +39 -0
  122. package/dist/a2a/a2a-stream.d.ts.map +1 -0
  123. package/dist/a2a/a2a-stream.js +290 -0
  124. package/dist/a2a/a2a-stream.js.map +1 -0
  125. package/dist/a2a/errors.d.ts +29 -0
  126. package/dist/a2a/errors.d.ts.map +1 -0
  127. package/dist/a2a/errors.js +48 -0
  128. package/dist/a2a/errors.js.map +1 -0
  129. package/dist/a2a/index.d.ts +12 -0
  130. package/dist/a2a/index.d.ts.map +1 -0
  131. package/dist/a2a/index.js +11 -0
  132. package/dist/a2a/index.js.map +1 -0
  133. package/dist/a2a/producer/auth-filter.d.ts +34 -0
  134. package/dist/a2a/producer/auth-filter.d.ts.map +1 -0
  135. package/dist/a2a/producer/auth-filter.js +39 -0
  136. package/dist/a2a/producer/auth-filter.js.map +1 -0
  137. package/dist/a2a/producer/card-builder.d.ts +59 -0
  138. package/dist/a2a/producer/card-builder.d.ts.map +1 -0
  139. package/dist/a2a/producer/card-builder.js +59 -0
  140. package/dist/a2a/producer/card-builder.js.map +1 -0
  141. package/dist/a2a/producer/dispatcher.d.ts +276 -0
  142. package/dist/a2a/producer/dispatcher.d.ts.map +1 -0
  143. package/dist/a2a/producer/dispatcher.js +896 -0
  144. package/dist/a2a/producer/dispatcher.js.map +1 -0
  145. package/dist/a2a/producer/index.d.ts +26 -0
  146. package/dist/a2a/producer/index.d.ts.map +1 -0
  147. package/dist/a2a/producer/index.js +23 -0
  148. package/dist/a2a/producer/index.js.map +1 -0
  149. package/dist/a2a/producer/mount.d.ts +75 -0
  150. package/dist/a2a/producer/mount.d.ts.map +1 -0
  151. package/dist/a2a/producer/mount.js +422 -0
  152. package/dist/a2a/producer/mount.js.map +1 -0
  153. package/dist/a2a/producer/public-url-cache.d.ts +73 -0
  154. package/dist/a2a/producer/public-url-cache.d.ts.map +1 -0
  155. package/dist/a2a/producer/public-url-cache.js +0 -0
  156. package/dist/a2a/producer/public-url-cache.js.map +1 -0
  157. package/dist/a2a/producer/registry.d.ts +138 -0
  158. package/dist/a2a/producer/registry.d.ts.map +1 -0
  159. package/dist/a2a/producer/registry.js +117 -0
  160. package/dist/a2a/producer/registry.js.map +1 -0
  161. package/dist/a2a/producer/sse-emitter.d.ts +85 -0
  162. package/dist/a2a/producer/sse-emitter.d.ts.map +1 -0
  163. package/dist/a2a/producer/sse-emitter.js +405 -0
  164. package/dist/a2a/producer/sse-emitter.js.map +1 -0
  165. package/dist/a2a/producer/state-translator.d.ts +63 -0
  166. package/dist/a2a/producer/state-translator.d.ts.map +1 -0
  167. package/dist/a2a/producer/state-translator.js +108 -0
  168. package/dist/a2a/producer/state-translator.js.map +1 -0
  169. package/dist/a2a/producer/task-store.d.ts +128 -0
  170. package/dist/a2a/producer/task-store.d.ts.map +1 -0
  171. package/dist/a2a/producer/task-store.js +128 -0
  172. package/dist/a2a/producer/task-store.js.map +1 -0
  173. package/dist/agent.d.ts +72 -0
  174. package/dist/agent.d.ts.map +1 -1
  175. package/dist/agent.js +618 -13
  176. package/dist/agent.js.map +1 -1
  177. package/dist/api-runtime.d.ts +25 -0
  178. package/dist/api-runtime.d.ts.map +1 -1
  179. package/dist/api-runtime.js +75 -2
  180. package/dist/api-runtime.js.map +1 -1
  181. package/dist/claim-dispatcher.d.ts +126 -0
  182. package/dist/claim-dispatcher.d.ts.map +1 -0
  183. package/dist/claim-dispatcher.js +478 -0
  184. package/dist/claim-dispatcher.js.map +1 -0
  185. package/dist/express.d.ts.map +1 -1
  186. package/dist/express.js +33 -6
  187. package/dist/express.js.map +1 -1
  188. package/dist/inbound-job-dispatch.d.ts +105 -0
  189. package/dist/inbound-job-dispatch.d.ts.map +1 -0
  190. package/dist/inbound-job-dispatch.js +335 -0
  191. package/dist/inbound-job-dispatch.js.map +1 -0
  192. package/dist/index.d.ts +37 -4
  193. package/dist/index.d.ts.map +1 -1
  194. package/dist/index.js +29 -3
  195. package/dist/index.js.map +1 -1
  196. package/dist/job-context.d.ts +107 -0
  197. package/dist/job-context.d.ts.map +1 -0
  198. package/dist/job-context.js +95 -0
  199. package/dist/job-context.js.map +1 -0
  200. package/dist/jobs-cancel-route.d.ts +36 -0
  201. package/dist/jobs-cancel-route.d.ts.map +1 -0
  202. package/dist/jobs-cancel-route.js +60 -0
  203. package/dist/jobs-cancel-route.js.map +1 -0
  204. package/dist/jobs-helper-tools.d.ts +48 -0
  205. package/dist/jobs-helper-tools.d.ts.map +1 -0
  206. package/dist/jobs-helper-tools.js +133 -0
  207. package/dist/jobs-helper-tools.js.map +1 -0
  208. package/dist/llm-agent.d.ts +62 -53
  209. package/dist/llm-agent.d.ts.map +1 -1
  210. package/dist/llm-agent.js +211 -292
  211. package/dist/llm-agent.js.map +1 -1
  212. package/dist/llm-provider.d.ts +4 -4
  213. package/dist/llm.d.ts +4 -1
  214. package/dist/llm.d.ts.map +1 -1
  215. package/dist/llm.js +7 -17
  216. package/dist/llm.js.map +1 -1
  217. package/dist/mesh-job-submitter.d.ts +83 -0
  218. package/dist/mesh-job-submitter.d.ts.map +1 -0
  219. package/dist/mesh-job-submitter.js +143 -0
  220. package/dist/mesh-job-submitter.js.map +1 -0
  221. package/dist/proxy.d.ts +30 -0
  222. package/dist/proxy.d.ts.map +1 -1
  223. package/dist/proxy.js +351 -1
  224. package/dist/proxy.js.map +1 -1
  225. package/dist/resolver-meshjob.d.ts +170 -0
  226. package/dist/resolver-meshjob.d.ts.map +1 -0
  227. package/dist/resolver-meshjob.js +159 -0
  228. package/dist/resolver-meshjob.js.map +1 -0
  229. package/dist/route.d.ts +4 -0
  230. package/dist/route.d.ts.map +1 -1
  231. package/dist/route.js.map +1 -1
  232. package/dist/schema-normalize.d.ts +62 -0
  233. package/dist/schema-normalize.d.ts.map +1 -0
  234. package/dist/schema-normalize.js +128 -0
  235. package/dist/schema-normalize.js.map +1 -0
  236. package/dist/sse-stream.d.ts +44 -0
  237. package/dist/sse-stream.d.ts.map +1 -0
  238. package/dist/sse-stream.js +173 -0
  239. package/dist/sse-stream.js.map +1 -0
  240. package/dist/types.d.ts +351 -9
  241. package/dist/types.d.ts.map +1 -1
  242. package/package.json +4 -3
@@ -0,0 +1,173 @@
1
+ /**
2
+ * SSE streaming helper for Express route handlers.
3
+ *
4
+ * Pipes any ``AsyncIterable<string>`` to an Express ``Response`` as
5
+ * ``text/event-stream``. Designed to be called from inside a ``mesh.route``
6
+ * handler — for example, to forward chunks from a remote streaming tool to
7
+ * a browser client via SSE.
8
+ *
9
+ * Wire format mirrors the Python ``mesh.route`` SSE adapter:
10
+ * - ``data: <chunk>\n\n`` per item
11
+ * - ``data: [DONE]\n\n`` terminator on normal completion
12
+ * - ``event: error\ndata: <json>\n\n`` on per-chunk error
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * import { mesh } from "@mcpmesh/sdk";
17
+ *
18
+ * app.post("/plan", mesh.route(["trip_planner"], async (req, res, { trip_planner }) => {
19
+ * if (!trip_planner) return res.status(503).end();
20
+ * await mesh.sseStream(res, trip_planner.stream(req.body));
21
+ * }));
22
+ * ```
23
+ */
24
+ const SSE_HEADERS = {
25
+ "Content-Type": "text/event-stream",
26
+ "Cache-Control": "no-cache",
27
+ Connection: "keep-alive",
28
+ // Disable nginx response buffering so chunks reach the browser immediately
29
+ "X-Accel-Buffering": "no",
30
+ };
31
+ /**
32
+ * Format a single chunk as SSE ``data:`` lines per spec.
33
+ *
34
+ * Each newline in the chunk becomes its own ``data:`` line; the record is
35
+ * terminated by a blank line. Empty chunks still emit a single ``data:``
36
+ * line so consumers see a heartbeat-style event (matches Python behavior).
37
+ */
38
+ function frameChunkAsSSE(chunk) {
39
+ // splitlines() in Python splits on any line boundary; in JS we normalize
40
+ // CRLF to LF first then split on \n. An empty chunk still emits one frame.
41
+ const normalized = chunk.replace(/\r\n/g, "\n");
42
+ const lines = normalized === "" ? [""] : normalized.split("\n");
43
+ return lines.map((l) => `data: ${l}\n`).join("") + "\n";
44
+ }
45
+ /**
46
+ * Pipe an ``AsyncIterable<string>`` to an Express ``Response`` as SSE.
47
+ *
48
+ * Sets the standard SSE headers, writes one ``data: <chunk>\n\n`` frame per
49
+ * item from the iterable, and terminates with ``data: [DONE]\n\n``. On
50
+ * per-chunk error (e.g. the upstream stream throws), writes
51
+ * ``event: error\ndata: <json>\n\n`` and ends the response.
52
+ *
53
+ * Resolves when the response has been fully written. Callers do not need to
54
+ * call ``res.end()`` themselves.
55
+ *
56
+ * If the consumer disconnects mid-stream (``res.writableEnded``), iteration
57
+ * stops cleanly via the iterable's ``return()`` method (so the upstream
58
+ * proxy stream's ``finally`` block can release its underlying reader).
59
+ *
60
+ * @param res - Express response object
61
+ * @param source - Async iterable yielding strings
62
+ */
63
+ export async function sseStream(res, source) {
64
+ // Set headers if not already sent. Use writeHead for a single atomic flush
65
+ // so the browser sees the full set immediately (some proxies buffer until
66
+ // headers arrive). If the caller already wrote headers we just continue.
67
+ if (!res.headersSent) {
68
+ for (const [k, v] of Object.entries(SSE_HEADERS)) {
69
+ res.setHeader(k, v);
70
+ }
71
+ // Some Express versions need an explicit flushHeaders() to commit before
72
+ // the first data frame; call it if available.
73
+ if (typeof res.flushHeaders === "function") {
74
+ res.flushHeaders();
75
+ }
76
+ }
77
+ // Track whether end() has been called so we never double-end (which would
78
+ // throw "ERR_STREAM_WRITE_AFTER_END" on Node). ``writable`` flips to false
79
+ // when further writes will fail (e.g. socket closed) but we still want to
80
+ // call res.end() exactly once for cleanup.
81
+ let endCalled = false;
82
+ let writable = true;
83
+ const safeEnd = () => {
84
+ if (endCalled)
85
+ return;
86
+ endCalled = true;
87
+ try {
88
+ res.end();
89
+ }
90
+ catch {
91
+ // ignore — response may already be torn down
92
+ }
93
+ };
94
+ const safeWrite = (data) => {
95
+ if (!writable)
96
+ return false;
97
+ if (res.writableEnded || res.destroyed) {
98
+ writable = false;
99
+ return false;
100
+ }
101
+ try {
102
+ return res.write(data);
103
+ }
104
+ catch {
105
+ writable = false;
106
+ return false;
107
+ }
108
+ };
109
+ const iterator = source[Symbol.asyncIterator]();
110
+ try {
111
+ while (true) {
112
+ const { value, done } = await iterator.next();
113
+ if (done)
114
+ break;
115
+ if (typeof value !== "string") {
116
+ // v1 supports str only — surface a structured error and stop
117
+ const errPayload = JSON.stringify({
118
+ error: `sseStream: expected string chunk, got ${typeof value}`,
119
+ type: "TypeError",
120
+ });
121
+ safeWrite(`event: error\ndata: ${errPayload}\n\n`);
122
+ safeEnd();
123
+ // best-effort cleanup of upstream
124
+ if (typeof iterator.return === "function") {
125
+ try {
126
+ await iterator.return();
127
+ }
128
+ catch {
129
+ // ignore
130
+ }
131
+ }
132
+ return;
133
+ }
134
+ const wroteOk = safeWrite(frameChunkAsSSE(value));
135
+ if (!wroteOk) {
136
+ // Consumer disconnected (or write threw) — clean up upstream and end.
137
+ if (typeof iterator.return === "function") {
138
+ try {
139
+ await iterator.return();
140
+ }
141
+ catch {
142
+ // ignore
143
+ }
144
+ }
145
+ safeEnd();
146
+ return;
147
+ }
148
+ }
149
+ safeWrite("data: [DONE]\n\n");
150
+ safeEnd();
151
+ }
152
+ catch (err) {
153
+ const errPayload = JSON.stringify({
154
+ error: err instanceof Error ? err.message : String(err),
155
+ type: err instanceof Error ? err.constructor.name : "Error",
156
+ });
157
+ safeWrite(`event: error\ndata: ${errPayload}\n\n`);
158
+ safeEnd();
159
+ // Release the upstream iterator if the failure originated outside the
160
+ // iterator itself (e.g. safeWrite threw). Without this, an upstream
161
+ // proxy.stream() generator's finally block — which cancels the
162
+ // OkHttp/fetch reader — never runs until GC, leaking the connection.
163
+ if (typeof iterator.return === "function") {
164
+ try {
165
+ await iterator.return();
166
+ }
167
+ catch {
168
+ /* upstream cleanup is best-effort */
169
+ }
170
+ }
171
+ }
172
+ }
173
+ //# sourceMappingURL=sse-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-stream.js","sourceRoot":"","sources":["../src/sse-stream.ts"],"names":[],"mappings":"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"}
package/dist/types.d.ts CHANGED
@@ -37,6 +37,76 @@ export interface MediaParamMeta {
37
37
  */
38
38
  export declare function mediaParam(mediaType?: string): z.ZodOptional<z.ZodString>;
39
39
  export type { JsAgentHandle, JsMeshEvent, JsAgentSpec, JsToolSpec, JsDependencySpec, JsLlmAgentSpec, JsLlmToolInfo, JsLlmProviderInfo, } from "@mcpmesh/core";
40
+ /**
41
+ * Type marker for DDDI injection of a long-running-task handle (Phase 1
42
+ * — MeshJob substrate).
43
+ *
44
+ * Used as a parameter-position type annotation on a tool registered with
45
+ * `agent.addTool({ task: true, ... })` (producer) or `mesh.route(...)`
46
+ * with a `task=true` dependency (consumer). The mesh runtime injects:
47
+ *
48
+ * - On the **producer side** (a tool decorated `{ task: true }` invoked
49
+ * via the inbound job-dispatch path or claim worker): a
50
+ * `JobController` exposing
51
+ * `await job.updateProgress(...)` /
52
+ * `await job.complete(result)` / `await job.fail(error)`.
53
+ *
54
+ * - On the **consumer side** (a function depending on a remote
55
+ * `task=true` capability): a submitter that returns a `JobProxy`
56
+ * exposing `await proxy.wait(timeoutSecs?)` / `await proxy.status()`
57
+ * / `await proxy.cancel(reason?)`.
58
+ *
59
+ * A MeshJob parameter is **orthogonal** to positional MeshTool slots
60
+ * per `MESHJOB_DDDI_CONTRACT.md` — it does not consume a positional
61
+ * dependency-injection index.
62
+ *
63
+ * If a function declaring a MeshJob param is invoked as a regular
64
+ * synchronous tool call (no `X-Mesh-Job-Id` header, no claim path),
65
+ * the runtime injects `null` for the slot. Producer code SHOULD treat
66
+ * `null` as a fast path with no progress reporting.
67
+ *
68
+ * The type itself is structurally minimal because TypeScript erases
69
+ * structural types at runtime; the DDDI resolver records signature
70
+ * positions explicitly when the SDK builds the tool definition (see
71
+ * `__tests__/resolver-meshjob.spec.ts`).
72
+ *
73
+ * @example Producer
74
+ * ```typescript
75
+ * agent.addTool({
76
+ * name: "plan_trip",
77
+ * capability: "plan_trip",
78
+ * task: true,
79
+ * parameters: z.object({ userId: z.string() }),
80
+ * dependencies: [{ capability: "weather" }],
81
+ * meshJobParamIndex: 2, // signature position of `job` below
82
+ * execute: async (
83
+ * { userId },
84
+ * weather: McpMeshTool | null = null,
85
+ * job: MeshJob | null = null,
86
+ * ) => {
87
+ * await job?.updateProgress(0.1, "checking weather");
88
+ * const w = await weather?.({ city: "PDX" });
89
+ * await job?.updateProgress(0.9, "done");
90
+ * return { itinerary: w };
91
+ * },
92
+ * });
93
+ * ```
94
+ */
95
+ export interface MeshJob {
96
+ jobId?: string;
97
+ updateProgress?(progress: number, message?: string): Promise<void>;
98
+ complete?(result: unknown): Promise<void>;
99
+ fail?(error: string): Promise<void>;
100
+ submit?(payload?: Record<string, unknown>, options?: {
101
+ maxDuration?: number;
102
+ maxRetries?: number;
103
+ totalDeadline?: number;
104
+ ownerInstanceId?: string;
105
+ }): Promise<MeshJob>;
106
+ wait?(timeoutSecs?: number): Promise<unknown>;
107
+ status?(): Promise<Record<string, unknown>>;
108
+ cancel?(reason?: string): Promise<void>;
109
+ }
40
110
  /**
41
111
  * Dependency specification for mesh tool DI.
42
112
  *
@@ -69,6 +139,16 @@ export type DependencySpec = string | {
69
139
  tags?: TagSpec[];
70
140
  /** Version constraint (e.g., ">=2.0.0") */
71
141
  version?: string;
142
+ /** Issue #547: optional Zod schema describing the expected provider response.
143
+ * When set, the registry uses the canonical hash to filter producers
144
+ * whose output schema matches under {@link matchMode}. Backward compat:
145
+ * if omitted, no schema check is performed.
146
+ */
147
+ expectedSchema?: z.ZodType<unknown>;
148
+ /** Issue #547: how to compare producer output schema against
149
+ * {@link expectedSchema}. Defaults to "subset" when expectedSchema is set.
150
+ */
151
+ matchMode?: "subset" | "strict";
72
152
  };
73
153
  /**
74
154
  * Normalized dependency specification (after processing).
@@ -77,6 +157,13 @@ export interface NormalizedDependency {
77
157
  capability: string;
78
158
  tags: TagSpec[];
79
159
  version?: string;
160
+ /** Issue #547: raw JSON Schema (post-zodToJsonSchema) for the expected
161
+ * dependency response. Normalization is deferred to the heartbeat pipeline
162
+ * to keep decorator-time work cheap and consistent with Python parity.
163
+ */
164
+ expectedSchemaRaw?: object;
165
+ /** Issue #547: schema match mode ("subset" or "strict"). */
166
+ matchMode?: "subset" | "strict";
80
167
  }
81
168
  /**
82
169
  * Resolved dependency info from registry.
@@ -155,6 +242,42 @@ export interface DependencyKwargs {
155
242
  /** Max response body size in bytes. Defaults to 10MB (10485760) */
156
243
  maxResponseSize?: number;
157
244
  }
245
+ /**
246
+ * Per-tool A2A bridge configuration (issue #917).
247
+ *
248
+ * When set on a `MeshToolDef`, the framework constructs a per-config
249
+ * `A2AClient` and injects it into the user's `execute` function as the
250
+ * LAST positional argument (after the standard dependency proxies and
251
+ * — for `task: true` tools — after the `JobController`). Multiple
252
+ * tools sharing the same `(url, skillId, auth, timeoutMs)` tuple share
253
+ * one cached client so the underlying undici connection pool is
254
+ * amortised.
255
+ *
256
+ * The presence of `a2aConfig` ALSO opts the tool into auto-tag
257
+ * injection: at heartbeat-build time the framework appends the
258
+ * surrounding agent name to the tool's tags array so downstream
259
+ * resolvers can pin a specific bridge via the tag selector. Mirrors
260
+ * Python's `@mesh.a2a_consumer` and Java's `@A2AConsumer`.
261
+ */
262
+ export interface MeshA2AConfig {
263
+ /** Required: A2A endpoint URL. Trailing slashes are stripped. */
264
+ url: string;
265
+ /** Optional: skill ID to invoke. Defaults to the tool's `capability`. */
266
+ skillId?: string;
267
+ /** Optional: bearer credential (instance or `{ tokenEnv }` / `{ token }` config). */
268
+ auth?: {
269
+ token?: string;
270
+ tokenEnv?: string;
271
+ } | {
272
+ authorizationHeader: () => string;
273
+ };
274
+ /** Optional: per-call deadline (ms). Default 30_000. */
275
+ timeoutMs?: number;
276
+ /** Optional: initial backoff between `tasks/get` polls (ms). Default 500. */
277
+ pollIntervalMs?: number;
278
+ /** Optional: cap on the backoff between polls (ms). Default 2_000. */
279
+ pollIntervalMaxMs?: number;
280
+ }
158
281
  /**
159
282
  * Tool definition for MeshAgent.
160
283
  */
@@ -171,6 +294,143 @@ export interface MeshToolDef<T extends z.ZodType = z.ZodType> {
171
294
  version?: string;
172
295
  /** Zod schema for input parameters */
173
296
  parameters: T;
297
+ /**
298
+ * Issue #547: Zod schema for the tool's return value.
299
+ *
300
+ * Optional, opt-in. When provided, the SDK extracts and normalizes the
301
+ * output schema and ships it to the registry alongside the input schema
302
+ * so consumers can match producers by canonical schema hash.
303
+ *
304
+ * Zod cannot infer the return type from the handler signature (unlike
305
+ * Python's reflection on Pydantic return annotations), so users must
306
+ * provide this explicitly.
307
+ */
308
+ outputSchema?: z.ZodType<unknown>;
309
+ /**
310
+ * Issue #547 Phase 4: per-tool override for the schema verdict policy.
311
+ *
312
+ * When `true` (default), a BLOCK verdict from the schema normalizer
313
+ * refuses agent startup. Set to `false` as a producer-side escape hatch
314
+ * to demote BLOCK to WARN for this specific tool. Wins even when the
315
+ * cluster-wide `MCP_MESH_SCHEMA_STRICT=true` env var is set (which
316
+ * otherwise promotes WARN to BLOCK across all tools).
317
+ */
318
+ outputSchemaStrict?: boolean;
319
+ /**
320
+ * Phase 1 MeshJob substrate: mark this tool as long-running.
321
+ *
322
+ * When `true`, producers advertise `task=true` in their tool
323
+ * metadata so consumers know to invoke this capability via job
324
+ * semantics (`mesh.MeshJob.submit(...) → wait/poll`) rather than as
325
+ * a regular synchronous `tools/call`. The actual job-context binding
326
+ * happens at inbound call time via the dispatch wrapper.
327
+ *
328
+ * Constraints (validated at `addTool` time):
329
+ *
330
+ * - `execute` MUST be an `async` function (long-running tools need
331
+ * a Promise-based control flow to drive `MeshJob.updateProgress()`,
332
+ * cancellation, and outbound polling). Sync `execute` raises a
333
+ * clear error at registration.
334
+ *
335
+ * Default: `false` (regular synchronous tool). See
336
+ * `MESHJOB_DESIGN.org` "Producer-side flow".
337
+ */
338
+ task?: boolean;
339
+ /**
340
+ * Phase 1 MeshJob substrate (producer-side): signature position of
341
+ * the `MeshJob` parameter on the user's `execute` function.
342
+ *
343
+ * When set on a `task: true` tool, the runtime injects a
344
+ * `JobController` at this position when the tool is invoked under
345
+ * a job context (claim path or inbound call carrying
346
+ * `X-Mesh-Job-Id`). When the tool is invoked synchronously without
347
+ * a job context, the runtime injects `null` per
348
+ * `MESHJOB_DDDI_CONTRACT.md`.
349
+ *
350
+ * Position 0 is reserved for `args`; deps start at 1. The
351
+ * `MeshJob` slot is orthogonal to MeshTool positional indexing —
352
+ * MeshTool deps skip the `meshJobParamIndex` position and shift
353
+ * accordingly. See `resolver-meshjob.ts` for the contract test
354
+ * seam.
355
+ *
356
+ * Producer example with one MeshTool dep and a MeshJob slot:
357
+ * ```ts
358
+ * agent.addTool({
359
+ * task: true,
360
+ * dependencies: ["weather"],
361
+ * meshJobParamIndex: 2, // job at sig pos 2
362
+ * execute: async (
363
+ * { city },
364
+ * weather: McpMeshTool | null = null, // dep at sig pos 1
365
+ * job: MeshJob | null = null, // controller at sig pos 2
366
+ * ) => { ... },
367
+ * });
368
+ * ```
369
+ */
370
+ meshJobParamIndex?: number;
371
+ /**
372
+ * Phase 1 MeshJob substrate (consumer-side): index into
373
+ * `dependencies` whose proxy should be injected as a
374
+ * `MeshJobSubmitter` (returns a `JobProxy`) instead of a regular
375
+ * `McpMeshTool` proxy.
376
+ *
377
+ * Use this when the consumer wants to call a remote `task: true`
378
+ * capability via job semantics (submit + poll/wait) rather than as
379
+ * a regular synchronous `tools/call`. The user function receives a
380
+ * `MeshJob`-typed handle at the dep's positional slot.
381
+ *
382
+ * Consumer example:
383
+ * ```ts
384
+ * agent.addTool({
385
+ * name: "commission_report",
386
+ * dependencies: ["generate_report"],
387
+ * meshJobDepIndex: 0, // generate_report is task=true
388
+ * execute: async ({ userId }, generateReport: MeshJob | null = null) => {
389
+ * const proxy = await generateReport!.submit(
390
+ * { user_id: userId, sections: ["intro"] },
391
+ * { maxDuration: 60 },
392
+ * );
393
+ * return await proxy.wait(60);
394
+ * },
395
+ * });
396
+ * ```
397
+ */
398
+ meshJobDepIndex?: number;
399
+ /**
400
+ * Issue #894: per-tool retry-eligible exception whitelist.
401
+ *
402
+ * When a `task: true` handler raises an Error whose constructor matches
403
+ * one of the entries (`err instanceof cls`), the dispatch wrapper calls
404
+ * `controller.releaseLease(reason)` instead of `controller.fail(reason)`.
405
+ * The registry then resets `owner_instance_id` so a peer replica can
406
+ * re-claim within ~5s — useful for transient failures (network blips,
407
+ * upstream unavailable) where the next attempt on a different replica
408
+ * is likely to succeed.
409
+ *
410
+ * Constraints (validated at `addTool` time):
411
+ *
412
+ * - requires `task: true` (no-op for synchronous tools — non-job
413
+ * handlers don't have a controller, so retry has no meaning);
414
+ * - entries must be Error constructor classes (functions); anything
415
+ * else throws at registration.
416
+ *
417
+ * Default: `undefined` (no retry-eligible exceptions; all raises mark
418
+ * the row failed). Empty array is equivalent.
419
+ *
420
+ * @example
421
+ * ```ts
422
+ * agent.addTool({
423
+ * task: true,
424
+ * retryOn: [TransientUpstreamError, AbortError],
425
+ * execute: async (args, job: MeshJob | null = null) => {
426
+ * // If this throws TransientUpstreamError, the registry will
427
+ * // hand the job to a peer replica within ~5s.
428
+ * return await callFlakeyApi(args);
429
+ * },
430
+ * });
431
+ * ```
432
+ */
433
+ retryOn?: Array<new (...args: unknown[]) => Error>;
174
434
  /**
175
435
  * Dependencies required by this tool.
176
436
  * Injected positionally as McpMeshTool params after args.
@@ -192,6 +452,13 @@ export interface MeshToolDef<T extends z.ZodType = z.ZodType> {
192
452
  * Supports duplicate capabilities with different settings.
193
453
  */
194
454
  dependencyKwargs?: DependencyKwargs[];
455
+ /**
456
+ * Issue #917: A2A bridge configuration. When set, the framework
457
+ * constructs a cached `A2AClient` and injects it at the trailing
458
+ * positional slot of `execute` (after deps + JobController). Also
459
+ * opts the tool into consumer-name auto-tag injection.
460
+ */
461
+ a2aConfig?: MeshA2AConfig;
195
462
  /**
196
463
  * Tool implementation.
197
464
  *
@@ -225,7 +492,7 @@ export interface MeshToolDef<T extends z.ZodType = z.ZodType> {
225
492
  * }
226
493
  * ```
227
494
  */
228
- execute: (args: z.infer<T>, ...deps: (McpMeshTool | null)[]) => Promise<unknown> | unknown;
495
+ execute: (args: z.infer<T>, ...deps: (McpMeshTool | MeshJob | null)[]) => Promise<unknown> | unknown;
229
496
  }
230
497
  /**
231
498
  * Proxy for calling remote MCP tools.
@@ -261,6 +528,27 @@ export interface McpMeshTool {
261
528
  callTool(toolName: string, args?: Record<string, unknown>, options?: {
262
529
  headers?: Record<string, string>;
263
530
  }): Promise<unknown>;
531
+ /**
532
+ * Stream text chunks from a remote ``Stream[str]`` tool.
533
+ *
534
+ * Returns an async iterable that yields each chunk the producer emits via
535
+ * MCP ``notifications/progress``. The final result message ends the stream
536
+ * (its content is NOT yielded — iterate to get the whole stream).
537
+ *
538
+ * NOTE: If the producer doesn't actually emit progress notifications, the
539
+ * underlying SSE response will only contain the final ``result`` and this
540
+ * iterable will yield nothing.
541
+ *
542
+ * @example
543
+ * ```typescript
544
+ * for await (const chunk of planner.stream({ destination: "Tokyo" })) {
545
+ * process.stdout.write(chunk);
546
+ * }
547
+ * ```
548
+ */
549
+ stream(args?: Record<string, unknown>, options?: {
550
+ headers?: Record<string, string>;
551
+ }): AsyncIterable<string>;
264
552
  /**
265
553
  * Get the endpoint URL for this dependency.
266
554
  */
@@ -291,26 +579,49 @@ export interface ToolMeta {
291
579
  tags: string[];
292
580
  description: string;
293
581
  inputSchema?: string;
582
+ /** Issue #547: raw JSON Schema (post-zodToJsonSchema) for return type. */
583
+ outputSchemaRaw?: object;
584
+ /** Issue #547 Phase 4: per-tool override for the schema verdict policy
585
+ * (default true). When false, a BLOCK verdict for this tool is demoted
586
+ * to WARN instead of refusing startup. */
587
+ outputSchemaStrict?: boolean;
294
588
  /** Normalized dependencies for this tool */
295
589
  dependencies: NormalizedDependency[];
296
590
  /** Per-dependency configuration indexed by position (matches dependencies array) */
297
591
  dependencyKwargs?: DependencyKwargs[];
592
+ /** Phase 1 MeshJob substrate: producer flag advertising this tool as
593
+ * long-running so consumers invoke via job semantics. See
594
+ * MeshToolDef.task for full semantics. */
595
+ task?: boolean;
596
+ /** Phase 1 MeshJob substrate: producer-side signature position of
597
+ * the MeshJob param. Used by the inbound dispatch wrapper to inject
598
+ * a JobController when running as a job. */
599
+ meshJobParamIndex?: number;
600
+ /** Phase 1 MeshJob substrate: consumer-side index into dependencies
601
+ * whose slot should hold a MeshJobSubmitter (instead of a regular
602
+ * McpMeshTool proxy). */
603
+ meshJobDepIndex?: number;
604
+ /** Issue #917: A2A bridge marker — when true, the heartbeat-build
605
+ * pass appends the surrounding agent name to the tool's tags before
606
+ * the registry sees them. */
607
+ a2aConsumer?: boolean;
608
+ /** Issue #917: agent name captured at addTool time so the heartbeat
609
+ * pass injects the correct value (in case the agent is renamed via
610
+ * env between addTool and heartbeat). */
611
+ a2aAgentName?: string;
298
612
  }
299
613
  /**
300
614
  * LLM provider specification.
301
- * Can be a direct LiteLLM provider string or mesh delegation config.
615
+ * Mesh delegation only describes the capability/tag filter used to
616
+ * discover an ``@mesh.llm_provider`` in the mesh.
302
617
  *
303
618
  * @example
304
619
  * ```typescript
305
- * // Direct LiteLLM provider
306
- * provider: "claude"
307
- * provider: "openai"
308
- *
309
620
  * // Mesh delegation (discover LLM provider via mesh)
310
621
  * provider: { capability: "llm", tags: ["+claude"] }
311
622
  * ```
312
623
  */
313
- export type LlmProviderSpec = string | {
624
+ export type LlmProviderSpec = {
314
625
  /** Capability name to discover in mesh */
315
626
  capability: string;
316
627
  /** Tags for filtering (e.g., ["+claude", "-deprecated"]) */
@@ -346,7 +657,7 @@ export interface LlmMeta {
346
657
  toolCalls: LlmToolCall[];
347
658
  /** Model used for generation */
348
659
  model: string;
349
- /** Provider used (litellm provider name or mesh agent ID) */
660
+ /** Provider used (e.g., ``mesh:<endpoint>`` or ``mesh:<capability>``) */
350
661
  provider: string;
351
662
  }
352
663
  /**
@@ -476,7 +787,7 @@ export interface MeshLlmConfig<TParams extends z.ZodType, TReturns extends z.Zod
476
787
  tags?: string[];
477
788
  /** Version of this capability. Defaults to "1.0.0" */
478
789
  version?: string;
479
- /** LLM provider - direct string (LiteLLM) or mesh delegation object */
790
+ /** LLM provider — mesh-delegation spec (capability + tag filter) */
480
791
  provider: LlmProviderSpec;
481
792
  /** Model override (e.g., "anthropic/claude-sonnet-4-5") */
482
793
  model?: string;
@@ -567,6 +878,37 @@ export interface LlmAgent<T = string> {
567
878
  * @param prompt - New system prompt (inline or "file://path.hbs")
568
879
  */
569
880
  setSystemPrompt(prompt: string): void;
881
+ /**
882
+ * Stream the assistant's text response chunk-by-chunk from a streaming
883
+ * mesh-delegated provider (Python's ``@mesh.llm_provider`` exposes a
884
+ * ``process_chat_stream`` MCP tool tagged ``ai.mcpmesh.stream``).
885
+ *
886
+ * **Tag opt-in (REQUIRED):** TypeScript users must explicitly add
887
+ * ``"ai.mcpmesh.stream"`` to their provider tags to discriminate the
888
+ * streaming variant from the buffered one. Python's ``@mesh.llm`` does
889
+ * this automatically based on the function's ``Stream[str]`` return type;
890
+ * TS does not perform that return-type analysis at decorator time, so the
891
+ * opt-in must be explicit:
892
+ *
893
+ * ```ts
894
+ * server.addTool(mesh.llm({
895
+ * name: "chat_stream",
896
+ * provider: { capability: "llm", tags: ["+claude", "ai.mcpmesh.stream"] },
897
+ * parameters: z.object({ message: z.string() }),
898
+ * execute: async ({ message }, { llm }) => {
899
+ * for await (const chunk of llm.stream(message)) {
900
+ * process.stdout.write(chunk);
901
+ * }
902
+ * return "ok";
903
+ * },
904
+ * }));
905
+ * ```
906
+ *
907
+ * @param message - User message (string or multi-turn array)
908
+ * @param options - Same runtime overrides as the callable form
909
+ * @returns AsyncIterable of text chunks (final accumulated result is NOT yielded)
910
+ */
911
+ stream(message: LlmMessageInput, options?: LlmCallOptions): AsyncIterable<string>;
570
912
  }
571
913
  /**
572
914
  * Context merge mode for runtime context override.