@aiwg/cli 2026.8.17 → 2026.8.19

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 (50) hide show
  1. package/bin/aiwg.mjs +24 -2
  2. package/dist/src/a2a/agent-card.js +4 -1
  3. package/dist/src/a2a/client.js +148 -68
  4. package/dist/src/a2a/codecs.js +480 -0
  5. package/dist/src/a2a/events.js +226 -0
  6. package/dist/src/a2a/hitl-driver.js +8 -6
  7. package/dist/src/a2a/hitl.js +2 -1
  8. package/dist/src/a2a/http.js +85 -5
  9. package/dist/src/a2a/protocol.js +136 -0
  10. package/dist/src/a2a/types.js +4 -14
  11. package/dist/src/a2a/webhook.js +101 -4
  12. package/dist/src/artifacts/index-builder.js +63 -12
  13. package/dist/src/artifacts/index-files.js +26 -5
  14. package/dist/src/artifacts/query-engine.js +67 -67
  15. package/dist/src/artifacts/stats.js +6 -2
  16. package/dist/src/artifacts/types.js +1 -1
  17. package/dist/src/audit/operator-decision.js +15 -1
  18. package/dist/src/channel/manager.mjs +89 -17
  19. package/dist/src/cli/handlers/index.js +3 -1
  20. package/dist/src/cli/handlers/installation.js +79 -0
  21. package/dist/src/cli/handlers/refresh.js +6 -2
  22. package/dist/src/cli/handlers/runtime-info.js +9 -1
  23. package/dist/src/cli/handlers/serve.js +107 -4
  24. package/dist/src/cli/handlers/session.js +12 -26
  25. package/dist/src/cli/handlers/use.js +19 -4
  26. package/dist/src/cli/handlers/utilities.js +4 -0
  27. package/dist/src/cli/handlers/version.js +4 -0
  28. package/dist/src/config/user-config-dir.mjs +29 -0
  29. package/dist/src/config/user-config.js +4 -22
  30. package/dist/src/extensions/commands/definitions.js +20 -1
  31. package/dist/src/features/catalog.js +2 -1
  32. package/dist/src/flow/graph-metadata.js +56 -0
  33. package/dist/src/installation/manager-command.mjs +31 -0
  34. package/dist/src/installation/manager.mjs +264 -0
  35. package/dist/src/serve/a2a-terminal-observer.js +28 -5
  36. package/dist/src/serve/dispatch-router.js +32 -4
  37. package/dist/src/serve/executor-registry.js +29 -0
  38. package/dist/src/serve/mission-conductor.js +15 -1
  39. package/dist/src/serve/stack-adapters.js +2 -1
  40. package/dist/src/serve/telemetry.js +5 -1
  41. package/dist/src/smiths/context-pipeline/claude-hook.js +8 -5
  42. package/dist/src/smiths/context-pipeline/line-endings.js +12 -0
  43. package/dist/src/smiths/context-pipeline/managed-hook.js +8 -5
  44. package/dist/src/smiths/context-pipeline/workspace-context.js +3 -1
  45. package/dist/src/update/checker.mjs +16 -15
  46. package/dist/src/update/notifier.mjs +8 -3
  47. package/dist/src/update/service.mjs +51 -5
  48. package/package.json +1 -1
  49. package/tools/agents/deploy-agents.mjs +28 -8
  50. package/tools/agents/providers/base.mjs +5 -3
