@arnilo/prism-supervisor 0.0.15 → 0.0.16

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.16] - 2026-07-26
4
+
5
+ ### Changed
6
+ - Released with exact 0.0.16 graph.
7
+
3
8
  ## [0.0.15] - 2026-07-26
4
9
 
5
10
  ### Changed
package/dist/a2a-card.js CHANGED
@@ -44,9 +44,7 @@ export async function verifyA2AAgentCard(card, options) {
44
44
  break;
45
45
  }
46
46
  }
47
- catch {
48
- continue;
49
- }
47
+ catch { }
50
48
  }
51
49
  if (!matched)
52
50
  throw new A2AError("Agent card signature is invalid or expired", 403, "ERR_PRISM_A2A_CARD_SIGNATURE");
@@ -71,13 +69,19 @@ function validateCard(card) {
71
69
  throw new A2AError("Agent card exceeds collection/byte limits", 400, "ERR_PRISM_A2A_CARD");
72
70
  if (!card.name?.trim() || !card.description?.trim() || !card.version?.trim())
73
71
  throw new A2AError("Agent card identity is incomplete", 400, "ERR_PRISM_A2A_CARD");
74
- if (!card.supportedInterfaces.length || !card.supportedInterfaces.every((item) => item.protocolBinding === "JSONRPC" && item.protocolVersion === "1.0" && isHttpsUrl(item.url)))
72
+ if (!card.supportedInterfaces.length ||
73
+ !card.supportedInterfaces.every((item) => item.protocolBinding === "JSONRPC" && item.protocolVersion === "1.0" && isHttpsUrl(item.url)))
75
74
  throw new A2AError("Agent card requires an HTTPS JSONRPC 1.0 interface", 400, "ERR_PRISM_A2A_CARD");
76
75
  if (!card.defaultInputModes.includes("text/plain") || !card.defaultOutputModes.includes("text/plain"))
77
76
  throw new A2AError("Agent card must support text/plain", 400, "ERR_PRISM_A2A_CARD");
78
77
  const ids = new Set();
79
78
  for (const skill of card.skills) {
80
- if (!skill.id.trim() || !skill.name.trim() || !skill.description.trim() || ids.has(skill.id) || skill.tags.length > 64 || [skill.id, skill.name, skill.description, ...skill.tags].some((value) => Buffer.byteLength(value) > 16 * 1024))
79
+ if (!skill.id.trim() ||
80
+ !skill.name.trim() ||
81
+ !skill.description.trim() ||
82
+ ids.has(skill.id) ||
83
+ skill.tags.length > 64 ||
84
+ [skill.id, skill.name, skill.description, ...skill.tags].some((value) => Buffer.byteLength(value) > 16 * 1024))
81
85
  throw new A2AError("Agent card skill is invalid", 400, "ERR_PRISM_A2A_CARD");
82
86
  ids.add(skill.id);
83
87
  }
@@ -87,7 +91,11 @@ function parseProtected(value) {
87
91
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
88
92
  throw new Error("invalid protected header");
89
93
  const record = parsed;
90
- if (typeof record.alg !== "string" || typeof record.typ !== "string" || typeof record.kid !== "string" || typeof record.iat !== "string" || typeof record.exp !== "string")
94
+ if (typeof record.alg !== "string" ||
95
+ typeof record.typ !== "string" ||
96
+ typeof record.kid !== "string" ||
97
+ typeof record.iat !== "string" ||
98
+ typeof record.exp !== "string")
91
99
  throw new Error("invalid protected header");
92
100
  return { alg: record.alg, typ: record.typ, kid: record.kid, iat: record.iat, exp: record.exp };
93
101
  }
@@ -103,7 +111,11 @@ function canonicalJson(value) {
103
111
  return `[${value.map(canonicalJson).join(",")}]`;
104
112
  if (value && typeof value === "object") {
105
113
  const record = value;
106
- return `{${Object.keys(record).filter((key) => record[key] !== undefined).sort().map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`).join(",")}}`;
114
+ return `{${Object.keys(record)
115
+ .filter((key) => record[key] !== undefined)
116
+ .sort()
117
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(record[key])}`)
118
+ .join(",")}}`;
107
119
  }
108
120
  throw new A2AError("Agent card is not canonical JSON", 400, "ERR_PRISM_A2A_CARD");
109
121
  }
@@ -1,7 +1,7 @@
1
1
  import { createA2AAgentCard } from "./a2a-card.js";
2
2
  import { resolveA2ALimits } from "./a2a-parts.js";
3
+ import { A2A_PROTOCOL_VERSION, } from "./a2a-types.js";
3
4
  import { A2AError } from "./errors.js";
