@stdiobus/workers-registry 1.3.19 → 1.3.21

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
@@ -1,4 +1,4 @@
1
- # @stdiobus/workers-registry
1
+ # stdio Bus – Worker Registry
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@stdiobus/workers-registry.svg)](https://www.npmjs.com/package/@stdiobus/workers-registry)
4
4
  [![License](https://img.shields.io/npm/l/@stdiobus/workers-registry.svg)](https://github.com/stdiobus/workers-registry/blob/main/LICENSE)
@@ -39,7 +39,7 @@ stdio Bus kernel provides the core protocol and message routing infrastructure.
39
39
  graph TB
40
40
  Client[Client Application] -->|TCP/Unix Socket| Kernel[stdio Bus kernel]
41
41
  Kernel -->|NDJSON stdin/stdout| ACP[ACP Worker]
42
- Kernel -->|NDJSON stdin/stdout| Registry[Registry Launcher]
42
+ Kernel -->|NDJSON stdin/stdout| Registry[ACP Registry Worker – acp-registry]
43
43
  Kernel -->|NDJSON stdin/stdout| Echo[Echo Worker]
44
44
  Kernel -->|NDJSON stdin/stdout| Proxy[MCP-to-ACP Proxy]
45
45
 
@@ -59,17 +59,6 @@ graph TB
59
59
  style Proxy fill:#e67e22,stroke:#a04000,stroke-width:2px,color:#fff
60
60
  ```
61
61
 
62
- **Architecture layers:**
63
- ```
64
- stdio Bus kernel ← https://github.com/stdiobus/stdiobus
65
- ↓ (spawns workers via stdin/stdout NDJSON)
66
- Workers Registry (this repo)
67
- ├── ACP Worker (Agent Client Protocol)
68
- ├── Registry Launcher (ACP Registry integration)
69
- ├── MCP-to-ACP Proxy (protocol bridge)
70
- └── Echo Worker (testing/examples)
71
- ```
72
-
73
62
  ## Prerequisites
74
63
 
75
64
  - stdio Bus kernel - available via [Docker](https://hub.docker.com/r/stdiobus/stdiobus) or [build from source](https://github.com/stdiobus/stdiobus)
@@ -79,11 +68,15 @@ Workers Registry (this repo)
79
68
 
80
69
  | Worker | Description | Protocol | Command |
81
70
  |--------|-------------|----------|---------|
82
- | `acp-worker` | Full ACP protocol implementation using official SDK | ACP | `stdiobus-acp-worker` |
83
- | `registry-launcher` | Routes messages to any agent in the ACP Registry | ACP | `stdiobus-registry-launcher` |
84
- | `mcp-to-acp-proxy` | Bridges MCP clients (like IDEs) to ACP agents | MCP ACP | `stdiobus-mcp-to-acp-proxy` |
85
- | `echo-worker` | Simple echo worker for testing NDJSON protocol | NDJSON | `stdiobus-echo-worker` |
86
- | `mcp-echo-server` | MCP server example for testing | MCP | `stdiobus-mcp-echo-server` |
71
+ | `acp-registry` | Registry Launcher worker that routes to ACP Registry agents (requires `api-keys.json`) | ACP | `node ./node_modules/@stdiobus/workers-registry/launch acp-registry` |
72
+ | `acp-worker` | Full ACP protocol implementation (standalone agent; does **not** route to ACP Registry) | ACP | `node ./node_modules/@stdiobus/workers-registry/launch acp-worker` |
73
+ | `registry-launcher` | Registry Launcher implementation module used by `acp-registry` (not a launch target) | ACP | Use `acp-registry` |
74
+ | `mcp-to-acp-proxy` | Bridges MCP clients (like IDEs) to ACP agents | MCP → ACP | `node ./node_modules/@stdiobus/workers-registry/launch mcp-to-acp-proxy` |
75
+ | `echo-worker` | Simple echo worker for testing NDJSON protocol | NDJSON | `node ./node_modules/@stdiobus/workers-registry/launch echo-worker` |
76
+ | `mcp-echo-server` | MCP server example for testing | MCP | `node ./node_modules/@stdiobus/workers-registry/launch mcp-echo-server` |
77
+
78
+ **Note:** The universal launcher is `@stdiobus/workers-registry/launch`. In this repo, use
79
+ `node ./launch/index.js <worker-name>` after `npm run build`.
87
80
 
88
81
  ## Package API
89
82
 
@@ -104,6 +97,9 @@ import { workers } from '@stdiobus/workers-registry/workers';
104
97
  console.log(workers['acp-worker'].entrypoint);
105
98
  ```
106
99
 
100
+ **Note:** `acp-registry` is a worker runtime launched via
101
+ `@stdiobus/workers-registry/launch` and is not exported as a module.
102
+
107
103
  ### TypeScript Support
108
104
 
109
105
  Full TypeScript definitions are included:
@@ -133,7 +129,36 @@ docker pull stdiobus/stdiobus:latest
133
129
 
134
130
  See [stdio Bus kernel repository](https://github.com/stdiobus/stdiobus) for build instructions.
135
131
 
136
- ### 3. Run with ACP Worker
132
+ ### 3. Run with ACP Registry (recommended for real agents)
133
+
134
+ **Create config.json:**
135
+ ```json
136
+ {
137
+ "pools": [
138
+ {
139
+ "id": "acp-registry",
140
+ "command": "node",
141
+ "args": [
142
+ "./stdiobus/node_modules/@stdiobus/workers-registry/launch",
143
+ "acp-registry"
144
+ ],
145
+ "instances": 1
146
+ }
147
+ ]
148
+ }
149
+ ```
150
+
151
+ **Important:** Place `api-keys.json` next to your stdio Bus config (working directory),
152
+ or pass a custom config file (third arg to `launch acp-registry`) with an absolute
153
+ `apiKeysPath`. In this repo, the default file is
154
+ `workers-registry/acp-registry/acp-registry-config.json`.
155
+ Use the same Docker/binary commands below (they run `config.json`), and ensure
156
+ `api-keys.json` is mounted into the container when using Docker.
157
+
158
+ ### 4. Run with ACP Worker
159
+
160
+ **Note:** `acp-worker` is a standalone ACP agent for SDK/protocol testing. It does **not**
161
+ route to the ACP Registry. Use `acp-registry` when you need real registry agents.
137
162
 
138
163
  **Create config.json:**
139
164
  ```json
@@ -169,7 +194,11 @@ docker run -p 9000:9000 \
169
194
  ### 5. Test Connection
170
195
 
171
196
  ```bash
197
+ # ACP worker (standalone)
172
198
  echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"clientInfo":{"name":"test","version":"1.0"}}}' | nc localhost 9000
199
+
200
+ # ACP Registry worker (route to a registry agent)
201
+ echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"agentId":"claude-acp","clientInfo":{"name":"test","version":"1.0"}}}' | nc localhost 9000
173
202
  ```
174
203
 
175
204
  ---
@@ -181,18 +210,21 @@ echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"clientInfo":{"n
181
210
  The simplest way to run any worker:
182
211
 
183
212
  ```bash
184
- # Run any worker by name
185
- node ./node_modules/@stdiobus/workers-registry/out/dist/index.js <worker-name>
213
+ # Run any worker by name (package install)
214
+ node ./node_modules/@stdiobus/workers-registry/launch <worker-name>
215
+
216
+ # Run any worker by name (this repo, after build)
217
+ node ./launch/index.js <worker-name>
186
218
 
187
219
  # Available workers:
220
+ # - acp-registry
188
221
  # - acp-worker
189
- # - acp-registry
190
222
  # - echo-worker
191
223
  # - mcp-echo-server
192
224
  # - mcp-to-acp-proxy
193
225
 
194
226
  # Example: Run echo worker for testing
195
- node ./node_modules/@stdiobus/workers-registry/out/dist/index.js echo-worker
227
+ node ./node_modules/@stdiobus/workers-registry/launch echo-worker
196
228
  ```
197
229
 
198
230
  ### Using in stdio Bus Configuration
@@ -212,23 +244,25 @@ node ./node_modules/@stdiobus/workers-registry/out/dist/index.js echo-worker
212
244
  }
213
245
  ```
214
246
 
