@cleocode/lafs-protocol 1.2.2 → 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 +58 -5
- package/dist/examples/discovery-server.js +4 -4
- package/dist/src/a2a/bindings/grpc.d.ts +67 -0
- package/dist/src/a2a/bindings/grpc.js +148 -0
- package/dist/src/a2a/bindings/http.d.ts +92 -0
- package/dist/src/a2a/bindings/http.js +99 -0
- package/dist/src/a2a/bindings/index.d.ts +31 -0
- package/dist/src/a2a/bindings/index.js +54 -0
- package/dist/src/a2a/bindings/jsonrpc.d.ts +77 -0
- package/dist/src/a2a/bindings/jsonrpc.js +114 -0
- package/dist/src/a2a/bridge.d.ts +121 -76
- package/dist/src/a2a/bridge.js +185 -89
- package/dist/src/a2a/extensions.d.ts +93 -0
- package/dist/src/a2a/extensions.js +147 -0
- package/dist/src/a2a/index.d.ts +27 -25
- package/dist/src/a2a/index.js +59 -25
- package/dist/src/a2a/task-lifecycle.d.ts +98 -0
- package/dist/src/a2a/task-lifecycle.js +263 -0
- package/dist/src/discovery.d.ts +203 -44
- package/dist/src/discovery.js +204 -166
- package/dist/src/index.d.ts +3 -1
- package/dist/src/index.js +10 -1
- package/lafs.md +1 -1
- package/package.json +14 -1
- package/schemas/v1/agent-card.schema.json +230 -0
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.
|
|
7
|
+
**Current version:** 1.3.1 | [📚 Documentation](https://codluv.gitbook.io/lafs-protocol/) | [Spec](lafs.md) | [Migration Guides](migrations/)
|
|
8
8
|
|
|
9
9
|
[](https://codluv.gitbook.io/lafs-protocol/)
|
|
10
10
|
[](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
|
-
| **
|
|
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
|
-
|
|
130
|
-
|
|
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.
|
|
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';
|