Commit 51043b1
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 <223556219+Copilot@users.noreply.github.com>
* Add canvas provider RPC tracing
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* Format Rust session imports
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* Normalize JSDoc style on CanvasAgentActionDeclaration
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Drop stale wire-rename guards from canvas declaration test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Document canvas action dispatch divergence in Rust SDK
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Require handler on canvas actions
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Collapse CanvasAgentActionDeclaration into CanvasAction
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Drop debug log for inbound JSON-RPC requests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Drop canvas debug logs
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
* 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 <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 08f0521 commit 51043b1
34 files changed
Lines changed: 4083 additions & 62 deletions
File tree
- dotnet
- src
- test/Unit
- go
- nodejs
- src
- test
- python
- copilot
- rust
- src
- tests
- e2e
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
0 commit comments