215
- **Registry Launcher with API Keys:**
247
+ **ACP Registry Worker with API Keys:**
216
248
  ```json
217
249
  {
218
250
  "pools": [
219
251
  {
220
- "id": "registry-launcher",
252
+ "id": "acp-registry",
221
253
  "command": "node",
222
254
  "args": [
223
255
  "./stdiobus/node_modules/@stdiobus/workers-registry/launch",
224
- "registry-launcher",
225
- "./api-keys.json"
256
+ "acp-registry"
226
257
  ],
227
258
  "instances": 1
228
259
  }
229
260
  ]
230
261
  }
231
262
  ```
263
+ **Note:** `acp-registry` reads `api-keys.json` via its config. The default
264
+ `apiKeysPath` is `./api-keys.json`. You can pass a custom config file as the third
265
+ arg to `launch acp-registry`.
232
266
 
233
267
  **Multiple Workers:**
234
268
  ```json
@@ -264,7 +298,11 @@ Configure MCP-to-ACP Proxy in Kiro's MCP settings:
264
298
  {
265
299
  "mcpServers": {
266
300
  "stdio-bus-acp": {
267
- "command": "stdiobus-mcp-to-acp-proxy",
301
+ "command": "node",
302
+ "args": [
303
+ "./node_modules/@stdiobus/workers-registry/launch",
304
+ "mcp-to-acp-proxy"
305
+ ],
268
306
  "env": {
269
307
  "ACP_HOST": "localhost",
270
308
  "ACP_PORT": "9000",
@@ -275,6 +313,9 @@ Configure MCP-to-ACP Proxy in Kiro's MCP settings:
275
313
  }
276
314
  ```
277
315
 
316
+ **Note:** Run `acp-registry` on the stdio Bus side so `AGENT_ID` resolves to real
317
+ ACP Registry agents. `acp-worker` is a standalone agent and will not route to the registry.
318
+
278
319
  ---
279
320
 
280
321
  ## Worker Documentation
@@ -320,11 +361,13 @@ Using binary:
320
361
 
321
362
  ---
322
363
 
323
- ### Registry Launcher
364
+ ### ACP Registry Worker (acp-registry)
324
365
 
325
366
  Routes messages to any agent in the [ACP Registry](https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json).
326
367
 
327
- **Location:** `workers-registry/acp-worker/src/registry-launcher/`
368
+ **Location (worker entrypoint):** `workers-registry/acp-registry/`
369
+
370
+ **Implementation:** `workers-registry/acp-worker/src/registry-launcher/`
328
371
 
329
372
  **Features:**
330
373
  - Automatic agent discovery from ACP Registry