4
- import { A2A_PROTOCOL_VERSION } from "./a2a-types.js";
5
5
  export function createA2AClient(options) {
6
6
  const endpoint = requireAllowedHttpsUrl(options.endpoint, options.allowedOrigins);
7
7
  const cardUrl = requireAllowedHttpsUrl(options.cardUrl ?? `${endpoint.origin}/.well-known/agent-card.json`, options.allowedOrigins);
@@ -24,7 +24,12 @@ export function createA2AClient(options) {
24
24
  }
25
25
  async function getCard(call = {}) {
26
26
  return withRequest(call.signal, async (signal) => {
27
- const response = await fetcher(cardUrl, { method: "GET", signal, redirect: "error", headers: { accept: "application/a2a+json, application/json" } });
27
+ const response = await fetcher(cardUrl, {
28
+ method: "GET",
29
+ signal,
30
+ redirect: "error",
31
+ headers: { accept: "application/a2a+json, application/json" },
32
+ });
28
33
  if (!response.ok)
29
34
  throw new A2AError("A2A card request failed", response.status, "ERR_PRISM_A2A_REMOTE");
30
35
  const value = await readBoundedJson(response, limits.maxCardBytes, signal);
@@ -45,7 +50,18 @@ export function createA2AClient(options) {
45
50
  if (new TextEncoder().encode(body).byteLength > limits.maxRequestBytes)
46
51
  throw new A2AError("A2A request exceeds max bytes", 413, "ERR_PRISM_A2A_REQUEST_LIMIT");
47
52
  const authHeaders = await abortable(Promise.resolve(options.authorize?.({ endpoint: endpoint.href, signal }) ?? {}), signal);
48
- const response = await fetcher(endpoint, { method: "POST", signal, redirect: "error", headers: { ...headersObject(authHeaders), "content-type": "application/a2a+json", accept: "application/a2a+json", "a2a-version": "1.0" }, body });
53
+ const response = await fetcher(endpoint, {
54
+ method: "POST",
55
+ signal,
56
+ redirect: "error",
57
+ headers: {
58
+ ...headersObject(authHeaders),
59
+ "content-type": "application/a2a+json",
60
+ accept: "application/a2a+json",
61
+ "a2a-version": "1.0",
62
+ },
63
+ body,
64
+ });
49
65
  if (!response.ok)
50
66
  throw new A2AError("A2A remote request failed", response.status, "ERR_PRISM_A2A_REMOTE");
51
67
  const rpc = parseRpcResponse(await readBoundedJson(response, limits.maxResponseBytes, signal), id);
@@ -68,7 +84,18 @@ export function createA2AClient(options) {
68
84
  if (new TextEncoder().encode(body).byteLength > limits.maxRequestBytes)
69
85
  throw new A2AError("A2A request exceeds max bytes", 413, "ERR_PRISM_A2A_REQUEST_LIMIT");
70
86
  const authHeaders = await abortable(Promise.resolve(options.authorize?.({ endpoint: endpoint.href, signal: owned.signal }) ?? {}), owned.signal);
71
- const response = await fetcher(endpoint, { method: "POST", signal: owned.signal, redirect: "error", headers: { ...headersObject(authHeaders), "content-type": "application/a2a+json", accept: "text/event-stream", "a2a-version": "1.0" }, body });
87
+ const response = await fetcher(endpoint, {
88
+ method: "POST",
89
+ signal: owned.signal,
90
+ redirect: "error",
91
+ headers: {
92
+ ...headersObject(authHeaders),
93
+ "content-type": "application/a2a+json",
94
+ accept: "text/event-stream",
95
+ "a2a-version": "1.0",
96
+ },
97
+ body,
98
+ });
72
99
  if (!response.ok || !response.body || !response.headers.get("content-type")?.startsWith("text/event-stream"))
73
100
  throw new A2AError("A2A stream request failed", response.status, "ERR_PRISM_A2A_REMOTE");
74
101
  reader = response.body.getReader();
@@ -89,7 +116,9 @@ export function createA2AClient(options) {
89
116
  if (rpc.error)
90
117
  throw new A2AError(safeRemote(rpc.error.message, options), 502, "ERR_PRISM_A2A_REMOTE");
91
118
  const task = parseTaskResult(rpc.result);
92
- if (task.status.state === "TASK_STATE_FAILED" || task.status.state === "TASK_STATE_CANCELED" || task.status.state === "TASK_STATE_REJECTED")
119
+ if (task.status.state === "TASK_STATE_FAILED" ||
120
+ task.status.state === "TASK_STATE_CANCELED" ||
121
+ task.status.state === "TASK_STATE_REJECTED")
93
122
  throw new A2AError("Remote A2A stream task failed", 502, "ERR_PRISM_A2A_REMOTE");
94
123
  if (task.status.state === "TASK_STATE_INPUT_REQUIRED" || task.status.state === "TASK_STATE_AUTH_REQUIRED")
95
124
  throw new A2AError(`Remote A2A task interrupted: ${task.status.state}`, 409, "ERR_PRISM_A2A_INTERRUPTED");
@@ -110,7 +139,12 @@ export function createA2AClient(options) {
110
139
  }
111
140
  }
112
141
  async function getCardWithin(signal) {
113
- const response = await fetcher(cardUrl, { method: "GET", signal, redirect: "error", headers: { accept: "application/a2a+json, application/json" } });
142
+ const response = await fetcher(cardUrl, {
143
+ method: "GET",
144
+ signal,
145
+ redirect: "error",
146
+ headers: { accept: "application/a2a+json, application/json" },
147
+ });
114
148
  if (!response.ok)
115
149
  throw new A2AError("A2A card request failed", response.status, "ERR_PRISM_A2A_REMOTE");
116
150
  const card = parseCard(await readBoundedJson(response, limits.maxCardBytes, signal));
@@ -128,7 +162,18 @@ export function createA2AClient(options) {
128
162
  if (Buffer.byteLength(body) > limits.maxRequestBytes)
129
163
  throw new A2AError("A2A request exceeds max bytes", 413, "ERR_PRISM_A2A_REQUEST_LIMIT");
130
164
  const authHeaders = await abortable(Promise.resolve(options.authorize?.({ endpoint: endpoint.href, signal: owned }) ?? {}), owned);
131
- const response = await fetcher(endpoint, { method: "POST", signal: owned, redirect: "error", headers: { ...headersObject(authHeaders), "content-type": "application/a2a+json", accept: "application/a2a+json", "a2a-version": "1.0" }, body });
165
+ const response = await fetcher(endpoint, {
166
+ method: "POST",
167
+ signal: owned,
168
+ redirect: "error",
169
+ headers: {
170
+ ...headersObject(authHeaders),
171
+ "content-type": "application/a2a+json",
172
+ accept: "application/a2a+json",
173
+ "a2a-version": "1.0",
174
+ },
175
+ body,
176
+ });
132
177
  if (!response.ok)
133
178
  throw new A2AError("A2A remote request failed", response.status, "ERR_PRISM_A2A_REMOTE");
134
179
  const rpc = parseRpcResponse(await readBoundedJson(response, limits.maxResponseBytes, owned), id);
@@ -140,14 +185,22 @@ export function createA2AClient(options) {
140
185
  async function sendMessage(message, call = {}) {
141
186
  return parseTaskResult(await invoke("SendMessage", { message, configuration: { returnImmediately: call.returnImmediately ?? false } }, call.signal));
142
187
  }
143
- async function getTask(id, call = {}) { return parseTaskResult(await invoke("GetTask", { id, historyLength: call.historyLength ?? 0 }, call.signal)); }
188
+ async function getTask(id, call = {}) {
189
+ return parseTaskResult(await invoke("GetTask", { id, historyLength: call.historyLength ?? 0 }, call.signal));
190
+ }
144
191
  async function listTasks(call = {}) {
145
192
  const value = await invoke("ListTasks", { pageSize: call.pageSize ?? 50, pageToken: call.pageToken, contextId: call.contextId }, call.signal);
146
193
  if (!isRecord(value) || !Array.isArray(value.tasks) || value.tasks.length > limits.maxPageSize)
147
194
  throw new A2AError("Malformed A2A task page", 502, "ERR_PRISM_A2A_REMOTE");
148
- return { tasks: value.tasks.map((task) => parseTaskResult(task)), nextPageToken: typeof value.nextPageToken === "string" ? value.nextPageToken : undefined, totalSize: typeof value.totalSize === "number" ? value.totalSize : undefined };
195
+ return {
196
+ tasks: value.tasks.map((task) => parseTaskResult(task)),
197
+ nextPageToken: typeof value.nextPageToken === "string" ? value.nextPageToken : undefined,
198
+ totalSize: typeof value.totalSize === "number" ? value.totalSize : undefined,
199
+ };
200
+ }
201
+ async function cancelTask(id, call = {}) {
202
+ return parseTaskResult(await invoke("CancelTask", { id }, call.signal));
149
203
  }
150
- async function cancelTask(id, call = {}) { return parseTaskResult(await invoke("CancelTask", { id }, call.signal)); }
151
204
  async function* subscribeToTask(id, call = {}) {
152
205
  if (active >= limits.maxConcurrentRequests)
153
206
  throw new A2AError("A2A client concurrency exceeded", 429, "ERR_PRISM_A2A_CONCURRENCY");
@@ -158,7 +211,18 @@ export function createA2AClient(options) {
158
211
  await getCardWithin(owned.signal);
159
212
  const request = ++requestId;
160
213
  const authHeaders = await abortable(Promise.resolve(options.authorize?.({ endpoint: endpoint.href, signal: owned.signal }) ?? {}), owned.signal);
161
- const response = await fetcher(endpoint, { method: "POST", signal: owned.signal, redirect: "error", headers: { ...headersObject(authHeaders), "content-type": "application/a2a+json", accept: "text/event-stream", "a2a-version": "1.0" }, body: JSON.stringify({ jsonrpc: "2.0", id: request, method: "SubscribeToTask", params: { id, afterEventId: call.afterEventId } }) });
214
+ const response = await fetcher(endpoint, {
215
+ method: "POST",
216
+ signal: owned.signal,
217
+ redirect: "error",
218
+ headers: {
219
+ ...headersObject(authHeaders),
220
+ "content-type": "application/a2a+json",
221
+ accept: "text/event-stream",
222
+ "a2a-version": "1.0",
223
+ },
224
+ body: JSON.stringify({ jsonrpc: "2.0", id: request, method: "SubscribeToTask", params: { id, afterEventId: call.afterEventId } }),
225
+ });
162
226
  if (!response.ok || !response.body || !response.headers.get("content-type")?.startsWith("text/event-stream"))
163
227
  throw new A2AError("A2A subscribe request failed", response.status, "ERR_PRISM_A2A_REMOTE");
164
228
  reader = response.body.getReader();
@@ -182,12 +246,38 @@ export function createA2AClient(options) {
182
246
  active -= 1;
183
247
  }
184
248
  }
185
- async function createPushConfig(config, call = {}) { return parsePushConfig(await invoke("CreateTaskPushNotificationConfig", { ...config }, call.signal)); }
186
- async function getPushConfig(taskId, id, call = {}) { return parsePushConfig(await invoke("GetTaskPushNotificationConfig", { taskId, id }, call.signal)); }
187
- async function listPushConfigs(taskId, call = {}) { const value = await invoke("ListTaskPushNotificationConfigs", { taskId, pageSize: call.pageSize, pageToken: call.pageToken }, call.signal); if (!isRecord(value) || !Array.isArray(value.configs))
188
- throw new A2AError("Malformed A2A push config page", 502, "ERR_PRISM_A2A_REMOTE"); return { configs: value.configs.map(parsePushConfig), nextPageToken: typeof value.nextPageToken === "string" ? value.nextPageToken : undefined }; }
189
- async function deletePushConfig(taskId, id, call = {}) { await invoke("DeleteTaskPushNotificationConfig", { taskId, id }, call.signal); }
190
- return { getCard, send, sendMessage, stream, getTask, listTasks, cancelTask, subscribeToTask, createPushConfig, getPushConfig, listPushConfigs, deletePushConfig };
249
+ async function createPushConfig(config, call = {}) {
250
+ return parsePushConfig(await invoke("CreateTaskPushNotificationConfig", { ...config }, call.signal));
251
+ }
252
+ async function getPushConfig(taskId, id, call = {}) {
253
+ return parsePushConfig(await invoke("GetTaskPushNotificationConfig", { taskId, id }, call.signal));
254
+ }
255
+ async function listPushConfigs(taskId, call = {}) {
256
+ const value = await invoke("ListTaskPushNotificationConfigs", { taskId, pageSize: call.pageSize, pageToken: call.pageToken }, call.signal);
257
+ if (!isRecord(value) || !Array.isArray(value.configs))
258
+ throw new A2AError("Malformed A2A push config page", 502, "ERR_PRISM_A2A_REMOTE");
259
+ return {
260
+ configs: value.configs.map(parsePushConfig),
261
+ nextPageToken: typeof value.nextPageToken === "string" ? value.nextPageToken : undefined,
262
+ };
263
+ }
264
+ async function deletePushConfig(taskId, id, call = {}) {
265
+ await invoke("DeleteTaskPushNotificationConfig", { taskId, id }, call.signal);
266
+ }
267
+ return {
268
+ getCard,
269
+ send,
270
+ sendMessage,
271
+ stream,
272
+ getTask,
273
+ listTasks,
274
+ cancelTask,
275
+ subscribeToTask,
276
+ createPushConfig,
277
+ getPushConfig,
278
+ listPushConfigs,
279
+ deletePushConfig,
280
+ };
191
281
  }
192
282
  async function* readA2AStreamData(reader, limits, signal) {
193
283
  const decoder = new TextDecoder("utf-8", { fatal: true });
@@ -295,12 +385,21 @@ function taskResult(task, options) {
295
385
  throw new A2AError("A2A response task is not terminal", 502, "ERR_PRISM_A2A_REMOTE");
296
386
  if (task.status.state === "TASK_STATE_INPUT_REQUIRED" || task.status.state === "TASK_STATE_AUTH_REQUIRED")
297
387
  throw new A2AError(`Remote A2A task interrupted: ${task.status.state}`, 409, "ERR_PRISM_A2A_INTERRUPTED");
298
- const text = (task.artifacts ?? []).flatMap((artifact) => artifact.parts.flatMap((part) => "text" in part ? [part.text] : [])).join("");
388
+ const text = (task.artifacts ?? []).flatMap((artifact) => artifact.parts.flatMap((part) => ("text" in part ? [part.text] : []))).join("");
299
389
  const safeText = options.redactor?.redact(text) ?? text;
300
390
  const status = task.status.state === "TASK_STATE_COMPLETED" ? "succeeded" : task.status.state === "TASK_STATE_CANCELED" ? "aborted" : "failed";
301
391
  const content = safeText ? [{ type: "text", text: safeText }] : [];
302
392
  const message = safeText ? { role: "assistant", content } : undefined;
303
- return Object.freeze({ sessionId: task.contextId, runId: task.id, status, text: safeText, content, message, error: status === "failed" ? { message: "Remote A2A task failed" } : undefined, abortReason: status === "aborted" ? "Remote A2A task canceled" : undefined });
393
+ return Object.freeze({
394
+ sessionId: task.contextId,
395
+ runId: task.id,
396
+ status,
397
+ text: safeText,
398
+ content,
399
+ message,
400
+ error: status === "failed" ? { message: "Remote A2A task failed" } : undefined,
401
+ abortReason: status === "aborted" ? "Remote A2A task canceled" : undefined,
402
+ });
304
403
  }
305
404
  function parseTaskResult(value) {
306
405
  if (!isRecord(value))
@@ -308,12 +407,36 @@ function parseTaskResult(value) {
308
407
  const task = isRecord(value.task) ? value.task : value;
309
408
  if (typeof task.id !== "string" || typeof task.contextId !== "string" || !isRecord(task.status) || typeof task.status.state !== "string")
310
409
  throw new A2AError("Malformed A2A task", 502, "ERR_PRISM_A2A_REMOTE");
311
- const states = new Set(["TASK_STATE_SUBMITTED", "TASK_STATE_WORKING", "TASK_STATE_COMPLETED", "TASK_STATE_FAILED", "TASK_STATE_CANCELED", "TASK_STATE_INPUT_REQUIRED", "TASK_STATE_REJECTED", "TASK_STATE_AUTH_REQUIRED"]);
410
+ const states = new Set([
411
+ "TASK_STATE_SUBMITTED",
412
+ "TASK_STATE_WORKING",
413
+ "TASK_STATE_COMPLETED",
414
+ "TASK_STATE_FAILED",
415
+ "TASK_STATE_CANCELED",
416
+ "TASK_STATE_INPUT_REQUIRED",
417
+ "TASK_STATE_REJECTED",
418
+ "TASK_STATE_AUTH_REQUIRED",
419
+ ]);
312
420
  if (!states.has(task.status.state))
313
421
  throw new A2AError("Unknown A2A task state", 502, "ERR_PRISM_A2A_REMOTE");
314
422
  const artifacts = task.artifacts === undefined ? undefined : parseArtifacts(task.artifacts);
315
- const history = task.history === undefined ? undefined : Array.isArray(task.history) ? task.history.map(parseRemoteMessage) : (() => { throw new A2AError("Malformed A2A task history", 502, "ERR_PRISM_A2A_REMOTE"); })();
316
- return { id: task.id, contextId: task.contextId, status: { state: task.status.state, timestamp: typeof task.status.timestamp === "string" ? task.status.timestamp : new Date(0).toISOString() }, artifacts, history };
423
+ const history = task.history === undefined
424
+ ? undefined
425
+ : Array.isArray(task.history)
426
+ ? task.history.map(parseRemoteMessage)
427
+ : (() => {
428
+ throw new A2AError("Malformed A2A task history", 502, "ERR_PRISM_A2A_REMOTE");
429
+ })();
430
+ return {
431
+ id: task.id,
432
+ contextId: task.contextId,
433
+ status: {
434
+ state: task.status.state,
435
+ timestamp: typeof task.status.timestamp === "string" ? task.status.timestamp : new Date(0).toISOString(),
436
+ },
437
+ artifacts,
438
+ history,
439
+ };
317
440
  }
318
441
  function parseArtifacts(value) {
319
442
  if (!Array.isArray(value) || value.length > 32)
@@ -330,10 +453,15 @@ function parseRemotePart(value) {
330
453
  const keys = ["text", "raw", "url", "data"].filter((key) => Object.hasOwn(value, key));
331
454
  if (keys.length !== 1)
332
455
  throw new A2AError("Malformed A2A part union", 502, "ERR_PRISM_A2A_REMOTE");
333
- const base = { mediaType: typeof value.mediaType === "string" ? value.mediaType : undefined, filename: typeof value.filename === "string" ? value.filename : undefined };
456
+ const base = {
457
+ mediaType: typeof value.mediaType === "string" ? value.mediaType : undefined,
458
+ filename: typeof value.filename === "string" ? value.filename : undefined,
459
+ };
334
460
  if (keys[0] === "text" && typeof value.text === "string")
335
461
  return { ...base, text: value.text };
336
- if (keys[0] === "raw" && typeof value.raw === "string" && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value.raw))
462
+ if (keys[0] === "raw" &&
463
+ typeof value.raw === "string" &&
464
+ /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value.raw))
337
465
  return { ...base, raw: value.raw };
338
466
  if (keys[0] === "url" && typeof value.url === "string") {
339
467
  const url = new URL(value.url);
@@ -345,25 +473,74 @@ function parseRemotePart(value) {
345
473
  return { ...base, data: structuredClone(value.data) };
346
474
  throw new A2AError("Malformed A2A part", 502, "ERR_PRISM_A2A_REMOTE");
347
475
  }
348
- function parseRemoteMessage(value) { if (!isRecord(value) || typeof value.messageId !== "string" || !Array.isArray(value.parts) || (value.role !== "ROLE_USER" && value.role !== "ROLE_AGENT" && value.role !== "user" && value.role !== "agent"))
349
- throw new A2AError("Malformed A2A message", 502, "ERR_PRISM_A2A_REMOTE"); return { role: value.role, messageId: value.messageId, parts: value.parts.map(parseRemotePart), contextId: typeof value.contextId === "string" ? value.contextId : undefined, taskId: typeof value.taskId === "string" ? value.taskId : undefined }; }
476
+ function parseRemoteMessage(value) {
477
+ if (!isRecord(value) ||
478
+ typeof value.messageId !== "string" ||
479
+ !Array.isArray(value.parts) ||
480
+ (value.role !== "ROLE_USER" && value.role !== "ROLE_AGENT" && value.role !== "user" && value.role !== "agent"))
481
+ throw new A2AError("Malformed A2A message", 502, "ERR_PRISM_A2A_REMOTE");
482
+ return {
483
+ role: value.role,
484
+ messageId: value.messageId,
485
+ parts: value.parts.map(parseRemotePart),
486
+ contextId: typeof value.contextId === "string" ? value.contextId : undefined,
487
+ taskId: typeof value.taskId === "string" ? value.taskId : undefined,
488
+ };
489
+ }
350
490
  function parseTaskEvent(value) {
351
491
  if (!isRecord(value) || typeof value.eventId !== "string" || !value.eventId)
352
492
  throw new A2AError("Malformed A2A task event", 502, "ERR_PRISM_A2A_REMOTE");
353
493
  if (isRecord(value.task))
354
494
  return { eventId: value.eventId, task: parseTaskResult(value.task) };
355
- if (isRecord(value.statusUpdate) && typeof value.statusUpdate.taskId === "string" && typeof value.statusUpdate.contextId === "string" && isRecord(value.statusUpdate.status)) {
356
- const parsed = parseTaskResult({ id: value.statusUpdate.taskId, contextId: value.statusUpdate.contextId, status: value.statusUpdate.status });
495
+ if (isRecord(value.statusUpdate) &&
496
+ typeof value.statusUpdate.taskId === "string" &&
497
+ typeof value.statusUpdate.contextId === "string" &&
498
+ isRecord(value.statusUpdate.status)) {
499
+ const parsed = parseTaskResult({
500
+ id: value.statusUpdate.taskId,
501
+ contextId: value.statusUpdate.contextId,
502
+ status: value.statusUpdate.status,
503
+ });
357
504
  return { eventId: value.eventId, statusUpdate: { taskId: parsed.id, contextId: parsed.contextId, status: parsed.status } };
358
505
  }
359
- if (isRecord(value.artifactUpdate) && typeof value.artifactUpdate.taskId === "string" && typeof value.artifactUpdate.contextId === "string" && isRecord(value.artifactUpdate.artifact))
360
- return { eventId: value.eventId, artifactUpdate: { taskId: value.artifactUpdate.taskId, contextId: value.artifactUpdate.contextId, artifact: parseArtifacts([value.artifactUpdate.artifact])[0], append: value.artifactUpdate.append === true, lastChunk: value.artifactUpdate.lastChunk === true } };
506
+ if (isRecord(value.artifactUpdate) &&
507
+ typeof value.artifactUpdate.taskId === "string" &&
508
+ typeof value.artifactUpdate.contextId === "string" &&
509
+ isRecord(value.artifactUpdate.artifact))
510
+ return {
511
+ eventId: value.eventId,
512
+ artifactUpdate: {
513
+ taskId: value.artifactUpdate.taskId,
514
+ contextId: value.artifactUpdate.contextId,
515
+ artifact: parseArtifacts([value.artifactUpdate.artifact])[0],
516
+ append: value.artifactUpdate.append === true,
517
+ lastChunk: value.artifactUpdate.lastChunk === true,
518
+ },
519
+ };
361
520
  throw new A2AError("Malformed A2A task event", 502, "ERR_PRISM_A2A_REMOTE");
362
521
  }
363
- function parsePushConfig(value) { if (!isRecord(value) || typeof value.id !== "string" || typeof value.taskId !== "string" || typeof value.url !== "string")
364
- throw new A2AError("Malformed A2A push config", 502, "ERR_PRISM_A2A_REMOTE"); const url = new URL(value.url); if (url.protocol !== "https:" || url.username || url.password || url.hash)
365
- throw new A2AError("Unsafe A2A push URL", 502, "ERR_PRISM_A2A_REMOTE"); return { id: value.id, taskId: value.taskId, url: url.href, token: typeof value.token === "string" ? value.token : undefined, authentication: isRecord(value.authentication) && typeof value.authentication.scheme === "string" ? { scheme: value.authentication.scheme, credentials: typeof value.authentication.credentials === "string" ? value.authentication.credentials : undefined } : undefined }; }
366
- function remoteProtocolError(code, message, options) { return new A2AError(safeRemote(message, options), code === -32001 ? 404 : code === -32004 ? 501 : 502, code === -32001 ? "ERR_PRISM_A2A_TASK_NOT_FOUND" : code === -32004 ? "ERR_PRISM_A2A_UNSUPPORTED" : "ERR_PRISM_A2A_REMOTE"); }
522
+ function parsePushConfig(value) {
523
+ if (!isRecord(value) || typeof value.id !== "string" || typeof value.taskId !== "string" || typeof value.url !== "string")
524
+ throw new A2AError("Malformed A2A push config", 502, "ERR_PRISM_A2A_REMOTE");
525
+ const url = new URL(value.url);
526
+ if (url.protocol !== "https:" || url.username || url.password || url.hash)
527
+ throw new A2AError("Unsafe A2A push URL", 502, "ERR_PRISM_A2A_REMOTE");
528
+ return {
529
+ id: value.id,
530
+ taskId: value.taskId,
531
+ url: url.href,
532
+ token: typeof value.token === "string" ? value.token : undefined,
533
+ authentication: isRecord(value.authentication) && typeof value.authentication.scheme === "string"
534
+ ? {
535
+ scheme: value.authentication.scheme,
536
+ credentials: typeof value.authentication.credentials === "string" ? value.authentication.credentials : undefined,
537
+ }
538
+ : undefined,
539
+ };
540
+ }
541
+ function remoteProtocolError(code, message, options) {
542
+ return new A2AError(safeRemote(message, options), code === -32001 ? 404 : code === -32004 ? 501 : 502, code === -32001 ? "ERR_PRISM_A2A_TASK_NOT_FOUND" : code === -32004 ? "ERR_PRISM_A2A_UNSUPPORTED" : "ERR_PRISM_A2A_REMOTE");
543
+ }
367
544
  function parseRpcResponse(value, id) {
368
545
  if (!isRecord(value) || value.jsonrpc !== "2.0" || value.id !== id)
369
546
  throw new A2AError("Malformed A2A JSON-RPC response", 502, "ERR_PRISM_A2A_REMOTE");
@@ -373,7 +550,16 @@ function parseRpcResponse(value, id) {
373
550
  return { jsonrpc: "2.0", id, result: value.result, error: error };
374
551
  }
375
552
  function parseCard(value) {
376
- if (!isRecord(value) || typeof value.name !== "string" || typeof value.description !== "string" || typeof value.version !== "string" || !Array.isArray(value.supportedInterfaces) || !Array.isArray(value.skills) || !stringArray(value.defaultInputModes) || !stringArray(value.defaultOutputModes) || !isRecord(value.capabilities) || typeof value.capabilities.streaming !== "boolean")
553
+ if (!isRecord(value) ||
554
+ typeof value.name !== "string" ||
555
+ typeof value.description !== "string" ||
556
+ typeof value.version !== "string" ||
557
+ !Array.isArray(value.supportedInterfaces) ||
558
+ !Array.isArray(value.skills) ||
559
+ !stringArray(value.defaultInputModes) ||
560
+ !stringArray(value.defaultOutputModes) ||
561
+ !isRecord(value.capabilities) ||
562
+ typeof value.capabilities.streaming !== "boolean")
377
563
  throw new A2AError("Malformed A2A agent card", 502, "ERR_PRISM_A2A_CARD");
378
564
  const supportedInterfaces = value.supportedInterfaces.map((item) => {
379
565
  if (!isRecord(item) || typeof item.url !== "string" || item.protocolBinding !== "JSONRPC" || item.protocolVersion !== "1.0")
@@ -381,21 +567,47 @@ function parseCard(value) {
381
567
  return { url: item.url, protocolBinding: "JSONRPC", protocolVersion: "1.0" };
382
568
  });
383
569
  const skills = value.skills.map((skill) => {
384
- if (!isRecord(skill) || typeof skill.id !== "string" || typeof skill.name !== "string" || typeof skill.description !== "string" || !stringArray(skill.tags))
570
+ if (!isRecord(skill) ||
571
+ typeof skill.id !== "string" ||
572
+ typeof skill.name !== "string" ||
573
+ typeof skill.description !== "string" ||
574
+ !stringArray(skill.tags))
385
575
  throw new A2AError("Malformed A2A agent skill", 502, "ERR_PRISM_A2A_CARD");
386
- return { id: skill.id, name: skill.name, description: skill.description, tags: skill.tags, examples: stringArray(skill.examples) ? skill.examples : undefined, inputModes: stringArray(skill.inputModes) ? skill.inputModes : undefined, outputModes: stringArray(skill.outputModes) ? skill.outputModes : undefined };
576
+ return {
577
+ id: skill.id,
578
+ name: skill.name,
579
+ description: skill.description,
580
+ tags: skill.tags,
581
+ examples: stringArray(skill.examples) ? skill.examples : undefined,
582
+ inputModes: stringArray(skill.inputModes) ? skill.inputModes : undefined,
583
+ outputModes: stringArray(skill.outputModes) ? skill.outputModes : undefined,
584
+ };
387
585
  });
388
- const signatures = value.signatures === undefined ? undefined : Array.isArray(value.signatures) ? value.signatures.map((signature) => {
389
- if (!isRecord(signature) || typeof signature.protected !== "string" || typeof signature.signature !== "string")
390
- throw new A2AError("Malformed A2A card signature", 502, "ERR_PRISM_A2A_CARD");
391
- return { protected: signature.protected, signature: signature.signature, header: isRecord(signature.header) ? signature.header : undefined };
392
- }) : (() => { throw new A2AError("Malformed A2A card signatures", 502, "ERR_PRISM_A2A_CARD"); })();
586
+ const signatures = value.signatures === undefined
587
+ ? undefined
588
+ : Array.isArray(value.signatures)
589
+ ? value.signatures.map((signature) => {
590
+ if (!isRecord(signature) || typeof signature.protected !== "string" || typeof signature.signature !== "string")
591
+ throw new A2AError("Malformed A2A card signature", 502, "ERR_PRISM_A2A_CARD");
592
+ return {
593
+ protected: signature.protected,
594
+ signature: signature.signature,
595
+ header: isRecord(signature.header) ? signature.header : undefined,
596
+ };
597
+ })
598
+ : (() => {
599
+ throw new A2AError("Malformed A2A card signatures", 502, "ERR_PRISM_A2A_CARD");
600
+ })();
393
601
  return createA2AAgentCard({
394
602
  name: value.name,
395
603
  description: value.description,
396
604
  version: value.version,
397
605
  supportedInterfaces,
398
- capabilities: { streaming: value.capabilities.streaming, pushNotifications: typeof value.capabilities.pushNotifications === "boolean" ? value.capabilities.pushNotifications : undefined, extendedAgentCard: typeof value.capabilities.extendedAgentCard === "boolean" ? value.capabilities.extendedAgentCard : undefined },
606
+ capabilities: {
607
+ streaming: value.capabilities.streaming,
608
+ pushNotifications: typeof value.capabilities.pushNotifications === "boolean" ? value.capabilities.pushNotifications : undefined,
609
+ extendedAgentCard: typeof value.capabilities.extendedAgentCard === "boolean" ? value.capabilities.extendedAgentCard : undefined,
610
+ },
399
611
  defaultInputModes: value.defaultInputModes,
400
612
  defaultOutputModes: value.defaultOutputModes,
401
613
  skills,
@@ -455,7 +667,13 @@ function ownedSignal(parent, timeoutMs) {
455
667
  else
456
668
  parent?.addEventListener("abort", abort, { once: true });
457
669
  const timer = setTimeout(() => controller.abort(new DOMException("A2A request timed out", "AbortError")), timeoutMs);
458
- return { signal: controller.signal, dispose: () => { clearTimeout(timer); parent?.removeEventListener("abort", abort); } };
670
+ return {
671
+ signal: controller.signal,
672
+ dispose: () => {
673
+ clearTimeout(timer);
674
+ parent?.removeEventListener("abort", abort);
675
+ },
676
+ };
459
677
  }
460
678
  function abortable(promise, signal) {
461
679
  if (signal.aborted)
@@ -466,11 +684,19 @@ function abortable(promise, signal) {
466
684
  promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
467
685
  });
468
686
  }
469
- function assertInput(input, maxBytes) { if (new TextEncoder().encode(input).byteLength > maxBytes)
470
- throw new A2AError("A2A input exceeds max bytes", 413, "ERR_PRISM_A2A_REQUEST_LIMIT"); }
471
- function headersObject(headers) { return Object.fromEntries(new Headers(headers).entries()); }
472
- function isRecord(value) { return !!value && typeof value === "object" && !Array.isArray(value); }
473
- function stringArray(value) { return Array.isArray(value) && value.every((item) => typeof item === "string"); }
687
+ function assertInput(input, maxBytes) {
688
+ if (new TextEncoder().encode(input).byteLength > maxBytes)
689
+ throw new A2AError("A2A input exceeds max bytes", 413, "ERR_PRISM_A2A_REQUEST_LIMIT");
690
+ }
691
+ function headersObject(headers) {
692
+ return Object.fromEntries(new Headers(headers).entries());
693
+ }
694
+ function isRecord(value) {
695
+ return !!value && typeof value === "object" && !Array.isArray(value);
696
+ }
697
+ function stringArray(value) {
698
+ return Array.isArray(value) && value.every((item) => typeof item === "string");
699
+ }
474
700
  function parseSecurity(value) {
475
701
  if (value === undefined)
476
702
  return undefined;
@@ -482,5 +708,7 @@ function parseSecurity(value) {
482
708
  return entry;
483
709
  });
484
710
  }
485
- function safeRemote(message, options) { return options.redactor?.redact(message.slice(0, 1024)) ?? message.slice(0, 1024); }
711
+ function safeRemote(message, options) {
712
+ return options.redactor?.redact(message.slice(0, 1024)) ?? message.slice(0, 1024);
713
+ }
486
714
  //# sourceMappingURL=a2a-client.js.map