import { z } from "zod"; import * as schema from "./schema/index.js"; import * as validate from "./schema/zod.gen.js"; export * from "./schema/index.js"; export * from "./stream.js"; /** * An agent-side connection to a client. * * This class provides the agent's view of an ACP connection, allowing * agents to communicate with clients. It implements the {@link Client} interface * to provide methods for requesting permissions, accessing the file system, * and sending session updates. * * See protocol docs: [Agent](https://agentclientprotocol.com/protocol/overview#agent) */ export class AgentSideConnection { #connection; /** * Creates a new agent-side connection to a client. * * This establishes the communication channel from the agent's perspective * following the ACP specification. * * @param toAgent - A function that creates an Agent handler to process incoming client requests * @param stream - The bidirectional message stream for communication. Typically created using * {@link ndJsonStream} for stdio-based connections. * * See protocol docs: [Communication Model](https://agentclientprotocol.com/protocol/overview#communication-model) */ constructor(toAgent, stream) { const agent = toAgent(this); const requestHandler = async (method, params) => { switch (method) { case schema.AGENT_METHODS.initialize: { const validatedParams = validate.zInitializeRequest.parse(params); return agent.initialize(validatedParams); } case schema.AGENT_METHODS.session_new: { const validatedParams = validate.zNewSessionRequest.parse(params); return agent.newSession(validatedParams); } case schema.AGENT_METHODS.session_load: { if (!agent.loadSession) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zLoadSessionRequest.parse(params); return agent.loadSession(validatedParams); } case schema.AGENT_METHODS.session_list: { if (!agent.unstable_listSessions) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zListSessionsRequest.parse(params); return agent.unstable_listSessions(validatedParams); } case schema.AGENT_METHODS.session_fork: { if (!agent.unstable_forkSession) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zForkSessionRequest.parse(params); return agent.unstable_forkSession(validatedParams); } case schema.AGENT_METHODS.session_resume: { if (!agent.unstable_resumeSession) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zResumeSessionRequest.parse(params); return agent.unstable_resumeSession(validatedParams); } case schema.AGENT_METHODS.session_set_mode: { if (!agent.setSessionMode) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zSetSessionModeRequest.parse(params); const result = await agent.setSessionMode(validatedParams); return result ?? {}; } case schema.AGENT_METHODS.authenticate: { const validatedParams = validate.zAuthenticateRequest.parse(params); const result = await agent.authenticate(validatedParams); return result ?? {}; } case schema.AGENT_METHODS.session_prompt: { const validatedParams = validate.zPromptRequest.parse(params); return agent.prompt(validatedParams); } case schema.AGENT_METHODS.session_set_model: { if (!agent.unstable_setSessionModel) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zSetSessionModelRequest.parse(params); const result = await agent.unstable_setSessionModel(validatedParams); return result ?? {}; } case schema.AGENT_METHODS.session_set_config_option: { if (!agent.unstable_setSessionConfigOption) { throw RequestError.methodNotFound(method); } const validatedParams = validate.zSetSessionConfigOptionRequest.parse(params); return agent.unstable_setSessionConfigOption(validatedParams); } default: if (agent.extMethod) { return agent.extMethod(method, params); } throw RequestError.methodNotFound(method); } }; const notificationHandler = async (method, params) => { switch (method) { case schema.AGENT_METHODS.session_cancel: { const validatedParams = validate.zCancelNotification.parse(params); return agent.cancel(validatedParams); } default: if (agent.extNotification) { return agent.extNotification(method, params); } throw RequestError.methodNotFound(method); } }; this.#connection = new Connection(requestHandler, notificationHandler, stream); } /** * Handles session update notifications from the agent. * * This is a notification endpoint (no response expected) that sends * real-time updates about session progress, including message chunks, * tool calls, and execution plans. * * Note: Clients SHOULD continue accepting tool call updates even after * sending a `session/cancel` notification, as the agent may send final * updates before responding with the cancelled stop reason. * * See protocol docs: [Agent Reports Output](https://agentclientprotocol.com/protocol/prompt-turn#3-agent-reports-output) */ async sessionUpdate(params) { return await this.#connection.sendNotification(schema.CLIENT_METHODS.session_update, params); } /** * Requests permission from the user for a tool call operation. * * Called by the agent when it needs user authorization before executing * a potentially sensitive operation. The client should present the options * to the user and return their decision. * * If the client cancels the prompt turn via `session/cancel`, it MUST * respond to this request with `RequestPermissionOutcome::Cancelled`. * * See protocol docs: [Requesting Permission](https://agentclientprotocol.com/protocol/tool-calls#requesting-permission) */ async requestPermission(params) { return await this.#connection.sendRequest(schema.CLIENT_METHODS.session_request_permission, params); } /** * Reads content from a text file in the client's file system. * * Only available if the client advertises the `fs.readTextFile` capability. * Allows the agent to access file contents within the client's environment. * * See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client) */ async readTextFile(params) { return await this.#connection.sendRequest(schema.CLIENT_METHODS.fs_read_text_file, params); } /** * Writes content to a text file in the client's file system. * * Only available if the client advertises the `fs.writeTextFile` capability. * Allows the agent to create or modify files within the client's environment. * * See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client) */ async writeTextFile(params) { return ((await this.#connection.sendRequest(schema.CLIENT_METHODS.fs_write_text_file, params)) ?? {}); } /** * Executes a command in a new terminal. * * Returns a `TerminalHandle` that can be used to get output, wait for exit, * kill the command, or release the terminal. * * The terminal can also be embedded in tool calls by using its ID in * `ToolCallContent` with type "terminal". * * @param params - The terminal creation parameters * @returns A handle to control and monitor the terminal */ async createTerminal(params) { const response = await this.#connection.sendRequest(schema.CLIENT_METHODS.terminal_create, params); return new TerminalHandle(response.terminalId, params.sessionId, this.#connection); } /** * Extension method * * Allows the Agent to send an arbitrary request that is not part of the ACP spec. */ async extMethod(method, params) { return await this.#connection.sendRequest(method, params); } /** * Extension notification * * Allows the Agent to send an arbitrary notification that is not part of the ACP spec. */ async extNotification(method, params) { return await this.#connection.sendNotification(method, params); } /** * AbortSignal that aborts when the connection closes. * * This signal can be used to: * - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})` * - Check connection status synchronously: `if (connection.signal.aborted) {...}` * - Pass to other APIs (fetch, setTimeout) for automatic cancellation * * The connection closes when the underlying stream ends, either normally or due to an error. * * @example * ```typescript * const connection = new AgentSideConnection(agent, stream); * * // Listen for closure * connection.signal.addEventListener('abort', () => { * console.log('Connection closed - performing cleanup'); * }); * * // Check status * if (connection.signal.aborted) { * console.log('Connection is already closed'); * } * * // Pass to other APIs * fetch(url, { signal: connection.signal }); * ``` */ get signal() { return this.#connection.signal; } /** * Promise that resolves when the connection closes. * * The connection closes when the underlying stream ends, either normally or due to an error. * Once closed, the connection cannot send or receive any more messages. * * This is useful for async/await style cleanup: * * @example * ```typescript * const connection = new AgentSideConnection(agent, stream); * await connection.closed; * console.log('Connection closed - performing cleanup'); * ``` */ get closed() { return this.#connection.closed; } } /** * Handle for controlling and monitoring a terminal created via `createTerminal`. * * Provides methods to: * - Get current output without waiting * - Wait for command completion * - Kill the running command * - Release terminal resources * * **Important:** Always call `release()` when done with the terminal to free resources. * The terminal supports async disposal via `Symbol.asyncDispose` for automatic cleanup. * You can use `await using` to ensure the terminal is automatically released when it * goes out of scope. */ export class TerminalHandle { id; #sessionId; #connection; constructor(id, sessionId, conn) { this.id = id; this.#sessionId = sessionId; this.#connection = conn; } /** * Gets the current terminal output without waiting for the command to exit. */ async currentOutput() { return await this.#connection.sendRequest(schema.CLIENT_METHODS.terminal_output, { sessionId: this.#sessionId, terminalId: this.id, }); } /** * Waits for the terminal command to complete and returns its exit status. */ async waitForExit() { return await this.#connection.sendRequest(schema.CLIENT_METHODS.terminal_wait_for_exit, { sessionId: this.#sessionId, terminalId: this.id, }); } /** * Kills the terminal command without releasing the terminal. * * The terminal remains valid after killing, allowing you to: * - Get the final output with `currentOutput()` * - Check the exit status * - Release the terminal when done * * Useful for implementing timeouts or cancellation. */ async kill() { return ((await this.#connection.sendRequest(schema.CLIENT_METHODS.terminal_kill, { sessionId: this.#sessionId, terminalId: this.id, })) ?? {}); } /** * Releases the terminal and frees all associated resources. * * If the command is still running, it will be killed. * After release, the terminal ID becomes invalid and cannot be used * with other terminal methods. * * Tool calls that already reference this terminal will continue to * display its output. * * **Important:** Always call this method when done with the terminal. */ async release() { return ((await this.#connection.sendRequest(schema.CLIENT_METHODS.terminal_release, { sessionId: this.#sessionId, terminalId: this.id, })) ?? {}); } async [Symbol.asyncDispose]() { await this.release(); } } /** * A client-side connection to an agent. * * This class provides the client's view of an ACP connection, allowing * clients (such as code editors) to communicate with agents. It implements * the {@link Agent} interface to provide methods for initializing sessions, sending * prompts, and managing the agent lifecycle. * * See protocol docs: [Client](https://agentclientprotocol.com/protocol/overview#client) */ export class ClientSideConnection { #connection; /** * Creates a new client-side connection to an agent. * * This establishes the communication channel between a client and agent * following the ACP specification. * * @param toClient - A function that creates a Client handler to process incoming agent requests * @param stream - The bidirectional message stream for communication. Typically created using * {@link ndJsonStream} for stdio-based connections. * * See protocol docs: [Communication Model](https://agentclientprotocol.com/protocol/overview#communication-model) */ constructor(toClient, stream) { const client = toClient(this); const requestHandler = async (method, params) => { switch (method) { case schema.CLIENT_METHODS.fs_write_text_file: { const validatedParams = validate.zWriteTextFileRequest.parse(params); return client.writeTextFile?.(validatedParams); } case schema.CLIENT_METHODS.fs_read_text_file: { const validatedParams = validate.zReadTextFileRequest.parse(params); return client.readTextFile?.(validatedParams); } case schema.CLIENT_METHODS.session_request_permission: { const validatedParams = validate.zRequestPermissionRequest.parse(params); return client.requestPermission(validatedParams); } case schema.CLIENT_METHODS.terminal_create: { const validatedParams = validate.zCreateTerminalRequest.parse(params); return client.createTerminal?.(validatedParams); } case schema.CLIENT_METHODS.terminal_output: { const validatedParams = validate.zTerminalOutputRequest.parse(params); return client.terminalOutput?.(validatedParams); } case schema.CLIENT_METHODS.terminal_release: { const validatedParams = validate.zReleaseTerminalRequest.parse(params); const result = await client.releaseTerminal?.(validatedParams); return result ?? {}; } case schema.CLIENT_METHODS.terminal_wait_for_exit: { const validatedParams = validate.zWaitForTerminalExitRequest.parse(params); return client.waitForTerminalExit?.(validatedParams); } case schema.CLIENT_METHODS.terminal_kill: { const validatedParams = validate.zKillTerminalCommandRequest.parse(params); const result = await client.killTerminal?.(validatedParams); return result ?? {}; } default: if (client.extMethod) { return client.extMethod(method, params); } throw RequestError.methodNotFound(method); } }; const notificationHandler = async (method, params) => { switch (method) { case schema.CLIENT_METHODS.session_update: { const validatedParams = validate.zSessionNotification.parse(params); return client.sessionUpdate(validatedParams); } default: if (client.extNotification) { return client.extNotification(method, params); } throw RequestError.methodNotFound(method); } }; this.#connection = new Connection(requestHandler, notificationHandler, stream); } /** * Establishes the connection with a client and negotiates protocol capabilities. * * This method is called once at the beginning of the connection to: * - Negotiate the protocol version to use * - Exchange capability information between client and agent * - Determine available authentication methods * * The agent should respond with its supported protocol version and capabilities. * * See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization) */ async initialize(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.initialize, params); } /** * Creates a new conversation session with the agent. * * Sessions represent independent conversation contexts with their own history and state. * * The agent should: * - Create a new session context * - Connect to any specified MCP servers * - Return a unique session ID for future requests * * May return an `auth_required` error if the agent requires authentication. * * See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup) */ async newSession(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_new, params); } /** * Loads an existing session to resume a previous conversation. * * This method is only available if the agent advertises the `loadSession` capability. * * The agent should: * - Restore the session context and conversation history * - Connect to the specified MCP servers * - Stream the entire conversation history back to the client via notifications * * See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions) */ async loadSession(params) { return ((await this.#connection.sendRequest(schema.AGENT_METHODS.session_load, params)) ?? {}); } /** * **UNSTABLE** * * This capability is not part of the spec yet, and may be removed or changed at any point. * * Forks an existing session to create a new independent session. * * Creates a new session based on the context of an existing one, allowing * operations like generating summaries without affecting the original session's history. * * This method is only available if the agent advertises the `session.fork` capability. * * @experimental */ async unstable_forkSession(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_fork, params); } /** * **UNSTABLE** * * This capability is not part of the spec yet, and may be removed or changed at any point. * * Lists existing sessions from the agent. * * This method is only available if the agent advertises the `listSessions` capability. * * Returns a list of sessions with metadata like session ID, working directory, * title, and last update time. Supports filtering by working directory and * cursor-based pagination. * * @experimental */ async unstable_listSessions(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_list, params); } /** * **UNSTABLE** * * This capability is not part of the spec yet, and may be removed or changed at any point. * * Resumes an existing session without returning previous messages. * * This method is only available if the agent advertises the `session.resume` capability. * * The agent should resume the session context, allowing the conversation to continue * without replaying the message history (unlike `session/load`). * * @experimental */ async unstable_resumeSession(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_resume, params); } /** * Sets the operational mode for a session. * * Allows switching between different agent modes (e.g., "ask", "architect", "code") * that affect system prompts, tool availability, and permission behaviors. * * The mode must be one of the modes advertised in `availableModes` during session * creation or loading. Agents may also change modes autonomously and notify the * client via `current_mode_update` notifications. * * This method can be called at any time during a session, whether the Agent is * idle or actively generating a turn. * * See protocol docs: [Session Modes](https://agentclientprotocol.com/protocol/session-modes) */ async setSessionMode(params) { return ((await this.#connection.sendRequest(schema.AGENT_METHODS.session_set_mode, params)) ?? {}); } /** * **UNSTABLE** * * This capability is not part of the spec yet, and may be removed or changed at any point. * * Select a model for a given session. * * @experimental */ async unstable_setSessionModel(params) { return ((await this.#connection.sendRequest(schema.AGENT_METHODS.session_set_model, params)) ?? {}); } /** * **UNSTABLE** * * This capability is not part of the spec yet, and may be removed or changed at any point. * * Set a configuration option for a given session. * * The response contains the full set of configuration options and their current values, * as changing one option may affect the available values or state of other options. * * @experimental */ async unstable_setSessionConfigOption(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_set_config_option, params); } /** * Authenticates the client using the specified authentication method. * * Called when the agent requires authentication before allowing session creation. * The client provides the authentication method ID that was advertised during initialization. * * After successful authentication, the client can proceed to create sessions with * `newSession` without receiving an `auth_required` error. * * See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization) */ async authenticate(params) { return ((await this.#connection.sendRequest(schema.AGENT_METHODS.authenticate, params)) ?? {}); } /** * Processes a user prompt within a session. * * This method handles the whole lifecycle of a prompt: * - Receives user messages with optional context (files, images, etc.) * - Processes the prompt using language models * - Reports language model content and tool calls to the Clients * - Requests permission to run tools * - Executes any requested tool calls * - Returns when the turn is complete with a stop reason * * See protocol docs: [Prompt Turn](https://agentclientprotocol.com/protocol/prompt-turn) */ async prompt(params) { return await this.#connection.sendRequest(schema.AGENT_METHODS.session_prompt, params); } /** * Cancels ongoing operations for a session. * * This is a notification sent by the client to cancel an ongoing prompt turn. * * Upon receiving this notification, the Agent SHOULD: * - Stop all language model requests as soon as possible * - Abort all tool call invocations in progress * - Send any pending `session/update` notifications * - Respond to the original `session/prompt` request with `StopReason::Cancelled` * * See protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation) */ async cancel(params) { return await this.#connection.sendNotification(schema.AGENT_METHODS.session_cancel, params); } /** * Extension method * * Allows the Client to send an arbitrary request that is not part of the ACP spec. */ async extMethod(method, params) { return await this.#connection.sendRequest(method, params); } /** * Extension notification * * Allows the Client to send an arbitrary notification that is not part of the ACP spec. */ async extNotification(method, params) { return await this.#connection.sendNotification(method, params); } /** * AbortSignal that aborts when the connection closes. * * This signal can be used to: * - Listen for connection closure: `connection.signal.addEventListener('abort', () => {...})` * - Check connection status synchronously: `if (connection.signal.aborted) {...}` * - Pass to other APIs (fetch, setTimeout) for automatic cancellation * * The connection closes when the underlying stream ends, either normally or due to an error. * * @example * ```typescript * const connection = new ClientSideConnection(client, stream); * * // Listen for closure * connection.signal.addEventListener('abort', () => { * console.log('Connection closed - performing cleanup'); * }); * * // Check status * if (connection.signal.aborted) { * console.log('Connection is already closed'); * } * * // Pass to other APIs * fetch(url, { signal: connection.signal }); * ``` */ get signal() { return this.#connection.signal; } /** * Promise that resolves when the connection closes. * * The connection closes when the underlying stream ends, either normally or due to an error. * Once closed, the connection cannot send or receive any more messages. * * This is useful for async/await style cleanup: * * @example * ```typescript * const connection = new ClientSideConnection(client, stream); * await connection.closed; * console.log('Connection closed - performing cleanup'); * ``` */ get closed() { return this.#connection.closed; } } class Connection { #pendingResponses = new Map(); #nextRequestId = 0; #requestHandler; #notificationHandler; #stream; #writeQueue = Promise.resolve(); #abortController = new AbortController(); #closedPromise; constructor(requestHandler, notificationHandler, stream) { this.#requestHandler = requestHandler; this.#notificationHandler = notificationHandler; this.#stream = stream; this.#closedPromise = new Promise((resolve) => { this.#abortController.signal.addEventListener("abort", () => resolve()); }); this.#receive(); } /** * AbortSignal that aborts when the connection closes. * * This signal can be used to: * - Listen for connection closure via event listeners * - Check connection status synchronously with `signal.aborted` * - Pass to other APIs (fetch, setTimeout) for automatic cancellation */ get signal() { return this.#abortController.signal; } /** * Promise that resolves when the connection closes. * * The connection closes when the underlying stream ends, either normally * or due to an error. Once closed, the connection cannot send or receive * any more messages. * * @example * ```typescript * const connection = new ClientSideConnection(client, stream); * await connection.closed; * console.log('Connection closed - performing cleanup'); * ``` */ get closed() { return this.#closedPromise; } async #receive() { const reader = this.#stream.readable.getReader(); try { while (true) { const { value: message, done } = await reader.read(); if (done) { break; } if (!message) { continue; } try { this.#processMessage(message); } catch (err) { console.error("Unexpected error during message processing:", message, err); // Only send error response if the message had an id (was a request) if ("id" in message && message.id !== undefined) { this.#sendMessage({ jsonrpc: "2.0", id: message.id, error: { code: -32700, message: "Parse error", }, }); } } } } finally { reader.releaseLock(); this.#abortController.abort(); } } async #processMessage(message) { if ("method" in message && "id" in message) { // It's a request const response = await this.#tryCallRequestHandler(message.method, message.params); if ("error" in response) { console.error("Error handling request", message, response.error); } await this.#sendMessage({ jsonrpc: "2.0", id: message.id, ...response, }); } else if ("method" in message) { // It's a notification const response = await this.#tryCallNotificationHandler(message.method, message.params); if ("error" in response) { console.error("Error handling notification", message, response.error); } } else if ("id" in message) { // It's a response this.#handleResponse(message); } else { console.error("Invalid message", { message }); } } async #tryCallRequestHandler(method, params) { try { const result = await this.#requestHandler(method, params); return { result: result ?? null }; } catch (error) { if (error instanceof RequestError) { return error.toResult(); } if (error instanceof z.ZodError) { return RequestError.invalidParams(error.format()).toResult(); } let details; if (error instanceof Error) { details = error.message; } else if (typeof error === "object" && error != null && "message" in error && typeof error.message === "string") { details = error.message; } try { return RequestError.internalError(details ? JSON.parse(details) : {}).toResult(); } catch { return RequestError.internalError({ details }).toResult(); } } } async #tryCallNotificationHandler(method, params) { try { await this.#notificationHandler(method, params); return { result: null }; } catch (error) { if (error instanceof RequestError) { return error.toResult(); } if (error instanceof z.ZodError) { return RequestError.invalidParams(error.format()).toResult(); } let details; if (error instanceof Error) { details = error.message; } else if (typeof error === "object" && error != null && "message" in error && typeof error.message === "string") { details = error.message; } try { return RequestError.internalError(details ? JSON.parse(details) : {}).toResult(); } catch { return RequestError.internalError({ details }).toResult(); } } } #handleResponse(response) { const pendingResponse = this.#pendingResponses.get(response.id); if (pendingResponse) { if ("result" in response) { pendingResponse.resolve(response.result); } else if ("error" in response) { pendingResponse.reject(response.error); } this.#pendingResponses.delete(response.id); } else { console.error("Got response to unknown request", response.id); } } async sendRequest(method, params) { const id = this.#nextRequestId++; const responsePromise = new Promise((resolve, reject) => { this.#pendingResponses.set(id, { resolve, reject }); }); await this.#sendMessage({ jsonrpc: "2.0", id, method, params }); return responsePromise; } async sendNotification(method, params) { await this.#sendMessage({ jsonrpc: "2.0", method, params }); } async #sendMessage(message) { this.#writeQueue = this.#writeQueue .then(async () => { const writer = this.#stream.writable.getWriter(); try { await writer.write(message); } finally { writer.releaseLock(); } }) .catch((error) => { // Continue processing writes on error console.error("ACP write error:", error); }); return this.#writeQueue; } } /** * JSON-RPC error object. * * Represents an error that occurred during method execution, following the * JSON-RPC 2.0 error object specification with optional additional data. * * See protocol docs: [JSON-RPC Error Object](https://www.jsonrpc.org/specification#error_object) */ export class RequestError extends Error { code; data; constructor(code, message, data) { super(message); this.code = code; this.name = "RequestError"; this.data = data; } /** * Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text. */ static parseError(data, additionalMessage) { return new RequestError(-32700, `Parse error${additionalMessage ? `: ${additionalMessage}` : ""}`, data); } /** * The JSON sent is not a valid Request object. */ static invalidRequest(data, additionalMessage) { return new RequestError(-32600, `Invalid request${additionalMessage ? `: ${additionalMessage}` : ""}`, data); } /** * The method does not exist / is not available. */ static methodNotFound(method) { return new RequestError(-32601, `"Method not found": ${method}`, { method, }); } /** * Invalid method parameter(s). */ static invalidParams(data, additionalMessage) { return new RequestError(-32602, `Invalid params${additionalMessage ? `: ${additionalMessage}` : ""}`, data); } /** * Internal JSON-RPC error. */ static internalError(data, additionalMessage) { return new RequestError(-32603, `Internal error${additionalMessage ? `: ${additionalMessage}` : ""}`, data); } /** * Authentication required. */ static authRequired(data, additionalMessage) { return new RequestError(-32000, `Authentication required${additionalMessage ? `: ${additionalMessage}` : ""}`, data); } /** * Resource, such as a file, was not found */ static resourceNotFound(uri) { return new RequestError(-32002, `Resource not found${uri ? `: ${uri}` : ""}`, uri && { uri }); } toResult() { return { error: { code: this.code, message: this.message, data: this.data, }, }; } toErrorResponse() { return { code: this.code, message: this.message, data: this.data, }; } } //# sourceMappingURL=acp.js.map