From 699c1feca9f9c94af0c48200032c9ece53aa2846 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 13 May 2026 09:40:08 +0200 Subject: [PATCH 1/5] chore: bump Copilot CLI schemas to 1.0.46 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Regenerated from `@github/copilot@1.0.46` npm tarball. - .copilot-schema-version: 1.0.44-2 → 1.0.46 - schemas/api.schema.json, schemas/session-events.schema.json: re-fetched - src/github/copilot_sdk/generated/event_specs.clj: re-generated via `bb codegen` New wire shapes (post-v1.0.0-beta.3 upstream commits): - assistant.message-data: anthropic-advisor-blocks, anthropic-advisor-model, model - session.start-data: detached-from-spawning-parent-session-id - permission-request / prompt-request: extension-management, extension-permission-access permission kinds (upstream 1.0.44-3) - models.list: modelPickerCategory, modelPickerPriceCategory (upstream 1.0.46) - session.commands.respondToQueuedCommand RPC (upstream 1.0.45) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .copilot-schema-version | 2 +- schemas/README.md | 2 +- schemas/api.schema.json | 310 +++++++++++++++++- schemas/session-events.schema.json | 202 ++++++++++++ .../copilot_sdk/generated/event_specs.clj | 14 +- 5 files changed, 510 insertions(+), 20 deletions(-) diff --git a/.copilot-schema-version b/.copilot-schema-version index ce2b8774..3c92cd0d 100644 --- a/.copilot-schema-version +++ b/.copilot-schema-version @@ -1 +1 @@ -1.0.44-2 +1.0.46 diff --git a/schemas/README.md b/schemas/README.md index 931e52c6..252e87b5 100644 --- a/schemas/README.md +++ b/schemas/README.md @@ -4,4 +4,4 @@ These files are fetched verbatim from the `@github/copilot` npm package at the v **Do not edit by hand.** To update, run `bb schemas:fetch` after bumping `.copilot-schema-version`. -Currently pinned version: `1.0.44-2` +Currently pinned version: `1.0.46` diff --git a/schemas/api.schema.json b/schemas/api.schema.json index 40853935..26d5c091 100644 --- a/schemas/api.schema.json +++ b/schemas/api.schema.json @@ -843,6 +843,41 @@ "$ref": "#/definitions/TasksRemoveResult" }, "stability": "experimental" + }, + "sendMessage": { + "rpcMethod": "session.tasks.sendMessage", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "id": { + "type": "string", + "description": "Agent task identifier" + }, + "message": { + "type": "string", + "description": "Message content to send to the agent" + }, + "fromAgentId": { + "type": "string", + "description": "Agent ID of the sender, if sent on behalf of another agent" + } + }, + "required": [ + "sessionId", + "id", + "message" + ], + "additionalProperties": false, + "title": "TasksSendMessageRequest" + }, + "result": { + "$ref": "#/definitions/TasksSendMessageResult" + }, + "stability": "experimental" } }, "skills": { @@ -1268,6 +1303,36 @@ "result": { "$ref": "#/definitions/CommandsHandlePendingCommandResult" } + }, + "respondToQueuedCommand": { + "rpcMethod": "session.commands.respondToQueuedCommand", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "requestId": { + "type": "string", + "description": "Request ID from the queued command event" + }, + "result": { + "$ref": "#/definitions/QueuedCommandResult", + "description": "Result of the queued command execution" + } + }, + "required": [ + "sessionId", + "requestId", + "result" + ], + "additionalProperties": false, + "title": "CommandsRespondToQueuedCommandRequest" + }, + "result": { + "$ref": "#/definitions/CommandsRespondToQueuedCommandResult" + } } }, "ui": { @@ -2196,6 +2261,39 @@ "additionalProperties": false, "title": "CommandsHandlePendingCommandResult" }, + "CommandsRespondToQueuedCommandRequest": { + "type": "object", + "properties": { + "requestId": { + "type": "string", + "description": "Request ID from the queued command event" + }, + "result": { + "$ref": "#/definitions/QueuedCommandResult", + "description": "Result of the queued command execution" + } + }, + "required": [ + "requestId", + "result" + ], + "additionalProperties": false, + "title": "CommandsRespondToQueuedCommandRequest" + }, + "CommandsRespondToQueuedCommandResult": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "Whether the response was accepted (false if the requestId was not found or already resolved)" + } + }, + "required": [ + "success" + ], + "additionalProperties": false, + "title": "CommandsRespondToQueuedCommandResult" + }, "ConnectRequest": { "type": "object", "properties": { @@ -3539,6 +3637,14 @@ "defaultReasoningEffort": { "type": "string", "description": "Default reasoning effort level (only present if model supports reasoning effort)" + }, + "modelPickerCategory": { + "$ref": "#/definitions/ModelPickerCategory", + "description": "Model capability category for grouping in the model picker" + }, + "modelPickerPriceCategory": { + "$ref": "#/definitions/ModelPickerPriceCategory", + "description": "Relative cost tier for token-based billing users" } }, "required": [ @@ -3557,9 +3663,6 @@ "description": "Billing cost multiplier relative to the base rate" } }, - "required": [ - "multiplier" - ], "additionalProperties": false, "description": "Billing information", "title": "ModelBilling" @@ -3748,6 +3851,27 @@ "additionalProperties": false, "title": "ModelList" }, + "ModelPickerCategory": { + "type": "string", + "enum": [ + "lightweight", + "versatile", + "powerful" + ], + "description": "Model capability category for grouping in the model picker", + "title": "ModelPickerCategory" + }, + "ModelPickerPriceCategory": { + "type": "string", + "enum": [ + "low", + "medium", + "high", + "very_high" + ], + "description": "Relative cost tier for token-based billing users", + "title": "ModelPickerPriceCategory" + }, "ModelPolicy": { "type": "object", "properties": { @@ -3927,6 +4051,12 @@ }, { "$ref": "#/definitions/PermissionDecisionApproveForLocationApprovalCustomTool" + }, + { + "$ref": "#/definitions/PermissionDecisionApproveForLocationApprovalExtensionManagement" + }, + { + "$ref": "#/definitions/PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess" } ], "description": "The approval to persist for this location", @@ -3971,6 +4101,41 @@ "additionalProperties": false, "title": "PermissionDecisionApproveForLocationApprovalCustomTool" }, + "PermissionDecisionApproveForLocationApprovalExtensionManagement": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-management" + }, + "operation": { + "type": "string" + } + }, + "required": [ + "kind" + ], + "additionalProperties": false, + "title": "PermissionDecisionApproveForLocationApprovalExtensionManagement" + }, + "PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-permission-access" + }, + "extensionName": { + "type": "string" + } + }, + "required": [ + "kind", + "extensionName" + ], + "additionalProperties": false, + "title": "PermissionDecisionApproveForLocationApprovalExtensionPermissionAccess" + }, "PermissionDecisionApproveForLocationApprovalMcp": { "type": "object", "properties": { @@ -4101,6 +4266,12 @@ }, { "$ref": "#/definitions/PermissionDecisionApproveForSessionApprovalCustomTool" + }, + { + "$ref": "#/definitions/PermissionDecisionApproveForSessionApprovalExtensionManagement" + }, + { + "$ref": "#/definitions/PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess" } ], "description": "The approval to add as a session-scoped rule", @@ -4145,6 +4316,41 @@ "additionalProperties": false, "title": "PermissionDecisionApproveForSessionApprovalCustomTool" }, + "PermissionDecisionApproveForSessionApprovalExtensionManagement": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-management" + }, + "operation": { + "type": "string" + } + }, + "required": [ + "kind" + ], + "additionalProperties": false, + "title": "PermissionDecisionApproveForSessionApprovalExtensionManagement" + }, + "PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-permission-access" + }, + "extensionName": { + "type": "string" + } + }, + "required": [ + "kind", + "extensionName" + ], + "additionalProperties": false, + "title": "PermissionDecisionApproveForSessionApprovalExtensionPermissionAccess" + }, "PermissionDecisionApproveForSessionApprovalMcp": { "type": "object", "properties": { @@ -4503,6 +4709,52 @@ "additionalProperties": false, "title": "PluginList" }, + "QueuedCommandHandled": { + "type": "object", + "properties": { + "handled": { + "type": "boolean", + "const": true, + "description": "The command was handled" + }, + "stopProcessingQueue": { + "type": "boolean", + "description": "If true, stop processing remaining queued items" + } + }, + "required": [ + "handled" + ], + "additionalProperties": false, + "title": "QueuedCommandHandled" + }, + "QueuedCommandNotHandled": { + "type": "object", + "properties": { + "handled": { + "type": "boolean", + "const": false, + "description": "The command was not handled" + } + }, + "required": [ + "handled" + ], + "additionalProperties": false, + "title": "QueuedCommandNotHandled" + }, + "QueuedCommandResult": { + "anyOf": [ + { + "$ref": "#/definitions/QueuedCommandHandled" + }, + { + "$ref": "#/definitions/QueuedCommandNotHandled" + } + ], + "description": "Result of the queued command execution", + "title": "QueuedCommandResult" + }, "RemoteEnableResult": { "type": "object", "properties": { @@ -5592,6 +5844,47 @@ "additionalProperties": false, "title": "TasksRemoveResult" }, + "TasksSendMessageRequest": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "Agent task identifier" + }, + "message": { + "type": "string", + "description": "Message content to send to the agent" + }, + "fromAgentId": { + "type": "string", + "description": "Agent ID of the sender, if sent on behalf of another agent" + } + }, + "required": [ + "id", + "message" + ], + "additionalProperties": false, + "title": "TasksSendMessageRequest" + }, + "TasksSendMessageResult": { + "type": "object", + "properties": { + "sent": { + "type": "boolean", + "description": "Whether the message was successfully delivered or steered" + }, + "error": { + "type": "string", + "description": "Error message if delivery failed" + } + }, + "required": [ + "sent" + ], + "additionalProperties": false, + "title": "TasksSendMessageResult" + }, "TasksStartAgentRequest": { "type": "object", "properties": { @@ -6448,9 +6741,6 @@ "user_named": { "type": "boolean" }, - "summary": { - "type": "string" - }, "summary_count": { "type": "integer", "minimum": 0, @@ -6476,14 +6766,6 @@ "mc_last_event_id": { "type": "string" }, - "session_sync_level": { - "type": "string", - "enum": [ - "local", - "user", - "repo_and_user" - ] - }, "chronicle_sync_dismissed": { "type": "boolean" } diff --git a/schemas/session-events.schema.json b/schemas/session-events.schema.json index c1e1e61d..76c2d41a 100644 --- a/schemas/session-events.schema.json +++ b/schemas/session-events.schema.json @@ -153,6 +153,10 @@ "type": "string", "description": "Unique identifier for this assistant message" }, + "model": { + "type": "string", + "description": "Model that produced this assistant message, if known" + }, "content": { "type": "string", "description": "The assistant's text response content" @@ -193,6 +197,15 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs" }, + "anthropicAdvisorBlocks": { + "type": "array", + "items": {}, + "description": "Raw Anthropic content array with advisor blocks (server_tool_use, advisor_tool_result) for verbatim round-tripping" + }, + "anthropicAdvisorModel": { + "type": "string", + "description": "Anthropic advisor model ID used for this response, for timeline display on replay" + }, "turnId": { "type": "string", "description": "Identifier for the agent loop turn that produced this message, matching the corresponding assistant.turn_start event" @@ -4409,6 +4422,14 @@ { "$ref": "#/definitions/PermissionPromptRequestHook", "description": "Hook confirmation permission prompt" + }, + { + "$ref": "#/definitions/PermissionPromptRequestExtensionManagement", + "description": "Extension management permission prompt" + }, + { + "$ref": "#/definitions/PermissionPromptRequestExtensionPermissionAccess", + "description": "Extension permission access prompt" } ], "description": "Derived user-facing permission prompt details for UI consumers", @@ -4494,6 +4515,68 @@ "description": "Custom tool invocation permission prompt", "title": "PermissionPromptRequestCustomTool" }, + "PermissionPromptRequestExtensionManagement": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-management", + "description": "Prompt kind discriminator" + }, + "toolCallId": { + "type": "string", + "description": "Tool call ID that triggered this permission request" + }, + "operation": { + "type": "string", + "description": "The extension management operation (scaffold, reload)" + }, + "extensionName": { + "type": "string", + "description": "Name of the extension being managed" + } + }, + "required": [ + "kind", + "operation" + ], + "additionalProperties": false, + "description": "Extension management permission prompt", + "title": "PermissionPromptRequestExtensionManagement" + }, + "PermissionPromptRequestExtensionPermissionAccess": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-permission-access", + "description": "Prompt kind discriminator" + }, + "toolCallId": { + "type": "string", + "description": "Tool call ID that triggered this permission request" + }, + "extensionName": { + "type": "string", + "description": "Name of the extension requesting permission access" + }, + "capabilities": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Capabilities the extension is requesting" + } + }, + "required": [ + "kind", + "extensionName", + "capabilities" + ], + "additionalProperties": false, + "description": "Extension permission access prompt", + "title": "PermissionPromptRequestExtensionPermissionAccess" + }, "PermissionPromptRequestHook": { "type": "object", "properties": { @@ -4814,6 +4897,14 @@ { "$ref": "#/definitions/PermissionRequestHook", "description": "Hook confirmation permission request" + }, + { + "$ref": "#/definitions/PermissionRequestExtensionManagement", + "description": "Extension management permission request" + }, + { + "$ref": "#/definitions/PermissionRequestExtensionPermissionAccess", + "description": "Extension permission access request" } ], "description": "Details of the permission being requested", @@ -4932,6 +5023,68 @@ "additionalProperties": false, "title": "PermissionRequestedEvent" }, + "PermissionRequestExtensionManagement": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-management", + "description": "Permission kind discriminator" + }, + "toolCallId": { + "type": "string", + "description": "Tool call ID that triggered this permission request" + }, + "operation": { + "type": "string", + "description": "The extension management operation (scaffold, reload)" + }, + "extensionName": { + "type": "string", + "description": "Name of the extension being managed" + } + }, + "required": [ + "kind", + "operation" + ], + "additionalProperties": false, + "description": "Extension management permission request", + "title": "PermissionRequestExtensionManagement" + }, + "PermissionRequestExtensionPermissionAccess": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-permission-access", + "description": "Permission kind discriminator" + }, + "toolCallId": { + "type": "string", + "description": "Tool call ID that triggered this permission request" + }, + "extensionName": { + "type": "string", + "description": "Name of the extension requesting permission access" + }, + "capabilities": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Capabilities the extension is requesting" + } + }, + "required": [ + "kind", + "extensionName", + "capabilities" + ], + "additionalProperties": false, + "description": "Extension permission access request", + "title": "PermissionRequestExtensionPermissionAccess" + }, "PermissionRequestHook": { "type": "object", "properties": { @@ -6714,6 +6867,10 @@ "remoteSteerable": { "type": "boolean", "description": "Whether this session supports remote steering via Mission Control" + }, + "detachedFromSpawningParentSessionId": { + "type": "string", + "description": "When set, identifies a parent session whose context this session continues — e.g., a detached headless rem-agent run launched on the parent's interactive shutdown. Telemetry from this session is reported under the parent's session_id." } }, "required": [ @@ -9295,6 +9452,12 @@ }, { "$ref": "#/definitions/UserToolSessionApprovalCustomTool" + }, + { + "$ref": "#/definitions/UserToolSessionApprovalExtensionManagement" + }, + { + "$ref": "#/definitions/UserToolSessionApprovalExtensionPermissionAccess" } ], "description": "The approval to add as a session-scoped rule", @@ -9343,6 +9506,45 @@ "additionalProperties": false, "title": "UserToolSessionApprovalCustomTool" }, + "UserToolSessionApprovalExtensionManagement": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-management", + "description": "Extension management approval kind" + }, + "operation": { + "type": "string", + "description": "Optional operation identifier" + } + }, + "required": [ + "kind" + ], + "additionalProperties": false, + "title": "UserToolSessionApprovalExtensionManagement" + }, + "UserToolSessionApprovalExtensionPermissionAccess": { + "type": "object", + "properties": { + "kind": { + "type": "string", + "const": "extension-permission-access", + "description": "Extension permission access approval kind" + }, + "extensionName": { + "type": "string", + "description": "Extension name" + } + }, + "required": [ + "kind", + "extensionName" + ], + "additionalProperties": false, + "title": "UserToolSessionApprovalExtensionPermissionAccess" + }, "UserToolSessionApprovalMcp": { "type": "object", "properties": { diff --git a/src/github/copilot_sdk/generated/event_specs.clj b/src/github/copilot_sdk/generated/event_specs.clj index 0acb8e0d..c9f0b593 100644 --- a/src/github/copilot_sdk/generated/event_specs.clj +++ b/src/github/copilot_sdk/generated/event_specs.clj @@ -29,6 +29,10 @@ (s/def :github.copilot-sdk.generated.event-specs/answer clojure.core/string?) +(s/def :github.copilot-sdk.generated.event-specs/anthropic-advisor-blocks (s/coll-of clojure.core/any?)) + +(s/def :github.copilot-sdk.generated.event-specs/anthropic-advisor-model clojure.core/string?) + (s/def :github.copilot-sdk.generated.event-specs/api-call-id clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/approved clojure.core/boolean?) @@ -93,6 +97,8 @@ (s/def :github.copilot-sdk.generated.event-specs/description clojure.core/string?) +(s/def :github.copilot-sdk.generated.event-specs/detached-from-spawning-parent-session-id clojure.core/string?) + (s/def :github.copilot-sdk.generated.event-specs/duration clojure.core/number?) (s/def :github.copilot-sdk.generated.event-specs/duration-ms clojure.core/number?) @@ -213,7 +219,7 @@ (s/def :github.copilot-sdk.generated.event-specs/performed-by clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/permission-request (s/or :branch-0 clojure.core/map? :branch-1 clojure.core/map? :branch-2 clojure.core/map? :branch-3 clojure.core/map? :branch-4 clojure.core/map? :branch-5 clojure.core/map? :branch-6 clojure.core/map? :branch-7 clojure.core/map?)) +(s/def :github.copilot-sdk.generated.event-specs/permission-request (s/or :branch-0 clojure.core/map? :branch-1 clojure.core/map? :branch-2 clojure.core/map? :branch-3 clojure.core/map? :branch-4 clojure.core/map? :branch-5 clojure.core/map? :branch-6 clojure.core/map? :branch-7 clojure.core/map? :branch-8 clojure.core/map? :branch-9 clojure.core/map?)) (s/def :github.copilot-sdk.generated.event-specs/phase clojure.core/string?) @@ -249,7 +255,7 @@ (s/def :github.copilot-sdk.generated.event-specs/prompt clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/prompt-request (s/or :branch-0 clojure.core/map? :branch-1 clojure.core/map? :branch-2 clojure.core/map? :branch-3 clojure.core/map? :branch-4 clojure.core/map? :branch-5 clojure.core/map? :branch-6 clojure.core/map? :branch-7 clojure.core/map? :branch-8 clojure.core/map?)) +(s/def :github.copilot-sdk.generated.event-specs/prompt-request (s/or :branch-0 clojure.core/map? :branch-1 clojure.core/map? :branch-2 clojure.core/map? :branch-3 clojure.core/map? :branch-4 clojure.core/map? :branch-5 clojure.core/map? :branch-6 clojure.core/map? :branch-7 clojure.core/map? :branch-8 clojure.core/map? :branch-9 clojure.core/map? :branch-10 clojure.core/map?)) (s/def :github.copilot-sdk.generated.event-specs/provider-call-id clojure.core/string?) @@ -407,7 +413,7 @@ (s/def :github.copilot-sdk.generated.event-specs/assistant.intent-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/intent])) -(s/def :github.copilot-sdk.generated.event-specs/assistant.message-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/content :github.copilot-sdk.generated.event-specs/message-id] :opt-un [:github.copilot-sdk.generated.event-specs/encrypted-content :github.copilot-sdk.generated.event-specs/interaction-id :github.copilot-sdk.generated.event-specs/output-tokens :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/phase :github.copilot-sdk.generated.event-specs/reasoning-opaque :github.copilot-sdk.generated.event-specs/reasoning-text :github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/tool-requests :github.copilot-sdk.generated.event-specs/turn-id])) +(s/def :github.copilot-sdk.generated.event-specs/assistant.message-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/content :github.copilot-sdk.generated.event-specs/message-id] :opt-un [:github.copilot-sdk.generated.event-specs/anthropic-advisor-blocks :github.copilot-sdk.generated.event-specs/anthropic-advisor-model :github.copilot-sdk.generated.event-specs/encrypted-content :github.copilot-sdk.generated.event-specs/interaction-id :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/output-tokens :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/phase :github.copilot-sdk.generated.event-specs/reasoning-opaque :github.copilot-sdk.generated.event-specs/reasoning-text :github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/tool-requests :github.copilot-sdk.generated.event-specs/turn-id])) (s/def :github.copilot-sdk.generated.event-specs/assistant.message_delta-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/delta-content :github.copilot-sdk.generated.event-specs/message-id] :opt-un [:github.copilot-sdk.generated.event-specs/parent-tool-call-id])) @@ -515,7 +521,7 @@ (s/def :github.copilot-sdk.generated.event-specs/session.snapshot_rewind-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/events-removed :github.copilot-sdk.generated.event-specs/up-to-event-id])) -(s/def :github.copilot-sdk.generated.event-specs/session.start-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/copilot-version :github.copilot-sdk.generated.event-specs/producer :github.copilot-sdk.generated.event-specs/session-id :github.copilot-sdk.generated.event-specs/start-time :github.copilot-sdk.generated.event-specs/version] :opt-un [:github.copilot-sdk.generated.event-specs/already-in-use :github.copilot-sdk.generated.event-specs/context :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/remote-steerable :github.copilot-sdk.generated.event-specs/selected-model])) +(s/def :github.copilot-sdk.generated.event-specs/session.start-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/copilot-version :github.copilot-sdk.generated.event-specs/producer :github.copilot-sdk.generated.event-specs/session-id :github.copilot-sdk.generated.event-specs/start-time :github.copilot-sdk.generated.event-specs/version] :opt-un [:github.copilot-sdk.generated.event-specs/already-in-use :github.copilot-sdk.generated.event-specs/context :github.copilot-sdk.generated.event-specs/detached-from-spawning-parent-session-id :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/remote-steerable :github.copilot-sdk.generated.event-specs/selected-model])) (s/def :github.copilot-sdk.generated.event-specs/session.task_complete-data (s/keys :opt-un [:github.copilot-sdk.generated.event-specs/success :github.copilot-sdk.generated.event-specs/summary])) From ff3164056be23e476d00bd26fd966ccad585a657 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 13 May 2026 09:40:21 +0200 Subject: [PATCH 2/5] feat(specs): surface new model picker fields and post-1.0.0-beta.3 wire fields Add idiom specs (kebab-case, ?-suffixed booleans) for new wire fields introduced in upstream CLI 1.0.44-3, 1.0.45, and 1.0.46. specs.clj: - ::permission-kind: add :extension-management, :extension-permission-access - ::assistant.message-data: add anthropic-advisor-blocks, anthropic-advisor-model - ::session.start-data: add detached-from-spawning-parent-session-id - ::model-info: add model-picker-category, model-picker-price-category (kept as open strings to let unknown future categories pass through) - Add ::handled? and ::stop-processing-queue? for the new queued-command RPC client.clj: - parse-model-info: add model-picker-category and model-picker-price-category to the select-keys whitelist so they're surfaced through list-models - list-models docstring: document the two new fields Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/github/copilot_sdk/client.clj | 5 ++++- src/github/copilot_sdk/specs.clj | 25 +++++++++++++++++++++---- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/github/copilot_sdk/client.clj b/src/github/copilot_sdk/client.clj index c40a72c9..1f852358 100644 --- a/src/github/copilot_sdk/client.clj +++ b/src/github/copilot_sdk/client.clj @@ -1165,7 +1165,9 @@ optional (merge (select-keys m [:default-temperature :model-picker-priority - :default-reasoning-effort]) + :default-reasoning-effort + :model-picker-category + :model-picker-price-category]) (when (contains? m :policy) (let [mp (:policy m)] (cond @@ -1214,6 +1216,7 @@ Returns a vector of model info maps with keys: :id :name :vendor :family :version :max-input-tokens :max-output-tokens :preview? :default-temperature :model-picker-priority + :model-picker-category :model-picker-price-category :model-capabilities {:model-supports {:supports-vision :supports-reasoning-effort} :model-limits {:max-prompt-tokens :max-context-window-tokens :vision-capabilities {:supported-media-types diff --git a/src/github/copilot_sdk/specs.clj b/src/github/copilot_sdk/specs.clj index 96320467..f0f85520 100644 --- a/src/github/copilot_sdk/specs.clj +++ b/src/github/copilot_sdk/specs.clj @@ -829,6 +829,7 @@ (s/def ::head-commit string?) (s/def ::base-commit string?) +(s/def ::detached-from-spawning-parent-session-id string?) (s/def ::session.start-data ;; Note: ::version is intentionally omitted from this hand-written spec. ;; The upstream schema types it as `number` while the global `::version` @@ -837,7 +838,8 @@ ;; canonical contract for this field. (s/keys :req-un [::session-id] :opt-un [::producer ::copilot-version ::start-time ::selected-model - ::reasoning-effort ::already-in-use? ::remote-steerable? ::host-type ::head-commit ::base-commit])) + ::reasoning-effort ::already-in-use? ::remote-steerable? ::host-type ::head-commit ::base-commit + ::detached-from-spawning-parent-session-id])) (s/def ::event-count nat-int?) (s/def ::session.resume-data @@ -882,11 +884,18 @@ #(or (not (contains? % :attachments)) (s/valid? ::inbound-attachments (:attachments %))))) +;; Queued command response (CLI 1.0.45, session.commands.respondToQueuedCommand) +(s/def ::handled? boolean?) +(s/def ::stop-processing-queue? boolean?) + +(s/def ::anthropic-advisor-blocks (s/coll-of any?)) +(s/def ::anthropic-advisor-model string?) (s/def ::assistant.message-data (s/keys :req-un [::message-id ::content] :opt-un [::tool-requests ::parent-tool-call-id ::encrypted-content ::interaction-id ::output-tokens ::phase ::reasoning-opaque - ::reasoning-text ::request-id])) + ::reasoning-text ::request-id + ::anthropic-advisor-blocks ::anthropic-advisor-model ::model])) (s/def ::total-response-size-bytes nat-int?) (s/def ::turn-id ::non-blank-string) @@ -1146,7 +1155,8 @@ ;; Permission types ;; ----------------------------------------------------------------------------- -(s/def ::permission-kind #{:shell :write :mcp :read :url :custom-tool :memory :hook}) +(s/def ::permission-kind #{:shell :write :mcp :read :url :custom-tool :memory :hook + :extension-management :extension-permission-access}) ;; Memory permission event data fields (CLI 1.0.22, upstream PR #1055) (s/def ::memory-action #{:store :vote}) @@ -1250,6 +1260,12 @@ (s/def ::supported-reasoning-efforts (s/coll-of string?)) (s/def ::default-reasoning-effort string?) +;; Model picker categorization (CLI 1.0.46). Upstream defines closed enums, +;; but the idiom spec keeps these as strings so future categories pass through +;; unchanged on the wire. +(s/def ::model-picker-category string?) +(s/def ::model-picker-price-category string?) + ;; Model info (s/def ::id string?) (s/def ::name string?) @@ -1264,7 +1280,8 @@ ::preview? ::default-temperature ::model-picker-priority ::model-capabilities ::model-policy ::model-billing ::supported-reasoning-efforts ::default-reasoning-effort - ::vision-limits])) + ::vision-limits + ::model-picker-category ::model-picker-price-category])) ;; Misc specs for instrument.clj (s/def ::message-id string?) From f77a6473786632506779ee1e104a99cd53b82021 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 13 May 2026 09:40:33 +0200 Subject: [PATCH 3/5] feat(session): add experimental respond-to-queued-command! RPC Wraps the new `session.commands.respondToQueuedCommand` RPC introduced in upstream Copilot CLI 1.0.45. Marked ^:experimental to mirror the upstream Node.js SDK, which exposes it only via the generated low-level RPC layer (no high-level helper). session.clj: - New respond-to-queued-command! function. Wire shape: {sessionId, requestId, result: {handled, stopProcessingQueue?}} Idiomatic API: {:request-id ... :handled? bool :stop-processing-queue? bool?} instrument.clj: - Register fdef with :handled? as :req-un (it is the discriminator between QueuedCommandHandled and QueuedCommandNotHandled per upstream rpc.ts) so spec instrumentation enforces presence. mock_server.clj: - Stub session.commands.respondToQueuedCommand returning {:success true}. integration_test.clj: - test-cli-1.0.46-sync-spec-additions: validate new wire/idiom specs. - test-list-models-surfaces-model-picker-fields: model picker fields flow through parse-model-info. - test-respond-to-queued-command: wire shape for handled=true with stop-processing-queue, and handled=false (stopProcessingQueue omitted). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/github/copilot_sdk/instrument.clj | 6 ++ src/github/copilot_sdk/session.clj | 33 ++++++++ test/github/copilot_sdk/integration_test.clj | 79 ++++++++++++++++++++ test/github/copilot_sdk/mock_server.clj | 1 + 4 files changed, 119 insertions(+) diff --git a/src/github/copilot_sdk/instrument.clj b/src/github/copilot_sdk/instrument.clj index db9a3fae..2e4214ac 100644 --- a/src/github/copilot_sdk/instrument.clj +++ b/src/github/copilot_sdk/instrument.clj @@ -309,6 +309,12 @@ :args (s/cat :session ::specs/session) :ret any?) +(register-fdef! github.copilot-sdk.session/respond-to-queued-command! + :args (s/cat :session ::specs/session + :params (s/keys :req-un [::specs/request-id ::specs/handled?] + :opt-un [::specs/stop-processing-queue?])) + :ret any?) + (register-fdef! github.copilot-sdk.session/mcp-list :args (s/cat :session ::specs/session) :ret map?) diff --git a/src/github/copilot_sdk/session.clj b/src/github/copilot_sdk/session.clj index cc759d02..69a455b7 100644 --- a/src/github/copilot_sdk/session.clj +++ b/src/github/copilot_sdk/session.clj @@ -1415,6 +1415,39 @@ conn (connection-io client)] (proto/send-request! conn "session.skills.reload" {:sessionId session-id}))) +;; -- Commands (queued command response) -------------------------------------- + +(defn ^:experimental respond-to-queued-command! + "Respond to a `:copilot/command.queued` event from the CLI. + + The CLI emits `command.queued` events when a slash-command is dispatched + for client-side execution. Each event carries a `:request-id` (and + `:command`). Clients should respond with either: + + {:request-id :handled? true ;; consumed by client + :stop-processing-queue? false} ;; optional + {:request-id :handled? false} ;; fall through + + When `:handled?` is `true`, the CLI marks the queued command done; when + `:stop-processing-queue?` is also `true`, the CLI stops processing the + remainder of the queue. When `:handled?` is `false`, the CLI re-routes + the command to its default handling. The CLI accepts the response via + the `session.commands.respondToQueuedCommand` RPC. + + Marked experimental — the upstream Node SDK exposes this only via the + generated low-level `commands.respondToQueuedCommand` RPC (no high-level + helper)." + [session {:keys [request-id handled? stop-processing-queue?] :as _params}] + (let [{:keys [session-id client]} session + conn (connection-io client) + result (cond-> {:handled (boolean handled?)} + (and handled? stop-processing-queue?) + (assoc :stopProcessingQueue true))] + (proto/send-request! conn "session.commands.respondToQueuedCommand" + {:sessionId session-id + :requestId request-id + :result result}))) + ;; -- MCP Servers ------------------------------------------------------------- (defn ^:experimental mcp-list diff --git a/test/github/copilot_sdk/integration_test.clj b/test/github/copilot_sdk/integration_test.clj index 704bfa4d..fd602015 100644 --- a/test/github/copilot_sdk/integration_test.clj +++ b/test/github/copilot_sdk/integration_test.clj @@ -1607,6 +1607,85 @@ ;; Last Session ID Tests ;; ----------------------------------------------------------------------------- +(deftest test-cli-1.0.46-sync-spec-additions + (testing "::permission-kind accepts new extension-* kinds (CLI 1.0.44-3)" + (is (s/valid? :github.copilot-sdk.specs/permission-kind :extension-management)) + (is (s/valid? :github.copilot-sdk.specs/permission-kind :extension-permission-access)) + (is (false? (s/valid? :github.copilot-sdk.specs/permission-kind :bogus-kind)))) + + (testing "::assistant.message-data accepts new advisor + model fields (CLI 1.0.45)" + (is (s/valid? :github.copilot-sdk.specs/assistant.message-data + {:message-id "m1" + :content "answer" + :anthropic-advisor-blocks [{:type "server_tool_use"}] + :anthropic-advisor-model "claude-advisor" + :model "gpt-5"}))) + + (testing "::session.start-data accepts :detached-from-spawning-parent-session-id (CLI 1.0.44-3)" + (is (s/valid? :github.copilot-sdk.specs/session.start-data + {:session-id "s1" + :detached-from-spawning-parent-session-id "parent-s0"}))) + + (testing "::model-info accepts model-picker categorization fields (CLI 1.0.46)" + (is (s/valid? :github.copilot-sdk.specs/model-info + {:id "m1" + :name "Model 1" + :model-picker-category "powerful" + :model-picker-price-category "very_high"})) + ;; Open string enum — unknown values should still validate as strings. + (is (s/valid? :github.copilot-sdk.specs/model-info + {:id "m1" + :name "Model 1" + :model-picker-category "future-tier-not-yet-defined"})))) + +(deftest test-list-models-surfaces-model-picker-fields + (testing "list-models exposes modelPickerCategory and modelPickerPriceCategory (CLI 1.0.46)" + (mock/set-request-hook! *mock-server* + (fn [method _params] + (when (= "models.list" method) + {:github.copilot-sdk.mock-server/merge-response + {:models [{:id "m-picker" + :name "Picker Model" + :modelPickerCategory "powerful" + :modelPickerPriceCategory "very_high"}]}}))) + (let [models (sdk/list-models *test-client*) + m (first models)] + (is (= "m-picker" (:id m))) + (is (= "powerful" (:model-picker-category m))) + (is (= "very_high" (:model-picker-price-category m)))))) + +(deftest test-respond-to-queued-command + (testing "respond-to-queued-command! sends correct wire shape with handled=true" + (let [requests (atom []) + session (sdk/create-session *test-client* {:on-permission-request sdk/approve-all})] + (mock/set-request-hook! *mock-server* + (fn [method params] + (swap! requests conj {:method method :params params}) + nil)) + (session/respond-to-queued-command! session + {:request-id "cmd-q-1" + :handled? true + :stop-processing-queue? true}) + (let [req (first (filter #(= "session.commands.respondToQueuedCommand" (:method %)) @requests))] + (is (some? req)) + (is (= "cmd-q-1" (:requestId (:params req)))) + (is (= {:handled true :stopProcessingQueue true} (:result (:params req))))))) + + (testing "respond-to-queued-command! sends correct wire shape with handled=false" + (let [requests (atom []) + session (sdk/create-session *test-client* {:on-permission-request sdk/approve-all})] + (mock/set-request-hook! *mock-server* + (fn [method params] + (swap! requests conj {:method method :params params}) + nil)) + (session/respond-to-queued-command! session + {:request-id "cmd-q-2" + :handled? false}) + (let [req (first (filter #(= "session.commands.respondToQueuedCommand" (:method %)) @requests))] + (is (some? req)) + (is (= "cmd-q-2" (:requestId (:params req)))) + (is (= {:handled false} (:result (:params req)))))))) + (deftest test-send-async-untaps-on-send-failure (testing "send-async cleans up tap when RPC fails" (log/info "Warnings expected in this test: async send RPC error is deliberate.") diff --git a/test/github/copilot_sdk/mock_server.clj b/test/github/copilot_sdk/mock_server.clj index 9a9e705b..bb30839c 100644 --- a/test/github/copilot_sdk/mock_server.clj +++ b/test/github/copilot_sdk/mock_server.clj @@ -341,6 +341,7 @@ "session.log" (handle-session-log server params) "session.permissions.handlePendingPermissionRequest" {:ok true} "session.commands.handlePendingCommand" {:ok true} + "session.commands.respondToQueuedCommand" {:success true} "session.tools.handlePendingToolCall" {:ok true} "session.ui.handlePendingElicitation" {:ok true} "session.mode.get" {:mode "interactive"} From cef65ef238172f1588cade7cc6b8623dfa4688e3 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 13 May 2026 09:40:43 +0200 Subject: [PATCH 4/5] docs: changelog and API reference for 1.0.46 sync - CHANGELOG: new "post-v1.0.0-beta.3 CLI sync" section under [Unreleased] with Added and Tracked-but-not-ported subsections. - doc/reference/API.md: list-models return shape now documents :model-picker-category and :model-picker-price-category. New Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 51 ++++++++++++++++++++++++++++++++++++++++++++ doc/reference/API.md | 26 ++++++++++++++++++++++ 2 files changed, 77 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dccaf201..61b33502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,57 @@ All notable changes to this project will be documented in this file. This change ## [Unreleased] +### Added (post-v1.0.0-beta.3 CLI sync) +- **Schema bump** — `.copilot-schema-version` advanced from `1.0.44-2` to + `1.0.46` (current `latest` on npm). Generated wire specs and coercions + regenerated. +- **Extension permission kinds** — `::permission-kind` accepts the new + upstream values `:extension-management` and `:extension-permission-access`, + emitted by the CLI for extension lifecycle and capability-access prompts. + (upstream PR #1239, CLI 1.0.44-3) +- **`:detached-from-spawning-parent-session-id` on `session.start` events** — + when a session continues another session's context (e.g., a detached + headless rem-agent run launched on the parent's interactive shutdown), + `session.start` now exposes the spawning parent's session id. Telemetry + from such sessions is reported under the parent's `session_id`. + Accepted by both the regenerated wire spec and the hand-curated + `::specs/session.start-data`. (upstream PR #1239, CLI 1.0.44-3) +- **Anthropic advisor block fields on `assistant.message`** — + `::assistant.message-data` now accepts the optional `:anthropic-advisor-blocks` + (raw Anthropic content array with advisor blocks, for verbatim replay), + `:anthropic-advisor-model`, and `:model` (model that produced the response, + when known). The regenerated wire spec already exposed these; the + hand-curated idiom spec now mirrors them. (upstream PR #1263, CLI 1.0.45) +- **`:model-picker-category` / `:model-picker-price-category` on `list-models`** — + the regenerated `Model` shape carries upstream's new model-picker + categorization fields (`"lightweight" | "versatile" | "powerful"` and + `"low" | "medium" | "high" | "very_high"`). `parse-model-info` now + surfaces both as idiomatic strings (open enum) on each entry returned by + `copilot/list-models`. (upstream PR #1270, CLI 1.0.46) +- **`session/respond-to-queued-command!` (experimental)** — wraps the new + `session.commands.respondToQueuedCommand` RPC for acknowledging + `:copilot/command.queued` events. Accepts + `{:request-id ... :handled? true/false :stop-processing-queue? bool?}` and + forwards the wire shape + `{:requestId ..., :result {:handled bool, :stopProcessingQueue bool?}}`. + Marked experimental, mirroring upstream's exposure of this only via the + generated low-level RPC. (upstream PR #1263, CLI 1.0.45) + +### Tracked-but-not-ported (post-v1.0.0-beta.3 CLI sync) +- **`session.tasks.sendMessage` (experimental)** — the upstream Tasks API + (`session.tasks.*`) is intentionally not surfaced in the Clojure SDK + yet; the new `sendMessage` RPC is tracked here for a future port. + (upstream PR #1239, CLI 1.0.44-3) +- **`UserToolSessionApproval` extension kinds** — upstream adds + `extension-management` and `extension-permission-access` to the + `UserToolSessionApproval` discriminated union. The Clojure idiom spec + for `::approval` is intentionally broad (`map?`), so these payloads pass + through unchanged; only the wire-side discriminator changed. + (upstream PR #1263, CLI 1.0.45) +- **`WorkspacesGetWorkspaceResult.session_sync_level` removal** — upstream + dropped this field. The Clojure SDK never surfaced it; no change needed. + (upstream PR #1239, CLI 1.0.44-3) + ## [1.0.0-beta.3.0] - 2026-05-12 ### Changed (release tooling) - **Version scheme — Maven qualifier support.** The release workflow, diff --git a/doc/reference/API.md b/doc/reference/API.md index 6916232c..ff02fb6e 100644 --- a/doc/reference/API.md +++ b/doc/reference/API.md @@ -415,6 +415,9 @@ Requires authentication (unless `:on-list-models` is provided). Returns a vector :model-policy {:policy-state "enabled" :terms "..."} :model-billing {:multiplier 1.0} + ;; Model picker categorization (CLI 1.0.46+): + :model-picker-category "powerful" ;; "lightweight" | "versatile" | "powerful" + :model-picker-price-category "very_high" ;; "low" | "medium" | "high" | "very_high" ;; For models supporting reasoning: :supported-reasoning-efforts ["low" "medium" "high" "xhigh"] :default-reasoning-effort "medium"} @@ -1014,6 +1017,29 @@ Get the client that owns this session. | `session/skills-disable!` | Disable a skill by name. | | `session/skills-reload!` | Reload all skills. | +**Queued commands** + +The CLI emits `:copilot/command.queued` events when a slash-command is +dispatched for client-side execution. Each event carries a `:request-id` +and `:command`. Clients respond via `respond-to-queued-command!`: + +```clojure +;; Inside an event handler that observes :copilot/command.queued +(session/respond-to-queued-command! session + {:request-id (:request-id event-data) + :handled? true + :stop-processing-queue? false}) + +;; Or, to let the CLI fall back to default handling: +(session/respond-to-queued-command! session + {:request-id (:request-id event-data) + :handled? false}) +``` + +| Function | Description | +|----------|-------------| +| `session/respond-to-queued-command!` | Acknowledge a `command.queued` event (experimental). | + **MCP Servers** | Function | Description | From 5dd5cf8f7199ca5f96f751f67f2fd4dc135ec110 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 13 May 2026 09:56:57 +0200 Subject: [PATCH 5/5] fix: address Copilot Code Review round 1 feedback value (including false) when key is present, instead of only when truthy. Previously {:stop-processing-queue? false} was silently dropped from the wire payload. 2. instrument.clj fdef: tighten params spec so :stop-processing-queue? is only allowed when :handled? is true (mirrors upstream wire union QueuedCommandHandled vs QueuedCommandNotHandled where the field only exists on the handled=true branch). 3. integration_test: add coverage for explicit stop-processing-queue?=false forwarding. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/github/copilot_sdk/instrument.clj | 10 ++++++++-- src/github/copilot_sdk/session.clj | 6 +++--- test/github/copilot_sdk/integration_test.clj | 18 +++++++++++++++++- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/github/copilot_sdk/instrument.clj b/src/github/copilot_sdk/instrument.clj index 2e4214ac..c4eb34e0 100644 --- a/src/github/copilot_sdk/instrument.clj +++ b/src/github/copilot_sdk/instrument.clj @@ -311,8 +311,14 @@ (register-fdef! github.copilot-sdk.session/respond-to-queued-command! :args (s/cat :session ::specs/session - :params (s/keys :req-un [::specs/request-id ::specs/handled?] - :opt-un [::specs/stop-processing-queue?])) + :params (s/and + (s/keys :req-un [::specs/request-id ::specs/handled?] + :opt-un [::specs/stop-processing-queue?]) + ;; Wire schema: stopProcessingQueue is only valid on the + ;; handled=true branch (QueuedCommandHandled). Reject + ;; stop-processing-queue? alongside handled?=false. + #(or (:handled? %) + (not (contains? % :stop-processing-queue?))))) :ret any?) (register-fdef! github.copilot-sdk.session/mcp-list diff --git a/src/github/copilot_sdk/session.clj b/src/github/copilot_sdk/session.clj index 69a455b7..cf8ad768 100644 --- a/src/github/copilot_sdk/session.clj +++ b/src/github/copilot_sdk/session.clj @@ -1437,12 +1437,12 @@ Marked experimental — the upstream Node SDK exposes this only via the generated low-level `commands.respondToQueuedCommand` RPC (no high-level helper)." - [session {:keys [request-id handled? stop-processing-queue?] :as _params}] + [session {:keys [request-id handled? stop-processing-queue?] :as params}] (let [{:keys [session-id client]} session conn (connection-io client) result (cond-> {:handled (boolean handled?)} - (and handled? stop-processing-queue?) - (assoc :stopProcessingQueue true))] + (and handled? (contains? params :stop-processing-queue?)) + (assoc :stopProcessingQueue (boolean stop-processing-queue?)))] (proto/send-request! conn "session.commands.respondToQueuedCommand" {:sessionId session-id :requestId request-id diff --git a/test/github/copilot_sdk/integration_test.clj b/test/github/copilot_sdk/integration_test.clj index fd602015..a65ccd5e 100644 --- a/test/github/copilot_sdk/integration_test.clj +++ b/test/github/copilot_sdk/integration_test.clj @@ -1684,7 +1684,23 @@ (let [req (first (filter #(= "session.commands.respondToQueuedCommand" (:method %)) @requests))] (is (some? req)) (is (= "cmd-q-2" (:requestId (:params req)))) - (is (= {:handled false} (:result (:params req)))))))) + (is (= {:handled false} (:result (:params req))))))) + + (testing "respond-to-queued-command! forwards explicit stop-processing-queue?=false" + (let [requests (atom []) + session (sdk/create-session *test-client* {:on-permission-request sdk/approve-all})] + (mock/set-request-hook! *mock-server* + (fn [method params] + (swap! requests conj {:method method :params params}) + nil)) + (session/respond-to-queued-command! session + {:request-id "cmd-q-3" + :handled? true + :stop-processing-queue? false}) + (let [req (first (filter #(= "session.commands.respondToQueuedCommand" (:method %)) @requests))] + (is (some? req)) + (is (= {:handled true :stopProcessingQueue false} (:result (:params req))) + "explicit false should be forwarded on the wire (not silently dropped)"))))) (deftest test-send-async-untaps-on-send-failure (testing "send-async cleans up tap when RPC fails"