Skip to content

Add Canvas channel (spec + all clients)#298

Open
colbylwilliams wants to merge 5 commits into
mainfrom
colby-canvas-channel
Open

Add Canvas channel (spec + all clients)#298
colbylwilliams wants to merge 5 commits into
mainfrom
colby-canvas-channel

Conversation

@colbylwilliams

@colbylwilliams colbylwilliams commented Jul 2, 2026

Copy link
Copy Markdown
Member

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

  • Capability — a canvas client capability advertising which native canvas types the client can render.
  • DiscoverycanvasProviders published atomically on SessionActiveClient (same lifecycle as tools), plus CanvasAvailability / CanvasProviderSource in session state.
  • Per-instance channels — one ahp-canvas:/<id> channel per open canvas instance (mirrors the terminal / changeset pattern), carrying canvas/updated, canvas/closeRequested, and the opaque canvas/message bridge.
  • Provider methods — server→client canvasProviderOpen / canvasProviderInvokeAction / canvasProviderClose in ServerCommandMap, mirrored in CommandMap (the resource* precedent).
  • In-band contentcanvasReadResource + the opaque canvas/message path.
  • ErrorCanvasProviderError carrying { code, message }.
  • Version — no PROTOCOL_VERSION bump. The canvas actions register at the current spec version (0.5.1) in ACTION_INTRODUCED_IN, and the CHANGELOG bullets land under ## [Unreleased]. Per repo convention (and the session/inputNeeded precedent), bumping PROTOCOL_VERSION and 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 authored in types/ (errors, capability, channels-canvas/, channels-session/ state + actions + reducer, common actions enum/union, messages maps, version registry, index).
  • Generators wired through find-protocol-sources, generate-action-origin, and generate-{go,rust,kotlin,swift}; generate-markdown gets the canvas slug + channel section.
  • Clients — reducer hand-ports for Rust, Kotlin, Swift, and Go, plus the TS reducer, all exercised by the shared conformance fixtures.

Fixtures

Reducer fixtures cover: provider-registry replace, open-catalogue replace, canvas/updated sparse merge (present overwrites / absent preserves), canvas/closeRequested no-op, and canvas/message no-op.

Validated deviations from the proposal

  1. canvas/updated uses a value-based sparse merge (present field overwrites, absent preserves) rather than the proposal's three-state null-clears / absent-preserves model. The three-state model isn't portable: the conformance harness collapses JSON nullundefined, and the generated Rust/Kotlin/Swift/Go nullable fields can't distinguish null from absent after deserialization. Action fields are therefore title?: string (no | null), and fresh snapshots on (re)subscribe cover the reset case.
  2. No "unknown-instance no-op" fixture: the channel is per-instance (the envelope's channel scopes it), so canvas/updated carries no instanceId and the reducer has no instance-lookup branch.
  3. CanvasProviderSource is modeled as a named discriminated union (CanvasProviderKind enum + CanvasServerProviderSource / CanvasClientProviderSource) rather than an inline anonymous union, because the per-language generators need named variants and the editorial rules mandate a *Kind discriminant.
  4. canvas/message is 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 full CanvasAction union regardless.

colbylwilliams and others added 2 commits July 1, 2026 21:49
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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Comment thread CHANGELOG.md Outdated
Comment thread docs/specification/canvas-channel.md
Comment thread docs/specification/canvas-channel.md
Comment thread types/reducers.ts
colbylwilliams and others added 2 commits July 1, 2026 22:29
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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 72/80 changed files
  • Comments generated: 3
  • Review effort level: Low

Comment thread types/version/registry.ts Outdated
Comment thread schema/notifications.schema.json
Comment thread schema/state.schema.json
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants