From d340645372185420bfd4a2dac1bb2960c880c588 Mon Sep 17 00:00:00 2001 From: "Anna.Zhdan" Date: Sun, 29 Mar 2026 11:25:17 +0200 Subject: [PATCH 1/4] feat(schema): Update schema to v0.11.4 Co-Authored-By: Claude Opus 4.6 (1M context) --- schema/meta.json | 10 + schema/schema.json | 1766 ++++++++++++++++++++++++++++++++++++++- scripts/generate.js | 2 +- src/schema/index.ts | 67 ++ src/schema/types.gen.ts | 1326 ++++++++++++++++++++++++++++- src/schema/zod.gen.ts | 787 +++++++++++++++-- 6 files changed, 3819 insertions(+), 139 deletions(-) diff --git a/schema/meta.json b/schema/meta.json index 6198214..167bba2 100644 --- a/schema/meta.json +++ b/schema/meta.json @@ -1,8 +1,18 @@ { "agentMethods": { "authenticate": "authenticate", + "document_did_change": "document/didChange", + "document_did_close": "document/didClose", + "document_did_focus": "document/didFocus", + "document_did_open": "document/didOpen", + "document_did_save": "document/didSave", "initialize": "initialize", "logout": "logout", + "nes_accept": "nes/accept", + "nes_close": "nes/close", + "nes_reject": "nes/reject", + "nes_start": "nes/start", + "nes_suggest": "nes/suggest", "session_cancel": "session/cancel", "session_close": "session/close", "session_fork": "session/fork", diff --git a/schema/schema.json b/schema/schema.json index 081e1a1..0a6fb84 100644 --- a/schema/schema.json +++ b/schema/schema.json @@ -1,5 +1,31 @@ { "$defs": { + "AcceptNesNotification": { + "description": "Notification sent when a suggestion is accepted.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "id": { + "description": "The ID of the accepted suggestion.", + "type": "string" + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + } + }, + "required": ["sessionId", "id"], + "type": "object", + "x-method": "nes/accept", + "x-side": "agent" + }, "AgentAuthCapabilities": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAuthentication-related capabilities supported by the agent.", "properties": { @@ -56,6 +82,28 @@ }, "description": "MCP capabilities supported by the agent." }, + "nes": { + "anyOf": [ + { + "$ref": "#/$defs/NesCapabilities" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nNES (Next Edit Suggestions) capabilities supported by the agent." + }, + "positionEncoding": { + "anyOf": [ + { + "$ref": "#/$defs/PositionEncodingKind" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe position encoding selected by the agent from the client's supported encodings." + }, "promptCapabilities": { "allOf": [ { @@ -357,6 +405,30 @@ ], "title": "SetSessionModelResponse" }, + { + "allOf": [ + { + "$ref": "#/$defs/StartNesResponse" + } + ], + "title": "StartNesResponse" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SuggestNesResponse" + } + ], + "title": "SuggestNesResponse" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CloseNesResponse" + } + ], + "title": "CloseNesResponse" + }, { "allOf": [ { @@ -850,6 +922,24 @@ }, "description": "File system capabilities supported by the client.\nDetermines which file operations the agent can request." }, + "nes": { + "anyOf": [ + { + "$ref": "#/$defs/ClientNesCapabilities" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nNES (Next Edit Suggestions) capabilities supported by the client." + }, + "positionEncodings": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe position encodings supported by the client, in order of preference.", + "items": { + "$ref": "#/$defs/PositionEncodingKind" + }, + "type": "array" + }, "terminal": { "default": false, "description": "Whether the Client support all `terminal/*` methods.", @@ -858,6 +948,50 @@ }, "type": "object" }, + "ClientNesCapabilities": { + "description": "NES capabilities advertised by the client during initialization.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "jump": { + "anyOf": [ + { + "$ref": "#/$defs/NesJumpCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the client supports the `jump` suggestion kind." + }, + "rename": { + "anyOf": [ + { + "$ref": "#/$defs/NesRenameCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the client supports the `rename` suggestion kind." + }, + "searchAndReplace": { + "anyOf": [ + { + "$ref": "#/$defs/NesSearchAndReplaceCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the client supports the `searchAndReplace` suggestion kind." + } + }, + "type": "object" + }, "ClientNotification": { "properties": { "method": { @@ -876,6 +1010,69 @@ "description": "Cancels ongoing operations for a session.\n\nThis is a notification sent by the client to cancel an ongoing prompt turn.\n\nUpon receiving this notification, the Agent SHOULD:\n- Stop all language model requests as soon as possible\n- Abort all tool call invocations in progress\n- Send any pending `session/update` notifications\n- Respond to the original `session/prompt` request with `StopReason::Cancelled`\n\nSee protocol docs: [Cancellation](https://agentclientprotocol.com/protocol/prompt-turn#cancellation)", "title": "CancelNotification" }, + { + "allOf": [ + { + "$ref": "#/$defs/DidOpenDocumentNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a file is opened in the editor.", + "title": "DidOpenDocumentNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DidChangeDocumentNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a file is edited.", + "title": "DidChangeDocumentNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DidCloseDocumentNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a file is closed.", + "title": "DidCloseDocumentNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DidSaveDocumentNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a file is saved.", + "title": "DidSaveDocumentNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/DidFocusDocumentNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a file becomes the active editor tab.", + "title": "DidFocusDocumentNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/AcceptNesNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a suggestion is accepted.", + "title": "AcceptNesNotification" + }, + { + "allOf": [ + { + "$ref": "#/$defs/RejectNesNotification" + } + ], + "description": "**UNSTABLE**\n\nNotification sent when a suggestion is rejected.", + "title": "RejectNesNotification" + }, { "allOf": [ { @@ -1027,6 +1224,33 @@ "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nSelect a model for a given session.", "title": "SetSessionModelRequest" }, + { + "allOf": [ + { + "$ref": "#/$defs/StartNesRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nStarts an NES session.", + "title": "StartNesRequest" + }, + { + "allOf": [ + { + "$ref": "#/$defs/SuggestNesRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nRequests a code suggestion.", + "title": "SuggestNesRequest" + }, + { + "allOf": [ + { + "$ref": "#/$defs/CloseNesRequest" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCloses an active NES session and frees up any resources associated with it.\n\nThe agent must cancel any ongoing work and then free up any resources\nassociated with the NES session.", + "title": "CloseNesRequest" + }, { "allOf": [ { @@ -1162,6 +1386,41 @@ ], "x-docs-ignore": true }, + "CloseNesRequest": { + "description": "Request to close an NES session.\n\nThe agent **must** cancel any ongoing work related to the NES session\nand then free up any resources associated with the session.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The ID of the NES session to close." + } + }, + "required": ["sessionId"], + "type": "object", + "x-method": "nes/close", + "x-side": "agent" + }, + "CloseNesResponse": { + "description": "Response from closing an NES session.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object", + "x-method": "nes/close", + "x-side": "agent" + }, "CloseSessionRequest": { "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nRequest parameters for closing an active session.\n\nIf supported, the agent **must** cancel any ongoing work related to the session\n(treat it as if `session/cancel` was called) and then free up any resources\nassociated with the session.\n\nOnly available if the Agent supports the `session.close` capability.", "properties": { @@ -1452,59 +1711,235 @@ "required": ["currentModeId"], "type": "object" }, - "Diff": { - "description": "A diff representing file modifications.\n\nShows changes to files in a format suitable for display in the client UI.\n\nSee protocol docs: [Content](https://agentclientprotocol.com/protocol/tool-calls#content)", + "DidChangeDocumentNotification": { + "description": "Notification sent when a file is edited.", "properties": { "_meta": { "additionalProperties": true, "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, - "newText": { - "description": "The new content after modification.", - "type": "string" + "contentChanges": { + "description": "The content changes.", + "items": { + "$ref": "#/$defs/TextDocumentContentChangeEvent" + }, + "type": "array" }, - "oldText": { - "description": "The original content (None for new files).", - "type": ["string", "null"] + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." }, - "path": { - "description": "The file path being modified.", + "uri": { + "description": "The URI of the changed document.", "type": "string" + }, + "version": { + "description": "The new version number of the document.", + "format": "int64", + "type": "integer" } }, - "required": ["path", "newText"], - "type": "object" + "required": ["sessionId", "uri", "version", "contentChanges"], + "type": "object", + "x-method": "document/didChange", + "x-side": "agent" }, - "ElicitationAcceptAction": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe user accepted the elicitation and provided content.", + "DidCloseDocumentNotification": { + "description": "Notification sent when a file is closed.", "properties": { - "content": { - "additionalProperties": { - "$ref": "#/$defs/ElicitationContentValue" - }, - "description": "The user-provided content, if any, as an object matching the requested schema.", + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + }, + "uri": { + "description": "The URI of the closed document.", + "type": "string" } }, - "type": "object" + "required": ["sessionId", "uri"], + "type": "object", + "x-method": "document/didClose", + "x-side": "agent" }, - "ElicitationAction": { - "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe user's action in response to an elicitation.", - "discriminator": { - "propertyName": "action" - }, - "oneOf": [ - { + "DidFocusDocumentNotification": { + "description": "Notification sent when a file becomes the active editor tab.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "position": { "allOf": [ { - "$ref": "#/$defs/ElicitationAcceptAction" + "$ref": "#/$defs/Position" } ], - "description": "The user accepted and provided content.", - "properties": { - "action": { - "const": "accept", + "description": "The current cursor position." + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + }, + "uri": { + "description": "The URI of the focused document.", + "type": "string" + }, + "version": { + "description": "The version number of the document.", + "format": "int64", + "type": "integer" + }, + "visibleRange": { + "allOf": [ + { + "$ref": "#/$defs/Range" + } + ], + "description": "The portion of the file currently visible in the editor viewport." + } + }, + "required": ["sessionId", "uri", "version", "position", "visibleRange"], + "type": "object", + "x-method": "document/didFocus", + "x-side": "agent" + }, + "DidOpenDocumentNotification": { + "description": "Notification sent when a file is opened in the editor.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "languageId": { + "description": "The language identifier of the document (e.g., \"rust\", \"python\").", + "type": "string" + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + }, + "text": { + "description": "The full text content of the document.", + "type": "string" + }, + "uri": { + "description": "The URI of the opened document.", + "type": "string" + }, + "version": { + "description": "The version number of the document.", + "format": "int64", + "type": "integer" + } + }, + "required": ["sessionId", "uri", "languageId", "version", "text"], + "type": "object", + "x-method": "document/didOpen", + "x-side": "agent" + }, + "DidSaveDocumentNotification": { + "description": "Notification sent when a file is saved.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + }, + "uri": { + "description": "The URI of the saved document.", + "type": "string" + } + }, + "required": ["sessionId", "uri"], + "type": "object", + "x-method": "document/didSave", + "x-side": "agent" + }, + "Diff": { + "description": "A diff representing file modifications.\n\nShows changes to files in a format suitable for display in the client UI.\n\nSee protocol docs: [Content](https://agentclientprotocol.com/protocol/tool-calls#content)", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "newText": { + "description": "The new content after modification.", + "type": "string" + }, + "oldText": { + "description": "The original content (None for new files).", + "type": ["string", "null"] + }, + "path": { + "description": "The file path being modified.", + "type": "string" + } + }, + "required": ["path", "newText"], + "type": "object" + }, + "ElicitationAcceptAction": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe user accepted the elicitation and provided content.", + "properties": { + "content": { + "additionalProperties": { + "$ref": "#/$defs/ElicitationContentValue" + }, + "description": "The user-provided content, if any, as an object matching the requested schema.", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "ElicitationAction": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nThe user's action in response to an elicitation.", + "discriminator": { + "propertyName": "action" + }, + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/ElicitationAcceptAction" + } + ], + "description": "The user accepted and provided content.", + "properties": { + "action": { + "const": "accept", "type": "string" } }, @@ -2126,6 +2561,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAdditional workspace roots to activate for this session. Each path must be absolute.\n\nWhen omitted or empty, no additional roots are activated. When non-empty,\nthis is the complete resulting additional-root list for the forked\nsession.", + "items": { + "type": "string" + }, + "type": "array" + }, "cwd": { "description": "The working directory for this session.", "type": "string" @@ -2467,6 +2909,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nFilter sessions by the exact ordered additional workspace roots. Each path must be absolute.\n\nThis filter applies only when the field is present and non-empty. When\nomitted or empty, no additional-root filter is applied.", + "items": { + "type": "string" + }, + "type": "array" + }, "cursor": { "description": "Opaque cursor token from a previous response's nextCursor field for cursor-based pagination", "type": ["string", "null"] @@ -2513,6 +2962,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAdditional workspace roots to activate for this session. Each path must be absolute.\n\nWhen omitted or empty, no additional roots are activated. When non-empty,\nthis is the complete resulting additional-root list for the loaded\nsession.", + "items": { + "type": "string" + }, + "type": "array" + }, "cwd": { "description": "The working directory for this session.", "type": "string" @@ -2855,18 +3311,907 @@ "minimum": 0, "type": ["integer", "null"] }, - "minItems": { - "description": "Minimum number of items to select.", - "format": "uint64", + "minItems": { + "description": "Minimum number of items to select.", + "format": "uint64", + "minimum": 0, + "type": ["integer", "null"] + }, + "title": { + "description": "Optional title for the property.", + "type": ["string", "null"] + } + }, + "required": ["items"], + "type": "object" + }, + "NesCapabilities": { + "description": "NES capabilities advertised by the agent during initialization.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "context": { + "anyOf": [ + { + "$ref": "#/$defs/NesContextCapabilities" + }, + { + "type": "null" + } + ], + "description": "Context the agent wants attached to each suggestion request." + }, + "events": { + "anyOf": [ + { + "$ref": "#/$defs/NesEventCapabilities" + }, + { + "type": "null" + } + ], + "description": "Events the agent wants to receive." + } + }, + "type": "object" + }, + "NesContextCapabilities": { + "description": "Context capabilities the agent wants attached to each suggestion request.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "diagnostics": { + "anyOf": [ + { + "$ref": "#/$defs/NesDiagnosticsCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants diagnostics context." + }, + "editHistory": { + "anyOf": [ + { + "$ref": "#/$defs/NesEditHistoryCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants edit history context." + }, + "openFiles": { + "anyOf": [ + { + "$ref": "#/$defs/NesOpenFilesCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants open files context." + }, + "recentFiles": { + "anyOf": [ + { + "$ref": "#/$defs/NesRecentFilesCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants recent files context." + }, + "relatedSnippets": { + "anyOf": [ + { + "$ref": "#/$defs/NesRelatedSnippetsCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants related snippets context." + }, + "userActions": { + "anyOf": [ + { + "$ref": "#/$defs/NesUserActionsCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants user actions context." + } + }, + "type": "object" + }, + "NesDiagnostic": { + "description": "A diagnostic (error, warning, etc.).", + "properties": { + "message": { + "description": "The diagnostic message.", + "type": "string" + }, + "range": { + "allOf": [ + { + "$ref": "#/$defs/Range" + } + ], + "description": "The range of the diagnostic." + }, + "severity": { + "allOf": [ + { + "$ref": "#/$defs/NesDiagnosticSeverity" + } + ], + "description": "The severity of the diagnostic." + }, + "uri": { + "description": "The URI of the file containing the diagnostic.", + "type": "string" + } + }, + "required": ["uri", "range", "severity", "message"], + "type": "object" + }, + "NesDiagnosticSeverity": { + "description": "Severity of a diagnostic.", + "oneOf": [ + { + "const": "error", + "description": "An error.", + "type": "string" + }, + { + "const": "warning", + "description": "A warning.", + "type": "string" + }, + { + "const": "information", + "description": "An informational message.", + "type": "string" + }, + { + "const": "hint", + "description": "A hint.", + "type": "string" + } + ] + }, + "NesDiagnosticsCapabilities": { + "description": "Capabilities for diagnostics context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesDocumentDidChangeCapabilities": { + "description": "Capabilities for `document/didChange` events.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "syncKind": { + "allOf": [ + { + "$ref": "#/$defs/TextDocumentSyncKind" + } + ], + "description": "The sync kind the agent wants: `\"full\"` or `\"incremental\"`." + } + }, + "required": ["syncKind"], + "type": "object" + }, + "NesDocumentDidCloseCapabilities": { + "description": "Marker for `document/didClose` capability support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesDocumentDidFocusCapabilities": { + "description": "Marker for `document/didFocus` capability support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesDocumentDidOpenCapabilities": { + "description": "Marker for `document/didOpen` capability support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesDocumentDidSaveCapabilities": { + "description": "Marker for `document/didSave` capability support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesDocumentEventCapabilities": { + "description": "Document event capabilities the agent wants to receive.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "didChange": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentDidChangeCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants `document/didChange` events, and the sync kind." + }, + "didClose": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentDidCloseCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants `document/didClose` events." + }, + "didFocus": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentDidFocusCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants `document/didFocus` events." + }, + "didOpen": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentDidOpenCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants `document/didOpen` events." + }, + "didSave": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentDidSaveCapabilities" + }, + { + "type": "null" + } + ], + "description": "Whether the agent wants `document/didSave` events." + } + }, + "type": "object" + }, + "NesEditHistoryCapabilities": { + "description": "Capabilities for edit history context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "maxCount": { + "description": "Maximum number of edit history entries the agent can use.", + "format": "uint32", + "minimum": 0, + "type": ["integer", "null"] + } + }, + "type": "object" + }, + "NesEditHistoryEntry": { + "description": "An entry in the edit history.", + "properties": { + "diff": { + "description": "A diff representing the edit.", + "type": "string" + }, + "uri": { + "description": "The URI of the edited file.", + "type": "string" + } + }, + "required": ["uri", "diff"], + "type": "object" + }, + "NesEditSuggestion": { + "description": "A text edit suggestion.", + "properties": { + "cursorPosition": { + "anyOf": [ + { + "$ref": "#/$defs/Position" + }, + { + "type": "null" + } + ], + "description": "Optional suggested cursor position after applying edits." + }, + "edits": { + "description": "The text edits to apply.", + "items": { + "$ref": "#/$defs/NesTextEdit" + }, + "type": "array" + }, + "id": { + "description": "Unique identifier for accept/reject tracking.", + "type": "string" + }, + "uri": { + "description": "The URI of the file to edit.", + "type": "string" + } + }, + "required": ["id", "uri", "edits"], + "type": "object" + }, + "NesEventCapabilities": { + "description": "Event capabilities the agent can consume.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "document": { + "anyOf": [ + { + "$ref": "#/$defs/NesDocumentEventCapabilities" + }, + { + "type": "null" + } + ], + "description": "Document event capabilities." + } + }, + "type": "object" + }, + "NesExcerpt": { + "description": "A code excerpt from a file.", + "properties": { + "endLine": { + "description": "The end line of the excerpt (zero-based).", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "startLine": { + "description": "The start line of the excerpt (zero-based).", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "text": { + "description": "The text content of the excerpt.", + "type": "string" + } + }, + "required": ["startLine", "endLine", "text"], + "type": "object" + }, + "NesJumpCapabilities": { + "description": "Marker for jump suggestion support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesJumpSuggestion": { + "description": "A jump-to-location suggestion.", + "properties": { + "id": { + "description": "Unique identifier for accept/reject tracking.", + "type": "string" + }, + "position": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The target position within the file." + }, + "uri": { + "description": "The file to navigate to.", + "type": "string" + } + }, + "required": ["id", "uri", "position"], + "type": "object" + }, + "NesOpenFile": { + "description": "An open file in the editor.", + "properties": { + "languageId": { + "description": "The language identifier.", + "type": "string" + }, + "lastFocusedMs": { + "description": "Timestamp in milliseconds since epoch of when the file was last focused.", + "format": "uint64", + "minimum": 0, + "type": ["integer", "null"] + }, + "uri": { + "description": "The URI of the file.", + "type": "string" + }, + "visibleRange": { + "anyOf": [ + { + "$ref": "#/$defs/Range" + }, + { + "type": "null" + } + ], + "description": "The visible range in the editor, if any." + } + }, + "required": ["uri", "languageId"], + "type": "object" + }, + "NesOpenFilesCapabilities": { + "description": "Capabilities for open files context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesRecentFile": { + "description": "A recently accessed file.", + "properties": { + "languageId": { + "description": "The language identifier.", + "type": "string" + }, + "text": { + "description": "The full text content of the file.", + "type": "string" + }, + "uri": { + "description": "The URI of the file.", + "type": "string" + } + }, + "required": ["uri", "languageId", "text"], + "type": "object" + }, + "NesRecentFilesCapabilities": { + "description": "Capabilities for recent files context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "maxCount": { + "description": "Maximum number of recent files the agent can use.", + "format": "uint32", + "minimum": 0, + "type": ["integer", "null"] + } + }, + "type": "object" + }, + "NesRejectReason": { + "description": "The reason a suggestion was rejected.", + "oneOf": [ + { + "const": "rejected", + "description": "The user explicitly dismissed the suggestion.", + "type": "string" + }, + { + "const": "ignored", + "description": "The suggestion was shown but the user continued editing without interacting.", + "type": "string" + }, + { + "const": "replaced", + "description": "The suggestion was superseded by a newer suggestion.", + "type": "string" + }, + { + "const": "cancelled", + "description": "The request was cancelled before the agent returned a response.", + "type": "string" + } + ] + }, + "NesRelatedSnippet": { + "description": "A related code snippet from a file.", + "properties": { + "excerpts": { + "description": "The code excerpts.", + "items": { + "$ref": "#/$defs/NesExcerpt" + }, + "type": "array" + }, + "uri": { + "description": "The URI of the file containing the snippets.", + "type": "string" + } + }, + "required": ["uri", "excerpts"], + "type": "object" + }, + "NesRelatedSnippetsCapabilities": { + "description": "Capabilities for related snippets context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesRenameCapabilities": { + "description": "Marker for rename suggestion support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesRenameSuggestion": { + "description": "A rename symbol suggestion.", + "properties": { + "id": { + "description": "Unique identifier for accept/reject tracking.", + "type": "string" + }, + "newName": { + "description": "The new name for the symbol.", + "type": "string" + }, + "position": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The position of the symbol to rename." + }, + "uri": { + "description": "The file URI containing the symbol.", + "type": "string" + } + }, + "required": ["id", "uri", "position", "newName"], + "type": "object" + }, + "NesRepository": { + "description": "Repository metadata for an NES session.", + "properties": { + "name": { + "description": "The repository name.", + "type": "string" + }, + "owner": { + "description": "The repository owner.", + "type": "string" + }, + "remoteUrl": { + "description": "The remote URL of the repository.", + "type": "string" + } + }, + "required": ["name", "owner", "remoteUrl"], + "type": "object" + }, + "NesSearchAndReplaceCapabilities": { + "description": "Marker for search and replace suggestion support.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, + "NesSearchAndReplaceSuggestion": { + "description": "A search-and-replace suggestion.", + "properties": { + "id": { + "description": "Unique identifier for accept/reject tracking.", + "type": "string" + }, + "isRegex": { + "description": "Whether `search` is a regular expression. Defaults to `false`.", + "type": ["boolean", "null"] + }, + "replace": { + "description": "The replacement text.", + "type": "string" + }, + "search": { + "description": "The text or pattern to find.", + "type": "string" + }, + "uri": { + "description": "The file URI to search within.", + "type": "string" + } + }, + "required": ["id", "uri", "search", "replace"], + "type": "object" + }, + "NesSuggestContext": { + "description": "Context attached to a suggestion request.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "diagnostics": { + "description": "Current diagnostics (errors, warnings).", + "items": { + "$ref": "#/$defs/NesDiagnostic" + }, + "type": ["array", "null"] + }, + "editHistory": { + "description": "Recent edit history.", + "items": { + "$ref": "#/$defs/NesEditHistoryEntry" + }, + "type": ["array", "null"] + }, + "openFiles": { + "description": "Currently open files in the editor.", + "items": { + "$ref": "#/$defs/NesOpenFile" + }, + "type": ["array", "null"] + }, + "recentFiles": { + "description": "Recently accessed files.", + "items": { + "$ref": "#/$defs/NesRecentFile" + }, + "type": ["array", "null"] + }, + "relatedSnippets": { + "description": "Related code snippets.", + "items": { + "$ref": "#/$defs/NesRelatedSnippet" + }, + "type": ["array", "null"] + }, + "userActions": { + "description": "Recent user actions (typing, navigation, etc.).", + "items": { + "$ref": "#/$defs/NesUserAction" + }, + "type": ["array", "null"] + } + }, + "type": "object" + }, + "NesSuggestion": { + "description": "A suggestion returned by the agent.", + "discriminator": { + "propertyName": "kind" + }, + "oneOf": [ + { + "allOf": [ + { + "$ref": "#/$defs/NesEditSuggestion" + } + ], + "description": "A text edit suggestion.", + "properties": { + "kind": { + "const": "edit", + "type": "string" + } + }, + "required": ["kind"], + "type": "object" + }, + { + "allOf": [ + { + "$ref": "#/$defs/NesJumpSuggestion" + } + ], + "description": "A jump-to-location suggestion.", + "properties": { + "kind": { + "const": "jump", + "type": "string" + } + }, + "required": ["kind"], + "type": "object" + }, + { + "allOf": [ + { + "$ref": "#/$defs/NesRenameSuggestion" + } + ], + "description": "A rename symbol suggestion.", + "properties": { + "kind": { + "const": "rename", + "type": "string" + } + }, + "required": ["kind"], + "type": "object" + }, + { + "allOf": [ + { + "$ref": "#/$defs/NesSearchAndReplaceSuggestion" + } + ], + "description": "A search-and-replace suggestion.", + "properties": { + "kind": { + "const": "searchAndReplace", + "type": "string" + } + }, + "required": ["kind"], + "type": "object" + } + ] + }, + "NesTextEdit": { + "description": "A text edit within a suggestion.", + "properties": { + "newText": { + "description": "The replacement text.", + "type": "string" + }, + "range": { + "allOf": [ + { + "$ref": "#/$defs/Range" + } + ], + "description": "The range to replace." + } + }, + "required": ["range", "newText"], + "type": "object" + }, + "NesTriggerKind": { + "description": "What triggered the suggestion request.", + "oneOf": [ + { + "const": "automatic", + "description": "Triggered by user typing or cursor movement.", + "type": "string" + }, + { + "const": "diagnostic", + "description": "Triggered by a diagnostic appearing at or near the cursor.", + "type": "string" + }, + { + "const": "manual", + "description": "Triggered by an explicit user action (keyboard shortcut).", + "type": "string" + } + ] + }, + "NesUserAction": { + "description": "A user action (typing, cursor movement, etc.).", + "properties": { + "action": { + "description": "The kind of action (e.g., \"insertChar\", \"cursorMovement\").", + "type": "string" + }, + "position": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The position where the action occurred." + }, + "timestampMs": { + "description": "Timestamp in milliseconds since epoch.", + "format": "uint64", + "minimum": 0, + "type": "integer" + }, + "uri": { + "description": "The URI of the file where the action occurred.", + "type": "string" + } + }, + "required": ["action", "uri", "position", "timestampMs"], + "type": "object" + }, + "NesUserActionsCapabilities": { + "description": "Capabilities for user actions context.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "maxCount": { + "description": "Maximum number of user actions the agent can use.", + "format": "uint32", "minimum": 0, "type": ["integer", "null"] - }, - "title": { - "description": "Optional title for the property.", - "type": ["string", "null"] } }, - "required": ["items"], "type": "object" }, "NewSessionRequest": { @@ -2877,6 +4222,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAdditional workspace roots for this session. Each path must be absolute.\n\nThese expand the session's filesystem scope without changing `cwd`, which\nremains the base for relative paths. When omitted or empty, no\nadditional roots are activated for the new session.", + "items": { + "type": "string" + }, + "type": "array" + }, "cwd": { "description": "The working directory for this session. Must be an absolute path.", "type": "string" @@ -3126,6 +4478,45 @@ } ] }, + "Position": { + "description": "A zero-based position in a text document.\n\nThe meaning of `character` depends on the negotiated position encoding.", + "properties": { + "character": { + "description": "Zero-based character offset (encoding-dependent).", + "format": "uint32", + "minimum": 0, + "type": "integer" + }, + "line": { + "description": "Zero-based line number.", + "format": "uint32", + "minimum": 0, + "type": "integer" + } + }, + "required": ["line", "character"], + "type": "object" + }, + "PositionEncodingKind": { + "description": "The encoding used for character offsets in positions.\n\nFollows the same conventions as LSP 3.17. The default is UTF-16.", + "oneOf": [ + { + "const": "utf-16", + "description": "Character offsets count UTF-16 code units. This is the default.", + "type": "string" + }, + { + "const": "utf-32", + "description": "Character offsets count Unicode code points.", + "type": "string" + }, + { + "const": "utf-8", + "description": "Character offsets count UTF-8 code units (bytes).", + "type": "string" + } + ] + }, "PromptCapabilities": { "description": "Prompt capabilities supported by the agent in `session/prompt` requests.\n\nBaseline agent functionality requires support for [`ContentBlock::Text`]\nand [`ContentBlock::ResourceLink`] in prompt requests.\n\nOther variants must be explicitly opted in to.\nCapabilities for different types of content in prompt requests.\n\nIndicates which content types beyond the baseline (text and resource links)\nthe agent can process.\n\nSee protocol docs: [Prompt Capabilities](https://agentclientprotocol.com/protocol/initialization#prompt-capabilities)", "properties": { @@ -3229,6 +4620,29 @@ "minimum": 0, "type": "integer" }, + "Range": { + "description": "A range in a text document, expressed as start and end positions.", + "properties": { + "end": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The end position (exclusive)." + }, + "start": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The start position (inclusive)." + } + }, + "required": ["start", "end"], + "type": "object" + }, "ReadTextFileRequest": { "description": "Request to read content from a text file.\n\nOnly available if the client supports the `fs.readTextFile` capability.", "properties": { @@ -3284,6 +4698,43 @@ "x-method": "fs/read_text_file", "x-side": "client" }, + "RejectNesNotification": { + "description": "Notification sent when a suggestion is rejected.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "id": { + "description": "The ID of the rejected suggestion.", + "type": "string" + }, + "reason": { + "anyOf": [ + { + "$ref": "#/$defs/NesRejectReason" + }, + { + "type": "null" + } + ], + "description": "The reason for rejection." + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this notification." + } + }, + "required": ["sessionId", "id"], + "type": "object", + "x-method": "nes/reject", + "x-side": "agent" + }, "ReleaseTerminalRequest": { "description": "Request to release a terminal and free its resources.", "properties": { @@ -3484,6 +4935,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAdditional workspace roots to activate for this session. Each path must be absolute.\n\nWhen omitted or empty, no additional roots are activated. When non-empty,\nthis is the complete resulting additional-root list for the resumed\nsession.", + "items": { + "type": "string" + }, + "type": "array" + }, "cwd": { "description": "The working directory for this session.", "type": "string" @@ -3576,6 +5034,17 @@ "required": ["optionId"], "type": "object" }, + "SessionAdditionalDirectoriesCapabilities": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nCapabilities for additional session directories support.\n\nBy supplying `{}` it means that the agent supports the `additionalDirectories` field on\nsupported session lifecycle requests and `session/list`.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + } + }, + "type": "object" + }, "SessionCapabilities": { "description": "Session capabilities supported by the agent.\n\nAs a baseline, all Agents **MUST** support `session/new`, `session/prompt`, `session/cancel`, and `session/update`.\n\nOptionally, they **MAY** support other session methods and notifications by specifying additional capabilities.\n\nNote: `session/load` is still handled by the top-level `load_session` capability. This will be unified in future versions of the protocol.\n\nSee protocol docs: [Session Capabilities](https://agentclientprotocol.com/protocol/initialization#session-capabilities)", "properties": { @@ -3584,6 +5053,17 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "anyOf": [ + { + "$ref": "#/$defs/SessionAdditionalDirectoriesCapabilities" + }, + { + "type": "null" + } + ], + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nWhether the agent supports `additionalDirectories` on supported session lifecycle requests and `session/list`." + }, "close": { "anyOf": [ { @@ -3892,6 +5372,13 @@ "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", "type": ["object", "null"] }, + "additionalDirectories": { + "description": "**UNSTABLE**\n\nThis capability is not part of the spec yet, and may be removed or changed at any point.\n\nAuthoritative ordered additional workspace roots for this session. Each path must be absolute.\n\nWhen omitted or empty, there are no additional roots for the session.", + "items": { + "type": "string" + }, + "type": "array" + }, "cwd": { "description": "The working directory for this session. Must be an absolute path.", "type": "string" @@ -4420,6 +5907,63 @@ "x-method": "session/set_model", "x-side": "agent" }, + "StartNesRequest": { + "description": "Request to start an NES session.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "repository": { + "anyOf": [ + { + "$ref": "#/$defs/NesRepository" + }, + { + "type": "null" + } + ], + "description": "Repository metadata, if the workspace is a git repository." + }, + "workspaceFolders": { + "description": "The workspace folders.", + "items": { + "$ref": "#/$defs/WorkspaceFolder" + }, + "type": ["array", "null"] + }, + "workspaceUri": { + "description": "The root URI of the workspace.", + "type": ["string", "null"] + } + }, + "type": "object", + "x-method": "nes/start", + "x-side": "agent" + }, + "StartNesResponse": { + "description": "Response to `nes/start`.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for the newly started NES session." + } + }, + "required": ["sessionId"], + "type": "object", + "x-method": "nes/start", + "x-side": "agent" + }, "StopReason": { "description": "Reasons why an agent stops processing a prompt turn.\n\nSee protocol docs: [Stop Reasons](https://agentclientprotocol.com/protocol/prompt-turn#stop-reasons)", "oneOf": [ @@ -4534,6 +6078,96 @@ }, "type": "object" }, + "SuggestNesRequest": { + "description": "Request for a code suggestion.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "context": { + "anyOf": [ + { + "$ref": "#/$defs/NesSuggestContext" + }, + { + "type": "null" + } + ], + "description": "Context for the suggestion, included based on agent capabilities." + }, + "position": { + "allOf": [ + { + "$ref": "#/$defs/Position" + } + ], + "description": "The current cursor position." + }, + "selection": { + "anyOf": [ + { + "$ref": "#/$defs/Range" + }, + { + "type": "null" + } + ], + "description": "The current text selection range, if any." + }, + "sessionId": { + "allOf": [ + { + "$ref": "#/$defs/SessionId" + } + ], + "description": "The session ID for this request." + }, + "triggerKind": { + "allOf": [ + { + "$ref": "#/$defs/NesTriggerKind" + } + ], + "description": "What triggered this suggestion request." + }, + "uri": { + "description": "The URI of the document to suggest for.", + "type": "string" + }, + "version": { + "description": "The version number of the document.", + "format": "int64", + "type": "integer" + } + }, + "required": ["sessionId", "uri", "version", "position", "triggerKind"], + "type": "object", + "x-method": "nes/suggest", + "x-side": "agent" + }, + "SuggestNesResponse": { + "description": "Response to `nes/suggest`.", + "properties": { + "_meta": { + "additionalProperties": true, + "description": "The _meta property is reserved by ACP to allow clients and agents to attach additional\nmetadata to their interactions. Implementations MUST NOT make assumptions about values at\nthese keys.\n\nSee protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility)", + "type": ["object", "null"] + }, + "suggestions": { + "description": "The list of suggestions.", + "items": { + "$ref": "#/$defs/NesSuggestion" + }, + "type": "array" + } + }, + "required": ["suggestions"], + "type": "object", + "x-method": "nes/suggest", + "x-side": "agent" + }, "Terminal": { "description": "Embed a terminal created with `terminal/create` by its id.\n\nThe terminal must be added before calling `terminal/release`.\n\nSee protocol docs: [Terminal](https://agentclientprotocol.com/protocol/terminals)", "properties": { @@ -4654,6 +6288,43 @@ "required": ["text"], "type": "object" }, + "TextDocumentContentChangeEvent": { + "description": "A content change event for a document.\n\nWhen `range` is `None`, `text` is the full content of the document.\nWhen `range` is `Some`, `text` replaces the given range.", + "properties": { + "range": { + "anyOf": [ + { + "$ref": "#/$defs/Range" + }, + { + "type": "null" + } + ], + "description": "The range of the document that changed. If `None`, the entire content is replaced." + }, + "text": { + "description": "The new text for the range, or the full document content if `range` is `None`.", + "type": "string" + } + }, + "required": ["text"], + "type": "object" + }, + "TextDocumentSyncKind": { + "description": "How the agent wants document changes delivered.", + "oneOf": [ + { + "const": "full", + "description": "Client sends the entire file content on each change.", + "type": "string" + }, + { + "const": "incremental", + "description": "Client sends only the changed ranges.", + "type": "string" + } + ] + }, "TextResourceContents": { "description": "Text-based resource contents.", "properties": { @@ -5142,6 +6813,21 @@ "x-method": "terminal/wait_for_exit", "x-side": "client" }, + "WorkspaceFolder": { + "description": "A workspace folder.", + "properties": { + "name": { + "description": "The display name of the folder.", + "type": "string" + }, + "uri": { + "description": "The URI of the folder.", + "type": "string" + } + }, + "required": ["uri", "name"], + "type": "object" + }, "WriteTextFileRequest": { "description": "Request to write content to a text file.\n\nOnly available if the client supports the `fs.writeTextFile` capability.", "properties": { diff --git a/scripts/generate.js b/scripts/generate.js index 975edc6..b905a43 100644 --- a/scripts/generate.js +++ b/scripts/generate.js @@ -5,7 +5,7 @@ import * as fs from "fs/promises"; import { dirname } from "path"; import * as prettier from "prettier"; -const CURRENT_SCHEMA_RELEASE = "v0.11.3"; +const CURRENT_SCHEMA_RELEASE = "v0.11.4"; await main(); diff --git a/src/schema/index.ts b/src/schema/index.ts index 797fb91..27799f4 100644 --- a/src/schema/index.ts +++ b/src/schema/index.ts @@ -1,6 +1,7 @@ // This file is auto-generated by @hey-api/openapi-ts export type { + AcceptNesNotification, AgentAuthCapabilities, AgentCapabilities, AgentNotification, @@ -24,9 +25,12 @@ export type { CancelNotification, CancelRequestNotification, ClientCapabilities, + ClientNesCapabilities, ClientNotification, ClientRequest, ClientResponse, + CloseNesRequest, + CloseNesResponse, CloseSessionRequest, CloseSessionResponse, ConfigOptionUpdate, @@ -37,6 +41,11 @@ export type { CreateTerminalRequest, CreateTerminalResponse, CurrentModeUpdate, + DidChangeDocumentNotification, + DidCloseDocumentNotification, + DidFocusDocumentNotification, + DidOpenDocumentNotification, + DidSaveDocumentNotification, Diff, ElicitationAcceptAction, ElicitationAction, @@ -90,6 +99,42 @@ export type { ModelInfo, MultiSelectItems, MultiSelectPropertySchema, + NesCapabilities, + NesContextCapabilities, + NesDiagnostic, + NesDiagnosticsCapabilities, + NesDiagnosticSeverity, + NesDocumentDidChangeCapabilities, + NesDocumentDidCloseCapabilities, + NesDocumentDidFocusCapabilities, + NesDocumentDidOpenCapabilities, + NesDocumentDidSaveCapabilities, + NesDocumentEventCapabilities, + NesEditHistoryCapabilities, + NesEditHistoryEntry, + NesEditSuggestion, + NesEventCapabilities, + NesExcerpt, + NesJumpCapabilities, + NesJumpSuggestion, + NesOpenFile, + NesOpenFilesCapabilities, + NesRecentFile, + NesRecentFilesCapabilities, + NesRejectReason, + NesRelatedSnippet, + NesRelatedSnippetsCapabilities, + NesRenameCapabilities, + NesRenameSuggestion, + NesRepository, + NesSearchAndReplaceCapabilities, + NesSearchAndReplaceSuggestion, + NesSuggestContext, + NesSuggestion, + NesTextEdit, + NesTriggerKind, + NesUserAction, + NesUserActionsCapabilities, NewSessionRequest, NewSessionResponse, NumberPropertySchema, @@ -100,12 +145,16 @@ export type { PlanEntry, PlanEntryPriority, PlanEntryStatus, + Position, + PositionEncodingKind, PromptCapabilities, PromptRequest, PromptResponse, ProtocolVersion, + Range, ReadTextFileRequest, ReadTextFileResponse, + RejectNesNotification, ReleaseTerminalRequest, ReleaseTerminalResponse, RequestId, @@ -117,6 +166,7 @@ export type { ResumeSessionResponse, Role, SelectedPermissionOutcome, + SessionAdditionalDirectoriesCapabilities, SessionCapabilities, SessionCloseCapabilities, SessionConfigBoolean, @@ -147,14 +197,20 @@ export type { SetSessionModelResponse, SetSessionModeRequest, SetSessionModeResponse, + StartNesRequest, + StartNesResponse, StopReason, StringFormat, StringPropertySchema, + SuggestNesRequest, + SuggestNesResponse, Terminal, TerminalExitStatus, TerminalOutputRequest, TerminalOutputResponse, TextContent, + TextDocumentContentChangeEvent, + TextDocumentSyncKind, TextResourceContents, TitledMultiSelectItems, ToolCall, @@ -170,14 +226,25 @@ export type { UsageUpdate, WaitForTerminalExitRequest, WaitForTerminalExitResponse, + WorkspaceFolder, WriteTextFileRequest, WriteTextFileResponse, } from "./types.gen"; export const AGENT_METHODS = { authenticate: "authenticate", + document_did_change: "document/didChange", + document_did_close: "document/didClose", + document_did_focus: "document/didFocus", + document_did_open: "document/didOpen", + document_did_save: "document/didSave", initialize: "initialize", logout: "logout", + nes_accept: "nes/accept", + nes_close: "nes/close", + nes_reject: "nes/reject", + nes_start: "nes/start", + nes_suggest: "nes/suggest", session_cancel: "session/cancel", session_close: "session/close", session_fork: "session/fork", diff --git a/src/schema/types.gen.ts b/src/schema/types.gen.ts index 5a07c7b..70ccd2c 100644 --- a/src/schema/types.gen.ts +++ b/src/schema/types.gen.ts @@ -5,6 +5,30 @@ type ClientOptions = { baseUrl: `${string}://${string}` | (string & {}); }; +/** + * Notification sent when a suggestion is accepted. + */ +export type AcceptNesNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The ID of the accepted suggestion. + */ + id: string; + /** + * The session ID for this notification. + */ + sessionId: SessionId; +}; + /** * **UNSTABLE** * @@ -70,6 +94,26 @@ export type AgentCapabilities = { * MCP capabilities supported by the agent. */ mcpCapabilities?: McpCapabilities; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * NES (Next Edit Suggestions) capabilities supported by the agent. + * + * @experimental + */ + nes?: NesCapabilities | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * The position encoding selected by the agent from the client's supported encodings. + * + * @experimental + */ + positionEncoding?: PositionEncodingKind | null; /** * Prompt capabilities supported by the agent. */ @@ -128,6 +172,9 @@ export type AgentResponse = | SetSessionConfigOptionResponse | PromptResponse | SetSessionModelResponse + | StartNesResponse + | SuggestNesResponse + | CloseNesResponse | ExtResponse; } | { @@ -611,15 +658,73 @@ export type ClientCapabilities = { * Determines which file operations the agent can request. */ fs?: FileSystemCapabilities; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * NES (Next Edit Suggestions) capabilities supported by the client. + * + * @experimental + */ + nes?: ClientNesCapabilities | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * The position encodings supported by the client, in order of preference. + * + * @experimental + */ + positionEncodings?: Array; /** * Whether the Client support all `terminal*` methods. */ terminal?: boolean; }; +/** + * NES capabilities advertised by the client during initialization. + */ +export type ClientNesCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Whether the client supports the `jump` suggestion kind. + */ + jump?: NesJumpCapabilities | null; + /** + * Whether the client supports the `rename` suggestion kind. + */ + rename?: NesRenameCapabilities | null; + /** + * Whether the client supports the `searchAndReplace` suggestion kind. + */ + searchAndReplace?: NesSearchAndReplaceCapabilities | null; +}; + export type ClientNotification = { method: string; - params?: CancelNotification | ExtNotification | null; + params?: + | CancelNotification + | DidOpenDocumentNotification + | DidChangeDocumentNotification + | DidCloseDocumentNotification + | DidSaveDocumentNotification + | DidFocusDocumentNotification + | AcceptNesNotification + | RejectNesNotification + | ExtNotification + | null; }; export type ClientRequest = { @@ -639,6 +744,9 @@ export type ClientRequest = { | SetSessionConfigOptionRequest | PromptRequest | SetSessionModelRequest + | StartNesRequest + | SuggestNesRequest + | CloseNesRequest | ExtRequest | null; }; @@ -671,6 +779,45 @@ export type ClientResponse = id: RequestId; }; +/** + * Request to close an NES session. + * + * The agent **must** cancel any ongoing work related to the NES session + * and then free up any resources associated with the session. + */ +export type CloseNesRequest = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The ID of the NES session to close. + */ + sessionId: SessionId; +}; + +/** + * Response from closing an NES session. + */ +export type CloseNesResponse = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + /** * **UNSTABLE** * @@ -941,6 +1088,158 @@ export type CurrentModeUpdate = { currentModeId: SessionModeId; }; +/** + * Notification sent when a file is edited. + */ +export type DidChangeDocumentNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The content changes. + */ + contentChanges: Array; + /** + * The session ID for this notification. + */ + sessionId: SessionId; + /** + * The URI of the changed document. + */ + uri: string; + /** + * The new version number of the document. + */ + version: number; +}; + +/** + * Notification sent when a file is closed. + */ +export type DidCloseDocumentNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The session ID for this notification. + */ + sessionId: SessionId; + /** + * The URI of the closed document. + */ + uri: string; +}; + +/** + * Notification sent when a file becomes the active editor tab. + */ +export type DidFocusDocumentNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The current cursor position. + */ + position: Position; + /** + * The session ID for this notification. + */ + sessionId: SessionId; + /** + * The URI of the focused document. + */ + uri: string; + /** + * The version number of the document. + */ + version: number; + /** + * The portion of the file currently visible in the editor viewport. + */ + visibleRange: Range; +}; + +/** + * Notification sent when a file is opened in the editor. + */ +export type DidOpenDocumentNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The language identifier of the document (e.g., "rust", "python"). + */ + languageId: string; + /** + * The session ID for this notification. + */ + sessionId: SessionId; + /** + * The full text content of the document. + */ + text: string; + /** + * The URI of the opened document. + */ + uri: string; + /** + * The version number of the document. + */ + version: number; +}; + +/** + * Notification sent when a file is saved. + */ +export type DidSaveDocumentNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The session ID for this notification. + */ + sessionId: SessionId; + /** + * The URI of the saved document. + */ + uri: string; +}; + /** * A diff representing file modifications. * @@ -1469,6 +1768,20 @@ export type ForkSessionRequest = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Additional workspace roots to activate for this session. Each path must be absolute. + * + * When omitted or empty, no additional roots are activated. When non-empty, + * this is the complete resulting additional-root list for the forked + * session. + * + * @experimental + */ + additionalDirectories?: Array; /** * The working directory for this session. */ @@ -1765,6 +2078,19 @@ export type ListSessionsRequest = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Filter sessions by the exact ordered additional workspace roots. Each path must be absolute. + * + * This filter applies only when the field is present and non-empty. When + * omitted or empty, no additional-root filter is applied. + * + * @experimental + */ + additionalDirectories?: Array; /** * Opaque cursor token from a previous response's nextCursor field for cursor-based pagination */ @@ -1818,6 +2144,20 @@ export type LoadSessionRequest = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Additional workspace roots to activate for this session. Each path must be absolute. + * + * When omitted or empty, no additional roots are activated. When non-empty, + * this is the complete resulting additional-root list for the loaded + * session. + * + * @experimental + */ + additionalDirectories?: Array; /** * The working directory for this session. */ @@ -2150,11 +2490,9 @@ export type MultiSelectPropertySchema = { }; /** - * Request parameters for creating a new session. - * - * See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session) + * NES capabilities advertised by the agent during initialization. */ -export type NewSessionRequest = { +export type NesCapabilities = { /** * The _meta property is reserved by ACP to allow clients and agents to attach additional * metadata to their interactions. Implementations MUST NOT make assumptions about values at @@ -2166,7 +2504,709 @@ export type NewSessionRequest = { [key: string]: unknown; } | null; /** - * The working directory for this session. Must be an absolute path. + * Context the agent wants attached to each suggestion request. + */ + context?: NesContextCapabilities | null; + /** + * Events the agent wants to receive. + */ + events?: NesEventCapabilities | null; +}; + +/** + * Context capabilities the agent wants attached to each suggestion request. + */ +export type NesContextCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Whether the agent wants diagnostics context. + */ + diagnostics?: NesDiagnosticsCapabilities | null; + /** + * Whether the agent wants edit history context. + */ + editHistory?: NesEditHistoryCapabilities | null; + /** + * Whether the agent wants open files context. + */ + openFiles?: NesOpenFilesCapabilities | null; + /** + * Whether the agent wants recent files context. + */ + recentFiles?: NesRecentFilesCapabilities | null; + /** + * Whether the agent wants related snippets context. + */ + relatedSnippets?: NesRelatedSnippetsCapabilities | null; + /** + * Whether the agent wants user actions context. + */ + userActions?: NesUserActionsCapabilities | null; +}; + +/** + * A diagnostic (error, warning, etc.). + */ +export type NesDiagnostic = { + /** + * The diagnostic message. + */ + message: string; + /** + * The range of the diagnostic. + */ + range: Range; + /** + * The severity of the diagnostic. + */ + severity: NesDiagnosticSeverity; + /** + * The URI of the file containing the diagnostic. + */ + uri: string; +}; + +/** + * Severity of a diagnostic. + */ +export type NesDiagnosticSeverity = + | "error" + | "warning" + | "information" + | "hint"; + +/** + * Capabilities for diagnostics context. + */ +export type NesDiagnosticsCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Capabilities for `document/didChange` events. + */ +export type NesDocumentDidChangeCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The sync kind the agent wants: `"full"` or `"incremental"`. + */ + syncKind: TextDocumentSyncKind; +}; + +/** + * Marker for `document/didClose` capability support. + */ +export type NesDocumentDidCloseCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Marker for `document/didFocus` capability support. + */ +export type NesDocumentDidFocusCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Marker for `document/didOpen` capability support. + */ +export type NesDocumentDidOpenCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Marker for `document/didSave` capability support. + */ +export type NesDocumentDidSaveCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Document event capabilities the agent wants to receive. + */ +export type NesDocumentEventCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Whether the agent wants `document/didChange` events, and the sync kind. + */ + didChange?: NesDocumentDidChangeCapabilities | null; + /** + * Whether the agent wants `document/didClose` events. + */ + didClose?: NesDocumentDidCloseCapabilities | null; + /** + * Whether the agent wants `document/didFocus` events. + */ + didFocus?: NesDocumentDidFocusCapabilities | null; + /** + * Whether the agent wants `document/didOpen` events. + */ + didOpen?: NesDocumentDidOpenCapabilities | null; + /** + * Whether the agent wants `document/didSave` events. + */ + didSave?: NesDocumentDidSaveCapabilities | null; +}; + +/** + * Capabilities for edit history context. + */ +export type NesEditHistoryCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Maximum number of edit history entries the agent can use. + */ + maxCount?: number | null; +}; + +/** + * An entry in the edit history. + */ +export type NesEditHistoryEntry = { + /** + * A diff representing the edit. + */ + diff: string; + /** + * The URI of the edited file. + */ + uri: string; +}; + +/** + * A text edit suggestion. + */ +export type NesEditSuggestion = { + /** + * Optional suggested cursor position after applying edits. + */ + cursorPosition?: Position | null; + /** + * The text edits to apply. + */ + edits: Array; + /** + * Unique identifier for accept/reject tracking. + */ + id: string; + /** + * The URI of the file to edit. + */ + uri: string; +}; + +/** + * Event capabilities the agent can consume. + */ +export type NesEventCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Document event capabilities. + */ + document?: NesDocumentEventCapabilities | null; +}; + +/** + * A code excerpt from a file. + */ +export type NesExcerpt = { + /** + * The end line of the excerpt (zero-based). + */ + endLine: number; + /** + * The start line of the excerpt (zero-based). + */ + startLine: number; + /** + * The text content of the excerpt. + */ + text: string; +}; + +/** + * Marker for jump suggestion support. + */ +export type NesJumpCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * A jump-to-location suggestion. + */ +export type NesJumpSuggestion = { + /** + * Unique identifier for accept/reject tracking. + */ + id: string; + /** + * The target position within the file. + */ + position: Position; + /** + * The file to navigate to. + */ + uri: string; +}; + +/** + * An open file in the editor. + */ +export type NesOpenFile = { + /** + * The language identifier. + */ + languageId: string; + /** + * Timestamp in milliseconds since epoch of when the file was last focused. + */ + lastFocusedMs?: number | null; + /** + * The URI of the file. + */ + uri: string; + /** + * The visible range in the editor, if any. + */ + visibleRange?: Range | null; +}; + +/** + * Capabilities for open files context. + */ +export type NesOpenFilesCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * A recently accessed file. + */ +export type NesRecentFile = { + /** + * The language identifier. + */ + languageId: string; + /** + * The full text content of the file. + */ + text: string; + /** + * The URI of the file. + */ + uri: string; +}; + +/** + * Capabilities for recent files context. + */ +export type NesRecentFilesCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Maximum number of recent files the agent can use. + */ + maxCount?: number | null; +}; + +/** + * The reason a suggestion was rejected. + */ +export type NesRejectReason = "rejected" | "ignored" | "replaced" | "cancelled"; + +/** + * A related code snippet from a file. + */ +export type NesRelatedSnippet = { + /** + * The code excerpts. + */ + excerpts: Array; + /** + * The URI of the file containing the snippets. + */ + uri: string; +}; + +/** + * Capabilities for related snippets context. + */ +export type NesRelatedSnippetsCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * Marker for rename suggestion support. + */ +export type NesRenameCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * A rename symbol suggestion. + */ +export type NesRenameSuggestion = { + /** + * Unique identifier for accept/reject tracking. + */ + id: string; + /** + * The new name for the symbol. + */ + newName: string; + /** + * The position of the symbol to rename. + */ + position: Position; + /** + * The file URI containing the symbol. + */ + uri: string; +}; + +/** + * Repository metadata for an NES session. + */ +export type NesRepository = { + /** + * The repository name. + */ + name: string; + /** + * The repository owner. + */ + owner: string; + /** + * The remote URL of the repository. + */ + remoteUrl: string; +}; + +/** + * Marker for search and replace suggestion support. + */ +export type NesSearchAndReplaceCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + +/** + * A search-and-replace suggestion. + */ +export type NesSearchAndReplaceSuggestion = { + /** + * Unique identifier for accept/reject tracking. + */ + id: string; + /** + * Whether `search` is a regular expression. Defaults to `false`. + */ + isRegex?: boolean | null; + /** + * The replacement text. + */ + replace: string; + /** + * The text or pattern to find. + */ + search: string; + /** + * The file URI to search within. + */ + uri: string; +}; + +/** + * Context attached to a suggestion request. + */ +export type NesSuggestContext = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Current diagnostics (errors, warnings). + */ + diagnostics?: Array | null; + /** + * Recent edit history. + */ + editHistory?: Array | null; + /** + * Currently open files in the editor. + */ + openFiles?: Array | null; + /** + * Recently accessed files. + */ + recentFiles?: Array | null; + /** + * Related code snippets. + */ + relatedSnippets?: Array | null; + /** + * Recent user actions (typing, navigation, etc.). + */ + userActions?: Array | null; +}; + +/** + * A suggestion returned by the agent. + */ +export type NesSuggestion = + | (NesEditSuggestion & { + kind: "edit"; + }) + | (NesJumpSuggestion & { + kind: "jump"; + }) + | (NesRenameSuggestion & { + kind: "rename"; + }) + | (NesSearchAndReplaceSuggestion & { + kind: "searchAndReplace"; + }); + +/** + * A text edit within a suggestion. + */ +export type NesTextEdit = { + /** + * The replacement text. + */ + newText: string; + /** + * The range to replace. + */ + range: Range; +}; + +/** + * What triggered the suggestion request. + */ +export type NesTriggerKind = "automatic" | "diagnostic" | "manual"; + +/** + * A user action (typing, cursor movement, etc.). + */ +export type NesUserAction = { + /** + * The kind of action (e.g., "insertChar", "cursorMovement"). + */ + action: string; + /** + * The position where the action occurred. + */ + position: Position; + /** + * Timestamp in milliseconds since epoch. + */ + timestampMs: number; + /** + * The URI of the file where the action occurred. + */ + uri: string; +}; + +/** + * Capabilities for user actions context. + */ +export type NesUserActionsCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Maximum number of user actions the agent can use. + */ + maxCount?: number | null; +}; + +/** + * Request parameters for creating a new session. + * + * See protocol docs: [Creating a Session](https://agentclientprotocol.com/protocol/session-setup#creating-a-session) + */ +export type NewSessionRequest = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Additional workspace roots for this session. Each path must be absolute. + * + * These expand the session's filesystem scope without changing `cwd`, which + * remains the base for relative paths. When omitted or empty, no + * additional roots are activated for the new session. + * + * @experimental + */ + additionalDirectories?: Array; + /** + * The working directory for this session. Must be an absolute path. */ cwd: string; /** @@ -2368,6 +3408,29 @@ export type PlanEntryPriority = "high" | "medium" | "low"; */ export type PlanEntryStatus = "pending" | "in_progress" | "completed"; +/** + * A zero-based position in a text document. + * + * The meaning of `character` depends on the negotiated position encoding. + */ +export type Position = { + /** + * Zero-based character offset (encoding-dependent). + */ + character: number; + /** + * Zero-based line number. + */ + line: number; +}; + +/** + * The encoding used for character offsets in positions. + * + * Follows the same conventions as LSP 3.17. The default is UTF-16. + */ +export type PositionEncodingKind = "utf-16" | "utf-32" | "utf-8"; + /** * Prompt capabilities supported by the agent in `session/prompt` requests. * @@ -2518,6 +3581,20 @@ export type PromptResponse = { */ export type ProtocolVersion = number; +/** + * A range in a text document, expressed as start and end positions. + */ +export type Range = { + /** + * The end position (exclusive). + */ + end: Position; + /** + * The start position (inclusive). + */ + start: Position; +}; + /** * Request to read content from a text file. * @@ -2569,6 +3646,34 @@ export type ReadTextFileResponse = { content: string; }; +/** + * Notification sent when a suggestion is rejected. + */ +export type RejectNesNotification = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The ID of the rejected suggestion. + */ + id: string; + /** + * The reason for rejection. + */ + reason?: NesRejectReason | null; + /** + * The session ID for this notification. + */ + sessionId: SessionId; +}; + /** * Request to release a terminal and free its resources. */ @@ -2733,6 +3838,20 @@ export type ResumeSessionRequest = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Additional workspace roots to activate for this session. Each path must be absolute. + * + * When omitted or empty, no additional roots are activated. When non-empty, + * this is the complete resulting additional-root list for the resumed + * session. + * + * @experimental + */ + additionalDirectories?: Array; /** * The working directory for this session. */ @@ -2814,6 +3933,31 @@ export type SelectedPermissionOutcome = { optionId: PermissionOptionId; }; +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Capabilities for additional session directories support. + * + * By supplying `{}` it means that the agent supports the `additionalDirectories` field on + * supported session lifecycle requests and `session/list`. + * + * @experimental + */ +export type SessionAdditionalDirectoriesCapabilities = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; +}; + /** * Session capabilities supported by the agent. * @@ -2836,6 +3980,16 @@ export type SessionCapabilities = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Whether the agent supports `additionalDirectories` on supported session lifecycle requests and `session/list`. + * + * @experimental + */ + additionalDirectories?: SessionAdditionalDirectoriesCapabilities | null; /** * **UNSTABLE** * @@ -3105,6 +4259,18 @@ export type SessionInfo = { _meta?: { [key: string]: unknown; } | null; + /** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Authoritative ordered additional workspace roots for this session. Each path must be absolute. + * + * When omitted or empty, there are no additional roots for the session. + * + * @experimental + */ + additionalDirectories?: Array; /** * The working directory for this session. Must be an absolute path. */ @@ -3489,6 +4655,54 @@ export type SetSessionModelResponse = { } | null; }; +/** + * Request to start an NES session. + */ +export type StartNesRequest = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Repository metadata, if the workspace is a git repository. + */ + repository?: NesRepository | null; + /** + * The workspace folders. + */ + workspaceFolders?: Array | null; + /** + * The root URI of the workspace. + */ + workspaceUri?: string | null; +}; + +/** + * Response to `nes/start`. + */ +export type StartNesResponse = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The session ID for the newly started NES session. + */ + sessionId: SessionId; +}; + /** * Reasons why an agent stops processing a prompt turn. * @@ -3551,6 +4765,70 @@ export type StringPropertySchema = { title?: string | null; }; +/** + * Request for a code suggestion. + */ +export type SuggestNesRequest = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * Context for the suggestion, included based on agent capabilities. + */ + context?: NesSuggestContext | null; + /** + * The current cursor position. + */ + position: Position; + /** + * The current text selection range, if any. + */ + selection?: Range | null; + /** + * The session ID for this request. + */ + sessionId: SessionId; + /** + * What triggered this suggestion request. + */ + triggerKind: NesTriggerKind; + /** + * The URI of the document to suggest for. + */ + uri: string; + /** + * The version number of the document. + */ + version: number; +}; + +/** + * Response to `nes/suggest`. + */ +export type SuggestNesResponse = { + /** + * The _meta property is reserved by ACP to allow clients and agents to attach additional + * metadata to their interactions. Implementations MUST NOT make assumptions about values at + * these keys. + * + * See protocol docs: [Extensibility](https://agentclientprotocol.com/protocol/extensibility) + */ + _meta?: { + [key: string]: unknown; + } | null; + /** + * The list of suggestions. + */ + suggestions: Array; +}; + /** * Embed a terminal created with `terminal/create` by its id. * @@ -3666,6 +4944,28 @@ export type TextContent = { text: string; }; +/** + * A content change event for a document. + * + * When `range` is `None`, `text` is the full content of the document. + * When `range` is `Some`, `text` replaces the given range. + */ +export type TextDocumentContentChangeEvent = { + /** + * The range of the document that changed. If `None`, the entire content is replaced. + */ + range?: Range | null; + /** + * The new text for the range, or the full document content if `range` is `None`. + */ + text: string; +}; + +/** + * How the agent wants document changes delivered. + */ +export type TextDocumentSyncKind = "full" | "incremental"; + /** * Text-based resource contents. */ @@ -4037,6 +5337,20 @@ export type WaitForTerminalExitResponse = { signal?: string | null; }; +/** + * A workspace folder. + */ +export type WorkspaceFolder = { + /** + * The display name of the folder. + */ + name: string; + /** + * The URI of the folder. + */ + uri: string; +}; + /** * Request to write content to a text file. * diff --git a/src/schema/zod.gen.ts b/src/schema/zod.gen.ts index 118039c..01a92c6 100644 --- a/src/schema/zod.gen.ts +++ b/src/schema/zod.gen.ts @@ -145,6 +145,13 @@ export const zBooleanPropertySchema = z.looseObject({ title: z.string().nullish(), }); +/** + * Response from closing an NES session. + */ +export const zCloseNesResponse = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + /** * **UNSTABLE** * @@ -438,24 +445,6 @@ export const zFileSystemCapabilities = z.looseObject({ writeTextFile: z.boolean().optional().default(false), }); -/** - * Capabilities supported by the client. - * - * Advertised during initialization to inform the agent about - * available features and methods. - * - * See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities) - */ -export const zClientCapabilities = z.looseObject({ - _meta: z.record(z.string(), z.unknown()).nullish(), - auth: zAuthCapabilities.optional().default({ terminal: false }), - elicitation: zElicitationCapabilities.nullish(), - fs: zFileSystemCapabilities - .optional() - .default({ readTextFile: false, writeTextFile: false }), - terminal: z.boolean().optional().default(false), -}); - /** * An HTTP header to set when making requests to the MCP server. */ @@ -502,6 +491,7 @@ export const zKillTerminalResponse = z.looseObject({ */ export const zListSessionsRequest = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cursor: z.string().nullish(), cwd: z.string().nullish(), }); @@ -652,6 +642,231 @@ export const zModelInfo = z.looseObject({ name: z.string(), }); +/** + * Severity of a diagnostic. + */ +export const zNesDiagnosticSeverity = z.union([ + z.literal("error"), + z.literal("warning"), + z.literal("information"), + z.literal("hint"), +]); + +/** + * Capabilities for diagnostics context. + */ +export const zNesDiagnosticsCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Marker for `document/didClose` capability support. + */ +export const zNesDocumentDidCloseCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Marker for `document/didFocus` capability support. + */ +export const zNesDocumentDidFocusCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Marker for `document/didOpen` capability support. + */ +export const zNesDocumentDidOpenCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Marker for `document/didSave` capability support. + */ +export const zNesDocumentDidSaveCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Capabilities for edit history context. + */ +export const zNesEditHistoryCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + maxCount: z + .number() + .int() + .gte(0) + .max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }) + .nullish(), +}); + +/** + * An entry in the edit history. + */ +export const zNesEditHistoryEntry = z.looseObject({ + diff: z.string(), + uri: z.string(), +}); + +/** + * A code excerpt from a file. + */ +export const zNesExcerpt = z.looseObject({ + endLine: z.number().int().gte(0).max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }), + startLine: z.number().int().gte(0).max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }), + text: z.string(), +}); + +/** + * Marker for jump suggestion support. + */ +export const zNesJumpCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Capabilities for open files context. + */ +export const zNesOpenFilesCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * A recently accessed file. + */ +export const zNesRecentFile = z.looseObject({ + languageId: z.string(), + text: z.string(), + uri: z.string(), +}); + +/** + * Capabilities for recent files context. + */ +export const zNesRecentFilesCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + maxCount: z + .number() + .int() + .gte(0) + .max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }) + .nullish(), +}); + +/** + * The reason a suggestion was rejected. + */ +export const zNesRejectReason = z.union([ + z.literal("rejected"), + z.literal("ignored"), + z.literal("replaced"), + z.literal("cancelled"), +]); + +/** + * A related code snippet from a file. + */ +export const zNesRelatedSnippet = z.looseObject({ + excerpts: z.array(zNesExcerpt), + uri: z.string(), +}); + +/** + * Capabilities for related snippets context. + */ +export const zNesRelatedSnippetsCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Marker for rename suggestion support. + */ +export const zNesRenameCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * Repository metadata for an NES session. + */ +export const zNesRepository = z.looseObject({ + name: z.string(), + owner: z.string(), + remoteUrl: z.string(), +}); + +/** + * Marker for search and replace suggestion support. + */ +export const zNesSearchAndReplaceCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + +/** + * NES capabilities advertised by the client during initialization. + */ +export const zClientNesCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + jump: zNesJumpCapabilities.nullish(), + rename: zNesRenameCapabilities.nullish(), + searchAndReplace: zNesSearchAndReplaceCapabilities.nullish(), +}); + +/** + * A search-and-replace suggestion. + */ +export const zNesSearchAndReplaceSuggestion = z.looseObject({ + id: z.string(), + isRegex: z.boolean().nullish(), + replace: z.string(), + search: z.string(), + uri: z.string(), +}); + +/** + * What triggered the suggestion request. + */ +export const zNesTriggerKind = z.union([ + z.literal("automatic"), + z.literal("diagnostic"), + z.literal("manual"), +]); + +/** + * Capabilities for user actions context. + */ +export const zNesUserActionsCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + maxCount: z + .number() + .int() + .gte(0) + .max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }) + .nullish(), +}); + +/** + * Context capabilities the agent wants attached to each suggestion request. + */ +export const zNesContextCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + diagnostics: zNesDiagnosticsCapabilities.nullish(), + editHistory: zNesEditHistoryCapabilities.nullish(), + openFiles: zNesOpenFilesCapabilities.nullish(), + recentFiles: zNesRecentFilesCapabilities.nullish(), + relatedSnippets: zNesRelatedSnippetsCapabilities.nullish(), + userActions: zNesUserActionsCapabilities.nullish(), +}); + /** * Request parameters for creating a new session. * @@ -659,6 +874,7 @@ export const zModelInfo = z.looseObject({ */ export const zNewSessionRequest = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), mcpServers: z.array(zMcpServer), }); @@ -754,6 +970,80 @@ export const zPlan = z.looseObject({ entries: z.array(zPlanEntry), }); +/** + * A zero-based position in a text document. + * + * The meaning of `character` depends on the negotiated position encoding. + */ +export const zPosition = z.looseObject({ + character: z.number().int().gte(0).max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }), + line: z.number().int().gte(0).max(4294967295, { + message: "Invalid value: Expected uint32 to be <= 4294967295", + }), +}); + +/** + * A jump-to-location suggestion. + */ +export const zNesJumpSuggestion = z.looseObject({ + id: z.string(), + position: zPosition, + uri: z.string(), +}); + +/** + * A rename symbol suggestion. + */ +export const zNesRenameSuggestion = z.looseObject({ + id: z.string(), + newName: z.string(), + position: zPosition, + uri: z.string(), +}); + +/** + * A user action (typing, cursor movement, etc.). + */ +export const zNesUserAction = z.looseObject({ + action: z.string(), + position: zPosition, + timestampMs: z.number(), + uri: z.string(), +}); + +/** + * The encoding used for character offsets in positions. + * + * Follows the same conventions as LSP 3.17. The default is UTF-16. + */ +export const zPositionEncodingKind = z.union([ + z.literal("utf-16"), + z.literal("utf-32"), + z.literal("utf-8"), +]); + +/** + * Capabilities supported by the client. + * + * Advertised during initialization to inform the agent about + * available features and methods. + * + * See protocol docs: [Client Capabilities](https://agentclientprotocol.com/protocol/initialization#client-capabilities) + */ +export const zClientCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + auth: zAuthCapabilities.optional().default({ terminal: false }), + elicitation: zElicitationCapabilities.nullish(), + fs: zFileSystemCapabilities + .optional() + .default({ readTextFile: false, writeTextFile: false }), + nes: zClientNesCapabilities.nullish(), + positionEncodings: z.array(zPositionEncodingKind).optional(), + terminal: z.boolean().optional().default(false), +}); + /** * Prompt capabilities supported by the agent in `session/prompt` requests. * @@ -801,6 +1091,91 @@ export const zInitializeRequest = z.looseObject({ protocolVersion: zProtocolVersion, }); +/** + * A range in a text document, expressed as start and end positions. + */ +export const zRange = z.looseObject({ + end: zPosition, + start: zPosition, +}); + +/** + * A diagnostic (error, warning, etc.). + */ +export const zNesDiagnostic = z.looseObject({ + message: z.string(), + range: zRange, + severity: zNesDiagnosticSeverity, + uri: z.string(), +}); + +/** + * An open file in the editor. + */ +export const zNesOpenFile = z.looseObject({ + languageId: z.string(), + lastFocusedMs: z.number().nullish(), + uri: z.string(), + visibleRange: zRange.nullish(), +}); + +/** + * Context attached to a suggestion request. + */ +export const zNesSuggestContext = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + diagnostics: z.array(zNesDiagnostic).nullish(), + editHistory: z.array(zNesEditHistoryEntry).nullish(), + openFiles: z.array(zNesOpenFile).nullish(), + recentFiles: z.array(zNesRecentFile).nullish(), + relatedSnippets: z.array(zNesRelatedSnippet).nullish(), + userActions: z.array(zNesUserAction).nullish(), +}); + +/** + * A text edit within a suggestion. + */ +export const zNesTextEdit = z.looseObject({ + newText: z.string(), + range: zRange, +}); + +/** + * A text edit suggestion. + */ +export const zNesEditSuggestion = z.looseObject({ + cursorPosition: zPosition.nullish(), + edits: z.array(zNesTextEdit), + id: z.string(), + uri: z.string(), +}); + +/** + * A suggestion returned by the agent. + */ +export const zNesSuggestion = z.union([ + zNesEditSuggestion.and( + z.looseObject({ + kind: z.literal("edit"), + }), + ), + zNesJumpSuggestion.and( + z.looseObject({ + kind: z.literal("jump"), + }), + ), + zNesRenameSuggestion.and( + z.looseObject({ + kind: z.literal("rename"), + }), + ), + zNesSearchAndReplaceSuggestion.and( + z.looseObject({ + kind: z.literal("searchAndReplace"), + }), + ), +]); + /** * Response containing the contents of a text file. */ @@ -925,6 +1300,22 @@ export const zRequestPermissionResponse = z.looseObject({ outcome: zRequestPermissionOutcome, }); +/** + * **UNSTABLE** + * + * This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Capabilities for additional session directories support. + * + * By supplying `{}` it means that the agent supports the `additionalDirectories` field on + * supported session lifecycle requests and `session/list`. + * + * @experimental + */ +export const zSessionAdditionalDirectoriesCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), +}); + /** * **UNSTABLE** * @@ -1077,6 +1468,15 @@ export const zSessionForkCapabilities = z.looseObject({ */ export const zSessionId = z.string(); +/** + * Notification sent when a suggestion is accepted. + */ +export const zAcceptNesNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + id: z.string(), + sessionId: zSessionId, +}); + /** * Notification to cancel ongoing operations for a session. * @@ -1087,9 +1487,15 @@ export const zCancelNotification = z.looseObject({ sessionId: zSessionId, }); -export const zClientNotification = z.looseObject({ - method: z.string(), - params: z.union([zCancelNotification, zExtNotification]).nullish(), +/** + * Request to close an NES session. + * + * The agent **must** cancel any ongoing work related to the NES session + * and then free up any resources associated with the session. + */ +export const zCloseNesRequest = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + sessionId: zSessionId, }); /** @@ -1125,6 +1531,48 @@ export const zCreateTerminalRequest = z.looseObject({ sessionId: zSessionId, }); +/** + * Notification sent when a file is closed. + */ +export const zDidCloseDocumentNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + sessionId: zSessionId, + uri: z.string(), +}); + +/** + * Notification sent when a file becomes the active editor tab. + */ +export const zDidFocusDocumentNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + position: zPosition, + sessionId: zSessionId, + uri: z.string(), + version: z.number(), + visibleRange: zRange, +}); + +/** + * Notification sent when a file is opened in the editor. + */ +export const zDidOpenDocumentNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + languageId: z.string(), + sessionId: zSessionId, + text: z.string(), + uri: z.string(), + version: z.number(), +}); + +/** + * Notification sent when a file is saved. + */ +export const zDidSaveDocumentNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + sessionId: zSessionId, + uri: z.string(), +}); + /** * **UNSTABLE** * @@ -1141,6 +1589,7 @@ export const zCreateTerminalRequest = z.looseObject({ */ export const zForkSessionRequest = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), mcpServers: z.array(zMcpServer).optional(), sessionId: zSessionId, @@ -1164,6 +1613,7 @@ export const zKillTerminalRequest = z.looseObject({ */ export const zLoadSessionRequest = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), mcpServers: z.array(zMcpServer), sessionId: zSessionId, @@ -1196,6 +1646,16 @@ export const zReadTextFileRequest = z.looseObject({ sessionId: zSessionId, }); +/** + * Notification sent when a suggestion is rejected. + */ +export const zRejectNesNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + id: z.string(), + reason: zNesRejectReason.nullish(), + sessionId: zSessionId, +}); + /** * Request to release a terminal and free its resources. */ @@ -1221,6 +1681,7 @@ export const zReleaseTerminalRequest = z.looseObject({ */ export const zResumeSessionRequest = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), mcpServers: z.array(zMcpServer).optional(), sessionId: zSessionId, @@ -1231,6 +1692,7 @@ export const zResumeSessionRequest = z.looseObject({ */ export const zSessionInfo = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: z.array(z.string()).optional(), cwd: z.string(), sessionId: zSessionId, title: z.string().nullish(), @@ -1402,60 +1864,13 @@ export const zSessionResumeCapabilities = z.looseObject({ */ export const zSessionCapabilities = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), + additionalDirectories: zSessionAdditionalDirectoriesCapabilities.nullish(), close: zSessionCloseCapabilities.nullish(), fork: zSessionForkCapabilities.nullish(), list: zSessionListCapabilities.nullish(), resume: zSessionResumeCapabilities.nullish(), }); -/** - * Capabilities supported by the agent. - * - * Advertised during initialization to inform the client about - * available features and content types. - * - * See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities) - */ -export const zAgentCapabilities = z.looseObject({ - _meta: z.record(z.string(), z.unknown()).nullish(), - auth: zAgentAuthCapabilities.optional().default({}), - loadSession: z.boolean().optional().default(false), - mcpCapabilities: zMcpCapabilities - .optional() - .default({ http: false, sse: false }), - promptCapabilities: zPromptCapabilities.optional().default({ - audio: false, - embeddedContext: false, - image: false, - }), - sessionCapabilities: zSessionCapabilities.optional().default({}), -}); - -/** - * Response to the `initialize` method. - * - * Contains the negotiated protocol version and agent capabilities. - * - * See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization) - */ -export const zInitializeResponse = z.looseObject({ - _meta: z.record(z.string(), z.unknown()).nullish(), - agentCapabilities: zAgentCapabilities.optional().default({ - auth: {}, - loadSession: false, - mcpCapabilities: { http: false, sse: false }, - promptCapabilities: { - audio: false, - embeddedContext: false, - image: false, - }, - sessionCapabilities: {}, - }), - agentInfo: zImplementation.nullish(), - authMethods: z.array(zAuthMethod).optional().default([]), - protocolVersion: zProtocolVersion, -}); - export const zSetSessionConfigOptionRequest = z.intersection( z.union([ z.looseObject({ @@ -1525,6 +1940,14 @@ export const zSetSessionModelResponse = z.looseObject({ _meta: z.record(z.string(), z.unknown()).nullish(), }); +/** + * Response to `nes/start`. + */ +export const zStartNesResponse = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + sessionId: zSessionId, +}); + /** * Reasons why an agent stops processing a prompt turn. * @@ -1580,6 +2003,28 @@ export const zStringPropertySchema = z.looseObject({ title: z.string().nullish(), }); +/** + * Request for a code suggestion. + */ +export const zSuggestNesRequest = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + context: zNesSuggestContext.nullish(), + position: zPosition, + selection: zRange.nullish(), + sessionId: zSessionId, + triggerKind: zNesTriggerKind, + uri: z.string(), + version: z.number(), +}); + +/** + * Response to `nes/suggest`. + */ +export const zSuggestNesResponse = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + suggestions: z.array(zNesSuggestion), +}); + /** * Embed a terminal created with `terminal/create` by its id. * @@ -1636,6 +2081,140 @@ export const zTextContent = z.looseObject({ text: z.string(), }); +/** + * A content change event for a document. + * + * When `range` is `None`, `text` is the full content of the document. + * When `range` is `Some`, `text` replaces the given range. + */ +export const zTextDocumentContentChangeEvent = z.looseObject({ + range: zRange.nullish(), + text: z.string(), +}); + +/** + * Notification sent when a file is edited. + */ +export const zDidChangeDocumentNotification = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + contentChanges: z.array(zTextDocumentContentChangeEvent), + sessionId: zSessionId, + uri: z.string(), + version: z.number(), +}); + +export const zClientNotification = z.looseObject({ + method: z.string(), + params: z + .union([ + zCancelNotification, + zDidOpenDocumentNotification, + zDidChangeDocumentNotification, + zDidCloseDocumentNotification, + zDidSaveDocumentNotification, + zDidFocusDocumentNotification, + zAcceptNesNotification, + zRejectNesNotification, + zExtNotification, + ]) + .nullish(), +}); + +/** + * How the agent wants document changes delivered. + */ +export const zTextDocumentSyncKind = z.union([ + z.literal("full"), + z.literal("incremental"), +]); + +/** + * Capabilities for `document/didChange` events. + */ +export const zNesDocumentDidChangeCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + syncKind: zTextDocumentSyncKind, +}); + +/** + * Document event capabilities the agent wants to receive. + */ +export const zNesDocumentEventCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + didChange: zNesDocumentDidChangeCapabilities.nullish(), + didClose: zNesDocumentDidCloseCapabilities.nullish(), + didFocus: zNesDocumentDidFocusCapabilities.nullish(), + didOpen: zNesDocumentDidOpenCapabilities.nullish(), + didSave: zNesDocumentDidSaveCapabilities.nullish(), +}); + +/** + * Event capabilities the agent can consume. + */ +export const zNesEventCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + document: zNesDocumentEventCapabilities.nullish(), +}); + +/** + * NES capabilities advertised by the agent during initialization. + */ +export const zNesCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + context: zNesContextCapabilities.nullish(), + events: zNesEventCapabilities.nullish(), +}); + +/** + * Capabilities supported by the agent. + * + * Advertised during initialization to inform the client about + * available features and content types. + * + * See protocol docs: [Agent Capabilities](https://agentclientprotocol.com/protocol/initialization#agent-capabilities) + */ +export const zAgentCapabilities = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + auth: zAgentAuthCapabilities.optional().default({}), + loadSession: z.boolean().optional().default(false), + mcpCapabilities: zMcpCapabilities + .optional() + .default({ http: false, sse: false }), + nes: zNesCapabilities.nullish(), + positionEncoding: zPositionEncodingKind.nullish(), + promptCapabilities: zPromptCapabilities.optional().default({ + audio: false, + embeddedContext: false, + image: false, + }), + sessionCapabilities: zSessionCapabilities.optional().default({}), +}); + +/** + * Response to the `initialize` method. + * + * Contains the negotiated protocol version and agent capabilities. + * + * See protocol docs: [Initialization](https://agentclientprotocol.com/protocol/initialization) + */ +export const zInitializeResponse = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + agentCapabilities: zAgentCapabilities.optional().default({ + auth: {}, + loadSession: false, + mcpCapabilities: { http: false, sse: false }, + promptCapabilities: { + audio: false, + embeddedContext: false, + image: false, + }, + sessionCapabilities: {}, + }), + agentInfo: zImplementation.nullish(), + authMethods: z.array(zAuthMethod).optional().default([]), + protocolVersion: zProtocolVersion, +}); + /** * Text-based resource contents. */ @@ -1738,29 +2317,6 @@ export const zPromptRequest = z.looseObject({ sessionId: zSessionId, }); -export const zClientRequest = z.looseObject({ - id: zRequestId, - method: z.string(), - params: z - .union([ - zInitializeRequest, - zAuthenticateRequest, - zLogoutRequest, - zNewSessionRequest, - zLoadSessionRequest, - zListSessionsRequest, - zForkSessionRequest, - zResumeSessionRequest, - zCloseSessionRequest, - zSetSessionModeRequest, - zSetSessionConfigOptionRequest, - zPromptRequest, - zSetSessionModelRequest, - zExtRequest, - ]) - .nullish(), -}); - /** * Items definition for titled multi-select enum properties. */ @@ -2102,6 +2658,9 @@ export const zAgentResponse = z.union([ zSetSessionConfigOptionResponse, zPromptResponse, zSetSessionModelResponse, + zStartNesResponse, + zSuggestNesResponse, + zCloseNesResponse, zExtResponse, ]), }), @@ -2241,6 +2800,50 @@ export const zWaitForTerminalExitResponse = z.looseObject({ signal: z.string().nullish(), }); +/** + * A workspace folder. + */ +export const zWorkspaceFolder = z.looseObject({ + name: z.string(), + uri: z.string(), +}); + +/** + * Request to start an NES session. + */ +export const zStartNesRequest = z.looseObject({ + _meta: z.record(z.string(), z.unknown()).nullish(), + repository: zNesRepository.nullish(), + workspaceFolders: z.array(zWorkspaceFolder).nullish(), + workspaceUri: z.string().nullish(), +}); + +export const zClientRequest = z.looseObject({ + id: zRequestId, + method: z.string(), + params: z + .union([ + zInitializeRequest, + zAuthenticateRequest, + zLogoutRequest, + zNewSessionRequest, + zLoadSessionRequest, + zListSessionsRequest, + zForkSessionRequest, + zResumeSessionRequest, + zCloseSessionRequest, + zSetSessionModeRequest, + zSetSessionConfigOptionRequest, + zPromptRequest, + zSetSessionModelRequest, + zStartNesRequest, + zSuggestNesRequest, + zCloseNesRequest, + zExtRequest, + ]) + .nullish(), +}); + /** * Request to write content to a text file. * From 3f689ed96182882676d8d7be1c2541c91ad4ff54 Mon Sep 17 00:00:00 2001 From: "Anna.Zhdan" Date: Sun, 29 Mar 2026 11:51:05 +0200 Subject: [PATCH 2/4] Support for unstable nes methods and additionalDirectories in session/start --- src/acp.ts | 345 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 341 insertions(+), 4 deletions(-) diff --git a/src/acp.ts b/src/acp.ts index 75ace72..f999ec4 100644 --- a/src/acp.ts +++ b/src/acp.ts @@ -134,6 +134,27 @@ export class AgentSideConnection { validate.zSetSessionConfigOptionRequest.parse(params); return agent.setSessionConfigOption(validatedParams); } + case schema.AGENT_METHODS.nes_start: { + if (!agent.unstable_startNes) { + throw RequestError.methodNotFound(method); + } + const validatedParams = validate.zStartNesRequest.parse(params); + return agent.unstable_startNes(validatedParams); + } + case schema.AGENT_METHODS.nes_suggest: { + if (!agent.unstable_suggestNes) { + throw RequestError.methodNotFound(method); + } + const validatedParams = validate.zSuggestNesRequest.parse(params); + return agent.unstable_suggestNes(validatedParams); + } + case schema.AGENT_METHODS.nes_close: { + if (!agent.unstable_closeNes) { + throw RequestError.methodNotFound(method); + } + const validatedParams = validate.zCloseNesRequest.parse(params); + return agent.unstable_closeNes(validatedParams); + } default: if (agent.extMethod) { return agent.extMethod(method, params as Record); @@ -151,6 +172,39 @@ export class AgentSideConnection { const validatedParams = validate.zCancelNotification.parse(params); return agent.cancel(validatedParams); } + case schema.AGENT_METHODS.document_did_open: { + const validatedParams = + validate.zDidOpenDocumentNotification.parse(params); + return agent.unstable_didOpenDocument?.(validatedParams); + } + case schema.AGENT_METHODS.document_did_change: { + const validatedParams = + validate.zDidChangeDocumentNotification.parse(params); + return agent.unstable_didChangeDocument?.(validatedParams); + } + case schema.AGENT_METHODS.document_did_close: { + const validatedParams = + validate.zDidCloseDocumentNotification.parse(params); + return agent.unstable_didCloseDocument?.(validatedParams); + } + case schema.AGENT_METHODS.document_did_save: { + const validatedParams = + validate.zDidSaveDocumentNotification.parse(params); + return agent.unstable_didSaveDocument?.(validatedParams); + } + case schema.AGENT_METHODS.document_did_focus: { + const validatedParams = + validate.zDidFocusDocumentNotification.parse(params); + return agent.unstable_didFocusDocument?.(validatedParams); + } + case schema.AGENT_METHODS.nes_accept: { + const validatedParams = validate.zAcceptNesNotification.parse(params); + return agent.unstable_acceptNes?.(validatedParams); + } + case schema.AGENT_METHODS.nes_reject: { + const validatedParams = validate.zRejectNesNotification.parse(params); + return agent.unstable_rejectNes?.(validatedParams); + } default: if (agent.extNotification) { return agent.extNotification( @@ -588,6 +642,9 @@ export class ClientSideConnection implements Agent { * - Connect to any specified MCP servers * - Return a unique session ID for future requests * + * The request may include `additionalDirectories` to expand the session's filesystem + * scope beyond `cwd` without changing the base for relative paths. + * * May return an `auth_required` error if the agent requires authentication. * * See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup) @@ -611,6 +668,9 @@ export class ClientSideConnection implements Agent { * - Connect to the specified MCP servers * - Stream the entire conversation history back to the client via notifications * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the loaded session. + * * See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions) */ async loadSession( @@ -634,6 +694,9 @@ export class ClientSideConnection implements Agent { * Creates a new session based on the context of an existing one, allowing * operations like generating summaries without affecting the original session's history. * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the forked session. + * * This method is only available if the agent advertises the `session.fork` capability. * * @experimental @@ -653,8 +716,8 @@ export class ClientSideConnection implements 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. + * title, and last update time. Supports filtering by working directory, + * `additionalDirectories`, and cursor-based pagination. */ async listSessions( params: schema.ListSessionsRequest, @@ -677,6 +740,9 @@ export class ClientSideConnection implements Agent { * The agent should resume the session context, allowing the conversation to continue * without replaying the message history (unlike `session/load`). * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the resumed session. + * * @experimental */ async unstable_resumeSession( @@ -852,6 +918,166 @@ export class ClientSideConnection implements Agent { ); } + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Starts a NES (Native Editor Support) session. + * + * @experimental + */ + async unstable_startNes( + params: schema.StartNesRequest, + ): Promise { + return await this.#connection.sendRequest( + schema.AGENT_METHODS.nes_start, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Sends a NES suggestion request. + * + * @experimental + */ + async unstable_suggestNes( + params: schema.SuggestNesRequest, + ): Promise { + return await this.#connection.sendRequest( + schema.AGENT_METHODS.nes_suggest, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Closes a NES session. + * + * @experimental + */ + async unstable_closeNes( + params: schema.CloseNesRequest, + ): Promise { + return await this.#connection.sendRequest( + schema.AGENT_METHODS.nes_close, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a document was opened. + * + * @experimental + */ + async unstable_didOpenDocument( + params: schema.DidOpenDocumentNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.document_did_open, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a document was changed. + * + * @experimental + */ + async unstable_didChangeDocument( + params: schema.DidChangeDocumentNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.document_did_change, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a document was closed. + * + * @experimental + */ + async unstable_didCloseDocument( + params: schema.DidCloseDocumentNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.document_did_close, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a document was saved. + * + * @experimental + */ + async unstable_didSaveDocument( + params: schema.DidSaveDocumentNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.document_did_save, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a document received focus. + * + * @experimental + */ + async unstable_didFocusDocument( + params: schema.DidFocusDocumentNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.document_did_focus, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a NES suggestion was accepted. + * + * @experimental + */ + async unstable_acceptNes( + params: schema.AcceptNesNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.nes_accept, + params, + ); + } + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Notifies the agent that a NES suggestion was rejected. + * + * @experimental + */ + async unstable_rejectNes( + params: schema.RejectNesNotification, + ): Promise { + return await this.#connection.sendNotification( + schema.AGENT_METHODS.nes_reject, + params, + ); + } + /** * Extension method * @@ -1492,6 +1718,9 @@ export interface Agent { * - Connect to any specified MCP servers * - Return a unique session ID for future requests * + * The request may include `additionalDirectories` to expand the session's filesystem + * scope beyond `cwd` without changing the base for relative paths. + * * May return an `auth_required` error if the agent requires authentication. * * See protocol docs: [Session Setup](https://agentclientprotocol.com/protocol/session-setup) @@ -1509,6 +1738,9 @@ export interface Agent { * - Connect to the specified MCP servers * - Stream the entire conversation history back to the client via notifications * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the loaded session. + * * See protocol docs: [Loading Sessions](https://agentclientprotocol.com/protocol/session-setup#loading-sessions) */ loadSession?( @@ -1524,6 +1756,9 @@ export interface Agent { * Creates a new session based on the context of an existing one, allowing * operations like generating summaries without affecting the original session's history. * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the forked session. + * * This method is only available if the agent advertises the `session.fork` capability. * * @experimental @@ -1537,8 +1772,8 @@ export interface 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. + * title, and last update time. Supports filtering by working directory, + * `additionalDirectories`, and cursor-based pagination. */ listSessions?( params: schema.ListSessionsRequest, @@ -1555,6 +1790,9 @@ export interface Agent { * The agent should resume the session context, allowing the conversation to continue * without replaying the message history (unlike `session/load`). * + * The request may include `additionalDirectories` to set the complete list of + * additional workspace roots for the resumed session. + * * @experimental */ unstable_resumeSession?( @@ -1670,6 +1908,105 @@ export interface Agent { */ cancel(params: schema.CancelNotification): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Starts a NES (Native Editor Support) session. + * + * @experimental + */ + unstable_startNes?( + params: schema.StartNesRequest, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Sends a NES suggestion request. + * + * @experimental + */ + unstable_suggestNes?( + params: schema.SuggestNesRequest, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Closes a NES session. + * + * @experimental + */ + unstable_closeNes?( + params: schema.CloseNesRequest, + ): Promise; + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a document is opened. + * + * @experimental + */ + unstable_didOpenDocument?( + params: schema.DidOpenDocumentNotification, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a document is changed. + * + * @experimental + */ + unstable_didChangeDocument?( + params: schema.DidChangeDocumentNotification, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a document is closed. + * + * @experimental + */ + unstable_didCloseDocument?( + params: schema.DidCloseDocumentNotification, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a document is saved. + * + * @experimental + */ + unstable_didSaveDocument?( + params: schema.DidSaveDocumentNotification, + ): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a document receives focus. + * + * @experimental + */ + unstable_didFocusDocument?( + params: schema.DidFocusDocumentNotification, + ): Promise; + + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a NES suggestion is accepted. + * + * @experimental + */ + unstable_acceptNes?(params: schema.AcceptNesNotification): Promise; + /** + * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. + * + * Called when a NES suggestion is rejected. + * + * @experimental + */ + unstable_rejectNes?(params: schema.RejectNesNotification): Promise; + /** * Extension method * From 07cfa2e5139b0870310c8bd94a3d6241241d7281 Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Wed, 1 Apr 2026 15:59:49 +0200 Subject: [PATCH 3/4] Align styles --- src/acp.test.ts | 511 ++++++++++++++++++++++++++++++++++++++++++++++++ src/acp.ts | 36 ++-- 2 files changed, 534 insertions(+), 13 deletions(-) diff --git a/src/acp.test.ts b/src/acp.test.ts index 74c7a0b..d612398 100644 --- a/src/acp.test.ts +++ b/src/acp.test.ts @@ -24,6 +24,25 @@ import { SessionNotification, PROTOCOL_VERSION, ndJsonStream, + StartNesRequest, + StartNesResponse, + SuggestNesRequest, + SuggestNesResponse, + CloseNesRequest, + CloseNesResponse, + AcceptNesNotification, + RejectNesNotification, + DidOpenDocumentNotification, + DidChangeDocumentNotification, + DidCloseDocumentNotification, + DidSaveDocumentNotification, + DidFocusDocumentNotification, + ForkSessionRequest, + ForkSessionResponse, + ListSessionsRequest, + ListSessionsResponse, + ResumeSessionRequest, + ResumeSessionResponse, } from "./acp.js"; describe("Connection", () => { @@ -1227,4 +1246,496 @@ describe("Connection", () => { }); expect(loadResponse).toEqual({}); }); + + it("handles NES request lifecycle", async () => { + class TestClient implements Client { + async writeTextFile( + _: WriteTextFileRequest, + ): Promise { + return {}; + } + async readTextFile( + _: ReadTextFileRequest, + ): Promise { + return { content: "" }; + } + async requestPermission( + _: RequestPermissionRequest, + ): Promise { + return { outcome: { outcome: "selected", optionId: "allow" } }; + } + async sessionUpdate(_: SessionNotification): Promise {} + } + + class TestAgent implements Agent { + async initialize(_: InitializeRequest): Promise { + return { + protocolVersion: 1, + agentCapabilities: { loadSession: false }, + authMethods: [], + }; + } + async newSession(_: NewSessionRequest): Promise { + return { sessionId: "test-session" }; + } + async authenticate(_: AuthenticateRequest): Promise {} + async prompt(_: PromptRequest): Promise { + return { stopReason: "end_turn" }; + } + async cancel(_: CancelNotification): Promise {} + + async unstable_startNes(_: StartNesRequest): Promise { + return { sessionId: "nes-session-1" }; + } + async unstable_suggestNes( + _: SuggestNesRequest, + ): Promise { + return { + suggestions: [ + { + kind: "edit", + id: "sug-1", + uri: "file:///test.ts", + edits: [ + { + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 5 }, + }, + newText: "hello", + }, + ], + }, + ], + }; + } + async unstable_closeNes(_: CloseNesRequest): Promise { + return {}; + } + } + + const agentConnection = new ClientSideConnection( + () => new TestClient(), + ndJsonStream(clientToAgent.writable, agentToClient.readable), + ); + const clientConnection = new AgentSideConnection( + () => new TestAgent(), + ndJsonStream(agentToClient.writable, clientToAgent.readable), + ); + + void clientConnection; + + const startResponse = await agentConnection.unstable_startNes({}); + expect(startResponse).toEqual({ sessionId: "nes-session-1" }); + + const suggestResponse = await agentConnection.unstable_suggestNes({ + sessionId: "nes-session-1", + position: { line: 0, character: 5 }, + triggerKind: "manual", + uri: "file:///test.ts", + version: 1, + }); + expect(suggestResponse).toEqual({ + suggestions: [ + { + kind: "edit", + id: "sug-1", + uri: "file:///test.ts", + edits: [ + { + range: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 5 }, + }, + newText: "hello", + }, + ], + }, + ], + }); + + const closeResponse = await agentConnection.unstable_closeNes({ + sessionId: "nes-session-1", + }); + expect(closeResponse).toEqual({}); + }); + + it("handles NES notifications", async () => { + const notificationLog: unknown[] = []; + + class TestClient implements Client { + async writeTextFile( + _: WriteTextFileRequest, + ): Promise { + return {}; + } + async readTextFile( + _: ReadTextFileRequest, + ): Promise { + return { content: "" }; + } + async requestPermission( + _: RequestPermissionRequest, + ): Promise { + return { outcome: { outcome: "selected", optionId: "allow" } }; + } + async sessionUpdate(_: SessionNotification): Promise {} + } + + class TestAgent implements Agent { + async initialize(_: InitializeRequest): Promise { + return { + protocolVersion: 1, + agentCapabilities: { loadSession: false }, + authMethods: [], + }; + } + async newSession(_: NewSessionRequest): Promise { + return { sessionId: "test-session" }; + } + async authenticate(_: AuthenticateRequest): Promise {} + async prompt(_: PromptRequest): Promise { + return { stopReason: "end_turn" }; + } + async cancel(_: CancelNotification): Promise {} + + async unstable_acceptNes(params: AcceptNesNotification): Promise { + notificationLog.push({ type: "acceptNes", params }); + } + async unstable_rejectNes(params: RejectNesNotification): Promise { + notificationLog.push({ type: "rejectNes", params }); + } + } + + const agentConnection = new ClientSideConnection( + () => new TestClient(), + ndJsonStream(clientToAgent.writable, agentToClient.readable), + ); + const clientConnection = new AgentSideConnection( + () => new TestAgent(), + ndJsonStream(agentToClient.writable, clientToAgent.readable), + ); + + void clientConnection; + + await agentConnection.unstable_acceptNes({ + sessionId: "nes-session-1", + id: "sug-1", + }); + await agentConnection.unstable_rejectNes({ + sessionId: "nes-session-1", + id: "sug-2", + reason: "rejected", + }); + + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(notificationLog).toEqual([ + { + type: "acceptNes", + params: { sessionId: "nes-session-1", id: "sug-1" }, + }, + { + type: "rejectNes", + params: { sessionId: "nes-session-1", id: "sug-2", reason: "rejected" }, + }, + ]); + }); + + it("handles document notifications", async () => { + const notificationLog: unknown[] = []; + + class TestClient implements Client { + async writeTextFile( + _: WriteTextFileRequest, + ): Promise { + return {}; + } + async readTextFile( + _: ReadTextFileRequest, + ): Promise { + return { content: "" }; + } + async requestPermission( + _: RequestPermissionRequest, + ): Promise { + return { outcome: { outcome: "selected", optionId: "allow" } }; + } + async sessionUpdate(_: SessionNotification): Promise {} + } + + class TestAgent implements Agent { + async initialize(_: InitializeRequest): Promise { + return { + protocolVersion: 1, + agentCapabilities: { loadSession: false }, + authMethods: [], + }; + } + async newSession(_: NewSessionRequest): Promise { + return { sessionId: "test-session" }; + } + async authenticate(_: AuthenticateRequest): Promise {} + async prompt(_: PromptRequest): Promise { + return { stopReason: "end_turn" }; + } + async cancel(_: CancelNotification): Promise {} + + async unstable_didOpenDocument( + params: DidOpenDocumentNotification, + ): Promise { + notificationLog.push({ type: "didOpen", params }); + } + async unstable_didChangeDocument( + params: DidChangeDocumentNotification, + ): Promise { + notificationLog.push({ type: "didChange", params }); + } + async unstable_didCloseDocument( + params: DidCloseDocumentNotification, + ): Promise { + notificationLog.push({ type: "didClose", params }); + } + async unstable_didSaveDocument( + params: DidSaveDocumentNotification, + ): Promise { + notificationLog.push({ type: "didSave", params }); + } + async unstable_didFocusDocument( + params: DidFocusDocumentNotification, + ): Promise { + notificationLog.push({ type: "didFocus", params }); + } + } + + const agentConnection = new ClientSideConnection( + () => new TestClient(), + ndJsonStream(clientToAgent.writable, agentToClient.readable), + ); + const clientConnection = new AgentSideConnection( + () => new TestAgent(), + ndJsonStream(agentToClient.writable, clientToAgent.readable), + ); + + void clientConnection; + + await agentConnection.unstable_didOpenDocument({ + sessionId: "s1", + uri: "file:///test.ts", + languageId: "typescript", + version: 1, + text: "const x = 1;", + }); + await agentConnection.unstable_didChangeDocument({ + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + contentChanges: [{ text: "const x = 2;" }], + }); + await agentConnection.unstable_didSaveDocument({ + sessionId: "s1", + uri: "file:///test.ts", + }); + await agentConnection.unstable_didFocusDocument({ + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + position: { line: 0, character: 5 }, + visibleRange: { + start: { line: 0, character: 0 }, + end: { line: 10, character: 0 }, + }, + }); + await agentConnection.unstable_didCloseDocument({ + sessionId: "s1", + uri: "file:///test.ts", + }); + + await new Promise((resolve) => setTimeout(resolve, 50)); + + expect(notificationLog).toEqual([ + { + type: "didOpen", + params: { + sessionId: "s1", + uri: "file:///test.ts", + languageId: "typescript", + version: 1, + text: "const x = 1;", + }, + }, + { + type: "didChange", + params: { + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + contentChanges: [{ text: "const x = 2;" }], + }, + }, + { + type: "didSave", + params: { + sessionId: "s1", + uri: "file:///test.ts", + }, + }, + { + type: "didFocus", + params: { + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + position: { line: 0, character: 5 }, + visibleRange: { + start: { line: 0, character: 0 }, + end: { line: 10, character: 0 }, + }, + }, + }, + { + type: "didClose", + params: { + sessionId: "s1", + uri: "file:///test.ts", + }, + }, + ]); + }); + + it("propagates additionalDirectories on session lifecycle methods", async () => { + let receivedNewSession: NewSessionRequest | undefined; + let receivedLoadSession: LoadSessionRequest | undefined; + let receivedForkSession: ForkSessionRequest | undefined; + let receivedResumeSession: ResumeSessionRequest | undefined; + let receivedListSessions: ListSessionsRequest | undefined; + + class TestClient implements Client { + async writeTextFile( + _: WriteTextFileRequest, + ): Promise { + return {}; + } + async readTextFile( + _: ReadTextFileRequest, + ): Promise { + return { content: "" }; + } + async requestPermission( + _: RequestPermissionRequest, + ): Promise { + return { outcome: { outcome: "selected", optionId: "allow" } }; + } + async sessionUpdate(_: SessionNotification): Promise {} + } + + class TestAgent implements Agent { + async initialize(_: InitializeRequest): Promise { + return { + protocolVersion: 1, + agentCapabilities: { loadSession: false }, + authMethods: [], + }; + } + async newSession(params: NewSessionRequest): Promise { + receivedNewSession = params; + return { sessionId: "new-s1" }; + } + async authenticate(_: AuthenticateRequest): Promise {} + async prompt(_: PromptRequest): Promise { + return { stopReason: "end_turn" }; + } + async cancel(_: CancelNotification): Promise {} + + async loadSession( + params: LoadSessionRequest, + ): Promise { + receivedLoadSession = params; + return {}; + } + async unstable_forkSession( + params: ForkSessionRequest, + ): Promise { + receivedForkSession = params; + return { sessionId: "forked-s1" }; + } + async unstable_resumeSession( + params: ResumeSessionRequest, + ): Promise { + receivedResumeSession = params; + return {}; + } + async listSessions( + params: ListSessionsRequest, + ): Promise { + receivedListSessions = params; + return { sessions: [] }; + } + } + + const agentConnection = new ClientSideConnection( + () => new TestClient(), + ndJsonStream(clientToAgent.writable, agentToClient.readable), + ); + const clientConnection = new AgentSideConnection( + () => new TestAgent(), + ndJsonStream(agentToClient.writable, clientToAgent.readable), + ); + + void clientConnection; + + const newSessionResponse = await agentConnection.newSession({ + cwd: "/test", + mcpServers: [], + additionalDirectories: ["/extra/root1", "/extra/root2"], + }); + expect(newSessionResponse).toEqual({ sessionId: "new-s1" }); + expect(receivedNewSession?.additionalDirectories).toEqual([ + "/extra/root1", + "/extra/root2", + ]); + + const loadResponse = await agentConnection.loadSession({ + sessionId: "s1", + cwd: "/test", + mcpServers: [], + additionalDirectories: ["/extra/root1", "/extra/root2"], + }); + expect(loadResponse).toEqual({}); + expect(receivedLoadSession?.additionalDirectories).toEqual([ + "/extra/root1", + "/extra/root2", + ]); + + const forkResponse = await agentConnection.unstable_forkSession({ + sessionId: "s1", + cwd: "/test", + additionalDirectories: ["/extra/root1", "/extra/root2"], + }); + expect(forkResponse).toEqual({ sessionId: "forked-s1" }); + expect(receivedForkSession?.additionalDirectories).toEqual([ + "/extra/root1", + "/extra/root2", + ]); + + const resumeResponse = await agentConnection.unstable_resumeSession({ + sessionId: "s1", + cwd: "/test", + additionalDirectories: ["/extra/root1", "/extra/root2"], + }); + expect(resumeResponse).toEqual({}); + expect(receivedResumeSession?.additionalDirectories).toEqual([ + "/extra/root1", + "/extra/root2", + ]); + + const listResponse = await agentConnection.listSessions({ + additionalDirectories: ["/extra/root1", "/extra/root2"], + }); + expect(listResponse).toEqual({ sessions: [] }); + expect(receivedListSessions?.additionalDirectories).toEqual([ + "/extra/root1", + "/extra/root2", + ]); + }); }); diff --git a/src/acp.ts b/src/acp.ts index f999ec4..c280365 100644 --- a/src/acp.ts +++ b/src/acp.ts @@ -153,7 +153,8 @@ export class AgentSideConnection { throw RequestError.methodNotFound(method); } const validatedParams = validate.zCloseNesRequest.parse(params); - return agent.unstable_closeNes(validatedParams); + const result = await agent.unstable_closeNes(validatedParams); + return result ?? {}; } default: if (agent.extMethod) { @@ -173,37 +174,44 @@ export class AgentSideConnection { return agent.cancel(validatedParams); } case schema.AGENT_METHODS.document_did_open: { + if (!agent.unstable_didOpenDocument) return; const validatedParams = validate.zDidOpenDocumentNotification.parse(params); - return agent.unstable_didOpenDocument?.(validatedParams); + return agent.unstable_didOpenDocument(validatedParams); } case schema.AGENT_METHODS.document_did_change: { + if (!agent.unstable_didChangeDocument) return; const validatedParams = validate.zDidChangeDocumentNotification.parse(params); - return agent.unstable_didChangeDocument?.(validatedParams); + return agent.unstable_didChangeDocument(validatedParams); } case schema.AGENT_METHODS.document_did_close: { + if (!agent.unstable_didCloseDocument) return; const validatedParams = validate.zDidCloseDocumentNotification.parse(params); - return agent.unstable_didCloseDocument?.(validatedParams); + return agent.unstable_didCloseDocument(validatedParams); } case schema.AGENT_METHODS.document_did_save: { + if (!agent.unstable_didSaveDocument) return; const validatedParams = validate.zDidSaveDocumentNotification.parse(params); - return agent.unstable_didSaveDocument?.(validatedParams); + return agent.unstable_didSaveDocument(validatedParams); } case schema.AGENT_METHODS.document_did_focus: { + if (!agent.unstable_didFocusDocument) return; const validatedParams = validate.zDidFocusDocumentNotification.parse(params); - return agent.unstable_didFocusDocument?.(validatedParams); + return agent.unstable_didFocusDocument(validatedParams); } case schema.AGENT_METHODS.nes_accept: { + if (!agent.unstable_acceptNes) return; const validatedParams = validate.zAcceptNesNotification.parse(params); - return agent.unstable_acceptNes?.(validatedParams); + return agent.unstable_acceptNes(validatedParams); } case schema.AGENT_METHODS.nes_reject: { + if (!agent.unstable_rejectNes) return; const validatedParams = validate.zRejectNesNotification.parse(params); - return agent.unstable_rejectNes?.(validatedParams); + return agent.unstable_rejectNes(validatedParams); } default: if (agent.extNotification) { @@ -921,7 +929,7 @@ export class ClientSideConnection implements Agent { /** * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. * - * Starts a NES (Native Editor Support) session. + * Starts a NES (Next Edit Suggestions) session. * * @experimental */ @@ -960,9 +968,11 @@ export class ClientSideConnection implements Agent { async unstable_closeNes( params: schema.CloseNesRequest, ): Promise { - return await this.#connection.sendRequest( - schema.AGENT_METHODS.nes_close, - params, + return ( + (await this.#connection.sendRequest( + schema.AGENT_METHODS.nes_close, + params, + )) ?? {} ); } @@ -1911,7 +1921,7 @@ export interface Agent { /** * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point. * - * Starts a NES (Native Editor Support) session. + * Starts a NES (Next Edit Suggestions) session. * * @experimental */ From e2ea207ae240b94f5e83d77855f2e1d92b4e1edf Mon Sep 17 00:00:00 2001 From: Ben Brandt Date: Wed, 1 Apr 2026 16:49:10 +0200 Subject: [PATCH 4/4] final --- src/acp.test.ts | 210 +++++++++++++++++++++++++++--------------------- src/acp.ts | 2 +- 2 files changed, 120 insertions(+), 92 deletions(-) diff --git a/src/acp.test.ts b/src/acp.test.ts index d612398..f73c3c3 100644 --- a/src/acp.test.ts +++ b/src/acp.test.ts @@ -1,4 +1,4 @@ -import { describe, it, expect, beforeEach } from "vitest"; +import { describe, it, expect, beforeEach, vi } from "vitest"; import { Agent, ClientSideConnection, @@ -461,12 +461,11 @@ describe("Connection", () => { sessionId: "test-session", }); - // Wait a bit for async handlers - await new Promise((resolve) => setTimeout(resolve, 50)); - // Verify notifications were received - expect(notificationLog).toContain("agent message: Hello from agent"); - expect(notificationLog).toContain("cancelled: test-session"); + await vi.waitFor(() => { + expect(notificationLog).toContain("agent message: Hello from agent"); + expect(notificationLog).toContain("cancelled: test-session"); + }); }); it("handles initialize method", async () => { @@ -653,27 +652,27 @@ describe("Connection", () => { extraNotificationField: "keep this too", } as any); - await new Promise((resolve) => setTimeout(resolve, 50)); - - expect(receivedInitializeParams).toMatchObject({ - extraTopLevel: "keep me", - clientCapabilities: { - customCapability: { - enabled: true, - }, - fs: { - experimentalFs: true, + await vi.waitFor(() => { + expect(receivedInitializeParams).toMatchObject({ + extraTopLevel: "keep me", + clientCapabilities: { + customCapability: { + enabled: true, + }, + fs: { + experimentalFs: true, + }, }, - }, - }); + }); - expect(receivedSessionUpdate).toMatchObject({ - extraNotificationField: "keep this too", - update: { - extraUpdateField: { - keep: true, + expect(receivedSessionUpdate).toMatchObject({ + extraNotificationField: "keep this too", + update: { + extraUpdateField: { + keep: true, + }, }, - }, + }); }); }); @@ -796,16 +795,15 @@ describe("Connection", () => { info: "agent notification", }); - // Wait a bit for async handlers - await new Promise((resolve) => setTimeout(resolve, 50)); - // Verify notifications were logged - expect(extensionLog).toContain( - "client extNotification: example.com/client/notify", - ); - expect(extensionLog).toContain( - "agent extNotification: example.com/agent/notify", - ); + await vi.waitFor(() => { + expect(extensionLog).toContain( + "client extNotification: example.com/client/notify", + ); + expect(extensionLog).toContain( + "agent extNotification: example.com/agent/notify", + ); + }); }); it("handles optional extension methods correctly", async () => { @@ -1248,6 +1246,8 @@ describe("Connection", () => { }); it("handles NES request lifecycle", async () => { + let receivedStartRequest: StartNesRequest | undefined; + class TestClient implements Client { async writeTextFile( _: WriteTextFileRequest, @@ -1284,7 +1284,10 @@ describe("Connection", () => { } async cancel(_: CancelNotification): Promise {} - async unstable_startNes(_: StartNesRequest): Promise { + async unstable_startNes( + params: StartNesRequest, + ): Promise { + receivedStartRequest = params; return { sessionId: "nes-session-1" }; } async unstable_suggestNes( @@ -1325,8 +1328,29 @@ describe("Connection", () => { void clientConnection; - const startResponse = await agentConnection.unstable_startNes({}); + const startResponse = await agentConnection.unstable_startNes({ + workspaceUri: "file:///workspace", + workspaceFolders: [ + { uri: "file:///workspace/frontend", name: "frontend" }, + { uri: "file:///workspace/backend", name: "backend" }, + ], + repository: { + name: "my-repo", + owner: "my-org", + remoteUrl: "https://github.com/my-org/my-repo.git", + }, + }); expect(startResponse).toEqual({ sessionId: "nes-session-1" }); + expect(receivedStartRequest?.workspaceUri).toEqual("file:///workspace"); + expect(receivedStartRequest?.workspaceFolders).toEqual([ + { uri: "file:///workspace/frontend", name: "frontend" }, + { uri: "file:///workspace/backend", name: "backend" }, + ]); + expect(receivedStartRequest?.repository).toEqual({ + name: "my-repo", + owner: "my-org", + remoteUrl: "https://github.com/my-org/my-repo.git", + }); const suggestResponse = await agentConnection.unstable_suggestNes({ sessionId: "nes-session-1", @@ -1428,18 +1452,22 @@ describe("Connection", () => { reason: "rejected", }); - await new Promise((resolve) => setTimeout(resolve, 50)); - - expect(notificationLog).toEqual([ - { - type: "acceptNes", - params: { sessionId: "nes-session-1", id: "sug-1" }, - }, - { - type: "rejectNes", - params: { sessionId: "nes-session-1", id: "sug-2", reason: "rejected" }, - }, - ]); + await vi.waitFor(() => { + expect(notificationLog).toEqual([ + { + type: "acceptNes", + params: { sessionId: "nes-session-1", id: "sug-1" }, + }, + { + type: "rejectNes", + params: { + sessionId: "nes-session-1", + id: "sug-2", + reason: "rejected", + }, + }, + ]); + }); }); it("handles document notifications", async () => { @@ -1551,56 +1579,56 @@ describe("Connection", () => { uri: "file:///test.ts", }); - await new Promise((resolve) => setTimeout(resolve, 50)); - - expect(notificationLog).toEqual([ - { - type: "didOpen", - params: { - sessionId: "s1", - uri: "file:///test.ts", - languageId: "typescript", - version: 1, - text: "const x = 1;", + await vi.waitFor(() => { + expect(notificationLog).toEqual([ + { + type: "didOpen", + params: { + sessionId: "s1", + uri: "file:///test.ts", + languageId: "typescript", + version: 1, + text: "const x = 1;", + }, }, - }, - { - type: "didChange", - params: { - sessionId: "s1", - uri: "file:///test.ts", - version: 2, - contentChanges: [{ text: "const x = 2;" }], + { + type: "didChange", + params: { + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + contentChanges: [{ text: "const x = 2;" }], + }, }, - }, - { - type: "didSave", - params: { - sessionId: "s1", - uri: "file:///test.ts", + { + type: "didSave", + params: { + sessionId: "s1", + uri: "file:///test.ts", + }, }, - }, - { - type: "didFocus", - params: { - sessionId: "s1", - uri: "file:///test.ts", - version: 2, - position: { line: 0, character: 5 }, - visibleRange: { - start: { line: 0, character: 0 }, - end: { line: 10, character: 0 }, + { + type: "didFocus", + params: { + sessionId: "s1", + uri: "file:///test.ts", + version: 2, + position: { line: 0, character: 5 }, + visibleRange: { + start: { line: 0, character: 0 }, + end: { line: 10, character: 0 }, + }, }, }, - }, - { - type: "didClose", - params: { - sessionId: "s1", - uri: "file:///test.ts", + { + type: "didClose", + params: { + sessionId: "s1", + uri: "file:///test.ts", + }, }, - }, - ]); + ]); + }); }); it("propagates additionalDirectories on session lifecycle methods", async () => { diff --git a/src/acp.ts b/src/acp.ts index c280365..bce38cb 100644 --- a/src/acp.ts +++ b/src/acp.ts @@ -1947,7 +1947,7 @@ export interface Agent { */ unstable_closeNes?( params: schema.CloseNesRequest, - ): Promise; + ): Promise; /** * **UNSTABLE**: This capability is not part of the spec yet, and may be removed or changed at any point.