@stdiobus/workers-registry 1.5.0-beta.1 → 1.5.0-beta.2

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
@@ -21,9 +21,15 @@ Worker implementations for [stdio Bus kernel](https://github.com/stdiobus/stdiob
21
21
  npm install @stdiobus/workers-registry
22
22
  ```
23
23
 
24
+ For embedded usage (no Docker/binary needed):
25
+
26
+ ```bash
27
+ npm install @stdiobus/node @stdiobus/workers-registry
28
+ ```
29
+
24
30
  **Requirements:**
25
31
  - Node.js ≥20.0.0
26
- - [stdio Bus kernel](https://github.com/stdiobus/stdiobus) (Docker or binary)
32
+ - [stdio Bus kernel](https://github.com/stdiobus/stdiobus) (Docker or binary) — or [`@stdiobus/node`](https://www.npmjs.com/package/@stdiobus/node) for embedded mode
27
33
 
28
34
  **Keywords:** `stdiobus`, `protocol`, `acp`, `mcp`, `agent`, `transport`, `json-rpc`, `stdio-bus`, `worker`
29
35
 
@@ -61,22 +67,26 @@ graph TB
61
67
 
62
68
  ## Prerequisites
63
69
 
64
- - stdio Bus kernel - available via [Docker](https://hub.docker.com/r/stdiobus/stdiobus) or [build from source](https://github.com/stdiobus/stdiobus)
65
- - Node.js 20.0.0 or later (for building workers)
70
+ - Node.js 20.0.0 or later
71
+ - One of:
72
+ - [`@stdiobus/node`](https://www.npmjs.com/package/@stdiobus/node) — embedded mode, no external dependencies
73
+ - [stdio Bus kernel via Docker](https://hub.docker.com/r/stdiobus/stdiobus) — TCP/Unix socket mode
74
+ - [stdio Bus kernel binary](https://github.com/stdiobus/stdiobus) — build from source
66
75
 
67
76
  ## Workers
68
77
 
69
78
  | Worker | Description | Protocol | Command |
70
79
  |--------|-------------|----------|---------|
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` |
80
+ | `acp-registry` | Registry Launcher worker that routes to ACP Registry agents (requires `api-keys.json`) | ACP | `npx @stdiobus/workers-registry acp-registry` |
81
+ | `acp-worker` | Full ACP protocol implementation (standalone agent; does **not** route to ACP Registry) | ACP | `npx @stdiobus/workers-registry acp-worker` |
73
82
  | `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` |
83
+ | `openai-agent` | OpenAI Chat Completions API agent (bridges ACP to any OpenAI-compatible endpoint) | ACP | `npx @stdiobus/workers-registry openai-agent` |
84
+ | `mcp-to-acp-proxy` | Bridges MCP clients (like IDEs) to ACP agents | MCP → ACP | `npx @stdiobus/workers-registry mcp-to-acp-proxy` |
85
+ | `echo-worker` | Simple echo worker for testing NDJSON protocol | NDJSON | `npx @stdiobus/workers-registry echo-worker` |
86
+ | `mcp-echo-server` | MCP server example for testing | MCP | `npx @stdiobus/workers-registry mcp-echo-server` |
77
87
 
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`.
88
+ **Note:** The universal launcher is `@stdiobus/workers-registry/launch`. For local
89
+ development in this repo, use `node ./launch/index.js <worker-name>` after `npm run build`.
80
90
 
81
91
  ## Package API
82
92
 
@@ -111,13 +121,75 @@ import type { MCPServer } from '@stdiobus/workers-registry/workers/mcp-echo-serv
111
121
 
112
122
  ## Quick Start
113
123
 
114
- ### 1. Install Package
124
+ ### Option A: Embedded via `@stdiobus/node` (simplest)
125
+
126
+ No Docker, no binary, no TCP — just npm packages. The bus runs inside your Node.js process.
127
+
128
+ ```bash
129
+ npm install @stdiobus/node @stdiobus/workers-registry
130
+ ```
131
+
132
+ Create `config.json`:
133
+
134
+ ```json
135
+ {
136
+ "pools": [
137
+ {
138
+ "id": "openai-agent",
139
+ "command": "npx",
140
+ "args": ["@stdiobus/workers-registry", "openai-agent"],
141
+ "instances": 1
142
+ }
143
+ ]
144
+ }
145
+ ```
146
+
147
+ Use it in code:
148
+
149
+ ```javascript
150
+ import { StdioBus } from '@stdiobus/node';
151
+
152
+ const bus = new StdioBus({ configPath: './config.json' });
153
+ await bus.start();
154
+
155
+ // Send ACP initialize request
156
+ const result = await bus.request('initialize', {
157
+ protocolVersion: 1,
158
+ clientInfo: { name: 'my-app', version: '1.0.0' },
159
+ });
160
+
161
+ console.log(result.agentInfo.name); // 'openai-agent'
162
+ console.log(result.authMethods); // [{ id: 'oauth2', ... }]
163
+
164
+ await bus.stop();
165
+ ```
166
+
167
+ Or run any other worker the same way — just change the pool config:
168
+
169
+ ```json
170
+ {
171
+ "pools": [
172
+ {
173
+ "id": "acp-registry",
174
+ "command": "npx",
175
+ "args": ["@stdiobus/workers-registry", "acp-registry"],
176
+ "instances": 1
177
+ }
178
+ ]
179
+ }
180
+ ```
181
+
182
+ See [`@stdiobus/node` on npm](https://www.npmjs.com/package/@stdiobus/node) for TCP mode, Unix socket mode, Docker backend, and full API reference.
183
+
184
+ ### Option B: Docker / Binary (TCP mode)
185
+
186
+ #### 1. Install Package
115
187
 
116
188
  ```bash
117
189
  npm install @stdiobus/workers-registry
118
190
  ```
119
191
 
120
- ### 2. Get stdio Bus kernel
192
+ #### 2. Get stdio Bus kernel
121
193
 
122
194
  **Option A: Using Docker (recommended)**
123
195
 
@@ -129,7 +201,7 @@ docker pull stdiobus/stdiobus:latest
129
201
 
130
202
  See [stdio Bus kernel repository](https://github.com/stdiobus/stdiobus) for build instructions.
131
203
 
132
- ### 3. Run with ACP Registry (recommended for real agents)
204
+ #### 3. Run with ACP Registry (recommended for real agents)
133
205
 
134
206
  **Create config.json:**
135
207
  ```json
@@ -155,7 +227,7 @@ or pass a custom config file (third arg to `launch acp-registry`) with an absolu
155
227
  Use the same Docker/binary commands below (they run `config.json`), and ensure
156
228
  `api-keys.json` is mounted into the container when using Docker.
157
229
 
158
- ### 4. Run with ACP Worker
230
+ #### 4. Run with ACP Worker
159
231
 
160
232
  **Note:** `acp-worker` is a standalone ACP agent for SDK/protocol testing. It does **not**
161
233
  route to the ACP Registry. Use `acp-registry` when you need real registry agents.
@@ -191,7 +263,7 @@ docker run -p 9000:9000 \
191
263
  ./stdio_bus --config config.json --tcp 0.0.0.0:9000
192
264
  ```
193
265
 
194
- ### 5. Test Connection
266
+ #### 5. Test Connection
195
267
 
196
268
  ```bash
197
269
  # ACP worker (standalone)
@@ -210,8 +282,8 @@ echo '{"jsonrpc":"2.0","id":"1","method":"initialize","params":{"agentId":"claud
210
282
  The simplest way to run any worker:
211
283
 
212
284
  ```bash
213
- # Run any worker by name (package install)
214
- node ./node_modules/@stdiobus/workers-registry/launch <worker-name>
285
+ # Run any worker by name (recommended)
286
+ npx @stdiobus/workers-registry <worker-name>
215
287
 
216
288
  # Run any worker by name (this repo, after build)
217
289
  node ./launch/index.js <worker-name>
@@ -222,9 +294,10 @@ node ./launch/index.js <worker-name>
222
294
  # - echo-worker
223
295
  # - mcp-echo-server
224
296
  # - mcp-to-acp-proxy
297
+ # - openai-agent
225
298
 
226
299
  # Example: Run echo worker for testing
227
- node ./node_modules/@stdiobus/workers-registry/launch echo-worker
300
+ npx @stdiobus/workers-registry echo-worker
228
301
  ```
229
302
 
230
303
  ### Using in stdio Bus Configuration
@@ -814,14 +887,35 @@ rl.on('close', () => process.exit(0));
814
887
 
815
888
  ```
816
889
  workers-registry/
890
+ ├── index.ts # Package entry point
891
+ ├── launch/ # Universal launcher (npx entry point)
817
892
  ├── acp-worker/ # Full ACP protocol implementation
818
893
  │ ├── src/
819
894
  │ │ ├── agent.ts # ACP Agent implementation
820
895
  │ │ ├── index.ts # Main entry point
896
+ │ │ ├── acp/ # ACP protocol layer
821
897
  │ │ ├── mcp/ # MCP server integration
898
+ │ │ ├── mcp-proxy/ # MCP-to-ACP proxy logic
822
899
  │ │ ├── session/ # Session management
823
- │ │ └── registry-launcher/ # Registry Launcher implementation
900
+ │ │ ├── stdio/ # Session ID routing
901
+ │ │ └── test-utils/ # Testing utilities
824
902
  │ └── tests/ # Test suites
903
+ ├── registry-launcher/ # Registry Launcher (agent discovery + routing)
904
+ │ └── src/
905
+ │ ├── auth/ # OAuth 2.1 authentication
906
+ │ ├── config/ # Configuration management
907
+ │ ├── registry/ # ACP Registry resolution
908
+ │ ├── router/ # Message routing
909
+ │ ├── runtime/ # Agent runtime management
910
+ │ ├── stream/ # NDJSON stream handling
911
+ │ └── test-utils/ # Testing utilities
912
+ ├── openai-agent/ # OpenAI Chat Completions API agent
913
+ │ └── src/
914
+ │ ├── agent.ts # ACP Agent bridging to OpenAI API
915
+ │ ├── client.ts # Chat Completions HTTP + SSE client
916
+ │ ├── sse-parser.ts # SSE line parser
917
+ │ ├── session.ts # Session state management
918
+ │ └── config.ts # Environment-based configuration
825
919
  ├── acp-registry/ # ACP Registry worker entrypoint + configs
826
920
  ├── echo-worker/ # Simple echo worker example
827
921
  ├── mcp-echo-server/ # MCP server example
@@ -884,8 +978,8 @@ nvm install 20 # If using nvm
884
978
  **Permission errors:**
885
979
  ```bash
886
980
  npm install -g @stdiobus/workers-registry # Global install (may need sudo)
887
- # Or use a local install
888
- node ./node_modules/@stdiobus/workers-registry/launch acp-worker
981
+ # Or use npx
982
+ npx @stdiobus/workers-registry acp-worker
889
983
  ```
890
984
 
891
985
  ### Runtime Issues
@@ -958,27 +1052,27 @@ Registry Launcher supports OAuth 2.1 with PKCE for secure browser-based authenti
958
1052
 
959
1053
  | Provider | OAuth 2.1 | API Key | Status |
960
1054
  |----------|-----------|---------|--------|
961
- | OpenAI | | | Production |
962
- | Anthropic | | | Production |
963
- | GitHub | | | Production |
964
- | Google | | | Production |
965
- | Azure AD | | | Production |
966
- | AWS Cognito | | | Production |
1055
+ | OpenAI | | | Production |
1056
+ | Anthropic | | | Production |
1057
+ | GitHub | | | Production |
1058
+ | Google | | | Production |
1059
+ | Azure AD | | | Production |
1060
+ | AWS Cognito | | | Production |
967
1061
 
968
1062
  ### Quick Start
969
1063
 
970
1064
  ```bash
971
1065
  # Check current authentication status
972
- node ./launch/index.js acp-registry --auth-status
1066
+ npx @stdiobus/workers-registry acp-registry --auth-status
973
1067
 
974
1068
  # Login with browser OAuth (opens browser)
975
- node ./launch/index.js acp-registry --login openai
1069
+ npx @stdiobus/workers-registry acp-registry --login openai
976
1070
 
977
1071
  # Interactive setup wizard
978
- node ./launch/index.js acp-registry --setup
1072
+ npx @stdiobus/workers-registry acp-registry --setup
979
1073
 
980
1074
  # Logout from all providers
981
- node ./launch/index.js acp-registry --logout
1075
+ npx @stdiobus/workers-registry acp-registry --logout
982
1076
  ```
983
1077
 
984
1078
  ### Backward Compatibility
@@ -1001,7 +1095,7 @@ echo '{"claude-acp":{"apiKey":"sk-..."}}' > api-keys.json
1001
1095
  export ANTHROPIC_API_KEY=sk-...
1002
1096
 
1003
1097
  # Option 3: Interactive setup (if TTY available)
1004
- node ./launch/index.js acp-registry --setup
1098
+ npx @stdiobus/workers-registry acp-registry --setup
1005
1099
  ```
1006
1100
 
1007
1101
  ### Documentation
@@ -1018,6 +1112,7 @@ node ./launch/index.js acp-registry --setup
1018
1112
  ## Resources
1019
1113
 
1020
1114
  - [stdio Bus kernel](https://github.com/stdiobus/stdiobus) - Core protocol and daemon (source code)
1115
+ - [`@stdiobus/node`](https://www.npmjs.com/package/@stdiobus/node) - Embedded Node.js binding (no Docker/binary needed)
1021
1116
  - [stdio Bus on Docker Hub](https://hub.docker.com/r/stdiobus/stdiobus) - Docker images for easy deployment
1022
1117
  - [stdio Bus Full Documentation](https://stdiobus.com) – Core protocol documentation
1023
1118
  - [ACP Registry](https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json) - Available ACP agents
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  import{Readable,Writable,Transform}from"node:stream";import{AgentSideConnection,ndJsonStream}from"@agentclientprotocol/sdk";import{PROTOCOL_VERSION}from"@agentclientprotocol/sdk";function loadConfig(){const baseUrl=process.env.OPENAI_BASE_URL||"https://api.openai.com/v1";const apiKey=process.env.OPENAI_API_KEY||"";const model=process.env.OPENAI_MODEL||"gpt-4o";const systemPrompt=process.env.OPENAI_SYSTEM_PROMPT||void 0;let maxTokens;const maxTokensStr=process.env.OPENAI_MAX_TOKENS;if(maxTokensStr!==void 0){const parsed=parseInt(maxTokensStr,10);maxTokens=Number.isNaN(parsed)?void 0:parsed}let temperature;const temperatureStr=process.env.OPENAI_TEMPERATURE;if(temperatureStr!==void 0){const parsed=parseFloat(temperatureStr);temperature=Number.isNaN(parsed)?void 0:parsed}if(!apiKey){console.error("[openai-agent] Warning: OPENAI_API_KEY is not set. This may be fine for local endpoints like Ollama.")}return{baseUrl,apiKey,model,systemPrompt,maxTokens,temperature}}import crypto from"node:crypto";var Session=class{id;cwd;_history=[];_abortController;_cancelled=false;constructor(id,cwd){this.id=id;this.cwd=cwd;this._abortController=new AbortController}getAbortSignal(){return this._abortController.signal}cancel(){this._cancelled=true;this._abortController.abort()}isCancelled(){return this._cancelled}resetCancellation(){this._cancelled=false;this._abortController=new AbortController}addHistoryEntry(role,content){this._history.push({role,content})}getHistory(){return[...this._history]}};var SessionManager=class{sessions=new Map;createSession(cwd){const id=crypto.randomUUID();const session=new Session(id,cwd);this.sessions.set(id,session);return session}getSession(id){return this.sessions.get(id)}cancelSession(id){const session=this.sessions.get(id);if(session){session.cancel();return true}return false}};var DATA_PREFIX="data: ";var DONE_MARKER="[DONE]";function parseLine(line){if(!line.trim()){return{type:"skip"}}if(line.startsWith(":")){return{type:"skip"}}if(!line.startsWith(DATA_PREFIX)){return{type:"skip"}}const data=line.slice(DATA_PREFIX.length);if(data===DONE_MARKER){return{type:"done"}}try{const payload=JSON.parse(data);return{type:"data",payload}}catch{console.error("[openai-agent] Failed to parse SSE JSON:",data);return{type:"skip"}}}function classifyHttpError(status,url){if(status===401||status===403){return`Authentication error (HTTP ${status}) calling ${url}. Check your OPENAI_API_KEY.`}if(status===429){return`Rate limit exceeded (HTTP 429) calling ${url}. Please retry later.`}if(status>=500){return`Server error (HTTP ${status}) from ${url}.`}return`HTTP error (${status}) from ${url}.`}var ChatCompletionsClient=class{config;constructor(config){this.config=config}async streamCompletion(messages,signal,onChunk){const url=`${this.config.baseUrl}/chat/completions`;const body={model:this.config.model,messages,stream:true};if(this.config.maxTokens!==void 0){body.max_tokens=this.config.maxTokens}if(this.config.temperature!==void 0){body.temperature=this.config.temperature}let response;try{response=await fetch(url,{method:"POST",headers:{"Authorization":`Bearer ${this.config.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(body),signal})}catch(error){if(error instanceof Error&&error.name==="AbortError"){return{stopReason:"cancelled",fullResponse:""}}const message=error instanceof Error?error.message:String(error);throw new Error(`Network error connecting to ${url}: ${message}`)}if(!response.ok){throw new Error(classifyHttpError(response.status,url))}if(!response.body){throw new Error(`No response body from ${url}.`)}let fullResponse="";const reader=response.body.getReader();const decoder=new TextDecoder;let buffer="";try{while(true){const{done,value}=await reader.read();if(done)break;buffer+=decoder.decode(value,{stream:true});const lines=buffer.split("\n");buffer=lines.pop()||"";for(const line of lines){const event=parseLine(line);if(event.type==="done"){return{stopReason:"end_turn",fullResponse}}if(event.type==="data"){const chunk=event.payload;const content=chunk.choices?.[0]?.delta?.content;if(content){fullResponse+=content;await onChunk(content)}}}}}catch(error){if(error instanceof Error&&error.name==="AbortError"){return{stopReason:"cancelled",fullResponse}}throw error}return{stopReason:"end_turn",fullResponse}}};function convertContentBlocks(blocks){const parts=[];for(const block of blocks){if(block.type==="text"){parts.push(block.text)}else if(block.type==="resource_link"){parts.push(`[Resource: ${block.name}] ${block.uri}`)}else if(block.type==="resource"){const text="text"in block.resource?block.resource.text:"";parts.push(`[Resource: ${block.resource.uri}]
3
- ${text}`)}else if(block.type==="image"){parts.push(`[Image: ${block.mimeType}]`)}}return parts.join("\n")}function buildMessages(systemPrompt,history,userMessage){const messages=[];if(systemPrompt){messages.push({role:"system",content:systemPrompt})}for(const entry of history){messages.push({role:entry.role,content:entry.content})}messages.push({role:"user",content:userMessage});return messages}var OpenAIAgent=class{connection;sessionManager;client;config;constructor(connection2){this.connection=connection2;this.sessionManager=new SessionManager;this.config=loadConfig();this.client=new ChatCompletionsClient(this.config)}async initialize(_params){return{protocolVersion:PROTOCOL_VERSION,agentInfo:{name:"openai-agent",version:"1.0.0"},agentCapabilities:{promptCapabilities:{embeddedContext:true}},authMethods:[]}}async newSession(params){const session=this.sessionManager.createSession(params.cwd);return{sessionId:session.id}}async loadSession(_params){throw new Error("Session loading is not supported")}async authenticate(_params){}async prompt(params){const session=this.sessionManager.getSession(params.sessionId);if(!session){throw new Error(`Session not found: ${params.sessionId}`)}if(session.isCancelled()){return{stopReason:"cancelled"}}session.resetCancellation();const userMessage=convertContentBlocks(params.prompt);session.addHistoryEntry("user",userMessage);const messages=buildMessages(this.config.systemPrompt,session.getHistory().slice(0,-1),userMessage);try{const result=await this.client.streamCompletion(messages,session.getAbortSignal(),async text=>{await this.connection.sessionUpdate({sessionId:params.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text}}})});if(result.stopReason==="cancelled"){return{stopReason:"cancelled"}}if(result.fullResponse){session.addHistoryEntry("assistant",result.fullResponse)}return{stopReason:"end_turn"}}catch(error){const errorMessage=error instanceof Error?error.message:String(error);await this.connection.sessionUpdate({sessionId:params.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:errorMessage}}});return{stopReason:"end_turn"}}}async cancel(params){this.sessionManager.cancelSession(params.sessionId)}};var SessionIdRouter=class{requestSessionIdMap=new Map;acpSessionIdMap=new Map;processIncomingLine(line){if(!line.trim()){return line}try{const msg=JSON.parse(line);const routingSessionId=this.readSessionId(msg.sessionId);const hasId=msg.id!==void 0&&msg.id!==null;if(hasId&&routingSessionId){this.requestSessionIdMap.set(msg.id,routingSessionId);console.error(`[worker] Saved sessionId="${routingSessionId}" for request id=${msg.id}`)}const paramsSessionId=this.readSessionId(msg.params?.sessionId);if(routingSessionId&&paramsSessionId){this.setAcpSessionMapping(paramsSessionId,routingSessionId,"request")}if(hasId&&routingSessionId){const{sessionId:_sessionId,...msgWithoutSession}=msg;return JSON.stringify(msgWithoutSession)}return line}catch{return line}}processOutgoingLine(line){if(!line.trim()){return line}try{const msg=JSON.parse(line);const hasId=msg.id!==void 0&&msg.id!==null;if(hasId&&this.requestSessionIdMap.has(msg.id)){const routingSessionId=this.requestSessionIdMap.get(msg.id);this.requestSessionIdMap.delete(msg.id);if(routingSessionId){const resultSessionId=this.readSessionId(msg.result?.sessionId);if(resultSessionId){this.setAcpSessionMapping(resultSessionId,routingSessionId,"response")}const msgWithSession={...msg,sessionId:routingSessionId};console.error(`[worker] Restored sessionId="${routingSessionId}" for response id=${msg.id}`);return JSON.stringify(msgWithSession)}}if(!hasId&&!this.readSessionId(msg.sessionId)){const paramsSessionId=this.readSessionId(msg.params?.sessionId);if(paramsSessionId){const routingSessionId=this.acpSessionIdMap.get(paramsSessionId);if(routingSessionId){const msgWithSession={...msg,sessionId:routingSessionId};return JSON.stringify(msgWithSession)}}}return line}catch{return line}}readSessionId(value){return typeof value==="string"&&value.length>0?value:null}setAcpSessionMapping(acpSessionId,routingSessionId,source){const existing=this.acpSessionIdMap.get(acpSessionId);if(existing===routingSessionId){return}this.acpSessionIdMap.set(acpSessionId,routingSessionId);console.error(`[worker] Mapped ACP sessionId="${acpSessionId}" to routing sessionId="${routingSessionId}" (${source})`)}};console.error("[openai-agent] Starting OpenAI Agent Worker...");var sessionIdRouter=new SessionIdRouter;var stdinTransform=new Transform({objectMode:false,transform(chunk,_encoding,callback){const lines=chunk.toString().split("\n");const processedLines=[];for(const line of lines){processedLines.push(sessionIdRouter.processIncomingLine(line))}callback(null,Buffer.from(processedLines.join("\n")))}});var stdoutTransform=new Transform({objectMode:false,transform(chunk,_encoding,callback){const lines=chunk.toString().split("\n");const processedLines=[];for(const line of lines){processedLines.push(sessionIdRouter.processOutgoingLine(line))}callback(null,Buffer.from(processedLines.join("\n")))}});process.stdin.pipe(stdinTransform);var inputStream=Readable.toWeb(stdinTransform);var outputStream=Writable.toWeb(stdoutTransform);stdoutTransform.pipe(process.stdout);var stream=ndJsonStream(outputStream,inputStream);var connection=new AgentSideConnection(conn=>new OpenAIAgent(conn),stream);console.error("[openai-agent] AgentSideConnection established, ready for messages");process.on("SIGTERM",async()=>{console.error("[openai-agent] Received SIGTERM, shutting down...");await connection.closed;process.exit(0)});process.on("SIGINT",async()=>{console.error("[openai-agent] Received SIGINT, shutting down...");await connection.closed;process.exit(0)});process.on("uncaughtException",error=>{console.error("[openai-agent] Uncaught exception:",error);process.exit(1)});process.on("unhandledRejection",(reason,promise)=>{console.error("[openai-agent] Unhandled rejection at:",promise,"reason:",reason)});connection.closed.then(()=>{console.error("[openai-agent] Connection closed");process.exit(0)}).catch(error=>{console.error("[openai-agent] Connection error:",error);process.exit(1)});
3
+ ${text}`)}else if(block.type==="image"){parts.push(`[Image: ${block.mimeType}]`)}}return parts.join("\n")}function buildMessages(systemPrompt,history,userMessage){const messages=[];if(systemPrompt){messages.push({role:"system",content:systemPrompt})}for(const entry of history){messages.push({role:entry.role,content:entry.content})}messages.push({role:"user",content:userMessage});return messages}var OpenAIAgent=class{connection;sessionManager;client;config;constructor(connection2){this.connection=connection2;this.sessionManager=new SessionManager;this.config=loadConfig();this.client=new ChatCompletionsClient(this.config)}async initialize(_params){return{protocolVersion:PROTOCOL_VERSION,agentInfo:{name:"openai-agent",version:"1.0.0"},agentCapabilities:{promptCapabilities:{embeddedContext:true}},authMethods:[{id:"oauth2",name:"OAuth 2.1 Authentication",description:"Authenticate through agent via OAuth 2.1 flow",_meta:{"agent-auth":true}}]}}async newSession(params){const session=this.sessionManager.createSession(params.cwd);return{sessionId:session.id}}async loadSession(_params){throw new Error("Session loading is not supported")}async authenticate(_params){}async prompt(params){const session=this.sessionManager.getSession(params.sessionId);if(!session){throw new Error(`Session not found: ${params.sessionId}`)}if(session.isCancelled()){return{stopReason:"cancelled"}}session.resetCancellation();const userMessage=convertContentBlocks(params.prompt);session.addHistoryEntry("user",userMessage);const messages=buildMessages(this.config.systemPrompt,session.getHistory().slice(0,-1),userMessage);try{const result=await this.client.streamCompletion(messages,session.getAbortSignal(),async text=>{await this.connection.sessionUpdate({sessionId:params.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text}}})});if(result.stopReason==="cancelled"){return{stopReason:"cancelled"}}if(result.fullResponse){session.addHistoryEntry("assistant",result.fullResponse)}return{stopReason:"end_turn"}}catch(error){const errorMessage=error instanceof Error?error.message:String(error);await this.connection.sessionUpdate({sessionId:params.sessionId,update:{sessionUpdate:"agent_message_chunk",content:{type:"text",text:errorMessage}}});return{stopReason:"end_turn"}}}async cancel(params){this.sessionManager.cancelSession(params.sessionId)}};var SessionIdRouter=class{requestSessionIdMap=new Map;acpSessionIdMap=new Map;processIncomingLine(line){if(!line.trim()){return line}try{const msg=JSON.parse(line);const routingSessionId=this.readSessionId(msg.sessionId);const hasId=msg.id!==void 0&&msg.id!==null;if(hasId&&routingSessionId){this.requestSessionIdMap.set(msg.id,routingSessionId);console.error(`[worker] Saved sessionId="${routingSessionId}" for request id=${msg.id}`)}const paramsSessionId=this.readSessionId(msg.params?.sessionId);if(routingSessionId&&paramsSessionId){this.setAcpSessionMapping(paramsSessionId,routingSessionId,"request")}if(hasId&&routingSessionId){const{sessionId:_sessionId,...msgWithoutSession}=msg;return JSON.stringify(msgWithoutSession)}return line}catch{return line}}processOutgoingLine(line){if(!line.trim()){return line}try{const msg=JSON.parse(line);const hasId=msg.id!==void 0&&msg.id!==null;if(hasId&&this.requestSessionIdMap.has(msg.id)){const routingSessionId=this.requestSessionIdMap.get(msg.id);this.requestSessionIdMap.delete(msg.id);if(routingSessionId){const resultSessionId=this.readSessionId(msg.result?.sessionId);if(resultSessionId){this.setAcpSessionMapping(resultSessionId,routingSessionId,"response")}const msgWithSession={...msg,sessionId:routingSessionId};console.error(`[worker] Restored sessionId="${routingSessionId}" for response id=${msg.id}`);return JSON.stringify(msgWithSession)}}if(!hasId&&!this.readSessionId(msg.sessionId)){const paramsSessionId=this.readSessionId(msg.params?.sessionId);if(paramsSessionId){const routingSessionId=this.acpSessionIdMap.get(paramsSessionId);if(routingSessionId){const msgWithSession={...msg,sessionId:routingSessionId};return JSON.stringify(msgWithSession)}}}return line}catch{return line}}readSessionId(value){return typeof value==="string"&&value.length>0?value:null}setAcpSessionMapping(acpSessionId,routingSessionId,source){const existing=this.acpSessionIdMap.get(acpSessionId);if(existing===routingSessionId){return}this.acpSessionIdMap.set(acpSessionId,routingSessionId);console.error(`[worker] Mapped ACP sessionId="${acpSessionId}" to routing sessionId="${routingSessionId}" (${source})`)}};console.error("[openai-agent] Starting OpenAI Agent Worker...");var sessionIdRouter=new SessionIdRouter;var stdinTransform=new Transform({objectMode:false,transform(chunk,_encoding,callback){const lines=chunk.toString().split("\n");const processedLines=[];for(const line of lines){processedLines.push(sessionIdRouter.processIncomingLine(line))}callback(null,Buffer.from(processedLines.join("\n")))}});var stdoutTransform=new Transform({objectMode:false,transform(chunk,_encoding,callback){const lines=chunk.toString().split("\n");const processedLines=[];for(const line of lines){processedLines.push(sessionIdRouter.processOutgoingLine(line))}callback(null,Buffer.from(processedLines.join("\n")))}});process.stdin.pipe(stdinTransform);var inputStream=Readable.toWeb(stdinTransform);var outputStream=Writable.toWeb(stdoutTransform);stdoutTransform.pipe(process.stdout);var stream=ndJsonStream(outputStream,inputStream);var connection=new AgentSideConnection(conn=>new OpenAIAgent(conn),stream);console.error("[openai-agent] AgentSideConnection established, ready for messages");process.on("SIGTERM",async()=>{console.error("[openai-agent] Received SIGTERM, shutting down...");await connection.closed;process.exit(0)});process.on("SIGINT",async()=>{console.error("[openai-agent] Received SIGINT, shutting down...");await connection.closed;process.exit(0)});process.on("uncaughtException",error=>{console.error("[openai-agent] Uncaught exception:",error);process.exit(1)});process.on("unhandledRejection",(reason,promise)=>{console.error("[openai-agent] Unhandled rejection at:",promise,"reason:",reason)});connection.closed.then(()=>{console.error("[openai-agent] Connection closed");process.exit(0)}).catch(error=>{console.error("[openai-agent] Connection error:",error);process.exit(1)});
4
4
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../workers-registry/openai-agent/src/index.ts", "../../../../workers-registry/openai-agent/src/agent.ts", "../../../../workers-registry/openai-agent/src/config.ts", "../../../../workers-registry/openai-agent/src/session-manager.ts", "../../../../workers-registry/openai-agent/src/session.ts", "../../../../workers-registry/openai-agent/src/sse-parser.ts", "../../../../workers-registry/openai-agent/src/client.ts", "../../../../workers-registry/openai-agent/src/session-id-router.ts"],
4
- "sourcesContent": ["/*\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 * OpenAI Agent Worker for stdio Bus kernel\n *\n * This worker implements the Agent Client Protocol (ACP) and bridges\n * to any OpenAI Chat Completions API-compatible endpoint.\n *\n * It runs as a child process of stdio Bus kernel, communicating via stdin/stdout NDJSON.\n *\n * @module index\n */\n\nimport { Readable, Writable, Transform } from 'node:stream';\nimport { AgentSideConnection, ndJsonStream } from '@agentclientprotocol/sdk';\nimport { OpenAIAgent } from './agent.js';\nimport { SessionIdRouter } from './session-id-router.js';\n\n// Log startup message to stderr (not stdout - stdout is for protocol messages)\nconsole.error('[openai-agent] Starting OpenAI Agent Worker...');\n\nconst sessionIdRouter = new SessionIdRouter();\n\n/**\n * Transform stream to intercept stdin and save sessionId from requests.\n * Removes sessionId before passing to ACP SDK (SDK doesn't know about it).\n */\nconst stdinTransform = new Transform({\n objectMode: false,\n transform(chunk: Buffer, _encoding, callback) {\n const lines = chunk.toString().split('\\n');\n const processedLines: string[] = [];\n\n for (const line of lines) {\n processedLines.push(sessionIdRouter.processIncomingLine(line));\n }\n\n callback(null, Buffer.from(processedLines.join('\\n')));\n },\n});\n\n/**\n * Transform stream to intercept stdout and restore sessionId in responses.\n * Adds sessionId back for stdio_bus routing.\n */\nconst stdoutTransform = new Transform({\n objectMode: false,\n transform(chunk: Buffer, _encoding, callback) {\n const lines = chunk.toString().split('\\n');\n const processedLines: string[] = [];\n\n for (const line of lines) {\n processedLines.push(sessionIdRouter.processOutgoingLine(line));\n }\n\n callback(null, Buffer.from(processedLines.join('\\n')));\n },\n});\n\n// Pipe stdin through transform before SDK\nprocess.stdin.pipe(stdinTransform);\n\n/**\n * Convert transformed stdin to web ReadableStream for SDK.\n */\nconst inputStream = Readable.toWeb(stdinTransform) as ReadableStream<Uint8Array>;\n\n/**\n * Convert stdout transform to web WritableStream for SDK.\n */\nconst outputStream = Writable.toWeb(stdoutTransform) as WritableStream<Uint8Array>;\n\n// Pipe transform output to actual stdout\nstdoutTransform.pipe(process.stdout);\n\n/**\n * Create the NDJSON stream for ACP communication.\n * The SDK handles all NDJSON framing and JSON-RPC protocol details automatically.\n */\nconst stream = ndJsonStream(outputStream, inputStream);\n\n/**\n * Create the AgentSideConnection with stdio transport.\n *\n * The SDK pattern uses a factory function that receives the connection\n * and returns an Agent instance. The SDK handles all NDJSON framing\n * and JSON-RPC protocol details automatically.\n */\nconst connection = new AgentSideConnection(\n (conn) => new OpenAIAgent(conn),\n stream,\n);\n\n// Log that connection is established\nconsole.error('[openai-agent] AgentSideConnection established, ready for messages');\n\n/**\n * Handle graceful shutdown on SIGTERM.\n *\n * When stdio Bus kernel sends SIGTERM, we should wait for the connection to close\n * and allow pending operations to complete.\n */\nprocess.on('SIGTERM', async () => {\n console.error('[openai-agent] Received SIGTERM, shutting down...');\n await connection.closed;\n process.exit(0);\n});\n\n/**\n * Handle SIGINT for development convenience.\n */\nprocess.on('SIGINT', async () => {\n console.error('[openai-agent] Received SIGINT, shutting down...');\n await connection.closed;\n process.exit(0);\n});\n\n/**\n * Handle uncaught exceptions to prevent silent failures.\n */\nprocess.on('uncaughtException', (error) => {\n console.error('[openai-agent] Uncaught exception:', error);\n process.exit(1);\n});\n\n/**\n * Handle unhandled promise rejections.\n */\nprocess.on('unhandledRejection', (reason, promise) => {\n console.error('[openai-agent] Unhandled rejection at:', promise, 'reason:', reason);\n});\n\n/**\n * Wait for the connection to close (either normally or due to error).\n * This keeps the process running until the connection ends.\n */\nconnection.closed.then(() => {\n console.error('[openai-agent] Connection closed');\n process.exit(0);\n}).catch((error) => {\n console.error('[openai-agent] Connection error:', error);\n process.exit(1);\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\nimport type {\n Agent,\n AgentSideConnection,\n AuthenticateRequest,\n AuthenticateResponse,\n CancelNotification,\n ContentBlock,\n InitializeRequest,\n InitializeResponse,\n LoadSessionRequest,\n LoadSessionResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n} from '@agentclientprotocol/sdk';\nimport { PROTOCOL_VERSION } from '@agentclientprotocol/sdk';\nimport { loadConfig } from './config.js';\nimport { SessionManager } from './session-manager.js';\nimport { ChatCompletionsClient } from './client.js';\nimport type { OpenAIMessage } from './types.js';\n\n/**\n * Convert ACP content blocks to a single user message string.\n */\nexport function convertContentBlocks(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const block of blocks) {\n if (block.type === 'text') {\n parts.push(block.text);\n } else if (block.type === 'resource_link') {\n parts.push(`[Resource: ${block.name}] ${block.uri}`);\n } else if (block.type === 'resource') {\n const text = 'text' in block.resource ? block.resource.text : '';\n parts.push(`[Resource: ${block.resource.uri}]\\n${text}`);\n } else if (block.type === 'image') {\n parts.push(`[Image: ${block.mimeType}]`);\n }\n }\n return parts.join('\\n');\n}\n\n/**\n * Build the full messages array for the Chat Completions API.\n */\nexport function buildMessages(\n systemPrompt: string | undefined,\n history: Array<{ role: 'user' | 'assistant'; content: string }>,\n userMessage: string,\n): OpenAIMessage[] {\n const messages: OpenAIMessage[] = [];\n if (systemPrompt) {\n messages.push({ role: 'system', content: systemPrompt });\n }\n for (const entry of history) {\n messages.push({ role: entry.role, content: entry.content });\n }\n messages.push({ role: 'user', content: userMessage });\n return messages;\n}\n\nexport class OpenAIAgent implements Agent {\n private readonly connection: AgentSideConnection;\n private readonly sessionManager: SessionManager;\n private readonly client: ChatCompletionsClient;\n private readonly config;\n\n constructor(connection: AgentSideConnection) {\n this.connection = connection;\n this.sessionManager = new SessionManager();\n this.config = loadConfig();\n this.client = new ChatCompletionsClient(this.config);\n }\n\n async initialize(_params: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentInfo: {\n name: 'openai-agent',\n version: '1.0.0',\n },\n agentCapabilities: {\n promptCapabilities: {\n embeddedContext: true,\n },\n },\n authMethods: [],\n };\n }\n\n async newSession(params: NewSessionRequest): Promise<NewSessionResponse> {\n const session = this.sessionManager.createSession(params.cwd);\n return { sessionId: session.id };\n }\n\n async loadSession(_params: LoadSessionRequest): Promise<LoadSessionResponse> {\n throw new Error('Session loading is not supported');\n }\n\n async authenticate(_params: AuthenticateRequest): Promise<AuthenticateResponse | void> {\n // No authentication needed at ACP level\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.sessionManager.getSession(params.sessionId);\n if (!session) {\n throw new Error(`Session not found: ${params.sessionId}`);\n }\n\n if (session.isCancelled()) {\n return { stopReason: 'cancelled' };\n }\n\n session.resetCancellation();\n\n const userMessage = convertContentBlocks(params.prompt);\n session.addHistoryEntry('user', userMessage);\n\n const messages = buildMessages(\n this.config.systemPrompt,\n session.getHistory().slice(0, -1),\n userMessage,\n );\n\n try {\n const result = await this.client.streamCompletion(\n messages,\n session.getAbortSignal(),\n async (text) => {\n await this.connection.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text },\n },\n });\n },\n );\n\n if (result.stopReason === 'cancelled') {\n return { stopReason: 'cancelled' };\n }\n\n if (result.fullResponse) {\n session.addHistoryEntry('assistant', result.fullResponse);\n }\n\n return { stopReason: 'end_turn' };\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n await this.connection.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: errorMessage },\n },\n });\n return { stopReason: 'end_turn' };\n }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n this.sessionManager.cancelSession(params.sessionId);\n }\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\nimport { AgentConfig } from './types.js';\n\nexport function loadConfig(): AgentConfig {\n const baseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';\n const apiKey = process.env.OPENAI_API_KEY || '';\n const model = process.env.OPENAI_MODEL || 'gpt-4o';\n const systemPrompt = process.env.OPENAI_SYSTEM_PROMPT || undefined;\n\n let maxTokens: number | undefined;\n const maxTokensStr = process.env.OPENAI_MAX_TOKENS;\n if (maxTokensStr !== undefined) {\n const parsed = parseInt(maxTokensStr, 10);\n maxTokens = Number.isNaN(parsed) ? undefined : parsed;\n }\n\n let temperature: number | undefined;\n const temperatureStr = process.env.OPENAI_TEMPERATURE;\n if (temperatureStr !== undefined) {\n const parsed = parseFloat(temperatureStr);\n temperature = Number.isNaN(parsed) ? undefined : parsed;\n }\n\n if (!apiKey) {\n console.error('[openai-agent] Warning: OPENAI_API_KEY is not set. This may be fine for local endpoints like Ollama.');\n }\n\n return { baseUrl, apiKey, model, systemPrompt, maxTokens, temperature };\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\nimport crypto from 'node:crypto';\nimport { Session } from './session.js';\n\nexport class SessionManager {\n private readonly sessions = new Map<string, Session>();\n\n createSession(cwd: string): Session {\n const id = crypto.randomUUID();\n const session = new Session(id, cwd);\n this.sessions.set(id, session);\n return session;\n }\n\n getSession(id: string): Session | undefined {\n return this.sessions.get(id);\n }\n\n cancelSession(id: string): boolean {\n const session = this.sessions.get(id);\n if (session) {\n session.cancel();\n return true;\n }\n return false;\n }\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\nexport interface HistoryEntry {\n role: 'user' | 'assistant';\n content: string;\n}\n\nexport class Session {\n readonly id: string;\n readonly cwd: string;\n private _history: HistoryEntry[] = [];\n private _abortController: AbortController;\n private _cancelled = false;\n\n constructor(id: string, cwd: string) {\n this.id = id;\n this.cwd = cwd;\n this._abortController = new AbortController();\n }\n\n getAbortSignal(): AbortSignal {\n return this._abortController.signal;\n }\n\n cancel(): void {\n this._cancelled = true;\n this._abortController.abort();\n }\n\n isCancelled(): boolean {\n return this._cancelled;\n }\n\n resetCancellation(): void {\n this._cancelled = false;\n this._abortController = new AbortController();\n }\n\n addHistoryEntry(role: 'user' | 'assistant', content: string): void {\n this._history.push({ role, content });\n }\n\n getHistory(): HistoryEntry[] {\n return [...this._history];\n }\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\nimport { SSEEvent } from './types.js';\n\nconst DATA_PREFIX = 'data: ';\nconst DONE_MARKER = '[DONE]';\n\nexport function parseLine(line: string): SSEEvent {\n // Skip empty lines and whitespace-only lines\n if (!line.trim()) {\n return { type: 'skip' };\n }\n\n // Skip SSE comments (lines starting with :)\n if (line.startsWith(':')) {\n return { type: 'skip' };\n }\n\n // Check for data: prefix\n if (!line.startsWith(DATA_PREFIX)) {\n return { type: 'skip' };\n }\n\n const data = line.slice(DATA_PREFIX.length);\n\n // Check for [DONE] marker\n if (data === DONE_MARKER) {\n return { type: 'done' };\n }\n\n // Try to parse JSON\n try {\n const payload = JSON.parse(data);\n return { type: 'data', payload };\n } catch {\n console.error('[openai-agent] Failed to parse SSE JSON:', data);\n return { type: 'skip' };\n }\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\nimport { AgentConfig, ChatCompletionResult, ChatCompletionsRequest, OpenAIMessage, SSEChunk } from './types.js';\nimport { parseLine } from './sse-parser.js';\n\nexport function classifyHttpError(status: number, url: string): string {\n if (status === 401 || status === 403) {\n return `Authentication error (HTTP ${status}) calling ${url}. Check your OPENAI_API_KEY.`;\n }\n if (status === 429) {\n return `Rate limit exceeded (HTTP 429) calling ${url}. Please retry later.`;\n }\n if (status >= 500) {\n return `Server error (HTTP ${status}) from ${url}.`;\n }\n return `HTTP error (${status}) from ${url}.`;\n}\n\nexport class ChatCompletionsClient {\n private readonly config: AgentConfig;\n\n constructor(config: AgentConfig) {\n this.config = config;\n }\n\n async streamCompletion(\n messages: OpenAIMessage[],\n signal: AbortSignal,\n onChunk: (text: string) => Promise<void>,\n ): Promise<ChatCompletionResult> {\n const url = `${this.config.baseUrl}/chat/completions`;\n const body: ChatCompletionsRequest = {\n model: this.config.model,\n messages,\n stream: true,\n };\n if (this.config.maxTokens !== undefined) {\n body.max_tokens = this.config.maxTokens;\n }\n if (this.config.temperature !== undefined) {\n body.temperature = this.config.temperature;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return { stopReason: 'cancelled', fullResponse: '' };\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Network error connecting to ${url}: ${message}`);\n }\n\n if (!response.ok) {\n throw new Error(classifyHttpError(response.status, url));\n }\n\n if (!response.body) {\n throw new Error(`No response body from ${url}.`);\n }\n\n let fullResponse = '';\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last potentially incomplete line in the buffer\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const event = parseLine(line);\n if (event.type === 'done') {\n return { stopReason: 'end_turn', fullResponse };\n }\n if (event.type === 'data') {\n const chunk = event.payload as SSEChunk;\n const content = chunk.choices?.[0]?.delta?.content;\n if (content) {\n fullResponse += content;\n await onChunk(content);\n }\n }\n }\n }\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return { stopReason: 'cancelled', fullResponse };\n }\n throw error;\n }\n\n return { stopReason: 'end_turn', fullResponse };\n }\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 * Session ID routing helper for stdio Bus \u2194 ACP messages.\n *\n * Tracks request IDs to restore stdio Bus sessionId on responses,\n * and maps ACP sessionId to stdio Bus sessionId for notifications.\n */\n\ntype JsonRecord = Record<string, unknown>;\n\nexport class SessionIdRouter {\n private readonly requestSessionIdMap = new Map<string | number, string>();\n private readonly acpSessionIdMap = new Map<string, string>();\n\n /**\n * Process a single inbound (stdin) line.\n *\n * - Saves stdio Bus sessionId for request/response correlation\n * - Tracks ACP sessionId \u2194 stdio Bus sessionId mapping when available\n * - Strips stdio Bus sessionId before passing to ACP SDK\n */\n processIncomingLine(line: string): string {\n if (!line.trim()) {\n return line;\n }\n\n try {\n const msg = JSON.parse(line) as JsonRecord;\n const routingSessionId = this.readSessionId(msg.sessionId);\n const hasId = msg.id !== undefined && msg.id !== null;\n\n if (hasId && routingSessionId) {\n this.requestSessionIdMap.set(msg.id as string | number, routingSessionId);\n console.error(`[worker] Saved sessionId=\"${routingSessionId}\" for request id=${msg.id}`);\n }\n\n const paramsSessionId = this.readSessionId((msg.params as JsonRecord | undefined)?.sessionId);\n if (routingSessionId && paramsSessionId) {\n this.setAcpSessionMapping(paramsSessionId, routingSessionId, 'request');\n }\n\n if (hasId && routingSessionId) {\n const { sessionId: _sessionId, ...msgWithoutSession } = msg;\n return JSON.stringify(msgWithoutSession);\n }\n\n return line;\n } catch {\n return line;\n }\n }\n\n /**\n * Process a single outbound (stdout) line.\n *\n * - Restores stdio Bus sessionId on responses using request mapping\n * - Maps ACP sessionId to stdio Bus sessionId for notifications\n */\n processOutgoingLine(line: string): string {\n if (!line.trim()) {\n return line;\n }\n\n try {\n const msg = JSON.parse(line) as JsonRecord;\n const hasId = msg.id !== undefined && msg.id !== null;\n\n if (hasId && this.requestSessionIdMap.has(msg.id as string | number)) {\n const routingSessionId = this.requestSessionIdMap.get(msg.id as string | number);\n this.requestSessionIdMap.delete(msg.id as string | number);\n\n if (routingSessionId) {\n const resultSessionId = this.readSessionId(\n (msg.result as JsonRecord | undefined)?.sessionId,\n );\n if (resultSessionId) {\n this.setAcpSessionMapping(resultSessionId, routingSessionId, 'response');\n }\n\n const msgWithSession = { ...msg, sessionId: routingSessionId };\n console.error(\n `[worker] Restored sessionId=\"${routingSessionId}\" for response id=${msg.id}`,\n );\n return JSON.stringify(msgWithSession);\n }\n }\n\n if (!hasId && !this.readSessionId(msg.sessionId)) {\n const paramsSessionId = this.readSessionId(\n (msg.params as JsonRecord | undefined)?.sessionId,\n );\n if (paramsSessionId) {\n const routingSessionId = this.acpSessionIdMap.get(paramsSessionId);\n if (routingSessionId) {\n const msgWithSession = { ...msg, sessionId: routingSessionId };\n return JSON.stringify(msgWithSession);\n }\n }\n }\n\n return line;\n } catch {\n return line;\n }\n }\n\n private readSessionId(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n }\n\n private setAcpSessionMapping(\n acpSessionId: string,\n routingSessionId: string,\n source: 'request' | 'response',\n ): void {\n const existing = this.acpSessionIdMap.get(acpSessionId);\n if (existing === routingSessionId) {\n return;\n }\n\n this.acpSessionIdMap.set(acpSessionId, routingSessionId);\n console.error(\n `[worker] Mapped ACP sessionId=\"${acpSessionId}\" ` +\n `to routing sessionId=\"${routingSessionId}\" (${source})`,\n );\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/*\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 * OpenAI Agent Worker for stdio Bus kernel\n *\n * This worker implements the Agent Client Protocol (ACP) and bridges\n * to any OpenAI Chat Completions API-compatible endpoint.\n *\n * It runs as a child process of stdio Bus kernel, communicating via stdin/stdout NDJSON.\n *\n * @module index\n */\n\nimport { Readable, Writable, Transform } from 'node:stream';\nimport { AgentSideConnection, ndJsonStream } from '@agentclientprotocol/sdk';\nimport { OpenAIAgent } from './agent.js';\nimport { SessionIdRouter } from './session-id-router.js';\n\n// Log startup message to stderr (not stdout - stdout is for protocol messages)\nconsole.error('[openai-agent] Starting OpenAI Agent Worker...');\n\nconst sessionIdRouter = new SessionIdRouter();\n\n/**\n * Transform stream to intercept stdin and save sessionId from requests.\n * Removes sessionId before passing to ACP SDK (SDK doesn't know about it).\n */\nconst stdinTransform = new Transform({\n objectMode: false,\n transform(chunk: Buffer, _encoding, callback) {\n const lines = chunk.toString().split('\\n');\n const processedLines: string[] = [];\n\n for (const line of lines) {\n processedLines.push(sessionIdRouter.processIncomingLine(line));\n }\n\n callback(null, Buffer.from(processedLines.join('\\n')));\n },\n});\n\n/**\n * Transform stream to intercept stdout and restore sessionId in responses.\n * Adds sessionId back for stdio_bus routing.\n */\nconst stdoutTransform = new Transform({\n objectMode: false,\n transform(chunk: Buffer, _encoding, callback) {\n const lines = chunk.toString().split('\\n');\n const processedLines: string[] = [];\n\n for (const line of lines) {\n processedLines.push(sessionIdRouter.processOutgoingLine(line));\n }\n\n callback(null, Buffer.from(processedLines.join('\\n')));\n },\n});\n\n// Pipe stdin through transform before SDK\nprocess.stdin.pipe(stdinTransform);\n\n/**\n * Convert transformed stdin to web ReadableStream for SDK.\n */\nconst inputStream = Readable.toWeb(stdinTransform) as ReadableStream<Uint8Array>;\n\n/**\n * Convert stdout transform to web WritableStream for SDK.\n */\nconst outputStream = Writable.toWeb(stdoutTransform) as WritableStream<Uint8Array>;\n\n// Pipe transform output to actual stdout\nstdoutTransform.pipe(process.stdout);\n\n/**\n * Create the NDJSON stream for ACP communication.\n * The SDK handles all NDJSON framing and JSON-RPC protocol details automatically.\n */\nconst stream = ndJsonStream(outputStream, inputStream);\n\n/**\n * Create the AgentSideConnection with stdio transport.\n *\n * The SDK pattern uses a factory function that receives the connection\n * and returns an Agent instance. The SDK handles all NDJSON framing\n * and JSON-RPC protocol details automatically.\n */\nconst connection = new AgentSideConnection(\n (conn) => new OpenAIAgent(conn),\n stream,\n);\n\n// Log that connection is established\nconsole.error('[openai-agent] AgentSideConnection established, ready for messages');\n\n/**\n * Handle graceful shutdown on SIGTERM.\n *\n * When stdio Bus kernel sends SIGTERM, we should wait for the connection to close\n * and allow pending operations to complete.\n */\nprocess.on('SIGTERM', async () => {\n console.error('[openai-agent] Received SIGTERM, shutting down...');\n await connection.closed;\n process.exit(0);\n});\n\n/**\n * Handle SIGINT for development convenience.\n */\nprocess.on('SIGINT', async () => {\n console.error('[openai-agent] Received SIGINT, shutting down...');\n await connection.closed;\n process.exit(0);\n});\n\n/**\n * Handle uncaught exceptions to prevent silent failures.\n */\nprocess.on('uncaughtException', (error) => {\n console.error('[openai-agent] Uncaught exception:', error);\n process.exit(1);\n});\n\n/**\n * Handle unhandled promise rejections.\n */\nprocess.on('unhandledRejection', (reason, promise) => {\n console.error('[openai-agent] Unhandled rejection at:', promise, 'reason:', reason);\n});\n\n/**\n * Wait for the connection to close (either normally or due to error).\n * This keeps the process running until the connection ends.\n */\nconnection.closed.then(() => {\n console.error('[openai-agent] Connection closed');\n process.exit(0);\n}).catch((error) => {\n console.error('[openai-agent] Connection error:', error);\n process.exit(1);\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\nimport type {\n Agent,\n AgentSideConnection,\n AuthenticateRequest,\n AuthenticateResponse,\n CancelNotification,\n ContentBlock,\n InitializeRequest,\n InitializeResponse,\n LoadSessionRequest,\n LoadSessionResponse,\n NewSessionRequest,\n NewSessionResponse,\n PromptRequest,\n PromptResponse,\n} from '@agentclientprotocol/sdk';\nimport { PROTOCOL_VERSION } from '@agentclientprotocol/sdk';\nimport { loadConfig } from './config.js';\nimport { SessionManager } from './session-manager.js';\nimport { ChatCompletionsClient } from './client.js';\nimport type { OpenAIMessage } from './types.js';\n\n/**\n * Convert ACP content blocks to a single user message string.\n */\nexport function convertContentBlocks(blocks: ContentBlock[]): string {\n const parts: string[] = [];\n for (const block of blocks) {\n if (block.type === 'text') {\n parts.push(block.text);\n } else if (block.type === 'resource_link') {\n parts.push(`[Resource: ${block.name}] ${block.uri}`);\n } else if (block.type === 'resource') {\n const text = 'text' in block.resource ? block.resource.text : '';\n parts.push(`[Resource: ${block.resource.uri}]\\n${text}`);\n } else if (block.type === 'image') {\n parts.push(`[Image: ${block.mimeType}]`);\n }\n }\n return parts.join('\\n');\n}\n\n/**\n * Build the full messages array for the Chat Completions API.\n */\nexport function buildMessages(\n systemPrompt: string | undefined,\n history: Array<{ role: 'user' | 'assistant'; content: string }>,\n userMessage: string,\n): OpenAIMessage[] {\n const messages: OpenAIMessage[] = [];\n if (systemPrompt) {\n messages.push({ role: 'system', content: systemPrompt });\n }\n for (const entry of history) {\n messages.push({ role: entry.role, content: entry.content });\n }\n messages.push({ role: 'user', content: userMessage });\n return messages;\n}\n\nexport class OpenAIAgent implements Agent {\n private readonly connection: AgentSideConnection;\n private readonly sessionManager: SessionManager;\n private readonly client: ChatCompletionsClient;\n private readonly config;\n\n constructor(connection: AgentSideConnection) {\n this.connection = connection;\n this.sessionManager = new SessionManager();\n this.config = loadConfig();\n this.client = new ChatCompletionsClient(this.config);\n }\n\n async initialize(_params: InitializeRequest): Promise<InitializeResponse> {\n return {\n protocolVersion: PROTOCOL_VERSION,\n agentInfo: {\n name: 'openai-agent',\n version: '1.0.0',\n },\n agentCapabilities: {\n promptCapabilities: {\n embeddedContext: true,\n },\n },\n authMethods: [\n {\n id: 'oauth2',\n name: 'OAuth 2.1 Authentication',\n description: 'Authenticate through agent via OAuth 2.1 flow',\n _meta: { 'agent-auth': true },\n },\n ],\n };\n }\n\n async newSession(params: NewSessionRequest): Promise<NewSessionResponse> {\n const session = this.sessionManager.createSession(params.cwd);\n return { sessionId: session.id };\n }\n\n async loadSession(_params: LoadSessionRequest): Promise<LoadSessionResponse> {\n throw new Error('Session loading is not supported');\n }\n\n async authenticate(_params: AuthenticateRequest): Promise<AuthenticateResponse | void> {\n // No authentication needed at ACP level\n }\n\n async prompt(params: PromptRequest): Promise<PromptResponse> {\n const session = this.sessionManager.getSession(params.sessionId);\n if (!session) {\n throw new Error(`Session not found: ${params.sessionId}`);\n }\n\n if (session.isCancelled()) {\n return { stopReason: 'cancelled' };\n }\n\n session.resetCancellation();\n\n const userMessage = convertContentBlocks(params.prompt);\n session.addHistoryEntry('user', userMessage);\n\n const messages = buildMessages(\n this.config.systemPrompt,\n session.getHistory().slice(0, -1),\n userMessage,\n );\n\n try {\n const result = await this.client.streamCompletion(\n messages,\n session.getAbortSignal(),\n async (text) => {\n await this.connection.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text },\n },\n });\n },\n );\n\n if (result.stopReason === 'cancelled') {\n return { stopReason: 'cancelled' };\n }\n\n if (result.fullResponse) {\n session.addHistoryEntry('assistant', result.fullResponse);\n }\n\n return { stopReason: 'end_turn' };\n } catch (error: unknown) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n await this.connection.sessionUpdate({\n sessionId: params.sessionId,\n update: {\n sessionUpdate: 'agent_message_chunk',\n content: { type: 'text', text: errorMessage },\n },\n });\n return { stopReason: 'end_turn' };\n }\n }\n\n async cancel(params: CancelNotification): Promise<void> {\n this.sessionManager.cancelSession(params.sessionId);\n }\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\nimport { AgentConfig } from './types.js';\n\nexport function loadConfig(): AgentConfig {\n const baseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';\n const apiKey = process.env.OPENAI_API_KEY || '';\n const model = process.env.OPENAI_MODEL || 'gpt-4o';\n const systemPrompt = process.env.OPENAI_SYSTEM_PROMPT || undefined;\n\n let maxTokens: number | undefined;\n const maxTokensStr = process.env.OPENAI_MAX_TOKENS;\n if (maxTokensStr !== undefined) {\n const parsed = parseInt(maxTokensStr, 10);\n maxTokens = Number.isNaN(parsed) ? undefined : parsed;\n }\n\n let temperature: number | undefined;\n const temperatureStr = process.env.OPENAI_TEMPERATURE;\n if (temperatureStr !== undefined) {\n const parsed = parseFloat(temperatureStr);\n temperature = Number.isNaN(parsed) ? undefined : parsed;\n }\n\n if (!apiKey) {\n console.error('[openai-agent] Warning: OPENAI_API_KEY is not set. This may be fine for local endpoints like Ollama.');\n }\n\n return { baseUrl, apiKey, model, systemPrompt, maxTokens, temperature };\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\nimport crypto from 'node:crypto';\nimport { Session } from './session.js';\n\nexport class SessionManager {\n private readonly sessions = new Map<string, Session>();\n\n createSession(cwd: string): Session {\n const id = crypto.randomUUID();\n const session = new Session(id, cwd);\n this.sessions.set(id, session);\n return session;\n }\n\n getSession(id: string): Session | undefined {\n return this.sessions.get(id);\n }\n\n cancelSession(id: string): boolean {\n const session = this.sessions.get(id);\n if (session) {\n session.cancel();\n return true;\n }\n return false;\n }\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\nexport interface HistoryEntry {\n role: 'user' | 'assistant';\n content: string;\n}\n\nexport class Session {\n readonly id: string;\n readonly cwd: string;\n private _history: HistoryEntry[] = [];\n private _abortController: AbortController;\n private _cancelled = false;\n\n constructor(id: string, cwd: string) {\n this.id = id;\n this.cwd = cwd;\n this._abortController = new AbortController();\n }\n\n getAbortSignal(): AbortSignal {\n return this._abortController.signal;\n }\n\n cancel(): void {\n this._cancelled = true;\n this._abortController.abort();\n }\n\n isCancelled(): boolean {\n return this._cancelled;\n }\n\n resetCancellation(): void {\n this._cancelled = false;\n this._abortController = new AbortController();\n }\n\n addHistoryEntry(role: 'user' | 'assistant', content: string): void {\n this._history.push({ role, content });\n }\n\n getHistory(): HistoryEntry[] {\n return [...this._history];\n }\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\nimport { SSEEvent } from './types.js';\n\nconst DATA_PREFIX = 'data: ';\nconst DONE_MARKER = '[DONE]';\n\nexport function parseLine(line: string): SSEEvent {\n // Skip empty lines and whitespace-only lines\n if (!line.trim()) {\n return { type: 'skip' };\n }\n\n // Skip SSE comments (lines starting with :)\n if (line.startsWith(':')) {\n return { type: 'skip' };\n }\n\n // Check for data: prefix\n if (!line.startsWith(DATA_PREFIX)) {\n return { type: 'skip' };\n }\n\n const data = line.slice(DATA_PREFIX.length);\n\n // Check for [DONE] marker\n if (data === DONE_MARKER) {\n return { type: 'done' };\n }\n\n // Try to parse JSON\n try {\n const payload = JSON.parse(data);\n return { type: 'data', payload };\n } catch {\n console.error('[openai-agent] Failed to parse SSE JSON:', data);\n return { type: 'skip' };\n }\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\nimport { AgentConfig, ChatCompletionResult, ChatCompletionsRequest, OpenAIMessage, SSEChunk } from './types.js';\nimport { parseLine } from './sse-parser.js';\n\nexport function classifyHttpError(status: number, url: string): string {\n if (status === 401 || status === 403) {\n return `Authentication error (HTTP ${status}) calling ${url}. Check your OPENAI_API_KEY.`;\n }\n if (status === 429) {\n return `Rate limit exceeded (HTTP 429) calling ${url}. Please retry later.`;\n }\n if (status >= 500) {\n return `Server error (HTTP ${status}) from ${url}.`;\n }\n return `HTTP error (${status}) from ${url}.`;\n}\n\nexport class ChatCompletionsClient {\n private readonly config: AgentConfig;\n\n constructor(config: AgentConfig) {\n this.config = config;\n }\n\n async streamCompletion(\n messages: OpenAIMessage[],\n signal: AbortSignal,\n onChunk: (text: string) => Promise<void>,\n ): Promise<ChatCompletionResult> {\n const url = `${this.config.baseUrl}/chat/completions`;\n const body: ChatCompletionsRequest = {\n model: this.config.model,\n messages,\n stream: true,\n };\n if (this.config.maxTokens !== undefined) {\n body.max_tokens = this.config.maxTokens;\n }\n if (this.config.temperature !== undefined) {\n body.temperature = this.config.temperature;\n }\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Authorization': `Bearer ${this.config.apiKey}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(body),\n signal,\n });\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return { stopReason: 'cancelled', fullResponse: '' };\n }\n const message = error instanceof Error ? error.message : String(error);\n throw new Error(`Network error connecting to ${url}: ${message}`);\n }\n\n if (!response.ok) {\n throw new Error(classifyHttpError(response.status, url));\n }\n\n if (!response.body) {\n throw new Error(`No response body from ${url}.`);\n }\n\n let fullResponse = '';\n const reader = response.body.getReader();\n const decoder = new TextDecoder();\n let buffer = '';\n\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split('\\n');\n // Keep the last potentially incomplete line in the buffer\n buffer = lines.pop() || '';\n\n for (const line of lines) {\n const event = parseLine(line);\n if (event.type === 'done') {\n return { stopReason: 'end_turn', fullResponse };\n }\n if (event.type === 'data') {\n const chunk = event.payload as SSEChunk;\n const content = chunk.choices?.[0]?.delta?.content;\n if (content) {\n fullResponse += content;\n await onChunk(content);\n }\n }\n }\n }\n } catch (error: unknown) {\n if (error instanceof Error && error.name === 'AbortError') {\n return { stopReason: 'cancelled', fullResponse };\n }\n throw error;\n }\n\n return { stopReason: 'end_turn', fullResponse };\n }\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 * Session ID routing helper for stdio Bus \u2194 ACP messages.\n *\n * Tracks request IDs to restore stdio Bus sessionId on responses,\n * and maps ACP sessionId to stdio Bus sessionId for notifications.\n */\n\ntype JsonRecord = Record<string, unknown>;\n\nexport class SessionIdRouter {\n private readonly requestSessionIdMap = new Map<string | number, string>();\n private readonly acpSessionIdMap = new Map<string, string>();\n\n /**\n * Process a single inbound (stdin) line.\n *\n * - Saves stdio Bus sessionId for request/response correlation\n * - Tracks ACP sessionId \u2194 stdio Bus sessionId mapping when available\n * - Strips stdio Bus sessionId before passing to ACP SDK\n */\n processIncomingLine(line: string): string {\n if (!line.trim()) {\n return line;\n }\n\n try {\n const msg = JSON.parse(line) as JsonRecord;\n const routingSessionId = this.readSessionId(msg.sessionId);\n const hasId = msg.id !== undefined && msg.id !== null;\n\n if (hasId && routingSessionId) {\n this.requestSessionIdMap.set(msg.id as string | number, routingSessionId);\n console.error(`[worker] Saved sessionId=\"${routingSessionId}\" for request id=${msg.id}`);\n }\n\n const paramsSessionId = this.readSessionId((msg.params as JsonRecord | undefined)?.sessionId);\n if (routingSessionId && paramsSessionId) {\n this.setAcpSessionMapping(paramsSessionId, routingSessionId, 'request');\n }\n\n if (hasId && routingSessionId) {\n const { sessionId: _sessionId, ...msgWithoutSession } = msg;\n return JSON.stringify(msgWithoutSession);\n }\n\n return line;\n } catch {\n return line;\n }\n }\n\n /**\n * Process a single outbound (stdout) line.\n *\n * - Restores stdio Bus sessionId on responses using request mapping\n * - Maps ACP sessionId to stdio Bus sessionId for notifications\n */\n processOutgoingLine(line: string): string {\n if (!line.trim()) {\n return line;\n }\n\n try {\n const msg = JSON.parse(line) as JsonRecord;\n const hasId = msg.id !== undefined && msg.id !== null;\n\n if (hasId && this.requestSessionIdMap.has(msg.id as string | number)) {\n const routingSessionId = this.requestSessionIdMap.get(msg.id as string | number);\n this.requestSessionIdMap.delete(msg.id as string | number);\n\n if (routingSessionId) {\n const resultSessionId = this.readSessionId(\n (msg.result as JsonRecord | undefined)?.sessionId,\n );\n if (resultSessionId) {\n this.setAcpSessionMapping(resultSessionId, routingSessionId, 'response');\n }\n\n const msgWithSession = { ...msg, sessionId: routingSessionId };\n console.error(\n `[worker] Restored sessionId=\"${routingSessionId}\" for response id=${msg.id}`,\n );\n return JSON.stringify(msgWithSession);\n }\n }\n\n if (!hasId && !this.readSessionId(msg.sessionId)) {\n const paramsSessionId = this.readSessionId(\n (msg.params as JsonRecord | undefined)?.sessionId,\n );\n if (paramsSessionId) {\n const routingSessionId = this.acpSessionIdMap.get(paramsSessionId);\n if (routingSessionId) {\n const msgWithSession = { ...msg, sessionId: routingSessionId };\n return JSON.stringify(msgWithSession);\n }\n }\n }\n\n return line;\n } catch {\n return line;\n }\n }\n\n private readSessionId(value: unknown): string | null {\n return typeof value === 'string' && value.length > 0 ? value : null;\n }\n\n private setAcpSessionMapping(\n acpSessionId: string,\n routingSessionId: string,\n source: 'request' | 'response',\n ): void {\n const existing = this.acpSessionIdMap.get(acpSessionId);\n if (existing === routingSessionId) {\n return;\n }\n\n this.acpSessionIdMap.set(acpSessionId, routingSessionId);\n console.error(\n `[worker] Mapped ACP sessionId=\"${acpSessionId}\" ` +\n `to routing sessionId=\"${routingSessionId}\" (${source})`,\n );\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["connection"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stdiobus/workers-registry",
3
- "version": "1.5.0-beta.1",
3
+ "version": "1.5.0-beta.2",
4
4
  "description": "Worker implementations for stdio Bus kernel - ACP, MCP, and protocol bridges",
5
5
  "type": "module",
6
6
  "main": "./out/dist/workers-registry/acp-registry/index.js",
@@ -102,6 +102,7 @@
102
102
  "@modelcontextprotocol/sdk": "^1.27.1"
103
103
  },
104
104
  "devDependencies": {
105
+ "@stdiobus/node": "^0.1.0",
105
106
  "@types/jest": "^29.5.0",
106
107
  "@types/node": "^20.0.0",
107
108
  "esbuild": "^0.20.0",