@ap3x/a2a 1.0.0 → 2.0.0

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/LICENSE +21 -0
  2. package/README.md +27 -0
  3. package/dist/backend.d.ts +89 -0
  4. package/dist/backend.d.ts.map +1 -0
  5. package/dist/bindings/grpc.d.ts +121 -0
  6. package/dist/bindings/grpc.d.ts.map +1 -0
  7. package/dist/bindings/jsonrpc.d.ts +135 -0
  8. package/dist/bindings/jsonrpc.d.ts.map +1 -0
  9. package/dist/bindings/rest.d.ts +75 -0
  10. package/dist/bindings/rest.d.ts.map +1 -0
  11. package/dist/chunk-PYM7LV6R.js +1590 -0
  12. package/dist/client.d.ts +116 -0
  13. package/dist/client.d.ts.map +1 -0
  14. package/dist/executor.d.ts +91 -0
  15. package/dist/executor.d.ts.map +1 -0
  16. package/dist/grpc-5DAU6EYQ.js +591 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +454 -0
  20. package/dist/model.d.ts +480 -0
  21. package/dist/model.d.ts.map +1 -0
  22. package/dist/server.d.ts +60 -0
  23. package/dist/server.d.ts.map +1 -0
  24. package/dist/task-store.d.ts +61 -0
  25. package/dist/task-store.d.ts.map +1 -0
  26. package/package.json +26 -15
  27. package/proto/a2a.proto +813 -0
  28. package/proto/google/api/annotations.proto +6 -0
  29. package/proto/google/api/client.proto +4 -0
  30. package/proto/google/api/field_behavior.proto +4 -0
  31. package/src/__tests__/a2a-auth-expired.test.ts +0 -84
  32. package/src/__tests__/a2a.test.ts +0 -87
  33. package/src/__tests__/handler-sendsubscribe-error.test.ts +0 -32
  34. package/src/__tests__/sendsubscribe-rejected-promise.test.ts +0 -89
  35. package/src/__tests__/server-apikey-warning.test.ts +0 -71
  36. package/src/__tests__/server-body-limit.test.ts +0 -54
  37. package/src/__tests__/server-security-headers.test.ts +0 -112
  38. package/src/__tests__/server-timing-safe-auth.test.ts +0 -45
  39. package/src/__tests__/sse-handler-error-propagation.test.ts +0 -69
  40. package/src/card/generator.ts +0 -18
  41. package/src/client/index.ts +0 -172
  42. package/src/errors.ts +0 -21
  43. package/src/index.ts +0 -15
  44. package/src/server/handler.ts +0 -90
  45. package/src/server/index.ts +0 -208
  46. package/src/server/sse.ts +0 -49
  47. package/src/swarm/a2a-agent.ts +0 -34
  48. package/src/types.ts +0 -50
  49. package/tsconfig.json +0 -20
  50. package/vitest.config.ts +0 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AP3X
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,27 @@
1
+ # @ap3x/a2a
2
+
3
+ A2A protocol support: a client, a server, and the bindings that let a remote agent join a local swarm as an ordinary member.
4
+
5
+ Part of [AP3X](https://github.com/AP3X-Dev/AP3X) — a TypeScript multi-agent framework.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @ap3x/a2a
11
+ ```
12
+
13
+ ## What's inside
14
+
15
+ - **Client + server** — the A2A request/response surface with agent-card discovery.
16
+ - **Transports** — JSON-RPC and REST, with an optional gRPC binding that is lazily loaded so gRPC stays an opt-in dependency.
17
+ - **Swarm integration** — a remote A2A agent satisfies `AgentBackend`, so orchestration consumes it like any local member.
18
+
19
+ The A2A specification is Apache-2.0; see [a2aproject/A2A](https://github.com/a2aproject/A2A).
20
+
21
+ ## Documentation
22
+
23
+ See the [AP3X repository](https://github.com/AP3X-Dev/AP3X) for architecture notes, the full package map, and examples.
24
+
25
+ ## License
26
+
27
+ MIT
@@ -0,0 +1,89 @@
1
+ /**
2
+ * A2aBackend — an {@link AgentBackend} whose "runtime" is a remote A2A agent
3
+ * reached through an {@link A2aClient}. The mirror of `A2aExecutor`:
4
+ *
5
+ * - `run()` sends the task as an A2A Message (blocking by default) and, when
6
+ * the answer is not yet terminal, polls `GetTask` with capped exponential
7
+ * backoff.
8
+ * - `runStream()` (present only when the card declares streaming) maps the SSE
9
+ * stream (initial Task frame, then status updates) back to agent-core
10
+ * `AgentEvent`s.
11
+ * - ONE `contextId` per backend instance: consecutive runs share the remote
12
+ * conversational thread, mirroring a local stateful agent.
13
+ * - Failure containment: network/HTTP/protocol/timeout failures surface as a
14
+ * failed `AgentRunResult` (`stopReason: "error"`) — `run()` NEVER throws.
15
+ * - `abort()` (and `opts.signal`) cancels the in-flight HTTP request itself —
16
+ * even a blocking send with no task id yet — and best-effort CancelTasks
17
+ * once a task id is known; the run resolves a failed result, never throws.
18
+ * - `close()` / `Symbol.(async)Dispose` releases the shared client (refcounted
19
+ * across clones) — the grpc channel, when one was negotiated.
20
+ * - Usage is ZEROED, never fabricated: remote usage is not in the v1 model.
21
+ */
22
+ import type { AgentBackend, AgentEventStream, AgentMessage, AgentRunOptions, AgentRunResult, BackendCapability } from "@ap3x/agent-core";
23
+ import { A2aClient, type A2aClientOptions } from "./client";
24
+ import { type AgentCard } from "./model";
25
+ export interface A2aBackendOptions {
26
+ /** First poll delay when the remote answer is not yet terminal. Default 250. */
27
+ pollInitialDelayMs?: number;
28
+ /** Backoff cap. Default 5000. */
29
+ pollMaxDelayMs?: number;
30
+ /** Overall run deadline. Default 10 minutes (remote agents are orchestrators). */
31
+ timeoutMs?: number;
32
+ /** Injectable sleep (tests assert the backoff schedule). */
33
+ sleep?: (ms: number) => Promise<void>;
34
+ /** Injected clock (epoch millis). */
35
+ now?: () => number;
36
+ }
37
+ export declare class A2aBackend implements AgentBackend {
38
+ readonly card: AgentCard;
39
+ /** Present only when the card declares `capabilities.streaming`. */
40
+ runStream?: (task: string | AgentMessage[], opts?: AgentRunOptions) => AgentEventStream;
41
+ private readonly client;
42
+ private readonly options;
43
+ private readonly pollInitialDelayMs;
44
+ private readonly pollMaxDelayMs;
45
+ private readonly timeoutMs;
46
+ private readonly sleep;
47
+ private readonly now;
48
+ /** One conversational thread per instance; adopted from the first answer. */
49
+ private contextId?;
50
+ private currentTaskId?;
51
+ /** Aborts the in-flight HTTP request of the current run/stream. */
52
+ private runAbort?;
53
+ private closed;
54
+ /** Clones share the client (one grpc channel); the channel closes at zero. */
55
+ private readonly clientRefs;
56
+ constructor(client: A2aClient, options?: A2aBackendOptions, refs?: {
57
+ count: number;
58
+ });
59
+ run(task: string | AgentMessage[], opts?: AgentRunOptions): Promise<AgentRunResult>;
60
+ /**
61
+ * Cancel the current run: aborts the in-flight HTTP request (even a blocking
62
+ * send with no task id yet) and, when a task id is known, issues a
63
+ * best-effort remote CancelTask.
64
+ */
65
+ abort(): void;
66
+ /** A new backend over the SAME client/card (a remote agent is one endpoint). */
67
+ clone(): AgentBackend;
68
+ /**
69
+ * Release the shared client once EVERY clone has closed (refcounted): the
70
+ * underlying transport (the grpc channel, when negotiated) is released only
71
+ * when the last backend over it closes. Idempotent per backend.
72
+ */
73
+ close(): void;
74
+ [Symbol.dispose](): void;
75
+ [Symbol.asyncDispose](): Promise<void>;
76
+ supports(capability: BackendCapability): boolean;
77
+ private cancelRemote;
78
+ private adopt;
79
+ private outbound;
80
+ private assistant;
81
+ private inbound;
82
+ private failure;
83
+ /** Map a TERMINAL remote task back to the uniform backend result. */
84
+ private toRunResult;
85
+ private streamRun;
86
+ }
87
+ /** Connect to a remote A2A agent and wrap it as an {@link AgentBackend}. */
88
+ export declare function connectA2a(baseUrl: string, options?: A2aClientOptions & A2aBackendOptions): Promise<A2aBackend>;
89
+ //# sourceMappingURL=backend.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,KAAK,EACV,YAAY,EAEZ,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,SAAS,EACT,KAAK,gBAAgB,EAItB,MAAM,UAAU,CAAC;AAElB,OAAO,EAAE,KAAK,SAAS,EAAwD,MAAM,SAAS,CAAC;AAgB/F,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iCAAiC;IACjC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,qCAAqC;IACrC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAsDD,qBAAa,UAAW,YAAW,YAAY;IAC7C,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,oEAAoE;IACpE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,KAAK,gBAAgB,CAAC;IAExF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAY;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;IAC5C,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAS;IAC5C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAgC;IACtD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,6EAA6E;IAC7E,OAAO,CAAC,SAAS,CAAC,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,mEAAmE;IACnE,OAAO,CAAC,QAAQ,CAAC,CAAkB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAoB;gBAEnC,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE,iBAAsB,EAAE,IAAI,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAkBlF,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,EAAE,EAAE,IAAI,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAiDzF;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAKb,gFAAgF;IAChF,KAAK,IAAI,YAAY;IAKrB;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAOb,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI;IAIlB,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5C,QAAQ,CAAC,UAAU,EAAE,iBAAiB,GAAG,OAAO;YAYlC,YAAY;IAU1B,OAAO,CAAC,KAAK;IAKb,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,OAAO;IAOf,OAAO,CAAC,OAAO;IAUf,qEAAqE;IACrE,OAAO,CAAC,WAAW;IAqBnB,OAAO,CAAC,SAAS;CAoGlB;AAED,4EAA4E;AAC5E,wBAAsB,UAAU,CAC9B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAgB,GAAG,iBAAsB,GACjD,OAAO,CAAC,UAAU,CAAC,CAGrB"}
@@ -0,0 +1,121 @@
1
+ import { type A2aStreamFrame } from "../client";
2
+ import type { A2aExecutor } from "../executor";
3
+ import { type Message, type Task, type TaskState } from "../model";
4
+ import { type ListTasksFilter } from "../task-store";
5
+ /** A proto<->canonical conversion failure — maps to INVALID_ARGUMENT. */
6
+ export declare class A2aGrpcMappingError extends Error {
7
+ constructor(message: string);
8
+ }
9
+ /** Canonical state -> proto `TASK_STATE_*` enum name. */
10
+ export declare function taskStateToProto(state: TaskState): string;
11
+ /** Proto `TASK_STATE_*` enum name -> canonical state; UNSPECIFIED is an error. */
12
+ export declare function taskStateFromProto(value: unknown): TaskState;
13
+ interface ProtoStruct {
14
+ fields?: Record<string, ProtoValue>;
15
+ }
16
+ interface ProtoValue {
17
+ kind?: string;
18
+ nullValue?: unknown;
19
+ numberValue?: number;
20
+ stringValue?: string;
21
+ boolValue?: boolean;
22
+ structValue?: ProtoStruct;
23
+ listValue?: {
24
+ values?: ProtoValue[];
25
+ };
26
+ }
27
+ interface ProtoTimestamp {
28
+ seconds?: number;
29
+ nanos?: number;
30
+ }
31
+ interface ProtoPart {
32
+ content?: string;
33
+ text?: string;
34
+ raw?: string;
35
+ url?: string;
36
+ data?: ProtoValue;
37
+ metadata?: ProtoStruct;
38
+ filename?: string;
39
+ mediaType?: string;
40
+ }
41
+ interface ProtoMessage {
42
+ messageId?: string;
43
+ contextId?: string;
44
+ taskId?: string;
45
+ role?: string;
46
+ parts?: ProtoPart[];
47
+ metadata?: ProtoStruct;
48
+ }
49
+ interface ProtoTaskStatus {
50
+ state?: string;
51
+ message?: ProtoMessage;
52
+ timestamp?: ProtoTimestamp;
53
+ }
54
+ interface ProtoArtifact {
55
+ artifactId?: string;
56
+ name?: string;
57
+ description?: string;
58
+ parts?: ProtoPart[];
59
+ metadata?: ProtoStruct;
60
+ }
61
+ interface ProtoTask {
62
+ id?: string;
63
+ contextId?: string;
64
+ status?: ProtoTaskStatus;
65
+ artifacts?: ProtoArtifact[];
66
+ history?: ProtoMessage[];
67
+ metadata?: ProtoStruct;
68
+ }
69
+ /** Canonical Task -> proto Task. */
70
+ export declare function taskToProto(task: Task): ProtoTask;
71
+ /** Proto Task -> canonical Task. */
72
+ export declare function taskFromProto(proto: ProtoTask): Task;
73
+ export interface A2aGrpcServerOptions {
74
+ /** Host to bind (same host as the HTTP server). */
75
+ host: string;
76
+ /** Port to bind; 0 picks an ephemeral port. */
77
+ port: number;
78
+ /** When set, every call requires metadata `authorization: Bearer <token>`. */
79
+ bearerToken?: string;
80
+ }
81
+ export interface A2aGrpcServer {
82
+ /** gRPC target of the bound server (`host:port`, no scheme). */
83
+ url: string;
84
+ close(): Promise<void>;
85
+ }
86
+ /** Serve `executor` over gRPC; resolves once bound. Card stays on HTTP. */
87
+ export declare function startGrpcServer(executor: A2aExecutor, options: A2aGrpcServerOptions): Promise<A2aGrpcServer>;
88
+ export interface GrpcClientTransportOptions {
89
+ /** Sent as metadata `authorization: Bearer <token>` on every call. */
90
+ bearerToken?: string;
91
+ /** Per-call deadline in milliseconds. */
92
+ timeoutMs: number;
93
+ }
94
+ /**
95
+ * The six A2A operations over a gRPC channel — the client half of this
96
+ * binding. Constructed by `A2aClient.connect` when the card negotiates GRPC.
97
+ */
98
+ export declare class GrpcClientTransport {
99
+ private readonly client;
100
+ private readonly timeoutMs;
101
+ private readonly bearerToken?;
102
+ constructor(target: string, options: GrpcClientTransportOptions);
103
+ /** Close the underlying channel (keeps the event loop free after tests). */
104
+ close(): void;
105
+ sendMessage(message: Message, config?: {
106
+ returnImmediately?: boolean;
107
+ }): Promise<Task | Message>;
108
+ sendStreamingMessage(message: Message): AsyncGenerator<A2aStreamFrame>;
109
+ getTask(id: string): Promise<Task>;
110
+ listTasks(filter?: ListTasksFilter): Promise<Task[]>;
111
+ cancelTask(id: string): Promise<Task>;
112
+ subscribeToTask(id: string): AsyncGenerator<A2aStreamFrame>;
113
+ private metadata;
114
+ private callOptions;
115
+ private wrapError;
116
+ private convert;
117
+ private unary;
118
+ private stream;
119
+ }
120
+ export {};
121
+ //# sourceMappingURL=grpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grpc.d.ts","sourceRoot":"","sources":["../../src/bindings/grpc.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * JSON-RPC 2.0 + SSE binding — the A2A wire dialect over the canonical model.
3
+ *
4
+ * One POST endpoint routes every method. Interop posture: **accept both
5
+ * dialects, emit slash.** The deployed reference SDK (0.3.x) speaks
6
+ * slash-methods (`message/send`, `tasks/get`, …) while the a2a-protocol.org
7
+ * "latest" spec text documents PascalCase operation names (`SendMessage`, …).
8
+ * {@link A2A_RPC_METHODS} holds the emit names (slash);
9
+ * {@link A2A_RPC_METHOD_ALIASES} is the accept-set routing BOTH families to
10
+ * the same handlers. `message/stream` and `tasks/resubscribe` answer with
11
+ * `text/event-stream`, one JSON-RPC result per event; per spec the stream
12
+ * MUST begin with the full Task object, followed by zero or more
13
+ * status/artifact update events, closing on the terminal event.
14
+ * `message/send` is BLOCKING by default — `configuration.returnImmediately:
15
+ * true` is the opt-out. JSON-RPC-level failures stay HTTP 200 per convention;
16
+ * every inbound payload is TypeBox-validated at this trust boundary.
17
+ *
18
+ * Residual interop doubts — confirm against a live reference peer, do not
19
+ * guess-implement:
20
+ * - Exact GetTask/CancelTask/SubscribeToTask param field name: we accept
21
+ * `{ id }`; the spec's proto may serialize it as `taskId`/`name`.
22
+ * - ListTasks filter/pagination param shape: we accept `{ contextId?, state? }`.
23
+ * - Whether stream events carry the `kind` discriminator in v1.0 JSON: we
24
+ * emit it on update events; clients here discriminate structurally (a Task
25
+ * has `id` + `status` and no update `kind`), so either peer choice parses.
26
+ *
27
+ * Resolved against @a2a-js/sdk 0.3.13 (accept both, emit ours):
28
+ * - Blocking knob: the SDK sends `configuration.blocking` (true = wait for
29
+ * terminal); we also accept our `configuration.returnImmediately`, which
30
+ * wins when both are present. See {@link resolveBlocking}.
31
+ * - TaskState serialization: the SDK emits hyphenated states
32
+ * (`input-required`, `auth-required`) plus `unknown`; we accept them via
33
+ * `normalizeWireTaskStates` at the parse boundary and keep emitting
34
+ * snake_case.
35
+ */
36
+ import type { ServerResponse } from "node:http";
37
+ import { type Static } from "@sinclair/typebox";
38
+ import type { A2aExecutor } from "../executor";
39
+ /**
40
+ * The JSON-RPC method strings AP3X EMITS — the slash dialect the deployed
41
+ * reference SDK (0.3.x) speaks. `tasks/list` is an AP3X extension (not in the
42
+ * 0.3.x SDK surface). `tasks/resubscribe` is the SDK's subscribe-to-existing
43
+ * verb.
44
+ */
45
+ export declare const A2A_RPC_METHODS: {
46
+ readonly sendMessage: "message/send";
47
+ readonly sendStreamingMessage: "message/stream";
48
+ readonly getTask: "tasks/get";
49
+ readonly listTasks: "tasks/list";
50
+ readonly cancelTask: "tasks/cancel";
51
+ readonly subscribeToTask: "tasks/resubscribe";
52
+ };
53
+ export type A2aRpcOperation = keyof typeof A2A_RPC_METHODS;
54
+ /**
55
+ * The ACCEPT-set: every inbound method string this binding routes, mapped to
56
+ * its canonical operation. Liberal in what we accept — both the slash dialect
57
+ * (emit names above) and the PascalCase names from the a2a-protocol.org spec
58
+ * text route to the same handlers.
59
+ */
60
+ export declare const A2A_RPC_METHOD_ALIASES: Readonly<Record<string, A2aRpcOperation>>;
61
+ export declare const JsonRpcRequestSchema: import("@sinclair/typebox").TObject<{
62
+ jsonrpc: import("@sinclair/typebox").TLiteral<"2.0">;
63
+ id: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TString, import("@sinclair/typebox").TNumber, import("@sinclair/typebox").TNull]>;
64
+ method: import("@sinclair/typebox").TString;
65
+ params: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnknown>;
66
+ }>;
67
+ export type JsonRpcRequest = Static<typeof JsonRpcRequestSchema>;
68
+ export declare const MessageSendParamsSchema: import("@sinclair/typebox").TObject<{
69
+ message: import("@sinclair/typebox").TObject<{
70
+ messageId: import("@sinclair/typebox").TString;
71
+ contextId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
72
+ taskId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
73
+ role: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"user">, import("@sinclair/typebox").TLiteral<"agent">]>;
74
+ parts: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TObject<{
75
+ mediaType: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
76
+ metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
77
+ kind: import("@sinclair/typebox").TLiteral<"text">;
78
+ text: import("@sinclair/typebox").TString;
79
+ }>, import("@sinclair/typebox").TObject<{
80
+ mediaType: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
81
+ metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
82
+ kind: import("@sinclair/typebox").TLiteral<"data">;
83
+ data: import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>;
84
+ }>, import("@sinclair/typebox").TObject<{
85
+ mediaType: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
86
+ metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
87
+ kind: import("@sinclair/typebox").TLiteral<"url">;
88
+ url: import("@sinclair/typebox").TString;
89
+ }>, import("@sinclair/typebox").TObject<{
90
+ mediaType: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
91
+ metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
92
+ kind: import("@sinclair/typebox").TLiteral<"raw">;
93
+ data: import("@sinclair/typebox").TString;
94
+ }>]>>;
95
+ metadata: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TRecord<import("@sinclair/typebox").TString, import("@sinclair/typebox").TUnknown>>;
96
+ }>;
97
+ configuration: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
98
+ /**
99
+ * When true, `SendMessage` returns the Task snapshot immediately instead
100
+ * of waiting for the terminal state. Default false — blocking is the
101
+ * spec default.
102
+ */
103
+ returnImmediately: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
104
+ /**
105
+ * The reference SDK's (0.3.x) knob for the same choice, inverted:
106
+ * `blocking: true` waits for the terminal state. Accepted for interop;
107
+ * AP3X clients emit `returnImmediately`.
108
+ */
109
+ blocking: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TBoolean>;
110
+ }>>;
111
+ }>;
112
+ /**
113
+ * Blocking resolution for `SendMessage` — ACCEPT both knobs: AP3X's
114
+ * `returnImmediately` wins when present; else the reference SDK's `blocking`;
115
+ * else blocking (the v1.0 spec default).
116
+ */
117
+ export declare function resolveBlocking(configuration?: {
118
+ returnImmediately?: boolean;
119
+ blocking?: boolean;
120
+ }): boolean;
121
+ export declare const TaskIdParamsSchema: import("@sinclair/typebox").TObject<{
122
+ id: import("@sinclair/typebox").TString;
123
+ }>;
124
+ export declare const TaskListParamsSchema: import("@sinclair/typebox").TObject<{
125
+ contextId: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
126
+ state: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TUnion<import("@sinclair/typebox").TLiteral<"submitted" | "working" | "input_required" | "auth_required" | "completed" | "failed" | "canceled" | "rejected">[]>>;
127
+ }>;
128
+ /** Open an SSE response and register it for shutdown. Shared with rest.ts. */
129
+ export declare function startSse(res: ServerResponse, sseStreams: Set<ServerResponse>): void;
130
+ /**
131
+ * Handle one JSON-RPC request body. `sseStreams` registers any stream this
132
+ * request opens so the server can shut them down on `close()`.
133
+ */
134
+ export declare function handleJsonRpc(executor: A2aExecutor, rawBody: string, res: ServerResponse, sseStreams: Set<ServerResponse>): Promise<void>;
135
+ //# sourceMappingURL=jsonrpc.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../../src/bindings/jsonrpc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAW/C;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;;;;;CAOlB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,eAAe,CAAC;AAE3D;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAU5E,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;;EAK/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAEjE,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAI9B;;;;WAIG;;QAEH;;;;WAIG;;;EAIP,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,aAAa,CAAC,EAAE;IAC9C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,OAAO,CAGV;AAED,eAAO,MAAM,kBAAkB;;EAAqC,CAAC;AAErE,eAAO,MAAM,oBAAoB;;;EAG/B,CAAC;AAmCH,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,EAAE,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,GAAG,IAAI,CAQnF;AAMD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CA2If"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * HTTP+JSON/REST binding — the same canonical core (executor / TaskStore /
3
+ * model) behind resource-style routes. Per the A2A spec every transport
4
+ * binding is a functionally equivalent mapping, so this file mirrors
5
+ * bindings/jsonrpc.ts operation-for-operation: blocking-by-default
6
+ * SendMessage, Task-first SSE streams, identical TypeBox validation at the
7
+ * trust boundary. Differences are purely syntactic: operations are HTTP
8
+ * method + path (gRPC-transcoding-style colon verbs like `:send`), errors are
9
+ * HTTP status codes carrying the same A2A error codes in a JSON body, and SSE
10
+ * frames are the bare Task / update objects (no JSON-RPC envelope).
11
+ *
12
+ * Residual interop doubts — confirm against a live reference peer, do not
13
+ * guess-implement:
14
+ * - Custom-method verb spelling: we serve `/v1/message:send` and
15
+ * `/v1/message:stream` (singular `message`, colon verbs per gRPC
16
+ * transcoding); a peer may serve plain `/v1/messages` or `/v1/message/send`.
17
+ * - Subscribe verb: we serve POST `/v1/tasks/{id}:subscribe` (custom methods
18
+ * transcode to POST); a peer may expect GET.
19
+ * - Error body: we send `{ error: { code, message } }` reusing the
20
+ * JSON-RPC-aligned A2A error codes; a peer may send google.rpc.Status
21
+ * (`{ code, message, details }`) with gRPC-numbered codes.
22
+ * - ListTasks result envelope: we return `{ tasks: [...] }` (identical to the
23
+ * JSON-RPC result); a peer may return a bare array or pagination fields.
24
+ */
25
+ import type { ServerResponse } from "node:http";
26
+ import { type Static } from "@sinclair/typebox";
27
+ import type { A2aExecutor } from "../executor";
28
+ /**
29
+ * The HTTP+JSON route table — ONE source for both the server router and the
30
+ * client transport. `{id}` marks the task-id path parameter.
31
+ */
32
+ export declare const A2A_REST_ROUTES: {
33
+ readonly sendMessage: {
34
+ readonly httpMethod: "POST";
35
+ readonly path: "/v1/message:send";
36
+ };
37
+ readonly sendStreamingMessage: {
38
+ readonly httpMethod: "POST";
39
+ readonly path: "/v1/message:stream";
40
+ };
41
+ readonly getTask: {
42
+ readonly httpMethod: "GET";
43
+ readonly path: "/v1/tasks/{id}";
44
+ };
45
+ readonly listTasks: {
46
+ readonly httpMethod: "GET";
47
+ readonly path: "/v1/tasks";
48
+ };
49
+ readonly cancelTask: {
50
+ readonly httpMethod: "POST";
51
+ readonly path: "/v1/tasks/{id}:cancel";
52
+ };
53
+ readonly subscribeToTask: {
54
+ readonly httpMethod: "POST";
55
+ readonly path: "/v1/tasks/{id}:subscribe";
56
+ };
57
+ };
58
+ export type A2aRestOperation = keyof typeof A2A_REST_ROUTES;
59
+ /** The JSON error body every non-2xx REST answer carries. */
60
+ export declare const RestErrorBodySchema: import("@sinclair/typebox").TObject<{
61
+ error: import("@sinclair/typebox").TObject<{
62
+ code: import("@sinclair/typebox").TNumber;
63
+ message: import("@sinclair/typebox").TString;
64
+ }>;
65
+ }>;
66
+ export type RestErrorBody = Static<typeof RestErrorBodySchema>;
67
+ /** HTTP status conveying each A2A error code in the REST binding. */
68
+ export declare function restStatusFor(code: number): number;
69
+ /**
70
+ * Handle one HTTP+JSON request. `path`/`query` come pre-split from the URL;
71
+ * `rawBody` is empty for GETs. `sseStreams` registers any stream this request
72
+ * opens so the server can shut it down on `close()`.
73
+ */
74
+ export declare function handleRest(executor: A2aExecutor, httpMethod: string, path: string, query: URLSearchParams, rawBody: string, res: ServerResponse, sseStreams: Set<ServerResponse>): Promise<void>;
75
+ //# sourceMappingURL=rest.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/bindings/rest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAEtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAe/C;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;CAOlB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,MAAM,OAAO,eAAe,CAAC;AAE5D,6DAA6D;AAC7D,eAAO,MAAM,mBAAmB;;;;;EAE9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAE/D,qEAAqE;AACrE,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAclD;AAuDD;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,cAAc,EACnB,UAAU,EAAE,GAAG,CAAC,cAAc,CAAC,GAC9B,OAAO,CAAC,IAAI,CAAC,CA6Gf"}