agentxjs 1.9.9-dev → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/RemoteClient.ts","../../../node_modules/commonxjs/dist/src/logger/ConsoleLogger.ts","../../../node_modules/commonxjs/dist/src/logger/LoggerFactoryImpl.ts","../src/presentation/types.ts","../src/presentation/reducer.ts","../src/presentation/Presentation.ts","../src/index.ts"],"sourcesContent":["/**\n * RemoteClient - AgentX client for remote server\n *\n * Uses RpcClient from @agentxjs/core/network for JSON-RPC communication.\n * This class focuses on business logic, not protocol details.\n */\n\nimport type { BusEvent, EventBus, BusEventHandler, Unsubscribe } from \"@agentxjs/core/event\";\nimport { EventBusImpl } from \"@agentxjs/core/event\";\nimport { RpcClient, type RpcMethod } from \"@agentxjs/core/network\";\nimport { createLogger } from \"commonxjs/logger\";\nimport type {\n AgentX,\n AgentXConfig,\n AgentCreateResponse,\n AgentGetResponse,\n AgentListResponse,\n ImageCreateResponse,\n ImageGetResponse,\n ImageListResponse,\n ContainerCreateResponse,\n ContainerGetResponse,\n ContainerListResponse,\n MessageSendResponse,\n BaseResponse,\n} from \"./types\";\nimport { Presentation, type PresentationOptions } from \"./presentation\";\n\nconst logger = createLogger(\"agentx/RemoteClient\");\n\n/**\n * RemoteClient implementation using JSON-RPC 2.0\n */\nexport class RemoteClient implements AgentX {\n private readonly config: AgentXConfig;\n private readonly eventBus: EventBus;\n private readonly rpcClient: RpcClient;\n\n constructor(config: AgentXConfig) {\n this.config = config;\n this.eventBus = new EventBusImpl();\n\n // Create RPC client\n this.rpcClient = new RpcClient({\n url: config.serverUrl,\n timeout: config.timeout ?? 30000,\n autoReconnect: config.autoReconnect ?? true,\n headers: config.headers as Record<string, string> | undefined,\n debug: false,\n });\n\n // Forward stream events to internal event bus\n this.rpcClient.onStreamEvent((topic, event) => {\n logger.debug(\"Received stream event\", { topic, type: event.type });\n this.eventBus.emit(event as BusEvent);\n });\n }\n\n // ==================== Properties ====================\n\n get connected(): boolean {\n return this.rpcClient.connected;\n }\n\n get events(): EventBus {\n return this.eventBus;\n }\n\n // ==================== Connection ====================\n\n async connect(): Promise<void> {\n await this.rpcClient.connect();\n logger.info(\"Connected to server\", { url: this.config.serverUrl });\n }\n\n async disconnect(): Promise<void> {\n this.rpcClient.disconnect();\n logger.info(\"Disconnected from server\");\n }\n\n async dispose(): Promise<void> {\n this.rpcClient.dispose();\n this.eventBus.destroy();\n logger.info(\"RemoteClient disposed\");\n }\n\n // ==================== Container Operations ====================\n\n async createContainer(containerId: string): Promise<ContainerCreateResponse> {\n const result = await this.rpcClient.call<ContainerCreateResponse>(\"container.create\", {\n containerId,\n });\n return { ...result, requestId: \"\" };\n }\n\n async getContainer(containerId: string): Promise<ContainerGetResponse> {\n const result = await this.rpcClient.call<ContainerGetResponse>(\"container.get\", {\n containerId,\n });\n return { ...result, requestId: \"\" };\n }\n\n async listContainers(): Promise<ContainerListResponse> {\n const result = await this.rpcClient.call<ContainerListResponse>(\"container.list\", {});\n return { ...result, requestId: \"\" };\n }\n\n // ==================== Image Operations ====================\n\n async createImage(params: {\n containerId: string;\n name?: string;\n description?: string;\n systemPrompt?: string;\n mcpServers?: Record<string, unknown>;\n }): Promise<ImageCreateResponse> {\n const result = await this.rpcClient.call<ImageCreateResponse>(\"image.create\", params);\n\n // Auto subscribe to session events\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n this.subscribe(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n }\n\n async getImage(imageId: string): Promise<ImageGetResponse> {\n const result = await this.rpcClient.call<ImageGetResponse>(\"image.get\", { imageId });\n\n // Auto subscribe\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n this.subscribe(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n }\n\n async listImages(containerId?: string): Promise<ImageListResponse> {\n const result = await this.rpcClient.call<ImageListResponse>(\"image.list\", { containerId });\n\n // Auto subscribe\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n this.subscribe(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n }\n\n async deleteImage(imageId: string): Promise<BaseResponse> {\n const result = await this.rpcClient.call<BaseResponse>(\"image.delete\", { imageId });\n return { ...result, requestId: \"\" };\n }\n\n // ==================== Agent Operations ====================\n\n async createAgent(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {\n // Agent creation via image.run RPC\n const result = await this.rpcClient.call<AgentCreateResponse>(\"image.run\" as RpcMethod, {\n imageId: params.imageId,\n agentId: params.agentId,\n });\n return { ...result, requestId: \"\" };\n }\n\n async getAgent(agentId: string): Promise<AgentGetResponse> {\n const result = await this.rpcClient.call<AgentGetResponse>(\"agent.get\", { agentId });\n return { ...result, requestId: \"\" };\n }\n\n async listAgents(containerId?: string): Promise<AgentListResponse> {\n const result = await this.rpcClient.call<AgentListResponse>(\"agent.list\", { containerId });\n return { ...result, requestId: \"\" };\n }\n\n async destroyAgent(agentId: string): Promise<BaseResponse> {\n const result = await this.rpcClient.call<BaseResponse>(\"agent.destroy\", { agentId });\n return { ...result, requestId: \"\" };\n }\n\n // ==================== Message Operations ====================\n\n async sendMessage(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {\n const result = await this.rpcClient.call<MessageSendResponse>(\"message.send\", {\n agentId,\n content,\n });\n return { ...result, requestId: \"\" };\n }\n\n async interrupt(agentId: string): Promise<BaseResponse> {\n const result = await this.rpcClient.call<BaseResponse>(\"agent.interrupt\", { agentId });\n return { ...result, requestId: \"\" };\n }\n\n // ==================== Event Subscription ====================\n\n on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {\n return this.eventBus.on(type, handler);\n }\n\n onAny(handler: BusEventHandler): Unsubscribe {\n return this.eventBus.onAny(handler);\n }\n\n subscribe(sessionId: string): void {\n this.rpcClient.subscribe(sessionId);\n logger.debug(\"Subscribed to session\", { sessionId });\n }\n\n // ==================== Presentation ====================\n\n presentation(agentId: string, options?: PresentationOptions): Presentation {\n return new Presentation(this, agentId, options);\n }\n}\n","/**\n * ConsoleLogger - Default logger implementation\n *\n * Simple console-based logger with color support.\n * Used as fallback when no custom LoggerFactory is provided.\n */\n\nimport type { Logger, LogContext, LogLevel } from \"./types\";\n\nexport interface ConsoleLoggerOptions {\n level?: LogLevel;\n colors?: boolean;\n timestamps?: boolean;\n}\n\nexport class ConsoleLogger implements Logger {\n readonly name: string;\n readonly level: LogLevel;\n private readonly colors: boolean;\n private readonly timestamps: boolean;\n\n private static readonly COLORS = {\n DEBUG: \"\\x1b[36m\",\n INFO: \"\\x1b[32m\",\n WARN: \"\\x1b[33m\",\n ERROR: \"\\x1b[31m\",\n RESET: \"\\x1b[0m\",\n };\n\n constructor(name: string, options: ConsoleLoggerOptions = {}) {\n this.name = name;\n this.level = options.level ?? \"info\";\n this.colors = options.colors ?? this.isNodeEnvironment();\n this.timestamps = options.timestamps ?? true;\n }\n\n debug(message: string, context?: LogContext): void {\n if (this.isDebugEnabled()) {\n this.log(\"DEBUG\", message, context);\n }\n }\n\n info(message: string, context?: LogContext): void {\n if (this.isInfoEnabled()) {\n this.log(\"INFO\", message, context);\n }\n }\n\n warn(message: string, context?: LogContext): void {\n if (this.isWarnEnabled()) {\n this.log(\"WARN\", message, context);\n }\n }\n\n error(message: string | Error, context?: LogContext): void {\n if (this.isErrorEnabled()) {\n if (message instanceof Error) {\n this.log(\"ERROR\", message.message, { ...context, stack: message.stack });\n } else {\n this.log(\"ERROR\", message, context);\n }\n }\n }\n\n isDebugEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"debug\");\n }\n\n isInfoEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"info\");\n }\n\n isWarnEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"warn\");\n }\n\n isErrorEnabled(): boolean {\n return this.getLevelValue(this.level) <= this.getLevelValue(\"error\");\n }\n\n private getLevelValue(level: LogLevel): number {\n const levels: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n silent: 4,\n };\n return levels[level];\n }\n\n private log(level: string, message: string, context?: LogContext): void {\n const parts: string[] = [];\n\n if (this.timestamps) {\n parts.push(new Date().toISOString());\n }\n\n if (this.colors) {\n const color = ConsoleLogger.COLORS[level as keyof typeof ConsoleLogger.COLORS];\n parts.push(`${color}${level.padEnd(5)}${ConsoleLogger.COLORS.RESET}`);\n } else {\n parts.push(level.padEnd(5));\n }\n\n parts.push(`[${this.name}]`);\n parts.push(message);\n\n const logLine = parts.join(\" \");\n const consoleMethod = this.getConsoleMethod(level);\n\n if (context && Object.keys(context).length > 0) {\n consoleMethod(logLine, context);\n } else {\n consoleMethod(logLine);\n }\n }\n\n private getConsoleMethod(level: string): (...args: unknown[]) => void {\n switch (level) {\n case \"DEBUG\":\n return console.debug.bind(console);\n case \"INFO\":\n return console.info.bind(console);\n case \"WARN\":\n return console.warn.bind(console);\n case \"ERROR\":\n return console.error.bind(console);\n default:\n return console.log.bind(console);\n }\n }\n\n private isNodeEnvironment(): boolean {\n return typeof process !== \"undefined\" && process.versions?.node !== undefined;\n }\n}\n","/**\n * LoggerFactoryImpl - Central factory for creating logger instances\n *\n * Implements lazy initialization pattern:\n * - createLogger() can be called at module level (before config)\n * - Real logger is created on first use\n * - External LoggerFactory can be injected via Runtime\n */\n\nimport type { Logger, LoggerFactory, LogContext, LogLevel } from \"./types\";\nimport { ConsoleLogger, type ConsoleLoggerOptions } from \"./ConsoleLogger\";\n\n// External factory injected via Runtime\nlet externalFactory: LoggerFactory | null = null;\n\n// Version counter to invalidate cached real loggers\nlet factoryVersion = 0;\n\nexport interface LoggerFactoryConfig {\n defaultImplementation?: (name: string) => Logger;\n defaultLevel?: LogLevel;\n consoleOptions?: Omit<ConsoleLoggerOptions, \"level\">;\n}\n\n/**\n * Internal LoggerFactory implementation\n *\n * Uses lazy proxy pattern to allow module-level createLogger() calls.\n */\nexport class LoggerFactoryImpl {\n private static loggers: Map<string, Logger> = new Map();\n private static config: LoggerFactoryConfig = {\n defaultLevel: \"info\",\n };\n\n static getLogger(nameOrClass: string | (new (...args: unknown[]) => unknown)): Logger {\n const name = typeof nameOrClass === \"string\" ? nameOrClass : nameOrClass.name;\n\n if (this.loggers.has(name)) {\n return this.loggers.get(name)!;\n }\n\n const lazyLogger = this.createLazyLogger(name);\n this.loggers.set(name, lazyLogger);\n return lazyLogger;\n }\n\n static configure(config: LoggerFactoryConfig): void {\n this.config = { ...this.config, ...config };\n }\n\n static reset(): void {\n this.loggers.clear();\n this.config = { defaultLevel: \"info\" };\n externalFactory = null;\n factoryVersion++; // Invalidate all cached real loggers\n }\n\n private static createLazyLogger(name: string): Logger {\n let realLogger: Logger | null = null;\n let loggerVersion = -1; // Track which factory version created this logger\n\n const getRealLogger = (): Logger => {\n // Recreate logger if factory version changed (setLoggerFactory was called)\n if (!realLogger || loggerVersion !== factoryVersion) {\n realLogger = this.createLogger(name);\n loggerVersion = factoryVersion;\n }\n return realLogger;\n };\n\n return {\n name,\n level: this.config.defaultLevel || \"info\",\n debug: (message: string, context?: LogContext) => getRealLogger().debug(message, context),\n info: (message: string, context?: LogContext) => getRealLogger().info(message, context),\n warn: (message: string, context?: LogContext) => getRealLogger().warn(message, context),\n error: (message: string | Error, context?: LogContext) =>\n getRealLogger().error(message, context),\n isDebugEnabled: () => getRealLogger().isDebugEnabled(),\n isInfoEnabled: () => getRealLogger().isInfoEnabled(),\n isWarnEnabled: () => getRealLogger().isWarnEnabled(),\n isErrorEnabled: () => getRealLogger().isErrorEnabled(),\n };\n }\n\n private static createLogger(name: string): Logger {\n if (externalFactory) {\n return externalFactory.getLogger(name);\n }\n\n if (this.config.defaultImplementation) {\n return this.config.defaultImplementation(name);\n }\n\n return new ConsoleLogger(name, {\n level: this.config.defaultLevel,\n ...this.config.consoleOptions,\n });\n }\n}\n\n/**\n * Set external LoggerFactory (called by Runtime initialization)\n */\nexport function setLoggerFactory(factory: LoggerFactory): void {\n externalFactory = factory;\n LoggerFactoryImpl.reset();\n externalFactory = factory;\n}\n\n/**\n * Create a logger instance\n *\n * Safe to call at module level before Runtime is configured.\n * Uses lazy initialization - actual logger is created on first use.\n *\n * @param name - Logger name (hierarchical, e.g., \"engine/AgentEngine\")\n * @returns Logger instance (lazy proxy)\n */\nexport function createLogger(name: string): Logger {\n return LoggerFactoryImpl.getLogger(name);\n}\n","/**\n * Presentation Types\n *\n * UI-friendly data model aggregated from stream events.\n * This implements the Presentation Model pattern.\n */\n\n// ============================================================================\n// Block Types - Basic content units\n// ============================================================================\n\n/**\n * Text block\n */\nexport interface TextBlock {\n type: \"text\";\n content: string;\n}\n\n/**\n * Tool block - represents a tool call and its result\n */\nexport interface ToolBlock {\n type: \"tool\";\n toolUseId: string;\n toolName: string;\n toolInput: Record<string, unknown>;\n toolResult?: string;\n status: \"pending\" | \"running\" | \"completed\" | \"error\";\n}\n\n/**\n * Image block\n */\nexport interface ImageBlock {\n type: \"image\";\n url: string;\n alt?: string;\n}\n\n/**\n * All block types\n */\nexport type Block = TextBlock | ToolBlock | ImageBlock;\n\n// ============================================================================\n// Conversation Types - A single turn in the conversation\n// ============================================================================\n\n/**\n * User conversation\n */\nexport interface UserConversation {\n role: \"user\";\n blocks: Block[];\n}\n\n/**\n * Assistant conversation\n */\nexport interface AssistantConversation {\n role: \"assistant\";\n blocks: Block[];\n isStreaming: boolean;\n}\n\n/**\n * Error conversation\n */\nexport interface ErrorConversation {\n role: \"error\";\n message: string;\n}\n\n/**\n * All conversation types\n */\nexport type Conversation = UserConversation | AssistantConversation | ErrorConversation;\n\n// ============================================================================\n// Presentation State\n// ============================================================================\n\n/**\n * Presentation state - the complete UI state\n */\nexport interface PresentationState {\n /**\n * All completed conversations\n */\n conversations: Conversation[];\n\n /**\n * Current streaming conversation (null if not streaming)\n */\n streaming: AssistantConversation | null;\n\n /**\n * Current status\n */\n status: \"idle\" | \"thinking\" | \"responding\" | \"executing\";\n}\n\n/**\n * Initial presentation state\n */\nexport const initialPresentationState: PresentationState = {\n conversations: [],\n streaming: null,\n status: \"idle\",\n};\n","/**\n * Presentation Reducer\n *\n * Aggregates stream events into PresentationState.\n * Pure function: (state, event) => newState\n */\n\nimport type { BusEvent } from \"@agentxjs/core/event\";\nimport type {\n PresentationState,\n AssistantConversation,\n TextBlock,\n ToolBlock,\n Block,\n} from \"./types\";\nimport { initialPresentationState } from \"./types\";\n\n// ============================================================================\n// Event Data Types (from stream events)\n// ============================================================================\n\ninterface MessageStartData {\n messageId?: string;\n model?: string;\n}\n\ninterface TextDeltaData {\n text: string;\n}\n\ninterface ToolUseStartData {\n toolUseId: string;\n toolName: string;\n}\n\ninterface InputJsonDeltaData {\n delta: string;\n}\n\ninterface ToolResultData {\n toolUseId: string;\n result: string;\n isError?: boolean;\n}\n\ninterface MessageStopData {\n stopReason?: string;\n}\n\ninterface ErrorData {\n message: string;\n code?: string;\n}\n\n// ============================================================================\n// Reducer\n// ============================================================================\n\n/**\n * Reduce a stream event into presentation state\n */\nexport function presentationReducer(\n state: PresentationState,\n event: BusEvent\n): PresentationState {\n switch (event.type) {\n case \"message_start\":\n return handleMessageStart(state, event.data as MessageStartData);\n\n case \"text_delta\":\n return handleTextDelta(state, event.data as TextDeltaData);\n\n case \"tool_use_start\":\n return handleToolUseStart(state, event.data as ToolUseStartData);\n\n case \"input_json_delta\":\n return handleInputJsonDelta(state, event.data as InputJsonDeltaData);\n\n case \"tool_result\":\n return handleToolResult(state, event.data as ToolResultData);\n\n case \"message_stop\":\n return handleMessageStop(state, event.data as MessageStopData);\n\n case \"error\":\n return handleError(state, event.data as ErrorData);\n\n default:\n return state;\n }\n}\n\n// ============================================================================\n// Handlers\n// ============================================================================\n\nfunction handleMessageStart(\n state: PresentationState,\n _data: MessageStartData\n): PresentationState {\n // Start a new streaming assistant conversation\n const streaming: AssistantConversation = {\n role: \"assistant\",\n blocks: [],\n isStreaming: true,\n };\n\n return {\n ...state,\n streaming,\n status: \"thinking\",\n };\n}\n\nfunction handleTextDelta(\n state: PresentationState,\n data: TextDeltaData\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const blocks = [...state.streaming.blocks];\n const lastBlock = blocks[blocks.length - 1];\n\n // Append to existing TextBlock or create new one\n if (lastBlock && lastBlock.type === \"text\") {\n blocks[blocks.length - 1] = {\n ...lastBlock,\n content: lastBlock.content + data.text,\n };\n } else {\n blocks.push({\n type: \"text\",\n content: data.text,\n } as TextBlock);\n }\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n status: \"responding\",\n };\n}\n\nfunction handleToolUseStart(\n state: PresentationState,\n data: ToolUseStartData\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const toolBlock: ToolBlock = {\n type: \"tool\",\n toolUseId: data.toolUseId,\n toolName: data.toolName,\n toolInput: {},\n status: \"pending\",\n };\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks: [...state.streaming.blocks, toolBlock],\n },\n status: \"executing\",\n };\n}\n\nfunction handleInputJsonDelta(\n state: PresentationState,\n data: InputJsonDeltaData\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const blocks = [...state.streaming.blocks];\n const lastBlock = blocks[blocks.length - 1];\n\n // Find the last tool block and update its input\n if (lastBlock && lastBlock.type === \"tool\") {\n // Accumulate JSON delta (will be parsed when complete)\n const currentInput = (lastBlock as ToolBlock & { _rawInput?: string })._rawInput || \"\";\n const newInput = currentInput + data.delta;\n\n // Try to parse the accumulated JSON\n let toolInput = lastBlock.toolInput;\n try {\n toolInput = JSON.parse(newInput);\n } catch {\n // Not yet valid JSON, keep accumulating\n }\n\n blocks[blocks.length - 1] = {\n ...lastBlock,\n toolInput,\n _rawInput: newInput,\n status: \"running\",\n } as ToolBlock & { _rawInput?: string };\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n };\n }\n\n return state;\n}\n\nfunction handleToolResult(\n state: PresentationState,\n data: ToolResultData\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const blocks = state.streaming.blocks.map((block): Block => {\n if (block.type === \"tool\" && block.toolUseId === data.toolUseId) {\n return {\n ...block,\n toolResult: data.result,\n status: data.isError ? \"error\" : \"completed\",\n };\n }\n return block;\n });\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n status: \"responding\",\n };\n}\n\nfunction handleMessageStop(\n state: PresentationState,\n _data: MessageStopData\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n // Move streaming to conversations\n const completedConversation: AssistantConversation = {\n ...state.streaming,\n isStreaming: false,\n };\n\n return {\n ...state,\n conversations: [...state.conversations, completedConversation],\n streaming: null,\n status: \"idle\",\n };\n}\n\nfunction handleError(\n state: PresentationState,\n data: ErrorData\n): PresentationState {\n // Add error conversation\n return {\n ...state,\n conversations: [\n ...state.conversations,\n {\n role: \"error\",\n message: data.message,\n },\n ],\n streaming: null,\n status: \"idle\",\n };\n}\n\n// ============================================================================\n// Helper: Add user conversation\n// ============================================================================\n\n/**\n * Add a user conversation to state\n */\nexport function addUserConversation(\n state: PresentationState,\n content: string\n): PresentationState {\n return {\n ...state,\n conversations: [\n ...state.conversations,\n {\n role: \"user\",\n blocks: [{ type: \"text\", content }],\n },\n ],\n };\n}\n\n/**\n * Create initial state\n */\nexport function createInitialState(): PresentationState {\n return { ...initialPresentationState };\n}\n","/**\n * Presentation Class\n *\n * High-level API for UI integration.\n * Wraps AgentX client and provides presentation state management.\n */\n\nimport type { AgentX } from \"../types\";\nimport type { Unsubscribe, BusEvent } from \"@agentxjs/core/event\";\nimport type { PresentationState } from \"./types\";\nimport {\n presentationReducer,\n addUserConversation,\n createInitialState,\n} from \"./reducer\";\n\n/**\n * Presentation update handler\n */\nexport type PresentationUpdateHandler = (state: PresentationState) => void;\n\n/**\n * Presentation error handler\n */\nexport type PresentationErrorHandler = (error: Error) => void;\n\n/**\n * Presentation options\n */\nexport interface PresentationOptions {\n /**\n * Called on every state update\n */\n onUpdate?: PresentationUpdateHandler;\n\n /**\n * Called on errors\n */\n onError?: PresentationErrorHandler;\n}\n\n/**\n * Presentation - UI-friendly wrapper for AgentX\n */\nexport class Presentation {\n private agentx: AgentX;\n private agentId: string;\n private state: PresentationState;\n private updateHandlers: Set<PresentationUpdateHandler> = new Set();\n private errorHandlers: Set<PresentationErrorHandler> = new Set();\n private eventUnsubscribe: Unsubscribe | null = null;\n\n constructor(agentx: AgentX, agentId: string, options?: PresentationOptions) {\n this.agentx = agentx;\n this.agentId = agentId;\n this.state = createInitialState();\n\n // Register initial handlers\n if (options?.onUpdate) {\n this.updateHandlers.add(options.onUpdate);\n }\n if (options?.onError) {\n this.errorHandlers.add(options.onError);\n }\n\n // Subscribe to all events\n this.subscribeToEvents();\n }\n\n /**\n * Get current state\n */\n getState(): PresentationState {\n return this.state;\n }\n\n /**\n * Subscribe to state updates\n */\n onUpdate(handler: PresentationUpdateHandler): Unsubscribe {\n this.updateHandlers.add(handler);\n // Immediately call with current state\n handler(this.state);\n return () => {\n this.updateHandlers.delete(handler);\n };\n }\n\n /**\n * Subscribe to errors\n */\n onError(handler: PresentationErrorHandler): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n /**\n * Send a message\n */\n async send(content: string): Promise<void> {\n // Add user conversation\n this.state = addUserConversation(this.state, content);\n this.notify();\n\n try {\n // Send message via agentx\n await this.agentx.sendMessage(this.agentId, content);\n } catch (error) {\n this.notifyError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Interrupt current response\n */\n async interrupt(): Promise<void> {\n try {\n await this.agentx.interrupt(this.agentId);\n } catch (error) {\n this.notifyError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Reset state\n */\n reset(): void {\n this.state = createInitialState();\n this.notify();\n }\n\n /**\n * Dispose and cleanup\n */\n dispose(): void {\n if (this.eventUnsubscribe) {\n this.eventUnsubscribe();\n this.eventUnsubscribe = null;\n }\n this.updateHandlers.clear();\n this.errorHandlers.clear();\n }\n\n // ==================== Private ====================\n\n private subscribeToEvents(): void {\n // Subscribe to all events and filter by agentId\n this.eventUnsubscribe = this.agentx.onAny((event: BusEvent) => {\n // Filter events for this agent (if context is available)\n // Note: Events from server may or may not include context with agentId\n const eventWithContext = event as BusEvent & { context?: { agentId?: string } };\n const eventAgentId = eventWithContext.context?.agentId;\n\n // Only filter if event has agentId and it doesn't match\n if (eventAgentId && eventAgentId !== this.agentId) {\n return;\n }\n\n // Reduce event into state\n const newState = presentationReducer(this.state, event);\n if (newState !== this.state) {\n this.state = newState;\n this.notify();\n }\n });\n }\n\n private notify(): void {\n for (const handler of this.updateHandlers) {\n try {\n handler(this.state);\n } catch (error) {\n console.error(\"Presentation update handler error:\", error);\n }\n }\n }\n\n private notifyError(error: Error): void {\n for (const handler of this.errorHandlers) {\n try {\n handler(error);\n } catch (e) {\n console.error(\"Presentation error handler error:\", e);\n }\n }\n }\n}\n","/**\n * agentxjs - AgentX Client SDK\n *\n * Connect to AgentX servers from Node.js and browsers.\n *\n * @example\n * ```typescript\n * import { createAgentX } from \"agentxjs\";\n *\n * // Connect to server\n * const agentx = await createAgentX({\n * serverUrl: \"ws://localhost:5200\",\n * headers: { Authorization: \"Bearer sk-xxx\" },\n * context: { userId: \"123\", tenantId: \"abc\" },\n * });\n *\n * // Create container and image\n * await agentx.createContainer(\"my-container\");\n * const { record: image } = await agentx.createImage({\n * containerId: \"my-container\",\n * name: \"Assistant\",\n * systemPrompt: \"You are a helpful assistant\",\n * });\n *\n * // Create agent and send message\n * const { agentId } = await agentx.createAgent({ imageId: image.imageId });\n *\n * // Subscribe to events\n * agentx.on(\"text_delta\", (event) => {\n * process.stdout.write(event.data.text);\n * });\n *\n * agentx.on(\"assistant_message\", (event) => {\n * console.log(\"Complete:\", event.data.content);\n * });\n *\n * // Send message\n * await agentx.sendMessage(agentId, \"Hello!\");\n *\n * // Cleanup\n * await agentx.dispose();\n * ```\n *\n * @example Dynamic headers and context\n * ```typescript\n * const agentx = await createAgentX({\n * serverUrl: \"ws://localhost:5200\",\n * headers: () => ({ Authorization: `Bearer ${getToken()}` }),\n * context: async () => ({\n * userId: await getUserId(),\n * permissions: await getPermissions(),\n * }),\n * });\n * ```\n */\n\nimport { RemoteClient } from \"./RemoteClient\";\nimport type { AgentX, AgentXConfig } from \"./types\";\n\n/**\n * Create an AgentX client\n *\n * @param config - Client configuration\n * @returns Connected AgentX client\n */\nexport async function createAgentX(config: AgentXConfig): Promise<AgentX> {\n const client = new RemoteClient(config);\n await client.connect();\n return client;\n}\n\n// Re-export types\nexport type {\n AgentX,\n AgentXConfig,\n MaybeAsync,\n AgentInfo,\n ImageRecord,\n ContainerInfo,\n AgentCreateResponse,\n AgentGetResponse,\n AgentListResponse,\n ImageCreateResponse,\n ImageGetResponse,\n ImageListResponse,\n ContainerCreateResponse,\n ContainerGetResponse,\n ContainerListResponse,\n MessageSendResponse,\n BaseResponse,\n} from \"./types\";\n\n// Re-export Presentation types and classes\nexport type {\n Block,\n TextBlock,\n ToolBlock,\n ImageBlock,\n Conversation,\n UserConversation,\n AssistantConversation,\n ErrorConversation,\n PresentationState,\n PresentationOptions,\n PresentationUpdateHandler,\n PresentationErrorHandler,\n} from \"./presentation\";\n\nexport {\n Presentation,\n presentationReducer,\n addUserConversation,\n createInitialState,\n initialPresentationState,\n} from \"./presentation\";\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/RemoteClient.ts","../src/namespaces/containers.ts","../src/namespaces/images.ts","../src/namespaces/agents.ts","../src/namespaces/sessions.ts","../src/presentation/types.ts","../src/presentation/reducer.ts","../src/presentation/Presentation.ts","../src/namespaces/presentations.ts","../src/LocalClient.ts","../src/index.ts"],"sourcesContent":["/**\n * RemoteClient - AgentX client for remote server\n *\n * Uses RpcClient from @agentxjs/core/network for JSON-RPC communication.\n * This class focuses on business logic, not protocol details.\n */\n\nimport type { BusEvent, EventBus, BusEventHandler, Unsubscribe } from \"@agentxjs/core/event\";\nimport { EventBusImpl } from \"@agentxjs/core/event\";\nimport { RpcClient } from \"@agentxjs/core/network\";\nimport { createLogger } from \"commonxjs/logger\";\nimport type {\n AgentX,\n AgentXConfig,\n ContainerNamespace,\n ImageNamespace,\n AgentNamespace,\n SessionNamespace,\n PresentationNamespace,\n} from \"./types\";\nimport { createRemoteContainers } from \"./namespaces/containers\";\nimport { createRemoteImages } from \"./namespaces/images\";\nimport { createRemoteAgents } from \"./namespaces/agents\";\nimport { createRemoteSessions } from \"./namespaces/sessions\";\nimport { createPresentations } from \"./namespaces/presentations\";\n\nconst logger = createLogger(\"agentx/RemoteClient\");\n\n/**\n * RemoteClient implementation using JSON-RPC 2.0\n */\nexport class RemoteClient implements AgentX {\n private readonly config: AgentXConfig;\n private readonly eventBus: EventBus;\n private readonly rpcClient: RpcClient;\n\n readonly containers: ContainerNamespace;\n readonly images: ImageNamespace;\n readonly agents: AgentNamespace;\n readonly sessions: SessionNamespace;\n readonly presentations: PresentationNamespace;\n\n constructor(config: AgentXConfig) {\n this.config = config;\n this.eventBus = new EventBusImpl();\n\n // Create RPC client (WebSocket factory from platform if available)\n this.rpcClient = new RpcClient({\n url: config.serverUrl!,\n createWebSocket: config.customPlatform?.webSocketFactory,\n timeout: config.timeout ?? 30000,\n autoReconnect: config.autoReconnect ?? true,\n headers: config.headers as Record<string, string> | undefined,\n debug: false,\n });\n\n // Forward stream events to internal event bus\n this.rpcClient.onStreamEvent((topic, event) => {\n logger.debug(\"Received stream event\", { topic, type: event.type });\n this.eventBus.emit(event as BusEvent);\n });\n\n // Assemble namespaces\n this.containers = createRemoteContainers(this.rpcClient);\n this.images = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));\n this.agents = createRemoteAgents(this.rpcClient);\n this.sessions = createRemoteSessions(this.rpcClient);\n this.presentations = createPresentations(this);\n }\n\n // ==================== Properties ====================\n\n get connected(): boolean {\n return this.rpcClient.connected;\n }\n\n get events(): EventBus {\n return this.eventBus;\n }\n\n // ==================== Connection ====================\n\n async connect(): Promise<void> {\n await this.rpcClient.connect();\n logger.info(\"Connected to server\", { url: this.config.serverUrl });\n }\n\n async disconnect(): Promise<void> {\n this.rpcClient.disconnect();\n logger.info(\"Disconnected from server\");\n }\n\n async dispose(): Promise<void> {\n this.rpcClient.dispose();\n this.eventBus.destroy();\n logger.info(\"RemoteClient disposed\");\n }\n\n // ==================== Event Subscription ====================\n\n on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {\n return this.eventBus.on(type, handler);\n }\n\n onAny(handler: BusEventHandler): Unsubscribe {\n return this.eventBus.onAny(handler);\n }\n\n subscribe(sessionId: string): void {\n this.rpcClient.subscribe(sessionId);\n logger.debug(\"Subscribed to session\", { sessionId });\n }\n}\n","/**\n * Container namespace factories\n */\n\nimport type { AgentXPlatform } from \"@agentxjs/core/runtime\";\nimport type { RpcClient } from \"@agentxjs/core/network\";\nimport type {\n ContainerNamespace,\n ContainerCreateResponse,\n ContainerGetResponse,\n ContainerListResponse,\n} from \"../types\";\n\n/**\n * Create local container namespace backed by embedded runtime\n */\nexport function createLocalContainers(platform: AgentXPlatform): ContainerNamespace {\n return {\n async create(containerId: string): Promise<ContainerCreateResponse> {\n const { getOrCreateContainer } = await import(\"@agentxjs/core/container\");\n const { containerRepository, imageRepository, sessionRepository } = platform;\n\n const container = await getOrCreateContainer(containerId, {\n containerRepository,\n imageRepository,\n sessionRepository,\n });\n\n return { containerId: container.containerId, requestId: \"\" };\n },\n\n async get(containerId: string): Promise<ContainerGetResponse> {\n const exists = await platform.containerRepository.containerExists(containerId);\n return { containerId, exists, requestId: \"\" };\n },\n\n async list(): Promise<ContainerListResponse> {\n const containers = await platform.containerRepository.findAllContainers();\n return { containerIds: containers.map((c) => c.containerId), requestId: \"\" };\n },\n };\n}\n\n/**\n * Create remote container namespace backed by RPC client\n */\nexport function createRemoteContainers(rpcClient: RpcClient): ContainerNamespace {\n return {\n async create(containerId: string): Promise<ContainerCreateResponse> {\n const result = await rpcClient.call<ContainerCreateResponse>(\"container.create\", {\n containerId,\n });\n return { ...result, requestId: \"\" };\n },\n\n async get(containerId: string): Promise<ContainerGetResponse> {\n const result = await rpcClient.call<ContainerGetResponse>(\"container.get\", {\n containerId,\n });\n return { ...result, requestId: \"\" };\n },\n\n async list(): Promise<ContainerListResponse> {\n const result = await rpcClient.call<ContainerListResponse>(\"container.list\", {});\n return { ...result, requestId: \"\" };\n },\n };\n}\n","/**\n * Image namespace factories\n */\n\nimport type { AgentXPlatform } from \"@agentxjs/core/runtime\";\nimport type { RpcClient } from \"@agentxjs/core/network\";\nimport type {\n ImageNamespace,\n ImageCreateResponse,\n ImageGetResponse,\n ImageListResponse,\n ImageUpdateResponse,\n BaseResponse,\n} from \"../types\";\n\n/**\n * Create local image namespace backed by embedded runtime\n */\nexport function createLocalImages(platform: AgentXPlatform): ImageNamespace {\n return {\n async create(params: {\n containerId: string;\n name?: string;\n description?: string;\n systemPrompt?: string;\n mcpServers?: Record<string, unknown>;\n customData?: Record<string, unknown>;\n }): Promise<ImageCreateResponse> {\n const { imageRepository, sessionRepository } = platform;\n const { createImage } = await import(\"@agentxjs/core/image\");\n\n const image = await createImage(\n {\n containerId: params.containerId,\n name: params.name,\n description: params.description,\n systemPrompt: params.systemPrompt,\n mcpServers: params.mcpServers as any,\n customData: params.customData,\n },\n { imageRepository, sessionRepository }\n );\n\n return {\n record: image.toRecord(),\n __subscriptions: [image.sessionId],\n requestId: \"\",\n };\n },\n\n async get(imageId: string): Promise<ImageGetResponse> {\n const record = await platform.imageRepository.findImageById(imageId);\n return {\n record,\n __subscriptions: record?.sessionId ? [record.sessionId] : undefined,\n requestId: \"\",\n };\n },\n\n async list(containerId?: string): Promise<ImageListResponse> {\n const records = containerId\n ? await platform.imageRepository.findImagesByContainerId(containerId)\n : await platform.imageRepository.findAllImages();\n\n return {\n records,\n __subscriptions: records.map((r) => r.sessionId),\n requestId: \"\",\n };\n },\n\n async update(\n imageId: string,\n updates: {\n name?: string;\n description?: string;\n customData?: Record<string, unknown>;\n }\n ): Promise<ImageUpdateResponse> {\n const { loadImage } = await import(\"@agentxjs/core/image\");\n const { imageRepository, sessionRepository } = platform;\n\n const image = await loadImage(imageId, { imageRepository, sessionRepository });\n if (!image) {\n throw new Error(`Image not found: ${imageId}`);\n }\n\n const updated = await image.update(updates);\n return { record: updated.toRecord(), requestId: \"\" };\n },\n\n async delete(imageId: string): Promise<BaseResponse> {\n const { loadImage } = await import(\"@agentxjs/core/image\");\n const { imageRepository, sessionRepository } = platform;\n\n const image = await loadImage(imageId, { imageRepository, sessionRepository });\n if (image) {\n await image.delete();\n }\n\n return { requestId: \"\" };\n },\n };\n}\n\n/**\n * Create remote image namespace backed by RPC client\n */\nexport function createRemoteImages(\n rpcClient: RpcClient,\n subscribeFn: (sessionId: string) => void\n): ImageNamespace {\n return {\n async create(params: {\n containerId: string;\n name?: string;\n description?: string;\n systemPrompt?: string;\n mcpServers?: Record<string, unknown>;\n customData?: Record<string, unknown>;\n }): Promise<ImageCreateResponse> {\n const result = await rpcClient.call<ImageCreateResponse>(\"image.create\", params);\n\n // Auto subscribe to session events\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n subscribeFn(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n },\n\n async get(imageId: string): Promise<ImageGetResponse> {\n const result = await rpcClient.call<ImageGetResponse>(\"image.get\", { imageId });\n\n // Auto subscribe\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n subscribeFn(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n },\n\n async list(containerId?: string): Promise<ImageListResponse> {\n const result = await rpcClient.call<ImageListResponse>(\"image.list\", { containerId });\n\n // Auto subscribe\n if (result.__subscriptions) {\n for (const sessionId of result.__subscriptions) {\n subscribeFn(sessionId);\n }\n }\n\n return { ...result, requestId: \"\" };\n },\n\n async update(\n imageId: string,\n updates: {\n name?: string;\n description?: string;\n customData?: Record<string, unknown>;\n }\n ): Promise<ImageUpdateResponse> {\n const result = await rpcClient.call<ImageUpdateResponse>(\"image.update\", {\n imageId,\n updates,\n });\n return { ...result, requestId: \"\" };\n },\n\n async delete(imageId: string): Promise<BaseResponse> {\n const result = await rpcClient.call<BaseResponse>(\"image.delete\", { imageId });\n return { ...result, requestId: \"\" };\n },\n };\n}\n","/**\n * Agent namespace factories\n */\n\nimport type { AgentXRuntime } from \"@agentxjs/core/runtime\";\nimport type { RpcClient, RpcMethod } from \"@agentxjs/core/network\";\nimport type {\n AgentNamespace,\n AgentCreateResponse,\n AgentGetResponse,\n AgentListResponse,\n BaseResponse,\n} from \"../types\";\n\n/**\n * Create local agent namespace backed by embedded runtime\n */\nexport function createLocalAgents(runtime: AgentXRuntime): AgentNamespace {\n return {\n async create(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {\n // Reuse existing running agent for this image\n const existingAgent = runtime\n .getAgents()\n .find((a) => a.imageId === params.imageId && a.lifecycle === \"running\");\n\n if (existingAgent) {\n return {\n agentId: existingAgent.agentId,\n imageId: existingAgent.imageId,\n containerId: existingAgent.containerId,\n sessionId: existingAgent.sessionId,\n requestId: \"\",\n };\n }\n\n const agent = await runtime.createAgent({\n imageId: params.imageId,\n agentId: params.agentId,\n });\n\n return {\n agentId: agent.agentId,\n imageId: agent.imageId,\n containerId: agent.containerId,\n sessionId: agent.sessionId,\n requestId: \"\",\n };\n },\n\n async get(agentId: string): Promise<AgentGetResponse> {\n const agent = runtime.getAgent(agentId);\n return {\n agent: agent\n ? {\n agentId: agent.agentId,\n imageId: agent.imageId,\n containerId: agent.containerId,\n sessionId: agent.sessionId,\n lifecycle: agent.lifecycle,\n }\n : null,\n exists: !!agent,\n requestId: \"\",\n };\n },\n\n async list(containerId?: string): Promise<AgentListResponse> {\n const agents = containerId ? runtime.getAgentsByContainer(containerId) : runtime.getAgents();\n\n return {\n agents: agents.map((a) => ({\n agentId: a.agentId,\n imageId: a.imageId,\n containerId: a.containerId,\n sessionId: a.sessionId,\n lifecycle: a.lifecycle,\n })),\n requestId: \"\",\n };\n },\n\n async destroy(agentId: string): Promise<BaseResponse> {\n const agent = runtime.getAgent(agentId);\n if (agent) {\n await runtime.destroyAgent(agentId);\n }\n return { requestId: \"\" };\n },\n };\n}\n\n/**\n * Create remote agent namespace backed by RPC client\n */\nexport function createRemoteAgents(rpcClient: RpcClient): AgentNamespace {\n return {\n async create(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {\n // Agent creation via image.run RPC\n const result = await rpcClient.call<AgentCreateResponse>(\"image.run\" as RpcMethod, {\n imageId: params.imageId,\n agentId: params.agentId,\n });\n return { ...result, requestId: \"\" };\n },\n\n async get(agentId: string): Promise<AgentGetResponse> {\n const result = await rpcClient.call<AgentGetResponse>(\"agent.get\", { agentId });\n return { ...result, requestId: \"\" };\n },\n\n async list(containerId?: string): Promise<AgentListResponse> {\n const result = await rpcClient.call<AgentListResponse>(\"agent.list\", { containerId });\n return { ...result, requestId: \"\" };\n },\n\n async destroy(agentId: string): Promise<BaseResponse> {\n const result = await rpcClient.call<BaseResponse>(\"agent.destroy\", { agentId });\n return { ...result, requestId: \"\" };\n },\n };\n}\n","/**\n * Session namespace factories (messaging)\n */\n\nimport type { AgentXRuntime } from \"@agentxjs/core/runtime\";\nimport type { UserContentPart, Message } from \"@agentxjs/core/agent\";\nimport type { RpcClient } from \"@agentxjs/core/network\";\nimport type { SessionNamespace, MessageSendResponse, BaseResponse, AgentInfo } from \"../types\";\n\n/**\n * Create local session namespace backed by embedded runtime\n */\nexport function createLocalSessions(runtime: AgentXRuntime): SessionNamespace {\n return {\n async send(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {\n await runtime.receive(agentId, content as string | UserContentPart[]);\n return { agentId, requestId: \"\" };\n },\n\n async interrupt(agentId: string): Promise<BaseResponse> {\n runtime.interrupt(agentId);\n return { requestId: \"\" };\n },\n\n async getMessages(agentId: string): Promise<Message[]> {\n const agent = runtime.getAgent(agentId);\n if (!agent) return [];\n return runtime.platform.sessionRepository.getMessages(agent.sessionId);\n },\n };\n}\n\n/**\n * Create remote session namespace backed by RPC client\n */\nexport function createRemoteSessions(rpcClient: RpcClient): SessionNamespace {\n return {\n async send(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {\n const result = await rpcClient.call<MessageSendResponse>(\"message.send\", {\n agentId,\n content,\n });\n return { ...result, requestId: \"\" };\n },\n\n async interrupt(agentId: string): Promise<BaseResponse> {\n const result = await rpcClient.call<BaseResponse>(\"agent.interrupt\", { agentId });\n return { ...result, requestId: \"\" };\n },\n\n async getMessages(agentId: string): Promise<Message[]> {\n const agentRes = await rpcClient.call<{ agent: AgentInfo | null }>(\"agent.get\", { agentId });\n if (!agentRes.agent) return [];\n const msgRes = await rpcClient.call<{ messages: Message[] }>(\"image.messages\", {\n imageId: agentRes.agent.imageId,\n });\n return msgRes.messages ?? [];\n },\n };\n}\n","/**\n * Presentation Types\n *\n * UI-friendly data model aggregated from stream events.\n * This implements the Presentation Model pattern.\n */\n\n// ============================================================================\n// Block Types - Basic content units\n// ============================================================================\n\n/**\n * Text block\n */\nexport interface TextBlock {\n type: \"text\";\n content: string;\n}\n\n/**\n * Tool block - represents a tool call and its result\n */\nexport interface ToolBlock {\n type: \"tool\";\n toolUseId: string;\n toolName: string;\n toolInput: Record<string, unknown>;\n toolResult?: string;\n status: \"pending\" | \"running\" | \"completed\" | \"error\";\n}\n\n/**\n * Image block\n */\nexport interface ImageBlock {\n type: \"image\";\n url: string;\n alt?: string;\n}\n\n/**\n * All block types\n */\nexport type Block = TextBlock | ToolBlock | ImageBlock;\n\n// ============================================================================\n// Conversation Types - A single turn in the conversation\n// ============================================================================\n\n/**\n * User conversation\n */\nexport interface UserConversation {\n role: \"user\";\n blocks: Block[];\n}\n\n/**\n * Token usage for a message (one LLM call / step)\n */\nexport interface TokenUsage {\n inputTokens: number;\n outputTokens: number;\n}\n\n/**\n * Assistant conversation\n */\nexport interface AssistantConversation {\n role: \"assistant\";\n blocks: Block[];\n isStreaming: boolean;\n /** Accumulated token usage across all steps in this conversation */\n usage?: TokenUsage;\n}\n\n/**\n * Error conversation\n */\nexport interface ErrorConversation {\n role: \"error\";\n message: string;\n}\n\n/**\n * All conversation types\n */\nexport type Conversation = UserConversation | AssistantConversation | ErrorConversation;\n\n// ============================================================================\n// Presentation State\n// ============================================================================\n\n/**\n * Presentation state - the complete UI state\n */\nexport interface PresentationState {\n /**\n * All completed conversations\n */\n conversations: Conversation[];\n\n /**\n * Current streaming conversation (null if not streaming)\n */\n streaming: AssistantConversation | null;\n\n /**\n * Current status\n */\n status: \"idle\" | \"thinking\" | \"responding\" | \"executing\";\n}\n\n/**\n * Initial presentation state\n */\nexport const initialPresentationState: PresentationState = {\n conversations: [],\n streaming: null,\n status: \"idle\",\n};\n","/**\n * Presentation Reducer\n *\n * Aggregates events into PresentationState.\n * Pure function: (state, event) => newState\n *\n * Event consumption strategy:\n * - Stream layer: message_start, text_delta, tool_use_start, tool_use_stop, message_stop\n * (for real-time streaming display)\n * - Message layer: tool_result_message\n * (for tool execution results — arrives after message_stop)\n *\n * Tool calls are stream-level blocks within the assistant turn,\n * matching the mainstream API pattern (Anthropic, OpenAI).\n */\n\nimport type { BusEvent } from \"@agentxjs/core/event\";\nimport type {\n Message,\n UserMessage,\n AssistantMessage,\n ToolResultMessage,\n ErrorMessage,\n ToolResultOutput,\n ToolCallPart,\n} from \"@agentxjs/core/agent\";\nimport type {\n PresentationState,\n Conversation,\n AssistantConversation,\n TextBlock,\n ToolBlock,\n Block,\n TokenUsage,\n} from \"./types\";\nimport { initialPresentationState } from \"./types\";\n\n// ============================================================================\n// Event Data Types\n// ============================================================================\n\ninterface MessageStartData {\n messageId?: string;\n model?: string;\n}\n\ninterface TextDeltaData {\n text: string;\n}\n\ninterface ToolUseStartData {\n toolCallId: string;\n toolName: string;\n}\n\ninterface ToolUseStopData {\n toolCallId: string;\n toolName: string;\n input: Record<string, unknown>;\n}\n\ninterface MessageDeltaData {\n usage?: {\n inputTokens: number;\n outputTokens: number;\n };\n}\n\ninterface MessageStopData {\n stopReason?: string;\n}\n\ninterface ErrorData {\n message: string;\n code?: string;\n}\n\n// ============================================================================\n// Reducer\n// ============================================================================\n\n/**\n * Reduce an event into presentation state.\n *\n * Consumes:\n * - Stream events: message_start, text_delta, tool_use_start, tool_use_stop, message_stop\n * - Message events: tool_result_message\n * - Error events: error\n */\nexport function presentationReducer(state: PresentationState, event: BusEvent): PresentationState {\n switch (event.type) {\n // Stream layer — real-time display\n case \"message_start\":\n return handleMessageStart(state, event.data as MessageStartData);\n\n case \"text_delta\":\n return handleTextDelta(state, event.data as TextDeltaData);\n\n case \"tool_use_start\":\n return handleToolUseStart(state, event.data as ToolUseStartData);\n\n case \"tool_use_stop\":\n return handleToolUseStop(state, event.data as ToolUseStopData);\n\n case \"message_delta\":\n return handleMessageDelta(state, event.data as MessageDeltaData);\n\n case \"message_stop\":\n return handleMessageStop(state, event.data as MessageStopData);\n\n // Message layer — tool results from Engine\n case \"tool_result_message\":\n return handleToolResultMessage(state, event.data as ToolResultMessage);\n\n case \"error\":\n return handleError(state, event.data as ErrorData);\n\n default:\n return state;\n }\n}\n\n// ============================================================================\n// Handlers\n// ============================================================================\n\nfunction handleMessageStart(state: PresentationState, _data: MessageStartData): PresentationState {\n // If streaming already exists (e.g. tool_use turn not yet flushed), flush it first\n let conversations = state.conversations;\n if (state.streaming && state.streaming.blocks.length > 0) {\n conversations = [...conversations, { ...state.streaming, isStreaming: false }];\n }\n\n const streaming: AssistantConversation = {\n role: \"assistant\",\n blocks: [],\n isStreaming: true,\n };\n\n return {\n ...state,\n conversations,\n streaming,\n status: \"thinking\",\n };\n}\n\nfunction handleTextDelta(state: PresentationState, data: TextDeltaData): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const blocks = [...state.streaming.blocks];\n const lastBlock = blocks[blocks.length - 1];\n\n if (lastBlock && lastBlock.type === \"text\") {\n blocks[blocks.length - 1] = {\n ...lastBlock,\n content: lastBlock.content + data.text,\n };\n } else {\n blocks.push({\n type: \"text\",\n content: data.text,\n } as TextBlock);\n }\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n status: \"responding\",\n };\n}\n\nfunction handleToolUseStart(state: PresentationState, data: ToolUseStartData): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n // Create a pending tool block — toolInput will be filled by tool_use_stop\n const toolBlock: ToolBlock = {\n type: \"tool\",\n toolUseId: data.toolCallId,\n toolName: data.toolName,\n toolInput: {},\n status: \"pending\",\n };\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks: [...state.streaming.blocks, toolBlock],\n },\n status: \"executing\",\n };\n}\n\n/**\n * Handle tool_use_stop from stream layer.\n * Fills in the complete toolInput for the matching pending tool block.\n * The stream event carries the fully assembled input.\n */\nfunction handleToolUseStop(state: PresentationState, data: ToolUseStopData): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const blocks = state.streaming.blocks.map((block): Block => {\n if (block.type === \"tool\" && block.toolUseId === data.toolCallId) {\n return {\n ...block,\n toolInput: data.input,\n status: \"running\",\n };\n }\n return block;\n });\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n };\n}\n\nfunction handleMessageDelta(state: PresentationState, data: MessageDeltaData): PresentationState {\n if (!state.streaming || !data.usage) {\n return state;\n }\n\n const prev = state.streaming.usage;\n const usage: TokenUsage = {\n inputTokens: (prev?.inputTokens ?? 0) + data.usage.inputTokens,\n outputTokens: (prev?.outputTokens ?? 0) + data.usage.outputTokens,\n };\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n usage,\n },\n };\n}\n\nfunction handleMessageStop(state: PresentationState, data: MessageStopData): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n // tool_use stop → don't flush, tool results are still incoming\n if (data.stopReason === \"tool_use\") {\n return {\n ...state,\n status: \"executing\",\n };\n }\n\n // end_turn / max_tokens / etc → flush streaming to conversations\n const completedConversation: AssistantConversation = {\n ...state.streaming,\n isStreaming: false,\n };\n\n return {\n ...state,\n conversations: [...state.conversations, completedConversation],\n streaming: null,\n status: \"idle\",\n };\n}\n\n/**\n * Handle tool_result_message from Engine layer.\n * Fills in the toolResult for the matching tool block.\n *\n * Note: tool_result_message arrives after message_stop(tool_use),\n * but streaming is kept alive (not flushed) during tool_use turns.\n */\nfunction handleToolResultMessage(\n state: PresentationState,\n data: ToolResultMessage\n): PresentationState {\n if (!state.streaming) {\n return state;\n }\n\n const toolCallId = data.toolCallId;\n const blocks = state.streaming.blocks.map((block): Block => {\n if (block.type === \"tool\" && block.toolUseId === toolCallId) {\n return {\n ...block,\n toolResult: formatToolResultOutput(data.toolResult.output),\n status:\n data.toolResult.output.type === \"error-text\" ||\n data.toolResult.output.type === \"error-json\" ||\n data.toolResult.output.type === \"execution-denied\"\n ? \"error\"\n : \"completed\",\n };\n }\n return block;\n });\n\n return {\n ...state,\n streaming: {\n ...state.streaming,\n blocks,\n },\n status: \"responding\",\n };\n}\n\nfunction handleError(state: PresentationState, data: ErrorData): PresentationState {\n return {\n ...state,\n conversations: [\n ...state.conversations,\n {\n role: \"error\",\n message: data.message,\n },\n ],\n streaming: null,\n status: \"idle\",\n };\n}\n\n// ============================================================================\n// Helper: Add user conversation\n// ============================================================================\n\nexport function addUserConversation(state: PresentationState, content: string): PresentationState {\n return {\n ...state,\n conversations: [\n ...state.conversations,\n {\n role: \"user\",\n blocks: [{ type: \"text\", content }],\n },\n ],\n };\n}\n\nexport function createInitialState(): PresentationState {\n return { ...initialPresentationState };\n}\n\n// ============================================================================\n// Helper: Format tool result output\n// ============================================================================\n\nfunction formatToolResultOutput(output: ToolResultOutput): string {\n switch (output.type) {\n case \"text\":\n case \"error-text\":\n return output.value;\n case \"json\":\n case \"error-json\":\n return JSON.stringify(output.value);\n case \"execution-denied\":\n return output.reason ?? \"Execution denied\";\n case \"content\":\n return output.value\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\");\n }\n}\n\n// ============================================================================\n// Message → Conversation Converter\n// ============================================================================\n\n/**\n * Convert persisted Messages to Presentation Conversations.\n *\n * Groups consecutive assistant + tool-result messages\n * into a single AssistantConversation.\n *\n * Tool calls are now part of AssistantMessage.content (as ToolCallPart),\n * so we extract them directly from the assistant message.\n */\nexport function messagesToConversations(messages: Message[]): Conversation[] {\n const conversations: Conversation[] = [];\n let currentAssistant: AssistantConversation | null = null;\n\n function flushAssistant() {\n if (currentAssistant && currentAssistant.blocks.length > 0) {\n conversations.push(currentAssistant);\n }\n currentAssistant = null;\n }\n\n for (const msg of messages) {\n switch (msg.subtype) {\n case \"user\": {\n flushAssistant();\n const m = msg as UserMessage;\n const text =\n typeof m.content === \"string\"\n ? m.content\n : m.content\n .filter((p): p is { type: \"text\"; text: string } => p.type === \"text\")\n .map((p) => p.text)\n .join(\"\");\n conversations.push({\n role: \"user\",\n blocks: [{ type: \"text\", content: text }],\n });\n break;\n }\n\n case \"assistant\": {\n if (!currentAssistant) {\n currentAssistant = { role: \"assistant\", blocks: [], isStreaming: false };\n }\n const m = msg as AssistantMessage;\n if (typeof m.content === \"string\") {\n if (m.content) {\n currentAssistant.blocks.push({ type: \"text\", content: m.content } as TextBlock);\n }\n } else {\n // Extract text and tool call parts from content\n for (const part of m.content) {\n if (part.type === \"text\") {\n if (part.text) {\n currentAssistant.blocks.push({ type: \"text\", content: part.text } as TextBlock);\n }\n } else if (part.type === \"tool-call\") {\n const tc = part as ToolCallPart;\n currentAssistant.blocks.push({\n type: \"tool\",\n toolUseId: tc.id,\n toolName: tc.name,\n toolInput: tc.input,\n status: \"completed\",\n } as ToolBlock);\n }\n }\n }\n break;\n }\n\n case \"tool-result\": {\n const m = msg as ToolResultMessage;\n if (currentAssistant) {\n for (const block of currentAssistant.blocks) {\n if (block.type === \"tool\" && block.toolUseId === m.toolResult.id) {\n block.toolResult = formatToolResultOutput(m.toolResult.output);\n block.status =\n m.toolResult.output.type === \"error-text\" ||\n m.toolResult.output.type === \"error-json\" ||\n m.toolResult.output.type === \"execution-denied\"\n ? \"error\"\n : \"completed\";\n break;\n }\n }\n }\n break;\n }\n\n case \"error\": {\n flushAssistant();\n const m = msg as ErrorMessage;\n conversations.push({\n role: \"error\",\n message: m.content,\n });\n break;\n }\n }\n }\n\n flushAssistant();\n return conversations;\n}\n","/**\n * Presentation Class\n *\n * High-level API for UI integration.\n * Wraps AgentX client and provides presentation state management.\n */\n\nimport type { AgentX } from \"../types\";\nimport type { Unsubscribe, BusEvent } from \"@agentxjs/core/event\";\nimport type { PresentationState, Conversation } from \"./types\";\nimport { initialPresentationState } from \"./types\";\nimport { presentationReducer, addUserConversation, createInitialState } from \"./reducer\";\n\n/**\n * Presentation update handler\n */\nexport type PresentationUpdateHandler = (state: PresentationState) => void;\n\n/**\n * Presentation error handler\n */\nexport type PresentationErrorHandler = (error: Error) => void;\n\n/**\n * Presentation options\n */\nexport interface PresentationOptions {\n /**\n * Called on every state update\n */\n onUpdate?: PresentationUpdateHandler;\n\n /**\n * Called on errors\n */\n onError?: PresentationErrorHandler;\n}\n\n/**\n * Presentation - UI-friendly wrapper for AgentX\n */\nexport class Presentation {\n private agentx: AgentX;\n private agentId: string;\n private state: PresentationState;\n private updateHandlers: Set<PresentationUpdateHandler> = new Set();\n private errorHandlers: Set<PresentationErrorHandler> = new Set();\n private eventUnsubscribe: Unsubscribe | null = null;\n\n constructor(\n agentx: AgentX,\n agentId: string,\n options?: PresentationOptions,\n initialConversations?: Conversation[]\n ) {\n this.agentx = agentx;\n this.agentId = agentId;\n this.state = initialConversations?.length\n ? { ...initialPresentationState, conversations: initialConversations }\n : createInitialState();\n\n // Register initial handlers\n if (options?.onUpdate) {\n this.updateHandlers.add(options.onUpdate);\n }\n if (options?.onError) {\n this.errorHandlers.add(options.onError);\n }\n\n // Subscribe to all events\n this.subscribeToEvents();\n }\n\n /**\n * Get current state\n */\n getState(): PresentationState {\n return this.state;\n }\n\n /**\n * Subscribe to state updates\n */\n onUpdate(handler: PresentationUpdateHandler): Unsubscribe {\n this.updateHandlers.add(handler);\n // Immediately call with current state\n handler(this.state);\n return () => {\n this.updateHandlers.delete(handler);\n };\n }\n\n /**\n * Subscribe to errors\n */\n onError(handler: PresentationErrorHandler): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n /**\n * Send a message\n */\n async send(content: string): Promise<void> {\n // Add user conversation\n this.state = addUserConversation(this.state, content);\n this.notify();\n\n try {\n // Send message via agentx\n await this.agentx.sessions.send(this.agentId, content);\n } catch (error) {\n this.notifyError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Interrupt current response\n */\n async interrupt(): Promise<void> {\n try {\n await this.agentx.sessions.interrupt(this.agentId);\n } catch (error) {\n this.notifyError(error instanceof Error ? error : new Error(String(error)));\n }\n }\n\n /**\n * Reset state\n */\n reset(): void {\n this.state = createInitialState();\n this.notify();\n }\n\n /**\n * Dispose and cleanup\n */\n dispose(): void {\n if (this.eventUnsubscribe) {\n this.eventUnsubscribe();\n this.eventUnsubscribe = null;\n }\n this.updateHandlers.clear();\n this.errorHandlers.clear();\n }\n\n // ==================== Private ====================\n\n private subscribeToEvents(): void {\n // Subscribe to all events and filter by agentId\n this.eventUnsubscribe = this.agentx.onAny((event: BusEvent) => {\n // Filter events for this agent (if context is available)\n // Note: Events from server may or may not include context with agentId\n const eventWithContext = event as BusEvent & { context?: { agentId?: string } };\n const eventAgentId = eventWithContext.context?.agentId;\n\n // Only filter if event has agentId and it doesn't match\n if (eventAgentId && eventAgentId !== this.agentId) {\n return;\n }\n\n // Reduce event into state\n const newState = presentationReducer(this.state, event);\n if (newState !== this.state) {\n this.state = newState;\n this.notify();\n }\n });\n }\n\n private notify(): void {\n for (const handler of this.updateHandlers) {\n try {\n handler(this.state);\n } catch (error) {\n console.error(\"Presentation update handler error:\", error);\n }\n }\n }\n\n private notifyError(error: Error): void {\n for (const handler of this.errorHandlers) {\n try {\n handler(error);\n } catch (e) {\n console.error(\"Presentation error handler error:\", e);\n }\n }\n }\n}\n","/**\n * Presentation namespace factory\n *\n * Single factory for both local and remote modes —\n * Presentation only depends on the AgentX interface.\n */\n\nimport type { AgentX, PresentationNamespace } from \"../types\";\nimport { Presentation, type PresentationOptions, messagesToConversations } from \"../presentation\";\n\n/**\n * Create presentation namespace backed by any AgentX client\n */\nexport function createPresentations(agentx: AgentX): PresentationNamespace {\n return {\n async create(agentId: string, options?: PresentationOptions): Promise<Presentation> {\n const messages = await agentx.sessions.getMessages(agentId);\n const conversations = messagesToConversations(messages);\n return new Presentation(agentx, agentId, options, conversations);\n },\n };\n}\n","/**\n * LocalClient - AgentX client for local mode\n *\n * Runs an embedded Runtime + Driver directly, without WebSocket.\n * Implements the same AgentX interface as RemoteClient.\n */\n\nimport type { BusEvent, EventBus, BusEventHandler, Unsubscribe } from \"@agentxjs/core/event\";\nimport type { AgentXRuntime } from \"@agentxjs/core/runtime\";\nimport { createLogger } from \"commonxjs/logger\";\nimport type {\n AgentX,\n ContainerNamespace,\n ImageNamespace,\n AgentNamespace,\n SessionNamespace,\n PresentationNamespace,\n} from \"./types\";\nimport { createLocalContainers } from \"./namespaces/containers\";\nimport { createLocalImages } from \"./namespaces/images\";\nimport { createLocalAgents } from \"./namespaces/agents\";\nimport { createLocalSessions } from \"./namespaces/sessions\";\nimport { createPresentations } from \"./namespaces/presentations\";\n\nconst logger = createLogger(\"agentx/LocalClient\");\n\n/**\n * LocalClient - Embedded runtime implementation\n */\nexport class LocalClient implements AgentX {\n private readonly runtime: AgentXRuntime;\n private isDisposed = false;\n\n readonly containers: ContainerNamespace;\n readonly images: ImageNamespace;\n readonly agents: AgentNamespace;\n readonly sessions: SessionNamespace;\n readonly presentations: PresentationNamespace;\n\n constructor(runtime: AgentXRuntime) {\n this.runtime = runtime;\n const platform = runtime.platform;\n\n this.containers = createLocalContainers(platform);\n this.images = createLocalImages(platform);\n this.agents = createLocalAgents(runtime);\n this.sessions = createLocalSessions(runtime);\n this.presentations = createPresentations(this);\n\n logger.info(\"LocalClient initialized\");\n }\n\n // ==================== Properties ====================\n\n get connected(): boolean {\n return !this.isDisposed;\n }\n\n get events(): EventBus {\n return this.runtime.platform.eventBus;\n }\n\n // ==================== Event Subscription ====================\n\n on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {\n return this.runtime.platform.eventBus.on(type, handler);\n }\n\n onAny(handler: BusEventHandler): Unsubscribe {\n return this.runtime.platform.eventBus.onAny(handler);\n }\n\n subscribe(_sessionId: string): void {\n // No-op for local mode - already subscribed via eventBus\n }\n\n // ==================== Lifecycle ====================\n\n async disconnect(): Promise<void> {\n // No-op for local mode\n }\n\n async dispose(): Promise<void> {\n if (this.isDisposed) return;\n await this.runtime.shutdown();\n this.isDisposed = true;\n logger.info(\"LocalClient disposed\");\n }\n}\n","/**\n * agentxjs - AgentX Client SDK\n *\n * Unified entry point supporting local and remote modes.\n *\n * @example Local mode (embedded runtime)\n * ```typescript\n * import { createAgentX } from \"agentxjs\";\n *\n * const agentx = await createAgentX({\n * apiKey: process.env.ANTHROPIC_API_KEY,\n * provider: \"anthropic\",\n * });\n *\n * await agentx.containers.create(\"my-app\");\n * const { record: image } = await agentx.images.create({\n * containerId: \"my-app\",\n * systemPrompt: \"You are helpful\",\n * });\n * const { agentId } = await agentx.agents.create({ imageId: image.imageId });\n *\n * agentx.on(\"text_delta\", (e) => process.stdout.write(e.data.text));\n * await agentx.sessions.send(agentId, \"Hello!\");\n * ```\n *\n * @example Remote mode (WebSocket client)\n * ```typescript\n * import { createAgentX } from \"agentxjs\";\n *\n * const agentx = await createAgentX({\n * serverUrl: \"ws://localhost:5200\",\n * });\n * ```\n */\n\nimport { RemoteClient } from \"./RemoteClient\";\nimport { LocalClient } from \"./LocalClient\";\nimport type { AgentX, AgentXConfig } from \"./types\";\n\n/**\n * Create an AgentX client\n *\n * Mode detection:\n * - `serverUrl` present → **Remote mode** (WebSocket client)\n * - `apiKey` present → **Local mode** (embedded Runtime + MonoDriver)\n *\n * @param config - Client configuration\n * @returns Connected AgentX client\n */\nexport async function createAgentX(config: AgentXConfig): Promise<AgentX> {\n if (config.serverUrl) {\n // Remote mode — resolve platform for WebSocket factory if needed\n const resolvedConfig = await resolvePlatformForRemote(config);\n const client = new RemoteClient(resolvedConfig);\n await client.connect();\n return client;\n }\n\n if (config.apiKey || config.createDriver || config.customPlatform) {\n // Local mode\n return createLocalClient(config);\n }\n\n throw new Error(\n \"Invalid AgentX config: provide either 'serverUrl' (remote mode) or 'apiKey' (local mode)\"\n );\n}\n\n/**\n * Resolve platform for remote mode\n *\n * In Node.js: auto-import node-platform to get webSocketFactory\n * In browser: no platform needed (native WebSocket is the default)\n */\nasync function resolvePlatformForRemote(config: AgentXConfig): Promise<AgentXConfig> {\n if (config.customPlatform?.webSocketFactory) {\n return config;\n }\n\n // In browser, native WebSocket works — no platform needed\n if (typeof globalThis !== \"undefined\" && (globalThis as any).window?.document !== undefined) {\n return config;\n }\n\n // Node.js — auto-resolve webSocketFactory from node-platform\n try {\n const { createNodeWebSocket } = await import(\"@agentxjs/node-platform/network\");\n return {\n ...config,\n customPlatform: {\n ...config.customPlatform,\n webSocketFactory: createNodeWebSocket,\n } as any,\n };\n } catch {\n // node-platform not available, fall back to global WebSocket\n return config;\n }\n}\n\n/**\n * Create a local client with embedded runtime\n */\nasync function createLocalClient(config: AgentXConfig): Promise<AgentX> {\n const { createAgentXRuntime } = await import(\"@agentxjs/core/runtime\");\n\n // Resolve platform\n let platform;\n if (config.customPlatform) {\n platform = config.customPlatform;\n } else {\n const { createNodePlatform } = await import(\"@agentxjs/node-platform\");\n platform = await createNodePlatform({\n dataPath: config.dataPath ?? \":memory:\",\n logLevel: config.logLevel ?? (config.debug ? \"debug\" : undefined),\n });\n }\n\n // Resolve createDriver\n let createDriver = config.createDriver;\n if (!createDriver) {\n const { createMonoDriver } = await import(\"@agentxjs/mono-driver\");\n createDriver = (driverConfig: import(\"@agentxjs/core/driver\").DriverConfig) => {\n const existingOptions = (driverConfig as any).options ?? {};\n return createMonoDriver({\n ...driverConfig,\n apiKey: config.apiKey ?? driverConfig.apiKey,\n baseUrl: config.baseUrl ?? driverConfig.baseUrl,\n model: config.model ?? driverConfig.model,\n options: {\n ...existingOptions,\n provider: config.provider ?? existingOptions.provider ?? \"anthropic\",\n },\n });\n };\n }\n\n // Create runtime\n const runtime = createAgentXRuntime(platform, createDriver);\n\n return new LocalClient(runtime);\n}\n\n// Re-export types\nexport type {\n AgentX,\n AgentXConfig,\n LLMProvider,\n MaybeAsync,\n AgentInfo,\n ImageRecord,\n ContainerInfo,\n ContainerNamespace,\n ImageNamespace,\n AgentNamespace,\n SessionNamespace,\n PresentationNamespace,\n AgentCreateResponse,\n AgentGetResponse,\n AgentListResponse,\n ImageCreateResponse,\n ImageGetResponse,\n ImageListResponse,\n ContainerCreateResponse,\n ContainerGetResponse,\n ContainerListResponse,\n MessageSendResponse,\n BaseResponse,\n} from \"./types\";\n\n// Re-export Presentation types and classes\nexport type {\n Block,\n TextBlock,\n ToolBlock,\n ImageBlock,\n Conversation,\n UserConversation,\n AssistantConversation,\n ErrorConversation,\n PresentationState,\n PresentationOptions,\n PresentationUpdateHandler,\n PresentationErrorHandler,\n} from \"./presentation\";\n\nexport {\n Presentation,\n presentationReducer,\n addUserConversation,\n createInitialState,\n initialPresentationState,\n messagesToConversations,\n} from \"./presentation\";\n"],"mappings":";AAQA,SAAS,oBAAoB;AAC7B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;;;ACMtB,SAAS,sBAAsB,UAA8C;AAClF,SAAO;AAAA,IACL,MAAM,OAAO,aAAuD;AAClE,YAAM,EAAE,qBAAqB,IAAI,MAAM,OAAO,0BAA0B;AACxE,YAAM,EAAE,qBAAqB,iBAAiB,kBAAkB,IAAI;AAEpE,YAAM,YAAY,MAAM,qBAAqB,aAAa;AAAA,QACxD;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAED,aAAO,EAAE,aAAa,UAAU,aAAa,WAAW,GAAG;AAAA,IAC7D;AAAA,IAEA,MAAM,IAAI,aAAoD;AAC5D,YAAM,SAAS,MAAM,SAAS,oBAAoB,gBAAgB,WAAW;AAC7E,aAAO,EAAE,aAAa,QAAQ,WAAW,GAAG;AAAA,IAC9C;AAAA,IAEA,MAAM,OAAuC;AAC3C,YAAM,aAAa,MAAM,SAAS,oBAAoB,kBAAkB;AACxE,aAAO,EAAE,cAAc,WAAW,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG;AAAA,IAC7E;AAAA,EACF;AACF;AAKO,SAAS,uBAAuB,WAA0C;AAC/E,SAAO;AAAA,IACL,MAAM,OAAO,aAAuD;AAClE,YAAM,SAAS,MAAM,UAAU,KAA8B,oBAAoB;AAAA,QAC/E;AAAA,MACF,CAAC;AACD,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,IAAI,aAAoD;AAC5D,YAAM,SAAS,MAAM,UAAU,KAA2B,iBAAiB;AAAA,QACzE;AAAA,MACF,CAAC;AACD,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,OAAuC;AAC3C,YAAM,SAAS,MAAM,UAAU,KAA4B,kBAAkB,CAAC,CAAC;AAC/E,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;ACjDO,SAAS,kBAAkB,UAA0C;AAC1E,SAAO;AAAA,IACL,MAAM,OAAO,QAOoB;AAC/B,YAAM,EAAE,iBAAiB,kBAAkB,IAAI;AAC/C,YAAM,EAAE,YAAY,IAAI,MAAM,OAAO,sBAAsB;AAE3D,YAAM,QAAQ,MAAM;AAAA,QAClB;AAAA,UACE,aAAa,OAAO;AAAA,UACpB,MAAM,OAAO;AAAA,UACb,aAAa,OAAO;AAAA,UACpB,cAAc,OAAO;AAAA,UACrB,YAAY,OAAO;AAAA,UACnB,YAAY,OAAO;AAAA,QACrB;AAAA,QACA,EAAE,iBAAiB,kBAAkB;AAAA,MACvC;AAEA,aAAO;AAAA,QACL,QAAQ,MAAM,SAAS;AAAA,QACvB,iBAAiB,CAAC,MAAM,SAAS;AAAA,QACjC,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,IAAI,SAA4C;AACpD,YAAM,SAAS,MAAM,SAAS,gBAAgB,cAAc,OAAO;AACnE,aAAO;AAAA,QACL;AAAA,QACA,iBAAiB,QAAQ,YAAY,CAAC,OAAO,SAAS,IAAI;AAAA,QAC1D,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,aAAkD;AAC3D,YAAM,UAAU,cACZ,MAAM,SAAS,gBAAgB,wBAAwB,WAAW,IAClE,MAAM,SAAS,gBAAgB,cAAc;AAEjD,aAAO;AAAA,QACL;AAAA,QACA,iBAAiB,QAAQ,IAAI,CAAC,MAAM,EAAE,SAAS;AAAA,QAC/C,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,OACJ,SACA,SAK8B;AAC9B,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,YAAM,EAAE,iBAAiB,kBAAkB,IAAI;AAE/C,YAAM,QAAQ,MAAM,UAAU,SAAS,EAAE,iBAAiB,kBAAkB,CAAC;AAC7E,UAAI,CAAC,OAAO;AACV,cAAM,IAAI,MAAM,oBAAoB,OAAO,EAAE;AAAA,MAC/C;AAEA,YAAM,UAAU,MAAM,MAAM,OAAO,OAAO;AAC1C,aAAO,EAAE,QAAQ,QAAQ,SAAS,GAAG,WAAW,GAAG;AAAA,IACrD;AAAA,IAEA,MAAM,OAAO,SAAwC;AACnD,YAAM,EAAE,UAAU,IAAI,MAAM,OAAO,sBAAsB;AACzD,YAAM,EAAE,iBAAiB,kBAAkB,IAAI;AAE/C,YAAM,QAAQ,MAAM,UAAU,SAAS,EAAE,iBAAiB,kBAAkB,CAAC;AAC7E,UAAI,OAAO;AACT,cAAM,MAAM,OAAO;AAAA,MACrB;AAEA,aAAO,EAAE,WAAW,GAAG;AAAA,IACzB;AAAA,EACF;AACF;AAKO,SAAS,mBACd,WACA,aACgB;AAChB,SAAO;AAAA,IACL,MAAM,OAAO,QAOoB;AAC/B,YAAM,SAAS,MAAM,UAAU,KAA0B,gBAAgB,MAAM;AAG/E,UAAI,OAAO,iBAAiB;AAC1B,mBAAW,aAAa,OAAO,iBAAiB;AAC9C,sBAAY,SAAS;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,IAAI,SAA4C;AACpD,YAAM,SAAS,MAAM,UAAU,KAAuB,aAAa,EAAE,QAAQ,CAAC;AAG9E,UAAI,OAAO,iBAAiB;AAC1B,mBAAW,aAAa,OAAO,iBAAiB;AAC9C,sBAAY,SAAS;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,KAAK,aAAkD;AAC3D,YAAM,SAAS,MAAM,UAAU,KAAwB,cAAc,EAAE,YAAY,CAAC;AAGpF,UAAI,OAAO,iBAAiB;AAC1B,mBAAW,aAAa,OAAO,iBAAiB;AAC9C,sBAAY,SAAS;AAAA,QACvB;AAAA,MACF;AAEA,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,OACJ,SACA,SAK8B;AAC9B,YAAM,SAAS,MAAM,UAAU,KAA0B,gBAAgB;AAAA,QACvE;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,OAAO,SAAwC;AACnD,YAAM,SAAS,MAAM,UAAU,KAAmB,gBAAgB,EAAE,QAAQ,CAAC;AAC7E,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;AClKO,SAAS,kBAAkB,SAAwC;AACxE,SAAO;AAAA,IACL,MAAM,OAAO,QAA6E;AAExF,YAAM,gBAAgB,QACnB,UAAU,EACV,KAAK,CAAC,MAAM,EAAE,YAAY,OAAO,WAAW,EAAE,cAAc,SAAS;AAExE,UAAI,eAAe;AACjB,eAAO;AAAA,UACL,SAAS,cAAc;AAAA,UACvB,SAAS,cAAc;AAAA,UACvB,aAAa,cAAc;AAAA,UAC3B,WAAW,cAAc;AAAA,UACzB,WAAW;AAAA,QACb;AAAA,MACF;AAEA,YAAM,QAAQ,MAAM,QAAQ,YAAY;AAAA,QACtC,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,MAClB,CAAC;AAED,aAAO;AAAA,QACL,SAAS,MAAM;AAAA,QACf,SAAS,MAAM;AAAA,QACf,aAAa,MAAM;AAAA,QACnB,WAAW,MAAM;AAAA,QACjB,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,IAAI,SAA4C;AACpD,YAAM,QAAQ,QAAQ,SAAS,OAAO;AACtC,aAAO;AAAA,QACL,OAAO,QACH;AAAA,UACE,SAAS,MAAM;AAAA,UACf,SAAS,MAAM;AAAA,UACf,aAAa,MAAM;AAAA,UACnB,WAAW,MAAM;AAAA,UACjB,WAAW,MAAM;AAAA,QACnB,IACA;AAAA,QACJ,QAAQ,CAAC,CAAC;AAAA,QACV,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,KAAK,aAAkD;AAC3D,YAAM,SAAS,cAAc,QAAQ,qBAAqB,WAAW,IAAI,QAAQ,UAAU;AAE3F,aAAO;AAAA,QACL,QAAQ,OAAO,IAAI,CAAC,OAAO;AAAA,UACzB,SAAS,EAAE;AAAA,UACX,SAAS,EAAE;AAAA,UACX,aAAa,EAAE;AAAA,UACf,WAAW,EAAE;AAAA,UACb,WAAW,EAAE;AAAA,QACf,EAAE;AAAA,QACF,WAAW;AAAA,MACb;AAAA,IACF;AAAA,IAEA,MAAM,QAAQ,SAAwC;AACpD,YAAM,QAAQ,QAAQ,SAAS,OAAO;AACtC,UAAI,OAAO;AACT,cAAM,QAAQ,aAAa,OAAO;AAAA,MACpC;AACA,aAAO,EAAE,WAAW,GAAG;AAAA,IACzB;AAAA,EACF;AACF;AAKO,SAAS,mBAAmB,WAAsC;AACvE,SAAO;AAAA,IACL,MAAM,OAAO,QAA6E;AAExF,YAAM,SAAS,MAAM,UAAU,KAA0B,aAA0B;AAAA,QACjF,SAAS,OAAO;AAAA,QAChB,SAAS,OAAO;AAAA,MAClB,CAAC;AACD,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,IAAI,SAA4C;AACpD,YAAM,SAAS,MAAM,UAAU,KAAuB,aAAa,EAAE,QAAQ,CAAC;AAC9E,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,KAAK,aAAkD;AAC3D,YAAM,SAAS,MAAM,UAAU,KAAwB,cAAc,EAAE,YAAY,CAAC;AACpF,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,QAAQ,SAAwC;AACpD,YAAM,SAAS,MAAM,UAAU,KAAmB,iBAAiB,EAAE,QAAQ,CAAC;AAC9E,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,EACF;AACF;;;AC5GO,SAAS,oBAAoB,SAA0C;AAC5E,SAAO;AAAA,IACL,MAAM,KAAK,SAAiB,SAA2D;AACrF,YAAM,QAAQ,QAAQ,SAAS,OAAqC;AACpE,aAAO,EAAE,SAAS,WAAW,GAAG;AAAA,IAClC;AAAA,IAEA,MAAM,UAAU,SAAwC;AACtD,cAAQ,UAAU,OAAO;AACzB,aAAO,EAAE,WAAW,GAAG;AAAA,IACzB;AAAA,IAEA,MAAM,YAAY,SAAqC;AACrD,YAAM,QAAQ,QAAQ,SAAS,OAAO;AACtC,UAAI,CAAC,MAAO,QAAO,CAAC;AACpB,aAAO,QAAQ,SAAS,kBAAkB,YAAY,MAAM,SAAS;AAAA,IACvE;AAAA,EACF;AACF;AAKO,SAAS,qBAAqB,WAAwC;AAC3E,SAAO;AAAA,IACL,MAAM,KAAK,SAAiB,SAA2D;AACrF,YAAM,SAAS,MAAM,UAAU,KAA0B,gBAAgB;AAAA,QACvE;AAAA,QACA;AAAA,MACF,CAAC;AACD,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,UAAU,SAAwC;AACtD,YAAM,SAAS,MAAM,UAAU,KAAmB,mBAAmB,EAAE,QAAQ,CAAC;AAChF,aAAO,EAAE,GAAG,QAAQ,WAAW,GAAG;AAAA,IACpC;AAAA,IAEA,MAAM,YAAY,SAAqC;AACrD,YAAM,WAAW,MAAM,UAAU,KAAkC,aAAa,EAAE,QAAQ,CAAC;AAC3F,UAAI,CAAC,SAAS,MAAO,QAAO,CAAC;AAC7B,YAAM,SAAS,MAAM,UAAU,KAA8B,kBAAkB;AAAA,QAC7E,SAAS,SAAS,MAAM;AAAA,MAC1B,CAAC;AACD,aAAO,OAAO,YAAY,CAAC;AAAA,IAC7B;AAAA,EACF;AACF;;;ACyDO,IAAM,2BAA8C;AAAA,EACzD,eAAe,CAAC;AAAA,EAChB,WAAW;AAAA,EACX,QAAQ;AACV;;;AC/BO,SAAS,oBAAoB,OAA0B,OAAoC;AAChG,UAAQ,MAAM,MAAM;AAAA;AAAA,IAElB,KAAK;AACH,aAAO,mBAAmB,OAAO,MAAM,IAAwB;AAAA,IAEjE,KAAK;AACH,aAAO,gBAAgB,OAAO,MAAM,IAAqB;AAAA,IAE3D,KAAK;AACH,aAAO,mBAAmB,OAAO,MAAM,IAAwB;AAAA,IAEjE,KAAK;AACH,aAAO,kBAAkB,OAAO,MAAM,IAAuB;AAAA,IAE/D,KAAK;AACH,aAAO,mBAAmB,OAAO,MAAM,IAAwB;AAAA,IAEjE,KAAK;AACH,aAAO,kBAAkB,OAAO,MAAM,IAAuB;AAAA;AAAA,IAG/D,KAAK;AACH,aAAO,wBAAwB,OAAO,MAAM,IAAyB;AAAA,IAEvE,KAAK;AACH,aAAO,YAAY,OAAO,MAAM,IAAiB;AAAA,IAEnD;AACE,aAAO;AAAA,EACX;AACF;AAMA,SAAS,mBAAmB,OAA0B,OAA4C;AAEhG,MAAI,gBAAgB,MAAM;AAC1B,MAAI,MAAM,aAAa,MAAM,UAAU,OAAO,SAAS,GAAG;AACxD,oBAAgB,CAAC,GAAG,eAAe,EAAE,GAAG,MAAM,WAAW,aAAa,MAAM,CAAC;AAAA,EAC/E;AAEA,QAAM,YAAmC;AAAA,IACvC,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,aAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,gBAAgB,OAA0B,MAAwC;AACzF,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,CAAC,GAAG,MAAM,UAAU,MAAM;AACzC,QAAM,YAAY,OAAO,OAAO,SAAS,CAAC;AAE1C,MAAI,aAAa,UAAU,SAAS,QAAQ;AAC1C,WAAO,OAAO,SAAS,CAAC,IAAI;AAAA,MAC1B,GAAG;AAAA,MACH,SAAS,UAAU,UAAU,KAAK;AAAA,IACpC;AAAA,EACF,OAAO;AACL,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,SAAS,KAAK;AAAA,IAChB,CAAc;AAAA,EAChB;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,mBAAmB,OAA0B,MAA2C;AAC/F,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,YAAuB;AAAA,IAC3B,MAAM;AAAA,IACN,WAAW,KAAK;AAAA,IAChB,UAAU,KAAK;AAAA,IACf,WAAW,CAAC;AAAA,IACZ,QAAQ;AAAA,EACV;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT,QAAQ,CAAC,GAAG,MAAM,UAAU,QAAQ,SAAS;AAAA,IAC/C;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAOA,SAAS,kBAAkB,OAA0B,MAA0C;AAC7F,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,UAAU,OAAO,IAAI,CAAC,UAAiB;AAC1D,QAAI,MAAM,SAAS,UAAU,MAAM,cAAc,KAAK,YAAY;AAChE,aAAO;AAAA,QACL,GAAG;AAAA,QACH,WAAW,KAAK;AAAA,QAChB,QAAQ;AAAA,MACV;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,OAA0B,MAA2C;AAC/F,MAAI,CAAC,MAAM,aAAa,CAAC,KAAK,OAAO;AACnC,WAAO;AAAA,EACT;AAEA,QAAM,OAAO,MAAM,UAAU;AAC7B,QAAM,QAAoB;AAAA,IACxB,cAAc,MAAM,eAAe,KAAK,KAAK,MAAM;AAAA,IACnD,eAAe,MAAM,gBAAgB,KAAK,KAAK,MAAM;AAAA,EACvD;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,kBAAkB,OAA0B,MAA0C;AAC7F,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAGA,MAAI,KAAK,eAAe,YAAY;AAClC,WAAO;AAAA,MACL,GAAG;AAAA,MACH,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,QAAM,wBAA+C;AAAA,IACnD,GAAG,MAAM;AAAA,IACT,aAAa;AAAA,EACf;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe,CAAC,GAAG,MAAM,eAAe,qBAAqB;AAAA,IAC7D,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACF;AASA,SAAS,wBACP,OACA,MACmB;AACnB,MAAI,CAAC,MAAM,WAAW;AACpB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,KAAK;AACxB,QAAM,SAAS,MAAM,UAAU,OAAO,IAAI,CAAC,UAAiB;AAC1D,QAAI,MAAM,SAAS,UAAU,MAAM,cAAc,YAAY;AAC3D,aAAO;AAAA,QACL,GAAG;AAAA,QACH,YAAY,uBAAuB,KAAK,WAAW,MAAM;AAAA,QACzD,QACE,KAAK,WAAW,OAAO,SAAS,gBAChC,KAAK,WAAW,OAAO,SAAS,gBAChC,KAAK,WAAW,OAAO,SAAS,qBAC5B,UACA;AAAA,MACR;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AAAA,IACL,GAAG;AAAA,IACH,WAAW;AAAA,MACT,GAAG,MAAM;AAAA,MACT;AAAA,IACF;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAEA,SAAS,YAAY,OAA0B,MAAoC;AACjF,SAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe;AAAA,MACb,GAAG,MAAM;AAAA,MACT;AAAA,QACE,MAAM;AAAA,QACN,SAAS,KAAK;AAAA,MAChB;AAAA,IACF;AAAA,IACA,WAAW;AAAA,IACX,QAAQ;AAAA,EACV;AACF;AAMO,SAAS,oBAAoB,OAA0B,SAAoC;AAChG,SAAO;AAAA,IACL,GAAG;AAAA,IACH,eAAe;AAAA,MACb,GAAG,MAAM;AAAA,MACT;AAAA,QACE,MAAM;AAAA,QACN,QAAQ,CAAC,EAAE,MAAM,QAAQ,QAAQ,CAAC;AAAA,MACpC;AAAA,IACF;AAAA,EACF;AACF;AAEO,SAAS,qBAAwC;AACtD,SAAO,EAAE,GAAG,yBAAyB;AACvC;AAMA,SAAS,uBAAuB,QAAkC;AAChE,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,OAAO;AAAA,IAChB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,KAAK,UAAU,OAAO,KAAK;AAAA,IACpC,KAAK;AACH,aAAO,OAAO,UAAU;AAAA,IAC1B,KAAK;AACH,aAAO,OAAO,MACX,OAAO,CAAC,MAA2C,EAAE,SAAS,MAAM,EACpE,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AAAA,EACd;AACF;AAeO,SAAS,wBAAwB,UAAqC;AAC3E,QAAM,gBAAgC,CAAC;AACvC,MAAI,mBAAiD;AAErD,WAAS,iBAAiB;AACxB,QAAI,oBAAoB,iBAAiB,OAAO,SAAS,GAAG;AAC1D,oBAAc,KAAK,gBAAgB;AAAA,IACrC;AACA,uBAAmB;AAAA,EACrB;AAEA,aAAW,OAAO,UAAU;AAC1B,YAAQ,IAAI,SAAS;AAAA,MACnB,KAAK,QAAQ;AACX,uBAAe;AACf,cAAM,IAAI;AACV,cAAM,OACJ,OAAO,EAAE,YAAY,WACjB,EAAE,UACF,EAAE,QACC,OAAO,CAAC,MAA2C,EAAE,SAAS,MAAM,EACpE,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AAChB,sBAAc,KAAK;AAAA,UACjB,MAAM;AAAA,UACN,QAAQ,CAAC,EAAE,MAAM,QAAQ,SAAS,KAAK,CAAC;AAAA,QAC1C,CAAC;AACD;AAAA,MACF;AAAA,MAEA,KAAK,aAAa;AAChB,YAAI,CAAC,kBAAkB;AACrB,6BAAmB,EAAE,MAAM,aAAa,QAAQ,CAAC,GAAG,aAAa,MAAM;AAAA,QACzE;AACA,cAAM,IAAI;AACV,YAAI,OAAO,EAAE,YAAY,UAAU;AACjC,cAAI,EAAE,SAAS;AACb,6BAAiB,OAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,EAAE,QAAQ,CAAc;AAAA,UAChF;AAAA,QACF,OAAO;AAEL,qBAAW,QAAQ,EAAE,SAAS;AAC5B,gBAAI,KAAK,SAAS,QAAQ;AACxB,kBAAI,KAAK,MAAM;AACb,iCAAiB,OAAO,KAAK,EAAE,MAAM,QAAQ,SAAS,KAAK,KAAK,CAAc;AAAA,cAChF;AAAA,YACF,WAAW,KAAK,SAAS,aAAa;AACpC,oBAAM,KAAK;AACX,+BAAiB,OAAO,KAAK;AAAA,gBAC3B,MAAM;AAAA,gBACN,WAAW,GAAG;AAAA,gBACd,UAAU,GAAG;AAAA,gBACb,WAAW,GAAG;AAAA,gBACd,QAAQ;AAAA,cACV,CAAc;AAAA,YAChB;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,eAAe;AAClB,cAAM,IAAI;AACV,YAAI,kBAAkB;AACpB,qBAAW,SAAS,iBAAiB,QAAQ;AAC3C,gBAAI,MAAM,SAAS,UAAU,MAAM,cAAc,EAAE,WAAW,IAAI;AAChE,oBAAM,aAAa,uBAAuB,EAAE,WAAW,MAAM;AAC7D,oBAAM,SACJ,EAAE,WAAW,OAAO,SAAS,gBAC7B,EAAE,WAAW,OAAO,SAAS,gBAC7B,EAAE,WAAW,OAAO,SAAS,qBACzB,UACA;AACN;AAAA,YACF;AAAA,UACF;AAAA,QACF;AACA;AAAA,MACF;AAAA,MAEA,KAAK,SAAS;AACZ,uBAAe;AACf,cAAM,IAAI;AACV,sBAAc,KAAK;AAAA,UACjB,MAAM;AAAA,UACN,SAAS,EAAE;AAAA,QACb,CAAC;AACD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,iBAAe;AACf,SAAO;AACT;;;AC5bO,IAAM,eAAN,MAAmB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiD,oBAAI,IAAI;AAAA,EACzD,gBAA+C,oBAAI,IAAI;AAAA,EACvD,mBAAuC;AAAA,EAE/C,YACE,QACA,SACA,SACA,sBACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU;AACf,SAAK,QAAQ,sBAAsB,SAC/B,EAAE,GAAG,0BAA0B,eAAe,qBAAqB,IACnE,mBAAmB;AAGvB,QAAI,SAAS,UAAU;AACrB,WAAK,eAAe,IAAI,QAAQ,QAAQ;AAAA,IAC1C;AACA,QAAI,SAAS,SAAS;AACpB,WAAK,cAAc,IAAI,QAAQ,OAAO;AAAA,IACxC;AAGA,SAAK,kBAAkB;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA,EAKA,WAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,SAAS,SAAiD;AACxD,SAAK,eAAe,IAAI,OAAO;AAE/B,YAAQ,KAAK,KAAK;AAClB,WAAO,MAAM;AACX,WAAK,eAAe,OAAO,OAAO;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,SAAgD;AACtD,SAAK,cAAc,IAAI,OAAO;AAC9B,WAAO,MAAM;AACX,WAAK,cAAc,OAAO,OAAO;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,KAAK,SAAgC;AAEzC,SAAK,QAAQ,oBAAoB,KAAK,OAAO,OAAO;AACpD,SAAK,OAAO;AAEZ,QAAI;AAEF,YAAM,KAAK,OAAO,SAAS,KAAK,KAAK,SAAS,OAAO;AAAA,IACvD,SAAS,OAAO;AACd,WAAK,YAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,YAA2B;AAC/B,QAAI;AACF,YAAM,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO;AAAA,IACnD,SAAS,OAAO;AACd,WAAK,YAAY,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,IAC5E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,QAAc;AACZ,SAAK,QAAQ,mBAAmB;AAChC,SAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,UAAgB;AACd,QAAI,KAAK,kBAAkB;AACzB,WAAK,iBAAiB;AACtB,WAAK,mBAAmB;AAAA,IAC1B;AACA,SAAK,eAAe,MAAM;AAC1B,SAAK,cAAc,MAAM;AAAA,EAC3B;AAAA;AAAA,EAIQ,oBAA0B;AAEhC,SAAK,mBAAmB,KAAK,OAAO,MAAM,CAAC,UAAoB;AAG7D,YAAM,mBAAmB;AACzB,YAAM,eAAe,iBAAiB,SAAS;AAG/C,UAAI,gBAAgB,iBAAiB,KAAK,SAAS;AACjD;AAAA,MACF;AAGA,YAAM,WAAW,oBAAoB,KAAK,OAAO,KAAK;AACtD,UAAI,aAAa,KAAK,OAAO;AAC3B,aAAK,QAAQ;AACb,aAAK,OAAO;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,eAAW,WAAW,KAAK,gBAAgB;AACzC,UAAI;AACF,gBAAQ,KAAK,KAAK;AAAA,MACpB,SAAS,OAAO;AACd,gBAAQ,MAAM,sCAAsC,KAAK;AAAA,MAC3D;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAY,OAAoB;AACtC,eAAW,WAAW,KAAK,eAAe;AACxC,UAAI;AACF,gBAAQ,KAAK;AAAA,MACf,SAAS,GAAG;AACV,gBAAQ,MAAM,qCAAqC,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AACF;;;ACnLO,SAAS,oBAAoB,QAAuC;AACzE,SAAO;AAAA,IACL,MAAM,OAAO,SAAiB,SAAsD;AAClF,YAAM,WAAW,MAAM,OAAO,SAAS,YAAY,OAAO;AAC1D,YAAM,gBAAgB,wBAAwB,QAAQ;AACtD,aAAO,IAAI,aAAa,QAAQ,SAAS,SAAS,aAAa;AAAA,IACjE;AAAA,EACF;AACF;;;ARKA,IAAM,SAAS,aAAa,qBAAqB;AAK1C,IAAM,eAAN,MAAqC;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EAER;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,QAAsB;AAChC,SAAK,SAAS;AACd,SAAK,WAAW,IAAI,aAAa;AAGjC,SAAK,YAAY,IAAI,UAAU;AAAA,MAC7B,KAAK,OAAO;AAAA,MACZ,iBAAiB,OAAO,gBAAgB;AAAA,MACxC,SAAS,OAAO,WAAW;AAAA,MAC3B,eAAe,OAAO,iBAAiB;AAAA,MACvC,SAAS,OAAO;AAAA,MAChB,OAAO;AAAA,IACT,CAAC;AAGD,SAAK,UAAU,cAAc,CAAC,OAAO,UAAU;AAC7C,aAAO,MAAM,yBAAyB,EAAE,OAAO,MAAM,MAAM,KAAK,CAAC;AACjE,WAAK,SAAS,KAAK,KAAiB;AAAA,IACtC,CAAC;AAGD,SAAK,aAAa,uBAAuB,KAAK,SAAS;AACvD,SAAK,SAAS,mBAAmB,KAAK,WAAW,CAAC,cAAc,KAAK,UAAU,SAAS,CAAC;AACzF,SAAK,SAAS,mBAAmB,KAAK,SAAS;AAC/C,SAAK,WAAW,qBAAqB,KAAK,SAAS;AACnD,SAAK,gBAAgB,oBAAoB,IAAI;AAAA,EAC/C;AAAA;AAAA,EAIA,IAAI,YAAqB;AACvB,WAAO,KAAK,UAAU;AAAA,EACxB;AAAA,EAEA,IAAI,SAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAIA,MAAM,UAAyB;AAC7B,UAAM,KAAK,UAAU,QAAQ;AAC7B,WAAO,KAAK,uBAAuB,EAAE,KAAK,KAAK,OAAO,UAAU,CAAC;AAAA,EACnE;AAAA,EAEA,MAAM,aAA4B;AAChC,SAAK,UAAU,WAAW;AAC1B,WAAO,KAAK,0BAA0B;AAAA,EACxC;AAAA,EAEA,MAAM,UAAyB;AAC7B,SAAK,UAAU,QAAQ;AACvB,SAAK,SAAS,QAAQ;AACtB,WAAO,KAAK,uBAAuB;AAAA,EACrC;AAAA;AAAA,EAIA,GAAqB,MAAS,SAA+D;AAC3F,WAAO,KAAK,SAAS,GAAG,MAAM,OAAO;AAAA,EACvC;AAAA,EAEA,MAAM,SAAuC;AAC3C,WAAO,KAAK,SAAS,MAAM,OAAO;AAAA,EACpC;AAAA,EAEA,UAAU,WAAyB;AACjC,SAAK,UAAU,UAAU,SAAS;AAClC,WAAO,MAAM,yBAAyB,EAAE,UAAU,CAAC;AAAA,EACrD;AACF;;;ASvGA,SAAS,gBAAAA,qBAAoB;AAe7B,IAAMC,UAASC,cAAa,oBAAoB;AAKzC,IAAM,cAAN,MAAoC;AAAA,EACxB;AAAA,EACT,aAAa;AAAA,EAEZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,SAAwB;AAClC,SAAK,UAAU;AACf,UAAM,WAAW,QAAQ;AAEzB,SAAK,aAAa,sBAAsB,QAAQ;AAChD,SAAK,SAAS,kBAAkB,QAAQ;AACxC,SAAK,SAAS,kBAAkB,OAAO;AACvC,SAAK,WAAW,oBAAoB,OAAO;AAC3C,SAAK,gBAAgB,oBAAoB,IAAI;AAE7C,IAAAD,QAAO,KAAK,yBAAyB;AAAA,EACvC;AAAA;AAAA,EAIA,IAAI,YAAqB;AACvB,WAAO,CAAC,KAAK;AAAA,EACf;AAAA,EAEA,IAAI,SAAmB;AACrB,WAAO,KAAK,QAAQ,SAAS;AAAA,EAC/B;AAAA;AAAA,EAIA,GAAqB,MAAS,SAA+D;AAC3F,WAAO,KAAK,QAAQ,SAAS,SAAS,GAAG,MAAM,OAAO;AAAA,EACxD;AAAA,EAEA,MAAM,SAAuC;AAC3C,WAAO,KAAK,QAAQ,SAAS,SAAS,MAAM,OAAO;AAAA,EACrD;AAAA,EAEA,UAAU,YAA0B;AAAA,EAEpC;AAAA;AAAA,EAIA,MAAM,aAA4B;AAAA,EAElC;AAAA,EAEA,MAAM,UAAyB;AAC7B,QAAI,KAAK,WAAY;AACrB,UAAM,KAAK,QAAQ,SAAS;AAC5B,SAAK,aAAa;AAClB,IAAAA,QAAO,KAAK,sBAAsB;AAAA,EACpC;AACF;;;ACvCA,eAAsB,aAAa,QAAuC;AACxE,MAAI,OAAO,WAAW;AAEpB,UAAM,iBAAiB,MAAM,yBAAyB,MAAM;AAC5D,UAAM,SAAS,IAAI,aAAa,cAAc;AAC9C,UAAM,OAAO,QAAQ;AACrB,WAAO;AAAA,EACT;AAEA,MAAI,OAAO,UAAU,OAAO,gBAAgB,OAAO,gBAAgB;AAEjE,WAAO,kBAAkB,MAAM;AAAA,EACjC;AAEA,QAAM,IAAI;AAAA,IACR;AAAA,EACF;AACF;AAQA,eAAe,yBAAyB,QAA6C;AACnF,MAAI,OAAO,gBAAgB,kBAAkB;AAC3C,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,eAAe,eAAgB,WAAmB,QAAQ,aAAa,QAAW;AAC3F,WAAO;AAAA,EACT;AAGA,MAAI;AACF,UAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,iCAAiC;AAC9E,WAAO;AAAA,MACL,GAAG;AAAA,MACH,gBAAgB;AAAA,QACd,GAAG,OAAO;AAAA,QACV,kBAAkB;AAAA,MACpB;AAAA,IACF;AAAA,EACF,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AAKA,eAAe,kBAAkB,QAAuC;AACtE,QAAM,EAAE,oBAAoB,IAAI,MAAM,OAAO,wBAAwB;AAGrE,MAAI;AACJ,MAAI,OAAO,gBAAgB;AACzB,eAAW,OAAO;AAAA,EACpB,OAAO;AACL,UAAM,EAAE,mBAAmB,IAAI,MAAM,OAAO,yBAAyB;AACrE,eAAW,MAAM,mBAAmB;AAAA,MAClC,UAAU,OAAO,YAAY;AAAA,MAC7B,UAAU,OAAO,aAAa,OAAO,QAAQ,UAAU;AAAA,IACzD,CAAC;AAAA,EACH;AAGA,MAAI,eAAe,OAAO;AAC1B,MAAI,CAAC,cAAc;AACjB,UAAM,EAAE,iBAAiB,IAAI,MAAM,OAAO,uBAAuB;AACjE,mBAAe,CAAC,iBAA+D;AAC7E,YAAM,kBAAmB,aAAqB,WAAW,CAAC;AAC1D,aAAO,iBAAiB;AAAA,QACtB,GAAG;AAAA,QACH,QAAQ,OAAO,UAAU,aAAa;AAAA,QACtC,SAAS,OAAO,WAAW,aAAa;AAAA,QACxC,OAAO,OAAO,SAAS,aAAa;AAAA,QACpC,SAAS;AAAA,UACP,GAAG;AAAA,UACH,UAAU,OAAO,YAAY,gBAAgB,YAAY;AAAA,QAC3D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,UAAU,oBAAoB,UAAU,YAAY;AAE1D,SAAO,IAAI,YAAY,OAAO;AAChC;","names":["createLogger","logger","createLogger"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "agentxjs",
3
- "version": "1.9.9-dev",
4
- "description": "AgentX Client SDK - Connect to AgentX servers",
3
+ "version": "2.0.0",
4
+ "description": "AgentX Client SDK - Local and remote AI agent management",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "main": "./dist/index.js",
@@ -20,15 +20,23 @@
20
20
  "scripts": {
21
21
  "build": "tsup",
22
22
  "typecheck": "tsc --noEmit",
23
- "test": "bun test"
23
+ "test": "echo 'No tests yet'",
24
+ "bdd": "bdd",
25
+ "bdd:developer": "bdd --tags @developer"
24
26
  },
25
27
  "dependencies": {
26
- "@agentxjs/core": "1.9.9-dev",
28
+ "@agentxjs/core": "^2.0.0",
29
+ "@agentxjs/mono-driver": "^2.0.0",
30
+ "@agentxjs/node-platform": "^2.0.0",
27
31
  "reconnecting-websocket": "^4.4.0",
28
32
  "ws": "^8.18.0"
29
33
  },
30
34
  "devDependencies": {
35
+ "@agentxjs/devtools": "^2.0.0",
36
+ "@agentxjs/server": "^2.0.0",
37
+ "@cucumber/cucumber": "^11.0.0",
31
38
  "@types/ws": "^8.5.10",
39
+ "tsx": "^4.19.0",
32
40
  "typescript": "^5.3.3"
33
41
  },
34
42
  "publishConfig": {
@@ -0,0 +1,89 @@
1
+ /**
2
+ * LocalClient - AgentX client for local mode
3
+ *
4
+ * Runs an embedded Runtime + Driver directly, without WebSocket.
5
+ * Implements the same AgentX interface as RemoteClient.
6
+ */
7
+
8
+ import type { BusEvent, EventBus, BusEventHandler, Unsubscribe } from "@agentxjs/core/event";
9
+ import type { AgentXRuntime } from "@agentxjs/core/runtime";
10
+ import { createLogger } from "commonxjs/logger";
11
+ import type {
12
+ AgentX,
13
+ ContainerNamespace,
14
+ ImageNamespace,
15
+ AgentNamespace,
16
+ SessionNamespace,
17
+ PresentationNamespace,
18
+ } from "./types";
19
+ import { createLocalContainers } from "./namespaces/containers";
20
+ import { createLocalImages } from "./namespaces/images";
21
+ import { createLocalAgents } from "./namespaces/agents";
22
+ import { createLocalSessions } from "./namespaces/sessions";
23
+ import { createPresentations } from "./namespaces/presentations";
24
+
25
+ const logger = createLogger("agentx/LocalClient");
26
+
27
+ /**
28
+ * LocalClient - Embedded runtime implementation
29
+ */
30
+ export class LocalClient implements AgentX {
31
+ private readonly runtime: AgentXRuntime;
32
+ private isDisposed = false;
33
+
34
+ readonly containers: ContainerNamespace;
35
+ readonly images: ImageNamespace;
36
+ readonly agents: AgentNamespace;
37
+ readonly sessions: SessionNamespace;
38
+ readonly presentations: PresentationNamespace;
39
+
40
+ constructor(runtime: AgentXRuntime) {
41
+ this.runtime = runtime;
42
+ const platform = runtime.platform;
43
+
44
+ this.containers = createLocalContainers(platform);
45
+ this.images = createLocalImages(platform);
46
+ this.agents = createLocalAgents(runtime);
47
+ this.sessions = createLocalSessions(runtime);
48
+ this.presentations = createPresentations(this);
49
+
50
+ logger.info("LocalClient initialized");
51
+ }
52
+
53
+ // ==================== Properties ====================
54
+
55
+ get connected(): boolean {
56
+ return !this.isDisposed;
57
+ }
58
+
59
+ get events(): EventBus {
60
+ return this.runtime.platform.eventBus;
61
+ }
62
+
63
+ // ==================== Event Subscription ====================
64
+
65
+ on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {
66
+ return this.runtime.platform.eventBus.on(type, handler);
67
+ }
68
+
69
+ onAny(handler: BusEventHandler): Unsubscribe {
70
+ return this.runtime.platform.eventBus.onAny(handler);
71
+ }
72
+
73
+ subscribe(_sessionId: string): void {
74
+ // No-op for local mode - already subscribed via eventBus
75
+ }
76
+
77
+ // ==================== Lifecycle ====================
78
+
79
+ async disconnect(): Promise<void> {
80
+ // No-op for local mode
81
+ }
82
+
83
+ async dispose(): Promise<void> {
84
+ if (this.isDisposed) return;
85
+ await this.runtime.shutdown();
86
+ this.isDisposed = true;
87
+ logger.info("LocalClient disposed");
88
+ }
89
+ }
@@ -7,24 +7,22 @@
7
7
 
8
8
  import type { BusEvent, EventBus, BusEventHandler, Unsubscribe } from "@agentxjs/core/event";
9
9
  import { EventBusImpl } from "@agentxjs/core/event";
10
- import { RpcClient, type RpcMethod } from "@agentxjs/core/network";
10
+ import { RpcClient } from "@agentxjs/core/network";
11
11
  import { createLogger } from "commonxjs/logger";
12
12
  import type {
13
13
  AgentX,
14
14
  AgentXConfig,
15
- AgentCreateResponse,
16
- AgentGetResponse,
17
- AgentListResponse,
18
- ImageCreateResponse,
19
- ImageGetResponse,
20
- ImageListResponse,
21
- ContainerCreateResponse,
22
- ContainerGetResponse,
23
- ContainerListResponse,
24
- MessageSendResponse,
25
- BaseResponse,
15
+ ContainerNamespace,
16
+ ImageNamespace,
17
+ AgentNamespace,
18
+ SessionNamespace,
19
+ PresentationNamespace,
26
20
  } from "./types";
27
- import { Presentation, type PresentationOptions } from "./presentation";
21
+ import { createRemoteContainers } from "./namespaces/containers";
22
+ import { createRemoteImages } from "./namespaces/images";
23
+ import { createRemoteAgents } from "./namespaces/agents";
24
+ import { createRemoteSessions } from "./namespaces/sessions";
25
+ import { createPresentations } from "./namespaces/presentations";
28
26
 
29
27
  const logger = createLogger("agentx/RemoteClient");
30
28
 
@@ -36,13 +34,20 @@ export class RemoteClient implements AgentX {
36
34
  private readonly eventBus: EventBus;
37
35
  private readonly rpcClient: RpcClient;
38
36
 
37
+ readonly containers: ContainerNamespace;
38
+ readonly images: ImageNamespace;
39
+ readonly agents: AgentNamespace;
40
+ readonly sessions: SessionNamespace;
41
+ readonly presentations: PresentationNamespace;
42
+
39
43
  constructor(config: AgentXConfig) {
40
44
  this.config = config;
41
45
  this.eventBus = new EventBusImpl();
42
46
 
43
- // Create RPC client
47
+ // Create RPC client (WebSocket factory from platform if available)
44
48
  this.rpcClient = new RpcClient({
45
- url: config.serverUrl,
49
+ url: config.serverUrl!,
50
+ createWebSocket: config.customPlatform?.webSocketFactory,
46
51
  timeout: config.timeout ?? 30000,
47
52
  autoReconnect: config.autoReconnect ?? true,
48
53
  headers: config.headers as Record<string, string> | undefined,
@@ -54,6 +59,13 @@ export class RemoteClient implements AgentX {
54
59
  logger.debug("Received stream event", { topic, type: event.type });
55
60
  this.eventBus.emit(event as BusEvent);
56
61
  });
62
+
63
+ // Assemble namespaces
64
+ this.containers = createRemoteContainers(this.rpcClient);
65
+ this.images = createRemoteImages(this.rpcClient, (sessionId) => this.subscribe(sessionId));
66
+ this.agents = createRemoteAgents(this.rpcClient);
67
+ this.sessions = createRemoteSessions(this.rpcClient);
68
+ this.presentations = createPresentations(this);
57
69
  }
58
70
 
59
71
  // ==================== Properties ====================
@@ -84,120 +96,6 @@ export class RemoteClient implements AgentX {
84
96
  logger.info("RemoteClient disposed");
85
97
  }
86
98
 
87
- // ==================== Container Operations ====================
88
-
89
- async createContainer(containerId: string): Promise<ContainerCreateResponse> {
90
- const result = await this.rpcClient.call<ContainerCreateResponse>("container.create", {
91
- containerId,
92
- });
93
- return { ...result, requestId: "" };
94
- }
95
-
96
- async getContainer(containerId: string): Promise<ContainerGetResponse> {
97
- const result = await this.rpcClient.call<ContainerGetResponse>("container.get", {
98
- containerId,
99
- });
100
- return { ...result, requestId: "" };
101
- }
102
-
103
- async listContainers(): Promise<ContainerListResponse> {
104
- const result = await this.rpcClient.call<ContainerListResponse>("container.list", {});
105
- return { ...result, requestId: "" };
106
- }
107
-
108
- // ==================== Image Operations ====================
109
-
110
- async createImage(params: {
111
- containerId: string;
112
- name?: string;
113
- description?: string;
114
- systemPrompt?: string;
115
- mcpServers?: Record<string, unknown>;
116
- }): Promise<ImageCreateResponse> {
117
- const result = await this.rpcClient.call<ImageCreateResponse>("image.create", params);
118
-
119
- // Auto subscribe to session events
120
- if (result.__subscriptions) {
121
- for (const sessionId of result.__subscriptions) {
122
- this.subscribe(sessionId);
123
- }
124
- }
125
-
126
- return { ...result, requestId: "" };
127
- }
128
-
129
- async getImage(imageId: string): Promise<ImageGetResponse> {
130
- const result = await this.rpcClient.call<ImageGetResponse>("image.get", { imageId });
131
-
132
- // Auto subscribe
133
- if (result.__subscriptions) {
134
- for (const sessionId of result.__subscriptions) {
135
- this.subscribe(sessionId);
136
- }
137
- }
138
-
139
- return { ...result, requestId: "" };
140
- }
141
-
142
- async listImages(containerId?: string): Promise<ImageListResponse> {
143
- const result = await this.rpcClient.call<ImageListResponse>("image.list", { containerId });
144
-
145
- // Auto subscribe
146
- if (result.__subscriptions) {
147
- for (const sessionId of result.__subscriptions) {
148
- this.subscribe(sessionId);
149
- }
150
- }
151
-
152
- return { ...result, requestId: "" };
153
- }
154
-
155
- async deleteImage(imageId: string): Promise<BaseResponse> {
156
- const result = await this.rpcClient.call<BaseResponse>("image.delete", { imageId });
157
- return { ...result, requestId: "" };
158
- }
159
-
160
- // ==================== Agent Operations ====================
161
-
162
- async createAgent(params: { imageId: string; agentId?: string }): Promise<AgentCreateResponse> {
163
- // Agent creation via image.run RPC
164
- const result = await this.rpcClient.call<AgentCreateResponse>("image.run" as RpcMethod, {
165
- imageId: params.imageId,
166
- agentId: params.agentId,
167
- });
168
- return { ...result, requestId: "" };
169
- }
170
-
171
- async getAgent(agentId: string): Promise<AgentGetResponse> {
172
- const result = await this.rpcClient.call<AgentGetResponse>("agent.get", { agentId });
173
- return { ...result, requestId: "" };
174
- }
175
-
176
- async listAgents(containerId?: string): Promise<AgentListResponse> {
177
- const result = await this.rpcClient.call<AgentListResponse>("agent.list", { containerId });
178
- return { ...result, requestId: "" };
179
- }
180
-
181
- async destroyAgent(agentId: string): Promise<BaseResponse> {
182
- const result = await this.rpcClient.call<BaseResponse>("agent.destroy", { agentId });
183
- return { ...result, requestId: "" };
184
- }
185
-
186
- // ==================== Message Operations ====================
187
-
188
- async sendMessage(agentId: string, content: string | unknown[]): Promise<MessageSendResponse> {
189
- const result = await this.rpcClient.call<MessageSendResponse>("message.send", {
190
- agentId,
191
- content,
192
- });
193
- return { ...result, requestId: "" };
194
- }
195
-
196
- async interrupt(agentId: string): Promise<BaseResponse> {
197
- const result = await this.rpcClient.call<BaseResponse>("agent.interrupt", { agentId });
198
- return { ...result, requestId: "" };
199
- }
200
-
201
99
  // ==================== Event Subscription ====================
202
100
 
203
101
  on<T extends string>(type: T, handler: BusEventHandler<BusEvent & { type: T }>): Unsubscribe {
@@ -212,10 +110,4 @@ export class RemoteClient implements AgentX {
212
110
  this.rpcClient.subscribe(sessionId);
213
111
  logger.debug("Subscribed to session", { sessionId });
214
112
  }
215
-
216
- // ==================== Presentation ====================
217
-
218
- presentation(agentId: string, options?: PresentationOptions): Presentation {
219
- return new Presentation(this, agentId, options);
220
- }
221
113
  }