Add Canvas channel (spec + all clients)#298
Open
colbylwilliams wants to merge 5 commits into
Open
Conversation
Implement the Canvas surface proposed in #297. A Canvas is a host-driven, interactive UI surface (editor, browser, terminal, document view, …) that a session can open and drive over AHP. This adds the full protocol surface plus matching support in all five client mirrors. Protocol surface (types/): - ClientCapabilities.canvas opt-in capability. - Session-state discovery surface: SessionState.canvases (declared canvas types) and SessionState.openCanvases (live instances), plus SessionActiveClient.canvasProviders published atomically like tools. New supporting types CanvasAvailability, CanvasProviderKind, CanvasProviderSource (named discriminated union), SessionCanvasDeclaration, ClientCanvasDeclaration, OpenCanvasRef, SessionCanvasAction. - Per-instance channel ahp-canvas:/<id> carrying CanvasState and the canvas/updated, canvas/closeRequested, canvas/message actions, with canvasReducer applying a sparse merge for canvas/updated. - Server -> client canvas provider request family (canvasOpen / canvasInvokeAction / canvasClose) mirrored in CommandMap for symmetry with the resource* family, and client -> server canvasReadResource for the in-band content path. - New CanvasProviderError (-32012) with CanvasProviderErrorData. - Protocol version 0.5.1 -> 0.6.0; canvas actions registered at 0.6.0. Generators/tooling: canvas sources wired into find-protocol-sources, generate-action-origin, and the Go/Rust/Swift/Kotlin generators; regenerated client types, JSON schemas, action-origin table, and reference docs. Clients: hand-ported canvasReducer and the session canvas arms to Rust, Go, Swift, Kotlin, and TypeScript. The exhaustive Rust/Swift state mirrors also route the ahp-canvas: channel; the prefix-routing Go/TS mirrors need no change. Fixtures: 8 shared reducer fixtures (232-239) exercising the session registry replacement, open-canvas catalogue replacement, canvas/updated full and partial merges, and the closeRequested / message / unknown-action no-ops. Validated across the TypeScript, Rust, Go, Swift, and Kotlin fixture runners. Docs: new specification/canvas-channel.md and guide/canvases.md, plus subscriptions.md, session-channel.md, and sidebar updates. CHANGELOGs updated for the spec and all five clients. Refs #297 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
- Reflow the `ahp_types::state` import block to satisfy `cargo fmt`. - Copy `CanvasAvailability` by deref instead of `.clone()` (it is `Copy`), fixing `clippy::clone_on_copy` under `-D warnings`. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Adds the new Canvas protocol surface (capability + discovery + per-instance channel + provider request family) to the canonical types/ tree, then propagates it through schema/docs generation and the Rust/Go/Swift/Kotlin/TypeScript client mirrors, alongside a protocol version bump to 0.6.0.
Changes:
- Introduces Canvas state, actions, commands, errors, and session discovery fields in
types/(plus reducers + fixtures). - Updates generators and regenerated artifacts (client generated types, JSON schemas, action-origin tables, version registries).
- Adds/updates specification and guide documentation, release metadata, and per-artifact CHANGELOG entries.
Show a summary per file
| File | Description |
|---|---|
| types/version/registry.ts | Bumps protocol version + registers canvas action introduction versions. |
| types/version/message-checks.ts | Updates compile-time command map expectations for canvas methods. |
| types/test-cases/reducers/232-session-canvaseschanged-sets-registry.json | Adds session reducer fixture for canvases registry replacement. |
| types/test-cases/reducers/233-session-opencanvaseschanged-sets-catalogue.json | Adds session reducer fixture for open canvases catalogue replacement. |
| types/test-cases/reducers/234-canvas-updated-merges-all-fields.json | Adds canvas reducer fixture for full sparse-merge update. |
| types/test-cases/reducers/235-canvas-updated-partial-preserves-absent.json | Adds canvas reducer fixture for partial merge (preserve absent). |
| types/test-cases/reducers/236-canvas-updated-partial-complementary.json | Adds canvas reducer fixture for complementary partial merge. |
| types/test-cases/reducers/237-canvas-closerequested-no-op.json | Adds canvas reducer fixture ensuring closeRequested is a no-op. |
| types/test-cases/reducers/238-canvas-message-no-op.json | Adds canvas reducer fixture ensuring message is a no-op. |
| types/test-cases/reducers/239-canvas-unknown-action-type-is-no-op.json | Adds fixture for unknown canvas action type no-op behavior. |
| types/state.ts | Exports canvas channel state from the state barrel. |
| types/reducers.ts | Exports the new canvas reducer from reducer barrel. |
| types/reducers.test.ts | Wires canvas reducer into fixture runner + source scanning. |
| types/messages.test.ts | Adds canvas channel sources to message tests’ scan set. |
| types/index.ts | Re-exports canvas types/actions/commands/reducer from public API. |
| types/common/state.ts | Extends snapshot state union to include CanvasState. |
| types/common/messages.ts | Registers canvas commands in CommandMap + ServerCommandMap. |
| types/common/errors.ts | Adds CanvasProviderError code and data payload type. |
| types/common/commands.ts | Adds ClientCapabilities.canvas capability definition. |
| types/common/actions.ts | Adds canvas/session canvas action types into common action unions. |
| types/commands.ts | Exports canvas channel commands from the commands barrel. |
| types/channels-session/state.ts | Adds canvases/openCanvases fields and canvas discovery types. |
| types/channels-session/reducer.ts | Adds session reducer handling for canvases/openCanvases actions. |
| types/channels-session/actions.ts | Defines session/canvasesChanged and session/openCanvasesChanged. |
| types/channels-canvas/state.ts | Defines CanvasState for per-instance ahp-canvas: channels. |
| types/channels-canvas/reducer.ts | Implements sparse-merge reducer and no-op signal handling. |
| types/channels-canvas/commands.ts | Defines canvas provider family + canvasReadResource content request. |
| types/channels-canvas/actions.ts | Defines canvas channel actions + dispatchability annotations. |
| types/actions.ts | Exports canvas channel actions from the actions barrel. |
| types/action-origin.generated.ts | Adds canvas action unions and dispatchability map entries. |
| scripts/generate-swift.ts | Updates Swift generator for canvas types/unions/commands/actions/errors. |
| scripts/generate-rust.ts | Updates Rust generator for canvas types/unions/commands/actions/errors. |
| scripts/generate-kotlin.ts | Updates Kotlin generator for canvas types/unions/commands/actions/errors. |
| scripts/generate-go.ts | Updates Go generator for canvas types/unions/commands/actions/errors. |
| scripts/generate-action-origin.ts | Extends action-origin generation to include canvas-scoped actions. |
| scripts/find-protocol-sources.ts | Adds channels-canvas to protocol source discovery. |
| schema/state.schema.json | Regenerates JSON schema to include CanvasState + session canvas fields/types. |
| schema/notifications.schema.json | Regenerates notification schema to include canvas-related state shapes. |
| docs/specification/subscriptions.md | Documents ahp-canvas: scheme + canvasReadResource in channel-scoped commands. |
| docs/specification/session-channel.md | Documents session-level canvas discovery fields and actions. |
| docs/specification/canvas-channel.md | Adds full Canvas Channel specification page (state/actions/commands/errors). |
| docs/guide/canvases.md | Adds a high-level “Canvases” guide describing roles and lifecycle. |
| docs/.vitepress/config.mts | Adds Canvases to guide/spec sidebar navigation. |
| clients/typescript/release-metadata.json | Adds 0.6.0 to supported protocol versions. |
| clients/typescript/CHANGELOG.md | Adds TypeScript client changelog entry for canvas support. |
| clients/swift/release-metadata.json | Adds 0.6.0 to supported protocol versions. |
| clients/swift/CHANGELOG.md | Adds Swift client changelog entry for canvas support. |
| clients/swift/AgentHostProtocol/Tests/AgentHostProtocolTests/FixtureDrivenReducerTests.swift | Adds fixture runner support for canvas reducer fixtures. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/MultiHostStateMirror.swift | Mirrors ahp-canvas: channels in the multi-host state mirror. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocolClient/AHPStateMirror.swift | Mirrors ahp-canvas: channels in the single-host state mirror. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Reducers.swift | Adds session canvas handling + a canvas reducer implementation. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Version.generated.swift | Bumps generated Swift protocol version + supported versions. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Errors.generated.swift | Adds generated Swift error code/data for CanvasProviderError. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Commands.generated.swift | Adds generated Swift capability + canvas command structs. |
| clients/swift/AgentHostProtocol/Sources/AgentHostProtocol/Generated/Actions.generated.swift | Adds generated Swift canvas/session actions + union wiring. |
| clients/rust/release-metadata.json | Adds 0.6.0 to supported protocol versions. |
| clients/rust/crates/ahp/tests/multi_host_state_mirror.rs | Updates Rust test helpers for new session canvas fields. |
| clients/rust/crates/ahp/src/reducers.rs | Adds session canvas reducers + new apply_action_to_canvas reducer. |
| clients/rust/crates/ahp/src/multi_host_state_mirror.rs | Mirrors ahp-canvas: channels in Rust multi-host state mirror. |
| clients/rust/crates/ahp-types/src/version.rs | Bumps Rust types crate protocol version + supported versions. |
| clients/rust/crates/ahp-types/src/state.rs | Adds Rust canvas types and session fields + snapshot state union update. |
| clients/rust/crates/ahp-types/src/errors.rs | Adds Rust CanvasProviderError code + data struct. |
| clients/rust/crates/ahp-types/src/commands.rs | Adds Rust ClientCapabilities.canvas + canvas command structs. |
| clients/rust/crates/ahp-types/src/actions.rs | Adds Rust canvas/session canvas actions + StateAction wiring. |
| clients/rust/CHANGELOG.md | Adds Rust client changelog entry for canvas support. |
| clients/kotlin/src/test/kotlin/com/microsoft/agenthostprotocol/FixtureDrivenReducerTest.kt | Adds Kotlin fixture runner support for canvas reducer fixtures. |
| clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/Reducers.kt | Adds Kotlin session canvas handling + canvas reducer implementation. |
| clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Version.generated.kt | Bumps generated Kotlin protocol version + supported versions. |
| clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Errors.generated.kt | Adds generated Kotlin error code/data for CanvasProviderError. |
| clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Commands.generated.kt | Adds generated Kotlin capability + canvas command structs. |
| clients/kotlin/src/main/kotlin/com/microsoft/agenthostprotocol/generated/Actions.generated.kt | Adds generated Kotlin canvas/session actions + union wiring. |
| clients/kotlin/release-metadata.json | Adds 0.6.0 to supported protocol versions. |
| clients/kotlin/CHANGELOG.md | Adds Kotlin client changelog entry for canvas support. |
| clients/go/release-metadata.json | Adds 0.6.0 to supported protocol versions. |
| clients/go/CHANGELOG.md | Adds Go client changelog entry for canvas support. |
| clients/go/ahptypes/version.generated.go | Bumps generated Go protocol version + supported versions. |
| clients/go/ahptypes/state.generated.go | Adds generated Go canvas types/session fields + snapshot union updates. |
| clients/go/ahptypes/errors.generated.go | Adds generated Go error code/data for CanvasProviderError. |
| clients/go/ahptypes/commands.generated.go | Adds generated Go capability + canvas command structs. |
| clients/go/ahptypes/actions.generated.go | Adds generated Go canvas/session actions + StateAction wiring. |
| clients/go/ahp/reducers.go | Adds Go session canvas handling + ApplyActionToCanvas reducer. |
| clients/go/ahp/reducers_fixture_test.go | Adds Go fixture runner support for canvas reducer fixtures. |
| CHANGELOG.md | Adds spec changelog entry describing the canvas channel addition. |
Review details
- Files reviewed: 78/88 changed files
- Comments generated: 4
- Review effort level: Low
Peer review of the canvas PR surfaced one design gap and three doc issues, each validated against the code before changing: - canvas/updated is now @clientDispatchable. The PR already models client-side canvas providers (ClientCanvasDeclaration, the client CanvasProviderSource variant, CanvasAvailability.Stale), and title / availability are mirrored onto OpenCanvasRef for other subscribers, yet canvas/updated was server-only — leaving a client-side provider no wire path to push its own presentation changes. This mirrors the established terminal/titleChanged pattern (a client may originate it; the host validates, applies, and re-broadcasts). Regenerated: IS_CLIENT_DISPATCHABLE now maps canvas/updated to true, ClientCanvasAction gains it, and ServerCanvasAction becomes `never`. - Fixed the canvas-channel.md sequence diagram to reference the real session/activeClientSet action (there is no session/activeClientsChanged). - Documented that a View to provider canvas/message routes to the single resolved provider, and that multi-renderer provider to View targeting is deferred to the open render-targeting question. - Clarified the deliberate channel split in the command family (session-scoped provider RPCs vs. instance-scoped canvasReadResource). No client reducer/mirror changes are needed: the dispatchability split lives only in the canonical action-origin table; the per-language reducers switch on action type. Verified across TS core (291 tests), Rust (fmt + clippy + test), Go, Swift, Kotlin, the TS client, and the docs build. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…ntDispatchable Copilot review follow-ups on the canvas PR: - Don't bump PROTOCOL_VERSION or invent a `## [0.6.0]` CHANGELOG heading in a feature PR. Per repo convention (AGENTS.md + the ea386ee precedent), new actions register at the *current* spec version and their bullets accumulate under `## [Unreleased]`; the version bump and `## [X.Y.Z]` rotation are a dedicated release chore. Revert PROTOCOL_VERSION 0.6.0 -> 0.5.1, drop 0.6.0 from SUPPORTED_PROTOCOL_VERSIONS, register the five canvas actions/session actions at 0.5.1, and fold the canvas bullet back under `## [Unreleased]`. Regenerate the per-client Version.generated.* and release-metadata.json. - Extend `isClientDispatchable` to accept `CanvasAction` and narrow to `ClientCanvasAction`, so consumers can validate the canvas channel's client-dispatchable actions (canvas/updated, canvas/closeRequested, canvas/message) without a cast. Add a canvas assertion to its test. The two mermaid comments (session/activeClientSet naming, canvas/updated direction) were already resolved in the prior review-response commit. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…0.5.2 main released AHP 0.5.1 (#301) and bumped PROTOCOL_VERSION to 0.5.2 for ongoing development. Re-register the canvas actions at the current spec version 0.5.2 (was 0.5.1), move the canvas CHANGELOG bullet under the spec [0.5.2] section and each client's [Unreleased], and combine the Rust generator's chat-turn-paging additions with the canvas imports. Regenerated all client mirrors, schemas, docs, and release metadata. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements the Canvas surface proposed in #297. A Canvas is a host-driven, interactive UI surface (editor, browser, terminal, document view, …) that a session can open and drive over AHP. This PR adds the full protocol surface in the canonical
types/tree, wires it through the four per-language generators, and hand-ports the runtime pieces to all five client mirrors.What's included
canvasclient capability advertising which native canvas types the client can render.canvasProviderspublished atomically onSessionActiveClient(same lifecycle astools), plusCanvasAvailability/CanvasProviderSourcein session state.ahp-canvas:/<id>channel per open canvas instance (mirrors the terminal / changeset pattern), carryingcanvas/updated,canvas/closeRequested, and the opaquecanvas/messagebridge.canvasProviderOpen/canvasProviderInvokeAction/canvasProviderCloseinServerCommandMap, mirrored inCommandMap(theresource*precedent).canvasReadResource+ the opaquecanvas/messagepath.CanvasProviderErrorcarrying{ code, message }.PROTOCOL_VERSIONbump. The canvas actions register at the current spec version (0.5.1) inACTION_INTRODUCED_IN, and the CHANGELOG bullets land under## [Unreleased]. Per repo convention (and thesession/inputNeededprecedent), bumpingPROTOCOL_VERSIONand rotating the## [X.Y.Z]heading is a separate release-time chore, not part of a feature PR. Client package versions stay 0.5.0 (bumped at release time).Cross-language surface
types/(errors, capability,channels-canvas/,channels-session/state + actions + reducer, common actions enum/union, messages maps, version registry, index).generate-markdowngets the canvas slug + channel section.Fixtures
Reducer fixtures cover: provider-registry replace, open-catalogue replace,
canvas/updatedsparse merge (present overwrites / absent preserves),canvas/closeRequestedno-op, andcanvas/messageno-op.Validated deviations from the proposal
canvas/updateduses a value-based sparse merge (present field overwrites, absent preserves) rather than the proposal's three-statenull-clears / absent-preserves model. The three-state model isn't portable: the conformance harness collapses JSONnull→undefined, and the generated Rust/Kotlin/Swift/Go nullable fields can't distinguishnullfrom absent after deserialization. Action fields are thereforetitle?: string(no| null), and fresh snapshots on (re)subscribe cover the reset case.channelscopes it), socanvas/updatedcarries noinstanceIdand the reducer has no instance-lookup branch.CanvasProviderSourceis modeled as a named discriminated union (CanvasProviderKindenum +CanvasServerProviderSource/CanvasClientProviderSource) rather than an inline anonymous union, because the per-language generators need named variants and the editorial rules mandate a*Kinddiscriminant.canvas/messageis bidirectional; since the action-origin model is binary it's marked@clientDispatchable(clients may send; the server may also emit). The reducer handles it via the fullCanvasActionunion regardless.