@cleocode/lafs-protocol 1.2.3 → 1.3.1

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/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  LAFS defines a standard envelope format for structured responses from LLM-powered agents and tools. It complements transport protocols like [MCP](https://modelcontextprotocol.io/) and [A2A](https://github.com/google/A2A) by standardizing what comes back — not how it gets there.
6
6
 
7
- **Current version:** 1.2.3 | [📚 Documentation](https://codluv.gitbook.io/lafs-protocol/) | [Spec](lafs.md) | [Migration Guides](migrations/)
7
+ **Current version:** 1.3.1 | [📚 Documentation](https://codluv.gitbook.io/lafs-protocol/) | [Spec](lafs.md) | [Migration Guides](migrations/)
8
8
 
9
9
  [![GitBook](https://img.shields.io/badge/docs-gitbook-blue)](https://codluv.gitbook.io/lafs-protocol/)
10
10
  [![npm](https://img.shields.io/npm/v/@cleocode/lafs-protocol)](https://www.npmjs.com/package/@cleocode/lafs-protocol)
@@ -18,7 +18,8 @@ LAFS defines a standard envelope format for structured responses from LLM-powere
18
18
  | | `schemas/v1/context-ledger.schema.json` | Context ledger for state tracking across request/response cycles |
19
19
  | | `schemas/v1/error-registry.json` | 12 registered error codes with HTTP/gRPC/CLI transport mappings |
20
20
  | **Tooling** | `src/` | TypeScript validation, conformance runner, CLI diagnostic tool |
21
- | **Tests** | `tests/` | 31 tests covering envelope, pagination, strict mode, error handling |
21
+ | **A2A** | `src/a2a/` | Agent-to-Agent integration: extensions, task lifecycle, protocol bindings (JSON-RPC/HTTP/gRPC) |
22
+ | **Tests** | `tests/` | Tests covering envelope, pagination, strict mode, error handling, A2A extensions, task lifecycle, bindings |
22
23
  | **Fixtures** | `fixtures/` | 14 JSON fixtures (valid + invalid) for conformance testing |
23
24
  | **Docs** | `docs/` | [GitBook documentation](https://codluv.gitbook.io/lafs-protocol/) with guides, SDK reference, and specs |
24
25
 
@@ -97,6 +98,47 @@ npm run typecheck
97
98
  - **Error registry** — 12 codes with category, retryability, and transport-specific status mappings
98
99
  - **Extension mechanism** — `_extensions` field for vendor metadata (`x-` prefix convention)
99
100
  - **Adoption tiers** — Core, Standard, Complete with progressive conformance requirements
101
+ - **A2A integration** — Agent Card discovery, extension negotiation, task lifecycle management, protocol bindings
102
+
103
+ ## A2A Integration
104
+
105
+ LAFS integrates with the [A2A Protocol](https://github.com/google/A2A) via `@a2a-js/sdk`. Import from the `@cleocode/lafs-protocol/a2a` subpath:
106
+
107
+ ```typescript
108
+ import {
109
+ // Extensions
110
+ buildLafsExtension,
111
+ extensionNegotiationMiddleware,
112
+ LAFS_EXTENSION_URI,
113
+
114
+ // Task lifecycle
115
+ TaskManager,
116
+ attachLafsEnvelope,
117
+ isTerminalState,
118
+
119
+ // Protocol bindings
120
+ getErrorCodeMapping,
121
+ createJsonRpcRequest,
122
+ createProblemDetails,
123
+ } from "@cleocode/lafs-protocol/a2a";
124
+ ```
125
+
126
+ **Agent Card with LAFS extension** — use `autoIncludeLafsExtension` in discovery config:
127
+
128
+ ```typescript
129
+ import { discoveryMiddleware } from "@cleocode/lafs-protocol/discovery";
130
+
131
+ app.use(discoveryMiddleware({
132
+ agent: { name: "my-agent", /* ... */ },
133
+ autoIncludeLafsExtension: true,
134
+ }));
135
+ ```
136
+
137
+ **Protocol bindings** are also available as a standalone subpath:
138
+
139
+ ```typescript
140
+ import { getErrorCodeMapping } from "@cleocode/lafs-protocol/a2a/bindings";
141
+ ```
100
142
 
101
143
  ## Conformance checks
102
144
 
@@ -125,9 +167,19 @@ src/
125
167
  conformance.ts # Conformance runner (8 checks)
126
168
  errorRegistry.ts # Error code helpers
127
169
  flagSemantics.ts # Format flag resolution
170
+ discovery.ts # A2A Agent Card discovery middleware
128
171
  cli.ts # CLI diagnostic tool
129
- tests/ # 31 tests (vitest)
130
- fixtures/ # 14 JSON test fixtures
172
+ a2a/
173
+ bridge.ts # A2A SDK integration & result wrapper
174
+ extensions.ts # Extension negotiation & LAFS extension builder
175
+ task-lifecycle.ts # Task state machine & lifecycle management
176
+ bindings/
177
+ jsonrpc.ts # JSON-RPC 2.0 method/error constants & builders
178
+ http.ts # HTTP endpoints, RFC 9457 Problem Details
179
+ grpc.ts # gRPC status codes & service definitions (types only)
180
+ index.ts # Barrel export & cross-binding error mapping
181
+ tests/ # Tests (vitest)
182
+ fixtures/ # JSON test fixtures
131
183
  docs/
132
184
  POSITIONING.md # MCP/A2A complementary positioning
133
185
  VISION.md # Project vision and primary persona
@@ -142,7 +194,8 @@ CONTRIBUTING.md # Contributor guidelines, RFC process
142
194
 
143
195
  | Version | Phase | Description |
144
196
  |---------|-------|-------------|
145
- | **v1.0.0** | **3** | **Production release: Token budgets, agent discovery, MCP integration, complete SDKs** |
197
+ | **v1.2.3** | **4** | **A2A v1.0+ compliance: extension negotiation, task lifecycle, protocol bindings (JSON-RPC/HTTP/gRPC)** |
198
+ | v1.0.0 | 3 | Production release: Token budgets, agent discovery, MCP integration, complete SDKs |
146
199
  | v0.5.0 | 2B | Conditional pagination, MVI field selection/expansion, context ledger schema |
147
200
  | v0.4.0 | 2A | Optional page/error, extensions, strict/lenient mode, warnings |
148
201
  | v0.3.0 | 1 | Strategic positioning, vision alignment, adoption tiers |
@@ -146,8 +146,8 @@ app.use(discoveryMiddleware(discoveryConfig));
146
146
  app.get("/health", (req, res) => {
147
147
  res.json({
148
148
  status: "healthy",
149
- service: discoveryConfig.service.name,
150
- version: discoveryConfig.service.version,
149
+ service: discoveryConfig.service?.name ?? discoveryConfig.agent?.name,
150
+ version: discoveryConfig.service?.version ?? discoveryConfig.agent?.version,
151
151
  timestamp: new Date().toISOString()
152
152
  });
153
153
  });
@@ -177,8 +177,8 @@ const server = app.listen(PORT, () => {
177
177
  ╔════════════════════════════════════════════════════════╗
178
178
  ║ LAFS Discovery Server Running ║
179
179
  ╠════════════════════════════════════════════════════════╣
180
- ║ Service: ${discoveryConfig.service.name.padEnd(43)}║
181
- ║ Version: ${discoveryConfig.service.version.padEnd(43)}║
180
+ ║ Service: ${(discoveryConfig.service?.name ?? discoveryConfig.agent?.name ?? 'unknown').padEnd(43)}║
181
+ ║ Version: ${(discoveryConfig.service?.version ?? discoveryConfig.agent?.version ?? 'unknown').padEnd(43)}║
182
182
  ║ Port: ${String(PORT).padEnd(43)}║
183
183
  ╠════════════════════════════════════════════════════════╣
184
184
  ║ Endpoints: ║
@@ -0,0 +1,67 @@
1
+ /**
2
+ * A2A gRPC Protocol Binding
3
+ *
4
+ * Status codes, error reasons, service method definitions, and metadata
5
+ * constants for gRPC transport. Types and helpers only — no @grpc/grpc-js
6
+ * runtime dependency.
7
+ *
8
+ * Reference: A2A spec Section 10.3-10.6
9
+ */
10
+ import type { A2AErrorType } from './jsonrpc.js';
11
+ /** Standard gRPC status codes (numeric values 0-16) */
12
+ export declare const GRPC_STATUS_CODE: {
13
+ readonly OK: 0;
14
+ readonly CANCELLED: 1;
15
+ readonly UNKNOWN: 2;
16
+ readonly INVALID_ARGUMENT: 3;
17
+ readonly DEADLINE_EXCEEDED: 4;
18
+ readonly NOT_FOUND: 5;
19
+ readonly ALREADY_EXISTS: 6;
20
+ readonly PERMISSION_DENIED: 7;
21
+ readonly RESOURCE_EXHAUSTED: 8;
22
+ readonly FAILED_PRECONDITION: 9;
23
+ readonly ABORTED: 10;
24
+ readonly OUT_OF_RANGE: 11;
25
+ readonly UNIMPLEMENTED: 12;
26
+ readonly INTERNAL: 13;
27
+ readonly UNAVAILABLE: 14;
28
+ readonly DATA_LOSS: 15;
29
+ readonly UNAUTHENTICATED: 16;
30
+ };
31
+ export type GrpcStatusCode = (typeof GRPC_STATUS_CODE)[keyof typeof GRPC_STATUS_CODE];
32
+ export type GrpcStatusName = keyof typeof GRPC_STATUS_CODE;
33
+ /** Maps A2A error types to gRPC status names */
34
+ export declare const A2A_GRPC_STATUS_CODES: Record<A2AErrorType, GrpcStatusName>;
35
+ /** UPPER_SNAKE_CASE error reasons without "Error" suffix */
36
+ export declare const A2A_GRPC_ERROR_REASONS: Record<A2AErrorType, string>;
37
+ /** Error domain for A2A gRPC errors */
38
+ export declare const A2A_GRPC_ERROR_DOMAIN: "a2a-protocol.org";
39
+ /** gRPC service method descriptor */
40
+ export interface GrpcServiceMethod {
41
+ request: string;
42
+ response: string;
43
+ streaming: boolean;
44
+ }
45
+ /** gRPC service method definitions for the A2A protocol */
46
+ export declare const GRPC_SERVICE_METHODS: Record<string, GrpcServiceMethod>;
47
+ /** gRPC metadata key for A2A protocol version */
48
+ export declare const GRPC_METADATA_VERSION_KEY: "a2a-version";
49
+ /** gRPC metadata key for activated A2A extensions */
50
+ export declare const GRPC_METADATA_EXTENSIONS_KEY: "a2a-extensions";
51
+ /** gRPC Status object for A2A errors */
52
+ export interface GrpcStatus {
53
+ code: GrpcStatusCode;
54
+ message: string;
55
+ details?: GrpcErrorInfo[];
56
+ }
57
+ /** google.rpc.ErrorInfo equivalent */
58
+ export interface GrpcErrorInfo {
59
+ reason: string;
60
+ domain: string;
61
+ metadata?: Record<string, string>;
62
+ }
63
+ /**
64
+ * Create a gRPC Status object for an A2A error type.
65
+ * Includes ErrorInfo details with reason and domain.
66
+ */
67
+ export declare function createGrpcStatus(errorType: A2AErrorType, message: string, metadata?: Record<string, string>): GrpcStatus;
@@ -0,0 +1,148 @@
1
+ /**
2
+ * A2A gRPC Protocol Binding
3
+ *
4
+ * Status codes, error reasons, service method definitions, and metadata
5
+ * constants for gRPC transport. Types and helpers only — no @grpc/grpc-js
6
+ * runtime dependency.
7
+ *
8
+ * Reference: A2A spec Section 10.3-10.6
9
+ */
10
+ // ============================================================================
11
+ // gRPC Status Codes (standard)
12
+ // ============================================================================
13
+ /** Standard gRPC status codes (numeric values 0-16) */
14
+ export const GRPC_STATUS_CODE = {
15
+ OK: 0,
16
+ CANCELLED: 1,
17
+ UNKNOWN: 2,
18
+ INVALID_ARGUMENT: 3,
19
+ DEADLINE_EXCEEDED: 4,
20
+ NOT_FOUND: 5,
21
+ ALREADY_EXISTS: 6,
22
+ PERMISSION_DENIED: 7,
23
+ RESOURCE_EXHAUSTED: 8,
24
+ FAILED_PRECONDITION: 9,
25
+ ABORTED: 10,
26
+ OUT_OF_RANGE: 11,
27
+ UNIMPLEMENTED: 12,
28
+ INTERNAL: 13,
29
+ UNAVAILABLE: 14,
30
+ DATA_LOSS: 15,
31
+ UNAUTHENTICATED: 16,
32
+ };
33
+ // ============================================================================
34
+ // A2A gRPC Status Mapping (spec Section 5.4)
35
+ // ============================================================================
36
+ /** Maps A2A error types to gRPC status names */
37
+ export const A2A_GRPC_STATUS_CODES = {
38
+ TaskNotFound: 'NOT_FOUND',
39
+ TaskNotCancelable: 'FAILED_PRECONDITION',
40
+ PushNotificationNotSupported: 'UNIMPLEMENTED',
41
+ UnsupportedOperation: 'UNIMPLEMENTED',
42
+ ContentTypeNotSupported: 'INVALID_ARGUMENT',
43
+ InvalidAgentResponse: 'INTERNAL',
44
+ AuthenticatedExtendedCardNotConfigured: 'NOT_FOUND',
45
+ ExtensionSupportRequired: 'FAILED_PRECONDITION',
46
+ VersionNotSupported: 'FAILED_PRECONDITION',
47
+ };
48
+ // ============================================================================
49
+ // Error Reasons (spec Section 10.6)
50
+ // ============================================================================
51
+ /** UPPER_SNAKE_CASE error reasons without "Error" suffix */
52
+ export const A2A_GRPC_ERROR_REASONS = {
53
+ TaskNotFound: 'TASK_NOT_FOUND',
54
+ TaskNotCancelable: 'TASK_NOT_CANCELABLE',
55
+ PushNotificationNotSupported: 'PUSH_NOTIFICATION_NOT_SUPPORTED',
56
+ UnsupportedOperation: 'UNSUPPORTED_OPERATION',
57
+ ContentTypeNotSupported: 'CONTENT_TYPE_NOT_SUPPORTED',
58
+ InvalidAgentResponse: 'INVALID_AGENT_RESPONSE',
59
+ AuthenticatedExtendedCardNotConfigured: 'AUTHENTICATED_EXTENDED_CARD_NOT_CONFIGURED',
60
+ ExtensionSupportRequired: 'EXTENSION_SUPPORT_REQUIRED',
61
+ VersionNotSupported: 'VERSION_NOT_SUPPORTED',
62
+ };
63
+ /** Error domain for A2A gRPC errors */
64
+ export const A2A_GRPC_ERROR_DOMAIN = 'a2a-protocol.org';
65
+ /** gRPC service method definitions for the A2A protocol */
66
+ export const GRPC_SERVICE_METHODS = {
67
+ SendMessage: {
68
+ request: 'MessageSendParams',
69
+ response: 'SendMessageResponse',
70
+ streaming: false,
71
+ },
72
+ SendStreamingMessage: {
73
+ request: 'MessageSendParams',
74
+ response: 'SendStreamingMessageResponse',
75
+ streaming: true,
76
+ },
77
+ GetTask: {
78
+ request: 'TaskQueryParams',
79
+ response: 'GetTaskResponse',
80
+ streaming: false,
81
+ },
82
+ ListTasks: {
83
+ request: 'TaskQueryParams',
84
+ response: 'ListTasksResponse',
85
+ streaming: false,
86
+ },
87
+ CancelTask: {
88
+ request: 'TaskIdParams',
89
+ response: 'CancelTaskResponse',
90
+ streaming: false,
91
+ },
92
+ SubscribeToTask: {
93
+ request: 'TaskIdParams',
94
+ response: 'SubscribeToTaskResponse',
95
+ streaming: true,
96
+ },
97
+ SetTaskPushNotificationConfig: {
98
+ request: 'TaskPushNotificationConfig',
99
+ response: 'SetTaskPushNotificationConfigResponse',
100
+ streaming: false,
101
+ },
102
+ GetTaskPushNotificationConfig: {
103
+ request: 'GetTaskPushNotificationConfigParams',
104
+ response: 'GetTaskPushNotificationConfigResponse',
105
+ streaming: false,
106
+ },
107
+ ListTaskPushNotificationConfig: {
108
+ request: 'ListTaskPushNotificationConfigParams',
109
+ response: 'ListTaskPushNotificationConfigResponse',
110
+ streaming: false,
111
+ },
112
+ DeleteTaskPushNotificationConfig: {
113
+ request: 'DeleteTaskPushNotificationConfigParams',
114
+ response: 'DeleteTaskPushNotificationConfigResponse',
115
+ streaming: false,
116
+ },
117
+ GetExtendedAgentCard: {
118
+ request: 'GetAuthenticatedExtendedCardRequest',
119
+ response: 'GetAuthenticatedExtendedCardResponse',
120
+ streaming: false,
121
+ },
122
+ };
123
+ // ============================================================================
124
+ // gRPC Metadata Constants
125
+ // ============================================================================
126
+ /** gRPC metadata key for A2A protocol version */
127
+ export const GRPC_METADATA_VERSION_KEY = 'a2a-version';
128
+ /** gRPC metadata key for activated A2A extensions */
129
+ export const GRPC_METADATA_EXTENSIONS_KEY = 'a2a-extensions';
130
+ /**
131
+ * Create a gRPC Status object for an A2A error type.
132
+ * Includes ErrorInfo details with reason and domain.
133
+ */
134
+ export function createGrpcStatus(errorType, message, metadata) {
135
+ const statusName = A2A_GRPC_STATUS_CODES[errorType];
136
+ const code = GRPC_STATUS_CODE[statusName];
137
+ return {
138
+ code,
139
+ message,
140
+ details: [
141
+ {
142
+ reason: A2A_GRPC_ERROR_REASONS[errorType],
143
+ domain: A2A_GRPC_ERROR_DOMAIN,
144
+ ...(metadata && { metadata }),
145
+ },
146
+ ],
147
+ };
148
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * A2A HTTP Protocol Binding
3
+ *
4
+ * HTTP endpoint definitions, status codes, error type URIs,
5
+ * and RFC 9457 Problem Details support per A2A spec Section 11.3-11.5.
6
+ */
7
+ import type { A2AErrorType } from './jsonrpc.js';
8
+ /** HTTP+JSON endpoint definitions for each A2A operation */
9
+ export declare const HTTP_ENDPOINTS: {
10
+ readonly SendMessage: {
11
+ readonly method: "POST";
12
+ readonly path: "/message:send";
13
+ };
14
+ readonly SendStreamingMessage: {
15
+ readonly method: "POST";
16
+ readonly path: "/message:stream";
17
+ };
18
+ readonly GetTask: {
19
+ readonly method: "GET";
20
+ readonly path: "/tasks/:id";
21
+ };
22
+ readonly ListTasks: {
23
+ readonly method: "GET";
24
+ readonly path: "/tasks";
25
+ };
26
+ readonly CancelTask: {
27
+ readonly method: "POST";
28
+ readonly path: "/tasks/:id:cancel";
29
+ };
30
+ readonly SubscribeToTask: {
31
+ readonly method: "GET";
32
+ readonly path: "/tasks/:id:subscribe";
33
+ };
34
+ readonly SetTaskPushNotificationConfig: {
35
+ readonly method: "POST";
36
+ readonly path: "/tasks/:id/pushNotificationConfig";
37
+ };
38
+ readonly GetTaskPushNotificationConfig: {
39
+ readonly method: "GET";
40
+ readonly path: "/tasks/:id/pushNotificationConfig";
41
+ };
42
+ readonly ListTaskPushNotificationConfig: {
43
+ readonly method: "GET";
44
+ readonly path: "/tasks/:id/pushNotificationConfig:list";
45
+ };
46
+ readonly DeleteTaskPushNotificationConfig: {
47
+ readonly method: "DELETE";
48
+ readonly path: "/tasks/:id/pushNotificationConfig/:configId";
49
+ };
50
+ readonly GetExtendedAgentCard: {
51
+ readonly method: "GET";
52
+ readonly path: "/agent/authenticatedExtendedCard";
53
+ };
54
+ };
55
+ export type HttpEndpoint = (typeof HTTP_ENDPOINTS)[keyof typeof HTTP_ENDPOINTS];
56
+ /** Maps A2A error types to HTTP status codes */
57
+ export declare const A2A_HTTP_STATUS_CODES: Record<A2AErrorType, number>;
58
+ /** RFC 9457 Problem Details type URIs for A2A errors */
59
+ export declare const A2A_ERROR_TYPE_URIS: Record<A2AErrorType, string>;
60
+ /** RFC 9457 Problem Details object */
61
+ export interface ProblemDetails {
62
+ type: string;
63
+ title: string;
64
+ status: number;
65
+ detail: string;
66
+ [key: string]: unknown;
67
+ }
68
+ /**
69
+ * Create an RFC 9457 Problem Details object for an A2A error.
70
+ * @param errorType - The A2A error type name
71
+ * @param detail - Human-readable explanation of the error
72
+ * @param extensions - Additional members to include in the response
73
+ */
74
+ export declare function createProblemDetails(errorType: A2AErrorType, detail: string, extensions?: Record<string, unknown>): ProblemDetails;
75
+ /**
76
+ * Build a URL by substituting path parameters.
77
+ * @param endpoint - HTTP endpoint definition (from HTTP_ENDPOINTS)
78
+ * @param params - Path parameter values (keys without leading colon)
79
+ */
80
+ export declare function buildUrl(endpoint: HttpEndpoint, params?: Record<string, string>): string;
81
+ /** Parsed query parameters for ListTasks (spec Section 11.5) */
82
+ export interface ListTasksQueryParams {
83
+ contextId?: string;
84
+ state?: string;
85
+ limit?: number;
86
+ pageToken?: string;
87
+ }
88
+ /**
89
+ * Parse camelCase query parameters for the ListTasks endpoint.
90
+ * Handles type coercion for numeric fields.
91
+ */
92
+ export declare function parseListTasksQuery(query: Record<string, string | undefined>): ListTasksQueryParams;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * A2A HTTP Protocol Binding
3
+ *
4
+ * HTTP endpoint definitions, status codes, error type URIs,
5
+ * and RFC 9457 Problem Details support per A2A spec Section 11.3-11.5.
6
+ */
7
+ // ============================================================================
8
+ // Endpoint Constants (spec Section 11.3)
9
+ // ============================================================================
10
+ /** HTTP+JSON endpoint definitions for each A2A operation */
11
+ export const HTTP_ENDPOINTS = {
12
+ SendMessage: { method: 'POST', path: '/message:send' },
13
+ SendStreamingMessage: { method: 'POST', path: '/message:stream' },
14
+ GetTask: { method: 'GET', path: '/tasks/:id' },
15
+ ListTasks: { method: 'GET', path: '/tasks' },
16
+ CancelTask: { method: 'POST', path: '/tasks/:id:cancel' },
17
+ SubscribeToTask: { method: 'GET', path: '/tasks/:id:subscribe' },
18
+ SetTaskPushNotificationConfig: { method: 'POST', path: '/tasks/:id/pushNotificationConfig' },
19
+ GetTaskPushNotificationConfig: { method: 'GET', path: '/tasks/:id/pushNotificationConfig' },
20
+ ListTaskPushNotificationConfig: { method: 'GET', path: '/tasks/:id/pushNotificationConfig:list' },
21
+ DeleteTaskPushNotificationConfig: { method: 'DELETE', path: '/tasks/:id/pushNotificationConfig/:configId' },
22
+ GetExtendedAgentCard: { method: 'GET', path: '/agent/authenticatedExtendedCard' },
23
+ };
24
+ // ============================================================================
25
+ // HTTP Status Codes (spec Section 5.4)
26
+ // ============================================================================
27
+ /** Maps A2A error types to HTTP status codes */
28
+ export const A2A_HTTP_STATUS_CODES = {
29
+ TaskNotFound: 404,
30
+ TaskNotCancelable: 409,
31
+ PushNotificationNotSupported: 400,
32
+ UnsupportedOperation: 400,
33
+ ContentTypeNotSupported: 415,
34
+ InvalidAgentResponse: 502,
35
+ AuthenticatedExtendedCardNotConfigured: 404,
36
+ ExtensionSupportRequired: 400,
37
+ VersionNotSupported: 400,
38
+ };
39
+ // ============================================================================
40
+ // Error Type URIs (spec Section 5.4)
41
+ // ============================================================================
42
+ /** RFC 9457 Problem Details type URIs for A2A errors */
43
+ export const A2A_ERROR_TYPE_URIS = {
44
+ TaskNotFound: 'https://a2a-protocol.org/errors/task-not-found',
45
+ TaskNotCancelable: 'https://a2a-protocol.org/errors/task-not-cancelable',
46
+ PushNotificationNotSupported: 'https://a2a-protocol.org/errors/push-notification-not-supported',
47
+ UnsupportedOperation: 'https://a2a-protocol.org/errors/unsupported-operation',
48
+ ContentTypeNotSupported: 'https://a2a-protocol.org/errors/content-type-not-supported',
49
+ InvalidAgentResponse: 'https://a2a-protocol.org/errors/invalid-agent-response',
50
+ AuthenticatedExtendedCardNotConfigured: 'https://a2a-protocol.org/errors/authenticated-extended-card-not-configured',
51
+ ExtensionSupportRequired: 'https://a2a-protocol.org/errors/extension-support-required',
52
+ VersionNotSupported: 'https://a2a-protocol.org/errors/version-not-supported',
53
+ };
54
+ /**
55
+ * Create an RFC 9457 Problem Details object for an A2A error.
56
+ * @param errorType - The A2A error type name
57
+ * @param detail - Human-readable explanation of the error
58
+ * @param extensions - Additional members to include in the response
59
+ */
60
+ export function createProblemDetails(errorType, detail, extensions) {
61
+ // Convert PascalCase to Title Case: "TaskNotFound" -> "Task Not Found"
62
+ const title = errorType.replace(/([A-Z])/g, ' $1').trim();
63
+ return {
64
+ type: A2A_ERROR_TYPE_URIS[errorType],
65
+ title,
66
+ status: A2A_HTTP_STATUS_CODES[errorType],
67
+ detail,
68
+ ...extensions,
69
+ };
70
+ }
71
+ // ============================================================================
72
+ // URL Building
73
+ // ============================================================================
74
+ /**
75
+ * Build a URL by substituting path parameters.
76
+ * @param endpoint - HTTP endpoint definition (from HTTP_ENDPOINTS)
77
+ * @param params - Path parameter values (keys without leading colon)
78
+ */
79
+ export function buildUrl(endpoint, params) {
80
+ let path = endpoint.path;
81
+ if (params) {
82
+ for (const [key, value] of Object.entries(params)) {
83
+ path = path.replace(`:${key}`, encodeURIComponent(value));
84
+ }
85
+ }
86
+ return path;
87
+ }
88
+ /**
89
+ * Parse camelCase query parameters for the ListTasks endpoint.
90
+ * Handles type coercion for numeric fields.
91
+ */
92
+ export function parseListTasksQuery(query) {
93
+ return {
94
+ contextId: query['contextId'],
95
+ state: query['state'],
96
+ limit: query['limit'] ? parseInt(query['limit'], 10) : undefined,
97
+ pageToken: query['pageToken'],
98
+ };
99
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * A2A Protocol Bindings - Barrel Export
3
+ *
4
+ * Re-exports all binding modules and provides cross-binding
5
+ * error code mapping for consistent error handling across transports.
6
+ */
7
+ export * from './jsonrpc.js';
8
+ export * from './http.js';
9
+ export * from './grpc.js';
10
+ import { type A2AErrorType } from './jsonrpc.js';
11
+ /** Complete error code mapping across all three transports */
12
+ export interface ErrorCodeMapping {
13
+ /** JSON-RPC numeric error code */
14
+ jsonRpcCode: number;
15
+ /** HTTP response status code */
16
+ httpStatus: number;
17
+ /** RFC 9457 Problem Details type URI */
18
+ httpTypeUri: string;
19
+ /** gRPC status name (e.g. NOT_FOUND) */
20
+ grpcStatus: string;
21
+ /** gRPC numeric status code */
22
+ grpcCode: number;
23
+ }
24
+ /** Precomputed cross-binding error mapping for all 9 A2A error types */
25
+ export declare const A2A_ERROR_MAPPINGS: ReadonlyMap<A2AErrorType, ErrorCodeMapping>;
26
+ /**
27
+ * Get the complete error code mapping for a given A2A error type.
28
+ * Returns consistent values across JSON-RPC, HTTP, and gRPC.
29
+ */
30
+ export declare function getErrorCodeMapping(errorType: A2AErrorType): ErrorCodeMapping;
31
+ export { A2A_GRPC_ERROR_REASONS } from './grpc.js';
@@ -0,0 +1,54 @@
1
+ /**
2
+ * A2A Protocol Bindings - Barrel Export
3
+ *
4
+ * Re-exports all binding modules and provides cross-binding
5
+ * error code mapping for consistent error handling across transports.
6
+ */
7
+ export * from './jsonrpc.js';
8
+ export * from './http.js';
9
+ export * from './grpc.js';
10
+ import { JSONRPC_A2A_ERROR_CODES } from './jsonrpc.js';
11
+ import { A2A_HTTP_STATUS_CODES, A2A_ERROR_TYPE_URIS } from './http.js';
12
+ import { A2A_GRPC_STATUS_CODES, GRPC_STATUS_CODE } from './grpc.js';
13
+ /** All 9 A2A error types */
14
+ const ERROR_TYPES = [
15
+ 'TaskNotFound',
16
+ 'TaskNotCancelable',
17
+ 'PushNotificationNotSupported',
18
+ 'UnsupportedOperation',
19
+ 'ContentTypeNotSupported',
20
+ 'InvalidAgentResponse',
21
+ 'AuthenticatedExtendedCardNotConfigured',
22
+ 'ExtensionSupportRequired',
23
+ 'VersionNotSupported',
24
+ ];
25
+ function buildMappings() {
26
+ const map = new Map();
27
+ for (const errorType of ERROR_TYPES) {
28
+ const grpcStatusName = A2A_GRPC_STATUS_CODES[errorType];
29
+ map.set(errorType, {
30
+ jsonRpcCode: JSONRPC_A2A_ERROR_CODES[errorType],
31
+ httpStatus: A2A_HTTP_STATUS_CODES[errorType],
32
+ httpTypeUri: A2A_ERROR_TYPE_URIS[errorType],
33
+ grpcStatus: grpcStatusName,
34
+ grpcCode: GRPC_STATUS_CODE[grpcStatusName],
35
+ });
36
+ }
37
+ return map;
38
+ }
39
+ /** Precomputed cross-binding error mapping for all 9 A2A error types */
40
+ export const A2A_ERROR_MAPPINGS = buildMappings();
41
+ /**
42
+ * Get the complete error code mapping for a given A2A error type.
43
+ * Returns consistent values across JSON-RPC, HTTP, and gRPC.
44
+ */
45
+ export function getErrorCodeMapping(errorType) {
46
+ const mapping = A2A_ERROR_MAPPINGS.get(errorType);
47
+ if (!mapping) {
48
+ throw new Error(`Unknown A2A error type: ${errorType}`);
49
+ }
50
+ return mapping;
51
+ }
52
+ // Also export A2A_GRPC_ERROR_REASONS for convenience (re-exported from grpc.ts via *)
53
+ // but explicitly reference it here so the cross-binding module is self-documenting
54
+ export { A2A_GRPC_ERROR_REASONS } from './grpc.js';