@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.
@@ -0,0 +1,77 @@
1
+ /**
2
+ * A2A JSON-RPC Protocol Binding
3
+ *
4
+ * Method constants, error codes, and request/response builders
5
+ * for JSON-RPC 2.0 transport per A2A spec Section 5.3-5.4.
6
+ */
7
+ /** All JSON-RPC method names defined by the A2A protocol */
8
+ export declare const JSONRPC_METHODS: {
9
+ readonly SendMessage: "message/send";
10
+ readonly SendStreamingMessage: "message/stream";
11
+ readonly GetTask: "tasks/get";
12
+ readonly ListTasks: "tasks/list";
13
+ readonly CancelTask: "tasks/cancel";
14
+ readonly SubscribeToTask: "tasks/resubscribe";
15
+ readonly SetTaskPushNotificationConfig: "tasks/pushNotificationConfig/set";
16
+ readonly GetTaskPushNotificationConfig: "tasks/pushNotificationConfig/get";
17
+ readonly ListTaskPushNotificationConfig: "tasks/pushNotificationConfig/list";
18
+ readonly DeleteTaskPushNotificationConfig: "tasks/pushNotificationConfig/delete";
19
+ readonly GetExtendedAgentCard: "agent/getAuthenticatedExtendedCard";
20
+ };
21
+ export type JsonRpcMethod = (typeof JSONRPC_METHODS)[keyof typeof JSONRPC_METHODS];
22
+ /** Standard JSON-RPC 2.0 error codes */
23
+ export declare const JSONRPC_STANDARD_ERROR_CODES: {
24
+ readonly ParseError: -32700;
25
+ readonly InvalidRequest: -32600;
26
+ readonly MethodNotFound: -32601;
27
+ readonly InvalidParams: -32602;
28
+ readonly InternalError: -32603;
29
+ };
30
+ /** A2A-specific error codes (-32001 through -32009) */
31
+ export declare const JSONRPC_A2A_ERROR_CODES: {
32
+ readonly TaskNotFound: -32001;
33
+ readonly TaskNotCancelable: -32002;
34
+ readonly PushNotificationNotSupported: -32003;
35
+ readonly UnsupportedOperation: -32004;
36
+ readonly ContentTypeNotSupported: -32005;
37
+ readonly InvalidAgentResponse: -32006;
38
+ readonly AuthenticatedExtendedCardNotConfigured: -32007;
39
+ readonly ExtensionSupportRequired: -32008;
40
+ readonly VersionNotSupported: -32009;
41
+ };
42
+ export type A2AErrorType = keyof typeof JSONRPC_A2A_ERROR_CODES;
43
+ export interface JsonRpcRequest {
44
+ jsonrpc: '2.0';
45
+ id: string | number;
46
+ method: string;
47
+ params?: Record<string, unknown>;
48
+ }
49
+ export interface JsonRpcResponse {
50
+ jsonrpc: '2.0';
51
+ id: string | number | null;
52
+ result: unknown;
53
+ }
54
+ export interface JsonRpcErrorResponse {
55
+ jsonrpc: '2.0';
56
+ id: string | number | null;
57
+ error: {
58
+ code: number;
59
+ message: string;
60
+ data?: Record<string, unknown>;
61
+ };
62
+ }
63
+ /** Create a JSON-RPC 2.0 request object */
64
+ export declare function createJsonRpcRequest(id: string | number, method: string, params?: Record<string, unknown>): JsonRpcRequest;
65
+ /** Create a JSON-RPC 2.0 success response */
66
+ export declare function createJsonRpcResponse(id: string | number | null, result: unknown): JsonRpcResponse;
67
+ /** Create a JSON-RPC 2.0 error response */
68
+ export declare function createJsonRpcErrorResponse(id: string | number | null, code: number, message: string, data?: Record<string, unknown>): JsonRpcErrorResponse;
69
+ /** Create an A2A-specific JSON-RPC error response by error type name */
70
+ export declare function createA2AErrorResponse(id: string | number | null, errorType: A2AErrorType, message: string, data?: Record<string, unknown>): JsonRpcErrorResponse;
71
+ /** Validate the structure of a JSON-RPC request */
72
+ export declare function validateJsonRpcRequest(input: unknown): {
73
+ valid: boolean;
74
+ errors: string[];
75
+ };
76
+ /** Check if a numeric error code is an A2A-specific error */
77
+ export declare function isA2AError(code: number): boolean;
@@ -0,0 +1,114 @@
1
+ /**
2
+ * A2A JSON-RPC Protocol Binding
3
+ *
4
+ * Method constants, error codes, and request/response builders
5
+ * for JSON-RPC 2.0 transport per A2A spec Section 5.3-5.4.
6
+ */
7
+ // ============================================================================
8
+ // Method Constants (spec Section 5.3)
9
+ // ============================================================================
10
+ /** All JSON-RPC method names defined by the A2A protocol */
11
+ export const JSONRPC_METHODS = {
12
+ SendMessage: 'message/send',
13
+ SendStreamingMessage: 'message/stream',
14
+ GetTask: 'tasks/get',
15
+ ListTasks: 'tasks/list',
16
+ CancelTask: 'tasks/cancel',
17
+ SubscribeToTask: 'tasks/resubscribe',
18
+ SetTaskPushNotificationConfig: 'tasks/pushNotificationConfig/set',
19
+ GetTaskPushNotificationConfig: 'tasks/pushNotificationConfig/get',
20
+ ListTaskPushNotificationConfig: 'tasks/pushNotificationConfig/list',
21
+ DeleteTaskPushNotificationConfig: 'tasks/pushNotificationConfig/delete',
22
+ GetExtendedAgentCard: 'agent/getAuthenticatedExtendedCard',
23
+ };
24
+ // ============================================================================
25
+ // Error Code Constants (spec Section 5.4)
26
+ // ============================================================================
27
+ /** Standard JSON-RPC 2.0 error codes */
28
+ export const JSONRPC_STANDARD_ERROR_CODES = {
29
+ ParseError: -32700,
30
+ InvalidRequest: -32600,
31
+ MethodNotFound: -32601,
32
+ InvalidParams: -32602,
33
+ InternalError: -32603,
34
+ };
35
+ /** A2A-specific error codes (-32001 through -32009) */
36
+ export const JSONRPC_A2A_ERROR_CODES = {
37
+ TaskNotFound: -32001,
38
+ TaskNotCancelable: -32002,
39
+ PushNotificationNotSupported: -32003,
40
+ UnsupportedOperation: -32004,
41
+ ContentTypeNotSupported: -32005,
42
+ InvalidAgentResponse: -32006,
43
+ AuthenticatedExtendedCardNotConfigured: -32007,
44
+ ExtensionSupportRequired: -32008,
45
+ VersionNotSupported: -32009,
46
+ };
47
+ // ============================================================================
48
+ // Builders
49
+ // ============================================================================
50
+ /** Create a JSON-RPC 2.0 request object */
51
+ export function createJsonRpcRequest(id, method, params) {
52
+ return {
53
+ jsonrpc: '2.0',
54
+ id,
55
+ method,
56
+ ...(params !== undefined && { params }),
57
+ };
58
+ }
59
+ /** Create a JSON-RPC 2.0 success response */
60
+ export function createJsonRpcResponse(id, result) {
61
+ return {
62
+ jsonrpc: '2.0',
63
+ id,
64
+ result,
65
+ };
66
+ }
67
+ /** Create a JSON-RPC 2.0 error response */
68
+ export function createJsonRpcErrorResponse(id, code, message, data) {
69
+ return {
70
+ jsonrpc: '2.0',
71
+ id,
72
+ error: {
73
+ code,
74
+ message,
75
+ ...(data !== undefined && { data }),
76
+ },
77
+ };
78
+ }
79
+ /** Create an A2A-specific JSON-RPC error response by error type name */
80
+ export function createA2AErrorResponse(id, errorType, message, data) {
81
+ return createJsonRpcErrorResponse(id, JSONRPC_A2A_ERROR_CODES[errorType], message, data);
82
+ }
83
+ // ============================================================================
84
+ // Validation
85
+ // ============================================================================
86
+ const knownMethods = new Set(Object.values(JSONRPC_METHODS));
87
+ /** Validate the structure of a JSON-RPC request */
88
+ export function validateJsonRpcRequest(input) {
89
+ const errors = [];
90
+ if (typeof input !== 'object' || input === null) {
91
+ return { valid: false, errors: ['Input must be an object'] };
92
+ }
93
+ const obj = input;
94
+ if (obj['jsonrpc'] !== '2.0') {
95
+ errors.push('jsonrpc must be "2.0"');
96
+ }
97
+ if (obj['id'] === undefined || (typeof obj['id'] !== 'string' && typeof obj['id'] !== 'number')) {
98
+ errors.push('id must be a string or number');
99
+ }
100
+ if (typeof obj['method'] !== 'string') {
101
+ errors.push('method must be a string');
102
+ }
103
+ else if (!knownMethods.has(obj['method'])) {
104
+ errors.push(`Unknown method: ${obj['method']}`);
105
+ }
106
+ if (obj['params'] !== undefined && (typeof obj['params'] !== 'object' || obj['params'] === null)) {
107
+ errors.push('params must be an object when provided');
108
+ }
109
+ return { valid: errors.length === 0, errors };
110
+ }
111
+ /** Check if a numeric error code is an A2A-specific error */
112
+ export function isA2AError(code) {
113
+ return code >= -32009 && code <= -32001;
114
+ }
@@ -1,90 +1,66 @@
1
1
  /**
2
- * LAFS A2A Bridge
2
+ * LAFS A2A Bridge v2.0
3
3
  *
4
- * Integration with official @a2a-js/sdk for Agent-to-Agent communication.
5
- * LAFS provides envelope wrapping and token budget support.
4
+ * Full integration with official @a2a-js/sdk for Agent-to-Agent communication.
5
+ * Implements A2A Protocol v1.0+ specification.
6
+ *
7
+ * Reference: specs/external/specification.md
8
+ */
9
+ import type { Task, TaskState, TaskStatus, Artifact, Part, Message, AgentCard, MessageSendConfiguration, SendMessageResponse, SendMessageSuccessResponse, JSONRPCErrorResponse, AGENT_CARD_PATH, HTTP_EXTENSION_HEADER } from '@a2a-js/sdk';
10
+ import type { LAFSEnvelope } from '../types.js';
11
+ /**
12
+ * Configuration for LAFS A2A integration
6
13
  */
