@groundnuty/macf-channel-server 0.2.28 → 0.2.32

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.
@@ -0,0 +1,85 @@
1
+ import type { Message, Task } from './a2a-types.js';
2
+ import type { AgentCard } from './agent-card.js';
3
+ /** Default per-target AgentCard cache TTL (5 minutes). */
4
+ export declare const AGENT_CARD_CACHE_TTL_MS: number;
5
+ export interface A2aClientConfig {
6
+ /** PEM-encoded client cert for mTLS handshake. */
7
+ readonly mTlsClientCertPem: string;
8
+ /** PEM-encoded client key for mTLS handshake. */
9
+ readonly mTlsClientKeyPem: string;
10
+ /** PEM-encoded CA cert chain to validate the remote server's cert. */
11
+ readonly caCertPem: string;
12
+ /** Optional override for per-request timeout (default 30s). */
13
+ readonly timeoutMs?: number;
14
+ /** Optional override for the AgentCard cache TTL (default 5min). */
15
+ readonly agentCardCacheTtlMs?: number;
16
+ }
17
+ /** Error class for A2A client failures. */
18
+ export declare class A2aClientError extends Error {
19
+ readonly cause?: unknown | undefined;
20
+ readonly code: string;
21
+ constructor(code: string, message: string, cause?: unknown | undefined);
22
+ }
23
+ /**
24
+ * Outbound A2A v1.0 client. Single instance per channel-server process.
25
+ *
26
+ * Hold the keep-alive https.Agent + AgentCard cache as instance state.
27
+ * Stateless across calls otherwise — each `sendMessage` /
28
+ * `getAgentCard` invocation is independent.
29
+ */
30
+ export declare class A2aClient {
31
+ #private;
32
+ constructor(config: A2aClientConfig);
33
+ /**
34
+ * Dispatch a `message/send` JSON-RPC call to a remote A2A v1.0 endpoint.
35
+ *
36
+ * Wraps in OTel CLIENT span named `invoke_agent {target}` per the
37
+ * canonical GenAI semconv (matches the existing `notify_peer` outbound
38
+ * pattern post-macf#369). The `target` is derived from the target URL's
39
+ * host:port pair when not explicitly provided.
40
+ *
41
+ * Returns the parsed `Task` on success.
42
+ *
43
+ * Throws `A2aClientError` on:
44
+ * - Transport failure (TLS, connect timeout, etc.) — code `'TRANSPORT_ERROR'`
45
+ * - HTTP non-200 — code `'HTTP_ERROR'`
46
+ * - JSON-RPC error envelope (`error` field set in response) — code `'JSONRPC_ERROR'`
47
+ * with `.cause` carrying the structured error object
48
+ * - Schema validation failure on response body — code `'INVALID_RESPONSE'`
49
+ *
50
+ * Does NOT retry on failure (per design Q4 — `message/send` is not idempotent).
51
+ */
52
+ sendMessage(targetUrl: string, message: Message, opts?: {
53
+ readonly target?: string;
54
+ readonly requestId?: string;
55
+ }): Promise<Task>;
56
+ /**
57
+ * Fetch a target's AgentCard via the well-known URL. Caches the result
58
+ * per `targetUrl` for `agentCardCacheTtlMs` (default 5min).
59
+ *
60
+ * Returns `null` if:
61
+ * - The endpoint returns 404 (target doesn't publish an AgentCard)
62
+ * - The endpoint returns 401/403 (auth failure — cache miss + signals
63
+ * to caller that they may need to refresh credentials)
64
+ *
65
+ * Throws `A2aClientError` on:
66
+ * - Transport failure (TLS, connect timeout) — code `'TRANSPORT_ERROR'`
67
+ * - HTTP 5xx — code `'HTTP_ERROR'` (caller may want to retry)
68
+ * - Body fails AgentCard schema validation — code `'INVALID_AGENT_CARD'`
69
+ *
70
+ * Retry on network errors: 3 attempts with exponential backoff
71
+ * (1s/2s/4s; total ~7s). HTTP responses (200, 404, 4xx, 5xx) are not
72
+ * retried — they're authoritative server signals.
73
+ */
74
+ getAgentCard(targetUrl: string): Promise<AgentCard | null>;
75
+ /** Diagnostic: count of cached AgentCard entries (testing aid). */
76
+ agentCardCacheSize(): number;
77
+ /** Manually invalidate a cached AgentCard (e.g., after detected target rotation). */
78
+ invalidateAgentCard(targetUrl: string): void;
79
+ /**
80
+ * Close the underlying https.Agent. Call on channel-server shutdown to
81
+ * release pooled sockets cleanly.
82
+ */
83
+ close(): void;
84
+ }
85
+ //# sourceMappingURL=a2a-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a-client.d.ts","sourceRoot":"","sources":["../src/a2a-client.ts"],"names":[],"mappings":"AAiEA,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAKjD,0DAA0D;AAC1D,eAAO,MAAM,uBAAuB,QAAgB,CAAC;AAQrD,MAAM,WAAW,eAAe;IAC9B,kDAAkD;IAClD,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,iDAAiD;IACjD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,+DAA+D;IAC/D,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CACvC;AAQD,2CAA2C;AAC3C,qBAAa,cAAe,SAAQ,KAAK;aAE6B,KAAK,CAAC,EAAE,OAAO;IADnF,SAAgB,IAAI,EAAE,MAAM,CAAC;gBACjB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAA2B,KAAK,CAAC,EAAE,OAAO,YAAA;CAKpF;AAED;;;;;;GAMG;AACH,qBAAa,SAAS;;gBAKR,MAAM,EAAE,eAAe;IAanC;;;;;;;;;;;;;;;;;;OAkBG;IACG,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAO,GACnE,OAAO,CAAC,IAAI,CAAC;IA8EhB;;;;;;;;;;;;;;;;;OAiBG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAqChE,mEAAmE;IACnE,kBAAkB,IAAI,MAAM;IAI5B,qFAAqF;IACrF,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI5C;;;OAGG;IACH,KAAK,IAAI,IAAI;CAsKd"}
@@ -0,0 +1,381 @@
1
+ /**
2
+ * A2A v1.0 outbound client primitive (groundnuty/macf#396 Phase 3).
3
+ *
4
+ * MACF channel-server's outbound A2A capability — dispatches `message/send`
5
+ * JSON-RPC to remote A2A v1.0-compliant agents + fetches their AgentCard
6
+ * via `/.well-known/agent-card.json`.
7
+ *
8
+ * **Hand-rolled SDK** (consistent with Phase 1 + 2a + 2c decisions):
9
+ * `@a2a-js/sdk` is at v0.3.13 (A2A v0.3 target); v1.0 not released.
10
+ * Hand-rolled Zod schemas (Message + Task + JSON-RPC envelopes) +
11
+ * `node:https` request are the minimal-blast-radius approach + reuse
12
+ * the same shapes the inbound side validates. Re-evaluate at Phase 3.5
13
+ * or Phase 4 if SDK reaches v1.0 stable.
14
+ *
15
+ * **Spec verification** (2026-05-19 via a2a-protocol.org):
16
+ * - § 9 JSON-RPC binding: method `"message/send"`; envelope `{ jsonrpc: "2.0", id, method, params }`
17
+ * - § 4.1.4 Message schema (reused from `a2a-types.ts`)
18
+ * - § 4.1.1 Task return shape (reused from `a2a-types.ts`)
19
+ * - § 14.3 well-known URL convention for AgentCard discovery
20
+ * - W3C tracecontext propagation via HTTP `traceparent` header
21
+ * (`propagation.inject()` from `@opentelemetry/api`)
22
+ *
23
+ * **Design references**: design proposal posted on `#396` 2026-05-19
24
+ * (science-agent approved with two notes — both addressed):
25
+ * - Span name: `invoke_agent {target}` via `buildInvokeAgentSpanName()`
26
+ * helper from `tracing.ts:60-65`; NOT `macf.invoke_agent`
27
+ * - AgentCard cache: folded into this file (NOT a separate `agent-card-cache.ts`);
28
+ * extract only if cache surface grows in a future phase
29
+ *
30
+ * **Retry policy** (per design Q4):
31
+ * - `getAgentCard()`: idempotent + safe to retry. Up to 3 attempts on
32
+ * network errors with exponential backoff (1s/2s/4s; ~7s total).
33
+ * - `sendMessage()`: NOT retried. The spec doesn't mandate `messageId`
34
+ * deduplication on the server side; re-sending may create a new task.
35
+ * Caller responsibility to handle network errors with explicit retry
36
+ * semantics (and a fresh `messageId` if they choose to).
37
+ *
38
+ * **AgentCard cache** (per design Q6):
39
+ * - Per-target in-memory Map; 5-min TTL
40
+ * - Fresh fetch on miss + on auth-failure (401/403)
41
+ * - Sweep on process exit (matches Phase 2a TaskStore lifecycle)
42
+ *
43
+ * **mTLS configuration**:
44
+ * - Per-project CA chain reused (DR-010 + DR-022)
45
+ * - `node:https.Agent` with `keepAlive: true` for connection reuse
46
+ * - `checkServerIdentity: () => undefined` since channel-server certs
47
+ * advertise CN-based identity, not SAN-matched hostname (matches
48
+ * existing `notify-peer.ts` outbound pattern)
49
+ */
50
+ import { request as httpsRequest, Agent as HttpsAgent } from 'node:https';
51
+ import { randomUUID } from 'node:crypto';
52
+ import { context, propagation, SpanKind, SpanStatusCode, trace, } from '@opentelemetry/api';
53
+ import { buildInvokeAgentSpanName, Attr, GenAiAttr } from './tracing.js';
54
+ import { JsonRpcSuccessResponseSchema, JsonRpcErrorResponseSchema, A2A_METHOD_MESSAGE_SEND, A2A_ENDPOINT_PATH, } from './a2a-types.js';
55
+ import { AgentCardSchema } from './agent-card.js';
56
+ /** Default request timeout for outbound A2A calls (synchronous message/send). */
57
+ const DEFAULT_TIMEOUT_MS = 30_000;
58
+ /** Default per-target AgentCard cache TTL (5 minutes). */
59
+ export const AGENT_CARD_CACHE_TTL_MS = 5 * 60 * 1000;
60
+ /** Well-known URL path for AgentCard discovery (A2A spec § 14.3). */
61
+ const AGENT_CARD_PATH = '/.well-known/agent-card.json';
62
+ /** Retry policy for idempotent operations (AgentCard fetch). */
63
+ const IDEMPOTENT_RETRY_DELAYS_MS = [1000, 2000, 4000];
64
+ /** Error class for A2A client failures. */
65
+ export class A2aClientError extends Error {
66
+ cause;
67
+ code;
68
+ constructor(code, message, cause) {
69
+ super(message);
70
+ this.cause = cause;
71
+ this.name = 'A2aClientError';
72
+ this.code = code;
73
+ }
74
+ }
75
+ /**
76
+ * Outbound A2A v1.0 client. Single instance per channel-server process.
77
+ *
78
+ * Hold the keep-alive https.Agent + AgentCard cache as instance state.
79
+ * Stateless across calls otherwise — each `sendMessage` /
80
+ * `getAgentCard` invocation is independent.
81
+ */
82
+ export class A2aClient {
83
+ #config;
84
+ #agent;
85
+ #agentCardCache = new Map();
86
+ constructor(config) {
87
+ this.#config = config;
88
+ // keepAlive lets us reuse TLS sessions across per-target calls; the
89
+ // agent-card-discovery flow typically does 2 calls (card fetch then
90
+ // message/send) so keepAlive saves a TLS handshake on the second.
91
+ this.#agent = new HttpsAgent({
92
+ keepAlive: true,
93
+ // Per-host concurrency cap. Channel-server's outbound is
94
+ // typically low-concurrency (1-2 in flight), so default is fine.
95
+ maxSockets: 8,
96
+ });
97
+ }
98
+ /**
99
+ * Dispatch a `message/send` JSON-RPC call to a remote A2A v1.0 endpoint.
100
+ *
101
+ * Wraps in OTel CLIENT span named `invoke_agent {target}` per the
102
+ * canonical GenAI semconv (matches the existing `notify_peer` outbound
103
+ * pattern post-macf#369). The `target` is derived from the target URL's
104
+ * host:port pair when not explicitly provided.
105
+ *
106
+ * Returns the parsed `Task` on success.
107
+ *
108
+ * Throws `A2aClientError` on:
109
+ * - Transport failure (TLS, connect timeout, etc.) — code `'TRANSPORT_ERROR'`
110
+ * - HTTP non-200 — code `'HTTP_ERROR'`
111
+ * - JSON-RPC error envelope (`error` field set in response) — code `'JSONRPC_ERROR'`
112
+ * with `.cause` carrying the structured error object
113
+ * - Schema validation failure on response body — code `'INVALID_RESPONSE'`
114
+ *
115
+ * Does NOT retry on failure (per design Q4 — `message/send` is not idempotent).
116
+ */
117
+ async sendMessage(targetUrl, message, opts = {}) {
118
+ const tracer = trace.getTracer('macf');
119
+ const spanTarget = opts.target ?? this.#deriveTargetHandle(targetUrl);
120
+ const requestId = opts.requestId ?? `req-${randomUUID()}`;
121
+ return tracer.startActiveSpan(buildInvokeAgentSpanName(spanTarget), {
122
+ kind: SpanKind.CLIENT,
123
+ attributes: {
124
+ [GenAiAttr.System]: 'macf',
125
+ [GenAiAttr.OperationName]: 'invoke_agent',
126
+ ...(spanTarget !== '' ? { [GenAiAttr.AgentName]: spanTarget } : {}),
127
+ // macf#396 Phase 3: distinguish A2A outbound from legacy
128
+ // notify_peer outbound under a single span name (both emit
129
+ // `invoke_agent` per OTel GenAI semconv; the `macf.outbound.
130
+ // protocol` attribute tells operators which dispatch path
131
+ // ran). Sister to the SERVER-side `macf.a2a.dispatch`
132
+ // attribute set in https.ts.
133
+ [Attr.OutboundProtocol]: 'a2a',
134
+ [Attr.OutboundTargetUrl]: targetUrl,
135
+ },
136
+ }, async (span) => {
137
+ try {
138
+ const envelope = {
139
+ jsonrpc: '2.0',
140
+ id: requestId,
141
+ method: A2A_METHOD_MESSAGE_SEND,
142
+ params: { message },
143
+ };
144
+ const response = await this.#postJsonRpc(`${targetUrl}${A2A_ENDPOINT_PATH}`, envelope);
145
+ // Try success-shape first; fall through to error-shape.
146
+ const success = JsonRpcSuccessResponseSchema.safeParse(response);
147
+ if (success.success) {
148
+ const task = success.data.result;
149
+ span.setAttribute(Attr.A2aTaskId, task.id);
150
+ span.setAttribute(Attr.A2aTaskState, task.status.state);
151
+ span.setStatus({ code: SpanStatusCode.OK });
152
+ return task;
153
+ }
154
+ const errorEnv = JsonRpcErrorResponseSchema.safeParse(response);
155
+ if (errorEnv.success) {
156
+ const err = new A2aClientError('JSONRPC_ERROR', `A2A server returned JSON-RPC error: ${errorEnv.data.error.message}`, errorEnv.data.error);
157
+ span.recordException(err);
158
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
159
+ throw err;
160
+ }
161
+ const err = new A2aClientError('INVALID_RESPONSE', `Response matches neither success nor error envelope`);
162
+ span.recordException(err);
163
+ span.setStatus({ code: SpanStatusCode.ERROR, message: err.message });
164
+ throw err;
165
+ }
166
+ catch (err) {
167
+ if (!(err instanceof A2aClientError)) {
168
+ span.recordException(err);
169
+ span.setStatus({
170
+ code: SpanStatusCode.ERROR,
171
+ message: err instanceof Error ? err.message : String(err),
172
+ });
173
+ }
174
+ throw err;
175
+ }
176
+ finally {
177
+ span.end();
178
+ }
179
+ });
180
+ }
181
+ /**
182
+ * Fetch a target's AgentCard via the well-known URL. Caches the result
183
+ * per `targetUrl` for `agentCardCacheTtlMs` (default 5min).
184
+ *
185
+ * Returns `null` if:
186
+ * - The endpoint returns 404 (target doesn't publish an AgentCard)
187
+ * - The endpoint returns 401/403 (auth failure — cache miss + signals
188
+ * to caller that they may need to refresh credentials)
189
+ *
190
+ * Throws `A2aClientError` on:
191
+ * - Transport failure (TLS, connect timeout) — code `'TRANSPORT_ERROR'`
192
+ * - HTTP 5xx — code `'HTTP_ERROR'` (caller may want to retry)
193
+ * - Body fails AgentCard schema validation — code `'INVALID_AGENT_CARD'`
194
+ *
195
+ * Retry on network errors: 3 attempts with exponential backoff
196
+ * (1s/2s/4s; total ~7s). HTTP responses (200, 404, 4xx, 5xx) are not
197
+ * retried — they're authoritative server signals.
198
+ */
199
+ async getAgentCard(targetUrl) {
200
+ const cached = this.#agentCardCache.get(targetUrl);
201
+ const ttl = this.#config.agentCardCacheTtlMs ?? AGENT_CARD_CACHE_TTL_MS;
202
+ if (cached !== undefined && Date.now() - cached.fetchedAt < ttl) {
203
+ return cached.card;
204
+ }
205
+ let lastError;
206
+ for (let attempt = 0; attempt <= IDEMPOTENT_RETRY_DELAYS_MS.length; attempt++) {
207
+ try {
208
+ const result = await this.#fetchAgentCardOnce(targetUrl);
209
+ if (result === null) {
210
+ // Auth/missing — don't cache; signal to caller.
211
+ this.#agentCardCache.delete(targetUrl);
212
+ return null;
213
+ }
214
+ this.#agentCardCache.set(targetUrl, { card: result, fetchedAt: Date.now() });
215
+ return result;
216
+ }
217
+ catch (err) {
218
+ lastError = err;
219
+ if (err instanceof A2aClientError && err.code !== 'TRANSPORT_ERROR') {
220
+ // HTTP-level error or schema-validation failure — authoritative;
221
+ // don't retry.
222
+ throw err;
223
+ }
224
+ // Transport error — back off + retry (if attempts remain).
225
+ if (attempt < IDEMPOTENT_RETRY_DELAYS_MS.length) {
226
+ await new Promise((r) => setTimeout(r, IDEMPOTENT_RETRY_DELAYS_MS[attempt]));
227
+ }
228
+ }
229
+ }
230
+ // Exhausted retries — surface the last error.
231
+ throw lastError;
232
+ }
233
+ /** Diagnostic: count of cached AgentCard entries (testing aid). */
234
+ agentCardCacheSize() {
235
+ return this.#agentCardCache.size;
236
+ }
237
+ /** Manually invalidate a cached AgentCard (e.g., after detected target rotation). */
238
+ invalidateAgentCard(targetUrl) {
239
+ this.#agentCardCache.delete(targetUrl);
240
+ }
241
+ /**
242
+ * Close the underlying https.Agent. Call on channel-server shutdown to
243
+ * release pooled sockets cleanly.
244
+ */
245
+ close() {
246
+ this.#agent.destroy();
247
+ this.#agentCardCache.clear();
248
+ }
249
+ // -------------------------------------------------------------------------
250
+ // Private helpers
251
+ // -------------------------------------------------------------------------
252
+ /**
253
+ * Derive a span-attribute target handle from a target URL. Prefer the
254
+ * host:port pair; fall back to the bare URL if parsing fails.
255
+ */
256
+ #deriveTargetHandle(targetUrl) {
257
+ try {
258
+ const u = new URL(targetUrl);
259
+ return `${u.hostname}:${u.port}`;
260
+ }
261
+ catch {
262
+ return targetUrl;
263
+ }
264
+ }
265
+ /**
266
+ * Single AgentCard fetch attempt. Returns null on 404/401/403; throws
267
+ * on transport / 5xx / schema-validation failure.
268
+ */
269
+ async #fetchAgentCardOnce(targetUrl) {
270
+ const fullUrl = `${targetUrl}${AGENT_CARD_PATH}`;
271
+ const { status, body } = await this.#httpsGet(fullUrl);
272
+ if (status === 404 || status === 401 || status === 403) {
273
+ return null;
274
+ }
275
+ if (status >= 500) {
276
+ throw new A2aClientError('HTTP_ERROR', `AgentCard fetch returned HTTP ${status}`);
277
+ }
278
+ if (status !== 200) {
279
+ throw new A2aClientError('HTTP_ERROR', `AgentCard fetch returned unexpected HTTP ${status}`);
280
+ }
281
+ let parsed;
282
+ try {
283
+ parsed = JSON.parse(body);
284
+ }
285
+ catch (err) {
286
+ throw new A2aClientError('INVALID_AGENT_CARD', `AgentCard body is not valid JSON`, err);
287
+ }
288
+ const validated = AgentCardSchema.safeParse(parsed);
289
+ if (!validated.success) {
290
+ throw new A2aClientError('INVALID_AGENT_CARD', `AgentCard body fails schema validation: ${validated.error.message}`, validated.error);
291
+ }
292
+ return validated.data;
293
+ }
294
+ /**
295
+ * Issue a JSON-RPC POST. Returns the parsed response body on HTTP 200
296
+ * (whether success or error envelope — caller discriminates). Throws
297
+ * on transport / non-200 / non-JSON.
298
+ *
299
+ * Tracecontext is injected via `propagation.inject(context.active(),
300
+ * headers)` — picks up the active span (set by `sendMessage`'s tracer
301
+ * scope) and writes `traceparent` + `tracestate` headers.
302
+ */
303
+ async #postJsonRpc(url, envelope) {
304
+ const bodyStr = JSON.stringify(envelope);
305
+ const headers = {
306
+ 'Content-Type': 'application/json',
307
+ 'Content-Length': Buffer.byteLength(bodyStr).toString(),
308
+ };
309
+ propagation.inject(context.active(), headers);
310
+ const { status, body } = await this.#httpsSend(url, 'POST', headers, bodyStr);
311
+ if (status !== 200) {
312
+ throw new A2aClientError('HTTP_ERROR', `JSON-RPC POST returned HTTP ${status}: ${body.slice(0, 200)}`);
313
+ }
314
+ try {
315
+ return JSON.parse(body);
316
+ }
317
+ catch (err) {
318
+ throw new A2aClientError('INVALID_RESPONSE', `JSON-RPC response body is not valid JSON`, err);
319
+ }
320
+ }
321
+ /** Issue an HTTPS GET. */
322
+ async #httpsGet(url) {
323
+ const headers = {};
324
+ propagation.inject(context.active(), headers);
325
+ return this.#httpsSend(url, 'GET', headers, null);
326
+ }
327
+ /**
328
+ * Low-level HTTPS request with mTLS client cert + connection pooling.
329
+ * Returns `{ status, body }` on completion; rejects on transport error
330
+ * with `A2aClientError` `code: 'TRANSPORT_ERROR'`.
331
+ */
332
+ #httpsSend(url, method, headers, body) {
333
+ return new Promise((resolve, reject) => {
334
+ let parsedUrl;
335
+ try {
336
+ parsedUrl = new URL(url);
337
+ }
338
+ catch (err) {
339
+ reject(new A2aClientError('TRANSPORT_ERROR', `Invalid URL: ${url}`, err));
340
+ return;
341
+ }
342
+ const req = httpsRequest({
343
+ hostname: parsedUrl.hostname,
344
+ port: parsedUrl.port,
345
+ path: `${parsedUrl.pathname}${parsedUrl.search}`,
346
+ method,
347
+ headers,
348
+ cert: this.#config.mTlsClientCertPem,
349
+ key: this.#config.mTlsClientKeyPem,
350
+ ca: this.#config.caCertPem,
351
+ rejectUnauthorized: true,
352
+ // Same rationale as notify-peer.ts: channel-server certs use
353
+ // CN-based identity, not SAN-matched hostname.
354
+ checkServerIdentity: () => undefined,
355
+ agent: this.#agent,
356
+ timeout: this.#config.timeoutMs ?? DEFAULT_TIMEOUT_MS,
357
+ }, (res) => {
358
+ const chunks = [];
359
+ res.on('data', (c) => chunks.push(c));
360
+ res.on('end', () => {
361
+ resolve({
362
+ status: res.statusCode ?? 0,
363
+ body: Buffer.concat(chunks).toString('utf-8'),
364
+ });
365
+ });
366
+ });
367
+ req.on('error', (err) => {
368
+ reject(new A2aClientError('TRANSPORT_ERROR', err.message, err));
369
+ });
370
+ req.on('timeout', () => {
371
+ req.destroy();
372
+ reject(new A2aClientError('TRANSPORT_ERROR', 'request timeout'));
373
+ });
374
+ if (body !== null) {
375
+ req.write(body);
376
+ }
377
+ req.end();
378
+ });
379
+ }
380
+ }
381
+ //# sourceMappingURL=a2a-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a-client.js","sourceRoot":"","sources":["../src/a2a-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ import type { Task, TaskState, Message } from './a2a-types.js';
2
+ /** True iff `from → to` is a legal transition per the v1.0 spec table. */
3
+ export declare function isTransitionAllowed(from: TaskState, to: TaskState): boolean;
4
+ /** Error class for illegal state transitions. */
5
+ export declare class InvalidTaskTransitionError extends Error {
6
+ readonly from: TaskState;
7
+ readonly to: TaskState;
8
+ readonly taskId: string;
9
+ readonly code = "INVALID_TASK_TRANSITION";
10
+ constructor(from: TaskState, to: TaskState, taskId: string);
11
+ }
12
+ /** Error class for resume attempts against unknown task ids (macf#392 Phase 2b). */
13
+ export declare class TaskNotFoundError extends Error {
14
+ readonly taskId: string;
15
+ readonly code = "TASK_NOT_FOUND";
16
+ constructor(taskId: string);
17
+ }
18
+ /** Error class for resume attempts against non-resumable from-states (macf#392 Phase 2b). */
19
+ export declare class TaskNotResumableError extends Error {
20
+ readonly taskId: string;
21
+ readonly currentState: TaskState;
22
+ readonly code = "TASK_NOT_RESUMABLE";
23
+ constructor(taskId: string, currentState: TaskState);
24
+ }
25
+ /** Error class for cancel attempts against terminal tasks (macf#398 Phase 2d). */
26
+ export declare class TaskNotCancelableError extends Error {
27
+ readonly taskId: string;
28
+ readonly currentState: TaskState;
29
+ readonly code = "TASK_NOT_CANCELABLE";
30
+ constructor(taskId: string, currentState: TaskState);
31
+ }
32
+ /**
33
+ * In-memory task store. NOT durable across channel-server restarts;
34
+ * Phase 2.5 will revisit if longer-lived persistence becomes a need.
35
+ *
36
+ * Concurrency: single-threaded Node.js event loop; no locking needed
37
+ * between request handlers. Map operations are atomic per-event-loop-turn.
38
+ */
39
+ export declare class TaskStore {
40
+ #private;
41
+ /**
42
+ * Create a fresh task in SUBMITTED state. Returns the task; caller
43
+ * is responsible for any subsequent transition.
44
+ *
45
+ * `contextId` is propagated from the inbound Message if present
46
+ * (per spec § 4.1.4 — contextId associates with a conversational
47
+ * group); otherwise undefined.
48
+ */
49
+ create(initialMessage: Message, opts: {
50
+ readonly nowIso: string;
51
+ }): Task;
52
+ /**
53
+ * Look up a task by ID. Used for resume flows (Message.taskId set)
54
+ * + idempotent retries. Returns `undefined` if no such task.
55
+ */
56
+ get(taskId: string): Task | undefined;
57
+ /**
58
+ * Apply a state transition. Validates against the spec table; throws
59
+ * `InvalidTaskTransitionError` on illegal moves. Returns the updated
60
+ * task (mutated in-place + immutable references returned for callers).
61
+ *
62
+ * Side effect: updates `task.status.state` + `task.status.timestamp`.
63
+ * `task.status.message` is set when the caller provides an
64
+ * accompanying message (e.g., agent's response).
65
+ */
66
+ transition(taskId: string, to: TaskState, opts: {
67
+ readonly nowIso: string;
68
+ readonly message?: Message;
69
+ }): Task;
70
+ /** True iff a task's current state is terminal. */
71
+ isTerminal(taskId: string): boolean;
72
+ /** Diagnostic: count of currently-tracked tasks. */
73
+ size(): number;
74
+ /**
75
+ * Phase 2a helper: drive a fresh task through the happy path
76
+ * SUBMITTED → WORKING → COMPLETED in one call. Returns the final
77
+ * task. Used by the inbound `message/send` route when the message
78
+ * is a non-resume submission with no intermediate-state needs.
79
+ *
80
+ * `responseMessage` is the agent's reply (role=ROLE_AGENT) attached
81
+ * to the COMPLETED status. Phase 2b will replace this with a real
82
+ * dispatch to MACF tooling that can return INPUT_REQUIRED.
83
+ */
84
+ completeHappyPath(initialMessage: Message, responseMessage: Message, opts: {
85
+ readonly nowIso: string;
86
+ }): Task;
87
+ /**
88
+ * Resume a task currently in INPUT_REQUIRED or AUTH_REQUIRED state
89
+ * (macf#392 Phase 2b). Validates ROLE_USER on the resume message
90
+ * (canonical client→server direction per spec § 4.1.5), the
91
+ * from-state is resumable, and transitions back to WORKING with
92
+ * the resume message appended to history.
93
+ *
94
+ * Errors:
95
+ * - `TaskNotFoundError` if `taskId` doesn't match any tracked task
96
+ * - `TaskNotResumableError` if from-state isn't INPUT_REQUIRED or AUTH_REQUIRED
97
+ * - `Error` (generic) if message.role !== 'ROLE_USER'
98
+ */
99
+ resume(taskId: string, resumeMessage: Message, opts: {
100
+ readonly nowIso: string;
101
+ }): Task;
102
+ /**
103
+ * Drive a fresh task to REJECTED state (macf#392 Phase 2b test
104
+ * fixture). SUBMITTED → REJECTED is a legal transition per the
105
+ * canonical proto table. Used by route handler test trigger when
106
+ * the inbound Message text matches a synthetic rejection pattern.
107
+ *
108
+ * NOT a production-policy rejection layer — real refusal logic
109
+ * comes in Phase 3+ when the skill-name → MCP-tool dispatcher
110
+ * needs to refuse certain inputs.
111
+ */
112
+ rejectFresh(initialMessage: Message, reason: Message, opts: {
113
+ readonly nowIso: string;
114
+ }): Task;
115
+ /**
116
+ * Cancel a non-terminal task (macf#398 Phase 2d). Cancellable from
117
+ * SUBMITTED / WORKING / INPUT_REQUIRED / AUTH_REQUIRED per the spec
118
+ * transition table; terminal tasks (COMPLETED / FAILED / CANCELED /
119
+ * REJECTED) reject with TaskNotCancelableError.
120
+ *
121
+ * Idempotent on already-CANCELED tasks would be ergonomic, but the
122
+ * spec doesn't mandate it + the transition table makes CANCELED a
123
+ * terminal state — so re-cancel returns the error. Callers can
124
+ * detect the terminal state via tasks/get first if they need to
125
+ * disambiguate.
126
+ *
127
+ * Errors:
128
+ * - `TaskNotFoundError` if `taskId` is unknown
129
+ * - `TaskNotCancelableError` if task is already terminal
130
+ */
131
+ cancel(taskId: string, opts: {
132
+ readonly nowIso: string;
133
+ }): Task;
134
+ }
135
+ //# sourceMappingURL=a2a-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a-task.d.ts","sourceRoot":"","sources":["../src/a2a-task.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAsD/D,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,GAAG,OAAO,CAE3E;AAED,iDAAiD;AACjD,qBAAa,0BAA2B,SAAQ,KAAK;aAGjC,IAAI,EAAE,SAAS;aACf,EAAE,EAAE,SAAS;aACb,MAAM,EAAE,MAAM;IAJhC,SAAgB,IAAI,6BAA6B;gBAE/B,IAAI,EAAE,SAAS,EACf,EAAE,EAAE,SAAS,EACb,MAAM,EAAE,MAAM;CAKjC;AAED,oFAAoF;AACpF,qBAAa,iBAAkB,SAAQ,KAAK;aAEd,MAAM,EAAE,MAAM;IAD1C,SAAgB,IAAI,oBAAoB;gBACZ,MAAM,EAAE,MAAM;CAI3C;AAED,6FAA6F;AAC7F,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,MAAM,EAAE,MAAM;aACd,YAAY,EAAE,SAAS;IAHzC,SAAgB,IAAI,wBAAwB;gBAE1B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,SAAS;CAK1C;AAED,kFAAkF;AAClF,qBAAa,sBAAuB,SAAQ,KAAK;aAG7B,MAAM,EAAE,MAAM;aACd,YAAY,EAAE,SAAS;IAHzC,SAAgB,IAAI,yBAAyB;gBAE3B,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,SAAS;CAK1C;AAMD;;;;;;GAMG;AACH,qBAAa,SAAS;;IAGpB;;;;;;;OAOG;IACH,MAAM,CAAC,cAAc,EAAE,OAAO,EAAE,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAexE;;;OAGG;IACH,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAIrC;;;;;;;;OAQG;IACH,UAAU,CACR,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,SAAS,EACb,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAC5D,IAAI;IA4BP,mDAAmD;IACnD,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAMnC,oDAAoD;IACpD,IAAI,IAAI,MAAM;IAId;;;;;;;;;OASG;IACH,iBAAiB,CACf,cAAc,EAAE,OAAO,EACvB,eAAe,EAAE,OAAO,EACxB,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAChC,IAAI;IASP;;;;;;;;;;;OAWG;IACH,MAAM,CACJ,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,OAAO,EACtB,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAChC,IAAI;IAmBP;;;;;;;;;OASG;IACH,WAAW,CACT,cAAc,EAAE,OAAO,EACvB,MAAM,EAAE,OAAO,EACf,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAChC,IAAI;IAQP;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;CAUhE"}