From 3ca8e843af9475c6c47def7b893463f238772ca5 Mon Sep 17 00:00:00 2001 From: Jon Gallant Date: Tue, 25 Aug 2026 09:42:15 -0700 Subject: [PATCH] chore(canvas-kit): sync vendored canvas-kit to 2026-08-25.1 Propagate the create-canvas-app skill's canvas-kit 2026-08-25.1 into the six extensions that vendor it. The kit added a buildSessionRestartDeepLink builder (ghapp://sessions//restart) for the Copilot host app's session-restart route, re-exported it on the browser client, and bumped KIT_VERSION. Updated extensions: code-tutor, language-tutor, news-aggregator, random-animal, stock-ticker, wiki-discover. Each vendored copy is byte-identical to the canonical kit; freshness checks pass at 2026-08-25.1. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../code-tutor/canvas-kit/.kit-version.json | 4 +-- extensions/code-tutor/canvas-kit/client.mjs | 1 + .../code-tutor/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ extensions/code-tutor/canvas-kit/version.mjs | 2 +- .../canvas-kit/.kit-version.json | 4 +-- .../language-tutor/canvas-kit/client.mjs | 1 + .../language-tutor/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ .../language-tutor/canvas-kit/version.mjs | 2 +- .../canvas-kit/.kit-version.json | 4 +-- .../news-aggregator/canvas-kit/client.mjs | 1 + .../news-aggregator/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ .../news-aggregator/canvas-kit/version.mjs | 2 +- .../canvas-kit/.kit-version.json | 4 +-- .../random-animal/canvas-kit/client.mjs | 1 + .../random-animal/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ .../random-animal/canvas-kit/version.mjs | 2 +- .../stock-ticker/canvas-kit/.kit-version.json | 4 +-- extensions/stock-ticker/canvas-kit/client.mjs | 1 + .../stock-ticker/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ .../stock-ticker/canvas-kit/version.mjs | 2 +- .../canvas-kit/.kit-version.json | 4 +-- .../wiki-discover/canvas-kit/client.mjs | 1 + .../wiki-discover/canvas-kit/deeplinks.mjs | 25 +++++++++++++++++++ .../wiki-discover/canvas-kit/version.mjs | 2 +- 24 files changed, 174 insertions(+), 18 deletions(-) diff --git a/extensions/code-tutor/canvas-kit/.kit-version.json b/extensions/code-tutor/canvas-kit/.kit-version.json index 0288758..a7d2443 100644 --- a/extensions/code-tutor/canvas-kit/.kit-version.json +++ b/extensions/code-tutor/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.187Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.244Z", "source": "create-canvas-app/kit" } diff --git a/extensions/code-tutor/canvas-kit/client.mjs b/extensions/code-tutor/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/code-tutor/canvas-kit/client.mjs +++ b/extensions/code-tutor/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/code-tutor/canvas-kit/deeplinks.mjs b/extensions/code-tutor/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/code-tutor/canvas-kit/deeplinks.mjs +++ b/extensions/code-tutor/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/code-tutor/canvas-kit/version.mjs b/extensions/code-tutor/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/code-tutor/canvas-kit/version.mjs +++ b/extensions/code-tutor/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1"; diff --git a/extensions/language-tutor/canvas-kit/.kit-version.json b/extensions/language-tutor/canvas-kit/.kit-version.json index ebef821..8a3226b 100644 --- a/extensions/language-tutor/canvas-kit/.kit-version.json +++ b/extensions/language-tutor/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.314Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.410Z", "source": "create-canvas-app/kit" } diff --git a/extensions/language-tutor/canvas-kit/client.mjs b/extensions/language-tutor/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/language-tutor/canvas-kit/client.mjs +++ b/extensions/language-tutor/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/language-tutor/canvas-kit/deeplinks.mjs b/extensions/language-tutor/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/language-tutor/canvas-kit/deeplinks.mjs +++ b/extensions/language-tutor/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/language-tutor/canvas-kit/version.mjs b/extensions/language-tutor/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/language-tutor/canvas-kit/version.mjs +++ b/extensions/language-tutor/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1"; diff --git a/extensions/news-aggregator/canvas-kit/.kit-version.json b/extensions/news-aggregator/canvas-kit/.kit-version.json index 4203a4e..04d4bf6 100644 --- a/extensions/news-aggregator/canvas-kit/.kit-version.json +++ b/extensions/news-aggregator/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.446Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.556Z", "source": "create-canvas-app/kit" } diff --git a/extensions/news-aggregator/canvas-kit/client.mjs b/extensions/news-aggregator/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/news-aggregator/canvas-kit/client.mjs +++ b/extensions/news-aggregator/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/news-aggregator/canvas-kit/deeplinks.mjs b/extensions/news-aggregator/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/news-aggregator/canvas-kit/deeplinks.mjs +++ b/extensions/news-aggregator/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/news-aggregator/canvas-kit/version.mjs b/extensions/news-aggregator/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/news-aggregator/canvas-kit/version.mjs +++ b/extensions/news-aggregator/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1"; diff --git a/extensions/random-animal/canvas-kit/.kit-version.json b/extensions/random-animal/canvas-kit/.kit-version.json index 822babc..2c4bb02 100644 --- a/extensions/random-animal/canvas-kit/.kit-version.json +++ b/extensions/random-animal/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.575Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.702Z", "source": "create-canvas-app/kit" } diff --git a/extensions/random-animal/canvas-kit/client.mjs b/extensions/random-animal/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/random-animal/canvas-kit/client.mjs +++ b/extensions/random-animal/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/random-animal/canvas-kit/deeplinks.mjs b/extensions/random-animal/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/random-animal/canvas-kit/deeplinks.mjs +++ b/extensions/random-animal/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/random-animal/canvas-kit/version.mjs b/extensions/random-animal/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/random-animal/canvas-kit/version.mjs +++ b/extensions/random-animal/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1"; diff --git a/extensions/stock-ticker/canvas-kit/.kit-version.json b/extensions/stock-ticker/canvas-kit/.kit-version.json index 4d0f806..5b6653a 100644 --- a/extensions/stock-ticker/canvas-kit/.kit-version.json +++ b/extensions/stock-ticker/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.710Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.847Z", "source": "create-canvas-app/kit" } diff --git a/extensions/stock-ticker/canvas-kit/client.mjs b/extensions/stock-ticker/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/stock-ticker/canvas-kit/client.mjs +++ b/extensions/stock-ticker/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/stock-ticker/canvas-kit/deeplinks.mjs b/extensions/stock-ticker/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/stock-ticker/canvas-kit/deeplinks.mjs +++ b/extensions/stock-ticker/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/stock-ticker/canvas-kit/version.mjs b/extensions/stock-ticker/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/stock-ticker/canvas-kit/version.mjs +++ b/extensions/stock-ticker/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1"; diff --git a/extensions/wiki-discover/canvas-kit/.kit-version.json b/extensions/wiki-discover/canvas-kit/.kit-version.json index 11f17c6..9210c86 100644 --- a/extensions/wiki-discover/canvas-kit/.kit-version.json +++ b/extensions/wiki-discover/canvas-kit/.kit-version.json @@ -1,5 +1,5 @@ { - "version": "2026-07-20.1", - "syncedAt": "2026-07-20T16:19:40.842Z", + "version": "2026-08-25.1", + "syncedAt": "2026-08-25T16:40:45.985Z", "source": "create-canvas-app/kit" } diff --git a/extensions/wiki-discover/canvas-kit/client.mjs b/extensions/wiki-discover/canvas-kit/client.mjs index f1710c9..79bfc08 100644 --- a/extensions/wiki-discover/canvas-kit/client.mjs +++ b/extensions/wiki-discover/canvas-kit/client.mjs @@ -36,6 +36,7 @@ export { hostedLauncherUrl, buildSessionDeepLink, buildSessionDetailDeepLink, + buildSessionRestartDeepLink, buildChatsDeepLink, buildNewChatDeepLink, buildNewAutomationDeepLink, diff --git a/extensions/wiki-discover/canvas-kit/deeplinks.mjs b/extensions/wiki-discover/canvas-kit/deeplinks.mjs index c4e8b3c..a46eaa8 100644 --- a/extensions/wiki-discover/canvas-kit/deeplinks.mjs +++ b/extensions/wiki-discover/canvas-kit/deeplinks.mjs @@ -223,6 +223,31 @@ export function buildSessionDetailDeepLink(sessionId) { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}`); } +/** + * `ghapp://sessions/:sessionId/restart`: restart a session's Copilot CLI process + * — kill the child process and spawn a fresh one, the same operation as the + * `/restart-session` slash command. Reach for this when a canvas needs the app to + * pick up process-start-resolved state (MCP servers, extensions resolved at + * launch) that a plain `plugins.reload()` / `skills.reload()` re-reads from disk + * but can't actually respawn. + * + * The route is DESTRUCTIVE (queued input and any in-flight response are discarded) + * and a global entry point, so the app ALWAYS shows a confirmation dialog before + * restarting and never navigates or self-approves — the canvas only BUILDS the + * URL. The id is resolved against the app's own live sessions, so an id that is + * not a session on this device (or one that runs on a remote host) is rejected + * before the dialog rather than prompting for something known to fail. `sessionId` + * must be the same safe token shape as {@link buildSessionDetailDeepLink} (so it + * can't smuggle extra path segments or query keys); returns null otherwise, so a + * caller can withhold the control instead of rendering a dead link. + * @param {string} sessionId + * @returns {string|null} + */ +export function buildSessionRestartDeepLink(sessionId) { + if (!isSafeSessionId(sessionId)) return null; + return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://sessions/${sessionId}/restart`); +} + /** `ghapp://chats`: open the Chats surface. */ export function buildChatsDeepLink() { return safeDeepLinkUrl(`${APP_DEEP_LINK_SCHEME}://chats`); diff --git a/extensions/wiki-discover/canvas-kit/version.mjs b/extensions/wiki-discover/canvas-kit/version.mjs index a36d063..22da8a3 100644 --- a/extensions/wiki-discover/canvas-kit/version.mjs +++ b/extensions/wiki-discover/canvas-kit/version.mjs @@ -10,4 +10,4 @@ // convention (the skill ships as files, not an npm version); a commit short-sha // works too. Re-exported from client.mjs so a canvas can read it at runtime. -export const KIT_VERSION = "2026-07-20.1"; +export const KIT_VERSION = "2026-08-25.1";