network-ai 4.0.17 → 4.1.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.
package/README.md CHANGED
@@ -4,10 +4,10 @@
4
4
 
5
5
  [![CI](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/ci.yml/badge.svg)](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/ci.yml)
6
6
  [![CodeQL](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/codeql.yml/badge.svg)](https://github.com/jovanSAPFIONEER/Network-AI/actions/workflows/codeql.yml)
7
- [![Release](https://img.shields.io/badge/release-v4.0.17-blue.svg)](https://github.com/jovanSAPFIONEER/Network-AI/releases)
7
+ [![Release](https://img.shields.io/badge/release-v4.1.0-blue.svg)](https://github.com/jovanSAPFIONEER/Network-AI/releases)
8
8
  [![npm](https://img.shields.io/npm/dw/network-ai.svg?label=npm%20downloads)](https://www.npmjs.com/package/network-ai)
9
- [![Tests](https://img.shields.io/badge/tests-1184%20passing-brightgreen.svg)](#testing)
10
- [![Adapters](https://img.shields.io/badge/frameworks-12%20supported-blueviolet.svg)](#adapter-system)
9
+ [![Tests](https://img.shields.io/badge/tests-1283%20passing-brightgreen.svg)](#testing)
10
+ [![Adapters](https://img.shields.io/badge/frameworks-13%20supported-blueviolet.svg)](#adapter-system)
11
11
  [![License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE)
12
12
  [![Socket](https://socket.dev/api/badge/npm/package/network-ai)](https://socket.dev/npm/package/network-ai/overview)
13
13
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18.0.0-brightgreen.svg)](https://nodejs.org)
@@ -19,7 +19,13 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
19
19
 
20
20
  - **Shared blackboard with locking** — atomic `propose → validate → commit` prevents race conditions and split-brain failures across parallel agents
21
21
  - **Guardrails and budgets** — FSM governance, per-agent token ceilings, HMAC audit trails, and permission gating
22
- - **12 framework adapters** — LangChain, AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, and more in one orchestrator — no glue code, no lock-in
22
+ - **13 adapters** — LangChain (+ streaming), AutoGen, CrewAI, OpenAI Assistants, LlamaIndex, Semantic Kernel, Haystack, DSPy, Agno, MCP, Custom (+ streaming), OpenClaw, and A2A — no glue code, no lock-in
23
+
24
+ > **The silent failure mode in multi-agent systems:** parallel agents writing to the same key
25
+ > use last-write-wins by default — one agent's result silently overwrites another's mid-flight.
26
+ > The outcome is split-brain state: double-spends, contradictory decisions, corrupted context,
27
+ > no error thrown. Network-AI's `propose → validate → commit` mutex prevents this at the
28
+ > coordination layer, before any write reaches shared state.
23
29
 
24
30
  **Use Network-AI as:**
25
31
  - A **TypeScript/Node.js library** — `import { createSwarmOrchestrator } from 'network-ai'`
@@ -28,6 +34,15 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
28
34
 
29
35
  [**5-minute quickstart →**](QUICKSTART.md)  |  [**Architecture →**](ARCHITECTURE.md)  |  [**All adapters →**](#adapter-system)  |  [**Benchmarks →**](BENCHMARKS.md)
30
36
 
37
+ > **Try the control-plane stress test — no API key, ~3 seconds:**
38
+ > ```bash
39
+ > npx ts-node examples/08-control-plane-stress-demo.ts
40
+ > ```
41
+ > Runs priority preemption, AuthGuardian permission gating, FSM governance, and compliance
42
+ > monitoring against a live swarm. No external services required.
43
+ >
44
+ > If it saves you from a race condition, a ⭐ helps others find it.
45
+
31
46
  ---
32
47
 
33
48
  ## Why teams use Network-AI
@@ -37,7 +52,7 @@ Network-AI is a TypeScript/Node.js multi-agent orchestrator that adds coordinati
37
52
  | Race conditions in parallel agents | Atomic blackboard: `propose → validate → commit` with file-system mutex |
38
53
  | Agent overspend / runaway costs | `FederatedBudget` — hard per-agent token ceilings with live spend tracking |
39
54
  | No visibility into what agents did | HMAC-signed audit log on every write, permission grant, and FSM transition |
40
- | Locked into one AI framework | 12 adapters — mix LangChain + AutoGen + CrewAI + custom in one swarm |
55
+ | Locked into one AI framework | 13 adapters — mix LangChain + AutoGen + CrewAI + A2A + custom in one swarm |
41
56
  | Agents escalating beyond their scope | `AuthGuardian` — scoped permission tokens required before sensitive operations |
42
57
 
43
58
  ---
@@ -90,6 +105,64 @@ No native dependencies, no build step. Adapters are dependency-free (BYOC — br
90
105
 
91
106
  ---
92
107
 
108
+ ## Use as MCP Server
109
+
110
+ Start the server (no config required, zero dependencies):
111
+
112
+ ```bash
113
+ npx network-ai-server --port 3001
114
+ # or from source:
115
+ npx ts-node bin/mcp-server.ts --port 3001
116
+ ```
117
+
118
+ Then wire any MCP-compatible client to it.
119
+
120
+ **Claude Desktop** — add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
121
+
122
+ ```json
123
+ {
124
+ "mcpServers": {
125
+ "network-ai": {
126
+ "url": "http://localhost:3001/sse"
127
+ }
128
+ }
129
+ }
130
+ ```
131
+
132
+ **Cursor / Cline / any SSE-based MCP client** — point to the same URL:
133
+
134
+ ```json
135
+ {
136
+ "mcpServers": {
137
+ "network-ai": {
138
+ "url": "http://localhost:3001/sse"
139
+ }
140
+ }
141
+ }
142
+ ```
143
+
144
+ Verify it's running:
145
+
146
+ ```bash
147
+ curl http://localhost:3001/health # { "status": "ok", "tools": <n>, "uptime": <ms> }
148
+ curl http://localhost:3001/tools # full tool list
149
+ ```
150
+
151
+ **Tools exposed over MCP:**
152
+ - `blackboard_read` / `blackboard_write` / `blackboard_list` / `blackboard_delete` / `blackboard_exists`
153
+ - `budget_status` / `budget_spend` / `budget_reset` — federated token tracking
154
+ - `token_create` / `token_validate` / `token_revoke` — HMAC-signed permission tokens
155
+ - `audit_query` — query the append-only audit log
156
+ - `config_get` / `config_set` — live orchestrator configuration
157
+ - `agent_list` / `agent_spawn` / `agent_stop` — agent lifecycle
158
+ - `fsm_transition` — write FSM state transitions to the blackboard
159
+
160
+ Each tool takes an `agent_id` parameter — all writes are identity-verified and namespace-scoped, exactly as they are in the TypeScript API.
161
+
162
+ Options: `--no-budget`, `--no-token`, `--no-control`, `--ceiling <n>`, `--board <name>`, `--audit-log <path>`.
163
+
164
+ ---
165
+
93
166
  ## Two agents, one shared state — without race conditions
94
167
 
95
168
  The real differentiator is coordination. Here is what no single-framework solution handles: two agents writing to the same resource concurrently, atomically, without corrupting each other.
@@ -157,12 +230,12 @@ npm run demo -- --07
157
230
 
158
231
  ## Adapter System
159
232
 
160
- 12 frameworks, zero adapter dependencies. You bring your own SDK objects.
233
+ 13 adapters, zero adapter dependencies. You bring your own SDK objects.
161
234
 
162
- | Adapter | Framework | Register method |
235
+ | Adapter | Framework / Protocol | Register method |
163
236
  |---|---|---|
164
237
  | `CustomAdapter` | Any function or HTTP endpoint | `registerHandler(name, fn)` |
165
- | `LangChainAdapter` | LangChain | `registerRunnable(name, runnable)` |
238
+ | `LangChainAdapter` | LangChain | `registerAgent(name, runnable)` |
166
239
  | `AutoGenAdapter` | AutoGen / AG2 | `registerAgent(name, agent)` |
167
240
  | `CrewAIAdapter` | CrewAI | `registerAgent` or `registerCrew` |
168
241
  | `MCPAdapter` | Model Context Protocol | `registerTool(name, handler)` |
@@ -173,8 +246,16 @@ npm run demo -- --07
173
246
  | `DSPyAdapter` | Stanford DSPy | `registerModule()`, `registerProgram()` |
174
247
  | `AgnoAdapter` | Agno (formerly Phidata) | `registerAgent()`, `registerTeam()` |
175
248
  | `OpenClawAdapter` | OpenClaw | `registerSkill(name, skillRef)` |
249
+ | `A2AAdapter` | Google A2A Protocol | `registerRemoteAgent(name, url)` |
250
+
251
+ **Streaming variants** (drop-in replacements with `.stream()` support):
176
252
 
177
- Extend `BaseAdapter` to add your own in minutes. See [references/adapter-system.md](references/adapter-system.md).
253
+ | Adapter | Extends | Streaming source |
254
+ |---|---|---|
255
+ | `LangChainStreamingAdapter` | `LangChainAdapter` | Calls `.stream()` on the Runnable if available; falls back to `.invoke()` |
256
+ | `CustomStreamingAdapter` | `CustomAdapter` | Pipes `AsyncIterable<string>` handlers; falls back to single-chunk for plain Promises |
257
+
258
+ Extend `BaseAdapter` (or `StreamingBaseAdapter` for streaming) to add your own in minutes. See [references/adapter-system.md](references/adapter-system.md).
178
259
 
179
260
  ---
180
261
 
@@ -184,7 +265,7 @@ Extend `BaseAdapter` to add your own in minutes. See [references/adapter-system.
184
265
 
185
266
  | Capability | Network-AI | LangGraph | CrewAI | AutoGen |
186
267
  |---|---|---|---|---|
187
- | Cross-framework agents in one swarm | ✅ 12 built-in adapters | ⚠️ Nodes can call any code; no adapter abstraction | ⚠️ Extensible via tools; CrewAI-native agents only | ⚠️ Extensible via plugins; AutoGen-native agents only |
268
+ | Cross-framework agents in one swarm | ✅ 13 built-in adapters | ⚠️ Nodes can call any code; no adapter abstraction | ⚠️ Extensible via tools; CrewAI-native agents only | ⚠️ Extensible via plugins; AutoGen-native agents only |
188
269
  | Atomic shared state (conflict-safe) | ✅ `propose → validate → commit` mutex | ⚠️ State passed between nodes; last-write-wins | ⚠️ Shared memory available; no conflict resolution | ⚠️ Shared context available; no conflict resolution |
189
270
  | Hard token ceiling per agent | ✅ `FederatedBudget` (first-class API) | ⚠️ Via callbacks / custom middleware | ⚠️ Via callbacks / custom middleware | ⚠️ Built-in token tracking in v0.4+; no swarm-level ceiling |
190
271
  | Permission gating before sensitive ops | ✅ `AuthGuardian` (built-in) | ⚠️ Possible via custom node logic | ⚠️ Possible via custom tools | ⚠️ Possible via custom middleware |
@@ -200,29 +281,31 @@ Extend `BaseAdapter` to add your own in minutes. See [references/adapter-system.
200
281
  npm run test:all # All suites in sequence
201
282
  npm test # Core orchestrator
202
283
  npm run test:security # Security module
203
- npm run test:adapters # All 12 adapters
284
+ npm run test:adapters # All 13 adapters
285
+ npm run test:streaming # Streaming adapters
286
+ npm run test:a2a # A2A protocol adapter
204
287
  npm run test:priority # Priority & preemption
205
288
  ```
206
289
 
207
- **1,184 passing assertions across 15 test suites** (verified by counting `assert()` / `pass()` calls in each file):
290
+ **1,283 passing assertions across 15 test suites** (`npm run test:all`):
208
291
 
209
292
  | Suite | Assertions | Covers |
210
293
  |---|---|---|
211
- | `test-standalone.ts` | 83 | Blackboard, auth, integration, persistence, parallelisation, quality gate |
212
- | `test-adapters.ts` | 142 | All 12 adapters, registry routing, integration, edge cases |
213
- | `test-phase4.ts` | 133 | FSM, compliance monitor, adapter integration |
214
- | `test-phase5d.ts` | 119 | Pluggable backend |
215
- | `test-phase5f.ts` | 113 | Phase 5f extended |
216
- | `test-phase5g.ts` | 106 | Phase 5g extended |
217
- | `test-phase6.ts` | 122 | Latest feature coverage |
218
- | `test-phase5c.ts` | 74 | Named multi-blackboard |
219
- | `test-phase5e.ts` | 88 | Phase 5e |
220
- | `test-phase5b.ts` | 56 | Pluggable backend part 2 |
221
- | `test-priority.ts` | 65 | Priority preemption, conflict resolution, backward compat |
222
- | `test-security.ts` | 35 | Tokens, sanitization, rate limiting, encryption, audit |
223
- | `test-phase5.ts` | 24 | Named multi-blackboard base |
224
- | `test.ts` | 24 | Full integration |
225
- | `test-phase4.ts` (stubs) | 4 | FSM stub coverage |
294
+ | `test-phase4.ts` | 147 | FSM governance, compliance monitor, adapter integration |
295
+ | `test-phase5f.ts` | 127 | SSE transport, `McpCombinedBridge`, extended MCP tools |
296
+ | `test-phase5g.ts` | 121 | CRDT backend, vector clocks, bidirectional sync |
297
+ | `test-phase6.ts` | 121 | MCP server, control-plane tools, audit tools |
298
+ | `test-phase5d.ts` | 117 | Pluggable backend (Redis, CRDT, Memory) |
299
+ | `test-adapters.ts` | 139 | All 13 adapters, registry routing, integration, edge cases |
300
+ | `test-standalone.ts` | 88 | Blackboard, auth, integration, persistence, parallelisation, quality gate |
301
+ | `test-phase5e.ts` | 87 | Federated budget tracking |
302
+ | `test-phase5c.ts` | 73 | Named multi-blackboard, isolation, backend options |
303
+ | `test-priority.ts` | 64 | Priority preemption, conflict resolution, backward compat |
304
+ | `test-a2a.ts` | 34 | A2A protocol: register, execute, mock fetch, error paths |
305
+ | `test-streaming.ts` | 31 | Streaming adapters, chunk shapes, fallback, collectStream |
306
+ | `test-phase5b.ts` | 55 | Pluggable backend part 2, consistency levels |
307
+ | `test-phase5.ts` | 42 | Named multi-blackboard base |
308
+ | `test-security.ts` | 34 | Tokens, sanitization, rate limiting, encryption, audit |
226
309
 
227
310
  ---
228
311
 
@@ -248,9 +331,6 @@ npm run test:priority # Priority & preemption
248
331
 
249
332
  1. Fork → feature branch → `npm run test:all` → pull request
250
333
  2. Bugs and feature requests via [Issues](https://github.com/jovanSAPFIONEER/Network-AI/issues)
251
- 3. If Network-AI saves you time, a ⭐ helps others find it
252
-
253
- [![Star on GitHub](https://img.shields.io/github/stars/jovanSAPFIONEER/Network-AI?style=social)](https://github.com/jovanSAPFIONEER/Network-AI)
254
334
 
255
335
  ---
256
336
 
@@ -0,0 +1,152 @@
1
+ /**
2
+ * A2AAdapter — Agent-to-Agent (A2A) protocol adapter.
3
+ *
4
+ * Implements the Google A2A (Agent-to-Agent) open protocol that lets
5
+ * independently hosted agents discover each other through a standard
6
+ * Agent Card (/.well-known/agent.json) and exchange tasks via a
7
+ * JSON-RPC envelope posted to the agent's task endpoint.
8
+ *
9
+ * References:
10
+ * https://google.github.io/A2A/
11
+ * https://github.com/google/A2A
12
+ *
13
+ * Usage:
14
+ *
15
+ * const adapter = new A2AAdapter();
16
+ * await adapter.initialize({});
17
+ *
18
+ * // Register a remote agent by its Agent Card URL
19
+ * await adapter.registerRemoteAgent('remote-analyst', 'https://agent.example.com');
20
+ *
21
+ * // Or register a local agent that serves an A2A-compliant card
22
+ * adapter.registerLocalA2AAgent('local-writer', {
23
+ * name: 'Writing Agent',
24
+ * description: 'Draft documents given a topic',
25
+ * version: '1.0',
26
+ * capabilities: { streaming: false },
27
+ * taskEndpoint: 'https://writer.internal/tasks',
28
+ * });
29
+ *
30
+ * await registry.addAdapter(adapter);
31
+ *
32
+ * // In the orchestrator:
33
+ * delegateTask({ targetAgent: 'a2a:remote-analyst', ... })
34
+ *
35
+ * @module A2AAdapter
36
+ * @version 1.0.0
37
+ */
38
+ import { BaseAdapter } from './base-adapter';
39
+ import type { AdapterConfig, AdapterCapabilities, AgentPayload, AgentContext, AgentResult } from '../types/agent-adapter';
40
+ /** Agent Card served at /.well-known/agent.json (A2A spec §3.1) */
41
+ export interface A2AAgentCard {
42
+ /** Human-readable agent name */
43
+ name: string;
44
+ /** Purpose / capabilities in plain English */
45
+ description?: string;
46
+ /** SemVer */
47
+ version?: string;
48
+ /** Protocol capabilities declared by the agent */
49
+ capabilities?: {
50
+ streaming?: boolean;
51
+ pushNotifications?: boolean;
52
+ stateTransitionHistory?: boolean;
53
+ };
54
+ /** URL that accepts A2A task envelopes (defaults to <baseUrl>/tasks) */
55
+ taskEndpoint?: string;
56
+ /** Agent homepage or further docs */
57
+ url?: string;
58
+ }
59
+ /** JSON-RPC 2.0 task request envelope sent to the task endpoint (A2A spec §4) */
60
+ export interface A2ATask {
61
+ jsonrpc: '2.0';
62
+ id: string;
63
+ method: 'tasks/send';
64
+ params: {
65
+ id: string;
66
+ message: {
67
+ role: 'user';
68
+ parts: Array<{
69
+ type: 'text';
70
+ text: string;
71
+ }>;
72
+ };
73
+ metadata?: Record<string, unknown>;
74
+ };
75
+ }
76
+ /** State of a running A2A task */
77
+ export type A2ATaskState = 'submitted' | 'working' | 'input-required' | 'completed' | 'canceled' | 'failed' | 'unknown';
78
+ /** Artifact produced by the agent (A2A spec §4.3) */
79
+ export interface A2AArtifact {
80
+ name?: string;
81
+ description?: string;
82
+ parts: Array<{
83
+ type: string;
84
+ text?: string;
85
+ data?: unknown;
86
+ }>;
87
+ }
88
+ /** JSON-RPC 2.0 task response (A2A spec §4) */
89
+ export interface A2ATaskResponse {
90
+ jsonrpc: '2.0';
91
+ id: string;
92
+ result?: {
93
+ id: string;
94
+ status: {
95
+ state: A2ATaskState;
96
+ message?: string;
97
+ };
98
+ artifacts?: A2AArtifact[];
99
+ metadata?: Record<string, unknown>;
100
+ };
101
+ error?: {
102
+ code: number;
103
+ message: string;
104
+ data?: unknown;
105
+ };
106
+ }
107
+ /** Adapter configuration specific to A2A */
108
+ export interface A2AAdapterConfig extends AdapterConfig {
109
+ /** Default bearer token applied to all agents unless overridden at agent level */
110
+ defaultBearerToken?: string;
111
+ /** Default timeout for all agents in ms (default: 30 000) */
112
+ defaultTimeoutMs?: number;
113
+ /** Custom fetch implementation (for testing / node compat) */
114
+ fetchImpl?: typeof fetch;
115
+ }
116
+ export declare class A2AAdapter extends BaseAdapter {
117
+ readonly name = "a2a";
118
+ readonly version = "1.0.0";
119
+ private a2aAgents;
120
+ private defaultBearerToken?;
121
+ private defaultTimeoutMs;
122
+ private fetchImpl;
123
+ get capabilities(): AdapterCapabilities;
124
+ initialize(config: A2AAdapterConfig): Promise<void>;
125
+ /**
126
+ * Fetch the Agent Card from `<baseUrl>/.well-known/agent.json` and register
127
+ * the remote agent for use in the orchestrator.
128
+ *
129
+ * @param agentId - Local identifier (used in `delegate_task` calls)
130
+ * @param baseUrl - Root URL of the remote A2A-compliant agent server
131
+ * @param options - Optional bearer token / timeout override
132
+ */
133
+ registerRemoteAgent(agentId: string, baseUrl: string, options?: {
134
+ bearerToken?: string;
135
+ timeoutMs?: number;
136
+ }): Promise<void>;
137
+ /**
138
+ * Register a local A2A agent whose card you already have (no network fetch).
139
+ * Useful when the card is embedded in config or returned from another service.
140
+ */
141
+ registerLocalA2AAgent(agentId: string, card: A2AAgentCard & {
142
+ taskEndpoint: string;
143
+ }, options?: {
144
+ bearerToken?: string;
145
+ timeoutMs?: number;
146
+ }): void;
147
+ executeAgent(agentId: string, payload: AgentPayload, context: AgentContext): Promise<AgentResult>;
148
+ private fetchAgentCard;
149
+ private sendTask;
150
+ private extractOutput;
151
+ }
152
+ //# sourceMappingURL=a2a-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a-adapter.d.ts","sourceRoot":"","sources":["../../adapters/a2a-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,235 @@
1
+ "use strict";
2
+ /**
3
+ * A2AAdapter — Agent-to-Agent (A2A) protocol adapter.
4
+ *
5
+ * Implements the Google A2A (Agent-to-Agent) open protocol that lets
6
+ * independently hosted agents discover each other through a standard
7
+ * Agent Card (/.well-known/agent.json) and exchange tasks via a
8
+ * JSON-RPC envelope posted to the agent's task endpoint.
9
+ *
10
+ * References:
11
+ * https://google.github.io/A2A/
12
+ * https://github.com/google/A2A
13
+ *
14
+ * Usage:
15
+ *
16
+ * const adapter = new A2AAdapter();
17
+ * await adapter.initialize({});
18
+ *
19
+ * // Register a remote agent by its Agent Card URL
20
+ * await adapter.registerRemoteAgent('remote-analyst', 'https://agent.example.com');
21
+ *
22
+ * // Or register a local agent that serves an A2A-compliant card
23
+ * adapter.registerLocalA2AAgent('local-writer', {
24
+ * name: 'Writing Agent',
25
+ * description: 'Draft documents given a topic',
26
+ * version: '1.0',
27
+ * capabilities: { streaming: false },
28
+ * taskEndpoint: 'https://writer.internal/tasks',
29
+ * });
30
+ *
31
+ * await registry.addAdapter(adapter);
32
+ *
33
+ * // In the orchestrator:
34
+ * delegateTask({ targetAgent: 'a2a:remote-analyst', ... })
35
+ *
36
+ * @module A2AAdapter
37
+ * @version 1.0.0
38
+ */
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.A2AAdapter = void 0;
41
+ const base_adapter_1 = require("./base-adapter");
42
+ class A2AAdapter extends base_adapter_1.BaseAdapter {
43
+ name = 'a2a';
44
+ version = '1.0.0';
45
+ a2aAgents = new Map();
46
+ defaultBearerToken;
47
+ defaultTimeoutMs = 30_000;
48
+ fetchImpl = globalThis.fetch;
49
+ get capabilities() {
50
+ return {
51
+ streaming: false,
52
+ parallel: true,
53
+ bidirectional: false,
54
+ discovery: true,
55
+ authentication: true,
56
+ statefulSessions: false,
57
+ };
58
+ }
59
+ async initialize(config) {
60
+ await super.initialize(config);
61
+ if (config.defaultBearerToken)
62
+ this.defaultBearerToken = config.defaultBearerToken;
63
+ if (config.defaultTimeoutMs)
64
+ this.defaultTimeoutMs = config.defaultTimeoutMs;
65
+ if (config.fetchImpl)
66
+ this.fetchImpl = config.fetchImpl;
67
+ }
68
+ // ── Registration ────────────────────────────────────────────────────────────
69
+ /**
70
+ * Fetch the Agent Card from `<baseUrl>/.well-known/agent.json` and register
71
+ * the remote agent for use in the orchestrator.
72
+ *
73
+ * @param agentId - Local identifier (used in `delegate_task` calls)
74
+ * @param baseUrl - Root URL of the remote A2A-compliant agent server
75
+ * @param options - Optional bearer token / timeout override
76
+ */
77
+ async registerRemoteAgent(agentId, baseUrl, options) {
78
+ const url = baseUrl.replace(/\/$/, '');
79
+ const card = await this.fetchAgentCard(url, options?.bearerToken ?? this.defaultBearerToken);
80
+ const taskEndpoint = card.taskEndpoint ??
81
+ (card.url ? `${card.url.replace(/\/$/, '')}/tasks` : `${url}/tasks`);
82
+ this.a2aAgents.set(agentId, {
83
+ baseUrl: url,
84
+ card,
85
+ taskEndpoint,
86
+ bearerToken: options?.bearerToken ?? this.defaultBearerToken,
87
+ timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
88
+ });
89
+ this.registerLocalAgent({
90
+ id: agentId,
91
+ name: card.name,
92
+ description: card.description ?? `Remote A2A agent at ${url}`,
93
+ capabilities: card.capabilities
94
+ ? Object.keys(card.capabilities).filter(k => card.capabilities[k] === true)
95
+ : undefined,
96
+ status: 'available',
97
+ metadata: { a2aBaseUrl: url, taskEndpoint },
98
+ });
99
+ }
100
+ /**
101
+ * Register a local A2A agent whose card you already have (no network fetch).
102
+ * Useful when the card is embedded in config or returned from another service.
103
+ */
104
+ registerLocalA2AAgent(agentId, card, options) {
105
+ this.a2aAgents.set(agentId, {
106
+ baseUrl: card.url ?? '',
107
+ card,
108
+ taskEndpoint: card.taskEndpoint,
109
+ bearerToken: options?.bearerToken ?? this.defaultBearerToken,
110
+ timeoutMs: options?.timeoutMs ?? this.defaultTimeoutMs,
111
+ });
112
+ this.registerLocalAgent({
113
+ id: agentId,
114
+ name: card.name,
115
+ description: card.description ?? `Local A2A agent: ${agentId}`,
116
+ capabilities: card.capabilities
117
+ ? Object.keys(card.capabilities).filter(k => card.capabilities[k] === true)
118
+ : undefined,
119
+ status: 'available',
120
+ });
121
+ }
122
+ // ── Execution ───────────────────────────────────────────────────────────────
123
+ async executeAgent(agentId, payload, context) {
124
+ this.ensureReady();
125
+ const config = this.a2aAgents.get(agentId);
126
+ if (!config) {
127
+ return this.errorResult('AGENT_NOT_FOUND', `A2A agent "${agentId}" is not registered. Call registerRemoteAgent() or registerLocalA2AAgent() first.`, false);
128
+ }
129
+ const startTime = Date.now();
130
+ // Build the task instruction from the handoff payload
131
+ const instruction = payload.handoff?.instruction ??
132
+ (payload.params ? JSON.stringify(payload.params) : 'No instruction provided');
133
+ const taskId = `${context.taskId ?? 'task'}-${Date.now()}`;
134
+ const taskEnvelope = {
135
+ jsonrpc: '2.0',
136
+ id: taskId,
137
+ method: 'tasks/send',
138
+ params: {
139
+ id: taskId,
140
+ message: {
141
+ role: 'user',
142
+ parts: [{ type: 'text', text: instruction }],
143
+ },
144
+ metadata: {
145
+ sourceAgent: context.agentId,
146
+ sessionId: context.sessionId,
147
+ ...(payload.handoff?.context ?? {}),
148
+ },
149
+ },
150
+ };
151
+ try {
152
+ const response = await this.sendTask(config, taskEnvelope);
153
+ if (response.error) {
154
+ return this.errorResult(`A2A_ERROR_${response.error.code}`, response.error.message, response.error.code >= 500, response.error);
155
+ }
156
+ if (!response.result) {
157
+ return this.errorResult('A2A_EMPTY_RESPONSE', 'A2A response had no result field', true);
158
+ }
159
+ const state = response.result.status.state;
160
+ if (state === 'failed' || state === 'canceled') {
161
+ return this.errorResult(`A2A_TASK_${state.toUpperCase()}`, response.result.status.message ?? `Task ended with state: ${state}`, state === 'failed');
162
+ }
163
+ // Extract text from artifacts
164
+ const output = this.extractOutput(response.result.artifacts);
165
+ return this.successResult({ output, state, artifacts: response.result.artifacts, metadata: response.result.metadata }, Date.now() - startTime);
166
+ }
167
+ catch (err) {
168
+ if (err instanceof Error && err.name === 'AbortError') {
169
+ return this.errorResult('A2A_TIMEOUT', `A2A request timed out after ${config.timeoutMs}ms`, true);
170
+ }
171
+ return this.errorResult('A2A_REQUEST_FAILED', err instanceof Error ? err.message : 'A2A request failed', true, err);
172
+ }
173
+ }
174
+ // ── Internals ───────────────────────────────────────────────────────────────
175
+ async fetchAgentCard(baseUrl, bearerToken) {
176
+ const cardUrl = `${baseUrl}/.well-known/agent.json`;
177
+ const headers = { Accept: 'application/json' };
178
+ if (bearerToken)
179
+ headers.Authorization = `Bearer ${bearerToken}`;
180
+ const controller = new AbortController();
181
+ const id = setTimeout(() => controller.abort(), this.defaultTimeoutMs);
182
+ let response;
183
+ try {
184
+ response = await this.fetchImpl(cardUrl, { headers, signal: controller.signal });
185
+ }
186
+ finally {
187
+ clearTimeout(id);
188
+ }
189
+ if (!response.ok) {
190
+ throw new Error(`Failed to fetch agent card from ${cardUrl}: HTTP ${response.status}`);
191
+ }
192
+ const card = await response.json();
193
+ if (!card.name) {
194
+ throw new Error(`Agent card at ${cardUrl} is missing required "name" field`);
195
+ }
196
+ return card;
197
+ }
198
+ async sendTask(config, task) {
199
+ const headers = {
200
+ 'Content-Type': 'application/json',
201
+ Accept: 'application/json',
202
+ };
203
+ if (config.bearerToken)
204
+ headers.Authorization = `Bearer ${config.bearerToken}`;
205
+ const controller = new AbortController();
206
+ const id = setTimeout(() => controller.abort(), config.timeoutMs);
207
+ let response;
208
+ try {
209
+ response = await this.fetchImpl(config.taskEndpoint, {
210
+ method: 'POST',
211
+ headers,
212
+ body: JSON.stringify(task),
213
+ signal: controller.signal,
214
+ });
215
+ }
216
+ finally {
217
+ clearTimeout(id);
218
+ }
219
+ if (!response.ok) {
220
+ throw new Error(`A2A task endpoint returned HTTP ${response.status}: ${response.statusText}`);
221
+ }
222
+ return response.json();
223
+ }
224
+ extractOutput(artifacts) {
225
+ if (!artifacts?.length)
226
+ return '';
227
+ return artifacts
228
+ .flatMap(a => a.parts)
229
+ .filter(p => p.type === 'text' && typeof p.text === 'string')
230
+ .map(p => p.text)
231
+ .join('\n');
232
+ }
233
+ }
234
+ exports.A2AAdapter = A2AAdapter;
235
+ //# sourceMappingURL=a2a-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a-adapter.js","sourceRoot":"","sources":["../../adapters/a2a-adapter.ts"],"names":[],"mappings":"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"}