From 22cc8fa6707d2a72009d15d02e1cb330f0690955 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Sat, 23 May 2026 18:04:10 +0200 Subject: [PATCH 1/6] chore(schema): bump to 1.0.52-4 (upstream PR #1393) Regenerates schemas and event specs. Additive changes: - New event `mcp_app.tool_call_complete` (SEP-1865) - Optional `serviceRequestId` on error/assistant.message/assistant.usage/ model.call_failure/session.compaction_complete - Optional `contextTier` on session.model_change - Optional `transport`/`pluginName`/`pluginVersion` on loaded MCP servers - Optional `error` on mcp_server_status_changed - Optional `source`/`trigger` on skill.invoked - Optional `toolDescription`/`uiResource` on tool.execution_complete Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .copilot-schema-version | 2 +- schemas/README.md | 2 +- schemas/api.schema.json | 745 +++++++++++++++++- schemas/session-events.schema.json | 482 +++++++++++ .../copilot_sdk/generated/event_specs.clj | 60 +- 5 files changed, 1258 insertions(+), 33 deletions(-) diff --git a/.copilot-schema-version b/.copilot-schema-version index fa2dd9d..c221ad4 100644 --- a/.copilot-schema-version +++ b/.copilot-schema-version @@ -1 +1 @@ -1.0.52-1 +1.0.52-4 diff --git a/schemas/README.md b/schemas/README.md index c045c4e..1b66a5c 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.52-1` +Currently pinned version: `1.0.52-4` diff --git a/schemas/api.schema.json b/schemas/api.schema.json index 2e2a346..8d82d86 100644 --- a/schemas/api.schema.json +++ b/schemas/api.schema.json @@ -2094,6 +2094,217 @@ }, "stability": "experimental" } + }, + "apps": { + "readResource": { + "rpcMethod": "session.mcp.apps.readResource", + "description": "Fetch an MCP resource (typically a `ui://` MCP App bundle, per SEP-1865) from a connected server. Requires the `mcp-apps` session capability.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "Name of the MCP server hosting the resource" + }, + "uri": { + "type": "string", + "description": "Resource URI (typically ui://...)" + } + }, + "required": [ + "sessionId", + "serverName", + "uri" + ], + "additionalProperties": false, + "description": "MCP server and resource URI to fetch.", + "title": "McpAppsReadResourceRequest" + }, + "result": { + "$ref": "#/definitions/McpAppsReadResourceResult", + "description": "Resource contents returned by the MCP server." + }, + "stability": "experimental" + }, + "listTools": { + "rpcMethod": "session.mcp.apps.listTools", + "description": "List tools that an MCP App view is allowed to call (SEP-1865 visibility filter). Returns tools whose `_meta.ui.visibility` is unset (default `[\"model\",\"app\"]`) or includes `\"app\"`.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server hosting the app" + }, + "originServerName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "**Required.** Server whose ui:// view issued the request. Per SEP-1865 ('callable by the app from this server only'), the call is rejected when this differs from `serverName`, and rejected outright when missing." + } + }, + "required": [ + "sessionId", + "serverName", + "originServerName" + ], + "additionalProperties": false, + "description": "MCP server to list app-callable tools for.", + "title": "McpAppsListToolsRequest" + }, + "result": { + "$ref": "#/definitions/McpAppsListToolsResult", + "description": "App-callable tools from the named MCP server." + }, + "stability": "experimental" + }, + "callTool": { + "rpcMethod": "session.mcp.apps.callTool", + "description": "Call an MCP tool from an MCP App view (SEP-1865). Enforces the visibility check that prevents an app iframe from invoking model-only tools. Returns the standard MCP `CallToolResult`.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server hosting the tool" + }, + "toolName": { + "type": "string", + "description": "MCP tool name" + }, + "arguments": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Tool arguments" + }, + "originServerName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "**Required.** Server whose ui:// view issued the request. Per SEP-1865 ('callable by the app from this server only'), the call is rejected when this differs from `serverName`, and rejected outright when missing." + } + }, + "required": [ + "sessionId", + "serverName", + "toolName", + "originServerName" + ], + "additionalProperties": false, + "description": "MCP server, tool name, and arguments to invoke from an MCP App view.", + "title": "McpAppsCallToolRequest" + }, + "result": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Standard MCP CallToolResult" + }, + "stability": "experimental" + }, + "setHostContext": { + "rpcMethod": "session.mcp.apps.setHostContext", + "description": "Replace the host context returned to MCP App guests on `ui/initialize`. Hosts use this to advertise theme, locale, or other metadata to the guest UI.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "context": { + "$ref": "#/definitions/McpAppsSetHostContextDetails", + "description": "Host context advertised to MCP App guests" + } + }, + "required": [ + "sessionId", + "context" + ], + "additionalProperties": false, + "description": "Host context to advertise to MCP App guests.", + "title": "McpAppsSetHostContextRequest" + }, + "result": { + "type": "null" + }, + "stability": "experimental" + }, + "getHostContext": { + "rpcMethod": "session.mcp.apps.getHostContext", + "description": "Read the current host context advertised to MCP App guests.", + "params": { + "type": "object", + "description": "Identifies the target session.", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + } + }, + "required": [ + "sessionId" + ], + "additionalProperties": false + }, + "result": { + "$ref": "#/definitions/McpAppsHostContext", + "description": "Current host context advertised to MCP App guests." + }, + "stability": "experimental" + }, + "diagnose": { + "rpcMethod": "session.mcp.apps.diagnose", + "description": "Diagnose MCP Apps wiring for a specific MCP server. Reports the session capability, feature-flag state, advertised extension, and how many tools have `_meta.ui` populated.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server to probe" + } + }, + "required": [ + "sessionId", + "serverName" + ], + "additionalProperties": false, + "description": "MCP server to diagnose MCP Apps wiring for.", + "title": "McpAppsDiagnoseRequest" + }, + "result": { + "$ref": "#/definitions/McpAppsDiagnoseResult", + "description": "Diagnostic snapshot of MCP Apps wiring for the named server." + }, + "stability": "experimental" + } } }, "plugins": { @@ -6004,7 +6215,7 @@ }, "type": { "$ref": "#/definitions/DiscoveredMcpServerType", - "description": "Server transport type: stdio, http, sse, or memory" + "description": "Server transport type: stdio, http, sse (deprecated), or memory" }, "source": { "$ref": "#/definitions/McpServerSource", @@ -6032,12 +6243,12 @@ "sse", "memory" ], - "description": "Server transport type: stdio, http, sse, or memory", + "description": "Server transport type: stdio, http, sse (deprecated), or memory", "title": "DiscoveredMcpServerType", "x-enumDescriptions": { "stdio": "Server communicates over stdio with a local child process.", "http": "Server communicates over streamable HTTP.", - "sse": "Server communicates over Server-Sent Events.", + "sse": "Server communicates over Server-Sent Events (deprecated).", "memory": "Server is backed by an in-memory runtime implementation." } }, @@ -6531,6 +6742,13 @@ "description": { "type": "string", "description": "Human-readable description of the binary data" + }, + "metadata": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Optional metadata from the producing tool." } }, "required": [ @@ -7506,6 +7724,480 @@ "description": "Parameters for (re)loading the merged LSP configuration set.", "title": "LspInitializeRequest" }, + "McpAppsCallToolRequest": { + "type": "object", + "properties": { + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server hosting the tool" + }, + "toolName": { + "type": "string", + "description": "MCP tool name" + }, + "arguments": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Tool arguments" + }, + "originServerName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "**Required.** Server whose ui:// view issued the request. Per SEP-1865 ('callable by the app from this server only'), the call is rejected when this differs from `serverName`, and rejected outright when missing." + } + }, + "required": [ + "serverName", + "toolName", + "originServerName" + ], + "additionalProperties": false, + "description": "MCP server, tool name, and arguments to invoke from an MCP App view.", + "title": "McpAppsCallToolRequest" + }, + "McpAppsDiagnoseCapability": { + "type": "object", + "properties": { + "sessionHasMcpApps": { + "type": "boolean", + "description": "Whether the session has the `mcp-apps` capability" + }, + "featureFlagEnabled": { + "type": "boolean", + "description": "Whether the MCP_APPS feature flag (or COPILOT_MCP_APPS env override) is on" + }, + "advertised": { + "type": "boolean", + "description": "Whether the runtime advertises `extensions.io.modelcontextprotocol/ui` to MCP servers" + } + }, + "required": [ + "sessionHasMcpApps", + "featureFlagEnabled", + "advertised" + ], + "additionalProperties": false, + "description": "Capability negotiation snapshot", + "title": "McpAppsDiagnoseCapability" + }, + "McpAppsDiagnoseRequest": { + "type": "object", + "properties": { + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server to probe" + } + }, + "required": [ + "serverName" + ], + "additionalProperties": false, + "description": "MCP server to diagnose MCP Apps wiring for.", + "title": "McpAppsDiagnoseRequest" + }, + "McpAppsDiagnoseResult": { + "type": "object", + "properties": { + "capability": { + "$ref": "#/definitions/McpAppsDiagnoseCapability", + "description": "Capability negotiation snapshot" + }, + "server": { + "$ref": "#/definitions/McpAppsDiagnoseServer", + "description": "What the server returned for this session" + } + }, + "required": [ + "capability", + "server" + ], + "additionalProperties": false, + "description": "Diagnostic snapshot of MCP Apps wiring for the named server.", + "title": "McpAppsDiagnoseResult" + }, + "McpAppsDiagnoseServer": { + "type": "object", + "properties": { + "connected": { + "type": "boolean", + "description": "Whether the named server is currently connected" + }, + "toolCount": { + "type": "number", + "description": "Total tools returned by the server's tools/list" + }, + "toolsWithUiMeta": { + "type": "number", + "description": "Tools whose `_meta.ui` is populated (resourceUri and/or visibility set)" + }, + "sampleToolNames": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Up to 5 tool names with `_meta.ui` for quick inspection" + } + }, + "required": [ + "connected", + "toolCount", + "toolsWithUiMeta", + "sampleToolNames" + ], + "additionalProperties": false, + "description": "What the server returned for this session", + "title": "McpAppsDiagnoseServer" + }, + "McpAppsHostContext": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/McpAppsHostContextDetails", + "description": "Current host context" + } + }, + "required": [ + "context" + ], + "additionalProperties": false, + "description": "Current host context advertised to MCP App guests.", + "title": "McpAppsHostContext" + }, + "McpAppsHostContextDetails": { + "type": "object", + "properties": { + "theme": { + "$ref": "#/definitions/McpAppsHostContextDetailsTheme", + "description": "UI theme preference per SEP-1865" + }, + "locale": { + "type": "string", + "description": "BCP-47 locale, e.g. 'en-US'" + }, + "timeZone": { + "type": "string", + "description": "IANA timezone, e.g. 'America/New_York'" + }, + "displayMode": { + "$ref": "#/definitions/McpAppsHostContextDetailsDisplayMode", + "description": "Current display mode (SEP-1865)" + }, + "availableDisplayModes": { + "type": "array", + "items": { + "$ref": "#/definitions/McpAppsHostContextDetailsAvailableDisplayMode" + }, + "description": "Display modes the host supports" + }, + "platform": { + "$ref": "#/definitions/McpAppsHostContextDetailsPlatform", + "description": "Platform type for responsive design" + }, + "userAgent": { + "type": "string", + "description": "Host application identifier" + } + }, + "additionalProperties": {}, + "description": "Current host context", + "title": "McpAppsHostContextDetails" + }, + "McpAppsHostContextDetailsAvailableDisplayMode": { + "type": "string", + "enum": [ + "inline", + "fullscreen", + "pip" + ], + "title": "McpAppsHostContextDetailsAvailableDisplayMode", + "x-enumDescriptions": { + "inline": "Rendered inline within the host conversation surface", + "fullscreen": "Rendered as a fullscreen overlay", + "pip": "Rendered as a picture-in-picture floating panel" + }, + "description": "Allowed values for the `McpAppsHostContextDetailsAvailableDisplayMode` enumeration." + }, + "McpAppsHostContextDetailsDisplayMode": { + "type": "string", + "enum": [ + "inline", + "fullscreen", + "pip" + ], + "description": "Current display mode (SEP-1865)", + "title": "McpAppsHostContextDetailsDisplayMode", + "x-enumDescriptions": { + "inline": "Rendered inline within the host conversation surface", + "fullscreen": "Rendered as a fullscreen overlay", + "pip": "Rendered as a picture-in-picture floating panel" + } + }, + "McpAppsHostContextDetailsPlatform": { + "type": "string", + "enum": [ + "web", + "desktop", + "mobile" + ], + "description": "Platform type for responsive design", + "title": "McpAppsHostContextDetailsPlatform", + "x-enumDescriptions": { + "web": "Host runs in a web browser", + "desktop": "Host runs as a desktop application", + "mobile": "Host runs on a mobile device" + } + }, + "McpAppsHostContextDetailsTheme": { + "type": "string", + "enum": [ + "light", + "dark" + ], + "description": "UI theme preference per SEP-1865", + "title": "McpAppsHostContextDetailsTheme", + "x-enumDescriptions": { + "light": "Light UI theme", + "dark": "Dark UI theme" + } + }, + "McpAppsListToolsRequest": { + "type": "object", + "properties": { + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "MCP server hosting the app" + }, + "originServerName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "**Required.** Server whose ui:// view issued the request. Per SEP-1865 ('callable by the app from this server only'), the call is rejected when this differs from `serverName`, and rejected outright when missing." + } + }, + "required": [ + "serverName", + "originServerName" + ], + "additionalProperties": false, + "description": "MCP server to list app-callable tools for.", + "title": "McpAppsListToolsRequest" + }, + "McpAppsListToolsResult": { + "type": "object", + "properties": { + "tools": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + } + }, + "description": "App-callable tools from the server" + } + }, + "required": [ + "tools" + ], + "additionalProperties": false, + "description": "App-callable tools from the named MCP server.", + "title": "McpAppsListToolsResult" + }, + "McpAppsReadResourceRequest": { + "type": "object", + "properties": { + "serverName": { + "type": "string", + "minLength": 1, + "pattern": "^[^\\x00-\\x1f/\\x7f-\\x9f}]+(?:\\/[^\\x00-\\x1f/\\x7f-\\x9f}]+)*$", + "description": "Name of the MCP server hosting the resource" + }, + "uri": { + "type": "string", + "description": "Resource URI (typically ui://...)" + } + }, + "required": [ + "serverName", + "uri" + ], + "additionalProperties": false, + "description": "MCP server and resource URI to fetch.", + "title": "McpAppsReadResourceRequest" + }, + "McpAppsReadResourceResult": { + "type": "object", + "properties": { + "contents": { + "type": "array", + "items": { + "$ref": "#/definitions/McpAppsResourceContent" + }, + "description": "Resource contents returned by the server" + } + }, + "required": [ + "contents" + ], + "additionalProperties": false, + "description": "Resource contents returned by the MCP server.", + "title": "McpAppsReadResourceResult" + }, + "McpAppsResourceContent": { + "type": "object", + "properties": { + "uri": { + "type": "string", + "description": "The resource URI (typically ui://...)" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the content" + }, + "text": { + "type": "string", + "description": "Text content (e.g. HTML)" + }, + "blob": { + "type": "string", + "description": "Base64-encoded binary content" + }, + "_meta": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Resource-level metadata (CSP, permissions, etc.)" + } + }, + "required": [ + "uri" + ], + "additionalProperties": false, + "title": "McpAppsResourceContent", + "description": "Schema for the `McpAppsResourceContent` type." + }, + "McpAppsSetHostContextDetails": { + "type": "object", + "properties": { + "theme": { + "$ref": "#/definitions/McpAppsSetHostContextDetailsTheme", + "description": "UI theme preference per SEP-1865" + }, + "locale": { + "type": "string", + "description": "BCP-47 locale, e.g. 'en-US'" + }, + "timeZone": { + "type": "string", + "description": "IANA timezone, e.g. 'America/New_York'" + }, + "displayMode": { + "$ref": "#/definitions/McpAppsSetHostContextDetailsDisplayMode", + "description": "Current display mode (SEP-1865)" + }, + "availableDisplayModes": { + "type": "array", + "items": { + "$ref": "#/definitions/McpAppsSetHostContextDetailsAvailableDisplayMode" + }, + "description": "Display modes the host supports" + }, + "platform": { + "$ref": "#/definitions/McpAppsSetHostContextDetailsPlatform", + "description": "Platform type for responsive design" + }, + "userAgent": { + "type": "string", + "description": "Host application identifier" + } + }, + "additionalProperties": {}, + "description": "Host context advertised to MCP App guests", + "title": "McpAppsSetHostContextDetails" + }, + "McpAppsSetHostContextDetailsAvailableDisplayMode": { + "type": "string", + "enum": [ + "inline", + "fullscreen", + "pip" + ], + "title": "McpAppsSetHostContextDetailsAvailableDisplayMode", + "x-enumDescriptions": { + "inline": "Rendered inline within the host conversation surface", + "fullscreen": "Rendered as a fullscreen overlay", + "pip": "Rendered as a picture-in-picture floating panel" + }, + "description": "Allowed values for the `McpAppsSetHostContextDetailsAvailableDisplayMode` enumeration." + }, + "McpAppsSetHostContextDetailsDisplayMode": { + "type": "string", + "enum": [ + "inline", + "fullscreen", + "pip" + ], + "description": "Current display mode (SEP-1865)", + "title": "McpAppsSetHostContextDetailsDisplayMode", + "x-enumDescriptions": { + "inline": "Rendered inline within the host conversation surface", + "fullscreen": "Rendered as a fullscreen overlay", + "pip": "Rendered as a picture-in-picture floating panel" + } + }, + "McpAppsSetHostContextDetailsPlatform": { + "type": "string", + "enum": [ + "web", + "desktop", + "mobile" + ], + "description": "Platform type for responsive design", + "title": "McpAppsSetHostContextDetailsPlatform", + "x-enumDescriptions": { + "web": "Host runs in a web browser", + "desktop": "Host runs as a desktop application", + "mobile": "Host runs on a mobile device" + } + }, + "McpAppsSetHostContextDetailsTheme": { + "type": "string", + "enum": [ + "light", + "dark" + ], + "description": "UI theme preference per SEP-1865", + "title": "McpAppsSetHostContextDetailsTheme", + "x-enumDescriptions": { + "light": "Light UI theme", + "dark": "Dark UI theme" + } + }, + "McpAppsSetHostContextRequest": { + "type": "object", + "properties": { + "context": { + "$ref": "#/definitions/McpAppsSetHostContextDetails", + "description": "Host context advertised to MCP App guests" + } + }, + "required": [ + "context" + ], + "additionalProperties": false, + "description": "Host context to advertise to MCP App guests.", + "title": "McpAppsSetHostContextRequest" + }, "McpCancelSamplingExecutionParams": { "type": "object", "properties": { @@ -8483,31 +9175,66 @@ "type": "object", "properties": { "inputPrice": { - "type": "integer", + "type": "number", "minimum": 0, - "description": "Price per billing batch of input tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD)" + "description": "AI Credits cost per billing batch of input tokens" }, "outputPrice": { - "type": "integer", + "type": "number", "minimum": 0, - "description": "Price per billing batch of output tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD)" + "description": "AI Credits cost per billing batch of output tokens" }, "cachePrice": { - "type": "integer", + "type": "number", "minimum": 0, - "description": "Price per billing batch of cached tokens in nano-AIUs (1 nano-AIU = 0.000000001 AIU, 1 AIU = $0.01 USD)" + "description": "AI Credits cost per billing batch of cached tokens" }, "batchSize": { "type": "integer", "exclusiveMinimum": true, "minimum": 0, "description": "Number of tokens per standard billing batch" + }, + "contextMax": { + "type": "integer", + "description": "Maximum context window tokens for the default tier" + }, + "longContext": { + "$ref": "#/definitions/ModelBillingTokenPricesLongContext", + "description": "Long context tier pricing (available for models with extended context windows)" } }, "additionalProperties": false, "description": "Token-level pricing information for this model", "title": "ModelBillingTokenPrices" }, + "ModelBillingTokenPricesLongContext": { + "type": "object", + "properties": { + "inputPrice": { + "type": "number", + "minimum": 0, + "description": "AI Credits cost per billing batch of input tokens" + }, + "outputPrice": { + "type": "number", + "minimum": 0, + "description": "AI Credits cost per billing batch of output tokens" + }, + "cachePrice": { + "type": "number", + "minimum": 0, + "description": "AI Credits cost per billing batch of cached tokens" + }, + "contextMax": { + "type": "integer", + "description": "Maximum context window tokens for the long context tier" + } + }, + "additionalProperties": false, + "description": "Long context tier pricing (available for models with extended context windows)", + "title": "ModelBillingTokenPricesLongContext" + }, "ModelCapabilities": { "type": "object", "properties": { diff --git a/schemas/session-events.schema.json b/schemas/session-events.schema.json index 160fb55..88fb105 100644 --- a/schemas/session-events.schema.json +++ b/schemas/session-events.schema.json @@ -208,6 +208,10 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs" }, + "serviceRequestId": { + "type": "string", + "description": "Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation" + }, "anthropicAdvisorBlocks": { "type": "array", "items": { @@ -1016,6 +1020,10 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for server-side log correlation" }, + "serviceRequestId": { + "type": "string", + "description": "Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation" + }, "apiEndpoint": { "$ref": "#/definitions/AssistantUsageApiEndpoint", "description": "API endpoint used for this model call, matching CAPI supported_endpoints vocabulary" @@ -1478,6 +1486,10 @@ "elicitation": { "type": "boolean", "description": "Whether elicitation is now supported" + }, + "mcpApps": { + "type": "boolean", + "description": "Whether MCP Apps (SEP-1865) UI passthrough is now supported" } }, "additionalProperties": false, @@ -1972,6 +1984,10 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for the compaction LLM call" }, + "serviceRequestId": { + "type": "string", + "description": "Copilot service request ID (x-copilot-service-request-id header) for the compaction LLM call" + }, "systemTokens": { "type": "integer", "minimum": 0, @@ -2797,6 +2813,10 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for correlating with server-side logs" }, + "serviceRequestId": { + "type": "string", + "description": "Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation" + }, "url": { "type": "string", "description": "Optional URL associated with this error that the user can open in a browser" @@ -3829,6 +3849,160 @@ "description": "Session event \"session.info\". Informational message for timeline display with categorization", "title": "InfoEvent" }, + "McpAppToolCallCompleteData": { + "type": "object", + "properties": { + "serverName": { + "type": "string", + "description": "Name of the MCP server hosting the tool" + }, + "toolName": { + "type": "string", + "description": "MCP tool name that was invoked" + }, + "arguments": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Arguments passed to the tool by the app view, if any" + }, + "success": { + "type": "boolean", + "description": "True when the call completed without throwing AND the MCP CallToolResult did not set isError" + }, + "durationMs": { + "type": "number", + "description": "Wall-clock duration of the underlying tools/call in milliseconds" + }, + "result": { + "type": "object", + "additionalProperties": { + "x-opaque-json": true + }, + "description": "Standard MCP CallToolResult returned by the server. Present whether or not the call set isError." + }, + "error": { + "$ref": "#/definitions/McpAppToolCallCompleteError", + "description": "Set when the underlying tools/call threw an error before returning a CallToolResult" + }, + "toolMeta": { + "$ref": "#/definitions/McpAppToolCallCompleteToolMeta", + "description": "The tool's `_meta.ui` block at the time of the call, so consumers can decide whether to forward the result to the model without re-listing tools." + } + }, + "required": [ + "serverName", + "toolName", + "success", + "durationMs" + ], + "additionalProperties": false, + "description": "MCP App view called a tool on a connected MCP server (SEP-1865)", + "title": "McpAppToolCallCompleteData" + }, + "McpAppToolCallCompleteError": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Human-readable error message" + } + }, + "required": [ + "message" + ], + "additionalProperties": false, + "description": "Set when the underlying tools/call threw an error before returning a CallToolResult", + "title": "McpAppToolCallCompleteError" + }, + "McpAppToolCallCompleteEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique event identifier (UUID v4), generated when the event is emitted" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the event was created" + }, + "parentId": { + "anyOf": [ + { + "type": "string", + "format": "uuid" + }, + { + "type": "null" + } + ], + "description": "ID of the chronologically preceding event in the session, forming a linked chain. Null for the first event." + }, + "ephemeral": { + "type": "boolean", + "const": true, + "description": "Always true for events that are transient and not persisted to the session event log on disk." + }, + "agentId": { + "type": "string", + "description": "Sub-agent instance identifier. Absent for events from the root/main agent and session-level events." + }, + "type": { + "type": "string", + "const": "mcp_app.tool_call_complete", + "description": "Type discriminator. Always \"mcp_app.tool_call_complete\"." + }, + "data": { + "$ref": "#/definitions/McpAppToolCallCompleteData", + "description": "MCP App view called a tool on a connected MCP server (SEP-1865)" + } + }, + "required": [ + "id", + "timestamp", + "parentId", + "ephemeral", + "type", + "data" + ], + "additionalProperties": false, + "description": "Session event \"mcp_app.tool_call_complete\". MCP App view called a tool on a connected MCP server (SEP-1865)", + "title": "McpAppToolCallCompleteEvent" + }, + "McpAppToolCallCompleteToolMeta": { + "type": "object", + "properties": { + "ui": { + "$ref": "#/definitions/McpAppToolCallCompleteToolMetaUI", + "description": "Schema for the `McpAppToolCallCompleteToolMetaUI` type." + } + }, + "additionalProperties": true, + "description": "The tool's `_meta.ui` block at the time of the call, so consumers can decide whether to forward the result to the model without re-listing tools.", + "title": "McpAppToolCallCompleteToolMeta" + }, + "McpAppToolCallCompleteToolMetaUI": { + "type": "object", + "properties": { + "resourceUri": { + "type": "string", + "description": "`ui://` URI declared by the tool's `_meta.ui.resourceUri`" + }, + "visibility": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tool visibility per SEP-1865 (typically a subset of `[\"model\",\"app\"]`)" + } + }, + "additionalProperties": true, + "title": "McpAppToolCallCompleteToolMetaUI", + "description": "Schema for the `McpAppToolCallCompleteToolMetaUI` type." + }, "McpOauthCompletedData": { "type": "object", "properties": { @@ -4101,6 +4275,18 @@ "error": { "type": "string", "description": "Error message if the server failed to connect" + }, + "transport": { + "$ref": "#/definitions/McpServerTransport", + "description": "Transport mechanism: stdio, http, sse (deprecated), or memory (in-process MCP server)" + }, + "pluginName": { + "type": "string", + "description": "Name of the plugin that supplied the effective MCP server config, only when source is plugin" + }, + "pluginVersion": { + "type": "string", + "description": "Version of the plugin that supplied the effective MCP server config, only when source is plugin" } }, "required": [ @@ -4159,6 +4345,10 @@ "status": { "$ref": "#/definitions/McpServerStatus", "description": "Connection status: connected, failed, needs-auth, pending, disabled, or not_configured" + }, + "error": { + "type": "string", + "description": "Error message if the server entered a failed state" } }, "required": [ @@ -4225,6 +4415,23 @@ "description": "Session event \"session.mcp_server_status_changed\".", "title": "McpServerStatusChangedEvent" }, + "McpServerTransport": { + "type": "string", + "enum": [ + "stdio", + "http", + "sse", + "memory" + ], + "description": "Transport mechanism: stdio, http, sse (deprecated), or memory (in-process MCP server)", + "title": "McpServerTransport", + "x-enumDescriptions": { + "stdio": "Server communicates over stdio with a local child process.", + "http": "Server communicates over streamable HTTP.", + "sse": "Server communicates over Server-Sent Events (deprecated).", + "memory": "Server is backed by an in-memory runtime implementation." + } + }, "ModeChangedData": { "type": "object", "properties": { @@ -4318,6 +4525,10 @@ "type": "string", "description": "GitHub request tracing ID (x-github-request-id header) for server-side log correlation" }, + "serviceRequestId": { + "type": "string", + "description": "Copilot service request ID (x-copilot-service-request-id header) for CAPI log correlation" + }, "statusCode": { "type": "integer", "minimum": 0, @@ -4447,6 +4658,25 @@ "$ref": "#/definitions/ReasoningSummary", "description": "Reasoning summary mode after the model change, if applicable" }, + "contextTier": { + "anyOf": [ + { + "type": "string", + "enum": [ + "default", + "long_context" + ], + "x-enumDescriptions": { + "default": "Default context tier with standard context window size.", + "long_context": "Extended context tier with a larger context window." + } + }, + { + "type": "null" + } + ], + "description": "Context tier after the model change; null explicitly clears a previously selected tier" + }, "cause": { "type": "string", "description": "Reason the change happened, when not user-initiated. Currently `\"rate_limit_auto_switch\"` for changes triggered by the auto-mode-switch rate-limit recovery path. UI clients can use this to render contextual copy." @@ -6872,6 +7102,10 @@ { "$ref": "#/definitions/ExtensionsLoadedEvent", "description": "Session event \"session.extensions_loaded\"." + }, + { + "$ref": "#/definitions/McpAppToolCallCompleteEvent", + "description": "Session event \"mcp_app.tool_call_complete\". MCP App view called a tool on a connected MCP server (SEP-1865)" } ], "description": "Union of all session event variants emitted by the Copilot CLI runtime." @@ -7221,6 +7455,10 @@ }, "description": "Tool names that should be auto-approved when this skill is active" }, + "source": { + "type": "string", + "description": "Source identifier for where the skill was discovered. Known values include: project (workspace skill), inherited (parent-directory skill), personal-copilot (~/.copilot/skills), personal-agents (~/.agents/skills), personal-claude (~/.claude/skills), custom (configured directory), plugin (installed plugin), builtin (bundled runtime skill), and remote (org/enterprise skill)" + }, "pluginName": { "type": "string", "description": "Name of the plugin this skill originated from, when applicable" @@ -7232,6 +7470,10 @@ "description": { "type": "string", "description": "Description of the skill from its SKILL.md frontmatter" + }, + "trigger": { + "$ref": "#/definitions/SkillInvokedTrigger", + "description": "What triggered the skill invocation: `user-invoked` (explicit user action, such as via a slash command or UI affordance), `agent-invoked` (agent requested the skill), or `context-load` (loaded as part of another context, such as preloading skills configured on a custom agent or subagent)" } }, "required": [ @@ -7297,6 +7539,21 @@ "description": "Session event \"skill.invoked\". Skill invocation details including content, allowed tools, and plugin metadata", "title": "SkillInvokedEvent" }, + "SkillInvokedTrigger": { + "type": "string", + "enum": [ + "user-invoked", + "agent-invoked", + "context-load" + ], + "description": "What triggered the skill invocation: `user-invoked` (explicit user action, such as via a slash command or UI affordance), `agent-invoked` (agent requested the skill), or `context-load` (loaded as part of another context, such as preloading skills configured on a custom agent or subagent)", + "title": "SkillInvokedTrigger", + "x-enumDescriptions": { + "user-invoked": "Skill invocation requested explicitly by the user, such as via a slash command or UI affordance.", + "agent-invoked": "Skill invocation requested by the agent.", + "context-load": "Skill content loaded as part of another context, such as a configured custom agent or subagent." + } + }, "SkillsLoadedData": { "type": "object", "properties": { @@ -8934,6 +9191,10 @@ "type": "string", "description": "Identifier for the agent loop turn this tool was invoked in, matching the corresponding assistant.turn_start event" }, + "toolDescription": { + "$ref": "#/definitions/ToolExecutionCompleteToolDescription", + "description": "Tool definition metadata, present for MCP tools with MCP Apps support" + }, "sandboxed": { "type": "boolean", "description": "Whether this tool execution ran inside a sandbox container" @@ -9043,6 +9304,10 @@ "description": "A content block within a tool result, which may be text, terminal output, image, audio, or a resource" }, "description": "Structured content blocks (text, images, audio, resources) returned by the tool in their native format" + }, + "uiResource": { + "$ref": "#/definitions/ToolExecutionCompleteUIResource", + "description": "MCP Apps UI resource content for rendering in a sandboxed iframe" } }, "required": [ @@ -9052,6 +9317,223 @@ "description": "Tool execution result on success", "title": "ToolExecutionCompleteResult" }, + "ToolExecutionCompleteToolDescription": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Tool name" + }, + "description": { + "type": "string", + "description": "Tool description" + }, + "_meta": { + "$ref": "#/definitions/ToolExecutionCompleteToolDescriptionMeta", + "description": "MCP Apps metadata for UI resource association" + } + }, + "required": [ + "name" + ], + "additionalProperties": false, + "description": "Tool definition metadata, present for MCP tools with MCP Apps support", + "title": "ToolExecutionCompleteToolDescription" + }, + "ToolExecutionCompleteToolDescriptionMeta": { + "type": "object", + "properties": { + "ui": { + "$ref": "#/definitions/ToolExecutionCompleteToolDescriptionMetaUI", + "description": "Schema for the `ToolExecutionCompleteToolDescriptionMetaUI` type." + } + }, + "additionalProperties": false, + "description": "MCP Apps metadata for UI resource association", + "title": "ToolExecutionCompleteToolDescriptionMeta" + }, + "ToolExecutionCompleteToolDescriptionMetaUI": { + "type": "object", + "properties": { + "resourceUri": { + "type": "string", + "description": "URI of the UI resource" + }, + "visibility": { + "type": "array", + "items": { + "$ref": "#/definitions/ToolExecutionCompleteToolDescriptionMetaUIVisibility" + }, + "description": "Who can access this tool" + } + }, + "additionalProperties": false, + "title": "ToolExecutionCompleteToolDescriptionMetaUI", + "description": "Schema for the `ToolExecutionCompleteToolDescriptionMetaUI` type." + }, + "ToolExecutionCompleteToolDescriptionMetaUIVisibility": { + "type": "string", + "enum": [ + "model", + "app" + ], + "title": "ToolExecutionCompleteToolDescriptionMetaUIVisibility", + "x-enumDescriptions": { + "model": "Tool is callable by the model (LLM tool surface)", + "app": "Tool is callable by the MCP App view (iframe) via session.mcp.apps.callTool" + }, + "description": "Allowed values for the `ToolExecutionCompleteToolDescriptionMetaUIVisibility` enumeration." + }, + "ToolExecutionCompleteUIResource": { + "type": "object", + "properties": { + "uri": { + "type": "string", + "description": "The ui:// URI of the resource" + }, + "mimeType": { + "type": "string", + "description": "MIME type of the content" + }, + "text": { + "type": "string", + "description": "HTML content as a string" + }, + "blob": { + "type": "string", + "description": "Base64-encoded HTML content" + }, + "_meta": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMeta", + "description": "Resource-level UI metadata (CSP, permissions, visual preferences)" + } + }, + "required": [ + "uri", + "mimeType" + ], + "additionalProperties": false, + "description": "MCP Apps UI resource content for rendering in a sandboxed iframe", + "title": "ToolExecutionCompleteUIResource" + }, + "ToolExecutionCompleteUIResourceMeta": { + "type": "object", + "properties": { + "ui": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUI", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUI` type." + } + }, + "additionalProperties": false, + "description": "Resource-level UI metadata (CSP, permissions, visual preferences)", + "title": "ToolExecutionCompleteUIResourceMeta" + }, + "ToolExecutionCompleteUIResourceMetaUI": { + "type": "object", + "properties": { + "csp": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUICsp", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUICsp` type." + }, + "permissions": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUIPermissions", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissions` type." + }, + "domain": { + "type": "string" + }, + "prefersBorder": { + "type": "boolean" + } + }, + "additionalProperties": false, + "title": "ToolExecutionCompleteUIResourceMetaUI", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUI` type." + }, + "ToolExecutionCompleteUIResourceMetaUICsp": { + "type": "object", + "properties": { + "connectDomains": { + "type": "array", + "items": { + "type": "string" + } + }, + "resourceDomains": { + "type": "array", + "items": { + "type": "string" + } + }, + "frameDomains": { + "type": "array", + "items": { + "type": "string" + } + }, + "baseUriDomains": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": false, + "title": "ToolExecutionCompleteUIResourceMetaUICsp", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUICsp` type." + }, + "ToolExecutionCompleteUIResourceMetaUIPermissions": { + "type": "object", + "properties": { + "camera": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUIPermissionsCamera", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsCamera` type." + }, + "microphone": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUIPermissionsMicrophone", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsMicrophone` type." + }, + "geolocation": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUIPermissionsGeolocation", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsGeolocation` type." + }, + "clipboardWrite": { + "$ref": "#/definitions/ToolExecutionCompleteUIResourceMetaUIPermissionsClipboardWrite", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsClipboardWrite` type." + } + }, + "additionalProperties": false, + "title": "ToolExecutionCompleteUIResourceMetaUIPermissions", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissions` type." + }, + "ToolExecutionCompleteUIResourceMetaUIPermissionsCamera": { + "type": "object", + "properties": {}, + "additionalProperties": true, + "title": "ToolExecutionCompleteUIResourceMetaUIPermissionsCamera", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsCamera` type." + }, + "ToolExecutionCompleteUIResourceMetaUIPermissionsClipboardWrite": { + "type": "object", + "properties": {}, + "additionalProperties": true, + "title": "ToolExecutionCompleteUIResourceMetaUIPermissionsClipboardWrite", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsClipboardWrite` type." + }, + "ToolExecutionCompleteUIResourceMetaUIPermissionsGeolocation": { + "type": "object", + "properties": {}, + "additionalProperties": true, + "title": "ToolExecutionCompleteUIResourceMetaUIPermissionsGeolocation", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsGeolocation` type." + }, + "ToolExecutionCompleteUIResourceMetaUIPermissionsMicrophone": { + "type": "object", + "properties": {}, + "additionalProperties": true, + "title": "ToolExecutionCompleteUIResourceMetaUIPermissionsMicrophone", + "description": "Schema for the `ToolExecutionCompleteUIResourceMetaUIPermissionsMicrophone` type." + }, "ToolExecutionPartialData": { "type": "object", "properties": { diff --git a/src/github/copilot_sdk/generated/event_specs.clj b/src/github/copilot_sdk/generated/event_specs.clj index b64ab34..567e35a 100644 --- a/src/github/copilot_sdk/generated/event_specs.clj +++ b/src/github/copilot_sdk/generated/event_specs.clj @@ -41,7 +41,7 @@ (s/def :github.copilot-sdk.generated.event-specs/args clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/arguments clojure.core/any?) +(s/def :github.copilot-sdk.generated.event-specs/arguments (s/spec (fn [v948] (or (s/valid? clojure.core/any? v948) (s/valid? clojure.core/map? v948))))) (s/def :github.copilot-sdk.generated.event-specs/attachments (s/coll-of (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?))) @@ -73,9 +73,11 @@ (s/def :github.copilot-sdk.generated.event-specs/compaction-tokens-used clojure.core/map?) -(s/def :github.copilot-sdk.generated.event-specs/content (s/spec (fn [v942] (or (s/valid? clojure.core/string? v942) (s/valid? clojure.core/map? v942))))) +(s/def :github.copilot-sdk.generated.event-specs/content (s/spec (fn [v945] (or (s/valid? clojure.core/string? v945) (s/valid? clojure.core/map? v945))))) -(s/def :github.copilot-sdk.generated.event-specs/context (s/spec (fn [v940] (or (s/valid? clojure.core/map? v940) (s/valid? clojure.core/string? v940))))) +(s/def :github.copilot-sdk.generated.event-specs/context (s/spec (fn [v943] (or (s/valid? clojure.core/map? v943) (s/valid? clojure.core/string? v943))))) + +(s/def :github.copilot-sdk.generated.event-specs/context-tier (s/nilable #{"long_context" "default"})) (s/def :github.copilot-sdk.generated.event-specs/continue-pending-work clojure.core/boolean?) @@ -107,7 +109,7 @@ (s/def :github.copilot-sdk.generated.event-specs/duration clojure.core/integer?) -(s/def :github.copilot-sdk.generated.event-specs/duration-ms clojure.core/integer?) +(s/def :github.copilot-sdk.generated.event-specs/duration-ms (s/spec (fn [v938] (or (s/valid? clojure.core/integer? v938) (s/valid? clojure.core/number? v938))))) (s/def :github.copilot-sdk.generated.event-specs/elicitation-source clojure.core/string?) @@ -117,7 +119,7 @@ (s/def :github.copilot-sdk.generated.event-specs/ephemeral clojure.core/boolean?) -(s/def :github.copilot-sdk.generated.event-specs/error (s/spec (fn [v937] (or (s/valid? clojure.core/string? v937) (s/valid? clojure.core/map? v937))))) +(s/def :github.copilot-sdk.generated.event-specs/error (s/spec (fn [v940] (or (s/valid? clojure.core/string? v940) (s/valid? clojure.core/map? v940))))) (s/def :github.copilot-sdk.generated.event-specs/error-code clojure.core/string?) @@ -151,7 +153,7 @@ (s/def :github.copilot-sdk.generated.event-specs/host-type #{"github" "ado"}) -(s/def :github.copilot-sdk.generated.event-specs/id (s/spec (fn [v938] (or (s/valid? clojure.core/string? v938) (s/valid? clojure.core/integer? v938))))) +(s/def :github.copilot-sdk.generated.event-specs/id (s/spec (fn [v941] (or (s/valid? clojure.core/string? v941) (s/valid? clojure.core/integer? v941))))) (s/def :github.copilot-sdk.generated.event-specs/info-type clojure.core/string?) @@ -209,7 +211,7 @@ (s/def :github.copilot-sdk.generated.event-specs/new-model clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/operation (s/spec (fn [v941] (or (s/valid? #{"delete" "update" "create"} v941) (s/valid? #{"update" "create"} v941))))) +(s/def :github.copilot-sdk.generated.event-specs/operation (s/spec (fn [v944] (or (s/valid? #{"delete" "update" "create"} v944) (s/valid? #{"update" "create"} v944))))) (s/def :github.copilot-sdk.generated.event-specs/output clojure.core/any?) @@ -277,7 +279,7 @@ (s/def :github.copilot-sdk.generated.event-specs/reason #{"user_abort" "remote_command" "user_initiated"}) -(s/def :github.copilot-sdk.generated.event-specs/reasoning-effort (s/spec (fn [v939] (or (s/valid? clojure.core/string? v939) (s/valid? clojure.core/any? v939))))) +(s/def :github.copilot-sdk.generated.event-specs/reasoning-effort (s/spec (fn [v942] (or (s/valid? clojure.core/string? v942) (s/valid? clojure.core/any? v942))))) (s/def :github.copilot-sdk.generated.event-specs/reasoning-id clojure.core/string?) @@ -297,7 +299,7 @@ (s/def :github.copilot-sdk.generated.event-specs/remote-steerable clojure.core/boolean?) -(s/def :github.copilot-sdk.generated.event-specs/repository (s/spec (fn [v936] (or (s/valid? clojure.core/map? v936) (s/valid? clojure.core/string? v936))))) +(s/def :github.copilot-sdk.generated.event-specs/repository (s/spec (fn [v939] (or (s/valid? clojure.core/map? v939) (s/valid? clojure.core/string? v939))))) (s/def :github.copilot-sdk.generated.event-specs/repository-host clojure.core/string?) @@ -309,7 +311,7 @@ (s/def :github.copilot-sdk.generated.event-specs/response #{"yes_always" "yes" "no"}) -(s/def :github.copilot-sdk.generated.event-specs/result (s/spec (fn [v945] (or (s/valid? clojure.core/map? v945) (s/valid? (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?) v945))))) +(s/def :github.copilot-sdk.generated.event-specs/result (s/spec (fn [v949] (or (s/valid? clojure.core/map? v949) (s/valid? (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?) v949))))) (s/def :github.copilot-sdk.generated.event-specs/resume-time clojure.core/string?) @@ -329,6 +331,8 @@ (s/def :github.copilot-sdk.generated.event-specs/servers (s/coll-of clojure.core/map?)) +(s/def :github.copilot-sdk.generated.event-specs/service-request-id clojure.core/string?) + (s/def :github.copilot-sdk.generated.event-specs/session-id clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/session-start-time clojure.core/integer?) @@ -339,7 +343,7 @@ (s/def :github.copilot-sdk.generated.event-specs/skills (s/coll-of clojure.core/map?)) -(s/def :github.copilot-sdk.generated.event-specs/source (s/spec (fn [v943] (or (s/valid? clojure.core/string? v943) (s/valid? #{"top_level" "subagent" "mcp_sampling"} v943))))) +(s/def :github.copilot-sdk.generated.event-specs/source (s/spec (fn [v946] (or (s/valid? clojure.core/string? v946) (s/valid? #{"top_level" "subagent" "mcp_sampling"} v946))))) (s/def :github.copilot-sdk.generated.event-specs/source-type #{"remote" "local"}) @@ -385,6 +389,10 @@ (s/def :github.copilot-sdk.generated.event-specs/tool-definitions-tokens clojure.core/integer?) +(s/def :github.copilot-sdk.generated.event-specs/tool-description clojure.core/map?) + +(s/def :github.copilot-sdk.generated.event-specs/tool-meta clojure.core/map?) + (s/def :github.copilot-sdk.generated.event-specs/tool-name clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/tool-requests (s/coll-of clojure.core/map?)) @@ -411,9 +419,11 @@ (s/def :github.copilot-sdk.generated.event-specs/transformed-content clojure.core/string?) +(s/def :github.copilot-sdk.generated.event-specs/trigger #{"agent-invoked" "user-invoked" "context-load"}) + (s/def :github.copilot-sdk.generated.event-specs/turn-id clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/type (s/spec (fn [v944] (or (s/valid? #{"session.start"} v944) (s/valid? #{"session.resume"} v944) (s/valid? #{"session.remote_steerable_changed"} v944) (s/valid? #{"session.error"} v944) (s/valid? #{"session.idle"} v944) (s/valid? #{"session.title_changed"} v944) (s/valid? #{"session.schedule_created"} v944) (s/valid? #{"session.schedule_cancelled"} v944) (s/valid? #{"session.info"} v944) (s/valid? #{"session.warning"} v944) (s/valid? #{"session.model_change"} v944) (s/valid? #{"session.mode_changed"} v944) (s/valid? #{"session.plan_changed"} v944) (s/valid? #{"session.workspace_file_changed"} v944) (s/valid? #{"session.handoff"} v944) (s/valid? #{"session.truncation"} v944) (s/valid? #{"session.snapshot_rewind"} v944) (s/valid? #{"session.shutdown"} v944) (s/valid? #{"session.context_changed"} v944) (s/valid? #{"session.usage_info"} v944) (s/valid? #{"session.compaction_start"} v944) (s/valid? #{"session.compaction_complete"} v944) (s/valid? #{"session.task_complete"} v944) (s/valid? #{"user.message"} v944) (s/valid? #{"pending_messages.modified"} v944) (s/valid? #{"assistant.turn_start"} v944) (s/valid? #{"assistant.intent"} v944) (s/valid? #{"assistant.reasoning"} v944) (s/valid? #{"assistant.reasoning_delta"} v944) (s/valid? #{"assistant.streaming_delta"} v944) (s/valid? #{"assistant.message"} v944) (s/valid? #{"assistant.message_start"} v944) (s/valid? #{"assistant.message_delta"} v944) (s/valid? #{"assistant.turn_end"} v944) (s/valid? #{"assistant.usage"} v944) (s/valid? #{"model.call_failure"} v944) (s/valid? #{"abort"} v944) (s/valid? #{"tool.user_requested"} v944) (s/valid? #{"tool.execution_start"} v944) (s/valid? #{"tool.execution_partial_result"} v944) (s/valid? #{"tool.execution_progress"} v944) (s/valid? #{"tool.execution_complete"} v944) (s/valid? #{"skill.invoked"} v944) (s/valid? #{"subagent.started"} v944) (s/valid? #{"subagent.completed"} v944) (s/valid? #{"subagent.failed"} v944) (s/valid? #{"subagent.selected"} v944) (s/valid? #{"subagent.deselected"} v944) (s/valid? #{"hook.start"} v944) (s/valid? #{"hook.end"} v944) (s/valid? #{"system.message"} v944) (s/valid? #{"system.notification"} v944) (s/valid? #{"permission.requested"} v944) (s/valid? #{"permission.completed"} v944) (s/valid? #{"user_input.requested"} v944) (s/valid? #{"user_input.completed"} v944) (s/valid? #{"elicitation.requested"} v944) (s/valid? #{"elicitation.completed"} v944) (s/valid? #{"sampling.requested"} v944) (s/valid? #{"sampling.completed"} v944) (s/valid? #{"mcp.oauth_required"} v944) (s/valid? #{"mcp.oauth_completed"} v944) (s/valid? #{"session.custom_notification"} v944) (s/valid? #{"external_tool.requested"} v944) (s/valid? #{"external_tool.completed"} v944) (s/valid? #{"command.queued"} v944) (s/valid? #{"command.execute"} v944) (s/valid? #{"command.completed"} v944) (s/valid? #{"auto_mode_switch.requested"} v944) (s/valid? #{"auto_mode_switch.completed"} v944) (s/valid? #{"commands.changed"} v944) (s/valid? #{"capabilities.changed"} v944) (s/valid? #{"exit_plan_mode.requested"} v944) (s/valid? #{"exit_plan_mode.completed"} v944) (s/valid? #{"session.tools_updated"} v944) (s/valid? #{"session.background_tasks_changed"} v944) (s/valid? #{"session.skills_loaded"} v944) (s/valid? #{"session.custom_agents_updated"} v944) (s/valid? #{"session.mcp_servers_loaded"} v944) (s/valid? #{"session.mcp_server_status_changed"} v944) (s/valid? #{"session.extensions_loaded"} v944))))) +(s/def :github.copilot-sdk.generated.event-specs/type (s/spec (fn [v947] (or (s/valid? #{"session.start"} v947) (s/valid? #{"session.resume"} v947) (s/valid? #{"session.remote_steerable_changed"} v947) (s/valid? #{"session.error"} v947) (s/valid? #{"session.idle"} v947) (s/valid? #{"session.title_changed"} v947) (s/valid? #{"session.schedule_created"} v947) (s/valid? #{"session.schedule_cancelled"} v947) (s/valid? #{"session.info"} v947) (s/valid? #{"session.warning"} v947) (s/valid? #{"session.model_change"} v947) (s/valid? #{"session.mode_changed"} v947) (s/valid? #{"session.plan_changed"} v947) (s/valid? #{"session.workspace_file_changed"} v947) (s/valid? #{"session.handoff"} v947) (s/valid? #{"session.truncation"} v947) (s/valid? #{"session.snapshot_rewind"} v947) (s/valid? #{"session.shutdown"} v947) (s/valid? #{"session.context_changed"} v947) (s/valid? #{"session.usage_info"} v947) (s/valid? #{"session.compaction_start"} v947) (s/valid? #{"session.compaction_complete"} v947) (s/valid? #{"session.task_complete"} v947) (s/valid? #{"user.message"} v947) (s/valid? #{"pending_messages.modified"} v947) (s/valid? #{"assistant.turn_start"} v947) (s/valid? #{"assistant.intent"} v947) (s/valid? #{"assistant.reasoning"} v947) (s/valid? #{"assistant.reasoning_delta"} v947) (s/valid? #{"assistant.streaming_delta"} v947) (s/valid? #{"assistant.message"} v947) (s/valid? #{"assistant.message_start"} v947) (s/valid? #{"assistant.message_delta"} v947) (s/valid? #{"assistant.turn_end"} v947) (s/valid? #{"assistant.usage"} v947) (s/valid? #{"model.call_failure"} v947) (s/valid? #{"abort"} v947) (s/valid? #{"tool.user_requested"} v947) (s/valid? #{"tool.execution_start"} v947) (s/valid? #{"tool.execution_partial_result"} v947) (s/valid? #{"tool.execution_progress"} v947) (s/valid? #{"tool.execution_complete"} v947) (s/valid? #{"skill.invoked"} v947) (s/valid? #{"subagent.started"} v947) (s/valid? #{"subagent.completed"} v947) (s/valid? #{"subagent.failed"} v947) (s/valid? #{"subagent.selected"} v947) (s/valid? #{"subagent.deselected"} v947) (s/valid? #{"hook.start"} v947) (s/valid? #{"hook.end"} v947) (s/valid? #{"system.message"} v947) (s/valid? #{"system.notification"} v947) (s/valid? #{"permission.requested"} v947) (s/valid? #{"permission.completed"} v947) (s/valid? #{"user_input.requested"} v947) (s/valid? #{"user_input.completed"} v947) (s/valid? #{"elicitation.requested"} v947) (s/valid? #{"elicitation.completed"} v947) (s/valid? #{"sampling.requested"} v947) (s/valid? #{"sampling.completed"} v947) (s/valid? #{"mcp.oauth_required"} v947) (s/valid? #{"mcp.oauth_completed"} v947) (s/valid? #{"session.custom_notification"} v947) (s/valid? #{"external_tool.requested"} v947) (s/valid? #{"external_tool.completed"} v947) (s/valid? #{"command.queued"} v947) (s/valid? #{"command.execute"} v947) (s/valid? #{"command.completed"} v947) (s/valid? #{"auto_mode_switch.requested"} v947) (s/valid? #{"auto_mode_switch.completed"} v947) (s/valid? #{"commands.changed"} v947) (s/valid? #{"capabilities.changed"} v947) (s/valid? #{"exit_plan_mode.requested"} v947) (s/valid? #{"exit_plan_mode.completed"} v947) (s/valid? #{"session.tools_updated"} v947) (s/valid? #{"session.background_tasks_changed"} v947) (s/valid? #{"session.skills_loaded"} v947) (s/valid? #{"session.custom_agents_updated"} v947) (s/valid? #{"session.mcp_servers_loaded"} v947) (s/valid? #{"session.mcp_server_status_changed"} v947) (s/valid? #{"session.extensions_loaded"} v947) (s/valid? #{"mcp_app.tool_call_complete"} v947))))) (s/def :github.copilot-sdk.generated.event-specs/ui clojure.core/map?) @@ -433,7 +443,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/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-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/service-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])) @@ -449,7 +459,7 @@ (s/def :github.copilot-sdk.generated.event-specs/assistant.turn_start-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/turn-id] :opt-un [:github.copilot-sdk.generated.event-specs/interaction-id])) -(s/def :github.copilot-sdk.generated.event-specs/assistant.usage-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/model] :opt-un [:github.copilot-sdk.generated.event-specs/api-call-id :github.copilot-sdk.generated.event-specs/api-endpoint :github.copilot-sdk.generated.event-specs/cache-read-tokens :github.copilot-sdk.generated.event-specs/cache-write-tokens :github.copilot-sdk.generated.event-specs/copilot-usage :github.copilot-sdk.generated.event-specs/cost :github.copilot-sdk.generated.event-specs/duration :github.copilot-sdk.generated.event-specs/initiator :github.copilot-sdk.generated.event-specs/input-tokens :github.copilot-sdk.generated.event-specs/inter-token-latency-ms :github.copilot-sdk.generated.event-specs/output-tokens :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/quota-snapshots :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/reasoning-tokens :github.copilot-sdk.generated.event-specs/time-to-first-token-ms])) +(s/def :github.copilot-sdk.generated.event-specs/assistant.usage-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/model] :opt-un [:github.copilot-sdk.generated.event-specs/api-call-id :github.copilot-sdk.generated.event-specs/api-endpoint :github.copilot-sdk.generated.event-specs/cache-read-tokens :github.copilot-sdk.generated.event-specs/cache-write-tokens :github.copilot-sdk.generated.event-specs/copilot-usage :github.copilot-sdk.generated.event-specs/cost :github.copilot-sdk.generated.event-specs/duration :github.copilot-sdk.generated.event-specs/initiator :github.copilot-sdk.generated.event-specs/input-tokens :github.copilot-sdk.generated.event-specs/inter-token-latency-ms :github.copilot-sdk.generated.event-specs/output-tokens :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/quota-snapshots :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/reasoning-tokens :github.copilot-sdk.generated.event-specs/service-request-id :github.copilot-sdk.generated.event-specs/time-to-first-token-ms])) (s/def :github.copilot-sdk.generated.event-specs/auto_mode_switch.completed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/response])) @@ -485,7 +495,9 @@ (s/def :github.copilot-sdk.generated.event-specs/mcp.oauth_required-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/server-name :github.copilot-sdk.generated.event-specs/server-url] :opt-un [:github.copilot-sdk.generated.event-specs/static-client-config])) -(s/def :github.copilot-sdk.generated.event-specs/model.call_failure-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/source] :opt-un [:github.copilot-sdk.generated.event-specs/api-call-id :github.copilot-sdk.generated.event-specs/duration-ms :github.copilot-sdk.generated.event-specs/error-message :github.copilot-sdk.generated.event-specs/initiator :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/status-code])) +(s/def :github.copilot-sdk.generated.event-specs/mcp_app.tool_call_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/duration-ms :github.copilot-sdk.generated.event-specs/server-name :github.copilot-sdk.generated.event-specs/success :github.copilot-sdk.generated.event-specs/tool-name] :opt-un [:github.copilot-sdk.generated.event-specs/arguments :github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/result :github.copilot-sdk.generated.event-specs/tool-meta])) + +(s/def :github.copilot-sdk.generated.event-specs/model.call_failure-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/source] :opt-un [:github.copilot-sdk.generated.event-specs/api-call-id :github.copilot-sdk.generated.event-specs/duration-ms :github.copilot-sdk.generated.event-specs/error-message :github.copilot-sdk.generated.event-specs/initiator :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/service-request-id :github.copilot-sdk.generated.event-specs/status-code])) (s/def :github.copilot-sdk.generated.event-specs/pending_messages.modified-data (s/keys)) @@ -499,7 +511,7 @@ (s/def :github.copilot-sdk.generated.event-specs/session.background_tasks_changed-data (s/keys)) -(s/def :github.copilot-sdk.generated.event-specs/session.compaction_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/success] :opt-un [:github.copilot-sdk.generated.event-specs/checkpoint-number :github.copilot-sdk.generated.event-specs/checkpoint-path :github.copilot-sdk.generated.event-specs/compaction-tokens-used :github.copilot-sdk.generated.event-specs/conversation-tokens :github.copilot-sdk.generated.event-specs/custom-instructions :github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/messages-removed :github.copilot-sdk.generated.event-specs/post-compaction-tokens :github.copilot-sdk.generated.event-specs/pre-compaction-messages-length :github.copilot-sdk.generated.event-specs/pre-compaction-tokens :github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/summary-content :github.copilot-sdk.generated.event-specs/system-tokens :github.copilot-sdk.generated.event-specs/tokens-removed :github.copilot-sdk.generated.event-specs/tool-definitions-tokens])) +(s/def :github.copilot-sdk.generated.event-specs/session.compaction_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/success] :opt-un [:github.copilot-sdk.generated.event-specs/checkpoint-number :github.copilot-sdk.generated.event-specs/checkpoint-path :github.copilot-sdk.generated.event-specs/compaction-tokens-used :github.copilot-sdk.generated.event-specs/conversation-tokens :github.copilot-sdk.generated.event-specs/custom-instructions :github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/messages-removed :github.copilot-sdk.generated.event-specs/post-compaction-tokens :github.copilot-sdk.generated.event-specs/pre-compaction-messages-length :github.copilot-sdk.generated.event-specs/pre-compaction-tokens :github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/service-request-id :github.copilot-sdk.generated.event-specs/summary-content :github.copilot-sdk.generated.event-specs/system-tokens :github.copilot-sdk.generated.event-specs/tokens-removed :github.copilot-sdk.generated.event-specs/tool-definitions-tokens])) (s/def :github.copilot-sdk.generated.event-specs/session.compaction_start-data (s/keys :opt-un [:github.copilot-sdk.generated.event-specs/conversation-tokens :github.copilot-sdk.generated.event-specs/system-tokens :github.copilot-sdk.generated.event-specs/tool-definitions-tokens])) @@ -509,7 +521,7 @@ (s/def :github.copilot-sdk.generated.event-specs/session.custom_notification-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/name :github.copilot-sdk.generated.event-specs/payload :github.copilot-sdk.generated.event-specs/source] :opt-un [:github.copilot-sdk.generated.event-specs/subject :github.copilot-sdk.generated.event-specs/version])) -(s/def :github.copilot-sdk.generated.event-specs/session.error-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/error-type :github.copilot-sdk.generated.event-specs/message] :opt-un [:github.copilot-sdk.generated.event-specs/eligible-for-auto-switch :github.copilot-sdk.generated.event-specs/error-code :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/stack :github.copilot-sdk.generated.event-specs/status-code :github.copilot-sdk.generated.event-specs/url])) +(s/def :github.copilot-sdk.generated.event-specs/session.error-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/error-type :github.copilot-sdk.generated.event-specs/message] :opt-un [:github.copilot-sdk.generated.event-specs/eligible-for-auto-switch :github.copilot-sdk.generated.event-specs/error-code :github.copilot-sdk.generated.event-specs/provider-call-id :github.copilot-sdk.generated.event-specs/service-request-id :github.copilot-sdk.generated.event-specs/stack :github.copilot-sdk.generated.event-specs/status-code :github.copilot-sdk.generated.event-specs/url])) (s/def :github.copilot-sdk.generated.event-specs/session.extensions_loaded-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/extensions])) @@ -519,13 +531,13 @@ (s/def :github.copilot-sdk.generated.event-specs/session.info-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/info-type :github.copilot-sdk.generated.event-specs/message] :opt-un [:github.copilot-sdk.generated.event-specs/tip :github.copilot-sdk.generated.event-specs/url])) -(s/def :github.copilot-sdk.generated.event-specs/session.mcp_server_status_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/server-name :github.copilot-sdk.generated.event-specs/status])) +(s/def :github.copilot-sdk.generated.event-specs/session.mcp_server_status_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/server-name :github.copilot-sdk.generated.event-specs/status] :opt-un [:github.copilot-sdk.generated.event-specs/error])) (s/def :github.copilot-sdk.generated.event-specs/session.mcp_servers_loaded-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/servers])) (s/def :github.copilot-sdk.generated.event-specs/session.mode_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/new-mode :github.copilot-sdk.generated.event-specs/previous-mode])) -(s/def :github.copilot-sdk.generated.event-specs/session.model_change-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/new-model] :opt-un [:github.copilot-sdk.generated.event-specs/cause :github.copilot-sdk.generated.event-specs/previous-model :github.copilot-sdk.generated.event-specs/previous-reasoning-effort :github.copilot-sdk.generated.event-specs/previous-reasoning-summary :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/reasoning-summary])) +(s/def :github.copilot-sdk.generated.event-specs/session.model_change-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/new-model] :opt-un [:github.copilot-sdk.generated.event-specs/cause :github.copilot-sdk.generated.event-specs/context-tier :github.copilot-sdk.generated.event-specs/previous-model :github.copilot-sdk.generated.event-specs/previous-reasoning-effort :github.copilot-sdk.generated.event-specs/previous-reasoning-summary :github.copilot-sdk.generated.event-specs/reasoning-effort :github.copilot-sdk.generated.event-specs/reasoning-summary])) (s/def :github.copilot-sdk.generated.event-specs/session.plan_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/operation])) @@ -559,7 +571,7 @@ (s/def :github.copilot-sdk.generated.event-specs/session.workspace_file_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/operation :github.copilot-sdk.generated.event-specs/path])) -(s/def :github.copilot-sdk.generated.event-specs/skill.invoked-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/content :github.copilot-sdk.generated.event-specs/name :github.copilot-sdk.generated.event-specs/path] :opt-un [:github.copilot-sdk.generated.event-specs/allowed-tools :github.copilot-sdk.generated.event-specs/description :github.copilot-sdk.generated.event-specs/plugin-name :github.copilot-sdk.generated.event-specs/plugin-version])) +(s/def :github.copilot-sdk.generated.event-specs/skill.invoked-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/content :github.copilot-sdk.generated.event-specs/name :github.copilot-sdk.generated.event-specs/path] :opt-un [:github.copilot-sdk.generated.event-specs/allowed-tools :github.copilot-sdk.generated.event-specs/description :github.copilot-sdk.generated.event-specs/plugin-name :github.copilot-sdk.generated.event-specs/plugin-version :github.copilot-sdk.generated.event-specs/source :github.copilot-sdk.generated.event-specs/trigger])) (s/def :github.copilot-sdk.generated.event-specs/subagent.completed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/agent-display-name :github.copilot-sdk.generated.event-specs/agent-name :github.copilot-sdk.generated.event-specs/tool-call-id] :opt-un [:github.copilot-sdk.generated.event-specs/duration-ms :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/total-tokens :github.copilot-sdk.generated.event-specs/total-tool-calls])) @@ -575,7 +587,7 @@ (s/def :github.copilot-sdk.generated.event-specs/system.notification-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/content :github.copilot-sdk.generated.event-specs/kind])) -(s/def :github.copilot-sdk.generated.event-specs/tool.execution_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/success :github.copilot-sdk.generated.event-specs/tool-call-id] :opt-un [:github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/interaction-id :github.copilot-sdk.generated.event-specs/is-user-requested :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/result :github.copilot-sdk.generated.event-specs/sandboxed :github.copilot-sdk.generated.event-specs/tool-telemetry :github.copilot-sdk.generated.event-specs/turn-id])) +(s/def :github.copilot-sdk.generated.event-specs/tool.execution_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/success :github.copilot-sdk.generated.event-specs/tool-call-id] :opt-un [:github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/interaction-id :github.copilot-sdk.generated.event-specs/is-user-requested :github.copilot-sdk.generated.event-specs/model :github.copilot-sdk.generated.event-specs/parent-tool-call-id :github.copilot-sdk.generated.event-specs/result :github.copilot-sdk.generated.event-specs/sandboxed :github.copilot-sdk.generated.event-specs/tool-description :github.copilot-sdk.generated.event-specs/tool-telemetry :github.copilot-sdk.generated.event-specs/turn-id])) (s/def :github.copilot-sdk.generated.event-specs/tool.execution_partial_result-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/partial-output :github.copilot-sdk.generated.event-specs/tool-call-id])) @@ -647,6 +659,8 @@ (s/def :github.copilot-sdk.generated.event-specs/mcp.oauth_required (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "mcp.oauth_required" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/mcp.oauth_required-data (:data event))))) +(s/def :github.copilot-sdk.generated.event-specs/mcp_app.tool_call_complete (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "mcp_app.tool_call_complete" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/mcp_app.tool_call_complete-data (:data event))))) + (s/def :github.copilot-sdk.generated.event-specs/model.call_failure (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "model.call_failure" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/model.call_failure-data (:data event))))) (s/def :github.copilot-sdk.generated.event-specs/pending_messages.modified (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "pending_messages.modified" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/pending_messages.modified-data (:data event))))) @@ -753,7 +767,7 @@ (s/def :github.copilot-sdk.generated.event-specs/user_input.requested (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "user_input.requested" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/user_input.requested-data (:data event))))) -(def event-types "Set of all event-type strings known to the schema." #{"abort" "assistant.intent" "assistant.message" "assistant.message_delta" "assistant.message_start" "assistant.reasoning" "assistant.reasoning_delta" "assistant.streaming_delta" "assistant.turn_end" "assistant.turn_start" "assistant.usage" "auto_mode_switch.completed" "auto_mode_switch.requested" "capabilities.changed" "command.completed" "command.execute" "command.queued" "commands.changed" "elicitation.completed" "elicitation.requested" "exit_plan_mode.completed" "exit_plan_mode.requested" "external_tool.completed" "external_tool.requested" "hook.end" "hook.start" "mcp.oauth_completed" "mcp.oauth_required" "model.call_failure" "pending_messages.modified" "permission.completed" "permission.requested" "sampling.completed" "sampling.requested" "session.background_tasks_changed" "session.compaction_complete" "session.compaction_start" "session.context_changed" "session.custom_agents_updated" "session.custom_notification" "session.error" "session.extensions_loaded" "session.handoff" "session.idle" "session.info" "session.mcp_server_status_changed" "session.mcp_servers_loaded" "session.mode_changed" "session.model_change" "session.plan_changed" "session.remote_steerable_changed" "session.resume" "session.schedule_cancelled" "session.schedule_created" "session.shutdown" "session.skills_loaded" "session.snapshot_rewind" "session.start" "session.task_complete" "session.title_changed" "session.tools_updated" "session.truncation" "session.usage_info" "session.warning" "session.workspace_file_changed" "skill.invoked" "subagent.completed" "subagent.deselected" "subagent.failed" "subagent.selected" "subagent.started" "system.message" "system.notification" "tool.execution_complete" "tool.execution_partial_result" "tool.execution_progress" "tool.execution_start" "tool.user_requested" "user.message" "user_input.completed" "user_input.requested"}) +(def event-types "Set of all event-type strings known to the schema." #{"abort" "assistant.intent" "assistant.message" "assistant.message_delta" "assistant.message_start" "assistant.reasoning" "assistant.reasoning_delta" "assistant.streaming_delta" "assistant.turn_end" "assistant.turn_start" "assistant.usage" "auto_mode_switch.completed" "auto_mode_switch.requested" "capabilities.changed" "command.completed" "command.execute" "command.queued" "commands.changed" "elicitation.completed" "elicitation.requested" "exit_plan_mode.completed" "exit_plan_mode.requested" "external_tool.completed" "external_tool.requested" "hook.end" "hook.start" "mcp.oauth_completed" "mcp.oauth_required" "mcp_app.tool_call_complete" "model.call_failure" "pending_messages.modified" "permission.completed" "permission.requested" "sampling.completed" "sampling.requested" "session.background_tasks_changed" "session.compaction_complete" "session.compaction_start" "session.context_changed" "session.custom_agents_updated" "session.custom_notification" "session.error" "session.extensions_loaded" "session.handoff" "session.idle" "session.info" "session.mcp_server_status_changed" "session.mcp_servers_loaded" "session.mode_changed" "session.model_change" "session.plan_changed" "session.remote_steerable_changed" "session.resume" "session.schedule_cancelled" "session.schedule_created" "session.shutdown" "session.skills_loaded" "session.snapshot_rewind" "session.start" "session.task_complete" "session.title_changed" "session.tools_updated" "session.truncation" "session.usage_info" "session.warning" "session.workspace_file_changed" "skill.invoked" "subagent.completed" "subagent.deselected" "subagent.failed" "subagent.selected" "subagent.started" "system.message" "system.notification" "tool.execution_complete" "tool.execution_partial_result" "tool.execution_progress" "tool.execution_start" "tool.user_requested" "user.message" "user_input.completed" "user_input.requested"}) (defmulti event-mm :type) @@ -813,6 +827,8 @@ (defmethod event-mm "mcp.oauth_required" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/mcp.oauth_required)) +(defmethod event-mm "mcp_app.tool_call_complete" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/mcp_app.tool_call_complete)) + (defmethod event-mm "model.call_failure" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/model.call_failure)) (defmethod event-mm "pending_messages.modified" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/pending_messages.modified)) From 73774e93c01f437bc4524b68f8b739a6b1ee1b54 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Sat, 23 May 2026 18:23:44 +0200 Subject: [PATCH 2/6] feat: drop v2 protocol back-compat + runtime_instructions + mcp_app event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ports upstream PRs #1378 and #1377 plus opaque-field handling for the new mcp_app.tool_call_complete event from schema 1.0.52-4 (SEP-1865). BREAKING: minimum supported protocol version raised from 2 to 3 (upstream PR #1378). Removes v2 `tool.call` and `permission.request` RPC dispatcher cases from set-request-handler! and the v2 tool.call arguments escape hatch from protocol/normalize-incoming. v3 broadcast cover the same behaviour. Deletes 7 obsolete v2-only deftests. Adds (upstream PR #1377): - :runtime-instructions to specs/system-prompt-sections - util/section-key->wire entry for runtime_instructions - specs/system-message-sections + ::specs/system-message-section aliases pointing at the system-prompt-sections data, matching the upstream SystemPromptSection → SystemMessageSection rename without breaking existing callers Adds (upstream schema 1.0.52-4): - :copilot/mcp_app.tool_call_complete to the public sdk/event-types registry and to specs/::event-type - protocol/preserve-event-opaque-fields case for mcp_app.tool_call_complete so :arguments and :result keep source-defined keys (no kebab-case) Mock server: PROTOCOL_VERSION → DEFAULT_PROTOCOL_VERSION (= 3) with a per-instance :protocol-version atom on MockServer so tests can configure a v2 server and verify rejection. Tests added: - test-schema-1-0-52-4-mcp-app-tool-call-complete-event-type - test-schema-1-0-52-4-mcp-app-tool-call-complete-opaque-fields - test-schema-1-0-52-4-service-request-id - test-schema-1-0-52-4-model-change-context-tier - test-schema-1-0-52-4-skill-invoked-source-trigger - test-schema-1-0-52-4-runtime-instructions-section - test-schema-1-0-52-4-runtime-instructions-wire-roundtrip - test-schema-1-0-52-4-min-protocol-version-3 Docs: - CHANGELOG: post-v1.0.0-beta.4 round 5 entries - API.md: runtime-instructions section + SystemMessageSection rename note + mcp_app.tool_call_complete event row Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 51 ++++ doc/reference/API.md | 13 +- src/github/copilot_sdk.clj | 4 +- src/github/copilot_sdk/client.clj | 35 +-- src/github/copilot_sdk/protocol.clj | 32 +- src/github/copilot_sdk/specs.clj | 42 ++- src/github/copilot_sdk/util.clj | 23 +- test/github/copilot_sdk/integration_test.clj | 289 ++++++++++--------- test/github/copilot_sdk/mock_server.clj | 14 +- 9 files changed, 307 insertions(+), 196 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76106b7..b10116d 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.4 sync, round 5) +- **`:runtime-instructions` system message section** — New section recognized + by the SDK's `:system-message` `:customize` mode. Wire-encoded as + `"runtime_instructions"` and accepted by `::specs/system-prompt-section`. + Upstream PR #1377 also renamed `SystemPromptSection` → `SystemMessageSection` + in TypeScript; for source compatibility the Clojure side keeps + `specs/system-prompt-sections` as the canonical name and exposes + `specs/system-message-sections` (and `::specs/system-message-section`) as + aliases pointing at the same data. (upstream PR #1377) +- **`:copilot/mcp_app.tool_call_complete` event** — New session event emitted + when a tool call from an MCP App completes (upstream schema 1.0.52-4, + SEP-1865). Added to the public `event-types` set. The `:arguments` and + `:result` fields are preserved opaquely by `protocol/preserve-event-opaque-fields` + (they survive `normalize-incoming` without kebab-case rewriting so + source-defined keys round-trip verbatim). +- **Additional event-data fields (passive, via schema regen)** — All optional; + generated `:opt-un` specs pick them up automatically: + - `:service-request-id` on `:error`, `:assistant.message`, `:assistant.usage`, + `:model.call_failure`, `:session.compaction_complete` event data + (Copilot CAPI service-request-id for correlation with CAPI logs). + - `:context-tier` (`"long_context" | "default" | nil`) on + `:session.model_change` data. + - `:transport`, `:plugin-name`, `:plugin-version` on the loaded MCP server + spec inside `:session.mcp_servers_loaded` data. + - `:error` on `:session.mcp_server_status_changed` data. + - `:source` and `:trigger` (`"user-invoked" | "agent-invoked" | "context-load"`) + on `:skill.invoked` data. + - `:tool-description` and `:ui-resource` on `:tool.execution_complete` data. +- **Schema bump** — `.copilot-schema-version` advanced from `1.0.52-1` to + `1.0.52-4`. (upstream PR #1393) + +### Changed (post-v1.0.0-beta.4 sync, round 5) +- **BREAKING: Minimum supported protocol version raised from 2 to 3.** The + SDK will now reject CLI servers that report protocol version 2. The + back-compat shims that adapted v2 `tool.call` / `permission.request` + JSON-RPC requests into v3 broadcast-event flows have been removed from + `set-request-handler!` and from `protocol/normalize-incoming`. Clients + must use a Copilot CLI that supports protocol v3 (CLI 1.0.46 or later). + (upstream PR #1378) + +### Removed (post-v1.0.0-beta.4 sync, round 5) +- **v2 protocol RPC dispatcher cases** — `tool.call` and `permission.request` + request handlers (and their associated tests + `test-tool-call-response-shape`, `test-tool-handler-runs-on-blocking-thread`, + `test-permission-denied-with-deny-handler`, + `test-permission-approved-with-handler`, + `test-permission-unknown-session-response-shape`, + `test-permission-custom-handler`, `test-permission-no-result-v2`). v3 + broadcast handlers `handle-v3-tool-requested!` / `handle-v3-permission-requested!` + cover the same behaviour. (upstream PR #1378) + ### Added (post-v1.0.0-beta.4 sync, round 4) - **`:on-pre-mcp-tool-call` hook** — New lifecycle hook in the `:hooks` map that fires before an MCP tool call is dispatched to its server (upstream diff --git a/doc/reference/API.md b/doc/reference/API.md index 8979af2..c543a85 100644 --- a/doc/reference/API.md +++ b/doc/reference/API.md @@ -1435,6 +1435,7 @@ Convert an unqualified event keyword to a namespace-qualified `:copilot/` keywor | `:copilot/sampling.completed` | MCP sampling request completed; ephemeral | | `:copilot/session.remote_steerable_changed` | Session remote steering capability changed; data: `{:remote-steerable true/false}` | | `:copilot/capabilities.changed` | Session capabilities dynamically changed (e.g., elicitation support); ephemeral. Data: `{:ui {:elicitation true/false}}` | +| `:copilot/mcp_app.tool_call_complete` | An MCP App tool call completed (upstream schema 1.0.52-4, SEP-1865); ephemeral. Data: `{:server-name ... :tool-name ... :duration-ms ... :success bool :arguments {...} :result {...}}` — `:arguments` and `:result` are opaque source-defined maps whose keys are preserved verbatim (not kebab-cased). | ### Example: Handling Events @@ -1756,9 +1757,19 @@ Inspect available sections with the `system-prompt-sections` constant: ```clojure copilot/system-prompt-sections ;; => {:identity {:description "Agent identity preamble and mode statement"} -;; :tone {:description "Response style, conciseness rules, ..."} ...} +;; :tone {:description "Response style, conciseness rules, ..."} +;; :runtime-instructions {:description "Runtime instructions injected ..."} ...} ``` +Available section keys: `:identity`, `:tone`, `:proactiveness`, `:formatting`, +`:tools`, `:context-collection`, `:task-management`, `:safety`, `:agent-mode`, +`:additional-instructions`, `:runtime-instructions` (added in upstream PR #1377). + +> **Naming note** — Upstream renamed `SystemPromptSection` → +> `SystemMessageSection` in the TypeScript SDK. The Clojure SDK keeps +> `system-prompt-sections` as the canonical name (for back-compat) and +> exposes `system-message-sections` as an alias. + Unknown section keywords are allowed — they gracefully fall back to appending content to additional instructions. ### Default Agent Tool Exclusions diff --git a/src/github/copilot_sdk.clj b/src/github/copilot_sdk.clj index ae64749..990241e 100644 --- a/src/github/copilot_sdk.clj +++ b/src/github/copilot_sdk.clj @@ -120,7 +120,9 @@ :copilot/sampling.requested :copilot/sampling.completed :copilot/session.remote_steerable_changed - :copilot/capabilities.changed}) + :copilot/capabilities.changed + ;; MCP Apps tool-call complete (upstream schema 1.0.52-4, SEP-1865) + :copilot/mcp_app.tool_call_complete}) (def session-events "Session lifecycle and state management events." diff --git a/src/github/copilot_sdk/client.clj b/src/github/copilot_sdk/client.clj index f3eb3be..29e6a1f 100644 --- a/src/github/copilot_sdk/client.clj +++ b/src/github/copilot_sdk/client.clj @@ -15,7 +15,10 @@ [java.util.concurrent LinkedBlockingQueue])) (def ^:private sdk-protocol-version-max 3) -(def ^:private sdk-protocol-version-min 2) +;; Upstream PR #1378 raised the minimum protocol version to 3 by removing +;; the v2 back-compat shims (the `tool.call` and `permission.request` +;; server→client RPCs). Servers reporting a version below 3 are now rejected. +(def ^:private sdk-protocol-version-min 3) (defn- get-trace-context "Call the user-provided trace context provider. Returns {} when no provider @@ -632,34 +635,20 @@ (str/join "\n" lines))))) (defn- setup-request-handler! - "Set up handler for incoming requests (tool calls, permission requests, hooks, user input, sessionFs)." + "Set up handler for incoming requests (hooks, user input, sessionFs, etc.). + + Protocol v3 (the only supported version, see [[sdk-protocol-version-min]]) + delivers tool calls and permission requests as broadcast events on + `session.event` — see [[handle-v3-tool-requested!]] and + [[handle-v3-permission-requested!]] — not as server→client RPCs. The v2 + `tool.call` / `permission.request` dispatcher cases were removed + alongside upstream PR #1378." [client] (let [{:keys [connection-io]} @(:state client)] (proto/set-request-handler! connection-io (fn [method params] (go (case method - "tool.call" - (let [{:keys [session-id tool-call-id tool-name arguments]} params] - (if-not (get-in @(:state client) [:sessions session-id]) - {:error {:code -32001 :message (str "Unknown session: " session-id)}} - {:result ( converted-event + (contains? (:data raw-event) :arguments) + (assoc-in [:data :arguments] (get-in raw-event [:data :arguments])) + (contains? (:data raw-event) :result) + (assoc-in [:data :result] (get-in raw-event [:data :result]))) + converted-event)) (defn- normalize-incoming "Convert wire-format keys to Clojure keys, preserving opaque user data. - For v2 tool.call RPC and v3 external_tool.requested broadcast events, - tool arguments are kept in their original wire format so user-defined - tool handlers receive the keys the server sent. For v3 - session.custom_notification events, the source-defined `:subject` and - opaque `:payload` are also preserved verbatim. The same preservation - applies to historical events returned in `session.getMessages` responses - so live and historical event shapes agree." + + For v3 `external_tool.requested` broadcast events, tool arguments are + kept in their original wire format so user-defined tool handlers receive + the keys the server sent. For v3 `session.custom_notification` events, + the source-defined `:subject` and opaque `:payload` are also preserved + verbatim. For v3 `mcp_app.tool_call_complete` events (schema 1.0.52-4, + SEP-1865), the `:arguments` and `:result` payloads are similarly + preserved. The same preservation applies to historical events returned + in `session.getMessages` responses so live and historical event shapes + agree." [msg] (let [method (:method msg) params (:params msg) converted (util/wire->clj msg) raw-events (get-in msg [:result :events])] (cond - ;; v2: preserve raw arguments for tool.call RPC - (and (= "tool.call" method) (map? params) (contains? params :arguments)) - (assoc-in converted [:params :arguments] (:arguments params)) - ;; Upstream PR #1299: SQL bind parameters are opaque keyed values ;; (e.g. `$user_id`). Preserve the raw map so kebab-case conversion ;; doesn't mangle placeholder names before the handler binds them. diff --git a/src/github/copilot_sdk/specs.clj b/src/github/copilot_sdk/specs.clj index f4c2a6e..4a2b70e 100644 --- a/src/github/copilot_sdk/specs.clj +++ b/src/github/copilot_sdk/specs.clj @@ -233,22 +233,34 @@ (s/def ::system-message-mode #{:append :replace :customize}) (s/def ::system-message-content string?) -;; System prompt sections for customize mode (upstream PR #816) +;; System message sections for customize mode (upstream PR #816) +;; Upstream PR #1377 renamed `SystemPromptSection` to `SystemMessageSection` +;; and added the `runtime_instructions` section. The Clojure SDK keeps the +;; historical `system-prompt-sections` var as the canonical name and exposes +;; `system-message-sections` as an alias to match the upstream naming. (def system-prompt-sections - "Known system prompt section identifiers for the customize mode. - Each section corresponds to a distinct part of the system prompt." - {:identity {:description "Agent identity preamble and mode statement"} - :tone {:description "Response style, conciseness rules, output formatting preferences"} - :tool-efficiency {:description "Tool usage patterns, parallel calling, batching guidelines"} - :environment-context {:description "CWD, OS, git root, directory listing, available tools"} - :code-change-rules {:description "Coding rules, linting/testing, ecosystem tools, style"} - :guidelines {:description "Tips, behavioral best practices, behavioral guidelines"} - :safety {:description "Environment limitations, prohibited actions, security policies"} - :tool-instructions {:description "Per-tool usage instructions"} - :custom-instructions {:description "Repository and organization custom instructions"} - :last-instructions {:description "End-of-prompt instructions: parallel tool calling, persistence, task completion"}}) + "Known system message section identifiers for the customize mode. + Each section corresponds to a distinct part of the system message. + Upstream alias: `SystemMessageSection`." + {:identity {:description "Agent identity preamble and mode statement"} + :tone {:description "Response style, conciseness rules, output formatting preferences"} + :tool-efficiency {:description "Tool usage patterns, parallel calling, batching guidelines"} + :environment-context {:description "CWD, OS, git root, directory listing, available tools"} + :code-change-rules {:description "Coding rules, linting/testing, ecosystem tools, style"} + :guidelines {:description "Tips, behavioral best practices, behavioral guidelines"} + :safety {:description "Environment limitations, prohibited actions, security policies"} + :tool-instructions {:description "Per-tool usage instructions"} + :custom-instructions {:description "Repository and organization custom instructions"} + :runtime-instructions {:description "Runtime-provided context and instructions (e.g. system notifications, memories, workspace context, mode-specific instructions, content-exclusion policy)"} + :last-instructions {:description "End-of-prompt instructions: parallel tool calling, persistence, task completion"}}) + +(def system-message-sections + "Alias for [[system-prompt-sections]] matching the upstream + `SYSTEM_MESSAGE_SECTIONS` name (upstream PR #1377)." + system-prompt-sections) (s/def ::system-prompt-section (set (keys system-prompt-sections))) +(s/def ::system-message-section ::system-prompt-section) ;; Section override: action can be a keyword for static overrides, or a fn for transforms (s/def ::section-action @@ -888,7 +900,9 @@ ;; Capabilities changed (upstream PR #908) :copilot/capabilities.changed ;; Schedule events (upstream schema 1.0.42) - :copilot/session.schedule_created :copilot/session.schedule_cancelled}) + :copilot/session.schedule_created :copilot/session.schedule_cancelled + ;; MCP Apps tool-call complete (upstream schema 1.0.52-4, SEP-1865) + :copilot/mcp_app.tool_call_complete}) ;; Session events (s/def ::already-in-use? boolean?) diff --git a/src/github/copilot_sdk/util.clj b/src/github/copilot_sdk/util.clj index e315c44..6e943c9 100644 --- a/src/github/copilot_sdk/util.clj +++ b/src/github/copilot_sdk/util.clj @@ -54,17 +54,18 @@ ;; ----------------------------------------------------------------------------- (def section-key->wire - "Map from Clojure keyword to wire string for system prompt sections." - {:identity "identity" - :tone "tone" - :tool-efficiency "tool_efficiency" - :environment-context "environment_context" - :code-change-rules "code_change_rules" - :guidelines "guidelines" - :safety "safety" - :tool-instructions "tool_instructions" - :custom-instructions "custom_instructions" - :last-instructions "last_instructions"}) + "Map from Clojure keyword to wire string for system message sections." + {:identity "identity" + :tone "tone" + :tool-efficiency "tool_efficiency" + :environment-context "environment_context" + :code-change-rules "code_change_rules" + :guidelines "guidelines" + :safety "safety" + :tool-instructions "tool_instructions" + :custom-instructions "custom_instructions" + :runtime-instructions "runtime_instructions" + :last-instructions "last_instructions"}) (def wire->section-key "Map from wire string to Clojure keyword for system prompt sections." diff --git a/test/github/copilot_sdk/integration_test.clj b/test/github/copilot_sdk/integration_test.clj index 7d9598f..860c20c 100644 --- a/test/github/copilot_sdk/integration_test.clj +++ b/test/github/copilot_sdk/integration_test.clj @@ -8,6 +8,7 @@ [github.copilot-sdk.client :as client] [github.copilot-sdk.protocol :as protocol] [github.copilot-sdk.session :as session] + [github.copilot-sdk.specs :as specs] [github.copilot-sdk.tools :as tools] [github.copilot-sdk.util :as util] [github.copilot-sdk.generated.event-specs] @@ -160,7 +161,7 @@ (deftest test-ping (testing "Ping returns protocol version" (let [result (sdk/ping *test-client*)] - (is (= 2 (:protocol-version result))) + (is (= 3 (:protocol-version result))) ;; Upstream PR #1340 / CLI 1.0.51 changed timestamp from epoch number ;; to ISO 8601 string (`timestamp: string, format: date-time`). (is (string? (:timestamp result))) @@ -181,7 +182,7 @@ (testing "Get CLI status returns version and protocol" (let [result (sdk/get-status *test-client*)] (is (string? (:version result))) - (is (= 2 (:protocol-version result)))))) + (is (= 3 (:protocol-version result)))))) (deftest test-get-auth-status (testing "Get auth status returns authentication info" @@ -685,40 +686,12 @@ :handler (fn [_args _invocation] "result")})]})] (is (some? session))))) -(deftest test-tool-call-response-shape - (testing "tool.call handler returns a nested result wrapper" - (let [tool (sdk/define-tool "echo" - {:handler (fn [args _] args)}) - session (sdk/create-session *test-client* {:on-permission-request sdk/approve-all :tools [tool]}) - handler (get-in @(:state *test-client*) [:connection :request-handler]) - response (clj on relevant event data specs" + ;; Upstream schema 1.0.52-4 adds optional `serviceRequestId` (the + ;; Copilot CAPI x-copilot-service-request-id header) to several + ;; event-data shapes for correlation with CAPI logs. The generated + ;; specs accept it via `:opt-un`; we verify roundtrip through + ;; normalize-incoming. + (doseq [spec-key [:github.copilot-sdk.generated.event-specs/assistant.message-data + :github.copilot-sdk.generated.event-specs/assistant.usage-data + :github.copilot-sdk.generated.event-specs/model.call_failure-data + :github.copilot-sdk.generated.event-specs/session.compaction_complete-data + :github.copilot-sdk.generated.event-specs/session.error-data]] + (is (some? (s/get-spec spec-key)) (str spec-key " should exist"))) + (let [normalize @#'protocol/normalize-incoming + raw-msg {:jsonrpc "2.0" + :method "session.event" + :params {:sessionId "abc" + :event {:type "assistant.usage" + :id "evt-2" + :timestamp "2026-05-23T08:00:00.000Z" + :parentId nil + :data {:model "gpt-5" + :serviceRequestId "svc-req-abc"}}}} + data (get-in (normalize raw-msg) [:params :event :data])] + (is (= "svc-req-abc" (:service-request-id data)) + "serviceRequestId must arrive as :service-request-id")))) + +(deftest test-schema-1-0-52-4-model-change-context-tier + (testing "session.model_change accepts :context-tier (default | long_context | nil)" + ;; Upstream schema 1.0.52-4 adds optional :context-tier to ModelChangeData. + ;; A literal `null` explicitly clears a previously-selected tier. + (let [spec :github.copilot-sdk.generated.event-specs/session.model_change-data] + (is (s/valid? spec {:new-model "gpt-5" :context-tier "default"})) + (is (s/valid? spec {:new-model "gpt-5" :context-tier "long_context"})) + (is (s/valid? spec {:new-model "gpt-5" :context-tier nil})) + (is (s/valid? spec {:new-model "gpt-5"})) + (is (not (s/valid? spec {:new-model "gpt-5" :context-tier "tiny"})))))) + +(deftest test-schema-1-0-52-4-skill-invoked-source-trigger + (testing "skill.invoked accepts :source and :trigger" + (let [spec :github.copilot-sdk.generated.event-specs/skill.invoked-data] + (is (s/valid? spec {:name "foo" :path "/x" :content "..."})) + (is (s/valid? spec {:name "foo" :path "/x" :content "..." + :source "project" + :trigger "user-invoked"})) + (is (s/valid? spec {:name "foo" :path "/x" :content "..." + :trigger "agent-invoked"})) + (is (s/valid? spec {:name "foo" :path "/x" :content "..." + :trigger "context-load"})) + (is (not (s/valid? spec {:name "foo" :path "/x" :content "..." + :trigger "bogus"})))))) + +(deftest test-schema-1-0-52-4-runtime-instructions-section + (testing ":runtime-instructions is a known system message section (upstream PR #1377)" + (is (contains? (set (keys specs/system-prompt-sections)) :runtime-instructions)) + (is (= "runtime_instructions" (util/section-kw->wire-id :runtime-instructions)) + ":runtime-instructions converts to the wire string \"runtime_instructions\"") + (is (s/valid? :github.copilot-sdk.specs/system-prompt-section :runtime-instructions)) + (is (s/valid? :github.copilot-sdk.specs/system-message-section :runtime-instructions) + "::system-message-section alias also accepts it")) + (testing "system-message-sections alias points at the same map (upstream rename)" + (is (identical? specs/system-prompt-sections specs/system-message-sections)))) + +(deftest test-schema-1-0-52-4-runtime-instructions-wire-roundtrip + (testing ":runtime-instructions section survives the create-session wire conversion" + (let [seen (atom {}) + _ (mock/set-request-hook! *mock-server* + (fn [method params] + (when (#{"session.create"} method) + (swap! seen assoc method params)))) + _ (sdk/create-session *test-client* + {:on-permission-request sdk/approve-all + :system-message {:mode :customize + :sections + {:runtime-instructions + {:action :replace + :content "runtime ctx"}}}}) + wire (get-in @seen ["session.create" :systemMessage :sections])] + (is (contains? wire :runtime_instructions) + ":runtime-instructions must be sent as wire key :runtime_instructions") + (is (= "replace" (get-in wire [:runtime_instructions :action]))) + (is (= "runtime ctx" (get-in wire [:runtime_instructions :content])))))) + +(deftest test-schema-1-0-52-4-min-protocol-version-3 + (testing "client rejects servers reporting protocol version < 3 (upstream PR #1378)" + ;; The SDK no longer supports v2 servers after the cleanup PR removed + ;; the v2 `tool.call` / `permission.request` back-compat adapters. + (let [server (mock/create-mock-server) + _ (reset! (:protocol-version server) 2) + _ (mock/start-mock-server! server) + client (sdk/client {:auto-start? false}) + [in out] (mock/client-streams server)] + (try + (is (thrown-with-msg? clojure.lang.ExceptionInfo + #"(?i)protocol.*version" + (client/connect-with-streams! client in out))) + (finally + (try (sdk/disconnect! client) (catch Exception _)) + (mock/stop-mock-server! server)))))) + ;; ----------------------------------------------------------------------------- ;; Last Session ID Tests ;; ----------------------------------------------------------------------------- diff --git a/test/github/copilot_sdk/mock_server.clj b/test/github/copilot_sdk/mock_server.clj index 5748689..ea44113 100644 --- a/test/github/copilot_sdk/mock_server.clj +++ b/test/github/copilot_sdk/mock_server.clj @@ -9,7 +9,7 @@ PipedInputStream PipedOutputStream] [java.util.concurrent.atomic AtomicLong])) -(def ^:private PROTOCOL_VERSION 2) +(def ^:private DEFAULT_PROTOCOL_VERSION 3) (defn- write-message "Write a JSON-RPC message with Content-Length framing." @@ -69,7 +69,8 @@ expected-token ; atom string-or-nil - when set, `connect` validates token supports-connect? ; atom boolean - when false, `connect` returns -32601 (legacy fallback) pending-events ; atom - events to send on next opportunity - pending-responses]) ; atom {id -> chan} - responses to server→client RPCs + pending-responses ; atom {id -> chan} - responses to server→client RPCs + protocol-version]) ; atom Long - protocol version reported by ping/connect/status (defn- generate-id [^AtomicLong counter] (str "evt-" (.incrementAndGet counter))) @@ -96,7 +97,7 @@ (defn- handle-ping [server params] {:message (:message params) :timestamp (.toString (java.time.Instant/now)) - :protocolVersion PROTOCOL_VERSION}) + :protocolVersion (or (some-> server :protocol-version deref) DEFAULT_PROTOCOL_VERSION)}) (defn- handle-connect "Handle the `connect` handshake (upstream PR #1176). When :expected-token is @@ -109,12 +110,12 @@ (throw (ex-info "Invalid connection token" {:code -32603 :method "connect"}))) {:ok true - :protocolVersion PROTOCOL_VERSION + :protocolVersion (or (some-> server :protocol-version deref) DEFAULT_PROTOCOL_VERSION) :version "0.0.389-mock"})) (defn- handle-status-get [server params] {:version "0.0.389-mock" - :protocolVersion PROTOCOL_VERSION}) + :protocolVersion (or (some-> server :protocol-version deref) DEFAULT_PROTOCOL_VERSION)}) (defn- handle-auth-get-status [server params] {:isAuthenticated true @@ -460,7 +461,8 @@ :expected-token (atom nil) :supports-connect? (atom true) :pending-events (atom []) - :pending-responses (atom {})}))) + :pending-responses (atom {}) + :protocol-version (atom DEFAULT_PROTOCOL_VERSION)}))) (defn start-mock-server! "Start the mock server in a background thread." From 78f64646cf8de700e30b6b5d5839241b1ee77e38 Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Sun, 24 May 2026 09:20:52 +0200 Subject: [PATCH 3/6] fix(docs): align customize-mode section list with specs; bump schema to 1.0.52 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses Copilot Code Review feedback on PR #111: - The 'Available section keys' paragraph and the 'Customize Mode' table in doc/reference/API.md listed sections that don't exist in github.copilot-sdk.specs/system-prompt-sections (e.g. :proactiveness, :formatting, :tools, :context-collection, :task-management, :agent-mode, :additional-instructions) and omitted real ones (:tool-efficiency, :environment-context, :code-change-rules, :guidelines, :tool-instructions, :custom-instructions, :runtime-instructions). Both locations now mirror the canonical spec (eleven sections) verbatim, including :runtime-instructions from upstream PR #1377. Also picks up upstream PR #1405 (schema bump @github/copilot 1.0.52-4 → 1.0.52 stable). The shipped JSON Schemas are byte-identical between the two versions, so codegen produces no diff; only the pin in .copilot-schema-version and the README/CHANGELOG references move to the stable release name. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .copilot-schema-version | 2 +- CHANGELOG.md | 5 ++++- doc/reference/API.md | 10 ++++++---- schemas/README.md | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.copilot-schema-version b/.copilot-schema-version index c221ad4..46354d7 100644 --- a/.copilot-schema-version +++ b/.copilot-schema-version @@ -1 +1 @@ -1.0.52-4 +1.0.52 diff --git a/CHANGELOG.md b/CHANGELOG.md index b10116d..ce76e0e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,7 +32,10 @@ All notable changes to this project will be documented in this file. This change on `:skill.invoked` data. - `:tool-description` and `:ui-resource` on `:tool.execution_complete` data. - **Schema bump** — `.copilot-schema-version` advanced from `1.0.52-1` to - `1.0.52-4`. (upstream PR #1393) + `1.0.52` (stable). Picked up the 1.0.52-4 pre-release (upstream PR #1393) + and then advanced to the 1.0.52 stable release (upstream PR #1405); the + shipped JSON Schemas are byte-identical between 1.0.52-4 and 1.0.52, so + no additional schema-driven changes were required. ### Changed (post-v1.0.0-beta.4 sync, round 5) - **BREAKING: Minimum supported protocol version raised from 2 to 3.** The diff --git a/doc/reference/API.md b/doc/reference/API.md index c543a85..efdd179 100644 --- a/doc/reference/API.md +++ b/doc/reference/API.md @@ -1706,7 +1706,7 @@ For full control (removes all guardrails), use `:mode :replace`: #### Customize Mode -The `:customize` mode enables section-level overrides of the system prompt. Ten sections are configurable: +The `:customize` mode enables section-level overrides of the system prompt. Eleven sections are configurable: | Section | Description | |---------|-------------| @@ -1719,6 +1719,7 @@ The `:customize` mode enables section-level overrides of the system prompt. Ten | `:safety` | Environment limitations, prohibited actions, security | | `:tool-instructions` | Per-tool usage instructions | | `:custom-instructions` | Repository and organization custom instructions | +| `:runtime-instructions` | Runtime-provided context (system notifications, memories, mode-specific instructions, content-exclusion policy) — added in upstream PR #1377 | | `:last-instructions` | End-of-prompt instructions | Each section supports static actions (`:replace`, `:remove`, `:append`, `:prepend`) and transform callbacks (1-arity functions). @@ -1761,9 +1762,10 @@ copilot/system-prompt-sections ;; :runtime-instructions {:description "Runtime instructions injected ..."} ...} ``` -Available section keys: `:identity`, `:tone`, `:proactiveness`, `:formatting`, -`:tools`, `:context-collection`, `:task-management`, `:safety`, `:agent-mode`, -`:additional-instructions`, `:runtime-instructions` (added in upstream PR #1377). +Available section keys: `:identity`, `:tone`, `:tool-efficiency`, +`:environment-context`, `:code-change-rules`, `:guidelines`, `:safety`, +`:tool-instructions`, `:custom-instructions`, `:runtime-instructions` +(added in upstream PR #1377), `:last-instructions`. > **Naming note** — Upstream renamed `SystemPromptSection` → > `SystemMessageSection` in the TypeScript SDK. The Clojure SDK keeps diff --git a/schemas/README.md b/schemas/README.md index 1b66a5c..360fa59 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.52-4` +Currently pinned version: `1.0.52` From e527bc29d322832b5393260710989018e26907ef Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 27 May 2026 09:34:09 +0200 Subject: [PATCH 4/6] chore(schema): bump to 1.0.55-1 and surface canvas event types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Advance `.copilot-schema-version` from 1.0.52 to 1.0.55-1, picking up: - upstream PR #1408 (1.0.53-2) - upstream PR #1410 (1.0.53) - upstream PR #1411 (1.0.54) - upstream PR #1412 (1.0.55-0) - upstream PRs #1401 / #1413 (canvas runtime — wire-only, see below) - upstream PR #1432 (1.0.55-1) Schema regen surfaces two new wire-only canvas event types: `session.canvas.opened` and `session.canvas.registry_changed`, plus the field set behind them. These events now appear in the public `event-types` set for forward compatibility, but the canvas runtime (extension manifests, `requestCanvasRenderer`, `openCanvases`, extension info, etc. — upstream PRs #1401, #1413) is intentionally NOT yet exposed on the public Clojure API. Canvas runtime support is deferred to a dedicated future sync round; for now the events flow through as generic session events. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .copilot-schema-version | 2 +- schemas/README.md | 2 +- schemas/api.schema.json | 1076 +++++++++++++++-- schemas/session-events.schema.json | 283 +++++ .../copilot_sdk/generated/event_specs.clj | 54 +- src/github/copilot_sdk/specs.clj | 6 +- 6 files changed, 1325 insertions(+), 98 deletions(-) diff --git a/.copilot-schema-version b/.copilot-schema-version index 46354d7..1dc08bd 100644 --- a/.copilot-schema-version +++ b/.copilot-schema-version @@ -1 +1 @@ -1.0.52 +1.0.55-1 diff --git a/schemas/README.md b/schemas/README.md index 360fa59..29a817c 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.52` +Currently pinned version: `1.0.55-1` diff --git a/schemas/api.schema.json b/schemas/api.schema.json index 8d82d86..314b857 100644 --- a/schemas/api.schema.json +++ b/schemas/api.schema.json @@ -407,7 +407,7 @@ }, "result": { "$ref": "#/definitions/SessionEnrichMetadataResult", - "description": "The same metadata records, with summary and context fields backfilled where available." + "description": "The enriched metadata records, with summary and context fields backfilled where available. Sessions confirmed empty and unnamed are omitted." }, "stability": "experimental" }, @@ -672,6 +672,162 @@ "stability": "experimental" } }, + "canvas": { + "list": { + "rpcMethod": "session.canvas.list", + "description": "Lists canvases declared for the session.", + "params": { + "type": "object", + "description": "Identifies the target session.", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + } + }, + "required": [ + "sessionId" + ], + "additionalProperties": false + }, + "result": { + "$ref": "#/definitions/CanvasList", + "description": "Declared canvases available in this session." + }, + "stability": "experimental" + }, + "listOpen": { + "rpcMethod": "session.canvas.listOpen", + "description": "Lists currently open canvas instances for the live session.", + "params": { + "type": "object", + "description": "Identifies the target session.", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + } + }, + "required": [ + "sessionId" + ], + "additionalProperties": false + }, + "result": { + "$ref": "#/definitions/CanvasListOpenResult", + "description": "Live open-canvas snapshot." + }, + "stability": "experimental" + }, + "open": { + "rpcMethod": "session.canvas.open", + "description": "Opens or focuses a canvas instance.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier. Optional when the canvasId is unique across providers; required to disambiguate when multiple providers register the same canvasId." + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Caller-supplied stable instance identifier" + }, + "input": { + "description": "Canvas open input", + "x-opaque-json": true + } + }, + "required": [ + "sessionId", + "canvasId", + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas open parameters.", + "title": "CanvasOpenRequest" + }, + "result": { + "$ref": "#/definitions/OpenCanvasInstance", + "description": "Open canvas instance snapshot." + }, + "stability": "experimental" + }, + "close": { + "rpcMethod": "session.canvas.close", + "description": "Closes an open canvas instance.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "instanceId": { + "type": "string", + "description": "Open canvas instance identifier" + } + }, + "required": [ + "sessionId", + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas close parameters.", + "title": "CanvasCloseRequest" + }, + "result": { + "type": "null" + }, + "stability": "experimental" + }, + "invokeAction": { + "rpcMethod": "session.canvas.invokeAction", + "description": "Invokes an action on an open canvas instance.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "instanceId": { + "type": "string", + "description": "Open canvas instance identifier" + }, + "actionName": { + "type": "string", + "description": "Action name to invoke" + }, + "input": { + "description": "Action input", + "x-opaque-json": true + } + }, + "required": [ + "sessionId", + "instanceId", + "actionName" + ], + "additionalProperties": false, + "description": "Canvas action invocation parameters.", + "title": "CanvasInvokeActionRequest" + }, + "result": { + "$ref": "#/definitions/CanvasInvokeActionResult", + "description": "Canvas action invocation result." + }, + "stability": "experimental" + } + }, "model": { "getCurrent": { "rpcMethod": "session.model.getCurrent", @@ -1169,6 +1325,35 @@ "description": "Descriptor for the saved paste file, or null when the workspace is unavailable." }, "stability": "experimental" + }, + "diff": { + "rpcMethod": "session.workspaces.diff", + "description": "Computes a diff for the session workspace.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "mode": { + "$ref": "#/definitions/WorkspaceDiffMode", + "description": "Diff mode requested by the client." + } + }, + "required": [ + "sessionId", + "mode" + ], + "additionalProperties": false, + "description": "Parameters for computing a workspace diff.", + "title": "WorkspacesDiffRequest" + }, + "result": { + "$ref": "#/definitions/WorkspaceDiffResult", + "description": "Workspace diff result for the requested mode." + }, + "stability": "experimental" } }, "instructions": { @@ -4665,7 +4850,8 @@ "result": { "$ref": "#/definitions/SessionFsReadFileResult", "description": "File content as a UTF-8 string, or a filesystem error if the read failed." - } + }, + "stability": "experimental" }, "writeFile": { "rpcMethod": "sessionFs.writeFile", @@ -4711,7 +4897,8 @@ } ], "description": "Describes a filesystem error." - } + }, + "stability": "experimental" }, "appendFile": { "rpcMethod": "sessionFs.appendFile", @@ -4757,7 +4944,8 @@ } ], "description": "Describes a filesystem error." - } + }, + "stability": "experimental" }, "exists": { "rpcMethod": "sessionFs.exists", @@ -4785,7 +4973,8 @@ "result": { "$ref": "#/definitions/SessionFsExistsResult", "description": "Indicates whether the requested path exists in the client-provided session filesystem." - } + }, + "stability": "experimental" }, "stat": { "rpcMethod": "sessionFs.stat", @@ -4813,7 +5002,8 @@ "result": { "$ref": "#/definitions/SessionFsStatResult", "description": "Filesystem metadata for the requested path, or a filesystem error if the stat failed." - } + }, + "stability": "experimental" }, "mkdir": { "rpcMethod": "sessionFs.mkdir", @@ -4858,7 +5048,8 @@ } ], "description": "Describes a filesystem error." - } + }, + "stability": "experimental" }, "readdir": { "rpcMethod": "sessionFs.readdir", @@ -4886,7 +5077,8 @@ "result": { "$ref": "#/definitions/SessionFsReaddirResult", "description": "Names of entries in the requested directory, or a filesystem error if the read failed." - } + }, + "stability": "experimental" }, "readdirWithTypes": { "rpcMethod": "sessionFs.readdirWithTypes", @@ -4914,7 +5106,8 @@ "result": { "$ref": "#/definitions/SessionFsReaddirWithTypesResult", "description": "Entries in the requested directory paired with file/directory type information, or a filesystem error if the read failed." - } + }, + "stability": "experimental" }, "rm": { "rpcMethod": "sessionFs.rm", @@ -4958,7 +5151,8 @@ } ], "description": "Describes a filesystem error." - } + }, + "stability": "experimental" }, "rename": { "rpcMethod": "sessionFs.rename", @@ -4999,7 +5193,8 @@ } ], "description": "Describes a filesystem error." - } + }, + "stability": "experimental" }, "sqliteQuery": { "rpcMethod": "sessionFs.sqliteQuery", @@ -5044,7 +5239,8 @@ "result": { "$ref": "#/definitions/SessionFsSqliteQueryResult", "description": "Query results including rows, columns, and rows affected, or a filesystem error if execution failed." - } + }, + "stability": "experimental" }, "sqliteExists": { "rpcMethod": "sessionFs.sqliteExists", @@ -5066,7 +5262,151 @@ "result": { "$ref": "#/definitions/SessionFsSqliteExistsResult", "description": "Indicates whether the per-session SQLite database already exists." - } + }, + "stability": "experimental" + } + }, + "canvas": { + "open": { + "rpcMethod": "canvas.open", + "description": "Opens a canvas instance on the provider.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Stable caller-supplied canvas instance identifier" + }, + "input": { + "description": "Canvas open input", + "x-opaque-json": true + }, + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." + } + }, + "required": [ + "sessionId", + "extensionId", + "canvasId", + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas open parameters sent to the provider.", + "title": "CanvasProviderOpenRequest" + }, + "result": { + "$ref": "#/definitions/CanvasProviderOpenResult", + "description": "Canvas open result returned by the provider." + }, + "stability": "experimental" + }, + "close": { + "rpcMethod": "canvas.close", + "description": "Closes a canvas instance on the provider.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Canvas instance identifier" + }, + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." + } + }, + "required": [ + "sessionId", + "extensionId", + "canvasId", + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas close parameters sent to the provider.", + "title": "CanvasProviderCloseRequest" + }, + "result": { + "type": "null" + }, + "stability": "experimental" + }, + "invokeAction": { + "rpcMethod": "canvas.invokeAction", + "description": "Invokes an action on an open canvas instance via the provider.", + "params": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Target session identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Canvas instance identifier" + }, + "actionName": { + "type": "string", + "description": "Action name to invoke" + }, + "input": { + "description": "Action input", + "x-opaque-json": true + }, + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." + } + }, + "required": [ + "sessionId", + "extensionId", + "canvasId", + "instanceId", + "actionName" + ], + "additionalProperties": false, + "description": "Canvas action invocation parameters sent to the provider.", + "title": "CanvasProviderInvokeActionRequest" + }, + "result": { + "description": "Provider-supplied action result.", + "x-opaque-json": true + }, + "stability": "experimental" } } }, @@ -5371,91 +5711,393 @@ } }, "required": [ - "agent" + "agent" + ], + "additionalProperties": false, + "description": "The newly selected custom agent.", + "title": "AgentSelectResult" + }, + "ApiKeyAuthInfo": { + "type": "object", + "properties": { + "type": { + "type": "string", + "const": "api-key", + "description": "API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style)." + }, + "apiKey": { + "type": "string", + "description": "The API key. Treat as a secret." + }, + "host": { + "type": "string", + "description": "Authentication host." + }, + "copilotUser": { + "$ref": "#/definitions/CopilotUserResponse", + "description": "Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set." + } + }, + "required": [ + "type", + "apiKey", + "host" + ], + "additionalProperties": false, + "title": "ApiKeyAuthInfo", + "description": "Schema for the `ApiKeyAuthInfo` type." + }, + "AuthInfo": { + "anyOf": [ + { + "$ref": "#/definitions/HMACAuthInfo" + }, + { + "$ref": "#/definitions/EnvAuthInfo" + }, + { + "$ref": "#/definitions/TokenAuthInfo" + }, + { + "$ref": "#/definitions/CopilotApiTokenAuthInfo" + }, + { + "$ref": "#/definitions/UserAuthInfo" + }, + { + "$ref": "#/definitions/GhCliAuthInfo" + }, + { + "$ref": "#/definitions/ApiKeyAuthInfo" + } + ], + "description": "The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit.", + "title": "AuthInfo" + }, + "AuthInfoType": { + "type": "string", + "enum": [ + "hmac", + "env", + "user", + "gh-cli", + "api-key", + "token", + "copilot-api-token" + ], + "description": "Authentication type", + "title": "AuthInfoType", + "x-enumDescriptions": { + "hmac": "Authentication provided by a GitHub App HMAC credential.", + "env": "Authentication resolved from environment-provided credentials.", + "user": "Authentication from an interactive user sign-in.", + "gh-cli": "Authentication delegated to the GitHub CLI.", + "api-key": "Authentication from an API key credential.", + "token": "Authentication from a GitHub token.", + "copilot-api-token": "Authentication from a Copilot API token." + } + }, + "CanvasAction": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name exposed by the canvas provider" + }, + "description": { + "type": "string", + "description": "Description of the action" + }, + "inputSchema": { + "$ref": "#/definitions/CanvasJsonSchema", + "description": "JSON Schema for the action input" + } + }, + "required": [ + "name" + ], + "additionalProperties": false, + "description": "Canvas action that the agent or host can invoke. To discover the input schema for a particular action, call the list_canvas_capabilities tool.", + "title": "CanvasAction" + }, + "CanvasCloseRequest": { + "type": "object", + "properties": { + "instanceId": { + "type": "string", + "description": "Open canvas instance identifier" + } + }, + "required": [ + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas close parameters.", + "title": "CanvasCloseRequest" + }, + "CanvasHostContext": { + "type": "object", + "properties": { + "capabilities": { + "$ref": "#/definitions/CanvasHostContextCapabilities", + "description": "Host capabilities" + } + }, + "additionalProperties": false, + "description": "Host context supplied by the runtime.", + "title": "CanvasHostContext" + }, + "CanvasHostContextCapabilities": { + "type": "object", + "properties": { + "canvases": { + "type": "boolean", + "description": "Whether canvas rendering is supported" + } + }, + "additionalProperties": false, + "description": "Host capabilities", + "title": "CanvasHostContextCapabilities" + }, + "CanvasInstanceAvailability": { + "type": "string", + "enum": [ + "ready", + "stale" + ], + "description": "Runtime-controlled routing state for an open canvas instance.", + "title": "CanvasInstanceAvailability", + "x-enumDescriptions": { + "ready": "The owning provider is currently connected and routing calls will be dispatched normally.", + "stale": "The owning provider is not currently connected. Routing calls fail with canvas_provider_unavailable until the agent re-issues open_canvas (which rehydrates via a fresh canvas.open) or the provider reconnects." + } + }, + "CanvasInvokeActionRequest": { + "type": "object", + "properties": { + "instanceId": { + "type": "string", + "description": "Open canvas instance identifier" + }, + "actionName": { + "type": "string", + "description": "Action name to invoke" + }, + "input": { + "description": "Action input", + "x-opaque-json": true + } + }, + "required": [ + "instanceId", + "actionName" + ], + "additionalProperties": false, + "description": "Canvas action invocation parameters.", + "title": "CanvasInvokeActionRequest" + }, + "CanvasInvokeActionResult": { + "type": "object", + "properties": { + "result": { + "description": "Provider-supplied action result", + "x-opaque-json": true + } + }, + "additionalProperties": false, + "description": "Canvas action invocation result.", + "title": "CanvasInvokeActionResult" + }, + "CanvasJsonSchema": { + "description": "JSON Schema for canvas open input", + "title": "CanvasJsonSchema", + "x-opaque-json": true + }, + "CanvasList": { + "type": "object", + "properties": { + "canvases": { + "type": "array", + "items": { + "$ref": "#/definitions/DiscoveredCanvas", + "description": "Canvas available in the current session." + }, + "description": "Declared canvases available in this session" + } + }, + "required": [ + "canvases" + ], + "additionalProperties": false, + "description": "Declared canvases available in this session.", + "title": "CanvasList" + }, + "CanvasListOpenResult": { + "type": "object", + "properties": { + "openCanvases": { + "type": "array", + "items": { + "$ref": "#/definitions/OpenCanvasInstance", + "description": "Open canvas instance snapshot." + }, + "description": "Currently open canvas instances" + } + }, + "required": [ + "openCanvases" + ], + "additionalProperties": false, + "description": "Live open-canvas snapshot.", + "title": "CanvasListOpenResult" + }, + "CanvasOpenRequest": { + "type": "object", + "properties": { + "extensionId": { + "type": "string", + "description": "Owning provider identifier. Optional when the canvasId is unique across providers; required to disambiguate when multiple providers register the same canvasId." + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Caller-supplied stable instance identifier" + }, + "input": { + "description": "Canvas open input", + "x-opaque-json": true + } + }, + "required": [ + "canvasId", + "instanceId" + ], + "additionalProperties": false, + "description": "Canvas open parameters.", + "title": "CanvasOpenRequest" + }, + "CanvasProviderCloseRequest": { + "type": "object", + "properties": { + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "instanceId": { + "type": "string", + "description": "Canvas instance identifier" + }, + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." + } + }, + "required": [ + "extensionId", + "canvasId", + "instanceId" ], "additionalProperties": false, - "description": "The newly selected custom agent.", - "title": "AgentSelectResult" + "description": "Canvas close parameters sent to the provider.", + "title": "CanvasProviderCloseRequest" }, - "ApiKeyAuthInfo": { + "CanvasProviderInvokeActionRequest": { "type": "object", "properties": { - "type": { + "extensionId": { "type": "string", - "const": "api-key", - "description": "API-key authentication for non-GitHub LLM providers (e.g. when running BYOM-style)." + "description": "Owning provider identifier" }, - "apiKey": { + "canvasId": { "type": "string", - "description": "The API key. Treat as a secret." + "description": "Provider-local canvas identifier" }, - "host": { + "instanceId": { "type": "string", - "description": "Authentication host." + "description": "Canvas instance identifier" }, - "copilotUser": { - "$ref": "#/definitions/CopilotUserResponse", - "description": "Snapshot of the authenticated user's Copilot subscription info, if known. Mirrors the GitHub API `/copilot_internal/v2/token` user response shape — the runtime trusts this verbatim and does not re-fetch when set." + "actionName": { + "type": "string", + "description": "Action name to invoke" + }, + "input": { + "description": "Action input", + "x-opaque-json": true + }, + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." } }, "required": [ - "type", - "apiKey", - "host" + "extensionId", + "canvasId", + "instanceId", + "actionName" ], "additionalProperties": false, - "title": "ApiKeyAuthInfo", - "description": "Schema for the `ApiKeyAuthInfo` type." + "description": "Canvas action invocation parameters sent to the provider.", + "title": "CanvasProviderInvokeActionRequest" }, - "AuthInfo": { - "anyOf": [ - { - "$ref": "#/definitions/HMACAuthInfo" - }, - { - "$ref": "#/definitions/EnvAuthInfo" - }, - { - "$ref": "#/definitions/TokenAuthInfo" + "CanvasProviderOpenRequest": { + "type": "object", + "properties": { + "extensionId": { + "type": "string", + "description": "Owning provider identifier" }, - { - "$ref": "#/definitions/CopilotApiTokenAuthInfo" + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" }, - { - "$ref": "#/definitions/UserAuthInfo" + "instanceId": { + "type": "string", + "description": "Stable caller-supplied canvas instance identifier" }, - { - "$ref": "#/definitions/GhCliAuthInfo" + "input": { + "description": "Canvas open input", + "x-opaque-json": true }, - { - "$ref": "#/definitions/ApiKeyAuthInfo" + "host": { + "$ref": "#/definitions/CanvasHostContext", + "description": "Host context supplied by the runtime." } + }, + "required": [ + "extensionId", + "canvasId", + "instanceId" ], - "description": "The new auth credentials to install on the session. When omitted or `undefined`, the call is a no-op and the session's existing credentials are preserved. The runtime stores the value verbatim and uses it for outbound model/API requests; it does NOT re-validate or re-fetch the associated Copilot user response. Several variants carry secret material; treat this method's params as containing secrets at rest and in transit.", - "title": "AuthInfo" + "additionalProperties": false, + "description": "Canvas open parameters sent to the provider.", + "title": "CanvasProviderOpenRequest" }, - "AuthInfoType": { - "type": "string", - "enum": [ - "hmac", - "env", - "user", - "gh-cli", - "api-key", - "token", - "copilot-api-token" - ], - "description": "Authentication type", - "title": "AuthInfoType", - "x-enumDescriptions": { - "hmac": "Authentication provided by a GitHub App HMAC credential.", - "env": "Authentication resolved from environment-provided credentials.", - "user": "Authentication from an interactive user sign-in.", - "gh-cli": "Authentication delegated to the GitHub CLI.", - "api-key": "Authentication from an API key credential.", - "token": "Authentication from a GitHub token.", - "copilot-api-token": "Authentication from a Copilot API token." - } + "CanvasProviderOpenResult": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL for web-rendered canvases" + }, + "title": { + "type": "string", + "description": "Provider-supplied title" + }, + "status": { + "type": "string", + "description": "Provider-supplied status text" + } + }, + "additionalProperties": false, + "description": "Canvas open result returned by the provider.", + "title": "CanvasProviderOpenResult" }, "CommandList": { "type": "object", @@ -6204,6 +6846,53 @@ "description": "The currently selected model and reasoning effort for the session.", "title": "CurrentModel" }, + "DiscoveredCanvas": { + "type": "object", + "properties": { + "displayName": { + "type": "string", + "description": "Human-readable canvas name" + }, + "description": { + "type": "string", + "minLength": 1, + "description": "Short, single-sentence description shown to the agent in canvas catalogs." + }, + "inputSchema": { + "$ref": "#/definitions/CanvasJsonSchema", + "description": "JSON Schema for canvas open input" + }, + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/CanvasAction", + "description": "Canvas action that the agent or host can invoke. To discover the input schema for a particular action, call the list_canvas_capabilities tool." + }, + "description": "Actions the agent or host may invoke on an open instance" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "extensionName": { + "type": "string", + "description": "Owning extension display name, when available" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + } + }, + "required": [ + "displayName", + "description", + "extensionId", + "canvasId" + ], + "additionalProperties": false, + "description": "Canvas available in the current session.", + "title": "DiscoveredCanvas" + }, "DiscoveredMcpServer": { "type": "object", "properties": { @@ -8638,6 +9327,14 @@ "description": "Timeout in milliseconds for tool calls to this server.", "format": "duration" }, + "oidc": { + "$ref": "#/definitions/McpServerConfigHttpOidc", + "description": "OIDC token configuration. When truthy, a token is automatically gathered." + }, + "auth": { + "$ref": "#/definitions/McpServerConfigHttpAuth", + "description": "Additional authentication configuration for this server." + }, "url": { "type": "string", "format": "uri", @@ -8661,10 +9358,6 @@ "oauthGrantType": { "$ref": "#/definitions/McpServerConfigHttpOauthGrantType", "description": "OAuth grant type to use when authenticating to the remote MCP server." - }, - "auth": { - "$ref": "#/definitions/McpServerConfigHttpAuth", - "description": "Additional authentication configuration for this server." } }, "required": [ @@ -8684,7 +9377,7 @@ "description": "Fixed port for the OAuth redirect callback server." } }, - "additionalProperties": false, + "additionalProperties": true, "description": "Additional authentication configuration for this server.", "title": "McpServerConfigHttpAuth" }, @@ -8701,6 +9394,20 @@ "client_credentials": "Headless client credentials flow using the configured OAuth client." } }, + "McpServerConfigHttpOidc": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "additionalProperties": {} + } + ], + "description": "OIDC token configuration. When truthy, a token is automatically gathered.", + "title": "McpServerConfigHttpOidc", + "x-opaque-json": true + }, "McpServerConfigHttpType": { "type": "string", "enum": [ @@ -8740,6 +9447,14 @@ "description": "Timeout in milliseconds for tool calls to this server.", "format": "duration" }, + "oidc": { + "$ref": "#/definitions/McpServerConfigStdioOidc", + "description": "OIDC token configuration. When truthy, a token is automatically gathered." + }, + "auth": { + "$ref": "#/definitions/McpServerConfigStdioAuth", + "description": "Authentication configuration for this server." + }, "command": { "type": "string", "description": "Executable command used to start the Stdio MCP server process." @@ -8771,6 +9486,34 @@ "description": "Stdio MCP server configuration launched as a child process.", "title": "McpServerConfigStdio" }, + "McpServerConfigStdioAuth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "additionalProperties": {} + } + ], + "description": "Authentication configuration for this server.", + "title": "McpServerConfigStdioAuth", + "x-opaque-json": true + }, + "McpServerConfigStdioOidc": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "object", + "additionalProperties": {} + } + ], + "description": "OIDC token configuration. When truthy, a token is automatically gathered.", + "title": "McpServerConfigStdioOidc", + "x-opaque-json": true + }, "McpServerList": { "type": "object", "properties": { @@ -9660,6 +10403,61 @@ "description": "New friendly name to apply to the session.", "title": "NameSetRequest" }, + "OpenCanvasInstance": { + "type": "object", + "properties": { + "instanceId": { + "type": "string", + "description": "Stable caller-supplied canvas instance identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "extensionName": { + "type": "string", + "description": "Owning extension display name, when available" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "title": { + "type": "string", + "description": "Rendered title" + }, + "status": { + "type": "string", + "description": "Provider-supplied status text" + }, + "url": { + "type": "string", + "description": "URL for web-rendered canvases" + }, + "input": { + "description": "Input supplied when the instance was opened", + "x-opaque-json": true + }, + "reopen": { + "type": "boolean", + "description": "Whether this snapshot came from an idempotent reopen" + }, + "availability": { + "$ref": "#/definitions/CanvasInstanceAvailability", + "description": "Runtime-controlled routing state for an open canvas instance." + } + }, + "required": [ + "instanceId", + "extensionId", + "canvasId", + "reopen", + "availability" + ], + "additionalProperties": false, + "description": "Open canvas instance snapshot.", + "title": "OpenCanvasInstance" + }, "OptionsUpdateEnvValueMode": { "type": "string", "enum": [ @@ -12727,14 +13525,14 @@ "items": { "$ref": "#/definitions/SessionMetadata" }, - "description": "Same records, with summary and context backfilled" + "description": "Enriched records, with summary and context backfilled. Sessions confirmed empty and unnamed may be omitted." } }, "required": [ "sessions" ], "additionalProperties": false, - "description": "The same metadata records, with summary and context fields backfilled where available.", + "description": "The enriched metadata records, with summary and context fields backfilled where available. Sessions confirmed empty and unnamed are omitted.", "title": "SessionEnrichMetadataResult" }, "SessionFsAppendFileRequest": { @@ -17013,6 +17811,107 @@ "title": "UserToolSessionApprovalWrite", "description": "Schema for the `UserToolSessionApprovalWrite` type." }, + "WorkspaceDiffFileChange": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to the changed file, relative to the workspace root." + }, + "diff": { + "type": "string", + "description": "Unified diff content for the file. Empty when the diff was truncated." + }, + "changeType": { + "$ref": "#/definitions/WorkspaceDiffFileChangeType", + "description": "Type of change represented by this file diff." + }, + "oldPath": { + "type": "string", + "description": "Original file path for renamed files." + }, + "isTruncated": { + "type": "boolean", + "description": "Whether the diff content was omitted because it exceeded the per-file size limit." + } + }, + "required": [ + "path", + "diff", + "changeType" + ], + "additionalProperties": false, + "description": "A single changed file and its unified diff.", + "title": "WorkspaceDiffFileChange" + }, + "WorkspaceDiffFileChangeType": { + "type": "string", + "enum": [ + "added", + "modified", + "deleted", + "renamed" + ], + "description": "Type of change represented by this file diff.", + "title": "WorkspaceDiffFileChangeType", + "x-enumDescriptions": { + "added": "The file was added.", + "modified": "The file was modified.", + "deleted": "The file was deleted.", + "renamed": "The file was renamed." + } + }, + "WorkspaceDiffMode": { + "type": "string", + "enum": [ + "unstaged", + "branch" + ], + "description": "Diff mode requested by the client.", + "title": "WorkspaceDiffMode", + "x-enumDescriptions": { + "unstaged": "Return staged, unstaged, and untracked working tree changes.", + "branch": "Return changes compared with the default branch." + } + }, + "WorkspaceDiffResult": { + "type": "object", + "properties": { + "requestedMode": { + "$ref": "#/definitions/WorkspaceDiffMode", + "description": "Diff mode requested by the client." + }, + "mode": { + "$ref": "#/definitions/WorkspaceDiffMode", + "description": "Effective mode used for the returned changes." + }, + "changes": { + "type": "array", + "items": { + "$ref": "#/definitions/WorkspaceDiffFileChange", + "description": "A single changed file and its unified diff." + }, + "description": "Changed files and their unified diffs." + }, + "baseBranch": { + "type": "string", + "description": "Default branch used for a branch diff, when branch mode was requested." + }, + "isFallback": { + "type": "boolean", + "description": "Whether a requested branch diff fell back to unstaged changes because branch diff failed." + } + }, + "required": [ + "requestedMode", + "mode", + "changes", + "isFallback" + ], + "additionalProperties": false, + "description": "Workspace diff result for the requested mode.", + "title": "WorkspaceDiffResult" + }, "WorkspacesCheckpoints": { "type": "object", "properties": { @@ -17059,6 +17958,21 @@ "description": "Relative path and UTF-8 content for the workspace file to create or overwrite.", "title": "WorkspacesCreateFileRequest" }, + "WorkspacesDiffRequest": { + "type": "object", + "properties": { + "mode": { + "$ref": "#/definitions/WorkspaceDiffMode", + "description": "Diff mode requested by the client." + } + }, + "required": [ + "mode" + ], + "additionalProperties": false, + "description": "Parameters for computing a workspace diff.", + "title": "WorkspacesDiffRequest" + }, "WorkspacesGetWorkspaceResult": { "type": "object", "properties": { diff --git a/schemas/session-events.schema.json b/schemas/session-events.schema.json index 88fb105..90977be 100644 --- a/schemas/session-events.schema.json +++ b/schemas/session-events.schema.json @@ -1412,6 +1412,277 @@ "description": "Session event \"session.background_tasks_changed\".", "title": "BackgroundTasksChangedEvent" }, + "CanvasOpenedAvailability": { + "type": "string", + "enum": [ + "ready", + "stale" + ], + "description": "Runtime-controlled routing state for the instance. \"ready\" when the provider connection is live; \"stale\" when the provider has gone away and the instance is awaiting rebinding.", + "title": "CanvasOpenedAvailability", + "x-enumDescriptions": { + "ready": "Provider connection is live; actions can be invoked.", + "stale": "Provider has gone away; the instance is awaiting rebinding." + } + }, + "CanvasOpenedData": { + "type": "object", + "properties": { + "instanceId": { + "type": "string", + "description": "Stable caller-supplied canvas instance identifier" + }, + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "extensionName": { + "type": "string", + "description": "Owning extension display name, when available" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "title": { + "type": "string", + "description": "Rendered title" + }, + "status": { + "type": "string", + "description": "Provider-supplied status text" + }, + "url": { + "type": "string", + "description": "URL for web-rendered canvases" + }, + "input": { + "description": "Input supplied when the instance was opened", + "x-opaque-json": true + }, + "reopen": { + "type": "boolean", + "description": "Whether this notification represents an idempotent reopen" + }, + "availability": { + "$ref": "#/definitions/CanvasOpenedAvailability", + "description": "Runtime-controlled routing state for the instance. \"ready\" when the provider connection is live; \"stale\" when the provider has gone away and the instance is awaiting rebinding." + } + }, + "required": [ + "instanceId", + "extensionId", + "canvasId", + "reopen", + "availability" + ], + "additionalProperties": false, + "title": "CanvasOpenedData", + "description": "Schema for the `CanvasOpenedData` type." + }, + "CanvasOpenedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique event identifier (UUID v4), generated when the event is emitted" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the event was created" + }, + "parentId": { + "anyOf": [ + { + "type": "string", + "format": "uuid" + }, + { + "type": "null" + } + ], + "description": "ID of the chronologically preceding event in the session, forming a linked chain. Null for the first event." + }, + "ephemeral": { + "type": "boolean", + "const": true, + "description": "Always true for events that are transient and not persisted to the session event log on disk." + }, + "agentId": { + "type": "string", + "description": "Sub-agent instance identifier. Absent for events from the root/main agent and session-level events." + }, + "type": { + "type": "string", + "const": "session.canvas.opened", + "description": "Type discriminator. Always \"session.canvas.opened\"." + }, + "data": { + "$ref": "#/definitions/CanvasOpenedData", + "description": "Schema for the `CanvasOpenedData` type." + } + }, + "required": [ + "id", + "timestamp", + "parentId", + "ephemeral", + "type", + "data" + ], + "additionalProperties": false, + "description": "Session event \"session.canvas.opened\".", + "title": "CanvasOpenedEvent" + }, + "CanvasRegistryChangedCanvas": { + "type": "object", + "properties": { + "extensionId": { + "type": "string", + "description": "Owning provider identifier" + }, + "extensionName": { + "type": "string", + "description": "Owning extension display name, when available" + }, + "canvasId": { + "type": "string", + "description": "Provider-local canvas identifier" + }, + "displayName": { + "type": "string", + "description": "Human-readable canvas name" + }, + "description": { + "type": "string", + "minLength": 1, + "description": "Short, single-sentence description shown to the agent in canvas catalogs." + }, + "inputSchema": { + "type": "object", + "additionalProperties": {}, + "description": "JSON Schema for canvas open input", + "x-opaque-json": true + }, + "actions": { + "type": "array", + "items": { + "$ref": "#/definitions/CanvasRegistryChangedCanvasAction" + }, + "description": "Actions the agent or host may invoke" + } + }, + "required": [ + "extensionId", + "canvasId", + "displayName", + "description" + ], + "additionalProperties": false, + "title": "CanvasRegistryChangedCanvas", + "description": "Schema for the `CanvasRegistryChangedCanvas` type." + }, + "CanvasRegistryChangedCanvasAction": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Action name" + }, + "description": { + "type": "string", + "description": "Action description" + }, + "inputSchema": { + "type": "object", + "additionalProperties": {}, + "description": "JSON Schema for action input", + "x-opaque-json": true + } + }, + "required": [ + "name" + ], + "additionalProperties": false, + "title": "CanvasRegistryChangedCanvasAction", + "description": "Schema for the `CanvasRegistryChangedCanvasAction` type." + }, + "CanvasRegistryChangedData": { + "type": "object", + "properties": { + "canvases": { + "type": "array", + "items": { + "$ref": "#/definitions/CanvasRegistryChangedCanvas" + }, + "description": "Canvas declarations currently available" + } + }, + "required": [ + "canvases" + ], + "additionalProperties": false, + "title": "CanvasRegistryChangedData", + "description": "Schema for the `CanvasRegistryChangedData` type." + }, + "CanvasRegistryChangedEvent": { + "type": "object", + "properties": { + "id": { + "type": "string", + "format": "uuid", + "description": "Unique event identifier (UUID v4), generated when the event is emitted" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "description": "ISO 8601 timestamp when the event was created" + }, + "parentId": { + "anyOf": [ + { + "type": "string", + "format": "uuid" + }, + { + "type": "null" + } + ], + "description": "ID of the chronologically preceding event in the session, forming a linked chain. Null for the first event." + }, + "ephemeral": { + "type": "boolean", + "const": true, + "description": "Always true for events that are transient and not persisted to the session event log on disk." + }, + "agentId": { + "type": "string", + "description": "Sub-agent instance identifier. Absent for events from the root/main agent and session-level events." + }, + "type": { + "type": "string", + "const": "session.canvas.registry_changed", + "description": "Type discriminator. Always \"session.canvas.registry_changed\"." + }, + "data": { + "$ref": "#/definitions/CanvasRegistryChangedData", + "description": "Schema for the `CanvasRegistryChangedData` type." + } + }, + "required": [ + "id", + "timestamp", + "parentId", + "ephemeral", + "type", + "data" + ], + "additionalProperties": false, + "description": "Session event \"session.canvas.registry_changed\".", + "title": "CanvasRegistryChangedEvent" + }, "CapabilitiesChangedData": { "type": "object", "properties": { @@ -1490,6 +1761,10 @@ "mcpApps": { "type": "boolean", "description": "Whether MCP Apps (SEP-1865) UI passthrough is now supported" + }, + "canvases": { + "type": "boolean", + "description": "Whether canvas rendering is now supported" } }, "additionalProperties": false, @@ -7103,6 +7378,14 @@ "$ref": "#/definitions/ExtensionsLoadedEvent", "description": "Session event \"session.extensions_loaded\"." }, + { + "$ref": "#/definitions/CanvasOpenedEvent", + "description": "Session event \"session.canvas.opened\"." + }, + { + "$ref": "#/definitions/CanvasRegistryChangedEvent", + "description": "Session event \"session.canvas.registry_changed\"." + }, { "$ref": "#/definitions/McpAppToolCallCompleteEvent", "description": "Session event \"mcp_app.tool_call_complete\". MCP App view called a tool on a connected MCP server (SEP-1865)" diff --git a/src/github/copilot_sdk/generated/event_specs.clj b/src/github/copilot_sdk/generated/event_specs.clj index 567e35a..f389489 100644 --- a/src/github/copilot_sdk/generated/event_specs.clj +++ b/src/github/copilot_sdk/generated/event_specs.clj @@ -41,12 +41,14 @@ (s/def :github.copilot-sdk.generated.event-specs/args clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/arguments (s/spec (fn [v948] (or (s/valid? clojure.core/any? v948) (s/valid? clojure.core/map? v948))))) +(s/def :github.copilot-sdk.generated.event-specs/arguments (s/spec (fn [v950] (or (s/valid? clojure.core/any? v950) (s/valid? clojure.core/map? v950))))) (s/def :github.copilot-sdk.generated.event-specs/attachments (s/coll-of (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?))) (s/def :github.copilot-sdk.generated.event-specs/auto-approve-edits clojure.core/boolean?) +(s/def :github.copilot-sdk.generated.event-specs/availability #{"ready" "stale"}) + (s/def :github.copilot-sdk.generated.event-specs/base-commit clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/branch clojure.core/string?) @@ -55,6 +57,10 @@ (s/def :github.copilot-sdk.generated.event-specs/cache-write-tokens clojure.core/integer?) +(s/def :github.copilot-sdk.generated.event-specs/canvas-id clojure.core/string?) + +(s/def :github.copilot-sdk.generated.event-specs/canvases (s/coll-of clojure.core/map?)) + (s/def :github.copilot-sdk.generated.event-specs/cause clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/checkpoint-number clojure.core/integer?) @@ -73,9 +79,9 @@ (s/def :github.copilot-sdk.generated.event-specs/compaction-tokens-used clojure.core/map?) -(s/def :github.copilot-sdk.generated.event-specs/content (s/spec (fn [v945] (or (s/valid? clojure.core/string? v945) (s/valid? clojure.core/map? v945))))) +(s/def :github.copilot-sdk.generated.event-specs/content (s/spec (fn [v947] (or (s/valid? clojure.core/string? v947) (s/valid? clojure.core/map? v947))))) -(s/def :github.copilot-sdk.generated.event-specs/context (s/spec (fn [v943] (or (s/valid? clojure.core/map? v943) (s/valid? clojure.core/string? v943))))) +(s/def :github.copilot-sdk.generated.event-specs/context (s/spec (fn [v944] (or (s/valid? clojure.core/map? v944) (s/valid? clojure.core/string? v944))))) (s/def :github.copilot-sdk.generated.event-specs/context-tier (s/nilable #{"long_context" "default"})) @@ -109,7 +115,7 @@ (s/def :github.copilot-sdk.generated.event-specs/duration clojure.core/integer?) -(s/def :github.copilot-sdk.generated.event-specs/duration-ms (s/spec (fn [v938] (or (s/valid? clojure.core/integer? v938) (s/valid? clojure.core/number? v938))))) +(s/def :github.copilot-sdk.generated.event-specs/duration-ms (s/spec (fn [v939] (or (s/valid? clojure.core/integer? v939) (s/valid? clojure.core/number? v939))))) (s/def :github.copilot-sdk.generated.event-specs/elicitation-source clojure.core/string?) @@ -119,7 +125,7 @@ (s/def :github.copilot-sdk.generated.event-specs/ephemeral clojure.core/boolean?) -(s/def :github.copilot-sdk.generated.event-specs/error (s/spec (fn [v940] (or (s/valid? clojure.core/string? v940) (s/valid? clojure.core/map? v940))))) +(s/def :github.copilot-sdk.generated.event-specs/error (s/spec (fn [v941] (or (s/valid? clojure.core/string? v941) (s/valid? clojure.core/map? v941))))) (s/def :github.copilot-sdk.generated.event-specs/error-code clojure.core/string?) @@ -135,6 +141,10 @@ (s/def :github.copilot-sdk.generated.event-specs/events-removed clojure.core/integer?) +(s/def :github.copilot-sdk.generated.event-specs/extension-id clojure.core/string?) + +(s/def :github.copilot-sdk.generated.event-specs/extension-name clojure.core/string?) + (s/def :github.copilot-sdk.generated.event-specs/extensions (s/coll-of clojure.core/map?)) (s/def :github.copilot-sdk.generated.event-specs/feedback clojure.core/string?) @@ -153,7 +163,7 @@ (s/def :github.copilot-sdk.generated.event-specs/host-type #{"github" "ado"}) -(s/def :github.copilot-sdk.generated.event-specs/id (s/spec (fn [v941] (or (s/valid? clojure.core/string? v941) (s/valid? clojure.core/integer? v941))))) +(s/def :github.copilot-sdk.generated.event-specs/id (s/spec (fn [v942] (or (s/valid? clojure.core/string? v942) (s/valid? clojure.core/integer? v942))))) (s/def :github.copilot-sdk.generated.event-specs/info-type clojure.core/string?) @@ -163,6 +173,8 @@ (s/def :github.copilot-sdk.generated.event-specs/input-tokens clojure.core/integer?) +(s/def :github.copilot-sdk.generated.event-specs/instance-id clojure.core/string?) + (s/def :github.copilot-sdk.generated.event-specs/intent clojure.core/string?) (s/def :github.copilot-sdk.generated.event-specs/inter-token-latency-ms clojure.core/number?) @@ -211,7 +223,7 @@ (s/def :github.copilot-sdk.generated.event-specs/new-model clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/operation (s/spec (fn [v944] (or (s/valid? #{"delete" "update" "create"} v944) (s/valid? #{"update" "create"} v944))))) +(s/def :github.copilot-sdk.generated.event-specs/operation (s/spec (fn [v946] (or (s/valid? #{"delete" "update" "create"} v946) (s/valid? #{"update" "create"} v946))))) (s/def :github.copilot-sdk.generated.event-specs/output clojure.core/any?) @@ -279,7 +291,7 @@ (s/def :github.copilot-sdk.generated.event-specs/reason #{"user_abort" "remote_command" "user_initiated"}) -(s/def :github.copilot-sdk.generated.event-specs/reasoning-effort (s/spec (fn [v942] (or (s/valid? clojure.core/string? v942) (s/valid? clojure.core/any? v942))))) +(s/def :github.copilot-sdk.generated.event-specs/reasoning-effort (s/spec (fn [v943] (or (s/valid? clojure.core/string? v943) (s/valid? clojure.core/any? v943))))) (s/def :github.copilot-sdk.generated.event-specs/reasoning-id clojure.core/string?) @@ -299,7 +311,9 @@ (s/def :github.copilot-sdk.generated.event-specs/remote-steerable clojure.core/boolean?) -(s/def :github.copilot-sdk.generated.event-specs/repository (s/spec (fn [v939] (or (s/valid? clojure.core/map? v939) (s/valid? clojure.core/string? v939))))) +(s/def :github.copilot-sdk.generated.event-specs/reopen clojure.core/boolean?) + +(s/def :github.copilot-sdk.generated.event-specs/repository (s/spec (fn [v940] (or (s/valid? clojure.core/map? v940) (s/valid? clojure.core/string? v940))))) (s/def :github.copilot-sdk.generated.event-specs/repository-host clojure.core/string?) @@ -311,7 +325,7 @@ (s/def :github.copilot-sdk.generated.event-specs/response #{"yes_always" "yes" "no"}) -(s/def :github.copilot-sdk.generated.event-specs/result (s/spec (fn [v949] (or (s/valid? clojure.core/map? v949) (s/valid? (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?) v949))))) +(s/def :github.copilot-sdk.generated.event-specs/result (s/spec (fn [v951] (or (s/valid? clojure.core/map? v951) (s/valid? (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?) v951))))) (s/def :github.copilot-sdk.generated.event-specs/resume-time clojure.core/string?) @@ -343,7 +357,7 @@ (s/def :github.copilot-sdk.generated.event-specs/skills (s/coll-of clojure.core/map?)) -(s/def :github.copilot-sdk.generated.event-specs/source (s/spec (fn [v946] (or (s/valid? clojure.core/string? v946) (s/valid? #{"top_level" "subagent" "mcp_sampling"} v946))))) +(s/def :github.copilot-sdk.generated.event-specs/source (s/spec (fn [v948] (or (s/valid? clojure.core/string? v948) (s/valid? #{"top_level" "subagent" "mcp_sampling"} v948))))) (s/def :github.copilot-sdk.generated.event-specs/source-type #{"remote" "local"}) @@ -353,7 +367,7 @@ (s/def :github.copilot-sdk.generated.event-specs/static-client-config clojure.core/map?) -(s/def :github.copilot-sdk.generated.event-specs/status #{"failed" "not_configured" "needs-auth" "connected" "disabled" "pending"}) +(s/def :github.copilot-sdk.generated.event-specs/status (s/spec (fn [v945] (or (s/valid? #{"failed" "not_configured" "needs-auth" "connected" "disabled" "pending"} v945) (s/valid? clojure.core/string? v945))))) (s/def :github.copilot-sdk.generated.event-specs/status-code clojure.core/integer?) @@ -423,7 +437,7 @@ (s/def :github.copilot-sdk.generated.event-specs/turn-id clojure.core/string?) -(s/def :github.copilot-sdk.generated.event-specs/type (s/spec (fn [v947] (or (s/valid? #{"session.start"} v947) (s/valid? #{"session.resume"} v947) (s/valid? #{"session.remote_steerable_changed"} v947) (s/valid? #{"session.error"} v947) (s/valid? #{"session.idle"} v947) (s/valid? #{"session.title_changed"} v947) (s/valid? #{"session.schedule_created"} v947) (s/valid? #{"session.schedule_cancelled"} v947) (s/valid? #{"session.info"} v947) (s/valid? #{"session.warning"} v947) (s/valid? #{"session.model_change"} v947) (s/valid? #{"session.mode_changed"} v947) (s/valid? #{"session.plan_changed"} v947) (s/valid? #{"session.workspace_file_changed"} v947) (s/valid? #{"session.handoff"} v947) (s/valid? #{"session.truncation"} v947) (s/valid? #{"session.snapshot_rewind"} v947) (s/valid? #{"session.shutdown"} v947) (s/valid? #{"session.context_changed"} v947) (s/valid? #{"session.usage_info"} v947) (s/valid? #{"session.compaction_start"} v947) (s/valid? #{"session.compaction_complete"} v947) (s/valid? #{"session.task_complete"} v947) (s/valid? #{"user.message"} v947) (s/valid? #{"pending_messages.modified"} v947) (s/valid? #{"assistant.turn_start"} v947) (s/valid? #{"assistant.intent"} v947) (s/valid? #{"assistant.reasoning"} v947) (s/valid? #{"assistant.reasoning_delta"} v947) (s/valid? #{"assistant.streaming_delta"} v947) (s/valid? #{"assistant.message"} v947) (s/valid? #{"assistant.message_start"} v947) (s/valid? #{"assistant.message_delta"} v947) (s/valid? #{"assistant.turn_end"} v947) (s/valid? #{"assistant.usage"} v947) (s/valid? #{"model.call_failure"} v947) (s/valid? #{"abort"} v947) (s/valid? #{"tool.user_requested"} v947) (s/valid? #{"tool.execution_start"} v947) (s/valid? #{"tool.execution_partial_result"} v947) (s/valid? #{"tool.execution_progress"} v947) (s/valid? #{"tool.execution_complete"} v947) (s/valid? #{"skill.invoked"} v947) (s/valid? #{"subagent.started"} v947) (s/valid? #{"subagent.completed"} v947) (s/valid? #{"subagent.failed"} v947) (s/valid? #{"subagent.selected"} v947) (s/valid? #{"subagent.deselected"} v947) (s/valid? #{"hook.start"} v947) (s/valid? #{"hook.end"} v947) (s/valid? #{"system.message"} v947) (s/valid? #{"system.notification"} v947) (s/valid? #{"permission.requested"} v947) (s/valid? #{"permission.completed"} v947) (s/valid? #{"user_input.requested"} v947) (s/valid? #{"user_input.completed"} v947) (s/valid? #{"elicitation.requested"} v947) (s/valid? #{"elicitation.completed"} v947) (s/valid? #{"sampling.requested"} v947) (s/valid? #{"sampling.completed"} v947) (s/valid? #{"mcp.oauth_required"} v947) (s/valid? #{"mcp.oauth_completed"} v947) (s/valid? #{"session.custom_notification"} v947) (s/valid? #{"external_tool.requested"} v947) (s/valid? #{"external_tool.completed"} v947) (s/valid? #{"command.queued"} v947) (s/valid? #{"command.execute"} v947) (s/valid? #{"command.completed"} v947) (s/valid? #{"auto_mode_switch.requested"} v947) (s/valid? #{"auto_mode_switch.completed"} v947) (s/valid? #{"commands.changed"} v947) (s/valid? #{"capabilities.changed"} v947) (s/valid? #{"exit_plan_mode.requested"} v947) (s/valid? #{"exit_plan_mode.completed"} v947) (s/valid? #{"session.tools_updated"} v947) (s/valid? #{"session.background_tasks_changed"} v947) (s/valid? #{"session.skills_loaded"} v947) (s/valid? #{"session.custom_agents_updated"} v947) (s/valid? #{"session.mcp_servers_loaded"} v947) (s/valid? #{"session.mcp_server_status_changed"} v947) (s/valid? #{"session.extensions_loaded"} v947) (s/valid? #{"mcp_app.tool_call_complete"} v947))))) +(s/def :github.copilot-sdk.generated.event-specs/type (s/spec (fn [v949] (or (s/valid? #{"session.start"} v949) (s/valid? #{"session.resume"} v949) (s/valid? #{"session.remote_steerable_changed"} v949) (s/valid? #{"session.error"} v949) (s/valid? #{"session.idle"} v949) (s/valid? #{"session.title_changed"} v949) (s/valid? #{"session.schedule_created"} v949) (s/valid? #{"session.schedule_cancelled"} v949) (s/valid? #{"session.info"} v949) (s/valid? #{"session.warning"} v949) (s/valid? #{"session.model_change"} v949) (s/valid? #{"session.mode_changed"} v949) (s/valid? #{"session.plan_changed"} v949) (s/valid? #{"session.workspace_file_changed"} v949) (s/valid? #{"session.handoff"} v949) (s/valid? #{"session.truncation"} v949) (s/valid? #{"session.snapshot_rewind"} v949) (s/valid? #{"session.shutdown"} v949) (s/valid? #{"session.context_changed"} v949) (s/valid? #{"session.usage_info"} v949) (s/valid? #{"session.compaction_start"} v949) (s/valid? #{"session.compaction_complete"} v949) (s/valid? #{"session.task_complete"} v949) (s/valid? #{"user.message"} v949) (s/valid? #{"pending_messages.modified"} v949) (s/valid? #{"assistant.turn_start"} v949) (s/valid? #{"assistant.intent"} v949) (s/valid? #{"assistant.reasoning"} v949) (s/valid? #{"assistant.reasoning_delta"} v949) (s/valid? #{"assistant.streaming_delta"} v949) (s/valid? #{"assistant.message"} v949) (s/valid? #{"assistant.message_start"} v949) (s/valid? #{"assistant.message_delta"} v949) (s/valid? #{"assistant.turn_end"} v949) (s/valid? #{"assistant.usage"} v949) (s/valid? #{"model.call_failure"} v949) (s/valid? #{"abort"} v949) (s/valid? #{"tool.user_requested"} v949) (s/valid? #{"tool.execution_start"} v949) (s/valid? #{"tool.execution_partial_result"} v949) (s/valid? #{"tool.execution_progress"} v949) (s/valid? #{"tool.execution_complete"} v949) (s/valid? #{"skill.invoked"} v949) (s/valid? #{"subagent.started"} v949) (s/valid? #{"subagent.completed"} v949) (s/valid? #{"subagent.failed"} v949) (s/valid? #{"subagent.selected"} v949) (s/valid? #{"subagent.deselected"} v949) (s/valid? #{"hook.start"} v949) (s/valid? #{"hook.end"} v949) (s/valid? #{"system.message"} v949) (s/valid? #{"system.notification"} v949) (s/valid? #{"permission.requested"} v949) (s/valid? #{"permission.completed"} v949) (s/valid? #{"user_input.requested"} v949) (s/valid? #{"user_input.completed"} v949) (s/valid? #{"elicitation.requested"} v949) (s/valid? #{"elicitation.completed"} v949) (s/valid? #{"sampling.requested"} v949) (s/valid? #{"sampling.completed"} v949) (s/valid? #{"mcp.oauth_required"} v949) (s/valid? #{"mcp.oauth_completed"} v949) (s/valid? #{"session.custom_notification"} v949) (s/valid? #{"external_tool.requested"} v949) (s/valid? #{"external_tool.completed"} v949) (s/valid? #{"command.queued"} v949) (s/valid? #{"command.execute"} v949) (s/valid? #{"command.completed"} v949) (s/valid? #{"auto_mode_switch.requested"} v949) (s/valid? #{"auto_mode_switch.completed"} v949) (s/valid? #{"commands.changed"} v949) (s/valid? #{"capabilities.changed"} v949) (s/valid? #{"exit_plan_mode.requested"} v949) (s/valid? #{"exit_plan_mode.completed"} v949) (s/valid? #{"session.tools_updated"} v949) (s/valid? #{"session.background_tasks_changed"} v949) (s/valid? #{"session.skills_loaded"} v949) (s/valid? #{"session.custom_agents_updated"} v949) (s/valid? #{"session.mcp_servers_loaded"} v949) (s/valid? #{"session.mcp_server_status_changed"} v949) (s/valid? #{"session.extensions_loaded"} v949) (s/valid? #{"session.canvas.opened"} v949) (s/valid? #{"session.canvas.registry_changed"} v949) (s/valid? #{"mcp_app.tool_call_complete"} v949))))) (s/def :github.copilot-sdk.generated.event-specs/ui clojure.core/map?) @@ -511,6 +525,10 @@ (s/def :github.copilot-sdk.generated.event-specs/session.background_tasks_changed-data (s/keys)) +(s/def :github.copilot-sdk.generated.event-specs/session.canvas.opened-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/availability :github.copilot-sdk.generated.event-specs/canvas-id :github.copilot-sdk.generated.event-specs/extension-id :github.copilot-sdk.generated.event-specs/instance-id :github.copilot-sdk.generated.event-specs/reopen] :opt-un [:github.copilot-sdk.generated.event-specs/extension-name :github.copilot-sdk.generated.event-specs/input :github.copilot-sdk.generated.event-specs/status :github.copilot-sdk.generated.event-specs/title :github.copilot-sdk.generated.event-specs/url])) + +(s/def :github.copilot-sdk.generated.event-specs/session.canvas.registry_changed-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/canvases])) + (s/def :github.copilot-sdk.generated.event-specs/session.compaction_complete-data (s/keys :req-un [:github.copilot-sdk.generated.event-specs/success] :opt-un [:github.copilot-sdk.generated.event-specs/checkpoint-number :github.copilot-sdk.generated.event-specs/checkpoint-path :github.copilot-sdk.generated.event-specs/compaction-tokens-used :github.copilot-sdk.generated.event-specs/conversation-tokens :github.copilot-sdk.generated.event-specs/custom-instructions :github.copilot-sdk.generated.event-specs/error :github.copilot-sdk.generated.event-specs/messages-removed :github.copilot-sdk.generated.event-specs/post-compaction-tokens :github.copilot-sdk.generated.event-specs/pre-compaction-messages-length :github.copilot-sdk.generated.event-specs/pre-compaction-tokens :github.copilot-sdk.generated.event-specs/request-id :github.copilot-sdk.generated.event-specs/service-request-id :github.copilot-sdk.generated.event-specs/summary-content :github.copilot-sdk.generated.event-specs/system-tokens :github.copilot-sdk.generated.event-specs/tokens-removed :github.copilot-sdk.generated.event-specs/tool-definitions-tokens])) (s/def :github.copilot-sdk.generated.event-specs/session.compaction_start-data (s/keys :opt-un [:github.copilot-sdk.generated.event-specs/conversation-tokens :github.copilot-sdk.generated.event-specs/system-tokens :github.copilot-sdk.generated.event-specs/tool-definitions-tokens])) @@ -675,6 +693,10 @@ (s/def :github.copilot-sdk.generated.event-specs/session.background_tasks_changed (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "session.background_tasks_changed" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/session.background_tasks_changed-data (:data event))))) +(s/def :github.copilot-sdk.generated.event-specs/session.canvas.opened (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "session.canvas.opened" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/session.canvas.opened-data (:data event))))) + +(s/def :github.copilot-sdk.generated.event-specs/session.canvas.registry_changed (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "session.canvas.registry_changed" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/session.canvas.registry_changed-data (:data event))))) + (s/def :github.copilot-sdk.generated.event-specs/session.compaction_complete (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id :github.copilot-sdk.generated.event-specs/ephemeral]) (fn [event] (clojure.core/= "session.compaction_complete" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/session.compaction_complete-data (:data event))))) (s/def :github.copilot-sdk.generated.event-specs/session.compaction_start (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id :github.copilot-sdk.generated.event-specs/ephemeral]) (fn [event] (clojure.core/= "session.compaction_start" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/session.compaction_start-data (:data event))))) @@ -767,7 +789,7 @@ (s/def :github.copilot-sdk.generated.event-specs/user_input.requested (s/and (s/keys :req-un [:github.copilot-sdk.generated.event-specs/data :github.copilot-sdk.generated.event-specs/ephemeral :github.copilot-sdk.generated.event-specs/id :github.copilot-sdk.generated.event-specs/parent-id :github.copilot-sdk.generated.event-specs/timestamp :github.copilot-sdk.generated.event-specs/type] :opt-un [:github.copilot-sdk.generated.event-specs/agent-id]) (fn [event] (clojure.core/= true (:ephemeral event))) (fn [event] (clojure.core/= "user_input.requested" (:type event))) (fn [event] (s/valid? clojure.core/string? (:id event))) (fn [event] (s/valid? :github.copilot-sdk.generated.event-specs/user_input.requested-data (:data event))))) -(def event-types "Set of all event-type strings known to the schema." #{"abort" "assistant.intent" "assistant.message" "assistant.message_delta" "assistant.message_start" "assistant.reasoning" "assistant.reasoning_delta" "assistant.streaming_delta" "assistant.turn_end" "assistant.turn_start" "assistant.usage" "auto_mode_switch.completed" "auto_mode_switch.requested" "capabilities.changed" "command.completed" "command.execute" "command.queued" "commands.changed" "elicitation.completed" "elicitation.requested" "exit_plan_mode.completed" "exit_plan_mode.requested" "external_tool.completed" "external_tool.requested" "hook.end" "hook.start" "mcp.oauth_completed" "mcp.oauth_required" "mcp_app.tool_call_complete" "model.call_failure" "pending_messages.modified" "permission.completed" "permission.requested" "sampling.completed" "sampling.requested" "session.background_tasks_changed" "session.compaction_complete" "session.compaction_start" "session.context_changed" "session.custom_agents_updated" "session.custom_notification" "session.error" "session.extensions_loaded" "session.handoff" "session.idle" "session.info" "session.mcp_server_status_changed" "session.mcp_servers_loaded" "session.mode_changed" "session.model_change" "session.plan_changed" "session.remote_steerable_changed" "session.resume" "session.schedule_cancelled" "session.schedule_created" "session.shutdown" "session.skills_loaded" "session.snapshot_rewind" "session.start" "session.task_complete" "session.title_changed" "session.tools_updated" "session.truncation" "session.usage_info" "session.warning" "session.workspace_file_changed" "skill.invoked" "subagent.completed" "subagent.deselected" "subagent.failed" "subagent.selected" "subagent.started" "system.message" "system.notification" "tool.execution_complete" "tool.execution_partial_result" "tool.execution_progress" "tool.execution_start" "tool.user_requested" "user.message" "user_input.completed" "user_input.requested"}) +(def event-types "Set of all event-type strings known to the schema." #{"abort" "assistant.intent" "assistant.message" "assistant.message_delta" "assistant.message_start" "assistant.reasoning" "assistant.reasoning_delta" "assistant.streaming_delta" "assistant.turn_end" "assistant.turn_start" "assistant.usage" "auto_mode_switch.completed" "auto_mode_switch.requested" "capabilities.changed" "command.completed" "command.execute" "command.queued" "commands.changed" "elicitation.completed" "elicitation.requested" "exit_plan_mode.completed" "exit_plan_mode.requested" "external_tool.completed" "external_tool.requested" "hook.end" "hook.start" "mcp.oauth_completed" "mcp.oauth_required" "mcp_app.tool_call_complete" "model.call_failure" "pending_messages.modified" "permission.completed" "permission.requested" "sampling.completed" "sampling.requested" "session.background_tasks_changed" "session.canvas.opened" "session.canvas.registry_changed" "session.compaction_complete" "session.compaction_start" "session.context_changed" "session.custom_agents_updated" "session.custom_notification" "session.error" "session.extensions_loaded" "session.handoff" "session.idle" "session.info" "session.mcp_server_status_changed" "session.mcp_servers_loaded" "session.mode_changed" "session.model_change" "session.plan_changed" "session.remote_steerable_changed" "session.resume" "session.schedule_cancelled" "session.schedule_created" "session.shutdown" "session.skills_loaded" "session.snapshot_rewind" "session.start" "session.task_complete" "session.title_changed" "session.tools_updated" "session.truncation" "session.usage_info" "session.warning" "session.workspace_file_changed" "skill.invoked" "subagent.completed" "subagent.deselected" "subagent.failed" "subagent.selected" "subagent.started" "system.message" "system.notification" "tool.execution_complete" "tool.execution_partial_result" "tool.execution_progress" "tool.execution_start" "tool.user_requested" "user.message" "user_input.completed" "user_input.requested"}) (defmulti event-mm :type) @@ -843,6 +865,10 @@ (defmethod event-mm "session.background_tasks_changed" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/session.background_tasks_changed)) +(defmethod event-mm "session.canvas.opened" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/session.canvas.opened)) + +(defmethod event-mm "session.canvas.registry_changed" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/session.canvas.registry_changed)) + (defmethod event-mm "session.compaction_complete" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/session.compaction_complete)) (defmethod event-mm "session.compaction_start" [_] (s/get-spec :github.copilot-sdk.generated.event-specs/session.compaction_start)) diff --git a/src/github/copilot_sdk/specs.clj b/src/github/copilot_sdk/specs.clj index 4a2b70e..4d2bfbc 100644 --- a/src/github/copilot_sdk/specs.clj +++ b/src/github/copilot_sdk/specs.clj @@ -902,7 +902,11 @@ ;; Schedule events (upstream schema 1.0.42) :copilot/session.schedule_created :copilot/session.schedule_cancelled ;; MCP Apps tool-call complete (upstream schema 1.0.52-4, SEP-1865) - :copilot/mcp_app.tool_call_complete}) + :copilot/mcp_app.tool_call_complete + ;; Canvas events (upstream PR #1401, schema 1.0.53+). Canvas runtime + ;; support itself is not yet exposed on the public Clojure API; these + ;; events flow through as generic session events for forward compat. + :copilot/session.canvas.opened :copilot/session.canvas.registry_changed}) ;; Session events (s/def ::already-in-use? boolean?) From cdd2f2e343b439d606d77dfa17c6009859b03e6e Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 27 May 2026 09:34:28 +0200 Subject: [PATCH 5/6] feat(hooks): add :on-post-tool-use-failure lifecycle hook (upstream PR #1421) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a new lifecycle hook dispatched after a tool execution whose result was "failure". `:on-post-tool-use` only fires for successful results, so register this handler to observe or react to failed tool outcomes. Note: "rejected", "denied", and "timeout" results do not currently trigger this hook — only "failure" does. Handler input has `:tool-name`, `:tool-args`, `:error` (string), plus the base hook fields (`:session-id`, `:timestamp`, `:cwd`). Optional return value `{:additional-context "..."}` is appended as hidden guidance to the model alongside the failed tool result. Wiring sites: - `specs/::on-post-tool-use-failure` fn spec, added to `::hooks` :opt-un `:on-post-tool-use-failure` - `client/create-session` docstring lists the new hook key - API.md hooks example documents input/output shape Tests cover (a) handler invocation + `additionalContext` round-trip on the wire, and (b) graceful nil result when only the success hook is registered. RED→GREEN: the new tests fail without the dispatcher change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 24 +++++++++-- doc/reference/API.md | 23 +++++++++- src/github/copilot_sdk/client.clj | 9 +++- src/github/copilot_sdk/session.clj | 1 + src/github/copilot_sdk/specs.clj | 2 + test/github/copilot_sdk/integration_test.clj | 44 ++++++++++++++++++++ 6 files changed, 96 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce76e0e..f44121c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. This change ## [Unreleased] ### Added (post-v1.0.0-beta.4 sync, round 5) +- **`:on-post-tool-use-failure` hook** — New lifecycle hook in the + `:hooks` map. Fires after a tool execution whose result was `"failure"`; + `:on-post-tool-use` only fires for successful results, so register this + handler to observe or react to failed tool outcomes. Note: `"rejected"`, + `"denied"`, and `"timeout"` results do not currently trigger this hook — + only `"failure"` does. Handler input has `:tool-name`, `:tool-args`, + `:error` (string), plus the base hook fields (`:session-id`, + `:timestamp`, `:cwd`). Optional return value: + `{:additional-context "..."}` is appended as hidden guidance to the + model alongside the failed tool result. (upstream PR #1421) - **`:runtime-instructions` system message section** — New section recognized by the SDK's `:system-message` `:customize` mode. Wire-encoded as `"runtime_instructions"` and accepted by `::specs/system-prompt-section`. @@ -32,10 +42,16 @@ All notable changes to this project will be documented in this file. This change on `:skill.invoked` data. - `:tool-description` and `:ui-resource` on `:tool.execution_complete` data. - **Schema bump** — `.copilot-schema-version` advanced from `1.0.52-1` to - `1.0.52` (stable). Picked up the 1.0.52-4 pre-release (upstream PR #1393) - and then advanced to the 1.0.52 stable release (upstream PR #1405); the - shipped JSON Schemas are byte-identical between 1.0.52-4 and 1.0.52, so - no additional schema-driven changes were required. + `1.0.55-1`. Picked up the 1.0.52-4 pre-release (upstream PR #1393), the + 1.0.52 stable release (upstream PR #1405), and the 1.0.53 / 1.0.53-2 / + 1.0.54 / 1.0.55-0 / 1.0.55-1 schema bumps (upstream PRs #1408, #1410, + #1411, #1412, #1432). Schema regen surfaces new wire-only canvas event + types (`session.canvas.opened`, `session.canvas.registry_changed`) and + the field set behind them. These events now appear in the public + `event-types` set for forward compatibility, but the canvas runtime + (extension manifests, `requestCanvasRenderer`, `openCanvases`, etc. — + upstream PRs #1401, #1413) is **not yet exposed** on the public Clojure + API. Canvas events will flow through as generic session events. ### Changed (post-v1.0.0-beta.4 sync, round 5) - **BREAKING: Minimum supported protocol version raised from 2 to 3.** The diff --git a/doc/reference/API.md b/doc/reference/API.md index efdd179..bc6a35a 100644 --- a/doc/reference/API.md +++ b/doc/reference/API.md @@ -2258,11 +2258,30 @@ Lifecycle hooks allow custom logic at various points during the session: :on-post-tool-use (fn [input invocation] - ;; Called after each tool execution - ;; input contains {:tool-name "..." :result {...}} + ;; Called after each *successful* tool execution + ;; input contains {:tool-name "..." :tool-args {...} :tool-result {...}} + ;; For failed tool calls, register :on-post-tool-use-failure below. (println "Tool completed:" (:tool-name input)) nil) + :on-post-tool-use-failure + (fn [input invocation] + ;; Called after a tool execution whose result was `"failure"` + ;; (upstream PR #1421). :on-post-tool-use only fires for + ;; successful results, so register this handler to observe + ;; failed tool outcomes. Note: `"rejected"`, `"denied"`, and + ;; `"timeout"` results do NOT currently trigger this hook — + ;; only `"failure"` does. + ;; input contains {:tool-name "..." :tool-args {...} + ;; :error "failure message string" + ;; :session-id "..." :timestamp 12345} + ;; Optional return: {:additional-context "..."} is appended as + ;; hidden guidance to the model alongside the failed result. + ;; Other fields (e.g. :modified-result, :suppress-output) are + ;; not honored for failure hooks. + (println "Tool failed:" (:tool-name input) (:error input)) + {:additional-context "Tip: try `ls` first to see available files."}) + :on-pre-mcp-tool-call (fn [input invocation] ;; Called before each MCP tool call is dispatched (upstream PR #1366). diff --git a/src/github/copilot_sdk/client.clj b/src/github/copilot_sdk/client.clj index 29e6a1f..6b317b3 100644 --- a/src/github/copilot_sdk/client.clj +++ b/src/github/copilot_sdk/client.clj @@ -1655,7 +1655,8 @@ :elicitation-source, :url. Returns an ElicitationResult map. - :hooks - Lifecycle hooks map (PR #269): {:on-pre-tool-use, :on-pre-mcp-tool-call, - :on-post-tool-use, :on-user-prompt-submitted, + :on-post-tool-use, :on-post-tool-use-failure, + :on-user-prompt-submitted, :on-session-start, :on-session-end, :on-error-occurred} See `doc/reference/API.md` for hook input/output shapes. `:on-pre-mcp-tool-call` (upstream PR #1366) fires before @@ -1663,6 +1664,12 @@ `{:meta-to-use {...}}` replaces the request `_meta`, `{:meta-to-use nil}` removes it, and an empty / missing `:meta-to-use` preserves the existing `_meta`. + `:on-post-tool-use-failure` (upstream PR #1421) fires + after a tool execution whose `:result-type` was + `\"failure\"`; `:on-post-tool-use` only fires for + successful results. Handler input has `:tool-name`, + `:tool-args`, `:error` (string), plus base hook fields. + Optional output: `{:additional-context \"...\"}`. - :on-event - Event handler (1-arg fn) registered before the RPC call. Guarantees early events like session.start are not missed. - :enable-config-discovery - Boolean. Auto-discover .mcp.json, .vscode/mcp.json, skills, etc. diff --git a/src/github/copilot_sdk/session.clj b/src/github/copilot_sdk/session.clj index 14f8eed..207c0ee 100644 --- a/src/github/copilot_sdk/session.clj +++ b/src/github/copilot_sdk/session.clj @@ -695,6 +695,7 @@ "preToolUse" :on-pre-tool-use "preMcpToolCall" :on-pre-mcp-tool-call "postToolUse" :on-post-tool-use + "postToolUseFailure" :on-post-tool-use-failure "userPromptSubmitted" :on-user-prompt-submitted "sessionStart" :on-session-start "sessionEnd" :on-session-end diff --git a/src/github/copilot_sdk/specs.clj b/src/github/copilot_sdk/specs.clj index 4d2bfbc..d76d3fb 100644 --- a/src/github/copilot_sdk/specs.clj +++ b/src/github/copilot_sdk/specs.clj @@ -453,12 +453,14 @@ (s/def ::on-pre-tool-use fn?) (s/def ::on-pre-mcp-tool-call fn?) (s/def ::on-post-tool-use fn?) +(s/def ::on-post-tool-use-failure fn?) (s/def ::on-user-prompt-submitted fn?) (s/def ::on-session-start fn?) (s/def ::on-session-end fn?) (s/def ::on-error-occurred fn?) (s/def ::hooks (s/keys :opt-un [::on-pre-tool-use ::on-pre-mcp-tool-call ::on-post-tool-use + ::on-post-tool-use-failure ::on-user-prompt-submitted ::on-session-start ::on-session-end ::on-error-occurred])) diff --git a/test/github/copilot_sdk/integration_test.clj b/test/github/copilot_sdk/integration_test.clj index 860c20c..5dee98c 100644 --- a/test/github/copilot_sdk/integration_test.clj +++ b/test/github/copilot_sdk/integration_test.clj @@ -2999,6 +2999,50 @@ ;; Handler returned nil, so result is nil (is (nil? (:result response)))))) +(deftest test-hooks-post-tool-use-failure + (testing "hooks.invoke postToolUseFailure calls registered handler (upstream PR #1421)" + (let [handler-called (atom nil) + session (sdk/create-session *test-client* + {:on-permission-request sdk/approve-all + :hooks {:on-post-tool-use-failure + (fn [input ctx] + (reset! handler-called {:input input :ctx ctx}) + {:additional-context "noted"})}}) + session-id (sdk/session-id session) + response (mock/send-rpc-request! *mock-server* + "hooks.invoke" + {:sessionId session-id + :hookType "postToolUseFailure" + :input {:toolName "bash" + :toolArgs {:command "false"} + :error "command exited 1" + :timestamp 12345 + :cwd "/workspace"}})] + (is (some? @handler-called)) + (is (= "bash" (get-in @handler-called [:input :tool-name]))) + (is (= "command exited 1" (get-in @handler-called [:input :error]))) + (is (= session-id (get-in @handler-called [:input :session-id]))) + (is (= "noted" (get-in response [:result :additionalContext])))))) + +(deftest test-hooks-post-tool-use-failure-no-handler + (testing "hooks.invoke postToolUseFailure with no handler returns nil result" + (let [session (sdk/create-session *test-client* + {:on-permission-request sdk/approve-all + ;; Only success hook registered; failure should pass through as nil. + :hooks {:on-post-tool-use + (fn [_ _] nil)}}) + session-id (sdk/session-id session) + response (mock/send-rpc-request! *mock-server* + "hooks.invoke" + {:sessionId session-id + :hookType "postToolUseFailure" + :input {:toolName "bash" + :toolArgs {} + :error "boom" + :timestamp 12345 + :cwd "/workspace"}})] + (is (nil? (:result response)))))) + (deftest test-hooks-session-start (testing "hooks.invoke sessionStart calls registered handler" (let [handler-called (atom nil) From ded2f19661ce6c11cd2edea97bb92597bc96d08f Mon Sep 17 00:00:00 2001 From: Karl Krukow Date: Wed, 27 May 2026 09:45:02 +0200 Subject: [PATCH 6/6] fix(review): address multi-model review on schema bump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two findings from code-review pass on PR-candidate round-5 extension: - (gpt-5.5) Canvas events declare `x-opaque-json` fields (`data.input` on `session.canvas.opened`; nested `canvases[].inputSchema` and `canvases[].actions[].inputSchema` on `session.canvas.registry_changed`). Since the canvas runtime is intentionally deferred to a future sync round and we have not yet implemented opaque-field preservation for these payloads, do not surface canvas event types in the curated public `::event-type` set yet — they would expose mangled JSON-Schema keys to consumers. The wire layer (`generated.event-specs/event-types`) still has them; canvas event types and their opaque-field preservation will land together when the canvas runtime is ported. - (claude-opus-4.7) CHANGELOG schema-bump entry had the version/PR positional mapping wrong for the first two items (`1.0.53 → #1408` should be `1.0.53-2 → #1408`, `1.0.53 → #1410`). Reorder so each position is correct and add a forward-looking note about deferred canvas opaque-field preservation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- CHANGELOG.md | 21 ++++++++++++--------- src/github/copilot_sdk/specs.clj | 6 +----- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f44121c..be64f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,15 +43,18 @@ All notable changes to this project will be documented in this file. This change - `:tool-description` and `:ui-resource` on `:tool.execution_complete` data. - **Schema bump** — `.copilot-schema-version` advanced from `1.0.52-1` to `1.0.55-1`. Picked up the 1.0.52-4 pre-release (upstream PR #1393), the - 1.0.52 stable release (upstream PR #1405), and the 1.0.53 / 1.0.53-2 / - 1.0.54 / 1.0.55-0 / 1.0.55-1 schema bumps (upstream PRs #1408, #1410, - #1411, #1412, #1432). Schema regen surfaces new wire-only canvas event - types (`session.canvas.opened`, `session.canvas.registry_changed`) and - the field set behind them. These events now appear in the public - `event-types` set for forward compatibility, but the canvas runtime - (extension manifests, `requestCanvasRenderer`, `openCanvases`, etc. — - upstream PRs #1401, #1413) is **not yet exposed** on the public Clojure - API. Canvas events will flow through as generic session events. + 1.0.52 stable release (upstream PR #1405), the 1.0.53-2 pre-release + (upstream PR #1408), and the 1.0.53 / 1.0.54 / 1.0.55-0 / 1.0.55-1 + schema bumps (upstream PRs #1410, #1411, #1412, #1432). Schema regen + surfaces new wire-only canvas event types (`session.canvas.opened`, + `session.canvas.registry_changed`) and their field set in the + generated `event-specs` namespace. The canvas runtime (extension + manifests, `requestCanvasRenderer`, `openCanvases`, etc. — upstream + PRs #1401, #1413) is **not yet exposed** on the public Clojure API, + including the curated `event-types` set. Canvas runtime support + (including opaque-field preservation for `data.input` and nested + `inputSchema` payloads on canvas events) will land in a dedicated + future sync round. ### Changed (post-v1.0.0-beta.4 sync, round 5) - **BREAKING: Minimum supported protocol version raised from 2 to 3.** The diff --git a/src/github/copilot_sdk/specs.clj b/src/github/copilot_sdk/specs.clj index d76d3fb..1c63450 100644 --- a/src/github/copilot_sdk/specs.clj +++ b/src/github/copilot_sdk/specs.clj @@ -904,11 +904,7 @@ ;; Schedule events (upstream schema 1.0.42) :copilot/session.schedule_created :copilot/session.schedule_cancelled ;; MCP Apps tool-call complete (upstream schema 1.0.52-4, SEP-1865) - :copilot/mcp_app.tool_call_complete - ;; Canvas events (upstream PR #1401, schema 1.0.53+). Canvas runtime - ;; support itself is not yet exposed on the public Clojure API; these - ;; events flow through as generic session events for forward compat. - :copilot/session.canvas.opened :copilot/session.canvas.registry_changed}) + :copilot/mcp_app.tool_call_complete}) ;; Session events (s/def ::already-in-use? boolean?)