@@ -344,18 +387,21 @@ Routes messages to any agent in the [ACP Registry](https://cdn.agentclientprotoc
344
387
  {
345
388
  "pools": [
346
389
  {
347
- "id": "registry-launcher",
390
+ "id": "acp-registry",
348
391
  "command": "node",
349
392
  "args": [
350
393
  "./stdiobus/node_modules/@stdiobus/workers-registry/launch",
351
- "registry-launcher",
352
- "./api-keys.json"
394
+ "acp-registry"
353
395
  ],
354
396
  "instances": 1
355
397
  }
356
398
  ]
357
399
  }
358
400
  ```
401
+ **Note:** `acp-registry` uses its default config when no path is provided. You can
402
+ pass a custom config file as the third arg to `launch acp-registry`. The default
403
+ file in this repo is `workers-registry/acp-registry/acp-registry-config.json`, which
404
+ expects `api-keys.json` at `./api-keys.json` unless you override `apiKeysPath`.
359
405
 
360
406
  **Run:**
361
407
 
@@ -365,7 +411,7 @@ docker run \
365
411
  --name stdiobus-registry \
366
412
  -p 9000:9000 \
367
413
  -v $(pwd):/stdiobus:ro \
368
- -v $(pwd)/workers-registry/acp-registry/registry-launcher-config.json:/config.json:ro \
414
+ -v $(pwd)/workers-registry/acp-registry/acp-registry-config.json:/config.json:ro \
369
415
  -v $(pwd)/api-keys.json:/api-keys.json:ro \
370
416
  stdiobus/stdiobus:latest \
371
417
  --config /config.json --tcp 0.0.0.0:9000
@@ -373,7 +419,7 @@ docker run \
373
419
 
374
420
  Using binary:
375
421
  ```bash
376
- ./stdio_bus --config workers-registry/acp-registry/registry-launcher-config.json --tcp 0.0.0.0:9000
422
+ ./stdio_bus --config workers-registry/acp-registry/acp-registry-config.json --tcp 0.0.0.0:9000
377
423
  ```
378
424
 
379
425
  ---
@@ -386,7 +432,7 @@ Bridges MCP clients (like IDE) to ACP agents through stdio Bus.
386
432
 
387
433
  **Architecture:**
388
434
  ```
389
- IDE (MCP Client) → MCP-to-ACP Proxy → stdio Bus → Registry Launcher → ACP Agent
435
+ IDE (MCP Client) → MCP-to-ACP Proxy → stdio Bus → ACP Registry Worker (acp-registry) → ACP Agent
390
436
  ```
391
437
 
392
438
  **Configuration for IDE:**
@@ -691,14 +737,14 @@ echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"clientInfo":{"n
691
737
  docker stop stdiobus-acp-test && docker rm stdiobus-acp-test
692
738
  ```
693
739
 
694
- **Test Registry Launcher:**
740
+ **Test ACP Registry Worker – acp-registry:**
695
741
  ```bash
696
- # Start stdio Bus with Registry Launcher
742
+ # Start stdio Bus with ACP Registry worker
697
743
  docker run \
698
744
  --name stdiobus-registry-test \
699
745
  -p 9000:9000 \
700
746
  -v $(pwd):/stdiobus:ro \
701
- -v $(pwd)/workers-registry/acp-registry/registry-launcher-config.json:/config.json:ro \
747
+ -v $(pwd)/workers-registry/acp-registry/acp-registry-config.json:/config.json:ro \
702
748
  -v $(pwd)/api-keys.json:/api-keys.json:ro \
703
749
  stdiobus/stdiobus:latest \
704
750
  --config /config.json --tcp 0.0.0.0:9000
@@ -776,7 +822,7 @@ workers-registry/
776
822
  │ │ ├── session/ # Session management
777
823
  │ │ └── registry-launcher/ # Registry Launcher implementation
778
824
  │ └── tests/ # Test suites
779
- ├── acp-registry/ # Registry Launcher configs
825
+ ├── acp-registry/ # ACP Registry worker entrypoint + configs
780
826
  ├── echo-worker/ # Simple echo worker example
781
827
  ├── mcp-echo-server/ # MCP server example
782
828
  └── mcp-to-acp-proxy/ # MCP-to-ACP protocol bridge
@@ -838,8 +884,8 @@ nvm install 20 # If using nvm
838
884
  **Permission errors:**
839
885
  ```bash
840
886
  npm install -g @stdiobus/workers-registry # Global install (may need sudo)
841
- # Or use npx
842
- npx stdiobus-acp-worker
887
+ # Or use a local install
888
+ node ./node_modules/@stdiobus/workers-registry/launch acp-worker
843
889
  ```
844
890
 
845
891
  ### Runtime Issues
@@ -917,7 +963,7 @@ npm test
917
963
  ## Worker Documentation
918
964
 
919
965
  - [ACP Worker](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/acp-worker) - Full ACP protocol implementation
920
- - [Registry Launcher](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/acp-registry) - ACP Registry integration
966
+ - [ACP Registry Worker (acp-registry)](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/acp-registry) - ACP Registry integration
921
967
  - [Echo Worker](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/echo-worker) - Reference implementation
922
968
  - [MCP Echo Server](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/mcp-echo-server) - MCP server example
923
969
  - [MCP-to-ACP Proxy](https://github.com/stdiobus/workers-registry/tree/main/workers-registry/mcp-to-acp-proxy) - Protocol bridge
@@ -0,0 +1 @@
1
+ # Workers launcher
package/launch/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import{fileURLToPath}from"url";import{dirname,join}from"path";import{readFile}from"fs/promises";var __filename=fileURLToPath(import.meta.url);var __dirname=dirname(__filename);var STDIO_BUS_WORKERS={"acp-worker":{path:"../out/dist/workers-registry/acp-worker/index.js",description:"Full ACP protocol implementation with MCP integration"},"acp-registry":{path:"../out/dist/workers-registry/acp-registry/registry-launcher-client.js",description:"Registry Launcher for ACP Registry agents"},"echo-worker":{path:"../out/dist/workers-registry/echo-worker/echo-worker.js",description:"Simple echo worker for testing NDJSON protocol"},"mcp-echo-server":{path:"../out/dist/workers-registry/mcp-echo-server/index.js",description:"MCP server example for testing"},"mcp-to-acp-proxy":{path:"../out/dist/workers-registry/mcp-to-acp-proxy/proxy.js",description:"MCP-to-ACP protocol bridge"}};function showUsage(){console.error("Usage: node index.js <worker-name>");console.error("");console.error("Available workers:");for(const[name,config]of Object.entries(STDIO_BUS_WORKERS)){console.error(` - ${name.padEnd(20)} ${config.description}`)}console.error("");console.error("Examples:");console.error(" node index.js acp-worker");console.error(" node index.js echo-worker");console.error(" node index.js mcp-echo-server")}function isValidWorkerName(name){return name in STDIO_BUS_WORKERS}async function main(){const workerName=process.argv[2];if(!workerName){console.error("Error: Worker name is required\n");showUsage();process.exit(1)}if(!isValidWorkerName(workerName)){console.error(`Error: Unknown worker "${workerName}"
2
+ import{fileURLToPath}from"url";import{dirname,join}from"path";import{readFile}from"fs/promises";var __filename=fileURLToPath(import.meta.url);var __dirname=dirname(__filename);var STDIO_BUS_WORKERS={"acp-worker":{path:"../out/dist/workers-registry/acp-worker/index.js",description:"Full ACP protocol implementation with MCP integration"},"acp-registry":{path:"../out/dist/workers-registry/acp-registry/index.js",description:"Registry Launcher worker for ACP Registry agents"},"echo-worker":{path:"../out/dist/workers-registry/echo-worker/echo-worker.js",description:"Simple echo worker for testing NDJSON protocol"},"mcp-echo-server":{path:"../out/dist/workers-registry/mcp-echo-server/index.js",description:"MCP server example for testing"},"mcp-to-acp-proxy":{path:"../out/dist/workers-registry/mcp-to-acp-proxy/proxy.js",description:"MCP-to-ACP protocol bridge"}};function showUsage(){console.error("Usage: node index.js <worker-name>");console.error("");console.error("Available workers:");for(const[name,config]of Object.entries(STDIO_BUS_WORKERS)){console.error(` - ${name.padEnd(20)} ${config.description}`)}console.error("");console.error("Examples:");console.error(" node index.js acp-worker");console.error(" node index.js echo-worker");console.error(" node index.js mcp-echo-server")}function isValidWorkerName(name){return name in STDIO_BUS_WORKERS}async function main(){const workerName=process.argv[2];if(!workerName){console.error("Error: Worker name is required\n");showUsage();process.exit(1)}if(!isValidWorkerName(workerName)){console.error(`Error: Unknown worker "${workerName}"
3
3
  `);showUsage();process.exit(1)}const workerConfig=STDIO_BUS_WORKERS[workerName];const workerPath=workerConfig.path;const absolutePath=join(__dirname,workerPath);try{await readFile(absolutePath);console.error(`[launcher] Starting worker: ${workerName}`);console.error(`[launcher] Description: ${workerConfig.description}`);console.error(`[launcher] Path: ${absolutePath}`);await import(absolutePath)}catch(error){if(error&&typeof error==="object"&&"code"in error&&error.code==="ENOENT"){console.error(`Error: Worker file not found: ${absolutePath}`);console.error("");console.error('Please run "npm run build" first to compile the workers.');process.exit(1)}const errorMessage=error instanceof Error?error.message:String(error);const errorStack=error instanceof Error?error.stack:void 0;console.error(`Error loading worker "${workerName}":`,errorMessage);if(errorStack){console.error(errorStack)}process.exit(1)}}main().catch(error=>{console.error("Fatal error:",error);process.exit(1)});export{STDIO_BUS_WORKERS,isValidWorkerName,main as launch,showUsage};
4
4
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../workers-registry/launch/index.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n\n/*\n * Apache License 2.0\n * Copyright (c) 2025\u2013present Raman Marozau, Target Insight Function.\n * Contact: raman@worktif.com\n *\n * This file is part of the stdio bus protocol reference implementation:\n * stdio_bus_kernel_workers (target: <target_stdio_bus_kernel_workers>).\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Universal worker launcher for stdio Bus Workers Registry\n *\n * Usage:\n * node index.js <worker-name>\n * node index.js acp-worker\n * node index.js echo-worker\n * node index.js mcp-echo-server\n *\n * This script dynamically imports and runs the specified worker from the compiled output.\n */\n\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { readFile } from 'fs/promises';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Worker configuration mapping worker names to their entry points\n */\ninterface WorkerConfig {\n readonly path: string;\n readonly description: string;\n}\n\n/**\n * Available workers mapping\n */\nconst STDIO_BUS_WORKERS: Readonly<Record<string, WorkerConfig>> = {\n 'acp-worker': {\n path: '../out/dist/workers-registry/acp-worker/index.js',\n description: 'Full ACP protocol implementation with MCP integration'\n },\n 'acp-registry': {\n path: '../out/dist/workers-registry/acp-registry/registry-launcher-client.js',\n description: 'Registry Launcher for ACP Registry agents'\n },\n 'echo-worker': {\n path: '../out/dist/workers-registry/echo-worker/echo-worker.js',\n description: 'Simple echo worker for testing NDJSON protocol'\n },\n 'mcp-echo-server': {\n path: '../out/dist/workers-registry/mcp-echo-server/index.js',\n description: 'MCP server example for testing'\n },\n 'mcp-to-acp-proxy': {\n path: '../out/dist/workers-registry/mcp-to-acp-proxy/proxy.js',\n description: 'MCP-to-ACP protocol bridge'\n }\n} as const;\n\n/**\n * Worker name type\n */\ntype WorkerName = keyof typeof STDIO_BUS_WORKERS;\n\n/**\n * Display usage information\n */\nfunction showUsage(): void {\n console.error('Usage: node index.js <worker-name>');\n console.error('');\n console.error('Available workers:');\n\n for (const [name, config] of Object.entries(STDIO_BUS_WORKERS)) {\n console.error(` - ${name.padEnd(20)} ${config.description}`);\n }\n\n console.error('');\n console.error('Examples:');\n console.error(' node index.js acp-worker');\n console.error(' node index.js echo-worker');\n console.error(' node index.js mcp-echo-server');\n}\n\n/**\n * Validate worker name\n */\nfunction isValidWorkerName(name: string): name is WorkerName {\n return name in STDIO_BUS_WORKERS;\n}\n\n/**\n * Main entry point\n */\nasync function main(): Promise<void> {\n const workerName = process.argv[2];\n\n // Check if worker name is provided\n if (!workerName) {\n console.error('Error: Worker name is required\\n');\n showUsage();\n process.exit(1);\n }\n\n // Check if worker exists\n if (!isValidWorkerName(workerName)) {\n console.error(`Error: Unknown worker \"${workerName}\"\\n`);\n showUsage();\n process.exit(1);\n }\n\n const workerConfig = STDIO_BUS_WORKERS[workerName];\n const workerPath = workerConfig.path;\n\n // Resolve absolute path\n const absolutePath = join(__dirname, workerPath);\n\n try {\n // Verify the worker file exists\n await readFile(absolutePath);\n\n // Import and run the worker\n console.error(`[launcher] Starting worker: ${workerName}`);\n console.error(`[launcher] Description: ${workerConfig.description}`);\n console.error(`[launcher] Path: ${absolutePath}`);\n\n await import(absolutePath);\n } catch (error) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {\n console.error(`Error: Worker file not found: ${absolutePath}`);\n console.error('');\n console.error('Please run \"npm run build\" first to compile the workers.');\n process.exit(1);\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n console.error(`Error loading worker \"${workerName}\":`, errorMessage);\n if (errorStack) {\n console.error(errorStack);\n }\n process.exit(1);\n }\n}\n\n// Run main function\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n\n// Export for programmatic usage\nexport { STDIO_BUS_WORKERS, showUsage, isValidWorkerName, main as launch };\nexport type { WorkerConfig, WorkerName };\n"],
5
- "mappings": ";AAqCA,OAAS,kBAAqB,MAC9B,OAAS,QAAS,SAAY,OAC9B,OAAS,aAAgB,cAEzB,IAAM,WAAa,cAAc,YAAY,GAAG,EAChD,IAAM,UAAY,QAAQ,UAAU,EAapC,IAAM,kBAA4D,CAChE,aAAc,CACZ,KAAM,mDACN,YAAa,uDACf,EACA,eAAgB,CACd,KAAM,wEACN,YAAa,2CACf,EACA,cAAe,CACb,KAAM,0DACN,YAAa,gDACf,EACA,kBAAmB,CACjB,KAAM,wDACN,YAAa,gCACf,EACA,mBAAoB,CAClB,KAAM,yDACN,YAAa,4BACf,CACF,EAUA,SAAS,WAAkB,CACzB,QAAQ,MAAM,oCAAoC,EAClD,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,oBAAoB,EAElC,SAAW,CAAC,KAAM,MAAM,IAAK,OAAO,QAAQ,iBAAiB,EAAG,CAC9D,QAAQ,MAAM,OAAO,KAAK,OAAO,EAAE,CAAC,IAAI,OAAO,WAAW,EAAE,CAC9D,CAEA,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,WAAW,EACzB,QAAQ,MAAM,4BAA4B,EAC1C,QAAQ,MAAM,6BAA6B,EAC3C,QAAQ,MAAM,iCAAiC,CACjD,CAKA,SAAS,kBAAkB,KAAkC,CAC3D,OAAO,QAAQ,iBACjB,CAKA,eAAe,MAAsB,CACnC,MAAM,WAAa,QAAQ,KAAK,CAAC,EAGjC,GAAI,CAAC,WAAY,CACf,QAAQ,MAAM,kCAAkC,EAChD,UAAU,EACV,QAAQ,KAAK,CAAC,CAChB,CAGA,GAAI,CAAC,kBAAkB,UAAU,EAAG,CAClC,QAAQ,MAAM,0BAA0B,UAAU;AAAA,CAAK,EACvD,UAAU,EACV,QAAQ,KAAK,CAAC,CAChB,CAEA,MAAM,aAAe,kBAAkB,UAAU,EACjD,MAAM,WAAa,aAAa,KAGhC,MAAM,aAAe,KAAK,UAAW,UAAU,EAE/C,GAAI,CAEF,MAAM,SAAS,YAAY,EAG3B,QAAQ,MAAM,+BAA+B,UAAU,EAAE,EACzD,QAAQ,MAAM,2BAA2B,aAAa,WAAW,EAAE,EACnE,QAAQ,MAAM,oBAAoB,YAAY,EAAE,EAEhD,MAAM,OAAO,aACf,OAAS,MAAO,CACd,GAAI,OAAS,OAAO,QAAU,UAAY,SAAU,OAAS,MAAM,OAAS,SAAU,CACpF,QAAQ,MAAM,iCAAiC,YAAY,EAAE,EAC7D,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,0DAA0D,EACxE,QAAQ,KAAK,CAAC,CAChB,CAEA,MAAM,aAAe,iBAAiB,MAAQ,MAAM,QAAU,OAAO,KAAK,EAC1E,MAAM,WAAa,iBAAiB,MAAQ,MAAM,MAAQ,OAE1D,QAAQ,MAAM,yBAAyB,UAAU,KAAM,YAAY,EACnE,GAAI,WAAY,CACd,QAAQ,MAAM,UAAU,CAC1B,CACA,QAAQ,KAAK,CAAC,CAChB,CACF,CAGA,KAAK,EAAE,MAAO,OAAU,CACtB,QAAQ,MAAM,eAAgB,KAAK,EACnC,QAAQ,KAAK,CAAC,CAChB,CAAC",
4
+ "sourcesContent": ["#!/usr/bin/env node\n\n/*\n * Apache License 2.0\n * Copyright (c) 2025\u2013present Raman Marozau, Target Insight Function.\n * Contact: raman@worktif.com\n *\n * This file is part of the stdio bus protocol reference implementation:\n * stdio_bus_kernel_workers (target: <target_stdio_bus_kernel_workers>).\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n *\n * SPDX-License-Identifier: Apache-2.0\n */\n\n/**\n * Universal worker launcher for stdio Bus Workers Registry\n *\n * Usage:\n * node index.js <worker-name>\n * node index.js acp-worker\n * node index.js echo-worker\n * node index.js mcp-echo-server\n *\n * This script dynamically imports and runs the specified worker from the compiled output.\n */\n\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { readFile } from 'fs/promises';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Worker configuration mapping worker names to their entry points\n */\ninterface WorkerConfig {\n readonly path: string;\n readonly description: string;\n}\n\n/**\n * Available workers mapping\n */\nconst STDIO_BUS_WORKERS: Readonly<Record<string, WorkerConfig>> = {\n 'acp-worker': {\n path: '../out/dist/workers-registry/acp-worker/index.js',\n description: 'Full ACP protocol implementation with MCP integration'\n },\n 'acp-registry': {\n path: '../out/dist/workers-registry/acp-registry/index.js',\n description: 'Registry Launcher worker for ACP Registry agents'\n },\n 'echo-worker': {\n path: '../out/dist/workers-registry/echo-worker/echo-worker.js',\n description: 'Simple echo worker for testing NDJSON protocol'\n },\n 'mcp-echo-server': {\n path: '../out/dist/workers-registry/mcp-echo-server/index.js',\n description: 'MCP server example for testing'\n },\n 'mcp-to-acp-proxy': {\n path: '../out/dist/workers-registry/mcp-to-acp-proxy/proxy.js',\n description: 'MCP-to-ACP protocol bridge'\n }\n} as const;\n\n/**\n * Worker name type\n */\ntype WorkerName = keyof typeof STDIO_BUS_WORKERS;\n\n/**\n * Display usage information\n */\nfunction showUsage(): void {\n console.error('Usage: node index.js <worker-name>');\n console.error('');\n console.error('Available workers:');\n\n for (const [name, config] of Object.entries(STDIO_BUS_WORKERS)) {\n console.error(` - ${name.padEnd(20)} ${config.description}`);\n }\n\n console.error('');\n console.error('Examples:');\n console.error(' node index.js acp-worker');\n console.error(' node index.js echo-worker');\n console.error(' node index.js mcp-echo-server');\n}\n\n/**\n * Validate worker name\n */\nfunction isValidWorkerName(name: string): name is WorkerName {\n return name in STDIO_BUS_WORKERS;\n}\n\n/**\n * Main entry point\n */\nasync function main(): Promise<void> {\n const workerName = process.argv[2];\n\n // Check if worker name is provided\n if (!workerName) {\n console.error('Error: Worker name is required\\n');\n showUsage();\n process.exit(1);\n }\n\n // Check if worker exists\n if (!isValidWorkerName(workerName)) {\n console.error(`Error: Unknown worker \"${workerName}\"\\n`);\n showUsage();\n process.exit(1);\n }\n\n const workerConfig = STDIO_BUS_WORKERS[workerName];\n const workerPath = workerConfig.path;\n\n // Resolve absolute path\n const absolutePath = join(__dirname, workerPath);\n\n try {\n // Verify the worker file exists\n await readFile(absolutePath);\n\n // Import and run the worker\n console.error(`[launcher] Starting worker: ${workerName}`);\n console.error(`[launcher] Description: ${workerConfig.description}`);\n console.error(`[launcher] Path: ${absolutePath}`);\n\n await import(absolutePath);\n } catch (error) {\n if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {\n console.error(`Error: Worker file not found: ${absolutePath}`);\n console.error('');\n console.error('Please run \"npm run build\" first to compile the workers.');\n process.exit(1);\n }\n\n const errorMessage = error instanceof Error ? error.message : String(error);\n const errorStack = error instanceof Error ? error.stack : undefined;\n\n console.error(`Error loading worker \"${workerName}\":`, errorMessage);\n if (errorStack) {\n console.error(errorStack);\n }\n process.exit(1);\n }\n}\n\n// Run main function\nmain().catch((error) => {\n console.error('Fatal error:', error);\n process.exit(1);\n});\n\n// Export for programmatic usage\nexport { STDIO_BUS_WORKERS, showUsage, isValidWorkerName, main as launch };\nexport type { WorkerConfig, WorkerName };\n"],
5
+ "mappings": ";AAqCA,OAAS,kBAAqB,MAC9B,OAAS,QAAS,SAAY,OAC9B,OAAS,aAAgB,cAEzB,IAAM,WAAa,cAAc,YAAY,GAAG,EAChD,IAAM,UAAY,QAAQ,UAAU,EAapC,IAAM,kBAA4D,CAChE,aAAc,CACZ,KAAM,mDACN,YAAa,uDACf,EACA,eAAgB,CACd,KAAM,qDACN,YAAa,kDACf,EACA,cAAe,CACb,KAAM,0DACN,YAAa,gDACf,EACA,kBAAmB,CACjB,KAAM,wDACN,YAAa,gCACf,EACA,mBAAoB,CAClB,KAAM,yDACN,YAAa,4BACf,CACF,EAUA,SAAS,WAAkB,CACzB,QAAQ,MAAM,oCAAoC,EAClD,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,oBAAoB,EAElC,SAAW,CAAC,KAAM,MAAM,IAAK,OAAO,QAAQ,iBAAiB,EAAG,CAC9D,QAAQ,MAAM,OAAO,KAAK,OAAO,EAAE,CAAC,IAAI,OAAO,WAAW,EAAE,CAC9D,CAEA,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,WAAW,EACzB,QAAQ,MAAM,4BAA4B,EAC1C,QAAQ,MAAM,6BAA6B,EAC3C,QAAQ,MAAM,iCAAiC,CACjD,CAKA,SAAS,kBAAkB,KAAkC,CAC3D,OAAO,QAAQ,iBACjB,CAKA,eAAe,MAAsB,CACnC,MAAM,WAAa,QAAQ,KAAK,CAAC,EAGjC,GAAI,CAAC,WAAY,CACf,QAAQ,MAAM,kCAAkC,EAChD,UAAU,EACV,QAAQ,KAAK,CAAC,CAChB,CAGA,GAAI,CAAC,kBAAkB,UAAU,EAAG,CAClC,QAAQ,MAAM,0BAA0B,UAAU;AAAA,CAAK,EACvD,UAAU,EACV,QAAQ,KAAK,CAAC,CAChB,CAEA,MAAM,aAAe,kBAAkB,UAAU,EACjD,MAAM,WAAa,aAAa,KAGhC,MAAM,aAAe,KAAK,UAAW,UAAU,EAE/C,GAAI,CAEF,MAAM,SAAS,YAAY,EAG3B,QAAQ,MAAM,+BAA+B,UAAU,EAAE,EACzD,QAAQ,MAAM,2BAA2B,aAAa,WAAW,EAAE,EACnE,QAAQ,MAAM,oBAAoB,YAAY,EAAE,EAEhD,MAAM,OAAO,aACf,OAAS,MAAO,CACd,GAAI,OAAS,OAAO,QAAU,UAAY,SAAU,OAAS,MAAM,OAAS,SAAU,CACpF,QAAQ,MAAM,iCAAiC,YAAY,EAAE,EAC7D,QAAQ,MAAM,EAAE,EAChB,QAAQ,MAAM,0DAA0D,EACxE,QAAQ,KAAK,CAAC,CAChB,CAEA,MAAM,aAAe,iBAAiB,MAAQ,MAAM,QAAU,OAAO,KAAK,EAC1E,MAAM,WAAa,iBAAiB,MAAQ,MAAM,MAAQ,OAE1D,QAAQ,MAAM,yBAAyB,UAAU,KAAM,YAAY,EACnE,GAAI,WAAY,CACd,QAAQ,MAAM,UAAU,CAC1B,CACA,QAAQ,KAAK,CAAC,CAChB,CACF,CAGA,KAAK,EAAE,MAAO,OAAU,CACtB,QAAQ,MAAM,eAAgB,KAAK,EACnC,QAAQ,KAAK,CAAC,CAChB,CAAC",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,10 @@
1
+ {
2
+ "_comment": "Registry Launcher worker configuration (default for acp-registry worker)",
3
+ "_description": "Configuration options for the Registry Launcher worker process",
4
+ "registryUrl": "https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",
5
+ "_comment_registryUrl": "URL to fetch the ACP Registry JSON. Can also be set via ACP_REGISTRY_URL environment variable",
6
+ "apiKeysPath": "./api-keys.json",
7
+ "_comment_apiKeysPath": "Path to the API keys JSON file. Can be absolute or relative to the worker process. Can also be set via ACP_API_KEYS_PATH environment variable",
8
+ "shutdownTimeoutSec": 5,
9
+ "_comment_shutdownTimeoutSec": "Timeout in seconds for graceful shutdown. Agent processes receive SIGTERM, then SIGKILL after this timeout"
10
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res)=>function __init(){return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res};var DEFAULT_CONFIG;var init_types=__esm({"workers-registry/acp-worker/src/registry-launcher/config/types.ts"(){"use strict";DEFAULT_CONFIG={registryUrl:"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",apiKeysPath:"./api-keys.json",shutdownTimeoutSec:5}}});import{readFileSync}from"node:fs";function logWarning(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [WARN] [config] ${message}`)}function isNonEmptyString(value){return typeof value==="string"&&value.length>0}function isPositiveNumber(value){return typeof value==="number"&&value>0&&Number.isFinite(value)}function parseConfigObject(obj){const config={...DEFAULT_CONFIG};if(obj===null||typeof obj!=="object"){logWarning("Config file does not contain a valid object, using defaults");return config}const rawConfig=obj;if("registryUrl"in rawConfig){if(isNonEmptyString(rawConfig.registryUrl)){config.registryUrl=rawConfig.registryUrl}else{logWarning('Config field "registryUrl" is not a valid string, using default')}}if("apiKeysPath"in rawConfig){if(isNonEmptyString(rawConfig.apiKeysPath)){config.apiKeysPath=rawConfig.apiKeysPath}else{logWarning('Config field "apiKeysPath" is not a valid string, using default')}}if("shutdownTimeoutSec"in rawConfig){if(isPositiveNumber(rawConfig.shutdownTimeoutSec)){config.shutdownTimeoutSec=rawConfig.shutdownTimeoutSec}else{logWarning('Config field "shutdownTimeoutSec" is not a valid positive number, using default')}}return config}function applyEnvironmentOverrides(config){const envRegistryUrl=process.env[ENV_REGISTRY_URL];const envApiKeysPath=process.env[ENV_API_KEYS_PATH];const overrides={};if(isNonEmptyString(envRegistryUrl)){overrides.registryUrl=envRegistryUrl}if(isNonEmptyString(envApiKeysPath)){overrides.apiKeysPath=envApiKeysPath}return{...config,...overrides}}function loadConfig(configPath){let config={...DEFAULT_CONFIG};if(configPath){try{const fileContent=readFileSync(configPath,"utf-8");const parsed=JSON.parse(fileContent);config=parseConfigObject(parsed)}catch(error){if(error instanceof SyntaxError){logWarning(`Config file "${configPath}" contains malformed JSON, using defaults`)}else if(error.code==="ENOENT"){logWarning(`Config file "${configPath}" not found, using defaults`)}else if(error.code==="EACCES"){logWarning(`Config file "${configPath}" is not readable, using defaults`)}else{logWarning(`Failed to read config file "${configPath}": ${error.message}, using defaults`)}}}config=applyEnvironmentOverrides(config);return config}var ENV_REGISTRY_URL,ENV_API_KEYS_PATH;var init_config=__esm({"workers-registry/acp-worker/src/registry-launcher/config/config.ts"(){"use strict";init_types();ENV_REGISTRY_URL="ACP_REGISTRY_URL";ENV_API_KEYS_PATH="ACP_API_KEYS_PATH"}});import{readFileSync as readFileSync2}from"node:fs";function logWarning2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [WARN] [api-keys] ${message}`)}function logInfo(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [api-keys] ${message}`)}function loadApiKeys(apiKeysPath){try{const fileContent=readFileSync2(apiKeysPath,"utf-8");const parsed=JSON.parse(fileContent);if(!parsed.agents||typeof parsed.agents!=="object"){logWarning2(`API keys file "${apiKeysPath}" does not contain valid "agents" object`);return{}}const agentsWithKeys=Object.entries(parsed.agents).filter(([_,keys])=>keys.apiKey&&keys.apiKey.length>0);logInfo(`Loaded API keys for ${agentsWithKeys.length} agents from "${apiKeysPath}"`);return parsed.agents}catch(error){if(error.code==="ENOENT"){logWarning2(`API keys file "${apiKeysPath}" not found, agents will not be authenticated`)}else if(error instanceof SyntaxError){logWarning2(`API keys file "${apiKeysPath}" contains malformed JSON`)}else{logWarning2(`Failed to read API keys file "${apiKeysPath}": ${error.message}`)}return{}}}function getAgentApiKey(apiKeys,agentId){const keys=apiKeys[agentId];if(!keys||!keys.apiKey||keys.apiKey.length===0){return void 0}return keys.apiKey}var init_api_keys=__esm({"workers-registry/acp-worker/src/registry-launcher/config/api-keys.ts"(){"use strict"}});function getCurrentPlatform(){const platform=process.platform;const arch=process.arch;if(platform==="darwin"&&arch==="arm64")return"darwin-aarch64";if(platform==="darwin"&&arch==="x64")return"darwin-x86_64";if(platform==="linux"&&arch==="arm64")return"linux-aarch64";if(platform==="linux"&&arch==="x64")return"linux-x86_64";if(platform==="win32"&&arch==="arm64")return"windows-aarch64";if(platform==="win32"&&arch==="x64")return"windows-x86_64";return"linux-x86_64"}function resolveBinary(distribution,agentId){const currentPlatform=getCurrentPlatform();const target=distribution[currentPlatform];if(!target){throw new PlatformNotSupportedError(agentId,currentPlatform)}return{command:target.cmd,args:target.args??[],env:target.env}}function resolveNpx(distribution){return{command:"npx",args:[distribution.package,...distribution.args??[]],env:distribution.env}}function resolveUvx(distribution){return{command:"uvx",args:[distribution.package,...distribution.args??[]],env:distribution.env}}function resolve(distribution,agentId){if(distribution.npx){return resolveNpx(distribution.npx)}if(distribution.uvx){return resolveUvx(distribution.uvx)}if(distribution.binary){return resolveBinary(distribution.binary,agentId)}throw new NoDistributionError(agentId)}var PlatformNotSupportedError,NoDistributionError;var init_resolver=__esm({"workers-registry/acp-worker/src/registry-launcher/registry/resolver.ts"(){"use strict";PlatformNotSupportedError=class extends Error{constructor(agentId,platform){super(`Platform not supported: ${platform} for agent ${agentId}`);this.agentId=agentId;this.platform=platform;this.name="PlatformNotSupportedError"}};NoDistributionError=class extends Error{constructor(agentId){super(`No supported distribution type for agent ${agentId}`);this.agentId=agentId;this.name="NoDistributionError"}}}});function logError(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [registry] ${message}`)}function logInfo2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [registry] ${message}`)}function isNonEmptyString2(value){return typeof value==="string"&&value.length>0}function isValidDistribution(value){if(value===null||typeof value!=="object"){return false}const dist=value;const hasBinary=dist.binary!==void 0&&typeof dist.binary==="object";const hasNpx=dist.npx!==void 0&&typeof dist.npx==="object";const hasUvx=dist.uvx!==void 0&&typeof dist.uvx==="object";if(!hasBinary&&!hasNpx&&!hasUvx){return false}if(hasNpx){const npx=dist.npx;if(!isNonEmptyString2(npx.package)){return false}}if(hasUvx){const uvx=dist.uvx;if(!isNonEmptyString2(uvx.package)){return false}}return true}function parseAgent(value,index){if(value===null||typeof value!=="object"){throw new RegistryParseError(`Agent at index ${index} is not an object`)}const raw=value;if(!isNonEmptyString2(raw.id)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "id" field`)}if(!isNonEmptyString2(raw.name)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "name" field`)}if(!isNonEmptyString2(raw.version)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "version" field`)}if(!isValidDistribution(raw.distribution)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "distribution" field`)}const agent={id:raw.id,name:raw.name,version:raw.version,distribution:raw.distribution};if(typeof raw.description==="string"){agent.description=raw.description}if(typeof raw.repository==="string"){agent.repository=raw.repository}if(Array.isArray(raw.authors)){agent.authors=raw.authors.filter(a=>typeof a==="string")}if(typeof raw.license==="string"){agent.license=raw.license}if(typeof raw.icon==="string"){agent.icon=raw.icon}return agent}function parseRegistry(data){if(data===null||typeof data!=="object"){throw new RegistryParseError("Registry data is not an object")}const raw=data;if(!isNonEmptyString2(raw.version)){throw new RegistryParseError('Registry has invalid or missing "version" field')}if(!Array.isArray(raw.agents)){throw new RegistryParseError('Registry has invalid or missing "agents" field')}const agents=[];for(let i=0;i<raw.agents.length;i++){agents.push(parseAgent(raw.agents[i],i))}return{version:raw.version,agents}}var ENV_REGISTRY_URL2,RegistryFetchError,RegistryParseError,AgentNotFoundError,RegistryIndex;var init_registry=__esm({"workers-registry/acp-worker/src/registry-launcher/registry/index.ts"(){"use strict";init_resolver();init_resolver();ENV_REGISTRY_URL2="ACP_REGISTRY_URL";RegistryFetchError=class extends Error{constructor(message,cause){super(message);this.cause=cause;this.name="RegistryFetchError"}};RegistryParseError=class extends Error{constructor(message,cause){super(message);this.cause=cause;this.name="RegistryParseError"}};AgentNotFoundError=class extends Error{constructor(agentId){super(`Agent not found: ${agentId}`);this.agentId=agentId;this.name="AgentNotFoundError"}};RegistryIndex=class{registryUrl;registry=null;agentMap=new Map;constructor(registryUrl){const envUrl=process.env[ENV_REGISTRY_URL2];this.registryUrl=isNonEmptyString2(envUrl)?envUrl:registryUrl}async fetch(){logInfo2(`Fetching registry from ${this.registryUrl}`);let response;try{response=await fetch(this.registryUrl)}catch(error){const message=`Failed to fetch registry from ${this.registryUrl}: ${error.message}`;logError(message);throw new RegistryFetchError(message,error)}if(!response.ok){const message=`Failed to fetch registry from ${this.registryUrl}: HTTP ${response.status} ${response.statusText}`;logError(message);throw new RegistryFetchError(message)}let text;try{text=await response.text()}catch(error){const message=`Failed to read registry response body: ${error.message}`;logError(message);throw new RegistryFetchError(message,error)}let data;try{data=JSON.parse(text)}catch(error){const message=`Failed to parse registry JSON: ${error.message}`;logError(message);throw new RegistryParseError(message,error)}try{this.registry=parseRegistry(data)}catch(error){if(error instanceof RegistryParseError){logError(error.message);throw error}const message=`Failed to validate registry data: ${error.message}`;logError(message);throw new RegistryParseError(message,error)}this.agentMap.clear();for(const agent of this.registry.agents){this.agentMap.set(agent.id,agent)}logInfo2(`Registry loaded: version ${this.registry.version}, ${this.registry.agents.length} agents`)}lookup(agentId){return this.agentMap.get(agentId)}resolve(agentId){const agent=this.lookup(agentId);if(!agent){throw new AgentNotFoundError(agentId)}return resolve(agent.distribution,agentId)}getRegistry(){return this.registry}}}});function logError2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [ndjson] ${message}`)}var NDJSONHandler;var init_ndjson_handler=__esm({"workers-registry/acp-worker/src/registry-launcher/stream/ndjson-handler.ts"(){"use strict";NDJSONHandler=class{buffer="";output;messageCallback=null;errorCallback=null;constructor(output){this.output=output}onMessage(callback){this.messageCallback=callback}onError(callback){this.errorCallback=callback}write(message){if(!this.output.writable){return false}try{const json=JSON.stringify(message);this.output.write(json+"\n");return true}catch{return false}}processChunk(chunk){this.buffer+=chunk.toString("utf-8");this.processBuffer()}processBuffer(){let newlineIndex;while((newlineIndex=this.buffer.indexOf("\n"))!==-1){const line=this.buffer.slice(0,newlineIndex);this.buffer=this.buffer.slice(newlineIndex+1);if(line.trim().length===0){continue}this.parseLine(line)}}parseLine(line){try{const message=JSON.parse(line);if(message===null||typeof message!=="object"){const error=new Error("Parsed JSON is not an object");logError2(`Malformed NDJSON line (not an object): ${this.truncateLine(line)}`);this.errorCallback?.(error,line);return}this.messageCallback?.(message)}catch(error){logError2(`Failed to parse NDJSON line: ${this.truncateLine(line)}`);this.errorCallback?.(error,line)}}truncateLine(line,maxLength=100){if(line.length<=maxLength){return line}return line.slice(0,maxLength)+"..."}}}});import{spawn}from"child_process";var DEFAULT_TERMINATE_TIMEOUT_MS,AgentRuntimeImpl;var init_agent_runtime=__esm({"workers-registry/acp-worker/src/registry-launcher/runtime/agent-runtime.ts"(){"use strict";DEFAULT_TERMINATE_TIMEOUT_MS=5e3;AgentRuntimeImpl=class _AgentRuntimeImpl{agentId;state;process;onExitCallback;constructor(agentId,process2,onExit){this.agentId=agentId;this.process=process2;this.state="starting";this.onExitCallback=onExit;this.setupProcessHandlers()}static spawn(agentId,spawnCommand,onExit){const childProcess=spawn(spawnCommand.command,spawnCommand.args,{stdio:["pipe","pipe","pipe"],env:{...process.env,...spawnCommand.env},detached:false});if(childProcess.stdout){childProcess.stdout.setEncoding("utf8")}if(childProcess.stderr){childProcess.stderr.setEncoding("utf8")}return new _AgentRuntimeImpl(agentId,childProcess,onExit)}setupProcessHandlers(){this.process.on("spawn",()=>{if(this.state==="starting"){this.state="running"}});this.process.on("error",error=>{this.state="stopped";process.stderr.write(`[${new Date().toISOString()}] ERROR: Agent ${this.agentId} process error: ${error.message}
3
+ `)});this.process.on("exit",(code,signal)=>{this.state="stopped";if(this.onExitCallback){this.onExitCallback(code,signal)}});if(this.process.stdin){this.process.stdin.on("error",error=>{process.stderr.write(`[${new Date().toISOString()}] WARN: Agent ${this.agentId} stdin error: ${error.message}
4
+ `)})}}write(message){if(this.state!=="running"&&this.state!=="starting"){return false}if(!this.process.stdin||this.process.stdin.destroyed){return false}try{const ndjsonLine=JSON.stringify(message)+"\n";return this.process.stdin.write(ndjsonLine)}catch{return false}}async terminate(timeout=DEFAULT_TERMINATE_TIMEOUT_MS){if(this.state==="stopped"){return}if(this.state==="stopping"){return this.waitForExit()}this.state="stopping";if(this.process.stdin&&!this.process.stdin.destroyed){this.process.stdin.end()}this.process.kill("SIGTERM");const exitPromise=this.waitForExit();const timeoutPromise=new Promise(resolve2=>{setTimeout(()=>resolve2("timeout"),timeout)});const result=await Promise.race([exitPromise,timeoutPromise]);if(result==="timeout"&&!this.process.killed&&this.process.exitCode===null){this.process.kill("SIGKILL");await this.waitForExit()}}waitForExit(){if(this.state==="stopped"){return Promise.resolve()}return new Promise(resolve2=>{this.process.once("exit",()=>{resolve2()})})}}}});var DEFAULT_SHUTDOWN_TIMEOUT_MS,AgentRuntimeManager;var init_manager=__esm({"workers-registry/acp-worker/src/registry-launcher/runtime/manager.ts"(){"use strict";init_agent_runtime();DEFAULT_SHUTDOWN_TIMEOUT_MS=5e3;AgentRuntimeManager=class{runtimes=new Map;exitCallbacks=[];async getOrSpawn(agentId,spawnCommand){const existing=this.runtimes.get(agentId);if(existing&&existing.state!=="stopped"){return existing}const runtime=AgentRuntimeImpl.spawn(agentId,spawnCommand,(code,_signal)=>{this.handleAgentExit(agentId,code)});this.runtimes.set(agentId,runtime);return runtime}get(agentId){return this.runtimes.get(agentId)}async terminate(agentId,timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const runtime=this.runtimes.get(agentId);if(!runtime){return}await runtime.terminate(timeout);this.runtimes.delete(agentId)}async terminateAll(timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const terminatePromises=[];for(const[agentId,runtime]of this.runtimes){if(runtime.state!=="stopped"){terminatePromises.push(runtime.terminate(timeout).then(()=>{this.runtimes.delete(agentId)}))}}await Promise.all(terminatePromises)}onAgentExit(callback){this.exitCallbacks.push(callback)}handleAgentExit(agentId,code){this.runtimes.delete(agentId);for(const callback of this.exitCallbacks){try{callback(agentId,code)}catch{}}}get size(){return this.runtimes.size}has(agentId){return this.runtimes.has(agentId)}}}});function logError3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [router] ${message}`)}function logInfo3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [router] ${message}`)}function createErrorResponse(id,code,message,data){const response={jsonrpc:"2.0",id,error:{code,message}};if(data!==void 0){response.error.data=data}return response}function extractAgentId(message){const msg=message;const agentId=msg.agentId;if(typeof agentId==="string"&&agentId.length>0){return agentId}return void 0}function extractId(message){const msg=message;const id=msg.id;if(typeof id==="string"||typeof id==="number"){return id}return null}function transformMessage(message){const{agentId:_,...rest}=message;return rest}var RoutingErrorCodes,MessageRouter;var init_message_router=__esm({"workers-registry/acp-worker/src/registry-launcher/router/message-router.ts"(){"use strict";init_registry();init_api_keys();RoutingErrorCodes={MISSING_AGENT_ID:-32600,AGENT_NOT_FOUND:-32001,PLATFORM_NOT_SUPPORTED:-32002,SPAWN_FAILED:-32003};MessageRouter=class{registry;runtimeManager;writeCallback;apiKeys;pendingRequests=new Map;authState=new Map;sessionIdMap=new Map;constructor(registry,runtimeManager,writeCallback,apiKeys={}){this.registry=registry;this.runtimeManager=runtimeManager;this.writeCallback=writeCallback;this.apiKeys=apiKeys}async route(message){const id=extractId(message);const agentId=extractAgentId(message);if(agentId===void 0){logError3("Missing agentId in request");return createErrorResponse(id,RoutingErrorCodes.MISSING_AGENT_ID,"Missing agentId")}let spawnCommand;try{spawnCommand=this.registry.resolve(agentId)}catch(error){if(error instanceof AgentNotFoundError){logError3(`Agent not found: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.AGENT_NOT_FOUND,"Agent not found",{agentId})}if(error instanceof PlatformNotSupportedError){logError3(`Platform not supported for agent: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.PLATFORM_NOT_SUPPORTED,"Platform not supported",{agentId,platform:error.platform})}throw error}let runtime;try{runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to spawn agent ${agentId}: ${error.message}`);return createErrorResponse(id,RoutingErrorCodes.SPAWN_FAILED,"Agent spawn failed",{agentId,error:error.message})}if(id!==null){const msg=message;const clientSessionId=typeof msg.sessionId==="string"?msg.sessionId:void 0;this.pendingRequests.set(id,{id,agentId,timestamp:Date.now(),clientSessionId})}const transformedMessage=transformMessage(message);const success=runtime.write(transformedMessage);if(!success){logError3(`Failed to write to agent ${agentId}`);if(id!==null){this.pendingRequests.delete(id)}}else{logInfo3(`Routed message to agent ${agentId}`)}return void 0}handleAgentResponse(agentId,response){const id=extractId(response);const msg=response;if(id!==null){const pending=this.pendingRequests.get(id);if(pending&&pending.agentId===agentId){const result=msg.result;if(result&&Array.isArray(result.authMethods)&&result.authMethods.length>0){logInfo3(`Agent ${agentId} requires authentication, attempting auto-auth`);this.authState.set(agentId,"pending");void this.attemptAuthentication(agentId,result.authMethods)}if(result&&typeof result.sessionId==="string"){const agentSessionId=result.sessionId;const clientSessionId=pending.clientSessionId;if(clientSessionId){this.sessionIdMap.set(agentSessionId,clientSessionId);logInfo3(`Mapped agent sessionId ${agentSessionId} to client sessionId ${clientSessionId}`)}}this.pendingRequests.delete(id)}}if(id===null&&msg.method){logInfo3(`Received notification: ${msg.method}`);const params=msg.params;if(params&&typeof params.sessionId==="string"){const agentSessionId=params.sessionId;const clientSessionId=this.sessionIdMap.get(agentSessionId);if(clientSessionId){const enriched={...msg,sessionId:clientSessionId,params:{...params,sessionId:agentSessionId}};logInfo3(`Forwarding notification with mapped sessionId: ${clientSessionId}`);this.writeCallback(enriched);return}else{logInfo3(`Forwarding notification with unmapped agentSessionId: ${agentSessionId}`);this.writeCallback(response);return}}else{const topLevelSessionId=msg.sessionId;if(topLevelSessionId){this.writeCallback(response);return}else{logError3(`Notification without sessionId: ${msg.method}, adding default sessionId for routing`);const enriched={...msg,sessionId:"global-notifications"};this.writeCallback(enriched);return}}}this.writeCallback(response)}async attemptAuthentication(agentId,authMethods){const apiKey=getAgentApiKey(this.apiKeys,agentId);if(!apiKey){logError3(`No API key found for agent ${agentId}, authentication will fail`);this.authState.set(agentId,"none");return}let selectedMethod=authMethods.find(m=>m.id==="openai-api-key");if(!selectedMethod){selectedMethod=authMethods.find(m=>m.id.includes("api-key")||m.id.includes("apikey"))}if(!selectedMethod){selectedMethod=authMethods[0]}logInfo3(`Authenticating agent ${agentId} with method: ${selectedMethod.id}`);let runtime;try{const spawnCommand=this.registry.resolve(agentId);runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to get runtime for authentication: ${error.message}`);this.authState.set(agentId,"none");return}const authRequest={jsonrpc:"2.0",id:`auth-${agentId}-${Date.now()}`,method:"authenticate",params:{methodId:selectedMethod.id,credentials:{apiKey}}};const transformed=transformMessage(authRequest);const serialized=JSON.stringify(transformed)+"\n";if(runtime.process.stdin){runtime.process.stdin.write(serialized,error=>{if(error){logError3(`Failed to send authenticate request to ${agentId}: ${error.message}`);this.authState.set(agentId,"none")}else{logInfo3(`Sent authenticate request to agent ${agentId}`);this.authState.set(agentId,"authenticated")}})}}get pendingCount(){return this.pendingRequests.size}isPending(id){return this.pendingRequests.has(id)}clearPending(){this.pendingRequests.clear()}}}});function formatLogMessage(level,message,context=LOG_CONTEXT){const timestamp=new Date().toISOString();return`[${timestamp}] [${level}] [${context}] ${message}`}function log(level,message,context){const formatted=formatLogMessage(level,message,context);console.error(formatted)}function logExit(agentId,exitCode,signal){if(signal){log("INFO",`Agent "${agentId}" exited with signal ${signal}`)}else if(exitCode!==null){log("INFO",`Agent "${agentId}" exited with code ${exitCode}`)}else{log("INFO",`Agent "${agentId}" exited`)}}function logInfo4(message,context){log("INFO",message,context)}function logError4(message,context){log("ERROR",message,context)}var LOG_CONTEXT;var init_log=__esm({"workers-registry/acp-worker/src/registry-launcher/log.ts"(){"use strict";LOG_CONTEXT="registry-launcher"}});var registry_launcher_exports={};function parseArgs(){const args=process.argv.slice(2);if(args.length>0&&args[0]&&!args[0].startsWith("-")){return args[0]}return void 0}function setupSignalHandlers(runtimeManager,shutdownTimeoutMs){const shutdown=async()=>{if(isShuttingDown){return}isShuttingDown=true;logInfo4("Received shutdown signal, initiating graceful shutdown");try{await runtimeManager.terminateAll(shutdownTimeoutMs);logInfo4("All agent processes terminated");process.exit(ExitCodes.SUCCESS)}catch(error){logError4(`Error during shutdown: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}};process.on("SIGTERM",()=>{void shutdown()});process.on("SIGINT",()=>{void shutdown()});return shutdown}function setupStdinHandler(router,ndjsonHandler){ndjsonHandler.onMessage(async message=>{try{const errorResponse=await router.route(message);if(errorResponse){ndjsonHandler.write(errorResponse)}}catch(error){logError4(`Unexpected error routing message: ${error.message}`)}});ndjsonHandler.onError((error,line)=>{logError4(`Failed to parse NDJSON: ${error.message} - Line: ${line.slice(0,100)}`)});process.stdin.setEncoding("utf8");process.stdin.on("data",chunk=>{const buffer=typeof chunk==="string"?Buffer.from(chunk):chunk;ndjsonHandler.processChunk(buffer)});process.stdin.on("end",()=>{logInfo4("stdin closed")});process.stdin.on("error",error=>{logError4(`stdin error: ${error.message}`)})}function setupAgentResponseHandling(runtimeManager,router){runtimeManager.onAgentExit((agentId,code)=>{logExit(agentId,code)});const originalGetOrSpawn=runtimeManager.getOrSpawn.bind(runtimeManager);runtimeManager.getOrSpawn=async function(agentId,spawnCommand){const runtime=await originalGetOrSpawn(agentId,spawnCommand);const proc=runtime.process;if(proc.stdout&&!proc.stdout.listenerCount("data")){let buffer="";proc.stdout.on("data",chunk=>{buffer+=chunk;let newlineIndex;while((newlineIndex=buffer.indexOf("\n"))!==-1){const line=buffer.slice(0,newlineIndex);buffer=buffer.slice(newlineIndex+1);if(line.trim()){try{const response=JSON.parse(line);router.handleAgentResponse(agentId,response)}catch(err){logError4(`Failed to parse agent ${agentId} response: ${err.message}`)}}}})}if(proc.stderr&&!proc.stderr.listenerCount("data")){proc.stderr.on("data",chunk=>{process.stderr.write(`[agent:${agentId}] ${chunk}`)})}return runtime}}async function main(){logInfo4("Registry Launcher starting");const configPath=parseArgs();if(configPath){logInfo4(`Loading configuration from: ${configPath}`)}const config=loadConfig(configPath);logInfo4(`Configuration loaded: registryUrl=${config.registryUrl}, apiKeysPath=${config.apiKeysPath}, shutdownTimeoutSec=${config.shutdownTimeoutSec}`);const apiKeys=loadApiKeys(config.apiKeysPath);const registry=new RegistryIndex(config.registryUrl);try{await registry.fetch()}catch(error){if(error instanceof RegistryFetchError){logError4(`Failed to fetch registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}if(error instanceof RegistryParseError){logError4(`Failed to parse registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}logError4(`Unexpected error fetching registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}const runtimeManager=new AgentRuntimeManager;const ndjsonHandler=new NDJSONHandler(process.stdout);const router=new MessageRouter(registry,runtimeManager,message=>ndjsonHandler.write(message),apiKeys);const shutdownTimeoutMs=config.shutdownTimeoutSec*1e3;setupSignalHandlers(runtimeManager,shutdownTimeoutMs);setupAgentResponseHandling(runtimeManager,router);setupStdinHandler(router,ndjsonHandler);logInfo4("Registry Launcher ready, waiting for messages")}var ExitCodes,isShuttingDown;var init_registry_launcher=__esm({"workers-registry/acp-worker/src/registry-launcher/index.ts"(){"use strict";init_config();init_api_keys();init_registry();init_ndjson_handler();init_manager();init_message_router();init_log();ExitCodes={SUCCESS:0,FATAL_ERROR:1};isShuttingDown=false;main().catch(error=>{logError4(`Fatal error: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)})}});import{fileURLToPath}from"url";import{dirname,join}from"path";var __filename=fileURLToPath(import.meta.url);var __dirname=dirname(__filename);var DEFAULT_CONFIG_FILE="acp-registry-config.json";function ensureDefaultConfigArg(){const hasExplicitConfig=process.argv.length>2&&process.argv[2]&&!process.argv[2].startsWith("-");if(hasExplicitConfig){return}const defaultConfigPath=join(__dirname,DEFAULT_CONFIG_FILE);process.argv.splice(2,0,defaultConfigPath)}ensureDefaultConfigArg();await Promise.resolve().then(()=>(init_registry_launcher(),registry_launcher_exports));
5
+ //# sourceMappingURL=index.js.map