@aiwg/cli 2026.8.17 → 2026.8.18
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/bin/aiwg.mjs +24 -2
- package/dist/src/a2a/agent-card.js +4 -1
- package/dist/src/a2a/client.js +148 -68
- package/dist/src/a2a/codecs.js +480 -0
- package/dist/src/a2a/events.js +226 -0
- package/dist/src/a2a/hitl-driver.js +8 -6
- package/dist/src/a2a/hitl.js +2 -1
- package/dist/src/a2a/http.js +85 -5
- package/dist/src/a2a/protocol.js +136 -0
- package/dist/src/a2a/types.js +4 -14
- package/dist/src/a2a/webhook.js +101 -4
- package/dist/src/audit/operator-decision.js +15 -1
- package/dist/src/channel/manager.mjs +89 -17
- package/dist/src/cli/handlers/index.js +3 -1
- package/dist/src/cli/handlers/installation.js +79 -0
- package/dist/src/cli/handlers/refresh.js +4 -2
- package/dist/src/cli/handlers/runtime-info.js +9 -1
- package/dist/src/cli/handlers/serve.js +107 -4
- package/dist/src/cli/handlers/session.js +12 -26
- package/dist/src/cli/handlers/utilities.js +4 -0
- package/dist/src/cli/handlers/version.js +4 -0
- package/dist/src/config/user-config-dir.mjs +29 -0
- package/dist/src/config/user-config.js +4 -22
- package/dist/src/extensions/commands/definitions.js +20 -1
- package/dist/src/features/catalog.js +2 -1
- package/dist/src/flow/graph-metadata.js +56 -0
- package/dist/src/installation/manager.mjs +243 -0
- package/dist/src/serve/a2a-terminal-observer.js +28 -5
- package/dist/src/serve/dispatch-router.js +32 -4
- package/dist/src/serve/executor-registry.js +29 -0
- package/dist/src/serve/mission-conductor.js +15 -1
- package/dist/src/serve/stack-adapters.js +2 -1
- package/dist/src/serve/telemetry.js +5 -1
- package/dist/src/update/checker.mjs +16 -15
- package/dist/src/update/notifier.mjs +8 -3
- package/dist/src/update/service.mjs +49 -5
- package/package.json +1 -1
package/bin/aiwg.mjs
CHANGED
|
@@ -46,7 +46,18 @@ function detectVersionChannel(version) {
|
|
|
46
46
|
if (version.includes('-alpha.')) return 'alpha';
|
|
47
47
|
if (version.includes('-nightly.')) return 'nightly';
|
|
48
48
|
try {
|
|
49
|
-
const
|
|
49
|
+
const legacyDir = path.join(os.homedir(), '.aiwg');
|
|
50
|
+
const xdgDir = path.join(os.homedir(), '.config', 'aiwg');
|
|
51
|
+
const configDir = process.env.AIWG_CONFIG
|
|
52
|
+
? path.resolve(process.env.AIWG_CONFIG)
|
|
53
|
+
: existsSync(legacyDir) ? legacyDir : existsSync(xdgDir) ? xdgDir : legacyDir;
|
|
54
|
+
const installationFile = path.join(configDir, 'installation.json');
|
|
55
|
+
if (existsSync(installationFile)) {
|
|
56
|
+
const installation = JSON.parse(readFileSync(installationFile, 'utf8'));
|
|
57
|
+
if (installation?.runMode === 'development') return 'dev';
|
|
58
|
+
if (typeof installation?.channel === 'string') return installation.channel;
|
|
59
|
+
}
|
|
60
|
+
const raw = readFileSync(path.join(configDir, 'channel.json'), 'utf8');
|
|
50
61
|
const cfg = JSON.parse(raw);
|
|
51
62
|
if (cfg?.devMode) return 'dev';
|
|
52
63
|
if (typeof cfg?.channel === 'string') return cfg.channel;
|
|
@@ -124,6 +135,7 @@ const FAST_HELP_TEXT = `
|
|
|
124
135
|
|
|
125
136
|
VALIDATION
|
|
126
137
|
validate-metadata [path] Validate AIWG component metadata (defaults to agentic/code)
|
|
138
|
+
installation <action> Inspect/adopt/switch canonical global installation
|
|
127
139
|
verify <artifact> Verify DSSE provenance using an explicit versioned trust root
|
|
128
140
|
verify trust <action> Bootstrap, update, or inspect artifact trust state
|
|
129
141
|
context-firewall [scan] Audit provider context, trust, drift, poisoning signals, and budget
|
|
@@ -368,9 +380,19 @@ async function main() {
|
|
|
368
380
|
|
|
369
381
|
// Resolve the active router once. In dev mode this points into the checkout,
|
|
370
382
|
// while packageRoot still points at the globally installed launcher.
|
|
371
|
-
const routerPath =
|
|
383
|
+
const routerPath = args[0] === 'installation'
|
|
384
|
+
? path.join(packageRoot, 'dist', 'src', 'cli', 'router.js')
|
|
385
|
+
: await resolveRouterPath();
|
|
372
386
|
const activePackageRoot = path.resolve(path.dirname(routerPath), '..', '..', '..');
|
|
373
387
|
|
|
388
|
+
// Fail closed when a different installation wins PATH resolution. Recovery
|
|
389
|
+
// commands remain reachable so an operator can explicitly adopt or switch.
|
|
390
|
+
if (args[0] !== 'installation') {
|
|
391
|
+
const identityPath = path.join(activePackageRoot, 'dist', 'src', 'installation', 'manager.mjs');
|
|
392
|
+
const { assertCanonicalInstallation } = await import(pathToFileURL(identityPath).href);
|
|
393
|
+
assertCanonicalInstallation({ actualRoot: activePackageRoot });
|
|
394
|
+
}
|
|
395
|
+
|
|
374
396
|
// Wire up the logger level from -v/-vv/--quiet/AIWG_LOG_LEVEL before any
|
|
375
397
|
// handler runs, and stamp the top-level invocation ID so the logger can
|
|
376
398
|
// tag every record with it.
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// The card declares required + optional extensions, supported transports,
|
|
12
12
|
// and skills.
|
|
13
13
|
import { loadJwkSet, verifyAgentCardSignature } from './jws.js';
|
|
14
|
+
import { normalizeAgentCard } from './protocol.js';
|
|
14
15
|
const DEFAULT_TTL_MS = 5 * 60 * 1000;
|
|
15
16
|
export class AgentCardCache {
|
|
16
17
|
ttlMs;
|
|
@@ -83,8 +84,9 @@ export async function fetchAgentCard(host, instanceId, opts = {}) {
|
|
|
83
84
|
catch (err) {
|
|
84
85
|
throw new Error(`fetchAgentCard: invalid JSON from ${url}: ${err.message}`);
|
|
85
86
|
}
|
|
87
|
+
const normalized = normalizeAgentCard(card);
|
|
86
88
|
if (opts.skipVerify) {
|
|
87
|
-
return { card, raw, verifiedAt: new Date().toISOString() };
|
|
89
|
+
return { card, normalized, raw, verifiedAt: new Date().toISOString() };
|
|
88
90
|
}
|
|
89
91
|
let jwks = opts.jwks;
|
|
90
92
|
if (!jwks) {
|
|
@@ -98,6 +100,7 @@ export async function fetchAgentCard(host, instanceId, opts = {}) {
|
|
|
98
100
|
verifyAgentCardSignature(raw, jwks);
|
|
99
101
|
const verified = {
|
|
100
102
|
card,
|
|
103
|
+
normalized,
|
|
101
104
|
raw,
|
|
102
105
|
verifiedAt: new Date().toISOString(),
|
|
103
106
|
};
|
package/dist/src/a2a/client.js
CHANGED
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
// GET /agents/{id}/v1/extendedAgentCard (extended card)
|
|
16
16
|
// GET /agents/{id}/v1/card (legacy extended card)
|
|
17
17
|
import { A2AError, A2AHttpClient } from './http.js';
|
|
18
|
+
import { decodePushNotificationConfig, decodeSendMessageResponse, decodeTask, encodeMessage, encodePushNotificationConfig, } from './codecs.js';
|
|
19
|
+
import { A2AEventReconciler, decodeStreamResponse } from './events.js';
|
|
20
|
+
import { normalizeAgentCard, selectAgentInterface } from './protocol.js';
|
|
18
21
|
export const A2A_RUNTIME_V1 = 'https://agentic-sandbox.aiwg.io/extensions/runtime/v1';
|
|
19
22
|
export const A2A_IDEMPOTENCY_V1 = 'https://agentic-sandbox.aiwg.io/extensions/idempotency/v1';
|
|
20
23
|
export const A2A_HITL_PROMPT_V1 = 'https://agentic-sandbox.aiwg.io/extensions/hitl-prompt/v1';
|
|
@@ -25,21 +28,84 @@ export const A2A_PTY_EXTENSIONS_V1 = 'https://agentic-sandbox.aiwg.io/extensions
|
|
|
25
28
|
export const DEFAULT_REQUIRED_EXTENSIONS = [A2A_RUNTIME_V1, A2A_IDEMPOTENCY_V1];
|
|
26
29
|
export class A2AClient {
|
|
27
30
|
instanceId;
|
|
31
|
+
protocolVersion;
|
|
32
|
+
protocolPolicy;
|
|
33
|
+
selectedInterface;
|
|
28
34
|
http;
|
|
29
35
|
extensionSet;
|
|
36
|
+
fallbackClient;
|
|
37
|
+
allowProtocolFallback;
|
|
38
|
+
onProtocolFallback;
|
|
30
39
|
constructor(opts) {
|
|
31
40
|
this.instanceId = opts.instanceId;
|
|
41
|
+
this.protocolPolicy = opts.protocolPolicy ?? opts.protocolVersion ?? '0.3';
|
|
42
|
+
if (this.protocolPolicy === 'auto' && !opts.selectedInterface) {
|
|
43
|
+
throw new Error('A2AClient protocolPolicy=auto requires A2AClient.negotiate() or selectedInterface');
|
|
44
|
+
}
|
|
45
|
+
this.selectedInterface = opts.selectedInterface;
|
|
46
|
+
this.protocolVersion = opts.selectedInterface?.protocolVersion ?? opts.protocolVersion ?? '0.3';
|
|
47
|
+
this.allowProtocolFallback = opts.allowProtocolFallback ?? false;
|
|
48
|
+
this.onProtocolFallback = opts.onProtocolFallback;
|
|
32
49
|
const required = opts.requiredExtensions ?? DEFAULT_REQUIRED_EXTENSIONS;
|
|
33
50
|
const optional = opts.optionalExtensions ?? [];
|
|
34
51
|
this.extensionSet = [...required, ...optional];
|
|
35
52
|
this.http = new A2AHttpClient({
|
|
36
53
|
...opts,
|
|
54
|
+
baseUrl: opts.selectedInterface?.url ?? opts.baseUrl,
|
|
55
|
+
protocolVersion: this.protocolVersion,
|
|
37
56
|
defaultExtensions: this.extensionSet,
|
|
38
57
|
});
|
|
58
|
+
if (opts.selectedInterface && opts.onProtocolSelection) {
|
|
59
|
+
opts.onProtocolSelection({
|
|
60
|
+
selected: this.protocolVersion,
|
|
61
|
+
interface: opts.selectedInterface,
|
|
62
|
+
policy: this.protocolPolicy,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
/** Discover, normalize, and select an AgentCard interface deterministically. */
|
|
67
|
+
static async negotiate(opts) {
|
|
68
|
+
const policy = opts.protocolPolicy ?? 'auto';
|
|
69
|
+
const { selectedInterface: _ignoredSelectedInterface, protocolVersion: _ignoredProtocolVersion, onProtocolSelection, ...negotiationOpts } = opts;
|
|
70
|
+
const discovery = new A2AClient({ ...negotiationOpts, protocolPolicy: '0.3', protocolVersion: '0.3' });
|
|
71
|
+
const card = await discovery.getAgentCard();
|
|
72
|
+
const normalized = normalizeAgentCard(card);
|
|
73
|
+
const selected = selectAgentInterface(normalized, { policy });
|
|
74
|
+
const client = new A2AClient({
|
|
75
|
+
...negotiationOpts,
|
|
76
|
+
protocolPolicy: policy,
|
|
77
|
+
protocolVersion: selected.protocolVersion,
|
|
78
|
+
selectedInterface: selected,
|
|
79
|
+
});
|
|
80
|
+
if (policy === 'auto' && selected.protocolVersion === '1.0' && opts.allowProtocolFallback) {
|
|
81
|
+
try {
|
|
82
|
+
const fallback = selectAgentInterface(normalized, { policy: '0.3' });
|
|
83
|
+
client.fallbackClient = new A2AClient({
|
|
84
|
+
...negotiationOpts,
|
|
85
|
+
protocolPolicy: '0.3',
|
|
86
|
+
protocolVersion: '0.3',
|
|
87
|
+
selectedInterface: fallback,
|
|
88
|
+
allowProtocolFallback: false,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// No compatible 0.3 interface; auto remains 1.0-only.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Fire once for the interface actually selected for use; the dormant
|
|
96
|
+
// downgrade adapter is not itself a selection event.
|
|
97
|
+
onProtocolSelection?.({ selected: selected.protocolVersion, interface: selected, policy });
|
|
98
|
+
return client;
|
|
39
99
|
}
|
|
40
100
|
agentPath() {
|
|
41
101
|
return `/agents/${encodeURIComponent(this.instanceId)}/v1`;
|
|
42
102
|
}
|
|
103
|
+
operationPath(v1Path, legacyPath) {
|
|
104
|
+
if (this.selectedInterface) {
|
|
105
|
+
return this.protocolVersion === '1.0' ? `/${v1Path}` : `/v1/${legacyPath}`;
|
|
106
|
+
}
|
|
107
|
+
return `${this.agentPath()}/${legacyPath}`;
|
|
108
|
+
}
|
|
43
109
|
// ---------- AgentCard ----------
|
|
44
110
|
/**
|
|
45
111
|
* Fetch the well-known unsigned card. Callers that need verification should
|
|
@@ -115,15 +181,32 @@ export class A2AClient {
|
|
|
115
181
|
* `idempotentReplayed: true`.
|
|
116
182
|
*/
|
|
117
183
|
async sendMessage(message, opts = {}) {
|
|
118
|
-
const path =
|
|
184
|
+
const path = this.operationPath('message:send', 'messages:send');
|
|
119
185
|
const requestOptions = {
|
|
120
186
|
method: 'POST',
|
|
121
|
-
body: { message },
|
|
187
|
+
body: { message: encodeMessage(this.protocolVersion, message) },
|
|
122
188
|
extensions: opts.extensions ? [...opts.extensions] : this.extensionSet,
|
|
123
189
|
};
|
|
124
190
|
if (opts.signal)
|
|
125
191
|
requestOptions.signal = opts.signal;
|
|
126
|
-
|
|
192
|
+
let resp;
|
|
193
|
+
try {
|
|
194
|
+
resp = await this.http.request(path, requestOptions);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
if (error instanceof A2AError
|
|
198
|
+
&& error.versionNotSupported
|
|
199
|
+
&& this.protocolVersion === '1.0'
|
|
200
|
+
&& this.protocolPolicy === 'auto'
|
|
201
|
+
&& this.allowProtocolFallback
|
|
202
|
+
&& this.fallbackClient) {
|
|
203
|
+
const reason = `${error.problem.type}: ${error.problem.detail ?? error.problem.title}`;
|
|
204
|
+
this.onProtocolFallback?.({ from: '1.0', to: '0.3', reason });
|
|
205
|
+
const fallback = await this.fallbackClient.sendMessage(message, opts);
|
|
206
|
+
return { ...fallback, fallbackReason: reason };
|
|
207
|
+
}
|
|
208
|
+
throw error;
|
|
209
|
+
}
|
|
127
210
|
if (!resp.body) {
|
|
128
211
|
throw new A2AError(resp.status, path, {
|
|
129
212
|
type: 'about:blank',
|
|
@@ -131,15 +214,18 @@ export class A2AClient {
|
|
|
131
214
|
code: 'aiwg.empty_send_message',
|
|
132
215
|
});
|
|
133
216
|
}
|
|
217
|
+
const task = decodeSendMessageResponse(this.protocolVersion, resp.body);
|
|
134
218
|
return {
|
|
135
|
-
task
|
|
219
|
+
task,
|
|
136
220
|
idempotentReplayed: resp.idempotentReplayed,
|
|
137
221
|
activatedExtensions: resp.activatedExtensions,
|
|
222
|
+
protocolVersion: this.protocolVersion,
|
|
223
|
+
...(this.selectedInterface ? { selectedInterface: this.selectedInterface } : {}),
|
|
138
224
|
};
|
|
139
225
|
}
|
|
140
226
|
// ---------- Tasks ----------
|
|
141
227
|
async getTask(taskId, opts = {}) {
|
|
142
|
-
const path =
|
|
228
|
+
const path = this.operationPath(`tasks/${encodeURIComponent(taskId)}`, `tasks/${encodeURIComponent(taskId)}`);
|
|
143
229
|
const requestOptions = { method: 'GET' };
|
|
144
230
|
if (opts.signal)
|
|
145
231
|
requestOptions.signal = opts.signal;
|
|
@@ -151,24 +237,27 @@ export class A2AClient {
|
|
|
151
237
|
code: 'aiwg.empty_get_task',
|
|
152
238
|
});
|
|
153
239
|
}
|
|
154
|
-
return resp.body;
|
|
240
|
+
return decodeTask(this.protocolVersion, resp.body);
|
|
155
241
|
}
|
|
156
242
|
/** List tasks for this instance, optionally filtered by state. */
|
|
157
243
|
async listTasks(filter = {}) {
|
|
158
244
|
const params = new URLSearchParams();
|
|
159
245
|
if (filter.state)
|
|
160
|
-
params.set('state', filter.state);
|
|
246
|
+
params.set(this.protocolVersion === '1.0' ? 'status' : 'state', filter.state);
|
|
161
247
|
if (filter.limit !== undefined)
|
|
162
|
-
params.set('limit', String(filter.limit));
|
|
248
|
+
params.set(this.protocolVersion === '1.0' ? 'pageSize' : 'limit', String(filter.limit));
|
|
163
249
|
const query = params.toString();
|
|
164
|
-
const
|
|
250
|
+
const basePath = this.operationPath('tasks', 'tasks');
|
|
251
|
+
const path = `${basePath}${query ? '?' + query : ''}`;
|
|
165
252
|
const resp = await this.http.request(path, { method: 'GET' });
|
|
166
253
|
if (!resp.body)
|
|
167
254
|
return [];
|
|
168
|
-
|
|
255
|
+
const raw = Array.isArray(resp.body) ? resp.body : resp.body.tasks ?? [];
|
|
256
|
+
return raw.map((task, index) => decodeTask(this.protocolVersion, task, `$.tasks[${index}]`));
|
|
169
257
|
}
|
|
170
258
|
async cancelTask(taskId, opts = {}) {
|
|
171
|
-
const
|
|
259
|
+
const encoded = encodeURIComponent(taskId);
|
|
260
|
+
const path = this.operationPath(`tasks/${encoded}:cancel`, `tasks/${encoded}/cancel`);
|
|
172
261
|
const requestOptions = {
|
|
173
262
|
method: 'POST',
|
|
174
263
|
body: {},
|
|
@@ -184,7 +273,11 @@ export class A2AClient {
|
|
|
184
273
|
code: 'aiwg.empty_cancel_task',
|
|
185
274
|
});
|
|
186
275
|
}
|
|
187
|
-
|
|
276
|
+
const body = this.protocolVersion === '1.0'
|
|
277
|
+
&& resp.body && typeof resp.body === 'object' && 'task' in resp.body
|
|
278
|
+
? resp.body.task
|
|
279
|
+
: resp.body;
|
|
280
|
+
return decodeTask(this.protocolVersion, body);
|
|
188
281
|
}
|
|
189
282
|
// ---------- Task subscription (SSE) ----------
|
|
190
283
|
/**
|
|
@@ -205,7 +298,9 @@ export class A2AClient {
|
|
|
205
298
|
params.set('replay_from', String(opts.replayFromSeq));
|
|
206
299
|
}
|
|
207
300
|
const query = params.toString();
|
|
208
|
-
const
|
|
301
|
+
const encoded = encodeURIComponent(taskId);
|
|
302
|
+
const basePath = this.operationPath(`tasks/${encoded}:subscribe`, `tasks/${encoded}/subscribe`);
|
|
303
|
+
const path = `${basePath}${query ? '?' + query : ''}`;
|
|
209
304
|
const controller = new AbortController();
|
|
210
305
|
const externalSignal = opts.signal;
|
|
211
306
|
if (externalSignal) {
|
|
@@ -215,10 +310,11 @@ export class A2AClient {
|
|
|
215
310
|
externalSignal.addEventListener('abort', () => controller.abort(), { once: true });
|
|
216
311
|
}
|
|
217
312
|
const http = this.http;
|
|
313
|
+
const protocolVersion = this.protocolVersion;
|
|
218
314
|
let cancelled = false;
|
|
219
315
|
async function* iterate() {
|
|
220
316
|
const resp = await http.request(path, {
|
|
221
|
-
method: 'GET',
|
|
317
|
+
method: protocolVersion === '1.0' ? 'POST' : 'GET',
|
|
222
318
|
headers: { accept: 'text/event-stream' },
|
|
223
319
|
signal: controller.signal,
|
|
224
320
|
raw: true,
|
|
@@ -238,12 +334,21 @@ export class A2AClient {
|
|
|
238
334
|
code: 'aiwg.subscribe_empty_body',
|
|
239
335
|
});
|
|
240
336
|
}
|
|
337
|
+
const reconciler = new A2AEventReconciler({
|
|
338
|
+
taskId,
|
|
339
|
+
requireInitialSnapshot: protocolVersion === '1.0',
|
|
340
|
+
});
|
|
241
341
|
for await (const frame of parseEventStream(resp.rawBody)) {
|
|
242
342
|
if (cancelled)
|
|
243
343
|
return;
|
|
244
|
-
const event = decodeStreamEvent(frame);
|
|
245
|
-
if (event)
|
|
246
|
-
|
|
344
|
+
const event = decodeStreamEvent(protocolVersion, frame);
|
|
345
|
+
if (!event)
|
|
346
|
+
continue;
|
|
347
|
+
const accepted = reconciler.accept(event);
|
|
348
|
+
if (accepted)
|
|
349
|
+
yield accepted;
|
|
350
|
+
if (reconciler.isTerminal())
|
|
351
|
+
return;
|
|
247
352
|
}
|
|
248
353
|
}
|
|
249
354
|
const generator = iterate();
|
|
@@ -259,10 +364,10 @@ export class A2AClient {
|
|
|
259
364
|
}
|
|
260
365
|
// ---------- Push notification configs ----------
|
|
261
366
|
async createPushNotificationConfig(taskId, config) {
|
|
262
|
-
const path =
|
|
367
|
+
const path = this.operationPath(`tasks/${encodeURIComponent(taskId)}/pushNotificationConfigs`, `tasks/${encodeURIComponent(taskId)}/pushNotificationConfigs`);
|
|
263
368
|
const resp = await this.http.request(path, {
|
|
264
369
|
method: 'POST',
|
|
265
|
-
body: config,
|
|
370
|
+
body: encodePushNotificationConfig(this.protocolVersion, config),
|
|
266
371
|
extensions: [...this.extensionSet],
|
|
267
372
|
});
|
|
268
373
|
if (!resp.body) {
|
|
@@ -272,10 +377,11 @@ export class A2AClient {
|
|
|
272
377
|
code: 'aiwg.empty_push_config_create',
|
|
273
378
|
});
|
|
274
379
|
}
|
|
275
|
-
return resp.body;
|
|
380
|
+
return decodePushNotificationConfig(this.protocolVersion, resp.body);
|
|
276
381
|
}
|
|
277
382
|
async getPushNotificationConfig(taskId, configId) {
|
|
278
|
-
const
|
|
383
|
+
const suffix = `tasks/${encodeURIComponent(taskId)}/pushNotificationConfigs/${encodeURIComponent(configId)}`;
|
|
384
|
+
const path = this.operationPath(suffix, suffix);
|
|
279
385
|
const resp = await this.http.request(path, { method: 'GET' });
|
|
280
386
|
if (!resp.body) {
|
|
281
387
|
throw new A2AError(resp.status, path, {
|
|
@@ -284,10 +390,11 @@ export class A2AClient {
|
|
|
284
390
|
code: 'aiwg.empty_push_config_get',
|
|
285
391
|
});
|
|
286
392
|
}
|
|
287
|
-
return resp.body;
|
|
393
|
+
return decodePushNotificationConfig(this.protocolVersion, resp.body);
|
|
288
394
|
}
|
|
289
395
|
async deletePushNotificationConfig(taskId, configId) {
|
|
290
|
-
const
|
|
396
|
+
const suffix = `tasks/${encodeURIComponent(taskId)}/pushNotificationConfigs/${encodeURIComponent(configId)}`;
|
|
397
|
+
const path = this.operationPath(suffix, suffix);
|
|
291
398
|
await this.http.request(path, {
|
|
292
399
|
method: 'DELETE',
|
|
293
400
|
extensions: [...this.extensionSet],
|
|
@@ -357,55 +464,28 @@ export async function* parseEventStream(stream) {
|
|
|
357
464
|
reader.releaseLock();
|
|
358
465
|
}
|
|
359
466
|
}
|
|
360
|
-
function decodeStreamEvent(frame) {
|
|
467
|
+
export function decodeStreamEvent(protocolVersion, frame) {
|
|
361
468
|
if (!frame.data)
|
|
362
469
|
return null;
|
|
470
|
+
let obj;
|
|
363
471
|
try {
|
|
364
|
-
|
|
365
|
-
// Prefer the `kind` field if present (matches StreamEvent discriminator).
|
|
366
|
-
// Otherwise fall back to `event:` header from the frame.
|
|
367
|
-
const kindFromBody = typeof obj['kind'] === 'string' ? obj['kind'] : undefined;
|
|
368
|
-
const kind = kindFromBody ?? frame.event;
|
|
369
|
-
if (!kind)
|
|
370
|
-
return null;
|
|
371
|
-
switch (kind) {
|
|
372
|
-
case 'task-state':
|
|
373
|
-
if (obj['task']) {
|
|
374
|
-
return { kind: 'task-state', task: obj['task'] };
|
|
375
|
-
}
|
|
376
|
-
return null;
|
|
377
|
-
case 'status-update':
|
|
378
|
-
if (typeof obj['taskId'] === 'string' && obj['status']) {
|
|
379
|
-
const out = {
|
|
380
|
-
kind: 'status-update',
|
|
381
|
-
taskId: obj['taskId'],
|
|
382
|
-
status: obj['status'],
|
|
383
|
-
};
|
|
384
|
-
if (typeof obj['final'] === 'boolean') {
|
|
385
|
-
out.final = obj['final'];
|
|
386
|
-
}
|
|
387
|
-
return out;
|
|
388
|
-
}
|
|
389
|
-
return null;
|
|
390
|
-
case 'artifact-update':
|
|
391
|
-
if (typeof obj['taskId'] === 'string' && obj['artifact']) {
|
|
392
|
-
const out = {
|
|
393
|
-
kind: 'artifact-update',
|
|
394
|
-
taskId: obj['taskId'],
|
|
395
|
-
artifact: obj['artifact'],
|
|
396
|
-
};
|
|
397
|
-
if (typeof obj['append'] === 'boolean') {
|
|
398
|
-
out.append = obj['append'];
|
|
399
|
-
}
|
|
400
|
-
return out;
|
|
401
|
-
}
|
|
402
|
-
return null;
|
|
403
|
-
default:
|
|
404
|
-
return null;
|
|
405
|
-
}
|
|
472
|
+
obj = JSON.parse(frame.data);
|
|
406
473
|
}
|
|
407
|
-
catch {
|
|
408
|
-
|
|
474
|
+
catch (error) {
|
|
475
|
+
throw new A2AError(502, 'sse', {
|
|
476
|
+
type: 'about:blank',
|
|
477
|
+
title: 'Invalid SSE JSON',
|
|
478
|
+
detail: error.message,
|
|
479
|
+
code: 'aiwg.invalid_stream_json',
|
|
480
|
+
});
|
|
409
481
|
}
|
|
482
|
+
const sequence = frame.id !== undefined && /^\d+$/.test(frame.id)
|
|
483
|
+
? Number(frame.id)
|
|
484
|
+
: undefined;
|
|
485
|
+
return decodeStreamResponse(protocolVersion, obj, {
|
|
486
|
+
...(frame.event ? { eventName: frame.event } : {}),
|
|
487
|
+
...(frame.id ? { eventId: frame.id } : {}),
|
|
488
|
+
...(sequence !== undefined ? { sequence } : {}),
|
|
489
|
+
});
|
|
410
490
|
}
|
|
411
491
|
//# sourceMappingURL=client.js.map
|