7
- import { A2AClient } from '@a2a-js/sdk/client';
8
- import { Artifact, Part, SendMessageResponse, JSONRPCErrorResponse } from '@a2a-js/sdk';
9
14
  export interface LafsA2AConfig {
15
+ /** Default token budget for all operations */
10
16
  defaultBudget?: {
11
17
  maxTokens?: number;
12
18
  maxItems?: number;
19
+ maxBytes?: number;
13
20
  };
21
+ /** Whether to automatically wrap responses in LAFS envelopes */
14
22
  envelopeResponses?: boolean;
23
+ /** A2A protocol version to use (default: "1.0") */
24
+ protocolVersion?: string;
25
+ /** Extension URIs to activate for all requests */
26
+ defaultExtensions?: string[];
15
27
  }
16
- export interface LafsEnvelope {
17
- $schema: string;
18
- _meta: {
19
- specVersion: string;
20
- operation: string;
21
- requestId: string;
22
- mvi: string;
23
- _tokenEstimate?: {
24
- estimated: number;
25
- budget?: number;
26
- };
28
+ /**
29
+ * Request parameters for sending messages
30
+ */
31
+ export interface LafsSendMessageParams {
32
+ /** Message content */
33
+ message: {
34
+ role: 'user' | 'agent';
35
+ parts: Part[];
36
+ /** Optional message metadata */
37
+ metadata?: Record<string, unknown>;
27
38
  };
28
- success: boolean;
29
- result: unknown;
30
- error: null | {
31
- code: string;
32
- message: string;
33
- category: string;
34
- retryable: boolean;
39
+ /** A2A configuration for this request */
40
+ configuration?: MessageSendConfiguration;
41
+ /** Token budget override */
42
+ budget?: {
43
+ maxTokens?: number;
44
+ maxItems?: number;
45
+ maxBytes?: number;
35
46
  };
47
+ /** Extensions to activate for this request */
48
+ extensions?: string[];
49
+ /** Context ID for multi-turn conversations */
50
+ contextId?: string;
51
+ /** Task ID for continuing existing task */
52
+ taskId?: string;
36
53
  }
37
54
  /**
38
- * Wrap A2A client with LAFS envelope support
39
- *
40
- * @example
41
- * ```typescript
42
- * import { ClientFactory } from '@a2a-js/sdk/client';
43
- * import { withLafsEnvelope } from '@lafs/envelope/a2a';
44
- *
45
- * const factory = new ClientFactory();
46
- * const a2aClient = await factory.createFromUrl('http://localhost:4000');
47
- *
48
- * const client = withLafsEnvelope(a2aClient, {
49
- * envelopeResponses: true,
50
- * defaultBudget: { maxTokens: 4000 }
51
- * });
52
- *
53
- * const result = await client.sendMessage({
54
- * message: { role: 'user', parts: [{ text: 'Hello' }] }
55
- * });
56
- *
57
- * // Access LAFS envelope
58
- * const envelope = result.getLafsEnvelope();
59
- * console.log(envelope._meta._tokenEstimate);
60
- * ```
55
+ * Wrapper for A2A responses with LAFS envelope support
61
56
  */
62
- export declare function withLafsEnvelope(client: A2AClient, config?: LafsA2AConfig): LafsA2AClient;
63
- export declare class LafsA2AClient {
64
- private client;
65
- private config;
66
- constructor(client: A2AClient, config: LafsA2AConfig);
67
- sendMessage(params: {
68
- message: {
69
- role: 'user' | 'agent';
70
- parts: Part[];
71
- };
72
- budget?: {
73
- maxTokens?: number;
74
- maxItems?: number;
75
- };
76
- }): Promise<LafsA2AResult>;
77
- private generateId;
78
- }
79
57
  export declare class LafsA2AResult {
80
58
  private result;
81
- private budget;
82
- constructor(result: SendMessageResponse, budget: {
83
- maxTokens?: number;
84
- maxItems?: number;
85
- });
59
+ private config;
60
+ private requestId;
61
+ constructor(result: SendMessageResponse, config: LafsA2AConfig, requestId: string);
86
62
  /**
87
- * Get the underlying A2A result
63
+ * Get the raw A2A response
88
64
  */
89
65
  getA2AResult(): SendMessageResponse;
90
66
  /**
@@ -96,34 +72,103 @@ export declare class LafsA2AResult {
96
72
  */
97
73
  getError(): JSONRPCErrorResponse | null;
98
74
  /**
99
- * Extract LAFS envelope from A2A artifact
75
+ * Get success result
76
+ */
77
+ getSuccess(): SendMessageSuccessResponse | null;
78
+ /**
79
+ * Extract Task from response (if present)
80
+ */
81
+ getTask(): Task | null;
82
+ /**
83
+ * Extract Message from response (if present)
100
84
  */
101
- getLafsEnvelope(): LafsEnvelope | null;
85
+ getMessage(): Message | null;
102
86
  /**
103
- * Check if result contains LAFS envelope
87
+ * Check if response contains a LAFS envelope
104
88
  */
105
89
  hasLafsEnvelope(): boolean;
106
90
  /**
107
- * Get token estimate from envelope
91
+ * Extract LAFS envelope from A2A artifact
92
+ *
93
+ * A2A agents can return LAFS envelopes in artifacts for structured data.
94
+ * This method extracts the envelope from the first artifact containing one.
95
+ */
96
+ getLafsEnvelope(): LAFSEnvelope | null;
97
+ /**
98
+ * Get token estimate from LAFS envelope
108
99
  */
109
100
  getTokenEstimate(): {
110
101
  estimated: number;
111
102
  budget?: number;
103
+ truncated?: boolean;
112
104
  } | null;
105
+ /**
106
+ * Get task status
107
+ */
108
+ getTaskStatus(): TaskStatus | null;
109
+ /**
110
+ * Get task state
111
+ */
112
+ getTaskState(): TaskState | null;
113
+ /**
114
+ * Check if task is in a terminal state
115
+ */
116
+ isTerminal(): boolean;
117
+ /**
118
+ * Check if task requires input
119
+ */
120
+ isInputRequired(): boolean;
121
+ /**
122
+ * Check if task requires authentication
123
+ */
124
+ isAuthRequired(): boolean;
125
+ /**
126
+ * Get all artifacts from task
127
+ */
128
+ getArtifacts(): Artifact[];
129
+ private isDataPart;
113
130
  private isLafsEnvelope;
114
131
  }
115
132
  /**
116
- * Create a LAFS artifact for A2A
133
+ * Create a LAFS envelope artifact for A2A
117
134
  *
118
135
  * @example
119
136
  * ```typescript
120
- * const artifact = createLafsArtifact({
137
+ * const envelope = createEnvelope({
121
138
  * success: true,
122
139
  * result: { data: '...' },
123
140
  * meta: { operation: 'analysis.run' }
124
141
  * });
125
142
  *
143
+ * const artifact = createLafsArtifact(envelope);
126
144
  * task.artifacts.push(artifact);
127
145
  * ```
128
146
  */
129
- export declare function createLafsArtifact(envelope: LafsEnvelope): Artifact;
147
+ export declare function createLafsArtifact(envelope: LAFSEnvelope): Artifact;
148
+ /**
149
+ * Create a text artifact
150
+ */
151
+ export declare function createTextArtifact(text: string, name?: string): Artifact;
152
+ /**
153
+ * Create a file artifact
154
+ */
155
+ export declare function createFileArtifact(fileUrl: string, mediaType: string, filename?: string): Artifact;
156
+ /**
157
+ * Check if an extension is required
158
+ */
159
+ export declare function isExtensionRequired(agentCard: AgentCard, extensionUri: string): boolean;
160
+ /**
161
+ * Get extension parameters
162
+ */
163
+ export declare function getExtensionParams(agentCard: AgentCard, extensionUri: string): Record<string, unknown> | undefined;
164
+ /**
165
+ * A2A Agent Card well-known path
166
+ * Reference: specs/external/agent-discovery.md
167
+ */
168
+ export { AGENT_CARD_PATH };
169
+ /**
170
+ * HTTP header for A2A Extensions
171
+ * Reference: specs/external/extensions.md
172
+ */
173
+ export { HTTP_EXTENSION_HEADER };
174
+ export type { Task, TaskState, TaskStatus, Artifact, Part, Message, AgentCard, AgentSkill, AgentCapabilities, AgentExtension, PushNotificationConfig, MessageSendConfiguration, TaskStatusUpdateEvent, TaskArtifactUpdateEvent, SendMessageResponse, SendMessageSuccessResponse, JSONRPCErrorResponse, TextPart, DataPart, FilePart, } from '@a2a-js/sdk';