macro-agent 0.0.14 → 0.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.claude/settings.local.json +59 -0
  2. package/dist/acp/index.d.ts +1 -1
  3. package/dist/acp/index.d.ts.map +1 -1
  4. package/dist/acp/index.js.map +1 -1
  5. package/dist/acp/macro-agent.d.ts +21 -0
  6. package/dist/acp/macro-agent.d.ts.map +1 -1
  7. package/dist/acp/macro-agent.js +182 -0
  8. package/dist/acp/macro-agent.js.map +1 -1
  9. package/dist/acp/types.d.ts +31 -2
  10. package/dist/acp/types.d.ts.map +1 -1
  11. package/dist/acp/types.js.map +1 -1
  12. package/dist/agent/agent-manager.d.ts.map +1 -1
  13. package/dist/agent/agent-manager.js +10 -4
  14. package/dist/agent/agent-manager.js.map +1 -1
  15. package/dist/cli/acp.d.ts +6 -0
  16. package/dist/cli/acp.d.ts.map +1 -1
  17. package/dist/cli/acp.js +16 -2
  18. package/dist/cli/acp.js.map +1 -1
  19. package/dist/map/adapter/acp-over-map.d.ts +5 -0
  20. package/dist/map/adapter/acp-over-map.d.ts.map +1 -1
  21. package/dist/map/adapter/acp-over-map.js +47 -4
  22. package/dist/map/adapter/acp-over-map.js.map +1 -1
  23. package/dist/map/utils/address-translation.d.ts +99 -0
  24. package/dist/map/utils/address-translation.d.ts.map +1 -0
  25. package/dist/map/utils/address-translation.js +285 -0
  26. package/dist/map/utils/address-translation.js.map +1 -0
  27. package/dist/map/utils/index.d.ts +7 -0
  28. package/dist/map/utils/index.d.ts.map +1 -0
  29. package/dist/map/utils/index.js +7 -0
  30. package/dist/map/utils/index.js.map +1 -0
  31. package/dist/store/event-store.js +9 -2
  32. package/dist/store/event-store.js.map +1 -1
  33. package/dist/store/types/agents.d.ts +2 -0
  34. package/dist/store/types/agents.d.ts.map +1 -1
  35. package/package.json +4 -4
  36. package/references/acp-factory-ref/CHANGELOG.md +33 -0
  37. package/references/acp-factory-ref/LICENSE +21 -0
  38. package/references/acp-factory-ref/README.md +341 -0
  39. package/references/acp-factory-ref/package-lock.json +3102 -0
  40. package/references/acp-factory-ref/package.json +96 -0
  41. package/references/acp-factory-ref/python/CHANGELOG.md +33 -0
  42. package/references/acp-factory-ref/python/LICENSE +21 -0
  43. package/references/acp-factory-ref/python/Makefile +57 -0
  44. package/references/acp-factory-ref/python/README.md +253 -0
  45. package/references/acp-factory-ref/python/pyproject.toml +73 -0
  46. package/references/acp-factory-ref/python/tests/__init__.py +0 -0
  47. package/references/acp-factory-ref/python/tests/e2e/__init__.py +1 -0
  48. package/references/acp-factory-ref/python/tests/e2e/test_codex_e2e.py +349 -0
  49. package/references/acp-factory-ref/python/tests/e2e/test_gemini_e2e.py +165 -0
  50. package/references/acp-factory-ref/python/tests/e2e/test_opencode_e2e.py +296 -0
  51. package/references/acp-factory-ref/python/tests/test_client_handler.py +543 -0
  52. package/references/acp-factory-ref/python/tests/test_pushable.py +199 -0
  53. package/references/claude-code-acp/.github/workflows/ci.yml +45 -0
  54. package/references/claude-code-acp/.github/workflows/publish.yml +34 -0
  55. package/references/claude-code-acp/.prettierrc.json +4 -0
  56. package/references/claude-code-acp/CHANGELOG.md +249 -0
  57. package/references/claude-code-acp/LICENSE +222 -0
  58. package/references/claude-code-acp/README.md +53 -0
  59. package/references/claude-code-acp/docs/RELEASES.md +24 -0
  60. package/references/claude-code-acp/eslint.config.js +48 -0
  61. package/references/claude-code-acp/package-lock.json +4570 -0
  62. package/references/claude-code-acp/package.json +88 -0
  63. package/references/claude-code-acp/scripts/release.sh +119 -0
  64. package/references/claude-code-acp/src/acp-agent.ts +2079 -0
  65. package/references/claude-code-acp/src/index.ts +26 -0
  66. package/references/claude-code-acp/src/lib.ts +38 -0
  67. package/references/claude-code-acp/src/mcp-server.ts +911 -0
  68. package/references/claude-code-acp/src/settings.ts +522 -0
  69. package/references/claude-code-acp/src/tests/.claude/commands/quick-math.md +5 -0
  70. package/references/claude-code-acp/src/tests/.claude/commands/say-hello.md +6 -0
  71. package/references/claude-code-acp/src/tests/acp-agent-fork.test.ts +479 -0
  72. package/references/claude-code-acp/src/tests/acp-agent.test.ts +1502 -0
  73. package/references/claude-code-acp/src/tests/extract-lines.test.ts +103 -0
  74. package/references/claude-code-acp/src/tests/fork-session.test.ts +335 -0
  75. package/references/claude-code-acp/src/tests/replace-and-calculate-location.test.ts +334 -0
  76. package/references/claude-code-acp/src/tests/settings.test.ts +617 -0
  77. package/references/claude-code-acp/src/tests/skills-options.test.ts +187 -0
  78. package/references/claude-code-acp/src/tests/tools.test.ts +318 -0
  79. package/references/claude-code-acp/src/tests/typescript-declarations.test.ts +558 -0
  80. package/references/claude-code-acp/src/tools.ts +819 -0
  81. package/references/claude-code-acp/src/utils.ts +171 -0
  82. package/references/claude-code-acp/tsconfig.json +18 -0
  83. package/references/claude-code-acp/vitest.config.ts +19 -0
  84. package/references/multi-agent-protocol/.sudocode/issues.jsonl +111 -0
  85. package/references/multi-agent-protocol/.sudocode/specs.jsonl +13 -0
  86. package/references/multi-agent-protocol/LICENSE +21 -0
  87. package/references/multi-agent-protocol/README.md +113 -0
  88. package/references/multi-agent-protocol/docs/00-design-specification.md +496 -0
  89. package/references/multi-agent-protocol/docs/01-open-questions.md +1050 -0
  90. package/references/multi-agent-protocol/docs/02-wire-protocol.md +296 -0
  91. package/references/multi-agent-protocol/docs/03-streaming-semantics.md +252 -0
  92. package/references/multi-agent-protocol/docs/04-error-handling.md +231 -0
  93. package/references/multi-agent-protocol/docs/05-connection-model.md +244 -0
  94. package/references/multi-agent-protocol/docs/06-visibility-permissions.md +243 -0
  95. package/references/multi-agent-protocol/docs/07-federation.md +259 -0
  96. package/references/multi-agent-protocol/docs/08-macro-agent-migration.md +253 -0
  97. package/references/multi-agent-protocol/docs/09-authentication.md +680 -0
  98. package/references/multi-agent-protocol/docs/10-mail-protocol.md +553 -0
  99. package/references/multi-agent-protocol/docs/agent-iam-integration.md +877 -0
  100. package/references/multi-agent-protocol/docs/agentic-mesh-integration-draft.md +459 -0
  101. package/references/multi-agent-protocol/docs/git-transport-draft.md +251 -0
  102. package/references/multi-agent-protocol/docs-site/Gemfile +22 -0
  103. package/references/multi-agent-protocol/docs-site/README.md +82 -0
  104. package/references/multi-agent-protocol/docs-site/_config.yml +91 -0
  105. package/references/multi-agent-protocol/docs-site/_includes/head_custom.html +20 -0
  106. package/references/multi-agent-protocol/docs-site/_sass/color_schemes/map.scss +42 -0
  107. package/references/multi-agent-protocol/docs-site/_sass/custom/custom.scss +34 -0
  108. package/references/multi-agent-protocol/docs-site/examples/full-integration.md +510 -0
  109. package/references/multi-agent-protocol/docs-site/examples/index.md +138 -0
  110. package/references/multi-agent-protocol/docs-site/examples/simple-chat.md +282 -0
  111. package/references/multi-agent-protocol/docs-site/examples/task-queue.md +399 -0
  112. package/references/multi-agent-protocol/docs-site/getting-started/index.md +98 -0
  113. package/references/multi-agent-protocol/docs-site/getting-started/installation.md +219 -0
  114. package/references/multi-agent-protocol/docs-site/getting-started/overview.md +172 -0
  115. package/references/multi-agent-protocol/docs-site/getting-started/quickstart.md +237 -0
  116. package/references/multi-agent-protocol/docs-site/index.md +136 -0
  117. package/references/multi-agent-protocol/docs-site/protocol/authentication.md +391 -0
  118. package/references/multi-agent-protocol/docs-site/protocol/connection-model.md +376 -0
  119. package/references/multi-agent-protocol/docs-site/protocol/design.md +284 -0
  120. package/references/multi-agent-protocol/docs-site/protocol/error-handling.md +312 -0
  121. package/references/multi-agent-protocol/docs-site/protocol/federation.md +449 -0
  122. package/references/multi-agent-protocol/docs-site/protocol/index.md +129 -0
  123. package/references/multi-agent-protocol/docs-site/protocol/permissions.md +398 -0
  124. package/references/multi-agent-protocol/docs-site/protocol/streaming.md +353 -0
  125. package/references/multi-agent-protocol/docs-site/protocol/wire-protocol.md +369 -0
  126. package/references/multi-agent-protocol/docs-site/sdk/api/agent.md +357 -0
  127. package/references/multi-agent-protocol/docs-site/sdk/api/client.md +380 -0
  128. package/references/multi-agent-protocol/docs-site/sdk/api/index.md +62 -0
  129. package/references/multi-agent-protocol/docs-site/sdk/api/server.md +453 -0
  130. package/references/multi-agent-protocol/docs-site/sdk/api/types.md +468 -0
  131. package/references/multi-agent-protocol/docs-site/sdk/guides/agent.md +375 -0
  132. package/references/multi-agent-protocol/docs-site/sdk/guides/authentication.md +405 -0
  133. package/references/multi-agent-protocol/docs-site/sdk/guides/client.md +352 -0
  134. package/references/multi-agent-protocol/docs-site/sdk/guides/index.md +89 -0
  135. package/references/multi-agent-protocol/docs-site/sdk/guides/server.md +360 -0
  136. package/references/multi-agent-protocol/docs-site/sdk/guides/testing.md +446 -0
  137. package/references/multi-agent-protocol/docs-site/sdk/guides/transports.md +363 -0
  138. package/references/multi-agent-protocol/docs-site/sdk/index.md +206 -0
  139. package/references/multi-agent-protocol/package-lock.json +3886 -0
  140. package/references/multi-agent-protocol/package.json +56 -0
  141. package/references/multi-agent-protocol/schema/meta.json +467 -0
  142. package/references/multi-agent-protocol/schema/schema.json +2558 -0
  143. package/src/acp/__tests__/history.test.ts +526 -0
  144. package/src/acp/__tests__/integration.test.ts +2 -1
  145. package/src/acp/index.ts +4 -0
  146. package/src/acp/macro-agent.ts +329 -85
  147. package/src/acp/types.ts +39 -2
  148. package/src/agent/__tests__/agent-manager.test.ts +67 -1
  149. package/src/agent/agent-manager.ts +10 -4
  150. package/src/cli/__tests__/stable-instance-id.test.ts +57 -0
  151. package/src/cli/acp.ts +17 -2
  152. package/src/map/adapter/acp-over-map.ts +57 -2
  153. package/src/store/event-store.ts +10 -3
  154. package/src/store/types/agents.ts +2 -0
