Tags: github/copilot-sdk
Tags
Refactor Rust SDK errors to use structs with a `kind()` method (#1400) * Refactor Rust SDK errors to use structs with a `kind()` method The conventional `#[non_exhaustive] enum Error { ... }` pattern appears safe but creates problems as a library evolves. This PR changes all error types to the struct-with-`kind()` pattern, which also aligns with the Azure SDK for Rust error design. Why not a flat error enum: - `#[non_exhaustive]` on the enum prevents exhaustive matching, but individual variants are still fixed. Adding a field to any variant — even just to improve an error message with a line number or file path — is a breaking change. - Adding context data is harder than it looks. With a flat enum, new fields touch every affected variant and all match arms across the codebase. With a struct, new fields are added in one place and callers who don't use them are unaffected. - A single enum conflates all failure modes, making it impossible to document or guarantee which variants a given function can actually return. Callers must handle unrelated variants they will never see, or accept a wildcard arm that silently swallows future additions. The struct + kind pattern: | Concern | Flat enum | Struct + `kind()` | |---|---|---| | Categorization | Match directly on variant | Call `.kind()` → `&*Kind` | | Adding context | Breaking: add fields to variant | Non-breaking: add fields to struct | | `non_exhaustive` | On enum; variants are fixed | Not needed on struct with only private fields | | Simple display | Must match all variants | `format!("{err}")` — no match needed | Callers who only want to display or propagate an error with `?` do not need to call `.kind()` at all. Only callers who need to inspect the failure category call `.kind()`, and they get a stable, scoped `*Kind` enum to match against. * Remove unnecessary error structs Sticking with `*Kind` as a convention for error enums. * Add backtrace support to Error struct Enhanced the Error struct to include an optional backtrace, which is captured only when `RUST_BACKTRACE` is set. This change helps in debugging by providing context on error occurrences without inflating the Error size unnecessarily. * Resolve PR feedback
Refactor Rust SDK errors to use structs with a `kind()` method (#1400) * Refactor Rust SDK errors to use structs with a `kind()` method The conventional `#[non_exhaustive] enum Error { ... }` pattern appears safe but creates problems as a library evolves. This PR changes all error types to the struct-with-`kind()` pattern, which also aligns with the Azure SDK for Rust error design. Why not a flat error enum: - `#[non_exhaustive]` on the enum prevents exhaustive matching, but individual variants are still fixed. Adding a field to any variant — even just to improve an error message with a line number or file path — is a breaking change. - Adding context data is harder than it looks. With a flat enum, new fields touch every affected variant and all match arms across the codebase. With a struct, new fields are added in one place and callers who don't use them are unaffected. - A single enum conflates all failure modes, making it impossible to document or guarantee which variants a given function can actually return. Callers must handle unrelated variants they will never see, or accept a wildcard arm that silently swallows future additions. The struct + kind pattern: | Concern | Flat enum | Struct + `kind()` | |---|---|---| | Categorization | Match directly on variant | Call `.kind()` → `&*Kind` | | Adding context | Breaking: add fields to variant | Non-breaking: add fields to struct | | `non_exhaustive` | On enum; variants are fixed | Not needed on struct with only private fields | | Simple display | Must match all variants | `format!("{err}")` — no match needed | Callers who only want to display or propagate an error with `?` do not need to call `.kind()` at all. Only callers who need to inspect the failure category call `.kind()`, and they get a stable, scoped `*Kind` enum to match against. * Remove unnecessary error structs Sticking with `*Kind` as a convention for error enums. * Add backtrace support to Error struct Enhanced the Error struct to include an optional backtrace, which is captured only when `RUST_BACKTRACE` is set. This change helps in debugging by providing context on error occurrences without inflating the Error size unnecessarily. * Resolve PR feedback
Refactor Rust SDK errors to use structs with a `kind()` method (#1400) * Refactor Rust SDK errors to use structs with a `kind()` method The conventional `#[non_exhaustive] enum Error { ... }` pattern appears safe but creates problems as a library evolves. This PR changes all error types to the struct-with-`kind()` pattern, which also aligns with the Azure SDK for Rust error design. Why not a flat error enum: - `#[non_exhaustive]` on the enum prevents exhaustive matching, but individual variants are still fixed. Adding a field to any variant — even just to improve an error message with a line number or file path — is a breaking change. - Adding context data is harder than it looks. With a flat enum, new fields touch every affected variant and all match arms across the codebase. With a struct, new fields are added in one place and callers who don't use them are unaffected. - A single enum conflates all failure modes, making it impossible to document or guarantee which variants a given function can actually return. Callers must handle unrelated variants they will never see, or accept a wildcard arm that silently swallows future additions. The struct + kind pattern: | Concern | Flat enum | Struct + `kind()` | |---|---|---| | Categorization | Match directly on variant | Call `.kind()` → `&*Kind` | | Adding context | Breaking: add fields to variant | Non-breaking: add fields to struct | | `non_exhaustive` | On enum; variants are fixed | Not needed on struct with only private fields | | Simple display | Must match all variants | `format!("{err}")` — no match needed | Callers who only want to display or propagate an error with `?` do not need to call `.kind()` at all. Only callers who need to inspect the failure category call `.kind()`, and they get a stable, scoped `*Kind` enum to match against. * Remove unnecessary error structs Sticking with `*Kind` as a convention for error enums. * Add backtrace support to Error struct Enhanced the Error struct to include an optional backtrace, which is captured only when `RUST_BACKTRACE` is set. This change helps in debugging by providing context on error occurrences without inflating the Error size unnecessarily. * Resolve PR feedback
Plan and grader for phase 04
SDK: Align canvas with codegen pipeline, add e2e tests (#1413)
Add SDK canvas runtime support (#1401) * Add canvas runtime support to SDK Add Node extension canvas APIs and direct canvas provider callback routing. Add Rust canvas declarations, provider handlers, create/resume wiring, and host session.canvas APIs aligned with the runtime schema. Validation: nodejs typecheck/lint/tests; rust fmt/check/clippy; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Add canvas provider RPC tracing Co-authored-by: Copilot <[email protected]> * Add extension info session option Expose stable extension identity metadata on Node and Rust session create/resume options and forward extensionInfo on the wire for canvas providers. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Expose canvas resume durability fields Add CanvasInstanceAvailability, OpenCanvasInstance availability, and resume openCanvases seeding support to the Rust SDK. Validation: cargo +nightly-2026-04-14 fmt --check; cargo clippy --all-features --all-targets -- -D warnings; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Address canvas SDK review feedback Validate canvas provider request payloads before routing, surface Rust canvas serialization and builder errors, and clarify list_open RPC behavior. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Format Rust session imports Co-authored-by: Copilot <[email protected]> * Sync canvas tool surface docs Remove stale focus/close/reload canvas agent-tool references and cover custom-tool permission payload passthrough for open_canvas. Validation: nodejs typecheck; cargo test --all-features permission_request_data_extracts_typed_kind. Co-authored-by: Copilot <[email protected]> * Require canvas descriptions Align canvas contribution and discovered canvas descriptions with the runtime schema, update canvas tool-surface docs, and cover open_canvas custom-tool permission payloads. Validation: nodejs typecheck/lint/vitest client+extension; rust fmt/clippy; cargo check --all-features --all-targets; targeted canvas and permission tests. Co-authored-by: Copilot <[email protected]> * Require canvas instance availability Align OpenCanvasInstance with the runtime schema by making availability required and updating canvas host/resume tests. Validation: cargo check --all-features --all-targets; cargo test --all-features canvas; targeted session canvas tests. Co-authored-by: Copilot <[email protected]> * Rename Node canvas open handler Rename the Node canvas provider option from onOpen to open and remove lifecycle handler options from the extension canvas API. Validation: nodejs typecheck; vitest client and extension tests. Co-authored-by: Copilot <[email protected]> * Drop canvas toolbar and focus/reload surface Aligns the SDK canvas contract with copilot-agent-runtime jmoseley/adr-implementation-plan commits 85b23bc264 and acdefc1bc1: - Rename agentActions to actions on CanvasDeclaration and DiscoveredCanvas (Rust + Node). - Drop toolbar from CanvasContribution and CanvasOpenResponse, and remove CanvasToolbarItemDeclaration / CanvasToolbarItem entirely. - Drop SessionCanvas::focus and SessionCanvas::reload host APIs; re-opening with the same instanceId now drives focus via session.canvas.opened { reopen: true }, and reload is renderer-only. - Drop canvas.focus / canvas.reload provider JSON-RPC routes and the matching CanvasHandler::on_focus / on_reload hooks; canvas.close keeps its dedicated dispatch path. Co-authored-by: Copilot <[email protected]> * Restore optional onClose handler on Node canvas options Lets extension authors observe canvas instance close events without adding back the dropped onFocus/onReload hooks. Fire-and-forget: the handler's return value is ignored and the provider response is still undefined. Co-authored-by: Copilot <[email protected]> * Support per-action handlers on Node canvas actions Each entry in createCanvas({ actions }) may now carry its own optional handler, co-located with the action's metadata. The top-level onAction remains as a fallback for actions that don't define their own handler. Dispatch order: 1. Per-action handler when set. 2. Top-level onAction otherwise. 3. canvas_action_no_handler if neither is wired. The handler closure is stripped from the wire CanvasDeclaration sent on session.create / session.resume; only the action's name, description, and inputSchema reach the runtime. A new CanvasAction authoring type sits on top of the existing CanvasAgentActionDeclaration wire type. Co-authored-by: Copilot <[email protected]> * Drop top-level onAction fallback on Node canvases Per-action handlers are now the only dispatch path. Declared actions without a handler fall through to canvas_action_no_handler. Keeps the action's metadata and behavior co-located and removes a second indirection that always boiled down to a switch on actionName. Co-authored-by: Copilot <[email protected]> * Normalize JSDoc style on CanvasAgentActionDeclaration Co-authored-by: Copilot <[email protected]> * Drop stale wire-rename guards from canvas declaration test Co-authored-by: Copilot <[email protected]> * Document canvas action dispatch divergence in Rust SDK Co-authored-by: Copilot <[email protected]> * Require handler on canvas actions Co-authored-by: Copilot <[email protected]> * Collapse CanvasAgentActionDeclaration into CanvasAction Co-authored-by: Copilot <[email protected]> * Drop debug log for inbound JSON-RPC requests Co-authored-by: Copilot <[email protected]> * Drop canvas debug logs Co-authored-by: Copilot <[email protected]> * Remove canvas tools field Drop CanvasToolDefinition, CanvasToolDefinitionDefer, and the CanvasOpenResponse.tools / OpenCanvasInstance.tools fields from both the Node and Rust SDKs. The CLI side is being removed in lockstep, so the wire contract no longer carries this field. Co-authored-by: Copilot <[email protected]> * rust: slim canvas surface to wire types + CanvasHandler Move per-canvas registry, Canvas builder, dispatch helpers, and the SessionCanvas host helper out of the SDK. The Rust canvas surface now matches the other typed extension points (PermissionHandler / UserInputHandler / HookHandler): SessionConfig .with_canvases([CanvasDeclaration, ...]) .with_canvas_handler(Arc::new(MyHandler)) Removed: - canvas::Canvas, CanvasBuilder (declaration+handler bundle) - canvas::CanvasRegistry, build_registry, dispatch_canvas_* - session::SessionCanvas + Session::canvas() accessor (callers move to session.rpc().canvas().*) Kept (the wire boundary + typed extension point): - All wire types (CanvasDeclaration, OpenCanvasInstance, ...) - CanvasHandler trait + on_open/on_action/on_close - SessionConfig/ResumeSessionConfig.canvases (now Vec<CanvasDeclaration>) - SessionConfig/ResumeSessionConfig.canvas_handler handle_request dispatches canvas.open/close/action.invoke directly to the handler; the per-canvas registry now lives in the app layer. Co-authored-by: Copilot <[email protected]> * rust: drop canvas wire types duplicated by codegen Removed CanvasInstanceAvailability, OpenCanvasInstance, CanvasAgentActionDeclaration (-> CanvasAction), CanvasDiscoverResult, DiscoveredCanvas, CanvasListOpenResult, CanvasOpenRequest, CanvasCloseRequest, CanvasInvokeActionRequest, and CanvasInvokeActionResult from canvas.rs; consumers import these from crate::generated::api_types directly. The remaining hand-written types (CanvasDeclaration, CanvasOpenResponse, handler trait, contexts, CanvasError) are genuinely additive provider-authoring contracts. Co-authored-by: Copilot <[email protected]> * Fix broken intra-doc link to renamed CanvasAction type The canvas wire types were deduplicated against generated/api_types.rs, renaming CanvasAgentActionDeclaration to CanvasAction. A doc comment in canvas.rs still referenced the old name, which broke cargo doc on CI (broken_intra_doc_links is denied). Co-authored-by: Copilot <[email protected]> * go: add canvas runtime support Mirrors the Rust SDK canvas surface in rust/src/canvas.rs: - CanvasDeclaration, CanvasOpenResponse, CanvasHostContext, CanvasOpenContext / CanvasActionContext / CanvasLifecycleContext, CanvasError, CanvasHandler interface + CanvasHandlerDefaults, and ExtensionInfo. - SessionConfig / ResumeSessionConfig: Canvases, RequestCanvasRenderer, RequestExtensions, CanvasHandler, ExtensionInfo. - Inbound JSON-RPC dispatch for canvas.open, canvas.close, and canvas.action.invoke, with a canvas_handler_unset error envelope when no handler is installed and a canvas_handler_error envelope when a handler returns a non-CanvasError error. - Session.OpenCanvases() surfaces the openCanvases snapshot from the session.resume response. Co-authored-by: Copilot <[email protected]> * python: add canvas runtime support Mirrors the Rust SDK design: callers declare canvases on session.create / session.resume, install a single CanvasHandler, and the SDK dispatches inbound canvas.open / canvas.close / canvas.action.invoke JSON-RPC requests to that handler. Resume populates session.open_canvases from the response. JSON-RPC dispatch was loosened to allow handlers to return any JSON value (canvas.action.invoke result is arbitrary JSON). Co-authored-by: Copilot <[email protected]> * dotnet: add canvas runtime support Ports the canvas runtime surface from the Rust SDK to the .NET SDK so .NET hosts can declare canvases on session create/resume, advertise an extension identity, and handle inbound canvas.open / canvas.close / canvas.action.invoke RPC calls. * New public Canvas.cs surface (CanvasDeclaration, ExtensionInfo, CanvasOpenResponse, CanvasHostContext, lifecycle/action/open contexts, CanvasError, ICanvasHandler, CanvasHandlerBase). All marked [Experimental(GHCP001)]. * SessionConfigBase gains Canvases, RequestCanvasRenderer, RequestExtensions, ExtensionInfo, CanvasHandler. * CreateSession/ResumeSession requests forward the new fields and surface OpenCanvases on the response. CopilotSession exposes the returned canvases via OpenCanvases. * CopilotClient registers canvas.open / canvas.close / canvas.action.invoke handlers and dispatches them to the session, which invokes the user's ICanvasHandler and returns structured CanvasError data via a new JsonRpc LocalRpcInvocationException path. Co-authored-by: Copilot <[email protected]> * Address PR review: openCanvases parity + Node API divergence note - Node: add openCanvases accessor on CopilotSession and OpenCanvases field on ResumeSessionConfig so callers can both rehydrate from the resume response and pre-populate canvas state on resume. - Node: document why createCanvas/Canvas intentionally diverges from the per-session CanvasHandler pattern used by Rust/Python/Go/.NET. - Go: add ResumeSessionConfig.OpenCanvases, thread through to the resume request wire payload, and add a serialization test. - .NET: add ResumeSessionConfig.OpenCanvases, thread through to the internal ResumeSessionRequest record, and add a serialization test. Mirrors what Rust and Python already do, fixing wire-protocol parity across SDKs. Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
Add SDK canvas runtime support (#1401) * Add canvas runtime support to SDK Add Node extension canvas APIs and direct canvas provider callback routing. Add Rust canvas declarations, provider handlers, create/resume wiring, and host session.canvas APIs aligned with the runtime schema. Validation: nodejs typecheck/lint/tests; rust fmt/check/clippy; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Add canvas provider RPC tracing Co-authored-by: Copilot <[email protected]> * Add extension info session option Expose stable extension identity metadata on Node and Rust session create/resume options and forward extensionInfo on the wire for canvas providers. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Expose canvas resume durability fields Add CanvasInstanceAvailability, OpenCanvasInstance availability, and resume openCanvases seeding support to the Rust SDK. Validation: cargo +nightly-2026-04-14 fmt --check; cargo clippy --all-features --all-targets -- -D warnings; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Address canvas SDK review feedback Validate canvas provider request payloads before routing, surface Rust canvas serialization and builder errors, and clarify list_open RPC behavior. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Format Rust session imports Co-authored-by: Copilot <[email protected]> * Sync canvas tool surface docs Remove stale focus/close/reload canvas agent-tool references and cover custom-tool permission payload passthrough for open_canvas. Validation: nodejs typecheck; cargo test --all-features permission_request_data_extracts_typed_kind. Co-authored-by: Copilot <[email protected]> * Require canvas descriptions Align canvas contribution and discovered canvas descriptions with the runtime schema, update canvas tool-surface docs, and cover open_canvas custom-tool permission payloads. Validation: nodejs typecheck/lint/vitest client+extension; rust fmt/clippy; cargo check --all-features --all-targets; targeted canvas and permission tests. Co-authored-by: Copilot <[email protected]> * Require canvas instance availability Align OpenCanvasInstance with the runtime schema by making availability required and updating canvas host/resume tests. Validation: cargo check --all-features --all-targets; cargo test --all-features canvas; targeted session canvas tests. Co-authored-by: Copilot <[email protected]> * Rename Node canvas open handler Rename the Node canvas provider option from onOpen to open and remove lifecycle handler options from the extension canvas API. Validation: nodejs typecheck; vitest client and extension tests. Co-authored-by: Copilot <[email protected]> * Drop canvas toolbar and focus/reload surface Aligns the SDK canvas contract with copilot-agent-runtime jmoseley/adr-implementation-plan commits 85b23bc264 and acdefc1bc1: - Rename agentActions to actions on CanvasDeclaration and DiscoveredCanvas (Rust + Node). - Drop toolbar from CanvasContribution and CanvasOpenResponse, and remove CanvasToolbarItemDeclaration / CanvasToolbarItem entirely. - Drop SessionCanvas::focus and SessionCanvas::reload host APIs; re-opening with the same instanceId now drives focus via session.canvas.opened { reopen: true }, and reload is renderer-only. - Drop canvas.focus / canvas.reload provider JSON-RPC routes and the matching CanvasHandler::on_focus / on_reload hooks; canvas.close keeps its dedicated dispatch path. Co-authored-by: Copilot <[email protected]> * Restore optional onClose handler on Node canvas options Lets extension authors observe canvas instance close events without adding back the dropped onFocus/onReload hooks. Fire-and-forget: the handler's return value is ignored and the provider response is still undefined. Co-authored-by: Copilot <[email protected]> * Support per-action handlers on Node canvas actions Each entry in createCanvas({ actions }) may now carry its own optional handler, co-located with the action's metadata. The top-level onAction remains as a fallback for actions that don't define their own handler. Dispatch order: 1. Per-action handler when set. 2. Top-level onAction otherwise. 3. canvas_action_no_handler if neither is wired. The handler closure is stripped from the wire CanvasDeclaration sent on session.create / session.resume; only the action's name, description, and inputSchema reach the runtime. A new CanvasAction authoring type sits on top of the existing CanvasAgentActionDeclaration wire type. Co-authored-by: Copilot <[email protected]> * Drop top-level onAction fallback on Node canvases Per-action handlers are now the only dispatch path. Declared actions without a handler fall through to canvas_action_no_handler. Keeps the action's metadata and behavior co-located and removes a second indirection that always boiled down to a switch on actionName. Co-authored-by: Copilot <[email protected]> * Normalize JSDoc style on CanvasAgentActionDeclaration Co-authored-by: Copilot <[email protected]> * Drop stale wire-rename guards from canvas declaration test Co-authored-by: Copilot <[email protected]> * Document canvas action dispatch divergence in Rust SDK Co-authored-by: Copilot <[email protected]> * Require handler on canvas actions Co-authored-by: Copilot <[email protected]> * Collapse CanvasAgentActionDeclaration into CanvasAction Co-authored-by: Copilot <[email protected]> * Drop debug log for inbound JSON-RPC requests Co-authored-by: Copilot <[email protected]> * Drop canvas debug logs Co-authored-by: Copilot <[email protected]> * Remove canvas tools field Drop CanvasToolDefinition, CanvasToolDefinitionDefer, and the CanvasOpenResponse.tools / OpenCanvasInstance.tools fields from both the Node and Rust SDKs. The CLI side is being removed in lockstep, so the wire contract no longer carries this field. Co-authored-by: Copilot <[email protected]> * rust: slim canvas surface to wire types + CanvasHandler Move per-canvas registry, Canvas builder, dispatch helpers, and the SessionCanvas host helper out of the SDK. The Rust canvas surface now matches the other typed extension points (PermissionHandler / UserInputHandler / HookHandler): SessionConfig .with_canvases([CanvasDeclaration, ...]) .with_canvas_handler(Arc::new(MyHandler)) Removed: - canvas::Canvas, CanvasBuilder (declaration+handler bundle) - canvas::CanvasRegistry, build_registry, dispatch_canvas_* - session::SessionCanvas + Session::canvas() accessor (callers move to session.rpc().canvas().*) Kept (the wire boundary + typed extension point): - All wire types (CanvasDeclaration, OpenCanvasInstance, ...) - CanvasHandler trait + on_open/on_action/on_close - SessionConfig/ResumeSessionConfig.canvases (now Vec<CanvasDeclaration>) - SessionConfig/ResumeSessionConfig.canvas_handler handle_request dispatches canvas.open/close/action.invoke directly to the handler; the per-canvas registry now lives in the app layer. Co-authored-by: Copilot <[email protected]> * rust: drop canvas wire types duplicated by codegen Removed CanvasInstanceAvailability, OpenCanvasInstance, CanvasAgentActionDeclaration (-> CanvasAction), CanvasDiscoverResult, DiscoveredCanvas, CanvasListOpenResult, CanvasOpenRequest, CanvasCloseRequest, CanvasInvokeActionRequest, and CanvasInvokeActionResult from canvas.rs; consumers import these from crate::generated::api_types directly. The remaining hand-written types (CanvasDeclaration, CanvasOpenResponse, handler trait, contexts, CanvasError) are genuinely additive provider-authoring contracts. Co-authored-by: Copilot <[email protected]> * Fix broken intra-doc link to renamed CanvasAction type The canvas wire types were deduplicated against generated/api_types.rs, renaming CanvasAgentActionDeclaration to CanvasAction. A doc comment in canvas.rs still referenced the old name, which broke cargo doc on CI (broken_intra_doc_links is denied). Co-authored-by: Copilot <[email protected]> * go: add canvas runtime support Mirrors the Rust SDK canvas surface in rust/src/canvas.rs: - CanvasDeclaration, CanvasOpenResponse, CanvasHostContext, CanvasOpenContext / CanvasActionContext / CanvasLifecycleContext, CanvasError, CanvasHandler interface + CanvasHandlerDefaults, and ExtensionInfo. - SessionConfig / ResumeSessionConfig: Canvases, RequestCanvasRenderer, RequestExtensions, CanvasHandler, ExtensionInfo. - Inbound JSON-RPC dispatch for canvas.open, canvas.close, and canvas.action.invoke, with a canvas_handler_unset error envelope when no handler is installed and a canvas_handler_error envelope when a handler returns a non-CanvasError error. - Session.OpenCanvases() surfaces the openCanvases snapshot from the session.resume response. Co-authored-by: Copilot <[email protected]> * python: add canvas runtime support Mirrors the Rust SDK design: callers declare canvases on session.create / session.resume, install a single CanvasHandler, and the SDK dispatches inbound canvas.open / canvas.close / canvas.action.invoke JSON-RPC requests to that handler. Resume populates session.open_canvases from the response. JSON-RPC dispatch was loosened to allow handlers to return any JSON value (canvas.action.invoke result is arbitrary JSON). Co-authored-by: Copilot <[email protected]> * dotnet: add canvas runtime support Ports the canvas runtime surface from the Rust SDK to the .NET SDK so .NET hosts can declare canvases on session create/resume, advertise an extension identity, and handle inbound canvas.open / canvas.close / canvas.action.invoke RPC calls. * New public Canvas.cs surface (CanvasDeclaration, ExtensionInfo, CanvasOpenResponse, CanvasHostContext, lifecycle/action/open contexts, CanvasError, ICanvasHandler, CanvasHandlerBase). All marked [Experimental(GHCP001)]. * SessionConfigBase gains Canvases, RequestCanvasRenderer, RequestExtensions, ExtensionInfo, CanvasHandler. * CreateSession/ResumeSession requests forward the new fields and surface OpenCanvases on the response. CopilotSession exposes the returned canvases via OpenCanvases. * CopilotClient registers canvas.open / canvas.close / canvas.action.invoke handlers and dispatches them to the session, which invokes the user's ICanvasHandler and returns structured CanvasError data via a new JsonRpc LocalRpcInvocationException path. Co-authored-by: Copilot <[email protected]> * Address PR review: openCanvases parity + Node API divergence note - Node: add openCanvases accessor on CopilotSession and OpenCanvases field on ResumeSessionConfig so callers can both rehydrate from the resume response and pre-populate canvas state on resume. - Node: document why createCanvas/Canvas intentionally diverges from the per-session CanvasHandler pattern used by Rust/Python/Go/.NET. - Go: add ResumeSessionConfig.OpenCanvases, thread through to the resume request wire payload, and add a serialization test. - .NET: add ResumeSessionConfig.OpenCanvases, thread through to the internal ResumeSessionRequest record, and add a serialization test. Mirrors what Rust and Python already do, fixing wire-protocol parity across SDKs. Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
Add SDK canvas runtime support (#1401) * Add canvas runtime support to SDK Add Node extension canvas APIs and direct canvas provider callback routing. Add Rust canvas declarations, provider handlers, create/resume wiring, and host session.canvas APIs aligned with the runtime schema. Validation: nodejs typecheck/lint/tests; rust fmt/check/clippy; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Add canvas provider RPC tracing Co-authored-by: Copilot <[email protected]> * Add extension info session option Expose stable extension identity metadata on Node and Rust session create/resume options and forward extensionInfo on the wire for canvas providers. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Expose canvas resume durability fields Add CanvasInstanceAvailability, OpenCanvasInstance availability, and resume openCanvases seeding support to the Rust SDK. Validation: cargo +nightly-2026-04-14 fmt --check; cargo clippy --all-features --all-targets -- -D warnings; cargo test --all-features. Co-authored-by: Copilot <[email protected]> * Address canvas SDK review feedback Validate canvas provider request payloads before routing, surface Rust canvas serialization and builder errors, and clarify list_open RPC behavior. Validation: nodejs typecheck/lint/vitest; rust fmt/clippy/test --all-features. Co-authored-by: Copilot <[email protected]> * Format Rust session imports Co-authored-by: Copilot <[email protected]> * Sync canvas tool surface docs Remove stale focus/close/reload canvas agent-tool references and cover custom-tool permission payload passthrough for open_canvas. Validation: nodejs typecheck; cargo test --all-features permission_request_data_extracts_typed_kind. Co-authored-by: Copilot <[email protected]> * Require canvas descriptions Align canvas contribution and discovered canvas descriptions with the runtime schema, update canvas tool-surface docs, and cover open_canvas custom-tool permission payloads. Validation: nodejs typecheck/lint/vitest client+extension; rust fmt/clippy; cargo check --all-features --all-targets; targeted canvas and permission tests. Co-authored-by: Copilot <[email protected]> * Require canvas instance availability Align OpenCanvasInstance with the runtime schema by making availability required and updating canvas host/resume tests. Validation: cargo check --all-features --all-targets; cargo test --all-features canvas; targeted session canvas tests. Co-authored-by: Copilot <[email protected]> * Rename Node canvas open handler Rename the Node canvas provider option from onOpen to open and remove lifecycle handler options from the extension canvas API. Validation: nodejs typecheck; vitest client and extension tests. Co-authored-by: Copilot <[email protected]> * Drop canvas toolbar and focus/reload surface Aligns the SDK canvas contract with copilot-agent-runtime jmoseley/adr-implementation-plan commits 85b23bc264 and acdefc1bc1: - Rename agentActions to actions on CanvasDeclaration and DiscoveredCanvas (Rust + Node). - Drop toolbar from CanvasContribution and CanvasOpenResponse, and remove CanvasToolbarItemDeclaration / CanvasToolbarItem entirely. - Drop SessionCanvas::focus and SessionCanvas::reload host APIs; re-opening with the same instanceId now drives focus via session.canvas.opened { reopen: true }, and reload is renderer-only. - Drop canvas.focus / canvas.reload provider JSON-RPC routes and the matching CanvasHandler::on_focus / on_reload hooks; canvas.close keeps its dedicated dispatch path. Co-authored-by: Copilot <[email protected]> * Restore optional onClose handler on Node canvas options Lets extension authors observe canvas instance close events without adding back the dropped onFocus/onReload hooks. Fire-and-forget: the handler's return value is ignored and the provider response is still undefined. Co-authored-by: Copilot <[email protected]> * Support per-action handlers on Node canvas actions Each entry in createCanvas({ actions }) may now carry its own optional handler, co-located with the action's metadata. The top-level onAction remains as a fallback for actions that don't define their own handler. Dispatch order: 1. Per-action handler when set. 2. Top-level onAction otherwise. 3. canvas_action_no_handler if neither is wired. The handler closure is stripped from the wire CanvasDeclaration sent on session.create / session.resume; only the action's name, description, and inputSchema reach the runtime. A new CanvasAction authoring type sits on top of the existing CanvasAgentActionDeclaration wire type. Co-authored-by: Copilot <[email protected]> * Drop top-level onAction fallback on Node canvases Per-action handlers are now the only dispatch path. Declared actions without a handler fall through to canvas_action_no_handler. Keeps the action's metadata and behavior co-located and removes a second indirection that always boiled down to a switch on actionName. Co-authored-by: Copilot <[email protected]> * Normalize JSDoc style on CanvasAgentActionDeclaration Co-authored-by: Copilot <[email protected]> * Drop stale wire-rename guards from canvas declaration test Co-authored-by: Copilot <[email protected]> * Document canvas action dispatch divergence in Rust SDK Co-authored-by: Copilot <[email protected]> * Require handler on canvas actions Co-authored-by: Copilot <[email protected]> * Collapse CanvasAgentActionDeclaration into CanvasAction Co-authored-by: Copilot <[email protected]> * Drop debug log for inbound JSON-RPC requests Co-authored-by: Copilot <[email protected]> * Drop canvas debug logs Co-authored-by: Copilot <[email protected]> * Remove canvas tools field Drop CanvasToolDefinition, CanvasToolDefinitionDefer, and the CanvasOpenResponse.tools / OpenCanvasInstance.tools fields from both the Node and Rust SDKs. The CLI side is being removed in lockstep, so the wire contract no longer carries this field. Co-authored-by: Copilot <[email protected]> * rust: slim canvas surface to wire types + CanvasHandler Move per-canvas registry, Canvas builder, dispatch helpers, and the SessionCanvas host helper out of the SDK. The Rust canvas surface now matches the other typed extension points (PermissionHandler / UserInputHandler / HookHandler): SessionConfig .with_canvases([CanvasDeclaration, ...]) .with_canvas_handler(Arc::new(MyHandler)) Removed: - canvas::Canvas, CanvasBuilder (declaration+handler bundle) - canvas::CanvasRegistry, build_registry, dispatch_canvas_* - session::SessionCanvas + Session::canvas() accessor (callers move to session.rpc().canvas().*) Kept (the wire boundary + typed extension point): - All wire types (CanvasDeclaration, OpenCanvasInstance, ...) - CanvasHandler trait + on_open/on_action/on_close - SessionConfig/ResumeSessionConfig.canvases (now Vec<CanvasDeclaration>) - SessionConfig/ResumeSessionConfig.canvas_handler handle_request dispatches canvas.open/close/action.invoke directly to the handler; the per-canvas registry now lives in the app layer. Co-authored-by: Copilot <[email protected]> * rust: drop canvas wire types duplicated by codegen Removed CanvasInstanceAvailability, OpenCanvasInstance, CanvasAgentActionDeclaration (-> CanvasAction), CanvasDiscoverResult, DiscoveredCanvas, CanvasListOpenResult, CanvasOpenRequest, CanvasCloseRequest, CanvasInvokeActionRequest, and CanvasInvokeActionResult from canvas.rs; consumers import these from crate::generated::api_types directly. The remaining hand-written types (CanvasDeclaration, CanvasOpenResponse, handler trait, contexts, CanvasError) are genuinely additive provider-authoring contracts. Co-authored-by: Copilot <[email protected]> * Fix broken intra-doc link to renamed CanvasAction type The canvas wire types were deduplicated against generated/api_types.rs, renaming CanvasAgentActionDeclaration to CanvasAction. A doc comment in canvas.rs still referenced the old name, which broke cargo doc on CI (broken_intra_doc_links is denied). Co-authored-by: Copilot <[email protected]> * go: add canvas runtime support Mirrors the Rust SDK canvas surface in rust/src/canvas.rs: - CanvasDeclaration, CanvasOpenResponse, CanvasHostContext, CanvasOpenContext / CanvasActionContext / CanvasLifecycleContext, CanvasError, CanvasHandler interface + CanvasHandlerDefaults, and ExtensionInfo. - SessionConfig / ResumeSessionConfig: Canvases, RequestCanvasRenderer, RequestExtensions, CanvasHandler, ExtensionInfo. - Inbound JSON-RPC dispatch for canvas.open, canvas.close, and canvas.action.invoke, with a canvas_handler_unset error envelope when no handler is installed and a canvas_handler_error envelope when a handler returns a non-CanvasError error. - Session.OpenCanvases() surfaces the openCanvases snapshot from the session.resume response. Co-authored-by: Copilot <[email protected]> * python: add canvas runtime support Mirrors the Rust SDK design: callers declare canvases on session.create / session.resume, install a single CanvasHandler, and the SDK dispatches inbound canvas.open / canvas.close / canvas.action.invoke JSON-RPC requests to that handler. Resume populates session.open_canvases from the response. JSON-RPC dispatch was loosened to allow handlers to return any JSON value (canvas.action.invoke result is arbitrary JSON). Co-authored-by: Copilot <[email protected]> * dotnet: add canvas runtime support Ports the canvas runtime surface from the Rust SDK to the .NET SDK so .NET hosts can declare canvases on session create/resume, advertise an extension identity, and handle inbound canvas.open / canvas.close / canvas.action.invoke RPC calls. * New public Canvas.cs surface (CanvasDeclaration, ExtensionInfo, CanvasOpenResponse, CanvasHostContext, lifecycle/action/open contexts, CanvasError, ICanvasHandler, CanvasHandlerBase). All marked [Experimental(GHCP001)]. * SessionConfigBase gains Canvases, RequestCanvasRenderer, RequestExtensions, ExtensionInfo, CanvasHandler. * CreateSession/ResumeSession requests forward the new fields and surface OpenCanvases on the response. CopilotSession exposes the returned canvases via OpenCanvases. * CopilotClient registers canvas.open / canvas.close / canvas.action.invoke handlers and dispatches them to the session, which invokes the user's ICanvasHandler and returns structured CanvasError data via a new JsonRpc LocalRpcInvocationException path. Co-authored-by: Copilot <[email protected]> * Address PR review: openCanvases parity + Node API divergence note - Node: add openCanvases accessor on CopilotSession and OpenCanvases field on ResumeSessionConfig so callers can both rehydrate from the resume response and pre-populate canvas state on resume. - Node: document why createCanvas/Canvas intentionally diverges from the per-session CanvasHandler pattern used by Rust/Python/Go/.NET. - Go: add ResumeSessionConfig.OpenCanvases, thread through to the resume request wire payload, and add a serialization test. - .NET: add ResumeSessionConfig.OpenCanvases, thread through to the internal ResumeSessionRequest record, and add a serialization test. Mirrors what Rust and Python already do, fixing wire-protocol parity across SDKs. Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Copilot <[email protected]>
PreviousNext