@@ -0,0 +1,480 @@
1
+ export function encodePushNotificationConfig(version, config) {
2
+ assertNonEmptyString(version, '$.url', config.url);
3
+ if (version === '0.3') {
4
+ return {
5
+ ...(config.configId ? { configId: config.configId } : {}),
6
+ url: config.url,
7
+ ...(config.secret ? { secret: config.secret } : {}),
8
+ ...(config.eventTypes ? { eventTypes: config.eventTypes } : {}),
9
+ ...(config.metadata ? { metadata: config.metadata } : {}),
10
+ ...(config.token ? { token: config.token } : {}),
11
+ ...(config.authentication ? { authentication: config.authentication } : {}),
12
+ };
13
+ }
14
+ const token = config.token ?? config.secret;
15
+ return {
16
+ ...(config.configId ? { id: config.configId } : {}),
17
+ url: config.url,
18
+ ...(token ? { token } : {}),
19
+ ...(config.authentication ? { authentication: config.authentication } : {}),
20
+ };
21
+ }
22
+ export function decodePushNotificationConfig(version, input, path = '$') {
23
+ const obj = objectAt(version, path, input);
24
+ const result = {
25
+ url: stringAt(version, `${path}.url`, obj.url),
26
+ };
27
+ const id = version === '1.0' ? obj.id : obj.configId;
28
+ assignOptionalString(version, result, 'configId', id, `${path}.${version === '1.0' ? 'id' : 'configId'}`);
29
+ assignOptionalString(version, result, 'token', obj.token, `${path}.token`);
30
+ if (version === '0.3') {
31
+ assignOptionalString(version, result, 'secret', obj.secret, `${path}.secret`);
32
+ if (obj.eventTypes !== undefined) {
33
+ const values = arrayAt(version, `${path}.eventTypes`, obj.eventTypes);
34
+ if (!values.every(value => ['task', 'message', 'status', 'artifact'].includes(String(value)))) {
35
+ fail(version, `${path}.eventTypes`, 'contains an unsupported normalized event type');
36
+ }
37
+ result.eventTypes = values;
38
+ }
39
+ assignOptionalJsonObject(version, result, 'metadata', obj.metadata, `${path}.metadata`);
40
+ }
41
+ else if (result.token) {
42
+ result.secret = result.token;
43
+ }
44
+ if (obj.authentication !== undefined) {
45
+ const auth = objectAt(version, `${path}.authentication`, obj.authentication);
46
+ result.authentication = {
47
+ scheme: stringAt(version, `${path}.authentication.scheme`, auth.scheme),
48
+ ...(auth.credentials !== undefined
49
+ ? { credentials: stringAt(version, `${path}.authentication.credentials`, auth.credentials) }
50
+ : {}),
51
+ };
52
+ }
53
+ return result;
54
+ }
55
+ export class A2AWireValidationError extends Error {
56
+ protocolVersion;
57
+ path;
58
+ constructor(protocolVersion, path, detail) {
59
+ super(`Invalid A2A ${protocolVersion} payload at ${path}: ${detail}`);
60
+ this.name = 'A2AWireValidationError';
61
+ this.protocolVersion = protocolVersion;
62
+ this.path = path;
63
+ }
64
+ }
65
+ const LEGACY_STATES = new Set([
66
+ 'submitted', 'working', 'completed', 'failed', 'canceled',
67
+ 'input-required', 'rejected', 'auth-required',
68
+ ]);
69
+ const V1_TO_STATE = {
70
+ TASK_STATE_SUBMITTED: 'submitted',
71
+ TASK_STATE_WORKING: 'working',
72
+ TASK_STATE_COMPLETED: 'completed',
73
+ TASK_STATE_FAILED: 'failed',
74
+ TASK_STATE_CANCELED: 'canceled',
75
+ TASK_STATE_INPUT_REQUIRED: 'input-required',
76
+ TASK_STATE_REJECTED: 'rejected',
77
+ TASK_STATE_AUTH_REQUIRED: 'auth-required',
78
+ };
79
+ const STATE_TO_V1 = Object.fromEntries(Object.entries(V1_TO_STATE).map(([wire, normalized]) => [normalized, wire]));
80
+ export function encodeMessage(version, message) {
81
+ assertNonEmptyString(version, '$.messageId', message.messageId);
82
+ if (message.role !== 'user' && message.role !== 'agent') {
83
+ fail(version, '$.role', 'must be user or agent');
84
+ }
85
+ if (!Array.isArray(message.parts) || message.parts.length === 0) {
86
+ fail(version, '$.parts', 'must contain at least one part');
87
+ }
88
+ const out = {
89
+ messageId: message.messageId,
90
+ role: version === '1.0' ? (message.role === 'user' ? 'ROLE_USER' : 'ROLE_AGENT') : message.role,
91
+ parts: message.parts.map((part, index) => encodePart(version, part, `$.parts[${index}]`)),
92
+ };
93
+ copyOptional(out, 'contextId', message.contextId);
94
+ copyOptional(out, 'taskId', message.taskId);
95
+ copyJsonObject(version, out, 'metadata', message.metadata, '$.metadata');
96
+ copyStringArray(version, out, 'extensions', message.extensions, '$.extensions');
97
+ copyStringArray(version, out, 'referenceTaskIds', message.referenceTaskIds, '$.referenceTaskIds');
98
+ return out;
99
+ }
100
+ export function decodeMessage(version, input, path = '$') {
101
+ const obj = objectAt(version, path, input);
102
+ const messageId = stringAt(version, `${path}.messageId`, obj.messageId);
103
+ const role = decodeRole(version, obj.role, `${path}.role`);
104
+ const partsRaw = arrayAt(version, `${path}.parts`, obj.parts);
105
+ if (partsRaw.length === 0)
106
+ fail(version, `${path}.parts`, 'must contain at least one part');
107
+ const message = {
108
+ messageId,
109
+ role,
110
+ parts: partsRaw.map((part, index) => decodePart(version, part, `${path}.parts[${index}]`)),
111
+ };
112
+ assignOptionalString(version, message, 'contextId', obj.contextId, `${path}.contextId`);
113
+ assignOptionalString(version, message, 'taskId', obj.taskId, `${path}.taskId`);
114
+ assignOptionalJsonObject(version, message, 'metadata', obj.metadata, `${path}.metadata`);
115
+ assignOptionalStringArray(version, message, 'extensions', obj.extensions, `${path}.extensions`);
116
+ assignOptionalStringArray(version, message, 'referenceTaskIds', obj.referenceTaskIds, `${path}.referenceTaskIds`);
117
+ return message;
118
+ }
119
+ export function encodeTask(version, task) {
120
+ assertNonEmptyString(version, '$.id', task.id);
121
+ const out = {
122
+ id: task.id,
123
+ status: encodeStatus(version, task.status, '$.status'),
124
+ };
125
+ copyOptional(out, 'contextId', task.contextId);
126
+ if (task.artifacts !== undefined) {
127
+ out.artifacts = task.artifacts.map((artifact, index) => encodeArtifact(version, artifact, `$.artifacts[${index}]`));
128
+ }
129
+ if (task.history !== undefined) {
130
+ out.history = task.history.map((message, index) => encodeMessageAt(version, message, `$.history[${index}]`));
131
+ }
132
+ copyJsonObject(version, out, 'metadata', task.metadata, '$.metadata');
133
+ copyStringArray(version, out, 'extensions', task.extensions, '$.extensions');
134
+ return out;
135
+ }
136
+ export function decodeTask(version, input, path = '$') {
137
+ const obj = objectAt(version, path, input);
138
+ if (version === '1.0' && typeof obj.kind === 'string') {
139
+ fail(version, `${path}.kind`, 'legacy kind discriminator is not valid in 1.0');
140
+ }
141
+ const task = {
142
+ id: stringAt(version, `${path}.id`, obj.id),
143
+ status: decodeStatus(version, obj.status, `${path}.status`),
144
+ };
145
+ assignOptionalString(version, task, 'contextId', obj.contextId, `${path}.contextId`);
146
+ if (obj.artifacts !== undefined) {
147
+ task.artifacts = arrayAt(version, `${path}.artifacts`, obj.artifacts)
148
+ .map((artifact, index) => decodeArtifact(version, artifact, `${path}.artifacts[${index}]`));
149
+ }
150
+ if (obj.history !== undefined) {
151
+ task.history = arrayAt(version, `${path}.history`, obj.history)
152
+ .map((message, index) => decodeMessage(version, message, `${path}.history[${index}]`));
153
+ }
154
+ assignOptionalJsonObject(version, task, 'metadata', obj.metadata, `${path}.metadata`);
155
+ assignOptionalStringArray(version, task, 'extensions', obj.extensions, `${path}.extensions`);
156
+ return task;
157
+ }
158
+ export function decodeSendMessageResponse(version, input) {
159
+ if (version === '0.3')
160
+ return decodeTask(version, input);
161
+ const obj = objectAt(version, '$', input);
162
+ const members = ['task', 'message'].filter(key => obj[key] !== undefined);
163
+ if (members.length !== 1) {
164
+ fail(version, '$', 'send response must contain exactly one of task or message');
165
+ }
166
+ if (members[0] !== 'task') {
167
+ fail(version, '$.message', 'AIWG mission dispatch requires a Task response');
168
+ }
169
+ return decodeTask(version, obj.task, '$.task');
170
+ }
171
+ export function encodeStatus(version, status, path = '$') {
172
+ const out = {
173
+ state: version === '1.0' ? STATE_TO_V1[status.state] : status.state,
174
+ };
175
+ if (!out.state)
176
+ fail(version, `${path}.state`, `unsupported normalized state ${String(status.state)}`);
177
+ if (status.message !== undefined)
178
+ out.message = encodeMessageAt(version, status.message, `${path}.message`);
179
+ if (status.timestamp !== undefined) {
180
+ assertTimestamp(version, `${path}.timestamp`, status.timestamp);
181
+ out.timestamp = status.timestamp;
182
+ }
183
+ copyStringArray(version, out, 'extensions', status.extensions, `${path}.extensions`);
184
+ if (status.summary !== undefined)
185
+ out.summary = status.summary;
186
+ if (status.exitCode !== undefined)
187
+ out[version === '0.3' ? 'exit_code' : 'exitCode'] = status.exitCode;
188
+ return out;
189
+ }
190
+ export function decodeStatus(version, input, path = '$') {
191
+ const obj = objectAt(version, path, input);
192
+ const rawState = stringAt(version, `${path}.state`, obj.state);
193
+ const state = version === '1.0'
194
+ ? V1_TO_STATE[rawState]
195
+ : LEGACY_STATES.has(rawState) ? rawState : undefined;
196
+ if (!state)
197
+ fail(version, `${path}.state`, `unsupported state '${rawState}'`);
198
+ const status = { state };
199
+ if (obj.message !== undefined)
200
+ status.message = decodeMessage(version, obj.message, `${path}.message`);
201
+ if (obj.timestamp !== undefined) {
202
+ const timestamp = stringAt(version, `${path}.timestamp`, obj.timestamp);
203
+ assertTimestamp(version, `${path}.timestamp`, timestamp);
204
+ status.timestamp = timestamp;
205
+ }
206
+ assignOptionalStringArray(version, status, 'extensions', obj.extensions, `${path}.extensions`);
207
+ if (obj.summary !== undefined)
208
+ status.summary = stringAt(version, `${path}.summary`, obj.summary);
209
+ const exitCode = version === '0.3' ? obj.exit_code : obj.exitCode;
210
+ if (exitCode !== undefined) {
211
+ if (typeof exitCode !== 'number' || !Number.isInteger(exitCode)) {
212
+ fail(version, `${path}.${version === '0.3' ? 'exit_code' : 'exitCode'}`, 'must be an integer');
213
+ }
214
+ status.exitCode = exitCode;
215
+ }
216
+ return status;
217
+ }
218
+ export function encodeArtifact(version, artifact, path = '$') {
219
+ assertNonEmptyString(version, `${path}.artifactId`, artifact.artifactId);
220
+ if (!Array.isArray(artifact.parts) || artifact.parts.length === 0) {
221
+ fail(version, `${path}.parts`, 'must contain at least one part');
222
+ }
223
+ const out = {
224
+ artifactId: artifact.artifactId,
225
+ parts: artifact.parts.map((part, index) => encodePart(version, part, `${path}.parts[${index}]`)),
226
+ };
227
+ copyOptional(out, 'name', artifact.name);
228
+ copyOptional(out, 'description', artifact.description);
229
+ copyJsonObject(version, out, 'metadata', artifact.metadata, `${path}.metadata`);
230
+ copyStringArray(version, out, 'extensions', artifact.extensions, `${path}.extensions`);
231
+ return out;
232
+ }
233
+ export function decodeArtifact(version, input, path = '$') {
234
+ const obj = objectAt(version, path, input);
235
+ const partsRaw = arrayAt(version, `${path}.parts`, obj.parts);
236
+ if (partsRaw.length === 0)
237
+ fail(version, `${path}.parts`, 'must contain at least one part');
238
+ const artifact = {
239
+ artifactId: stringAt(version, `${path}.artifactId`, obj.artifactId),
240
+ parts: partsRaw.map((part, index) => decodePart(version, part, `${path}.parts[${index}]`)),
241
+ };
242
+ assignOptionalString(version, artifact, 'name', obj.name, `${path}.name`);
243
+ assignOptionalString(version, artifact, 'description', obj.description, `${path}.description`);
244
+ assignOptionalJsonObject(version, artifact, 'metadata', obj.metadata, `${path}.metadata`);
245
+ assignOptionalStringArray(version, artifact, 'extensions', obj.extensions, `${path}.extensions`);
246
+ return artifact;
247
+ }
248
+ function encodeMessageAt(version, message, path) {
249
+ try {
250
+ return encodeMessage(version, message);
251
+ }
252
+ catch (error) {
253
+ if (error instanceof A2AWireValidationError) {
254
+ throw new A2AWireValidationError(version, `${path}${error.path.slice(1)}`, error.message.split(': ').slice(1).join(': '));
255
+ }
256
+ throw error;
257
+ }
258
+ }
259
+ function encodePart(version, part, path) {
260
+ const common = {};
261
+ copyJsonObject(version, common, 'metadata', part.metadata, `${path}.metadata`);
262
+ copyOptional(common, version === '0.3' ? 'mimeType' : 'mediaType', part.mediaType);
263
+ if (version === '0.3') {
264
+ if (part.type === 'text')
265
+ return { kind: 'text', text: part.text, ...common };
266
+ if (part.type === 'data')
267
+ return { kind: 'data', data: part.data, ...common };
268
+ assertFileOneOf(version, path, part);
269
+ return {
270
+ kind: 'file',
271
+ ...(part.raw !== undefined ? { bytes: part.raw } : { uri: part.url }),
272
+ ...(part.filename !== undefined ? { name: part.filename } : {}),
273
+ ...common,
274
+ };
275
+ }
276
+ if (part.type === 'text')
277
+ return { text: part.text, ...common };
278
+ if (part.type === 'data')
279
+ return { data: part.data, ...common };
280
+ assertFileOneOf(version, path, part);
281
+ return {
282
+ ...(part.raw !== undefined ? { raw: part.raw } : { url: part.url }),
283
+ ...(part.filename !== undefined ? { filename: part.filename } : {}),
284
+ ...common,
285
+ };
286
+ }
287
+ function decodePart(version, input, path) {
288
+ const obj = objectAt(version, path, input);
289
+ if (version === '0.3')
290
+ return decodeLegacyPart(obj, path);
291
+ return decodeV1Part(obj, path);
292
+ }
293
+ function decodeLegacyPart(obj, path) {
294
+ if (['raw', 'url', 'mediaType'].some(key => obj[key] !== undefined)) {
295
+ fail('0.3', path, 'contains A2A 1.0 part fields');
296
+ }
297
+ const kind = stringAt('0.3', `${path}.kind`, obj.kind);
298
+ const metadata = optionalJsonObject('0.3', obj.metadata, `${path}.metadata`);
299
+ if (kind === 'text') {
300
+ return { type: 'text', text: stringAt('0.3', `${path}.text`, obj.text), ...optionalCommon(obj, metadata, 'mimeType') };
301
+ }
302
+ if (kind === 'data') {
303
+ if (!hasOwn(obj, 'data'))
304
+ fail('0.3', `${path}.data`, 'is required');
305
+ assertJsonValue('0.3', `${path}.data`, obj.data);
306
+ return { type: 'data', data: obj.data, ...optionalCommon(obj, metadata, 'mimeType') };
307
+ }
308
+ if (kind !== 'file')
309
+ fail('0.3', `${path}.kind`, `unsupported kind '${kind}'`);
310
+ const members = ['bytes', 'uri'].filter(key => obj[key] !== undefined);
311
+ if (members.length !== 1)
312
+ fail('0.3', path, 'file part must contain exactly one of bytes or uri');
313
+ const raw = obj.bytes !== undefined ? stringAt('0.3', `${path}.bytes`, obj.bytes) : undefined;
314
+ if (raw !== undefined)
315
+ assertBase64('0.3', `${path}.bytes`, raw);
316
+ return {
317
+ type: 'file',
318
+ ...(raw !== undefined ? { raw } : { url: stringAt('0.3', `${path}.uri`, obj.uri) }),
319
+ ...(obj.name !== undefined ? { filename: stringAt('0.3', `${path}.name`, obj.name) } : {}),
320
+ ...optionalCommon(obj, metadata, 'mimeType'),
321
+ };
322
+ }
323
+ function decodeV1Part(obj, path) {
324
+ if (['kind', 'mimeType', 'bytes', 'uri'].some(key => obj[key] !== undefined)) {
325
+ fail('1.0', path, 'contains legacy A2A 0.3 part fields');
326
+ }
327
+ const members = ['text', 'raw', 'url', 'data'].filter(key => hasOwn(obj, key));
328
+ if (members.length !== 1)
329
+ fail('1.0', path, 'Part must contain exactly one of text, raw, url, or data');
330
+ const metadata = optionalJsonObject('1.0', obj.metadata, `${path}.metadata`);
331
+ const common = optionalCommon(obj, metadata, 'mediaType');
332
+ switch (members[0]) {
333
+ case 'text':
334
+ return { type: 'text', text: stringAt('1.0', `${path}.text`, obj.text), ...common };
335
+ case 'data':
336
+ assertJsonValue('1.0', `${path}.data`, obj.data);
337
+ return { type: 'data', data: obj.data, ...common };
338
+ case 'raw': {
339
+ const raw = stringAt('1.0', `${path}.raw`, obj.raw);
340
+ assertBase64('1.0', `${path}.raw`, raw);
341
+ return {
342
+ type: 'file', raw,
343
+ ...(obj.filename !== undefined ? { filename: stringAt('1.0', `${path}.filename`, obj.filename) } : {}),
344
+ ...common,
345
+ };
346
+ }
347
+ case 'url':
348
+ return {
349
+ type: 'file', url: stringAt('1.0', `${path}.url`, obj.url),
350
+ ...(obj.filename !== undefined ? { filename: stringAt('1.0', `${path}.filename`, obj.filename) } : {}),
351
+ ...common,
352
+ };
353
+ default:
354
+ fail('1.0', path, 'unknown Part member');
355
+ }
356
+ }
357
+ function optionalCommon(obj, metadata, mediaKey) {
358
+ return {
359
+ ...(obj[mediaKey] !== undefined ? { mediaType: stringAt(mediaKey === 'mimeType' ? '0.3' : '1.0', `$.${mediaKey}`, obj[mediaKey]) } : {}),
360
+ ...(metadata ? { metadata } : {}),
361
+ };
362
+ }
363
+ function decodeRole(version, input, path) {
364
+ const role = stringAt(version, path, input);
365
+ if (version === '0.3') {
366
+ if (role === 'user' || role === 'agent')
367
+ return role;
368
+ }
369
+ else {
370
+ if (role === 'ROLE_USER')
371
+ return 'user';
372
+ if (role === 'ROLE_AGENT')
373
+ return 'agent';
374
+ }
375
+ fail(version, path, `unsupported role '${role}'`);
376
+ }
377
+ function assertFileOneOf(version, path, part) {
378
+ if ((part.raw === undefined) === (part.url === undefined)) {
379
+ fail(version, path, 'normalized file part must contain exactly one of raw or url');
380
+ }
381
+ if (part.raw !== undefined)
382
+ assertBase64(version, `${path}.raw`, part.raw);
383
+ }
384
+ function objectAt(version, path, value) {
385
+ if (!value || typeof value !== 'object' || Array.isArray(value))
386
+ fail(version, path, 'must be an object');
387
+ return value;
388
+ }
389
+ function arrayAt(version, path, value) {
390
+ if (!Array.isArray(value))
391
+ fail(version, path, 'must be an array');
392
+ return value;
393
+ }
394
+ function stringAt(version, path, value) {
395
+ if (typeof value !== 'string')
396
+ fail(version, path, 'must be a string');
397
+ return value;
398
+ }
399
+ function assertNonEmptyString(version, path, value) {
400
+ if (typeof value !== 'string' || value.length === 0)
401
+ fail(version, path, 'must be a non-empty string');
402
+ }
403
+ function assertTimestamp(version, path, value) {
404
+ if (!/^\d{4}-\d{2}-\d{2}T/.test(value) || !Number.isFinite(Date.parse(value))) {
405
+ fail(version, path, 'must be an RFC 3339 timestamp');
406
+ }
407
+ }
408
+ function assertBase64(version, path, value) {
409
+ if (!/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(value)) {
410
+ fail(version, path, 'must be canonical base64');
411
+ }
412
+ }
413
+ function assertJsonValue(version, path, value) {
414
+ if (value === null || ['string', 'boolean'].includes(typeof value))
415
+ return;
416
+ if (typeof value === 'number') {
417
+ if (!Number.isFinite(value))
418
+ fail(version, path, 'JSON numbers must be finite');
419
+ return;
420
+ }
421
+ if (Array.isArray(value)) {
422
+ value.forEach((entry, index) => assertJsonValue(version, `${path}[${index}]`, entry));
423
+ return;
424
+ }
425
+ if (value && typeof value === 'object') {
426
+ for (const [key, entry] of Object.entries(value))
427
+ assertJsonValue(version, `${path}.${key}`, entry);
428
+ return;
429
+ }
430
+ fail(version, path, 'must be a JSON value');
431
+ }
432
+ function optionalJsonObject(version, value, path) {
433
+ if (value === undefined)
434
+ return undefined;
435
+ const obj = objectAt(version, path, value);
436
+ assertJsonValue(version, path, obj);
437
+ return obj;
438
+ }
439
+ function copyOptional(out, key, value) {
440
+ if (value !== undefined)
441
+ out[key] = value;
442
+ }
443
+ function copyJsonObject(version, out, key, value, path) {
444
+ if (value === undefined)
445
+ return;
446
+ assertJsonValue(version, path, value);
447
+ out[key] = value;
448
+ }
449
+ function copyStringArray(version, out, key, value, path) {
450
+ if (value === undefined)
451
+ return;
452
+ if (!Array.isArray(value) || value.some(entry => typeof entry !== 'string')) {
453
+ fail(version, path, 'must be an array of strings');
454
+ }
455
+ out[key] = [...value];
456
+ }
457
+ function assignOptionalString(version, out, key, value, path) {
458
+ if (value !== undefined)
459
+ out[key] = stringAt(version, path, value);
460
+ }
461
+ function assignOptionalJsonObject(version, out, key, value, path) {
462
+ const parsed = optionalJsonObject(version, value, path);
463
+ if (parsed !== undefined)
464
+ out[key] = parsed;
465
+ }
466
+ function assignOptionalStringArray(version, out, key, value, path) {
467
+ if (value === undefined)
468
+ return;
469
+ if (!Array.isArray(value) || value.some(entry => typeof entry !== 'string')) {
470
+ fail(version, path, 'must be an array of strings');
471
+ }
472
+ out[key] = [...value];
473
+ }
474
+ function hasOwn(obj, key) {
475
+ return Object.prototype.hasOwnProperty.call(obj, key);
476
+ }
477
+ function fail(version, path, detail) {
478
+ throw new A2AWireValidationError(version, path, detail);
479
+ }
480
+ //# sourceMappingURL=codecs.js.map