@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,405 @@
1
+ import { buildArtifactUpdateFrame, buildResubscribeStream, buildSendSubscribeStream, buildStatusUpdateFrame, buildTaskFromStatus, JSONRPC_PARSE_ERROR, } from "./dispatcher.js";
2
+ import { A2A_COMPLETED, A2A_FAILED, A2A_CANCELED, A2A_WORKING, fromMesh, isMeshTerminal, meshStatusOf, } from "./state-translator.js";
3
+ /** Poll cadence for the long-running stream (spec §4.6 sequence diagram: 1s). */
4
+ export const POLL_INTERVAL_MILLIS = 1000;
5
+ /** Keepalive interval — SSE comment frame after this much inactivity (spec §5.1: 15s). */
6
+ export const KEEPALIVE_MILLIS = 15_000;
7
+ /** Maximum total stream duration as a defensive cap (1 hour, matches Java). */
8
+ export const MAX_STREAM_MILLIS = 60 * 60_000;
9
+ /**
10
+ * Consecutive `proxy.status()` failures to tolerate during the SSE poll
11
+ * loop before giving up. Spec §4.4: transient unreachability is NOT
12
+ * authoritative evidence the job is dead, so we keep emitting
13
+ * `state=working` status frames and continue polling until this cap.
14
+ * Once reached we close the SSE stream WITHOUT marking the task store
15
+ * record terminal — subsequent `tasks/get` resumes polling normally.
16
+ *
17
+ * Matches Java's `MAX_CONSECUTIVE_STATUS_FAILURES`.
18
+ */
19
+ export const MAX_CONSECUTIVE_STATUS_FAILURES = 5;
20
+ /**
21
+ * Build the SSE dispatcher middleware. Mounted in front of the JSON-RPC
22
+ * dispatcher: when the request body's `method` is `tasks/sendSubscribe`
23
+ * or `tasks/resubscribe`, this middleware consumes the request and
24
+ * streams an SSE response. Otherwise it calls `next()` and execution
25
+ * falls through to the JSON-RPC dispatcher.
26
+ *
27
+ * The middleware peeks at the parsed body (`req.body.method`) rather
28
+ * than `Accept` header — even when the client sends both, we want to
29
+ * route by JSON-RPC method to keep the dispatch deterministic.
30
+ */
31
+ export function buildSseDispatcherMiddleware(deps) {
32
+ return async function a2aSseDispatcher(req, res, next) {
33
+ const body = req.body;
34
+ if (!body || typeof body !== "object" || Array.isArray(body)) {
35
+ // Let the JSON-RPC dispatcher emit the canonical parse error.
36
+ next();
37
+ return;
38
+ }
39
+ const envelope = body;
40
+ const method = envelope["method"];
41
+ if (method !== "tasks/sendSubscribe" && method !== "tasks/resubscribe") {
42
+ next();
43
+ return;
44
+ }
45
+ const reqId = Object.prototype.hasOwnProperty.call(envelope, "id")
46
+ ? envelope["id"]
47
+ : null;
48
+ const params = readParams(envelope["params"]);
49
+ let plan;
50
+ try {
51
+ if (method === "tasks/sendSubscribe") {
52
+ plan = await buildSendSubscribeStream(reqId, params, deps);
53
+ }
54
+ else {
55
+ plan = buildResubscribeStream(reqId, params, deps.taskStore);
56
+ }
57
+ }
58
+ catch (err) {
59
+ // Unexpected dispatcher error — surface as a JSON-RPC parse
60
+ // error (HTTP 400) so the client can distinguish it from an SSE
61
+ // mid-stream failure.
62
+ res.status(400).type("application/json").send(JSON.stringify({
63
+ jsonrpc: "2.0",
64
+ error: {
65
+ code: JSONRPC_PARSE_ERROR,
66
+ message: `Dispatcher error: ${err?.message ?? String(err)}`,
67
+ },
68
+ id: reqId ?? null,
69
+ }));
70
+ return;
71
+ }
72
+ await renderSsePlan(req, res, plan, deps.taskStore);
73
+ };
74
+ }
75
+ /**
76
+ * Materialise an SSE stream-plan as an Express response. Exposed for
77
+ * advanced wiring / tests; the public mount API calls this via the
78
+ * middleware above.
79
+ */
80
+ export async function renderSsePlan(req, res, plan, taskStore) {
81
+ switch (plan.kind) {
82
+ case "error": {
83
+ res
84
+ .status(plan.httpStatus)
85
+ .type("application/json")
86
+ .send(JSON.stringify(plan.errorBody));
87
+ return;
88
+ }
89
+ case "single-frame": {
90
+ writeSseHeaders(res);
91
+ writeDataFrame(res, plan.frame);
92
+ endSse(res);
93
+ return;
94
+ }
95
+ case "sync-completed": {
96
+ writeSseHeaders(res);
97
+ writeDataFrame(res, plan.artifactFrame);
98
+ writeDataFrame(res, plan.terminalFrame);
99
+ endSse(res);
100
+ return;
101
+ }
102
+ case "long-running": {
103
+ writeSseHeaders(res);
104
+ await runLongRunningStream(req, res, plan.reqId, plan.taskId, plan.proxy, taskStore);
105
+ endSse(res);
106
+ return;
107
+ }
108
+ default: {
109
+ const exhaustive = plan;
110
+ throw new Error(`Unknown SSE plan kind: ${JSON.stringify(exhaustive)}`);
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Run the long-running poll loop (spec §5.3 long-running case):
116
+ *
117
+ * 1. Emit an initial `state=working, final=false` frame so the client
118
+ * confirms subscription liveness.
119
+ * 2. Poll `proxy.status()` every {@link POLL_INTERVAL_MILLIS} ms.
120
+ * 3. Emit a `state=working` frame only when `progress` or
121
+ * `progress_message` changed — suppresses redundant updates
122
+ * (Python `a2a.py:1057-1070`, Java's equivalent).
123
+ * 4. Emit a `: keepalive\n\n` SSE comment after {@link KEEPALIVE_MILLIS}
124
+ * of inactivity.
125
+ * 5. On terminal mesh state: attempt `proxy.wait(1.0)` for the completed
126
+ * branch, emit the artifact frame, then the terminal status frame
127
+ * (`final=true`), mark the task store record terminal, return.
128
+ */
129
+ async function runLongRunningStream(req, res, reqId, taskId, proxy, taskStore) {
130
+ const started = Date.now();
131
+ let disconnected = false;
132
+ const onClose = () => {
133
+ disconnected = true;
134
+ };
135
+ req.on("close", onClose);
136
+ res.on("close", onClose);
137
+ try {
138
+ // 1. Initial state=working frame.
139
+ if (!writeDataFrame(res, buildStatusUpdateFrame(reqId, taskId, A2A_WORKING, null, false, null))) {
140
+ return;
141
+ }
142
+ let lastProgress = undefined;
143
+ let lastMessage = undefined;
144
+ let lastEventTime = Date.now();
145
+ let consecutiveStatusFailures = 0;
146
+ // eslint-disable-next-line no-constant-condition
147
+ while (true) {
148
+ if (disconnected || res.writableEnded || res.destroyed) {
149
+ return;
150
+ }
151
+ // Stream-level cap — preserves task state in the store so callers
152
+ // can resume via tasks/resubscribe or check status via tasks/get.
153
+ // The cap protects the worker from a stuck job; it is NOT a
154
+ // job-death signal, so we emit a non-terminal status frame and
155
+ // do NOT mark the task terminal (spec §4.4: producer-side resource
156
+ // limits must not poison the task store).
157
+ if (Date.now() - started > MAX_STREAM_MILLIS) {
158
+ writeDataFrame(res, buildStatusUpdateFrame(reqId, taskId, A2A_WORKING, "stream closed: producer-side cap exceeded " +
159
+ "(task still running; reconnect via tasks/resubscribe)",
160
+ // final=false: the task is NOT terminal; we are only closing
161
+ // the SSE transport. `final=true` would signal task death to
162
+ // A2A clients.
163
+ false, null));
164
+ return;
165
+ }
166
+ let status;
167
+ try {
168
+ const raw = (await proxy.status());
169
+ status = (raw && typeof raw === "object" && !Array.isArray(raw))
170
+ ? raw
171
+ : {};
172
+ consecutiveStatusFailures = 0;
173
+ }
174
+ catch (err) {
175
+ consecutiveStatusFailures++;
176
+ // Spec §4.4 conformance: transient unreachability is NOT
177
+ // authoritative evidence the job is dead. Emit state=working
178
+ // carrying the error in status.message and CONTINUE polling.
179
+ // Do NOT mark the task store terminal.
180
+ if (!writeDataFrame(res, buildStatusUpdateFrame(reqId, taskId, A2A_WORKING, `status unavailable: ${errorTextOf(err)}`, false, null))) {
181
+ return;
182
+ }
183
+ // Transient-failure frame counts as activity — refresh
184
+ // `lastEventTime` so the keepalive branch doesn't fire a
185
+ // redundant `: keepalive\n\n` right after a data frame.
186
+ lastEventTime = Date.now();
187
+ if (consecutiveStatusFailures >= MAX_CONSECUTIVE_STATUS_FAILURES) {
188
+ // Cap hit — close the stream WITHOUT marking terminal so the
189
+ // client can retry via tasks/get / tasks/resubscribe.
190
+ return;
191
+ }
192
+ if (!(await sleepIfConnected(POLL_INTERVAL_MILLIS, req, res))) {
193
+ return;
194
+ }
195
+ continue;
196
+ }
197
+ const meshState = meshStatusOf(status);
198
+ if (isMeshTerminal(meshState)) {
199
+ const a2aState = fromMesh(meshState);
200
+ let finalResult = null;
201
+ let hasFinalResult = false;
202
+ if (a2aState === A2A_COMPLETED) {
203
+ try {
204
+ finalResult = await proxy.wait(1.0);
205
+ hasFinalResult = true;
206
+ // Emit artifact frame BEFORE the terminal status — spec
207
+ // §5.3 ordering.
208
+ if (!writeDataFrame(res, buildArtifactUpdateFrame(reqId, taskId, finalResult))) {
209
+ return;
210
+ }
211
+ }
212
+ catch {
213
+ // Best-effort: if wait() throws we skip the artifact and
214
+ // emit only the terminal status frame.
215
+ }
216
+ }
217
+ let finalMessage = null;
218
+ if (a2aState === A2A_FAILED) {
219
+ const err = status["error"];
220
+ finalMessage = (err !== null && err !== undefined && String(err).length > 0)
221
+ ? String(err)
222
+ : null;
223
+ if (!finalMessage) {
224
+ const pm = status["progress_message"];
225
+ finalMessage = (pm !== null && pm !== undefined && String(pm).length > 0)
226
+ ? String(pm)
227
+ : null;
228
+ }
229
+ }
230
+ else if (a2aState === A2A_CANCELED) {
231
+ const pm = status["progress_message"];
232
+ finalMessage = (pm !== null && pm !== undefined && String(pm).length > 0)
233
+ ? String(pm)
234
+ : null;
235
+ }
236
+ writeDataFrame(res, buildStatusUpdateFrame(reqId, taskId, a2aState, finalMessage, true, null));
237
+ // Cache the terminal envelope so subsequent tasks/get returns
238
+ // the same view as this stream's terminal frame.
239
+ const terminalEnvelope = buildTaskFromStatus(taskId, taskId, undefined, a2aState, status, finalResult, hasFinalResult);
240
+ taskStore.markTerminal(taskId, terminalEnvelope);
241
+ return;
242
+ }
243
+ const progress = status["progress"];
244
+ const progressMessage = status["progress_message"];
245
+ const now = Date.now();
246
+ const progressChanged = !primitiveOrNullishEqual(progress, lastProgress);
247
+ const messageChanged = !primitiveOrNullishEqual(progressMessage, lastMessage);
248
+ if (progressChanged || messageChanged) {
249
+ const msgText = (progressMessage !== null && progressMessage !== undefined)
250
+ ? String(progressMessage)
251
+ : null;
252
+ const progressNum = typeof progress === "number" ? progress : null;
253
+ if (!writeDataFrame(res, buildStatusUpdateFrame(reqId, taskId, A2A_WORKING, msgText, false, progressNum))) {
254
+ return;
255
+ }
256
+ lastProgress = progress;
257
+ lastMessage = progressMessage;
258
+ lastEventTime = now;
259
+ }
260
+ else if (now - lastEventTime > KEEPALIVE_MILLIS) {
261
+ // Spec §5.1: SSE comment line, ignored by parsers but resets
262
+ // proxy idle timers.
263
+ if (!writeKeepalive(res)) {
264
+ return;
265
+ }
266
+ lastEventTime = now;
267
+ }
268
+ if (!(await sleepIfConnected(POLL_INTERVAL_MILLIS, req, res))) {
269
+ return;
270
+ }
271
+ }
272
+ }
273
+ finally {
274
+ req.removeListener("close", onClose);
275
+ res.removeListener("close", onClose);
276
+ }
277
+ }
278
+ // ─────────────────────────────────────────────────────────────────────────
279
+ // Low-level SSE write helpers
280
+ // ─────────────────────────────────────────────────────────────────────────
281
+ function writeSseHeaders(res) {
282
+ // Spec §4.6 / §5.1.
283
+ res.status(200);
284
+ res.setHeader("Content-Type", "text/event-stream");
285
+ res.setHeader("Cache-Control", "no-cache");
286
+ res.setHeader("Connection", "keep-alive");
287
+ // Defeats nginx response buffering.
288
+ res.setHeader("X-Accel-Buffering", "no");
289
+ // Flush headers so the client confirms subscription liveness before
290
+ // the first frame arrives.
291
+ if (typeof res.flushHeaders === "function") {
292
+ res.flushHeaders();
293
+ }
294
+ }
295
+ /**
296
+ * Write one JSON-RPC envelope as an SSE `data:` frame. Returns `false`
297
+ * when the response is no longer writable (client disconnected) so
298
+ * callers can exit the loop without calling `JobProxy.cancel()` per spec
299
+ * §7.3.
300
+ */
301
+ function writeDataFrame(res, envelope) {
302
+ if (res.writableEnded || res.destroyed) {
303
+ return false;
304
+ }
305
+ try {
306
+ const json = JSON.stringify(envelope);
307
+ const written = res.write(`data: ${json}\n\n`);
308
+ return written !== false;
309
+ }
310
+ catch {
311
+ return false;
312
+ }
313
+ }
314
+ /**
315
+ * Write a raw SSE comment line (`: keepalive\n\n`). Spec §5.1 keepalive
316
+ * contract. Returns `false` on client disconnect.
317
+ */
318
+ function writeKeepalive(res) {
319
+ if (res.writableEnded || res.destroyed) {
320
+ return false;
321
+ }
322
+ try {
323
+ const written = res.write(": keepalive\n\n");
324
+ return written !== false;
325
+ }
326
+ catch {
327
+ return false;
328
+ }
329
+ }
330
+ function endSse(res) {
331
+ if (res.writableEnded || res.destroyed)
332
+ return;
333
+ try {
334
+ res.end();
335
+ }
336
+ catch {
337
+ // best-effort
338
+ }
339
+ }
340
+ /**
341
+ * Sleep for `ms` milliseconds, returning `false` if the client
342
+ * disconnected during the wait. Resolves early on `req`/`res` close so
343
+ * the poll loop exits promptly.
344
+ */
345
+ function sleepIfConnected(ms, req, res) {
346
+ return new Promise((resolve) => {
347
+ if (res.writableEnded || res.destroyed) {
348
+ resolve(false);
349
+ return;
350
+ }
351
+ let resolved = false;
352
+ const done = (ok) => {
353
+ if (resolved)
354
+ return;
355
+ resolved = true;
356
+ clearTimeout(timer);
357
+ req.removeListener("close", onClose);
358
+ res.removeListener("close", onClose);
359
+ resolve(ok);
360
+ };
361
+ const onClose = () => done(false);
362
+ const timer = setTimeout(() => done(true), ms);
363
+ req.on("close", onClose);
364
+ res.on("close", onClose);
365
+ });
366
+ }
367
+ // ─────────────────────────────────────────────────────────────────────────
368
+ // Misc helpers
369
+ // ─────────────────────────────────────────────────────────────────────────
370
+ function readParams(params) {
371
+ if (params === null || params === undefined)
372
+ return {};
373
+ if (typeof params !== "object" || Array.isArray(params))
374
+ return {};
375
+ return params;
376
+ }
377
+ function errorTextOf(err) {
378
+ if (err instanceof Error) {
379
+ return err.message || err.name || "Error";
380
+ }
381
+ if (typeof err === "string")
382
+ return err;
383
+ try {
384
+ return JSON.stringify(err);
385
+ }
386
+ catch {
387
+ return String(err);
388
+ }
389
+ }
390
+ /**
391
+ * Cheap equality for primitives + the few non-primitive shapes the
392
+ * status payload can hold (we only ever compare `progress` (number or
393
+ * undefined) and `progress_message` (string or undefined). A full deep
394
+ * equal would be overkill.
395
+ */
396
+ function primitiveOrNullishEqual(a, b) {
397
+ if (a === b)
398
+ return true;
399
+ // Treat null == undefined for the change-detect heuristic so
400
+ // toggling between absent and null doesn't spam frames.
401
+ if (a == null && b == null)
402
+ return true;
403
+ return false;
404
+ }
405
+ //# sourceMappingURL=sse-emitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sse-emitter.js","sourceRoot":"","sources":["../../../src/a2a/producer/sse-emitter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Mesh job lifecycle ↔ A2A v1.0 state translation (spec §7.2).
3
+ *
4
+ * The mesh job substrate emits these internal statuses:
5
+ * - `working`, `completed`, `failed`, `cancelled` (UK spelling)
6
+ *
7
+ * A2A v1.0 uses:
8
+ * - `working`, `completed`, `failed`, `canceled` (US spelling)
9
+ *
10
+ * The UK ↔ US spelling boundary is the most error-prone part of the
11
+ * translation (spec Appendix B item flagged). Consumers accept both
12
+ * spellings; producers MUST emit the US form.
13
+ *
14
+ * Unknown / unset mesh statuses fall back to `working` — preserves the
15
+ * invariant that we never emit an A2A state outside the spec's enumerated
16
+ * set, even when the registry reports a status we haven't mapped. Mirrors
17
+ * Java's `MeshA2AStateTranslator.fromMesh` exactly.
18
+ */
19
+ /** A2A v1.0 state: task submitted (conceptual — never actually emitted by the producer). */
20
+ export declare const A2A_SUBMITTED = "submitted";
21
+ /** A2A v1.0 state: long-running task in flight. */
22
+ export declare const A2A_WORKING = "working";
23
+ /** A2A v1.0 terminal state: task finished successfully. */
24
+ export declare const A2A_COMPLETED = "completed";
25
+ /** A2A v1.0 terminal state: handler raised or job failed. */
26
+ export declare const A2A_FAILED = "failed";
27
+ /** A2A v1.0 terminal state: task canceled (US spelling). */
28
+ export declare const A2A_CANCELED = "canceled";
29
+ /**
30
+ * Translate a mesh job status string to its A2A v1.0 equivalent.
31
+ *
32
+ * Mapping table:
33
+ * - `pending` → `submitted` (conceptual; mesh produces it briefly before claim)
34
+ * - `working` / `running` → `working`
35
+ * - `completed` → `completed`
36
+ * - `failed` → `failed`
37
+ * - `cancelled` (UK) / `canceled` (US) → `canceled` (US — A2A spelling)
38
+ * - `cancelling` → `working` (still in progress; cancel signal in flight)
39
+ * - anything else / null / empty → `working` (fallback)
40
+ *
41
+ * @param meshStatus the mesh-side status string (may be `null`/`undefined`)
42
+ * @returns one of the four A2A v1.0 enumerated states; never `null`
43
+ */
44
+ export declare function fromMesh(meshStatus: string | null | undefined): string;
45
+ /**
46
+ * @returns `true` when the A2A state is one of the three terminal values
47
+ * (`completed` / `failed` / `canceled`).
48
+ */
49
+ export declare function isTerminal(a2aState: string | null | undefined): boolean;
50
+ /**
51
+ * @returns `true` when the mesh status string represents a terminal state.
52
+ * Accepts both UK and US `canceled` spellings (the mesh substrate emits
53
+ * `cancelled` but a normalizer upstream may have already translated).
54
+ */
55
+ export declare function isMeshTerminal(meshStatus: string | null | undefined): boolean;
56
+ /**
57
+ * Extract the mesh-side status string from a `proxy.status()` payload.
58
+ *
59
+ * Returns `null` when the payload lacks a recognisable status field —
60
+ * callers default to `working` via {@link fromMesh}.
61
+ */
62
+ export declare function meshStatusOf(statusPayload: Record<string, unknown> | null | undefined): string | null;
63
+ //# sourceMappingURL=state-translator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-translator.d.ts","sourceRoot":"","sources":["../../../src/a2a/producer/state-translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,4FAA4F;AAC5F,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,mDAAmD;AACnD,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,2DAA2D;AAC3D,eAAO,MAAM,aAAa,cAAc,CAAC;AACzC,6DAA6D;AAC7D,eAAO,MAAM,UAAU,WAAW,CAAC;AACnC,4DAA4D;AAC5D,eAAO,MAAM,YAAY,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CA0BtE;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAMvE;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAQ7E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,GACxD,MAAM,GAAG,IAAI,CAOf"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Mesh job lifecycle ↔ A2A v1.0 state translation (spec §7.2).
3
+ *
4
+ * The mesh job substrate emits these internal statuses:
5
+ * - `working`, `completed`, `failed`, `cancelled` (UK spelling)
6
+ *
7
+ * A2A v1.0 uses:
8
+ * - `working`, `completed`, `failed`, `canceled` (US spelling)
9
+ *
10
+ * The UK ↔ US spelling boundary is the most error-prone part of the
11
+ * translation (spec Appendix B item flagged). Consumers accept both
12
+ * spellings; producers MUST emit the US form.
13
+ *
14
+ * Unknown / unset mesh statuses fall back to `working` — preserves the
15
+ * invariant that we never emit an A2A state outside the spec's enumerated
16
+ * set, even when the registry reports a status we haven't mapped. Mirrors
17
+ * Java's `MeshA2AStateTranslator.fromMesh` exactly.
18
+ */
19
+ /** A2A v1.0 state: task submitted (conceptual — never actually emitted by the producer). */
20
+ export const A2A_SUBMITTED = "submitted";
21
+ /** A2A v1.0 state: long-running task in flight. */
22
+ export const A2A_WORKING = "working";
23
+ /** A2A v1.0 terminal state: task finished successfully. */
24
+ export const A2A_COMPLETED = "completed";
25
+ /** A2A v1.0 terminal state: handler raised or job failed. */
26
+ export const A2A_FAILED = "failed";
27
+ /** A2A v1.0 terminal state: task canceled (US spelling). */
28
+ export const A2A_CANCELED = "canceled";
29
+ /**
30
+ * Translate a mesh job status string to its A2A v1.0 equivalent.
31
+ *
32
+ * Mapping table:
33
+ * - `pending` → `submitted` (conceptual; mesh produces it briefly before claim)
34
+ * - `working` / `running` → `working`
35
+ * - `completed` → `completed`
36
+ * - `failed` → `failed`
37
+ * - `cancelled` (UK) / `canceled` (US) → `canceled` (US — A2A spelling)
38
+ * - `cancelling` → `working` (still in progress; cancel signal in flight)
39
+ * - anything else / null / empty → `working` (fallback)
40
+ *
41
+ * @param meshStatus the mesh-side status string (may be `null`/`undefined`)
42
+ * @returns one of the four A2A v1.0 enumerated states; never `null`
43
+ */
44
+ export function fromMesh(meshStatus) {
45
+ if (!meshStatus) {
46
+ return A2A_WORKING;
47
+ }
48
+ switch (meshStatus) {
49
+ case "pending":
50
+ return A2A_SUBMITTED;
51
+ case "working":
52
+ case "running":
53
+ return A2A_WORKING;
54
+ case "completed":
55
+ return A2A_COMPLETED;
56
+ case "failed":
57
+ return A2A_FAILED;
58
+ case "cancelled":
59
+ case "canceled":
60
+ return A2A_CANCELED;
61
+ case "cancelling":
62
+ case "canceling":
63
+ // Still in progress; cancel signal in flight but the job has not
64
+ // yet observed the cancel. Surfaces as `working` so clients keep
65
+ // polling — they'll see `canceled` once the job acknowledges.
66
+ return A2A_WORKING;
67
+ default:
68
+ return A2A_WORKING;
69
+ }
70
+ }
71
+ /**
72
+ * @returns `true` when the A2A state is one of the three terminal values
73
+ * (`completed` / `failed` / `canceled`).
74
+ */
75
+ export function isTerminal(a2aState) {
76
+ return (a2aState === A2A_COMPLETED ||
77
+ a2aState === A2A_FAILED ||
78
+ a2aState === A2A_CANCELED);
79
+ }
80
+ /**
81
+ * @returns `true` when the mesh status string represents a terminal state.
82
+ * Accepts both UK and US `canceled` spellings (the mesh substrate emits
83
+ * `cancelled` but a normalizer upstream may have already translated).
84
+ */
85
+ export function isMeshTerminal(meshStatus) {
86
+ if (!meshStatus)
87
+ return false;
88
+ return (meshStatus === "completed" ||
89
+ meshStatus === "failed" ||
90
+ meshStatus === "cancelled" ||
91
+ meshStatus === "canceled");
92
+ }
93
+ /**
94
+ * Extract the mesh-side status string from a `proxy.status()` payload.
95
+ *
96
+ * Returns `null` when the payload lacks a recognisable status field —
97
+ * callers default to `working` via {@link fromMesh}.
98
+ */
99
+ export function meshStatusOf(statusPayload) {
100
+ if (!statusPayload || typeof statusPayload !== "object") {
101
+ return null;
102
+ }
103
+ const s = statusPayload["status"];
104
+ if (s === null || s === undefined)
105
+ return null;
106
+ return typeof s === "string" ? s : String(s);
107
+ }
108
+ //# sourceMappingURL=state-translator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-translator.js","sourceRoot":"","sources":["../../../src/a2a/producer/state-translator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,4FAA4F;AAC5F,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,mDAAmD;AACnD,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AACrC,2DAA2D;AAC3D,MAAM,CAAC,MAAM,aAAa,GAAG,WAAW,CAAC;AACzC,6DAA6D;AAC7D,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC;AACnC,4DAA4D;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ,CAAC,UAAqC;IAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,SAAS;YACZ,OAAO,aAAa,CAAC;QACvB,KAAK,SAAS,CAAC;QACf,KAAK,SAAS;YACZ,OAAO,WAAW,CAAC;QACrB,KAAK,WAAW;YACd,OAAO,aAAa,CAAC;QACvB,KAAK,QAAQ;YACX,OAAO,UAAU,CAAC;QACpB,KAAK,WAAW,CAAC;QACjB,KAAK,UAAU;YACb,OAAO,YAAY,CAAC;QACtB,KAAK,YAAY,CAAC;QAClB,KAAK,WAAW;YACd,iEAAiE;YACjE,iEAAiE;YACjE,8DAA8D;YAC9D,OAAO,WAAW,CAAC;QACrB;YACE,OAAO,WAAW,CAAC;IACvB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,QAAmC;IAC5D,OAAO,CACL,QAAQ,KAAK,aAAa;QAC1B,QAAQ,KAAK,UAAU;QACvB,QAAQ,KAAK,YAAY,CAC1B,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,UAAqC;IAClE,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,CACL,UAAU,KAAK,WAAW;QAC1B,UAAU,KAAK,QAAQ;QACvB,UAAU,KAAK,WAAW;QAC1B,UAAU,KAAK,UAAU,CAC1B,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAC1B,aAAyD;IAEzD,IAAI,CAAC,aAAa,IAAI,OAAO,aAAa,KAAK,QAAQ,EAAE,CAAC;QACxD,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,CAAC,GAAI,aAAyC,CAAC,QAAQ,CAAC,CAAC;IAC/D,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC"}