[wip] Add local-canvases protocol contract (LC-17) - #443
Draft
Ulugbek Abdullaev (ulugbekna) wants to merge 3 commits into
Draft
Ulugbek Abdullaev (ulugbekna) wants to merge 3 commits into
Ulugbek Abdullaev (ulugbekna) wants to merge 3 commits into
Conversation
Introduces a versioned, renderer-neutral `ahp-canvas:` channel for local extension/package-rendered canvas surfaces, promoting the VS Code PoC transport into the canonical AHP contract. - Stable identity: CanvasIdentityKey (chat, source, canvasType, instanceId) plus a host-assigned, opaque `incarnation` token that is never reused for a superseded logical instance; CanvasPackageSource carries a dedicated `sourceId` distinct from display-only `packageName`/`version`. - Lifecycle state: CanvasTrustState (trusted/pending/blocked) and CanvasAvailabilityState (unsupported/notLoaded/loading/empty/ready/failed) are independent axes; SessionState.canvases is durable membership, distinct from the new read-only listCanvasTypes discovery catalogue. - Commands: listCanvasTypes (read-only type discovery), openCanvas (requestId-scoped idempotency; a new requestId for an already-open identity may re-invoke the provider without creating a second identity), resolveCanvasSource (read-only current-state/live-URL read, never opens/resumes/restarts), invokeCanvasAction (required incarnation precondition, no exactly-once-across-crash promise), restartCanvasProvider (the only operation that bumps incarnation), and closeCanvas (required revision precondition; logical close, distinct from hiding a tab). - Capability: new server/runtime-side CanvasCapabilities / InitializeResult.canvases, independent of the existing client-side ClientCapabilities.canvases and of protocol-version negotiation alone. - Bounds: declared, enforceable size/depth limits (request id length, identity field length, schema property/depth, declared-action count, input/result length) plus an isCanvasSchemaWithinLimits helper. - canvasReducer and sessionReducer's session/canvasSet consistently reject stale-revision actions rather than special-casing incarnation. Bumps PROTOCOL_VERSION to 0.10.0 and regenerates all client mirrors (Rust, Kotlin, Swift, Go, .NET, TypeScript), JSON schemas, and docs via `npm run generate`. Adds reducer fixtures and boundary tests for the new channel; CHANGELOG.md heading and fragment collapse remain a release-time step per RELEASING.md, not part of this change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add braces to the existing canvas reducer, membership and schema-limit conditions without changing their behavior or protocol shape. Fix the canonical sources so downstream generated copies remain reproducible. Generation, types, lint and the Node coverage suite pass. The existing release-time changelog heading gate remains unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a069b1a2-65a9-4427-b3fe-6546a3bffc9e
Implement revision-checked reducers and lossless canvas snapshots across native clients. Preserve host isolation, empty catalogues and opaque incarnations, with shared conformance and native mirror regressions. Keep the preview capability-gated on the current protocol version rather than reserving an unauthorized release. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: a069b1a2-65a9-4427-b3fe-6546a3bffc9e
Ulugbek Abdullaev (ulugbekna)
force-pushed
the
ulugbekna/local-canvas-protocol
branch
from
September 13, 2026 15:09
40b2701 to
46a4752
Compare
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.
Summary
Introduces a versioned, renderer-neutral
ahp-canvas:channel for local extension/package-rendered canvas surfaces, promoting the VS Code local-canvas PoC transport into the canonical AHP contract (LC-17). This is coordinated with an independent VS Codelocal-canvasintegration; the VS Code side is expected to sync this contract via the repo's existing protocol-sync script once merged.What's included
CanvasIdentityKey(exact backing chat, extension/package source, canvas type, instance id) plus a host-assigned, opaqueincarnationtoken that MUST NOT be reused for a superseded logical instance.CanvasPackageSourcecarries a dedicatedsourceIddistinct from display-onlypackageName/version, since the same package name can be installed in more than one scope.CanvasTrustState(trusted/pending/blocked) andCanvasAvailabilityState(unsupported/notLoaded/loading/empty/ready/failed) are independent axes.SessionState.canvasesis durable membership, distinct from the new read-onlylistCanvasTypestype-discovery catalogue.listCanvasTypes— read-only discovery of canvas types available for a chat; never opens/materializes anything.openCanvas— requestId-scoped idempotency (same requestId + identical params dedupes; different params rejectsConflict; a genuinely new requestId for an already-open identity may re-invoke the provider without creating a second logical identity).resolveCanvasSource— read-only current-state/live-endpoint read (CanvasSourcePresentation { url, expiresAt? }, renderer-neutral and never persisted); never opens/resumes/restarts anything. Also used for client-local page reload and unavailable-source retry.invokeCanvasAction— requiredincarnationprecondition (rejectsConflictif stale); no exactly-once-across-crash promise; result never persisted into durable state.restartCanvasProvider— the only operation that intentionally bumpsincarnation; required requestId + incarnation preconditions.closeCanvas— requiredrevisionprecondition; logical close (durable membership removal), distinct from a client merely hiding a tab/view.CanvasCapabilities/InitializeResult.canvases, independent of the existing client-sideClientCapabilities.canvasesand of protocol-version negotiation alone. A protocol version does not by itself imply a working canvas runtime.CANVAS_REQUEST_ID_MAX_LENGTH,CANVAS_IDENTITY_FIELD_MAX_LENGTH,CANVAS_SCHEMA_MAX_PROPERTIES/CANVAS_SCHEMA_MAX_DEPTH,CANVAS_MAX_DECLARED_ACTIONS,CANVAS_INPUT_MAX_LENGTH/CANVAS_RESULT_MAX_LENGTH) plus anisCanvasSchemaWithinLimitsenforcement helper, to give hosts a precise contract for LC-28.canvasReducerandsessionReducer'ssession/canvasSetbranch both reject any action/update whose assertedrevisionis not strictly greater than the current revision, uniformly across all fields (not just incarnation).Version / generation
PROTOCOL_VERSIONat0.9.0, following the existing protocol version policy. The provisional0.10.0bump was removed; runtime canvas capability negotiation remains mandatory.npm run generate— no generated file was hand-edited.types/test-cases/reducers/280-290) and a new boundary-test suite (types/channels-canvas.test.ts) exercise the new channel's reducer logic and size/depth limits directly, not just the existing coverage-gate shim.docs/.changes/fragments describing the contract and native-client fixes. No invented release heading or release-time fragment collapse is included.Validation
npm run typecheck✅npm run lint✅npm run generate✅ (clean, idempotent)npm run verify:release-metadata✅npm run verify:change-fragments✅npm run verify:generated✅types/reducers.tsgate46a47524: check, TypeScript, Swift, Rust, Kotlin, Go and .NET.Open items for reviewers
docs/guide/*.mdcanvas guide page yet (would need a new per-channel doc-generator function).ChatStateintentionally does not carry a parallelcanvaseslist;SessionState.canvasesremains the single authoritative catalogue.CanvasSourcePresentation) is renderer-neutral and does not require that choice to be resolved.