@stdiobus/workers-registry 1.4.12 → 1.4.14

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.
@@ -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 * 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", "import 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", "import { 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", "import 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", "export 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", "import { 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", "import { 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 }\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
  }
@@ -7,7 +7,7 @@
7
7
  * @module registry/index
8
8
  */
9
9
  import { Registry, RegistryAgent, SpawnCommand } from './types.js';
10
- export type { Platform, BinaryDistribution, BinaryTarget, NpxDistribution, UvxDistribution, Distribution, RegistryAgent, Registry, SpawnCommand, } from './types.js';
10
+ export type { Platform, BinaryDistribution, BinaryTarget, NpxDistribution, UvxDistribution, Distribution, RegistryAgent, Registry, SpawnCommand, McpServerConfig, } from './types.js';
11
11
  export { PlatformNotSupportedError, NoDistributionError, getCurrentPlatform, resolve } from './resolver.js';
12
12
  /**
13
13
  * Error thrown when registry fetch fails.
@@ -60,6 +60,20 @@ export interface Distribution {
60
60
  /** UVX distribution (Python packages) */
61
61
  uvx?: UvxDistribution;
62
62
  }
63
+ /**
64
+ * MCP server configuration for agent.
65
+ * Defines an MCP server that should be connected when creating a session.
66
+ */
67
+ export interface McpServerConfig {
68
+ /** Server name/identifier */
69
+ name: string;
70
+ /** Command to spawn the server */
71
+ command: string;
72
+ /** Optional command-line arguments */
73
+ args?: string[];
74
+ /** Optional environment variables */
75
+ env?: Record<string, string>;
76
+ }
63
77
  /**
64
78
  * Agent entry in the ACP Registry.
65
79
  */
@@ -82,6 +96,8 @@ export interface RegistryAgent {
82
96
  icon?: string;
83
97
  /** Distribution methods */
84
98
  distribution: Distribution;
99
+ /** MCP servers to connect when creating a session */
100
+ mcpServers?: McpServerConfig[];
85
101
  }
86
102
  /**
87
103
  * Parsed ACP Registry structure.
@@ -100,6 +100,18 @@ export declare class MessageRouter {
100
100
  * @param apiKeys - API keys for agent authentication (optional)
101
101
  */
102
102
  constructor(registry: IRegistryIndex, runtimeManager: AgentRuntimeManager, writeCallback: WriteCallback, apiKeys?: Record<string, any>);
103
+ /**
104
+ * Inject mcpServers from registry into session/new request params.
105
+ *
106
+ * If the agent has mcpServers configured in the registry, they are merged
107
+ * with any mcpServers already present in the request params.
108
+ * Registry servers are added first, then request servers (request takes precedence for duplicates).
109
+ *
110
+ * @param message - The transformed message (without agentId)
111
+ * @param agentId - The agent ID to look up in registry
112
+ * @returns Message with mcpServers injected into params
113
+ */
114
+ private injectMcpServers;
103
115
  /**
104
116
  * Route an incoming message to the appropriate agent.
105
117
  *
@@ -1,11 +1 @@
1
- /**
2
- * OpenAI Agent Worker for stdio Bus kernel
3
- *
4
- * This worker implements the Agent Client Protocol (ACP) and bridges
5
- * to any OpenAI Chat Completions API-compatible endpoint.
6
- *
7
- * It runs as a child process of stdio Bus kernel, communicating via stdin/stdout NDJSON.
8
- *
9
- * @module index
10
- */
11
1
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stdiobus/workers-registry",
3
- "version": "1.4.12",
3
+ "version": "1.4.14",
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",
@@ -107,4 +107,4 @@
107
107
  "tsc-alias": "^1.8.16",
108
108
  "typescript": "^5.0.0"
109
109
  }
110
- }
110
+ }