@@ -0,0 +1,282 @@
1
+ ---
2
+ title: Simple Chat
3
+ parent: Examples
4
+ nav_order: 1
5
+ description: "Basic agent-to-agent messaging example"
6
+ ---
7
+
8
+ # Simple Chat
9
+ {: .no_toc }
10
+
11
+ A minimal example of agent-to-agent messaging.
12
+ {: .fs-6 .fw-300 }
13
+
14
+ ## Table of contents
15
+ {: .no_toc .text-delta }
16
+
17
+ 1. TOC
18
+ {:toc}
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ This example demonstrates:
25
+ - Setting up a MAP server
26
+ - Creating chat agents
27
+ - Sending messages between agents
28
+ - Subscribing to events
29
+
30
+ ---
31
+
32
+ ## Server
33
+
34
+ ```typescript
35
+ // server.ts
36
+ import { MAPServer } from "@multi-agent-protocol/sdk/server";
37
+ import { WebSocketServer } from "ws";
38
+
39
+ const server = new MAPServer({
40
+ name: "ChatServer",
41
+ version: "1.0.0",
42
+ });
43
+
44
+ // Log events
45
+ server.on("agent.registered", (event) => {
46
+ console.log(`[Server] Agent joined: ${event.data.agent.name}`);
47
+ });
48
+
49
+ server.on("agent.unregistered", (event) => {
50
+ console.log(`[Server] Agent left: ${event.data.agentId}`);
51
+ });
52
+
53
+ server.on("message.sent", (event) => {
54
+ console.log(`[Server] Message from ${event.data.from} to ${event.data.to}`);
55
+ });
56
+
57
+ // WebSocket server
58
+ const wss = new WebSocketServer({ port: 8080 });
59
+
60
+ wss.on("connection", (ws) => {
61
+ const stream = websocketToStream(ws);
62
+ server.accept(stream).start();
63
+ });
64
+
65
+ console.log("Chat server running on ws://localhost:8080");
66
+
67
+ // Helper function
68
+ function websocketToStream(ws) {
69
+ return {
70
+ readable: new ReadableStream({
71
+ start(controller) {
72
+ ws.on("message", (data) => {
73
+ controller.enqueue(JSON.parse(data.toString()));
74
+ });
75
+ ws.on("close", () => controller.close());
76
+ ws.on("error", (err) => controller.error(err));
77
+ },
78
+ }),
79
+ writable: new WritableStream({
80
+ write(message) {
81
+ ws.send(JSON.stringify(message));
82
+ },
83
+ close() {
84
+ ws.close();
85
+ },
86
+ }),
87
+ };
88
+ }
89
+ ```
90
+
91
+ ---
92
+
93
+ ## Chat Agent
94
+
95
+ ```typescript
96
+ // chat-agent.ts
97
+ import { AgentConnection } from "@multi-agent-protocol/sdk";
98
+ import WebSocket from "ws";
99
+ import * as readline from "readline";
100
+
101
+ async function main() {
102
+ const agentName = process.argv[2] || "Agent";
103
+
104
+ // Connect to server
105
+ const ws = new WebSocket("ws://localhost:8080");
106
+ await new Promise((resolve) => ws.on("open", resolve));
107
+
108
+ const stream = websocketToStream(ws);
109
+
110
+ // Create agent
111
+ const agent = new AgentConnection(stream, {
112
+ name: agentName,
113
+ role: "chatter",
114
+ });
115
+
116
+ // Handle incoming messages
117
+ agent.onMessage((message) => {
118
+ console.log(`\n[${message.from}]: ${message.payload.text}`);
119
+ rl.prompt();
120
+ });
121
+
122
+ // Connect
123
+ const { agent: registered } = await agent.connect();
124
+ console.log(`Connected as ${registered.name} (${registered.id})`);
125
+
126
+ // List other agents
127
+ const { agents } = await agent.listAgents();
128
+ const others = agents.filter((a) => a.id !== registered.id);
129
+
130
+ if (others.length > 0) {
131
+ console.log("Other agents online:");
132
+ others.forEach((a) => console.log(` - ${a.name} (${a.id})`));
133
+ } else {
134
+ console.log("No other agents online yet.");
135
+ }
136
+
137
+ // Set up readline for input
138
+ const rl = readline.createInterface({
139
+ input: process.stdin,
140
+ output: process.stdout,
141
+ });
142
+
143
+ console.log('\nType messages to send. Use "@name message" to send to specific agent.');
144
+ console.log('Type "list" to see online agents, "quit" to exit.\n');
145
+
146
+ rl.prompt();
147
+
148
+ rl.on("line", async (input) => {
149
+ const trimmed = input.trim();
150
+
151
+ if (trimmed === "quit") {
152
+ await agent.disconnect();
153
+ process.exit(0);
154
+ }
155
+
156
+ if (trimmed === "list") {
157
+ const { agents } = await agent.listAgents();
158
+ const others = agents.filter((a) => a.id !== registered.id);
159
+ console.log("Agents online:");
160
+ others.forEach((a) => console.log(` - ${a.name} (${a.id})`));
161
+ rl.prompt();
162
+ return;
163
+ }
164
+
165
+ // Parse @name message format
166
+ const match = trimmed.match(/^@(\S+)\s+(.+)$/);
167
+ if (match) {
168
+ const [, targetName, text] = match;
169
+
170
+ // Find agent by name
171
+ const { agents } = await agent.listAgents();
172
+ const target = agents.find(
173
+ (a) => a.name.toLowerCase() === targetName.toLowerCase()
174
+ );
175
+
176
+ if (target) {
177
+ await agent.send({
178
+ to: { agentId: target.id },
179
+ payload: { text },
180
+ });
181
+ console.log(`[You → ${target.name}]: ${text}`);
182
+ } else {
183
+ console.log(`Agent "${targetName}" not found.`);
184
+ }
185
+ } else if (trimmed) {
186
+ // Broadcast to all agents
187
+ const { agents } = await agent.listAgents();
188
+ const others = agents.filter((a) => a.id !== registered.id);
189
+
190
+ for (const other of others) {
191
+ await agent.send({
192
+ to: { agentId: other.id },
193
+ payload: { text: trimmed },
194
+ });
195
+ }
196
+ console.log(`[You → all]: ${trimmed}`);
197
+ }
198
+
199
+ rl.prompt();
200
+ });
201
+ }
202
+
203
+ main().catch(console.error);
204
+ ```
205
+
206
+ ---
207
+
208
+ ## Running the Example
209
+
210
+ 1. Start the server:
211
+
212
+ ```bash
213
+ npx ts-node server.ts
214
+ ```
215
+
216
+ 2. In separate terminals, start multiple chat agents:
217
+
218
+ ```bash
219
+ # Terminal 2
220
+ npx ts-node chat-agent.ts Alice
221
+
222
+ # Terminal 3
223
+ npx ts-node chat-agent.ts Bob
224
+ ```
225
+
226
+ 3. Type messages in each terminal:
227
+
228
+ ```
229
+ # Alice's terminal
230
+ > Hello everyone!
231
+ [You → all]: Hello everyone!
232
+
233
+ # Bob's terminal
234
+ [Alice]: Hello everyone!
235
+ > @Alice Hi Alice!
236
+ [You → Alice]: Hi Alice!
237
+ ```
238
+
239
+ ---
240
+
241
+ ## Key Concepts Demonstrated
242
+
243
+ ### Agent Registration
244
+
245
+ ```typescript
246
+ const agent = new AgentConnection(stream, {
247
+ name: agentName,
248
+ role: "chatter",
249
+ });
250
+
251
+ await agent.connect();
252
+ ```
253
+
254
+ ### Message Handling
255
+
256
+ ```typescript
257
+ agent.onMessage((message) => {
258
+ console.log(`[${message.from}]: ${message.payload.text}`);
259
+ });
260
+ ```
261
+
262
+ ### Agent Discovery
263
+
264
+ ```typescript
265
+ const { agents } = await agent.listAgents();
266
+ ```
267
+
268
+ ### Direct Messaging
269
+
270
+ ```typescript
271
+ await agent.send({
272
+ to: { agentId: target.id },
273
+ payload: { text: "Hello!" },
274
+ });
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Next Steps
280
+
281
+ - [Task Queue](./task-queue.html) - Work distribution with scopes
282
+ - [Full Integration](./full-integration.html) - Complete application
@@ -0,0 +1,399 @@
1
+ ---
2
+ title: Task Queue
3
+ parent: Examples
4
+ nav_order: 2
5
+ description: "Work distribution with scopes"
6
+ ---
7
+
8
+ # Task Queue
9
+ {: .no_toc }
10
+
11
+ Distribute work to agents using scopes.
12
+ {: .fs-6 .fw-300 }
13
+
14
+ ## Table of contents
15
+ {: .no_toc .text-delta }
16
+
17
+ 1. TOC
18
+ {:toc}
19
+
20
+ ---
21
+
22
+ ## Overview
23
+
24
+ This example demonstrates:
25
+ - Creating scopes for work distribution
26
+ - Coordinator pattern for task assignment
27
+ - Worker agents processing tasks
28
+ - Client submitting and monitoring work
29
+
30
+ ---
31
+
32
+ ## Architecture
33
+
34
+ ```mermaid
35
+ flowchart TB
36
+ Client["Client<br/>(submits tasks)"]
37
+ Coord["Coordinator<br/>(assigns to workers)"]
38
+ W1["Worker 1<br/>(scope)"]
39
+ W2["Worker 2<br/>(scope)"]
40
+ W3["Worker 3<br/>(scope)"]
41
+
42
+ Client --> Coord
43
+ Coord --> W1
44
+ Coord --> W2
45
+ Coord --> W3
46
+ ```
47
+
48
+ ---
49
+
50
+ ## Server
51
+
52
+ ```typescript
53
+ // server.ts
54
+ import { MAPServer } from "@multi-agent-protocol/sdk/server";
55
+ import { WebSocketServer } from "ws";
56
+
57
+ const server = new MAPServer({
58
+ name: "TaskQueueServer",
59
+ version: "1.0.0",
60
+ });
61
+
62
+ const wss = new WebSocketServer({ port: 8080 });
63
+
64
+ wss.on("connection", (ws) => {
65
+ server.accept(websocketToStream(ws)).start();
66
+ });
67
+
68
+ console.log("Task queue server running on ws://localhost:8080");
69
+ ```
70
+
71
+ ---
72
+
73
+ ## Coordinator
74
+
75
+ ```typescript
76
+ // coordinator.ts
77
+ import { AgentConnection } from "@multi-agent-protocol/sdk";
78
+ import WebSocket from "ws";
79
+
80
+ async function main() {
81
+ const ws = new WebSocket("ws://localhost:8080");
82
+ await new Promise((resolve) => ws.on("open", resolve));
83
+
84
+ const agent = new AgentConnection(websocketToStream(ws), {
85
+ name: "Coordinator",
86
+ role: "coordinator",
87
+ });
88
+
89
+ const { agent: registered } = await agent.connect();
90
+ console.log(`Coordinator registered: ${registered.id}`);
91
+
92
+ // Create task queue scope
93
+ const taskQueue = await agent.createScope({
94
+ name: "task-queue",
95
+ metadata: { type: "work-distribution" },
96
+ });
97
+ console.log(`Created task queue scope: ${taskQueue.id}`);
98
+
99
+ // Track workers and their state
100
+ const workers = new Map<string, { agentId: string; busy: boolean }>();
101
+ const pendingTasks: any[] = [];
102
+
103
+ // Subscribe to worker events
104
+ const subscription = await agent.subscribe({
105
+ eventTypes: ["scope.joined", "scope.left", "agent.unregistered"],
106
+ });
107
+
108
+ // Process events in background
109
+ (async () => {
110
+ for await (const event of subscription) {
111
+ if (event.type === "scope.joined" && event.data.scopeId === taskQueue.id) {
112
+ const { agentId } = event.data;
113
+ if (agentId !== registered.id) {
114
+ workers.set(agentId, { agentId, busy: false });
115
+ console.log(`Worker joined: ${agentId}`);
116
+ // Try to assign pending tasks
117
+ assignPendingTasks();
118
+ }
119
+ }
120
+
121
+ if (event.type === "scope.left" && event.data.scopeId === taskQueue.id) {
122
+ workers.delete(event.data.agentId);
123
+ console.log(`Worker left: ${event.data.agentId}`);
124
+ }
125
+
126
+ if (event.type === "agent.unregistered") {
127
+ workers.delete(event.data.agentId);
128
+ }
129
+ }
130
+ })();
131
+
132
+ // Handle incoming messages
133
+ agent.onMessage(async (message) => {
134
+ const { type } = message.payload;
135
+
136
+ if (type === "submit-task") {
137
+ const task = {
138
+ id: `task-${Date.now()}`,
139
+ ...message.payload.task,
140
+ submitter: message.from,
141
+ };
142
+
143
+ console.log(`Received task: ${task.id}`);
144
+
145
+ // Find available worker
146
+ const available = [...workers.values()].find((w) => !w.busy);
147
+
148
+ if (available) {
149
+ assignTask(task, available.agentId);
150
+ } else {
151
+ pendingTasks.push(task);
152
+ console.log(`Task ${task.id} queued (${pendingTasks.length} pending)`);
153
+ }
154
+ }
155
+
156
+ if (type === "task-complete") {
157
+ const { taskId, result, success } = message.payload;
158
+ const worker = workers.get(message.from);
159
+
160
+ if (worker) {
161
+ worker.busy = false;
162
+ }
163
+
164
+ console.log(`Task ${taskId} completed: ${success ? "success" : "failed"}`);
165
+
166
+ // Notify submitter
167
+ // ... forward result to original submitter
168
+
169
+ // Assign pending tasks
170
+ assignPendingTasks();
171
+ }
172
+ });
173
+
174
+ async function assignTask(task: any, workerId: string) {
175
+ const worker = workers.get(workerId);
176
+ if (worker) {
177
+ worker.busy = true;
178
+ }
179
+
180
+ await agent.send({
181
+ to: { agentId: workerId },
182
+ payload: {
183
+ type: "task",
184
+ task,
185
+ },
186
+ });
187
+
188
+ console.log(`Assigned task ${task.id} to ${workerId}`);
189
+ }
190
+
191
+ function assignPendingTasks() {
192
+ while (pendingTasks.length > 0) {
193
+ const available = [...workers.values()].find((w) => !w.busy);
194
+ if (!available) break;
195
+
196
+ const task = pendingTasks.shift()!;
197
+ assignTask(task, available.agentId);
198
+ }
199
+ }
200
+
201
+ console.log("Coordinator ready. Waiting for workers and tasks...");
202
+ }
203
+
204
+ main().catch(console.error);
205
+ ```
206
+
207
+ ---
208
+
209
+ ## Worker
210
+
211
+ ```typescript
212
+ // worker.ts
213
+ import { AgentConnection } from "@multi-agent-protocol/sdk";
214
+ import WebSocket from "ws";
215
+
216
+ async function main() {
217
+ const workerId = process.argv[2] || `Worker-${Math.random().toString(36).slice(2, 6)}`;
218
+
219
+ const ws = new WebSocket("ws://localhost:8080");
220
+ await new Promise((resolve) => ws.on("open", resolve));
221
+
222
+ const agent = new AgentConnection(websocketToStream(ws), {
223
+ name: workerId,
224
+ role: "worker",
225
+ });
226
+
227
+ const { agent: registered } = await agent.connect();
228
+ console.log(`Worker registered: ${registered.id}`);
229
+
230
+ // Find and join task queue
231
+ const { scopes } = await agent.listScopes();
232
+ const taskQueue = scopes.find((s) => s.name === "task-queue");
233
+
234
+ if (taskQueue) {
235
+ await agent.joinScope(taskQueue.id);
236
+ console.log("Joined task queue");
237
+ } else {
238
+ console.log("Task queue not found. Waiting for coordinator...");
239
+
240
+ // Subscribe to scope creation
241
+ const sub = await agent.subscribe({ eventTypes: ["scope.created"] });
242
+ for await (const event of sub) {
243
+ if (event.data.scope.name === "task-queue") {
244
+ await agent.joinScope(event.data.scope.id);
245
+ console.log("Joined task queue");
246
+ await sub.unsubscribe();
247
+ break;
248
+ }
249
+ }
250
+ }
251
+
252
+ // Handle tasks
253
+ agent.onMessage(async (message) => {
254
+ if (message.payload.type === "task") {
255
+ const { task } = message.payload;
256
+ console.log(`Processing task: ${task.id}`);
257
+
258
+ await agent.update({ state: "busy" });
259
+
260
+ try {
261
+ // Simulate work
262
+ await new Promise((r) => setTimeout(r, 2000 + Math.random() * 3000));
263
+
264
+ // Send result
265
+ await agent.send({
266
+ to: { agentId: message.from },
267
+ payload: {
268
+ type: "task-complete",
269
+ taskId: task.id,
270
+ success: true,
271
+ result: { processed: true },
272
+ },
273
+ });
274
+
275
+ console.log(`Completed task: ${task.id}`);
276
+ } catch (error) {
277
+ await agent.send({
278
+ to: { agentId: message.from },
279
+ payload: {
280
+ type: "task-complete",
281
+ taskId: task.id,
282
+ success: false,
283
+ error: error.message,
284
+ },
285
+ });
286
+ }
287
+
288
+ await agent.update({ state: "running" });
289
+ }
290
+ });
291
+
292
+ console.log("Worker ready. Waiting for tasks...");
293
+ }
294
+
295
+ main().catch(console.error);
296
+ ```
297
+
298
+ ---
299
+
300
+ ## Client
301
+
302
+ ```typescript
303
+ // client.ts
304
+ import { ClientConnection } from "@multi-agent-protocol/sdk";
305
+ import WebSocket from "ws";
306
+
307
+ async function main() {
308
+ const ws = new WebSocket("ws://localhost:8080");
309
+ await new Promise((resolve) => ws.on("open", resolve));
310
+
311
+ const client = new ClientConnection(websocketToStream(ws), {
312
+ name: "TaskSubmitter",
313
+ });
314
+
315
+ await client.connect();
316
+ console.log("Connected to task queue server");
317
+
318
+ // Find coordinator
319
+ const { agents } = await client.listAgents({ role: "coordinator" });
320
+
321
+ if (agents.length === 0) {
322
+ console.log("No coordinator found. Please start the coordinator first.");
323
+ return;
324
+ }
325
+
326
+ const coordinator = agents[0];
327
+ console.log(`Found coordinator: ${coordinator.id}`);
328
+
329
+ // Submit some tasks
330
+ for (let i = 1; i <= 5; i++) {
331
+ await client.send({
332
+ to: { agentId: coordinator.id },
333
+ payload: {
334
+ type: "submit-task",
335
+ task: {
336
+ name: `Task ${i}`,
337
+ data: { value: i * 10 },
338
+ },
339
+ },
340
+ });
341
+
342
+ console.log(`Submitted task ${i}`);
343
+ await new Promise((r) => setTimeout(r, 500));
344
+ }
345
+
346
+ console.log("All tasks submitted. Monitoring...");
347
+
348
+ // Subscribe to events
349
+ const subscription = await client.subscribe({
350
+ eventTypes: ["agent.*"],
351
+ });
352
+
353
+ for await (const event of subscription) {
354
+ console.log(`Event: ${event.type}`);
355
+ }
356
+ }
357
+
358
+ main().catch(console.error);
359
+ ```
360
+
361
+ ---
362
+
363
+ ## Running the Example
364
+
365
+ 1. Start the server:
366
+ ```bash
367
+ npx ts-node server.ts
368
+ ```
369
+
370
+ 2. Start the coordinator:
371
+ ```bash
372
+ npx ts-node coordinator.ts
373
+ ```
374
+
375
+ 3. Start some workers:
376
+ ```bash
377
+ npx ts-node worker.ts Worker1
378
+ npx ts-node worker.ts Worker2
379
+ ```
380
+
381
+ 4. Submit tasks:
382
+ ```bash
383
+ npx ts-node client.ts
384
+ ```
385
+
386
+ ---
387
+
388
+ ## Key Concepts Demonstrated
389
+
390
+ - **Scopes** for grouping related agents
391
+ - **Coordinator pattern** for task distribution
392
+ - **Worker pool** with busy/available tracking
393
+ - **Message passing** for task assignment and completion
394
+
395
+ ---
396
+
397
+ ## Next Steps
398
+
399
+ - [Full Integration](./full-integration.html) - Complete application with all concepts