@stdiobus/workers-registry 1.4.6 → 1.4.7

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,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  var __getOwnPropNames=Object.getOwnPropertyNames;var __esm=(fn,res)=>function __init(){return fn&&(res=(0,fn[__getOwnPropNames(fn)[0]])(fn=0)),res};var DEFAULT_CONFIG;var init_types=__esm({"workers-registry/acp-worker/src/registry-launcher/config/types.ts"(){"use strict";DEFAULT_CONFIG={registryUrl:"https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json",apiKeysPath:"./api-keys.json",shutdownTimeoutSec:5}}});import{readFileSync}from"node:fs";function logWarning(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [WARN] [config] ${message}`)}function isNonEmptyString(value){return typeof value==="string"&&value.length>0}function isPositiveNumber(value){return typeof value==="number"&&value>0&&Number.isFinite(value)}function parseConfigObject(obj){const config={...DEFAULT_CONFIG};if(obj===null||typeof obj!=="object"){logWarning("Config file does not contain a valid object, using defaults");return config}const rawConfig=obj;if("registryUrl"in rawConfig){if(isNonEmptyString(rawConfig.registryUrl)){config.registryUrl=rawConfig.registryUrl}else{logWarning('Config field "registryUrl" is not a valid string, using default')}}if("apiKeysPath"in rawConfig){if(isNonEmptyString(rawConfig.apiKeysPath)){config.apiKeysPath=rawConfig.apiKeysPath}else{logWarning('Config field "apiKeysPath" is not a valid string, using default')}}if("shutdownTimeoutSec"in rawConfig){if(isPositiveNumber(rawConfig.shutdownTimeoutSec)){config.shutdownTimeoutSec=rawConfig.shutdownTimeoutSec}else{logWarning('Config field "shutdownTimeoutSec" is not a valid positive number, using default')}}return config}function applyEnvironmentOverrides(config){const envRegistryUrl=process.env[ENV_REGISTRY_URL];const envApiKeysPath=process.env[ENV_API_KEYS_PATH];const overrides={};if(isNonEmptyString(envRegistryUrl)){overrides.registryUrl=envRegistryUrl}if(isNonEmptyString(envApiKeysPath)){overrides.apiKeysPath=envApiKeysPath}return{...config,...overrides}}function loadConfig(configPath){let config={...DEFAULT_CONFIG};if(configPath){try{const fileContent=readFileSync(configPath,"utf-8");const parsed=JSON.parse(fileContent);config=parseConfigObject(parsed)}catch(error){if(error instanceof SyntaxError){logWarning(`Config file "${configPath}" contains malformed JSON, using defaults`)}else if(error.code==="ENOENT"){logWarning(`Config file "${configPath}" not found, using defaults`)}else if(error.code==="EACCES"){logWarning(`Config file "${configPath}" is not readable, using defaults`)}else{logWarning(`Failed to read config file "${configPath}": ${error.message}, using defaults`)}}}config=applyEnvironmentOverrides(config);return config}var ENV_REGISTRY_URL,ENV_API_KEYS_PATH;var init_config=__esm({"workers-registry/acp-worker/src/registry-launcher/config/config.ts"(){"use strict";init_types();ENV_REGISTRY_URL="ACP_REGISTRY_URL";ENV_API_KEYS_PATH="ACP_API_KEYS_PATH"}});import{readFileSync as readFileSync2}from"node:fs";function logWarning2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [WARN] [api-keys] ${message}`)}function logInfo(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [api-keys] ${message}`)}function loadApiKeys(apiKeysPath){try{const fileContent=readFileSync2(apiKeysPath,"utf-8");const parsed=JSON.parse(fileContent);if(!parsed.agents||typeof parsed.agents!=="object"){logWarning2(`API keys file "${apiKeysPath}" does not contain valid "agents" object`);return{}}const agentsWithKeys=Object.entries(parsed.agents).filter(([_,keys])=>keys.apiKey&&keys.apiKey.length>0);logInfo(`Loaded API keys for ${agentsWithKeys.length} agents from "${apiKeysPath}"`);return parsed.agents}catch(error){if(error.code==="ENOENT"){logWarning2(`API keys file "${apiKeysPath}" not found, agents will not be authenticated`)}else if(error instanceof SyntaxError){logWarning2(`API keys file "${apiKeysPath}" contains malformed JSON`)}else{logWarning2(`Failed to read API keys file "${apiKeysPath}": ${error.message}`)}return{}}}function getAgentApiKey(apiKeys,agentId){const keys=apiKeys[agentId];if(!keys||!keys.apiKey||keys.apiKey.length===0){return void 0}return keys.apiKey}var init_api_keys=__esm({"workers-registry/acp-worker/src/registry-launcher/config/api-keys.ts"(){"use strict"}});function getCurrentPlatform(){const platform=process.platform;const arch=process.arch;if(platform==="darwin"&&arch==="arm64")return"darwin-aarch64";if(platform==="darwin"&&arch==="x64")return"darwin-x86_64";if(platform==="linux"&&arch==="arm64")return"linux-aarch64";if(platform==="linux"&&arch==="x64")return"linux-x86_64";if(platform==="win32"&&arch==="arm64")return"windows-aarch64";if(platform==="win32"&&arch==="x64")return"windows-x86_64";return"linux-x86_64"}function resolveBinary(distribution,agentId){const currentPlatform=getCurrentPlatform();const target=distribution[currentPlatform];if(!target){throw new PlatformNotSupportedError(agentId,currentPlatform)}return{command:target.cmd,args:target.args??[],env:target.env}}function resolveNpx(distribution){return{command:"npx",args:[distribution.package,...distribution.args??[]],env:distribution.env}}function resolveUvx(distribution){return{command:"uvx",args:[distribution.package,...distribution.args??[]],env:distribution.env}}function resolve(distribution,agentId){if(distribution.npx){return resolveNpx(distribution.npx)}if(distribution.uvx){return resolveUvx(distribution.uvx)}if(distribution.binary){return resolveBinary(distribution.binary,agentId)}throw new NoDistributionError(agentId)}var PlatformNotSupportedError,NoDistributionError;var init_resolver=__esm({"workers-registry/acp-worker/src/registry-launcher/registry/resolver.ts"(){"use strict";PlatformNotSupportedError=class extends Error{constructor(agentId,platform){super(`Platform not supported: ${platform} for agent ${agentId}`);this.agentId=agentId;this.platform=platform;this.name="PlatformNotSupportedError"}};NoDistributionError=class extends Error{constructor(agentId){super(`No supported distribution type for agent ${agentId}`);this.agentId=agentId;this.name="NoDistributionError"}}}});function logError(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [registry] ${message}`)}function logInfo2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [registry] ${message}`)}function isNonEmptyString2(value){return typeof value==="string"&&value.length>0}function isValidDistribution(value){if(value===null||typeof value!=="object"){return false}const dist=value;const hasBinary=dist.binary!==void 0&&typeof dist.binary==="object";const hasNpx=dist.npx!==void 0&&typeof dist.npx==="object";const hasUvx=dist.uvx!==void 0&&typeof dist.uvx==="object";if(!hasBinary&&!hasNpx&&!hasUvx){return false}if(hasNpx){const npx=dist.npx;if(!isNonEmptyString2(npx.package)){return false}}if(hasUvx){const uvx=dist.uvx;if(!isNonEmptyString2(uvx.package)){return false}}return true}function parseAgent(value,index){if(value===null||typeof value!=="object"){throw new RegistryParseError(`Agent at index ${index} is not an object`)}const raw=value;if(!isNonEmptyString2(raw.id)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "id" field`)}if(!isNonEmptyString2(raw.name)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "name" field`)}if(!isNonEmptyString2(raw.version)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "version" field`)}if(!isValidDistribution(raw.distribution)){throw new RegistryParseError(`Agent at index ${index} has invalid or missing "distribution" field`)}const agent={id:raw.id,name:raw.name,version:raw.version,distribution:raw.distribution};if(typeof raw.description==="string"){agent.description=raw.description}if(typeof raw.repository==="string"){agent.repository=raw.repository}if(Array.isArray(raw.authors)){agent.authors=raw.authors.filter(a=>typeof a==="string")}if(typeof raw.license==="string"){agent.license=raw.license}if(typeof raw.icon==="string"){agent.icon=raw.icon}return agent}function parseRegistry(data){if(data===null||typeof data!=="object"){throw new RegistryParseError("Registry data is not an object")}const raw=data;if(!isNonEmptyString2(raw.version)){throw new RegistryParseError('Registry has invalid or missing "version" field')}if(!Array.isArray(raw.agents)){throw new RegistryParseError('Registry has invalid or missing "agents" field')}const agents=[];for(let i=0;i<raw.agents.length;i++){agents.push(parseAgent(raw.agents[i],i))}return{version:raw.version,agents}}var ENV_REGISTRY_URL2,RegistryFetchError,RegistryParseError,AgentNotFoundError,RegistryIndex;var init_registry=__esm({"workers-registry/acp-worker/src/registry-launcher/registry/index.ts"(){"use strict";init_resolver();init_resolver();ENV_REGISTRY_URL2="ACP_REGISTRY_URL";RegistryFetchError=class extends Error{constructor(message,cause){super(message);this.cause=cause;this.name="RegistryFetchError"}};RegistryParseError=class extends Error{constructor(message,cause){super(message);this.cause=cause;this.name="RegistryParseError"}};AgentNotFoundError=class extends Error{constructor(agentId){super(`Agent not found: ${agentId}`);this.agentId=agentId;this.name="AgentNotFoundError"}};RegistryIndex=class{registryUrl;registry=null;agentMap=new Map;constructor(registryUrl){const envUrl=process.env[ENV_REGISTRY_URL2];this.registryUrl=isNonEmptyString2(envUrl)?envUrl:registryUrl}async fetch(){logInfo2(`Fetching registry from ${this.registryUrl}`);let response;try{response=await fetch(this.registryUrl)}catch(error){const message=`Failed to fetch registry from ${this.registryUrl}: ${error.message}`;logError(message);throw new RegistryFetchError(message,error)}if(!response.ok){const message=`Failed to fetch registry from ${this.registryUrl}: HTTP ${response.status} ${response.statusText}`;logError(message);throw new RegistryFetchError(message)}let text;try{text=await response.text()}catch(error){const message=`Failed to read registry response body: ${error.message}`;logError(message);throw new RegistryFetchError(message,error)}let data;try{data=JSON.parse(text)}catch(error){const message=`Failed to parse registry JSON: ${error.message}`;logError(message);throw new RegistryParseError(message,error)}try{this.registry=parseRegistry(data)}catch(error){if(error instanceof RegistryParseError){logError(error.message);throw error}const message=`Failed to validate registry data: ${error.message}`;logError(message);throw new RegistryParseError(message,error)}this.agentMap.clear();for(const agent of this.registry.agents){this.agentMap.set(agent.id,agent)}logInfo2(`Registry loaded: version ${this.registry.version}, ${this.registry.agents.length} agents`)}lookup(agentId){return this.agentMap.get(agentId)}resolve(agentId){const agent=this.lookup(agentId);if(!agent){throw new AgentNotFoundError(agentId)}return resolve(agent.distribution,agentId)}getRegistry(){return this.registry}}}});function logError2(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [ndjson] ${message}`)}var NDJSONHandler;var init_ndjson_handler=__esm({"workers-registry/acp-worker/src/registry-launcher/stream/ndjson-handler.ts"(){"use strict";NDJSONHandler=class{buffer="";output;messageCallback=null;errorCallback=null;constructor(output){this.output=output}onMessage(callback){this.messageCallback=callback}onError(callback){this.errorCallback=callback}write(message){if(!this.output.writable){return false}try{const json=JSON.stringify(message);this.output.write(json+"\n");return true}catch{return false}}processChunk(chunk){this.buffer+=chunk.toString("utf-8");this.processBuffer()}processBuffer(){let newlineIndex;while((newlineIndex=this.buffer.indexOf("\n"))!==-1){const line=this.buffer.slice(0,newlineIndex);this.buffer=this.buffer.slice(newlineIndex+1);if(line.trim().length===0){continue}this.parseLine(line)}}parseLine(line){try{const message=JSON.parse(line);if(message===null||typeof message!=="object"){const error=new Error("Parsed JSON is not an object");logError2(`Malformed NDJSON line (not an object): ${this.truncateLine(line)}`);this.errorCallback?.(error,line);return}this.messageCallback?.(message)}catch(error){logError2(`Failed to parse NDJSON line: ${this.truncateLine(line)}`);this.errorCallback?.(error,line)}}truncateLine(line,maxLength=100){if(line.length<=maxLength){return line}return line.slice(0,maxLength)+"..."}}}});import{spawn}from"child_process";var DEFAULT_TERMINATE_TIMEOUT_MS,AgentRuntimeImpl;var init_agent_runtime=__esm({"workers-registry/acp-worker/src/registry-launcher/runtime/agent-runtime.ts"(){"use strict";DEFAULT_TERMINATE_TIMEOUT_MS=5e3;AgentRuntimeImpl=class _AgentRuntimeImpl{agentId;state;process;onExitCallback;constructor(agentId,process2,onExit){this.agentId=agentId;this.process=process2;this.state="starting";this.onExitCallback=onExit;this.setupProcessHandlers()}static spawn(agentId,spawnCommand,onExit){const childProcess=spawn(spawnCommand.command,spawnCommand.args,{stdio:["pipe","pipe","pipe"],env:{...process.env,...spawnCommand.env},detached:false});if(childProcess.stdout){childProcess.stdout.setEncoding("utf8")}if(childProcess.stderr){childProcess.stderr.setEncoding("utf8")}return new _AgentRuntimeImpl(agentId,childProcess,onExit)}setupProcessHandlers(){this.process.on("spawn",()=>{if(this.state==="starting"){this.state="running"}});this.process.on("error",error=>{this.state="stopped";process.stderr.write(`[${new Date().toISOString()}] ERROR: Agent ${this.agentId} process error: ${error.message}
3
3
  `)});this.process.on("exit",(code,signal)=>{this.state="stopped";if(this.onExitCallback){this.onExitCallback(code,signal)}});if(this.process.stdin){this.process.stdin.on("error",error=>{process.stderr.write(`[${new Date().toISOString()}] WARN: Agent ${this.agentId} stdin error: ${error.message}
4
- `)})}}write(message){if(this.state!=="running"&&this.state!=="starting"){return false}if(!this.process.stdin||this.process.stdin.destroyed){return false}try{const ndjsonLine=JSON.stringify(message)+"\n";return this.process.stdin.write(ndjsonLine)}catch{return false}}async terminate(timeout=DEFAULT_TERMINATE_TIMEOUT_MS){if(this.state==="stopped"){return}if(this.state==="stopping"){return this.waitForExit()}this.state="stopping";if(this.process.stdin&&!this.process.stdin.destroyed){this.process.stdin.end()}this.process.kill("SIGTERM");const exitPromise=this.waitForExit();const timeoutPromise=new Promise(resolve2=>{setTimeout(()=>resolve2("timeout"),timeout)});const result=await Promise.race([exitPromise,timeoutPromise]);if(result==="timeout"&&!this.process.killed&&this.process.exitCode===null){this.process.kill("SIGKILL");await this.waitForExit()}}waitForExit(){if(this.state==="stopped"){return Promise.resolve()}return new Promise(resolve2=>{this.process.once("exit",()=>{resolve2()})})}}}});var DEFAULT_SHUTDOWN_TIMEOUT_MS,AgentRuntimeManager;var init_manager=__esm({"workers-registry/acp-worker/src/registry-launcher/runtime/manager.ts"(){"use strict";init_agent_runtime();DEFAULT_SHUTDOWN_TIMEOUT_MS=5e3;AgentRuntimeManager=class{runtimes=new Map;exitCallbacks=[];async getOrSpawn(agentId,spawnCommand){const existing=this.runtimes.get(agentId);if(existing&&existing.state!=="stopped"){return existing}const runtime=AgentRuntimeImpl.spawn(agentId,spawnCommand,(code,_signal)=>{this.handleAgentExit(agentId,code)});this.runtimes.set(agentId,runtime);return runtime}get(agentId){return this.runtimes.get(agentId)}async terminate(agentId,timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const runtime=this.runtimes.get(agentId);if(!runtime){return}await runtime.terminate(timeout);this.runtimes.delete(agentId)}async terminateAll(timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const terminatePromises=[];for(const[agentId,runtime]of this.runtimes){if(runtime.state!=="stopped"){terminatePromises.push(runtime.terminate(timeout).then(()=>{this.runtimes.delete(agentId)}))}}await Promise.all(terminatePromises)}onAgentExit(callback){this.exitCallbacks.push(callback)}handleAgentExit(agentId,code){this.runtimes.delete(agentId);for(const callback of this.exitCallbacks){try{callback(agentId,code)}catch{}}}get size(){return this.runtimes.size}has(agentId){return this.runtimes.has(agentId)}}}});function logError3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [router] ${message}`)}function logInfo3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [router] ${message}`)}function createErrorResponse(id,code,message,data){const response={jsonrpc:"2.0",id,error:{code,message}};if(data!==void 0){response.error.data=data}return response}function extractAgentId(message){const msg=message;const agentId=msg.agentId;if(typeof agentId==="string"&&agentId.length>0){return agentId}return void 0}function extractId(message){const msg=message;const id=msg.id;if(typeof id==="string"||typeof id==="number"){return id}return null}function transformMessage(message){const{agentId:_,...rest}=message;return rest}var RoutingErrorCodes,MessageRouter;var init_message_router=__esm({"workers-registry/acp-worker/src/registry-launcher/router/message-router.ts"(){"use strict";init_registry();init_api_keys();RoutingErrorCodes={MISSING_AGENT_ID:-32600,AGENT_NOT_FOUND:-32001,PLATFORM_NOT_SUPPORTED:-32002,SPAWN_FAILED:-32003};MessageRouter=class{registry;runtimeManager;writeCallback;apiKeys;pendingRequests=new Map;authState=new Map;sessionIdMap=new Map;constructor(registry,runtimeManager,writeCallback,apiKeys={}){this.registry=registry;this.runtimeManager=runtimeManager;this.writeCallback=writeCallback;this.apiKeys=apiKeys}async route(message){const id=extractId(message);const agentId=extractAgentId(message);if(agentId===void 0){logError3("Missing agentId in request");return createErrorResponse(id,RoutingErrorCodes.MISSING_AGENT_ID,"Missing agentId")}let spawnCommand;try{spawnCommand=this.registry.resolve(agentId)}catch(error){if(error instanceof AgentNotFoundError){logError3(`Agent not found: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.AGENT_NOT_FOUND,"Agent not found",{agentId})}if(error instanceof PlatformNotSupportedError){logError3(`Platform not supported for agent: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.PLATFORM_NOT_SUPPORTED,"Platform not supported",{agentId,platform:error.platform})}throw error}let runtime;try{runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to spawn agent ${agentId}: ${error.message}`);return createErrorResponse(id,RoutingErrorCodes.SPAWN_FAILED,"Agent spawn failed",{agentId,error:error.message})}if(id!==null){const msg=message;const clientSessionId=typeof msg.sessionId==="string"?msg.sessionId:void 0;this.pendingRequests.set(id,{id,agentId,timestamp:Date.now(),clientSessionId})}const transformedMessage=transformMessage(message);const success=runtime.write(transformedMessage);if(!success){logError3(`Failed to write to agent ${agentId}`);if(id!==null){this.pendingRequests.delete(id)}}else{logInfo3(`Routed message to agent ${agentId}`)}return void 0}handleAgentResponse(agentId,response){const id=extractId(response);const msg=response;if(id!==null){const pending=this.pendingRequests.get(id);if(pending&&pending.agentId===agentId){const result=msg.result;if(result&&Array.isArray(result.authMethods)&&result.authMethods.length>0){logInfo3(`Agent ${agentId} requires authentication, attempting auto-auth`);this.authState.set(agentId,"pending");void this.attemptAuthentication(agentId,result.authMethods)}if(result&&typeof result.sessionId==="string"){const agentSessionId=result.sessionId;const clientSessionId=pending.clientSessionId;if(clientSessionId){this.sessionIdMap.set(agentSessionId,clientSessionId);logInfo3(`Mapped agent sessionId ${agentSessionId} to client sessionId ${clientSessionId}`)}}this.pendingRequests.delete(id)}}if(id===null&&msg.method){logInfo3(`Received notification: ${msg.method}`);const params=msg.params;if(params&&typeof params.sessionId==="string"){const agentSessionId=params.sessionId;const clientSessionId=this.sessionIdMap.get(agentSessionId);if(clientSessionId){const enriched={...msg,sessionId:clientSessionId,params:{...params,sessionId:agentSessionId}};logInfo3(`Forwarding notification with mapped sessionId: ${clientSessionId}`);this.writeCallback(enriched);return}else{logError3(`Notification with unmapped agentSessionId: ${agentSessionId}, using default sessionId`);const enriched={...msg,sessionId:"global-notifications",params:{...params,sessionId:agentSessionId}};this.writeCallback(enriched);return}}else{const topLevelSessionId=msg.sessionId;if(topLevelSessionId){this.writeCallback(response);return}else{logError3(`Notification without sessionId: ${msg.method}, adding default sessionId for routing`);const enriched={...msg,sessionId:"global-notifications"};this.writeCallback(enriched);return}}}this.writeCallback(response)}async attemptAuthentication(agentId,authMethods){const apiKey=getAgentApiKey(this.apiKeys,agentId);if(!apiKey){logError3(`No API key found for agent ${agentId}, authentication will fail`);this.authState.set(agentId,"none");return}let selectedMethod=authMethods.find(m=>m.id==="openai-api-key");if(!selectedMethod){selectedMethod=authMethods.find(m=>m.id.includes("api-key")||m.id.includes("apikey"))}if(!selectedMethod){selectedMethod=authMethods[0]}logInfo3(`Authenticating agent ${agentId} with method: ${selectedMethod.id}`);let runtime;try{const spawnCommand=this.registry.resolve(agentId);runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to get runtime for authentication: ${error.message}`);this.authState.set(agentId,"none");return}const authRequest={jsonrpc:"2.0",id:`auth-${agentId}-${Date.now()}`,method:"authenticate",params:{methodId:selectedMethod.id,credentials:{apiKey}}};const transformed=transformMessage(authRequest);const serialized=JSON.stringify(transformed)+"\n";if(runtime.process.stdin){runtime.process.stdin.write(serialized,error=>{if(error){logError3(`Failed to send authenticate request to ${agentId}: ${error.message}`);this.authState.set(agentId,"none")}else{logInfo3(`Sent authenticate request to agent ${agentId}`);this.authState.set(agentId,"authenticated")}})}}get pendingCount(){return this.pendingRequests.size}isPending(id){return this.pendingRequests.has(id)}clearPending(){this.pendingRequests.clear()}}}});function formatLogMessage(level,message,context=LOG_CONTEXT){const timestamp=new Date().toISOString();return`[${timestamp}] [${level}] [${context}] ${message}`}function log(level,message,context){const formatted=formatLogMessage(level,message,context);console.error(formatted)}function logExit(agentId,exitCode,signal){if(signal){log("INFO",`Agent "${agentId}" exited with signal ${signal}`)}else if(exitCode!==null){log("INFO",`Agent "${agentId}" exited with code ${exitCode}`)}else{log("INFO",`Agent "${agentId}" exited`)}}function logInfo4(message,context){log("INFO",message,context)}function logError4(message,context){log("ERROR",message,context)}var LOG_CONTEXT;var init_log=__esm({"workers-registry/acp-worker/src/registry-launcher/log.ts"(){"use strict";LOG_CONTEXT="registry-launcher"}});var registry_launcher_exports={};function parseArgs(){const args=process.argv.slice(2);if(args.length>0&&args[0]&&!args[0].startsWith("-")){return args[0]}return void 0}function setupSignalHandlers(runtimeManager,shutdownTimeoutMs){const shutdown=async()=>{if(isShuttingDown){return}isShuttingDown=true;logInfo4("Received shutdown signal, initiating graceful shutdown");try{await runtimeManager.terminateAll(shutdownTimeoutMs);logInfo4("All agent processes terminated");process.exit(ExitCodes.SUCCESS)}catch(error){logError4(`Error during shutdown: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}};process.on("SIGTERM",()=>{void shutdown()});process.on("SIGINT",()=>{void shutdown()});return shutdown}function setupStdinHandler(router,ndjsonHandler){ndjsonHandler.onMessage(async message=>{try{const errorResponse=await router.route(message);if(errorResponse){ndjsonHandler.write(errorResponse)}}catch(error){logError4(`Unexpected error routing message: ${error.message}`)}});ndjsonHandler.onError((error,line)=>{logError4(`Failed to parse NDJSON: ${error.message} - Line: ${line.slice(0,100)}`)});process.stdin.setEncoding("utf8");process.stdin.on("data",chunk=>{const buffer=typeof chunk==="string"?Buffer.from(chunk):chunk;ndjsonHandler.processChunk(buffer)});process.stdin.on("end",()=>{logInfo4("stdin closed")});process.stdin.on("error",error=>{logError4(`stdin error: ${error.message}`)})}function setupAgentResponseHandling(runtimeManager,router){runtimeManager.onAgentExit((agentId,code)=>{logExit(agentId,code)});const originalGetOrSpawn=runtimeManager.getOrSpawn.bind(runtimeManager);runtimeManager.getOrSpawn=async function(agentId,spawnCommand){const runtime=await originalGetOrSpawn(agentId,spawnCommand);const proc=runtime.process;if(proc.stdout&&!proc.stdout.listenerCount("data")){let buffer="";proc.stdout.on("data",chunk=>{buffer+=chunk;let newlineIndex;while((newlineIndex=buffer.indexOf("\n"))!==-1){const line=buffer.slice(0,newlineIndex);buffer=buffer.slice(newlineIndex+1);if(line.trim()){try{const response=JSON.parse(line);router.handleAgentResponse(agentId,response)}catch(err){logError4(`Failed to parse agent ${agentId} response: ${err.message}`)}}}})}if(proc.stderr&&!proc.stderr.listenerCount("data")){proc.stderr.on("data",chunk=>{process.stderr.write(`[agent:${agentId}] ${chunk}`)})}return runtime}}async function main(){logInfo4("Registry Launcher starting");const configPath=parseArgs();if(configPath){logInfo4(`Loading configuration from: ${configPath}`)}const config=loadConfig(configPath);logInfo4(`Configuration loaded: registryUrl=${config.registryUrl}, apiKeysPath=${config.apiKeysPath}, shutdownTimeoutSec=${config.shutdownTimeoutSec}`);const apiKeys=loadApiKeys(config.apiKeysPath);const registry=new RegistryIndex(config.registryUrl);try{await registry.fetch()}catch(error){if(error instanceof RegistryFetchError){logError4(`Failed to fetch registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}if(error instanceof RegistryParseError){logError4(`Failed to parse registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}logError4(`Unexpected error fetching registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}const runtimeManager=new AgentRuntimeManager;const ndjsonHandler=new NDJSONHandler(process.stdout);const router=new MessageRouter(registry,runtimeManager,message=>ndjsonHandler.write(message),apiKeys);const shutdownTimeoutMs=config.shutdownTimeoutSec*1e3;setupSignalHandlers(runtimeManager,shutdownTimeoutMs);setupAgentResponseHandling(runtimeManager,router);setupStdinHandler(router,ndjsonHandler);logInfo4("Registry Launcher ready, waiting for messages")}var ExitCodes,isShuttingDown;var init_registry_launcher=__esm({"workers-registry/acp-worker/src/registry-launcher/index.ts"(){"use strict";init_config();init_api_keys();init_registry();init_ndjson_handler();init_manager();init_message_router();init_log();ExitCodes={SUCCESS:0,FATAL_ERROR:1};isShuttingDown=false;main().catch(error=>{logError4(`Fatal error: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)})}});import{fileURLToPath}from"url";import{dirname,join}from"path";var __filename=fileURLToPath(import.meta.url);var __dirname=dirname(__filename);var DEFAULT_CONFIG_FILE="acp-registry-config.json";function ensureDefaultConfigArg(){const hasExplicitConfig=process.argv.length>2&&process.argv[2]&&!process.argv[2].startsWith("-");if(hasExplicitConfig){return}const defaultConfigPath=join(__dirname,DEFAULT_CONFIG_FILE);process.argv.splice(2,0,defaultConfigPath)}ensureDefaultConfigArg();await Promise.resolve().then(()=>(init_registry_launcher(),registry_launcher_exports));
4
+ `)})}}write(message){if(this.state!=="running"&&this.state!=="starting"){return false}if(!this.process.stdin||this.process.stdin.destroyed){return false}try{const ndjsonLine=JSON.stringify(message)+"\n";return this.process.stdin.write(ndjsonLine)}catch{return false}}async terminate(timeout=DEFAULT_TERMINATE_TIMEOUT_MS){if(this.state==="stopped"){return}if(this.state==="stopping"){return this.waitForExit()}this.state="stopping";if(this.process.stdin&&!this.process.stdin.destroyed){this.process.stdin.end()}this.process.kill("SIGTERM");const exitPromise=this.waitForExit();const timeoutPromise=new Promise(resolve2=>{setTimeout(()=>resolve2("timeout"),timeout)});const result=await Promise.race([exitPromise,timeoutPromise]);if(result==="timeout"&&!this.process.killed&&this.process.exitCode===null){this.process.kill("SIGKILL");await this.waitForExit()}}waitForExit(){if(this.state==="stopped"){return Promise.resolve()}return new Promise(resolve2=>{this.process.once("exit",()=>{resolve2()})})}}}});var DEFAULT_SHUTDOWN_TIMEOUT_MS,AgentRuntimeManager;var init_manager=__esm({"workers-registry/acp-worker/src/registry-launcher/runtime/manager.ts"(){"use strict";init_agent_runtime();DEFAULT_SHUTDOWN_TIMEOUT_MS=5e3;AgentRuntimeManager=class{runtimes=new Map;exitCallbacks=[];async getOrSpawn(agentId,spawnCommand){const existing=this.runtimes.get(agentId);if(existing&&existing.state!=="stopped"){return existing}const runtime=AgentRuntimeImpl.spawn(agentId,spawnCommand,(code,_signal)=>{this.handleAgentExit(agentId,code)});this.runtimes.set(agentId,runtime);return runtime}get(agentId){return this.runtimes.get(agentId)}async terminate(agentId,timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const runtime=this.runtimes.get(agentId);if(!runtime){return}await runtime.terminate(timeout);this.runtimes.delete(agentId)}async terminateAll(timeout=DEFAULT_SHUTDOWN_TIMEOUT_MS){const terminatePromises=[];for(const[agentId,runtime]of this.runtimes){if(runtime.state!=="stopped"){terminatePromises.push(runtime.terminate(timeout).then(()=>{this.runtimes.delete(agentId)}))}}await Promise.all(terminatePromises)}onAgentExit(callback){this.exitCallbacks.push(callback)}handleAgentExit(agentId,code){this.runtimes.delete(agentId);for(const callback of this.exitCallbacks){try{callback(agentId,code)}catch{}}}get size(){return this.runtimes.size}has(agentId){return this.runtimes.has(agentId)}}}});function logError3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [ERROR] [router] ${message}`)}function logInfo3(message){const timestamp=new Date().toISOString();console.error(`[${timestamp}] [INFO] [router] ${message}`)}function createErrorResponse(id,code,message,data){const response={jsonrpc:"2.0",id,error:{code,message}};if(data!==void 0){response.error.data=data}return response}function extractAgentId(message){const msg=message;const agentId=msg.agentId;if(typeof agentId==="string"&&agentId.length>0){return agentId}return void 0}function extractId(message){const msg=message;const id=msg.id;if(typeof id==="string"||typeof id==="number"){return id}return null}function transformMessage(message){const{agentId:_,...rest}=message;return rest}var RoutingErrorCodes,MessageRouter;var init_message_router=__esm({"workers-registry/acp-worker/src/registry-launcher/router/message-router.ts"(){"use strict";init_registry();init_api_keys();RoutingErrorCodes={MISSING_AGENT_ID:-32600,AGENT_NOT_FOUND:-32001,PLATFORM_NOT_SUPPORTED:-32002,SPAWN_FAILED:-32003};MessageRouter=class{registry;runtimeManager;writeCallback;apiKeys;pendingRequests=new Map;authState=new Map;sessionIdMap=new Map;constructor(registry,runtimeManager,writeCallback,apiKeys={}){this.registry=registry;this.runtimeManager=runtimeManager;this.writeCallback=writeCallback;this.apiKeys=apiKeys}async route(message){const id=extractId(message);const agentId=extractAgentId(message);if(agentId===void 0){logError3("Missing agentId in request");return createErrorResponse(id,RoutingErrorCodes.MISSING_AGENT_ID,"Missing agentId")}let spawnCommand;try{spawnCommand=this.registry.resolve(agentId)}catch(error){if(error instanceof AgentNotFoundError){logError3(`Agent not found: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.AGENT_NOT_FOUND,"Agent not found",{agentId})}if(error instanceof PlatformNotSupportedError){logError3(`Platform not supported for agent: ${agentId}`);return createErrorResponse(id,RoutingErrorCodes.PLATFORM_NOT_SUPPORTED,"Platform not supported",{agentId,platform:error.platform})}throw error}let runtime;try{runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to spawn agent ${agentId}: ${error.message}`);return createErrorResponse(id,RoutingErrorCodes.SPAWN_FAILED,"Agent spawn failed",{agentId,error:error.message})}if(id!==null){const msg=message;const clientSessionId=typeof msg.sessionId==="string"?msg.sessionId:void 0;this.pendingRequests.set(id,{id,agentId,timestamp:Date.now(),clientSessionId})}const transformedMessage=transformMessage(message);const success=runtime.write(transformedMessage);if(!success){logError3(`Failed to write to agent ${agentId}`);if(id!==null){this.pendingRequests.delete(id)}}else{logInfo3(`Routed message to agent ${agentId}`)}return void 0}handleAgentResponse(agentId,response){const id=extractId(response);const msg=response;let clientSessionId;if(id!==null){const pending=this.pendingRequests.get(id);if(pending&&pending.agentId===agentId){clientSessionId=pending.clientSessionId;const result=msg.result;if(result&&Array.isArray(result.authMethods)&&result.authMethods.length>0){logInfo3(`Agent ${agentId} requires authentication, attempting auto-auth`);this.authState.set(agentId,"pending");void this.attemptAuthentication(agentId,result.authMethods)}if(result&&typeof result.sessionId==="string"){const agentSessionId=result.sessionId;if(clientSessionId){this.sessionIdMap.set(agentSessionId,clientSessionId);logInfo3(`Mapped agent sessionId ${agentSessionId} to client sessionId ${clientSessionId}`)}}this.pendingRequests.delete(id)}}if(id===null&&msg.method){logInfo3(`Received notification: ${msg.method}`);const params=msg.params;if(params&&typeof params.sessionId==="string"){const agentSessionId=params.sessionId;const mappedClientSessionId=this.sessionIdMap.get(agentSessionId);if(mappedClientSessionId){const enriched={...msg,sessionId:mappedClientSessionId,params:{...params,sessionId:agentSessionId}};logInfo3(`Forwarding notification with mapped sessionId: ${mappedClientSessionId}`);this.writeCallback(enriched);return}else{logError3(`Notification with unmapped agentSessionId: ${agentSessionId}, using default sessionId`);const enriched={...msg,sessionId:"global-notifications",params:{...params,sessionId:agentSessionId}};this.writeCallback(enriched);return}}else{const topLevelSessionId=msg.sessionId;if(topLevelSessionId){this.writeCallback(response);return}else{logError3(`Notification without sessionId: ${msg.method}, adding default sessionId for routing`);const enriched={...msg,sessionId:"global-notifications"};this.writeCallback(enriched);return}}}if(clientSessionId){const enrichedResponse={...msg,sessionId:clientSessionId};logInfo3(`Forwarding response with restored sessionId: ${clientSessionId}`);this.writeCallback(enrichedResponse);return}if(id!==null&&!msg.sessionId){logError3(`Response id=${id} has no sessionId and no pending request found - routing may fail`)}this.writeCallback(response)}async attemptAuthentication(agentId,authMethods){const apiKey=getAgentApiKey(this.apiKeys,agentId);if(!apiKey){logError3(`No API key found for agent ${agentId}, authentication will fail`);this.authState.set(agentId,"none");return}let selectedMethod=authMethods.find(m=>m.id==="openai-api-key");if(!selectedMethod){selectedMethod=authMethods.find(m=>m.id.includes("api-key")||m.id.includes("apikey"))}if(!selectedMethod){selectedMethod=authMethods[0]}logInfo3(`Authenticating agent ${agentId} with method: ${selectedMethod.id}`);let runtime;try{const spawnCommand=this.registry.resolve(agentId);runtime=await this.runtimeManager.getOrSpawn(agentId,spawnCommand)}catch(error){logError3(`Failed to get runtime for authentication: ${error.message}`);this.authState.set(agentId,"none");return}const authRequest={jsonrpc:"2.0",id:`auth-${agentId}-${Date.now()}`,method:"authenticate",params:{methodId:selectedMethod.id,credentials:{apiKey}}};const transformed=transformMessage(authRequest);const serialized=JSON.stringify(transformed)+"\n";if(runtime.process.stdin){runtime.process.stdin.write(serialized,error=>{if(error){logError3(`Failed to send authenticate request to ${agentId}: ${error.message}`);this.authState.set(agentId,"none")}else{logInfo3(`Sent authenticate request to agent ${agentId}`);this.authState.set(agentId,"authenticated")}})}}get pendingCount(){return this.pendingRequests.size}isPending(id){return this.pendingRequests.has(id)}clearPending(){this.pendingRequests.clear()}}}});function formatLogMessage(level,message,context=LOG_CONTEXT){const timestamp=new Date().toISOString();return`[${timestamp}] [${level}] [${context}] ${message}`}function log(level,message,context){const formatted=formatLogMessage(level,message,context);console.error(formatted)}function logExit(agentId,exitCode,signal){if(signal){log("INFO",`Agent "${agentId}" exited with signal ${signal}`)}else if(exitCode!==null){log("INFO",`Agent "${agentId}" exited with code ${exitCode}`)}else{log("INFO",`Agent "${agentId}" exited`)}}function logInfo4(message,context){log("INFO",message,context)}function logError4(message,context){log("ERROR",message,context)}var LOG_CONTEXT;var init_log=__esm({"workers-registry/acp-worker/src/registry-launcher/log.ts"(){"use strict";LOG_CONTEXT="registry-launcher"}});var registry_launcher_exports={};function parseArgs(){const args=process.argv.slice(2);if(args.length>0&&args[0]&&!args[0].startsWith("-")){return args[0]}return void 0}function setupSignalHandlers(runtimeManager,shutdownTimeoutMs){const shutdown=async()=>{if(isShuttingDown){return}isShuttingDown=true;logInfo4("Received shutdown signal, initiating graceful shutdown");try{await runtimeManager.terminateAll(shutdownTimeoutMs);logInfo4("All agent processes terminated");process.exit(ExitCodes.SUCCESS)}catch(error){logError4(`Error during shutdown: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}};process.on("SIGTERM",()=>{void shutdown()});process.on("SIGINT",()=>{void shutdown()});return shutdown}function setupStdinHandler(router,ndjsonHandler){ndjsonHandler.onMessage(async message=>{try{const errorResponse=await router.route(message);if(errorResponse){ndjsonHandler.write(errorResponse)}}catch(error){logError4(`Unexpected error routing message: ${error.message}`)}});ndjsonHandler.onError((error,line)=>{logError4(`Failed to parse NDJSON: ${error.message} - Line: ${line.slice(0,100)}`)});process.stdin.setEncoding("utf8");process.stdin.on("data",chunk=>{const buffer=typeof chunk==="string"?Buffer.from(chunk):chunk;ndjsonHandler.processChunk(buffer)});process.stdin.on("end",()=>{logInfo4("stdin closed")});process.stdin.on("error",error=>{logError4(`stdin error: ${error.message}`)})}function setupAgentResponseHandling(runtimeManager,router){runtimeManager.onAgentExit((agentId,code)=>{logExit(agentId,code)});const originalGetOrSpawn=runtimeManager.getOrSpawn.bind(runtimeManager);runtimeManager.getOrSpawn=async function(agentId,spawnCommand){const runtime=await originalGetOrSpawn(agentId,spawnCommand);const proc=runtime.process;if(proc.stdout&&!proc.stdout.listenerCount("data")){let buffer="";proc.stdout.on("data",chunk=>{buffer+=chunk;let newlineIndex;while((newlineIndex=buffer.indexOf("\n"))!==-1){const line=buffer.slice(0,newlineIndex);buffer=buffer.slice(newlineIndex+1);if(line.trim()){try{const response=JSON.parse(line);router.handleAgentResponse(agentId,response)}catch(err){logError4(`Failed to parse agent ${agentId} response: ${err.message}`)}}}})}if(proc.stderr&&!proc.stderr.listenerCount("data")){proc.stderr.on("data",chunk=>{process.stderr.write(`[agent:${agentId}] ${chunk}`)})}return runtime}}async function main(){logInfo4("Registry Launcher starting");const configPath=parseArgs();if(configPath){logInfo4(`Loading configuration from: ${configPath}`)}const config=loadConfig(configPath);logInfo4(`Configuration loaded: registryUrl=${config.registryUrl}, apiKeysPath=${config.apiKeysPath}, shutdownTimeoutSec=${config.shutdownTimeoutSec}`);const apiKeys=loadApiKeys(config.apiKeysPath);const registry=new RegistryIndex(config.registryUrl);try{await registry.fetch()}catch(error){if(error instanceof RegistryFetchError){logError4(`Failed to fetch registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}if(error instanceof RegistryParseError){logError4(`Failed to parse registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}logError4(`Unexpected error fetching registry: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)}const runtimeManager=new AgentRuntimeManager;const ndjsonHandler=new NDJSONHandler(process.stdout);const router=new MessageRouter(registry,runtimeManager,message=>ndjsonHandler.write(message),apiKeys);const shutdownTimeoutMs=config.shutdownTimeoutSec*1e3;setupSignalHandlers(runtimeManager,shutdownTimeoutMs);setupAgentResponseHandling(runtimeManager,router);setupStdinHandler(router,ndjsonHandler);logInfo4("Registry Launcher ready, waiting for messages")}var ExitCodes,isShuttingDown;var init_registry_launcher=__esm({"workers-registry/acp-worker/src/registry-launcher/index.ts"(){"use strict";init_config();init_api_keys();init_registry();init_ndjson_handler();init_manager();init_message_router();init_log();ExitCodes={SUCCESS:0,FATAL_ERROR:1};isShuttingDown=false;main().catch(error=>{logError4(`Fatal error: ${error.message}`);process.exit(ExitCodes.FATAL_ERROR)})}});import{fileURLToPath}from"url";import{dirname,join}from"path";var __filename=fileURLToPath(import.meta.url);var __dirname=dirname(__filename);var DEFAULT_CONFIG_FILE="acp-registry-config.json";function ensureDefaultConfigArg(){const hasExplicitConfig=process.argv.length>2&&process.argv[2]&&!process.argv[2].startsWith("-");if(hasExplicitConfig){return}const defaultConfigPath=join(__dirname,DEFAULT_CONFIG_FILE);process.argv.splice(2,0,defaultConfigPath)}ensureDefaultConfigArg();await Promise.resolve().then(()=>(init_registry_launcher(),registry_launcher_exports));
5
5
  //# sourceMappingURL=index.js.map