diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md
index f0f7931..266a0c6 100644
--- a/.github/copilot-instructions.md
+++ b/.github/copilot-instructions.md
@@ -179,6 +179,7 @@ src/
| `VAPID_PRIVATE_KEY` | No | — | VAPID private key for web push |
| `VAPID_SUBJECT` | No | — | VAPID subject (mailto: or https: URL) |
| `PUSH_STORE_PATH` | No | ./data/push-subscriptions | Directory for push subscription storage |
+| `ENABLE_REMOTE_SESSIONS` | No | true | Enable cloud/remote session publishing on the SDK client. Sessions still need per-session `remoteSession: "export"|"on"` opt-in. Set to `false` to hard-disable. |
## Build & Run
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index efdaeea..2e5a6a8 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -82,7 +82,7 @@ jobs:
e2e:
needs: check
runs-on: ubuntu-latest
- timeout-minutes: 15
+ timeout-minutes: 30
steps:
- uses: actions/checkout@v4
diff --git a/README.md b/README.md
index 0377ff1..269727c 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,7 @@
-
+
@@ -37,6 +37,8 @@
- **Every Copilot model** — Claude Opus 4.6, GPT-5.4, Gemini 3 Pro, Claude Sonnet 4.6, and more — switch mid-conversation, keep full history
- **Autopilot agents** — plan, code, run tests, and open PRs autonomously with live tool execution
+- **Remote session publishing** — opt sessions into being visible on github.com / Mobile via `remoteSession: "export" | "on"` (powered by SDK 1.0.0-beta.8); the browser app stays the steering surface, GitHub gets monitor visibility. Server-side toggle: `ENABLE_REMOTE_SESSIONS` (default on); per-session opt-in still required.
+- **Resume last session** — `GET /api/sessions/last` returns metadata for the user's most recent local session for one-tap continue-on-any-device flows
- **Extended thinking** — live reasoning traces with collapsible "Thinking…" blocks
- **Voice input** — speech-to-text via Web Speech API; mic button replaces send when input is empty (ChatGPT-style UX) — toggle in Settings
- **Read aloud** — text-to-speech on any assistant message; markdown-aware sentence chunking with configurable speed — toggle in Settings
@@ -138,6 +140,7 @@ Open [localhost:3000](http://localhost:3000). Log in with GitHub. Done.
| `VAPID_PRIVATE_KEY` | — | Push notifications (base64url) |
| `VAPID_SUBJECT` | — | Push subject (`mailto:` or `https:`) |
| `PUSH_STORE_PATH` | `/data/push-subscriptions` | Push subscription storage |
+| `ENABLE_REMOTE_SESSIONS` | `true` | Allow sessions to opt into cloud publishing (`remoteSession: "export"\|"on"`). Set to `false` to hard-disable. |
@@ -206,6 +209,20 @@ The Sessions panel auto-refreshes every 30 seconds. Use `COPILOT_CONFIG_DIR` to
+### Remote session publishing (SDK 1.0.0-beta.8)
+
+A chat can opt into being **published** to github.com / Copilot Mobile by passing one of these values when the session is created:
+
+| Mode | Effect |
+|---|---|
+| `"off"` *(default)* | Local only. Nothing leaves the server. |
+| `"export"` | Read-only mirror — session events stream to GitHub so it shows up on github.com/copilot and Mobile in monitor mode. |
+| `"on"` | Full remote-steerable — the session is steerable from github.com / Mobile as well as from this app. |
+
+This is sent over WebSocket as `{ type: "new_session", remoteSession: "on", ... }` and threaded through to the SDK's `sessionConfig.remoteSession`. The server-wide kill switch is `ENABLE_REMOTE_SESSIONS=false`.
+
+> **What's not in this release:** the app does **not** include an in-app browser for *other* remote sessions (the ones running elsewhere on your account) and does **not** let you steer arbitrary remote sessions from this UI — the SDK exposes no public REST endpoint for listing them, and the github.com remote-sessions view talks to an internal API that requires a Copilot bearer integrators can't currently mint. To view all your remote sessions, use github.com or the Copilot Mobile app. PRs welcome once the SDK surfaces a public list API.
+
---
## How It Works
@@ -317,7 +334,7 @@ Device Flow OAuth (same as GitHub CLI). Tokens are server-side only, never sent
## Built With
-SvelteKit 5 · Svelte 5 runes · TypeScript 5.7 · Node.js 24 · [`@github/copilot-sdk`](https://github.com/github/copilot-sdk) v0.2.2 · Vite · `ws` · Web Speech API · Vitest · Playwright · Docker · Bicep
+SvelteKit 5 · Svelte 5 runes · TypeScript 5.7 · Node.js 24 · [`@github/copilot-sdk`](https://github.com/github/copilot-sdk) v1.0.0-beta.8 · Vite · `ws` · Web Speech API · Vitest · Playwright · Docker · Bicep
## Contributing
diff --git a/package-lock.json b/package-lock.json
index 3880445..b02d086 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,36 +10,36 @@
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
- "@github/copilot-sdk": "^0.2.2",
+ "@github/copilot-sdk": "1.0.0-beta.8",
"@sveltejs/adapter-node": "^5.5.4",
- "@sveltejs/kit": "^2.57.1",
- "dompurify": "^3.4.0",
+ "@sveltejs/kit": "^2.61.1",
+ "dompurify": "^3.4.7",
"express-session": "^1.18.0",
"highlight.js": "^11.11.1",
"lucide-svelte": "^1.0.1",
- "marked": "^18.0.2",
+ "marked": "^18.0.4",
"session-file-store": "^1.5.0",
- "svelte": "^5.55.4",
- "vite": "^8.0.8",
+ "svelte": "^5.55.9",
+ "vite": "^8.0.14",
"web-push": "^3.6.7",
- "ws": "^8.18.0"
+ "ws": "^8.21.0"
},
"devDependencies": {
- "@playwright/test": "^1.59.1",
- "@sveltejs/vite-plugin-svelte": "^7.0.0",
+ "@playwright/test": "^1.60.0",
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
"@testing-library/jest-dom": "^6.9.1",
"@types/express-session": "^1.19.0",
- "@types/node": "^25.6.0",
+ "@types/node": "^25.7.0",
"@types/session-file-store": "^1.2.6",
"@types/web-push": "^3.6.4",
"@types/ws": "^8.5.13",
- "@vitest/coverage-v8": "^4.1.5",
+ "@vitest/coverage-v8": "^4.1.6",
"dotenv": "^17.4.2",
"husky": "^9.1.7",
- "jsdom": "^29.0.2",
- "lint-staged": "^16.4.0",
+ "jsdom": "^29.1.1",
+ "lint-staged": "^17.0.4",
"sharp": "^0.34.5",
- "svelte-check": "^4.4.6",
+ "svelte-check": "^4.4.8",
"typescript": "^6.0.3",
"vitest": "^4.1.3"
},
@@ -55,14 +55,15 @@
"license": "MIT"
},
"node_modules/@asamuzakjp/css-color": {
- "version": "5.1.10",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.10.tgz",
- "integrity": "sha512-02OhhkKtgNRuicQ/nF3TRnGsxL9wp0r3Y7VlKWyOHHGmGyvXv03y+PnymU8FKFJMTjIr1Bk8U2g1HWSLrpAHww==",
+ "version": "5.1.11",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz",
+ "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@csstools/css-calc": "^3.1.1",
- "@csstools/css-color-parser": "^4.0.2",
+ "@asamuzakjp/generational-cache": "^1.0.1",
+ "@csstools/css-calc": "^3.2.0",
+ "@csstools/css-color-parser": "^4.1.0",
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0"
},
@@ -71,12 +72,13 @@
}
},
"node_modules/@asamuzakjp/dom-selector": {
- "version": "7.0.9",
- "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.0.9.tgz",
- "integrity": "sha512-r3ElRr7y8ucyN2KdICwGsmj19RoN13CLCa/pvGydghWK6ZzeKQ+TcDjVdtEZz2ElpndM5jXw//B9CEee0mWnVg==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz",
+ "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==",
"dev": true,
"license": "MIT",
"dependencies": {
+ "@asamuzakjp/generational-cache": "^1.0.1",
"@asamuzakjp/nwsapi": "^2.3.9",
"bidi-js": "^1.0.3",
"css-tree": "^3.2.1",
@@ -86,6 +88,16 @@
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
+ "node_modules/@asamuzakjp/generational-cache": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz",
+ "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
+ }
+ },
"node_modules/@asamuzakjp/nwsapi": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
@@ -187,9 +199,9 @@
}
},
"node_modules/@csstools/css-calc": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.0.tgz",
- "integrity": "sha512-bR9e6o2BDB12jzN/gIbjHa5wLJ4UjD1CB9pM7ehlc0ddk6EBz+yYS1EV2MF55/HUxrHcB/hehAyt5vhsA3hx7w==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz",
+ "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==",
"dev": true,
"funding": [
{
@@ -211,9 +223,9 @@
}
},
"node_modules/@csstools/css-color-parser": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.0.tgz",
- "integrity": "sha512-U0KhLYmy2GVj6q4T3WaAe6NPuFYCPQoE3b0dRGxejWDgcPp8TP7S5rVdM5ZrFaqu4N67X8YaPBw14dQSYx3IyQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.1.tgz",
+ "integrity": "sha512-eZ5XOtyhK+mggRafYUWzA0tvaYOFgdY8AkgQiCJF9qNAePnUo/zmsqqYubBBb3sQ8uNUaSKTY9s9klfRaAXL0g==",
"dev": true,
"funding": [
{
@@ -228,7 +240,7 @@
"license": "MIT",
"dependencies": {
"@csstools/color-helpers": "^6.0.2",
- "@csstools/css-calc": "^3.2.0"
+ "@csstools/css-calc": "^3.2.1"
},
"engines": {
"node": ">=20.19.0"
@@ -262,9 +274,9 @@
}
},
"node_modules/@csstools/css-syntax-patches-for-csstree": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.1.tgz",
- "integrity": "sha512-BvqN0AMWNAnLk9G8jnUT77D+mUbY/H2b3uDTvg2isJkHaOufUE2R3AOwxWo7VBQKT1lOdwdvorddo2B/lk64+w==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.4.tgz",
+ "integrity": "sha512-wgsqt92b7C7tQhIdPNxj0n9zuUbQlvAuI1exyzeNrOKOi62SD7ren8zqszmpVREjAOqg8cD2FqYhQfAuKjk4sw==",
"dev": true,
"funding": [
{
@@ -307,9 +319,9 @@
}
},
"node_modules/@emnapi/core": {
- "version": "1.9.2",
- "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.2.tgz",
- "integrity": "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz",
+ "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -318,9 +330,9 @@
}
},
"node_modules/@emnapi/runtime": {
- "version": "1.9.2",
- "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.9.2.tgz",
- "integrity": "sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==",
+ "version": "1.10.0",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz",
+ "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -356,26 +368,31 @@
}
},
"node_modules/@github/copilot": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.21.tgz",
- "integrity": "sha512-P+nORjNKAtl92jYCG6Qr1Rsw2JoyScgeQSkIR6O2WB37WS5JVdA4ax1WVualMbfuc9V58CPHX6fwyNpkI89FkQ==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot/-/copilot-1.0.55-5.tgz",
+ "integrity": "sha512-n6Vr876Iz41PW8pSpOa7SbrNCqaV+6HDLNf/n8V4gIwwlOlIz7Jb00r/fboXZFIT+0dyAGGLoGgd7xUujVL/Xw==",
"license": "SEE LICENSE IN LICENSE.md",
+ "dependencies": {
+ "detect-libc": "^2.1.2"
+ },
"bin": {
"copilot": "npm-loader.js"
},
"optionalDependencies": {
- "@github/copilot-darwin-arm64": "1.0.21",
- "@github/copilot-darwin-x64": "1.0.21",
- "@github/copilot-linux-arm64": "1.0.21",
- "@github/copilot-linux-x64": "1.0.21",
- "@github/copilot-win32-arm64": "1.0.21",
- "@github/copilot-win32-x64": "1.0.21"
+ "@github/copilot-darwin-arm64": "1.0.55-5",
+ "@github/copilot-darwin-x64": "1.0.55-5",
+ "@github/copilot-linux-arm64": "1.0.55-5",
+ "@github/copilot-linux-x64": "1.0.55-5",
+ "@github/copilot-linuxmusl-arm64": "1.0.55-5",
+ "@github/copilot-linuxmusl-x64": "1.0.55-5",
+ "@github/copilot-win32-arm64": "1.0.55-5",
+ "@github/copilot-win32-x64": "1.0.55-5"
}
},
"node_modules/@github/copilot-darwin-arm64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.21.tgz",
- "integrity": "sha512-aB+s9ldTwcyCOYmzjcQ4SknV6g81z92T8aUJEJZBwOXOTBeWKAJtk16ooAKangZgdwuLgO3or1JUjx1FJAm5nQ==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-arm64/-/copilot-darwin-arm64-1.0.55-5.tgz",
+ "integrity": "sha512-Mult62GJVnxR3MOP2QNiVU5RRGXPJ+7BpjEMIvkoaMuWX6J7F4bz7N+HUXVHJUiGUp3hnL3M16kjkewWfNdoNg==",
"cpu": [
"arm64"
],
@@ -389,9 +406,9 @@
}
},
"node_modules/@github/copilot-darwin-x64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.21.tgz",
- "integrity": "sha512-aNad81DOGuGShmaiFNIxBUSZLwte0dXmDYkGfAF9WJIgY4qP4A8CPWFoNr8//gY+4CwaIf9V+f/OC6k2BdECbw==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-darwin-x64/-/copilot-darwin-x64-1.0.55-5.tgz",
+ "integrity": "sha512-IfY3WhNvHwXHldI2ARsiAYuPlKWlI07Fo1ALq+SViHhn0Zfp2yIr9laJRofyj0G1EbyUxkbNlqQm7UrXhkEVeg==",
"cpu": [
"x64"
],
@@ -405,12 +422,15 @@
}
},
"node_modules/@github/copilot-linux-arm64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.21.tgz",
- "integrity": "sha512-FL0NsCnHax4czHVv1S8iBqPLGZDhZ28N3+6nT29xWGhmjBWTkIofxLThKUPcyyMsfPTTxIlrdwWa8qQc5z2Q+g==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-arm64/-/copilot-linux-arm64-1.0.55-5.tgz",
+ "integrity": "sha512-UPZ5Y5QotcZvo3f4yFwJVOtAgUT3mq+q2fim82kWa/MA0+EkkADZ3kb+R4OnV1Nqv5EaoZiCFh0Ukk++IMSYwQ==",
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "SEE LICENSE IN LICENSE.md",
"optional": true,
"os": [
@@ -421,12 +441,15 @@
}
},
"node_modules/@github/copilot-linux-x64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.21.tgz",
- "integrity": "sha512-S7pWVI16hesZtxYbIyfw+MHZpc5ESoGKUVr5Y+lZJNaM2340gJGPQzQwSpvKIRMLHRKI2hXLwciAnYeMFxE/Tg==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linux-x64/-/copilot-linux-x64-1.0.55-5.tgz",
+ "integrity": "sha512-Fdwiir53Ogg8C9xv6sTc7/C4vFfQHt6VWFB74kojbDgIbYEpm57wNygQVwJvrwtVW3w/b1MLtGGTp7pEvUBACQ==",
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "SEE LICENSE IN LICENSE.md",
"optional": true,
"os": [
@@ -436,13 +459,51 @@
"copilot-linux-x64": "copilot"
}
},
+ "node_modules/@github/copilot-linuxmusl-arm64": {
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-arm64/-/copilot-linuxmusl-arm64-1.0.55-5.tgz",
+ "integrity": "sha512-NqPmeAA1+iI8Xd4wJUHNNCmVTmHCl+R3nqdXhEVQDLIau9ouGqGGay/91d2ZIgFXJn7J0UTAEdHbdBcfhbnhvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "bin": {
+ "copilot-linuxmusl-arm64": "copilot"
+ }
+ },
+ "node_modules/@github/copilot-linuxmusl-x64": {
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-linuxmusl-x64/-/copilot-linuxmusl-x64-1.0.55-5.tgz",
+ "integrity": "sha512-bOB4vKw1R7Mekn8z34xpNViYUQ4LQAEFzpkyxhc0uOliFmfku/YcIgo42aMWFzf/Bi3iBazBNfCN+L2lz/Jc9A==",
+ "cpu": [
+ "x64"
+ ],
+ "libc": [
+ "musl"
+ ],
+ "license": "SEE LICENSE IN LICENSE.md",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "bin": {
+ "copilot-linuxmusl-x64": "copilot"
+ }
+ },
"node_modules/@github/copilot-sdk": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-0.2.2.tgz",
- "integrity": "sha512-VZCqS08YlUM90bUKJ7VLeIxgTTEHtfXBo84T1IUMNvXRREX2csjPH6Z+CPw3S2468RcCLvzBXcc9LtJJTLIWFw==",
+ "version": "1.0.0-beta.8",
+ "resolved": "https://registry.npmjs.org/@github/copilot-sdk/-/copilot-sdk-1.0.0-beta.8.tgz",
+ "integrity": "sha512-lAuBfH6E5PUaSj8P/0FVMxzvwwBUs02tlvQ56PoJFtuc47KPqzGpf9BS7+h2eEr1UmjoLNJ/yqDiVApH9Oo1Fg==",
"license": "MIT",
"dependencies": {
- "@github/copilot": "^1.0.21",
+ "@github/copilot": "^1.0.55-1",
"vscode-jsonrpc": "^8.2.1",
"zod": "^4.3.6"
},
@@ -451,9 +512,9 @@
}
},
"node_modules/@github/copilot-win32-arm64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.21.tgz",
- "integrity": "sha512-a9qc2Ku+XbyBkXCclbIvBbIVnECACTIWnPctmXWsQeSdeapGxgfHGux7y8hAFV5j6+nhCm6cnyEMS3rkZjAhdA==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-arm64/-/copilot-win32-arm64-1.0.55-5.tgz",
+ "integrity": "sha512-pR2KaiXUanjxolaWgRPlFdeTEpb7jcN1Rk8xVnBCD2ORwERXdYrqXaLCyDbgdplI9mI6IjM+kkUbyXzXoWz/HQ==",
"cpu": [
"arm64"
],
@@ -467,9 +528,9 @@
}
},
"node_modules/@github/copilot-win32-x64": {
- "version": "1.0.21",
- "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.21.tgz",
- "integrity": "sha512-9klu+7NQ6tEyb8sibb0rsbimBivDrnNltZho10Bgbf1wh3o+erTjffXDjW9Zkyaw8lZA9Fz8bqhVkKntZq58Lg==",
+ "version": "1.0.55-5",
+ "resolved": "https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.55-5.tgz",
+ "integrity": "sha512-EuQBgqSnRFjavgeFifbnSYUJ4elTQBLC/kf+WHolrHR2oUGyiqCQZz/cV2DYVSLP1TGxDKAV4AQCM1AdUT1xEA==",
"cpu": [
"x64"
],
@@ -1018,9 +1079,9 @@
}
},
"node_modules/@napi-rs/wasm-runtime": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.3.tgz",
- "integrity": "sha512-xK9sGVbJWYb08+mTJt3/YV24WxvxpXcXtP6B172paPZ+Ts69Re9dAr7lKwJoeIx8OoeuimEiRZ7umkiUVClmmQ==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
+ "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1036,22 +1097,22 @@
}
},
"node_modules/@oxc-project/types": {
- "version": "0.124.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.124.0.tgz",
- "integrity": "sha512-VBFWMTBvHxS11Z5Lvlr3IWgrwhMTXV+Md+EQF0Xf60+wAdsGFTBx7X7K/hP4pi8N7dcm1RvcHwDxZ16Qx8keUg==",
+ "version": "0.132.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.132.0.tgz",
+ "integrity": "sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/Boshen"
}
},
"node_modules/@playwright/test": {
- "version": "1.59.1",
- "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.59.1.tgz",
- "integrity": "sha512-PG6q63nQg5c9rIi4/Z5lR5IVF7yU5MqmKaPOe0HSc0O2cX1fPi96sUQu5j7eo4gKCkB2AnNGoWt7y4/Xx3Kcqg==",
+ "version": "1.60.0",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz",
+ "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.59.1"
+ "playwright": "1.60.0"
},
"bin": {
"playwright": "cli.js"
@@ -1067,9 +1128,9 @@
"license": "MIT"
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.0-rc.15.tgz",
- "integrity": "sha512-YYe6aWruPZDtHNpwu7+qAHEMbQ/yRl6atqb/AhznLTnD3UY99Q1jE7ihLSahNWkF4EqRPVC4SiR4O0UkLK02tA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.2.tgz",
+ "integrity": "sha512-ZS4D1JPGn/MYQN/SYDWftIE/nVsM8j/AFOYEzAoOE2O3NktQOZru+/vYXGbR/qtdLdIfGCP0lcoJiYVzsEz+iQ==",
"cpu": [
"arm64"
],
@@ -1083,9 +1144,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.0-rc.15.tgz",
- "integrity": "sha512-oArR/ig8wNTPYsXL+Mzhs0oxhxfuHRfG7Ikw7jXsw8mYOtk71W0OkF2VEVh699pdmzjPQsTjlD1JIOoHkLP1Fg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.2.tgz",
+ "integrity": "sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==",
"cpu": [
"arm64"
],
@@ -1099,9 +1160,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.0-rc.15.tgz",
- "integrity": "sha512-YzeVqOqjPYvUbJSWJ4EDL8ahbmsIXQpgL3JVipmN+MX0XnXMeWomLN3Fb+nwCmP/jfyqte5I3XRSm7OfQrbyxw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.2.tgz",
+ "integrity": "sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==",
"cpu": [
"x64"
],
@@ -1115,9 +1176,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.0-rc.15.tgz",
- "integrity": "sha512-9Erhx956jeQ0nNTyif1+QWAXDRD38ZNjr//bSHrt6wDwB+QkAfl2q6Mn1k6OBPerznjRmbM10lgRb1Pli4xZPw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.2.tgz",
+ "integrity": "sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==",
"cpu": [
"x64"
],
@@ -1131,9 +1192,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.0-rc.15.tgz",
- "integrity": "sha512-cVwk0w8QbZJGTnP/AHQBs5yNwmpgGYStL88t4UIaqcvYJWBfS0s3oqVLZPwsPU6M0zlW4GqjP0Zq5MnAGwFeGA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.2.tgz",
+ "integrity": "sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==",
"cpu": [
"arm"
],
@@ -1147,12 +1208,15 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.0-rc.15.tgz",
- "integrity": "sha512-eBZ/u8iAK9SoHGanqe/jrPnY0JvBN6iXbVOsbO38mbz+ZJsaobExAm1Iu+rxa4S1l2FjG0qEZn4Rc6X8n+9M+w==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.2.tgz",
+ "integrity": "sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==",
"cpu": [
"arm64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1163,12 +1227,15 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.0-rc.15.tgz",
- "integrity": "sha512-ZvRYMGrAklV9PEkgt4LQM6MjQX2P58HPAuecwYObY2DhS2t35R0I810bKi0wmaYORt6m/2Sm+Z+nFgb0WhXNcQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.2.tgz",
+ "integrity": "sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==",
"cpu": [
"arm64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1179,12 +1246,15 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.0-rc.15.tgz",
- "integrity": "sha512-VDpgGBzgfg5hLg+uBpCLoFG5kVvEyafmfxGUV0UHLcL5irxAK7PKNeC2MwClgk6ZAiNhmo9FLhRYgvMmedLtnQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.2.tgz",
+ "integrity": "sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==",
"cpu": [
"ppc64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1195,12 +1265,15 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.0-rc.15.tgz",
- "integrity": "sha512-y1uXY3qQWCzcPgRJATPSOUP4tCemh4uBdY7e3EZbVwCJTY3gLJWnQABgeUetvED+bt1FQ01OeZwvhLS2bpNrAQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.2.tgz",
+ "integrity": "sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==",
"cpu": [
"s390x"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1211,12 +1284,15 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.0-rc.15.tgz",
- "integrity": "sha512-023bTPBod7J3Y/4fzAN6QtpkSABR0rigtrwaP+qSEabUh5zf6ELr9Nc7GujaROuPY3uwdSIXWrvhn1KxOvurWA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.2.tgz",
+ "integrity": "sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==",
"cpu": [
"x64"
],
+ "libc": [
+ "glibc"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1227,12 +1303,15 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.0-rc.15.tgz",
- "integrity": "sha512-witB2O0/hU4CgfOOKUoeFgQ4GktPi1eEbAhaLAIpgD6+ZnhcPkUtPsoKKHRzmOoWPZue46IThdSgdo4XneOLYw==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.2.tgz",
+ "integrity": "sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==",
"cpu": [
"x64"
],
+ "libc": [
+ "musl"
+ ],
"license": "MIT",
"optional": true,
"os": [
@@ -1243,9 +1322,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.0-rc.15.tgz",
- "integrity": "sha512-UCL68NJ0Ud5zRipXZE9dF5PmirzJE4E4BCIOOssEnM7wLDsxjc6Qb0sGDxTNRTP53I6MZpygyCpY8Aa8sPfKPg==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.2.tgz",
+ "integrity": "sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==",
"cpu": [
"arm64"
],
@@ -1259,27 +1338,27 @@
}
},
"node_modules/@rolldown/binding-wasm32-wasi": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.0-rc.15.tgz",
- "integrity": "sha512-ApLruZq/ig+nhaE7OJm4lDjayUnOHVUa77zGeqnqZ9pn0ovdVbbNPerVibLXDmWeUZXjIYIT8V3xkT58Rm9u5Q==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.2.tgz",
+ "integrity": "sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==",
"cpu": [
"wasm32"
],
"license": "MIT",
"optional": true,
"dependencies": {
- "@emnapi/core": "1.9.2",
- "@emnapi/runtime": "1.9.2",
- "@napi-rs/wasm-runtime": "^1.1.3"
+ "@emnapi/core": "1.10.0",
+ "@emnapi/runtime": "1.10.0",
+ "@napi-rs/wasm-runtime": "^1.1.4"
},
"engines": {
- "node": ">=14.0.0"
+ "node": "^20.19.0 || >=22.12.0"
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.0-rc.15.tgz",
- "integrity": "sha512-KmoUoU7HnN+Si5YWJigfTws1jz1bKBYDQKdbLspz0UaqjjFkddHsqorgiW1mxcAj88lYUE6NC/zJNwT+SloqtA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.2.tgz",
+ "integrity": "sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==",
"cpu": [
"arm64"
],
@@ -1293,9 +1372,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.0-rc.15.tgz",
- "integrity": "sha512-3P2A8L+x75qavWLe/Dll3EYBJLQmtkJN8rfh+U/eR3MqMgL/h98PhYI+JFfXuDPgPeCB7iZAKiqii5vqOvnA0g==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.2.tgz",
+ "integrity": "sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==",
"cpu": [
"x64"
],
@@ -1309,9 +1388,9 @@
}
},
"node_modules/@rolldown/pluginutils": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.15.tgz",
- "integrity": "sha512-UromN0peaE53IaBRe9W7CjrZgXl90fqGpK+mIZbA3qSTeYqg3pqpROBdIPvOG3F5ereDHNwoHBI2e50n1BDr1g==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
"license": "MIT"
},
"node_modules/@rollup/plugin-commonjs": {
@@ -1738,9 +1817,9 @@
"license": "MIT"
},
"node_modules/@sveltejs/acorn-typescript": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.9.tgz",
- "integrity": "sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==",
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.10.tgz",
+ "integrity": "sha512-4WfKk68eTih+MiJD4fSbxN7E8kVBmTMPWHUPYjvl2N0rMs53YLTT8/YjKU5Dtnz5LqDjl7LEw4U7lXR2W3J5WA==",
"license": "MIT",
"peerDependencies": {
"acorn": "^8.9.0"
@@ -1762,17 +1841,17 @@
}
},
"node_modules/@sveltejs/kit": {
- "version": "2.57.1",
- "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.57.1.tgz",
- "integrity": "sha512-VRdSbB96cI1EnRh09CqmnQqP/YJvET5buj8S6k7CxaJqBJD4bw4fRKDjcarAj/eX9k2eHifQfDH8NtOh+ZxxPw==",
+ "version": "2.61.1",
+ "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.61.1.tgz",
+ "integrity": "sha512-Ny8s1SR1TyQS2hD2Rvw0XKzU2Nw1eUF52dTb6T2bdcgz7wSC+Nyb5IwjWYlR4b2dvbbR5NJDiQwHg3rnNseghg==",
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.0.0",
- "@sveltejs/acorn-typescript": "^1.0.5",
+ "@sveltejs/acorn-typescript": "^1.0.9",
"@types/cookie": "^0.6.0",
- "acorn": "^8.14.1",
+ "acorn": "^8.16.0",
"cookie": "^0.6.0",
- "devalue": "^5.6.4",
+ "devalue": "^5.8.1",
"esm-env": "^1.2.2",
"kleur": "^4.1.5",
"magic-string": "^0.30.5",
@@ -1803,9 +1882,9 @@
}
},
"node_modules/@sveltejs/vite-plugin-svelte": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.0.0.tgz",
- "integrity": "sha512-ILXmxC7HAsnkK2eslgPetrqqW1BKSL7LktsFgqzNj83MaivMGZzluWq32m25j2mDOjmSKX7GGWahePhuEs7P/g==",
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-7.1.2.tgz",
+ "integrity": "sha512-DrUBA2UXRfDmUX/ZTiEopd3X40yavsJF1FX2RygcuIScHL7o5YX1fMvoYnDhjeJQC4weCOklirpNWlcb2NiSeA==",
"license": "MIT",
"dependencies": {
"deepmerge": "^4.3.1",
@@ -1842,9 +1921,9 @@
}
},
"node_modules/@tybys/wasm-util": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
- "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==",
+ "version": "0.10.2",
+ "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.2.tgz",
+ "integrity": "sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==",
"license": "MIT",
"optional": true,
"dependencies": {
@@ -1947,13 +2026,13 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "25.6.0",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
- "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
+ "version": "25.9.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.9.1.tgz",
+ "integrity": "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg==",
"devOptional": true,
"license": "MIT",
"dependencies": {
- "undici-types": "~7.19.0"
+ "undici-types": ">=7.24.0 <7.24.7"
}
},
"node_modules/@types/qs": {
@@ -2040,28 +2119,15 @@
"@types/node": "*"
}
},
- "node_modules/@typescript-eslint/types": {
- "version": "8.58.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.58.1.tgz",
- "integrity": "sha512-io/dV5Aw5ezwzfPBBWLoT+5QfVtP8O7q4Kftjn5azJ88bYyp/ZMCsyW1lpKK46EXJcaYMZ1JtYj+s/7TdzmQMw==",
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
"node_modules/@vitest/coverage-v8": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.5.tgz",
- "integrity": "sha512-38C0/Ddb7HcRG0Z4/DUem8x57d2p9jYgp18mkaYswEOQBGsI1CG4f/hjm0ZCeaJfWhSZ4k7jgs29V1Zom7Ki9A==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-4.1.7.tgz",
+ "integrity": "sha512-qsYPeXc5Q9dFLd1i8Ap+Bx8sQgcp+rFVQo4R0dDsWNBzl26ldVF1qOO+RL24K7FDrR6pA+50XedRLSoSG24bVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@bcoe/v8-coverage": "^1.0.2",
- "@vitest/utils": "4.1.5",
+ "@vitest/utils": "4.1.7",
"ast-v8-to-istanbul": "^1.0.0",
"istanbul-lib-coverage": "^3.2.2",
"istanbul-lib-report": "^3.0.1",
@@ -2075,8 +2141,8 @@
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "@vitest/browser": "4.1.5",
- "vitest": "4.1.5"
+ "@vitest/browser": "4.1.7",
+ "vitest": "4.1.7"
},
"peerDependenciesMeta": {
"@vitest/browser": {
@@ -2085,16 +2151,16 @@
}
},
"node_modules/@vitest/expect": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.5.tgz",
- "integrity": "sha512-PWBaRY5JoKuRnHlUHfpV/KohFylaDZTupcXN1H9vYryNLOnitSw60Mw9IAE2r67NbwwzBw/Cc/8q9BK3kIX8Kw==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.1.7.tgz",
+ "integrity": "sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"@types/chai": "^5.2.2",
- "@vitest/spy": "4.1.5",
- "@vitest/utils": "4.1.5",
+ "@vitest/spy": "4.1.7",
+ "@vitest/utils": "4.1.7",
"chai": "^6.2.2",
"tinyrainbow": "^3.1.0"
},
@@ -2103,13 +2169,13 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.5.tgz",
- "integrity": "sha512-/x2EmFC4mT4NNzqvC3fmesuV97w5FC903KPmey4gsnJiMQ3Be1IlDKVaDaG8iqaLFHqJ2FVEkxZk5VmeLjIItw==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.1.7.tgz",
+ "integrity": "sha512-vY7nuamKgfvpA1Koa3oYIw/k7D6kZnpGyNMZW8loow2bsBYla1TFdqTaXncWdRn4pgwNs+90RhnXhJScDwQeJA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/spy": "4.1.5",
+ "@vitest/spy": "4.1.7",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21"
},
@@ -2140,9 +2206,9 @@
}
},
"node_modules/@vitest/pretty-format": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.5.tgz",
- "integrity": "sha512-7I3q6l5qr03dVfMX2wCo9FxwSJbPdwKjy2uu/YPpU3wfHvIL4QHwVRp57OfGrDFeUJ8/8QdfBKIV12FTtLn00g==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.1.7.tgz",
+ "integrity": "sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -2153,13 +2219,13 @@
}
},
"node_modules/@vitest/runner": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.5.tgz",
- "integrity": "sha512-2D+o7Pr82IEO46YPpoA/YU0neeyr6FTerQb5Ro7BUnBuv6NQtT/kmVnczngiMEBhzgqz2UZYl5gArejsyERDSQ==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.1.7.tgz",
+ "integrity": "sha512-BapjmAQ2aI78WdMEfeUWivnfVzB+VPGwWRQcJE0OUq7qEeEcBsCSf+0T5iREBNE5nBb4wA5Ya0W6IA+sghdEFw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/utils": "4.1.5",
+ "@vitest/utils": "4.1.7",
"pathe": "^2.0.3"
},
"funding": {
@@ -2167,14 +2233,14 @@
}
},
"node_modules/@vitest/snapshot": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.5.tgz",
- "integrity": "sha512-zypXEt4KH/XgKGPUz4eC2AvErYx0My5hfL8oDb1HzGFpEk1P62bxSohdyOmvz+d9UJwanI68MKwr2EquOaOgMQ==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.1.7.tgz",
+ "integrity": "sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.1.5",
- "@vitest/utils": "4.1.5",
+ "@vitest/pretty-format": "4.1.7",
+ "@vitest/utils": "4.1.7",
"magic-string": "^0.30.21",
"pathe": "^2.0.3"
},
@@ -2183,9 +2249,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.5.tgz",
- "integrity": "sha512-2lNOsh6+R2Idnf1TCZqSwYlKN2E/iDlD8sgU59kYVl+OMDmvldO1VDk39smRfpUNwYpNRVn3w4YfuC7KfbBnkQ==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.1.7.tgz",
+ "integrity": "sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==",
"dev": true,
"license": "MIT",
"funding": {
@@ -2193,13 +2259,13 @@
}
},
"node_modules/@vitest/utils": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.5.tgz",
- "integrity": "sha512-76wdkrmfXfqGjueGgnb45ITPyUi1ycZ4IHgC2bhPDUfWHklY/q3MdLOAB+TF1e6xfl8NxNY0ZYaPCFNWSsw3Ug==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.1.7.tgz",
+ "integrity": "sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/pretty-format": "4.1.5",
+ "@vitest/pretty-format": "4.1.7",
"convert-source-map": "^2.0.0",
"tinyrainbow": "^3.1.0"
},
@@ -2244,6 +2310,32 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "6.2.3",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
+ "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
"node_modules/aria-query": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz",
@@ -2409,23 +2501,6 @@
"node": ">=6"
}
},
- "node_modules/colorette": {
- "version": "2.0.20",
- "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
- "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/commander": {
- "version": "14.0.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz",
- "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=20"
- }
- },
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
@@ -2529,9 +2604,9 @@
}
},
"node_modules/devalue": {
- "version": "5.6.4",
- "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.4.tgz",
- "integrity": "sha512-Gp6rDldRsFh/7XuouDbxMH3Mx8GMCcgzIb1pDTvNyn8pZGQ22u+Wa+lGV9dQCltFQ7uVw0MhRyb8XDskNFOReA==",
+ "version": "5.8.1",
+ "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.8.1.tgz",
+ "integrity": "sha512-4CXDYRBGqN+57wVJkuXBYmpAVUSg3L6JAQa/DFqm238G73E1wuyc/JhGQJzN7vUf/CMphYau2zXbfWzDR5aTEw==",
"license": "MIT"
},
"node_modules/dom-accessibility-api": {
@@ -2542,9 +2617,9 @@
"license": "MIT"
},
"node_modules/dompurify": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.0.tgz",
- "integrity": "sha512-nolgK9JcaUXMSmW+j1yaSvaEaoXYHwWyGJlkoCTghc97KgGDDSnpoU/PlEnw63Ah+TGKFOyY+X5LnxaWbCSfXg==",
+ "version": "3.4.7",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.7.tgz",
+ "integrity": "sha512-2jBxDJY4RR06tQNy4w5FlFH7kfxsQZlufd0sbv+chfHCxeJwrFw2baUDsSwvBISD4K4RDbd0PTfy3uNXsR6siA==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
@@ -2580,13 +2655,13 @@
"license": "MIT"
},
"node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz",
+ "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
- "node": ">=0.12"
+ "node": ">=20.19.0"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
@@ -2619,13 +2694,20 @@
"license": "MIT"
},
"node_modules/esrap": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.4.tgz",
- "integrity": "sha512-suICpxAmZ9A8bzJjEl/+rLJiDKC0X4gYWUxT6URAWBLvlXmtbZd5ySMu/N2ZGEtMCAmflUDPSehrP9BQcsGcSg==",
+ "version": "2.2.9",
+ "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.9.tgz",
+ "integrity": "sha512-4KijP+NxCWthMCUC3qHbE6n4vCjqgJS1uAYKhuT/GWfFTf1Qyive2TgOjep+gzbSzRfnNyaN/UU9YmdOt8Eg0A==",
"license": "MIT",
"dependencies": {
- "@jridgewell/sourcemap-codec": "^1.4.15",
+ "@jridgewell/sourcemap-codec": "^1.4.15"
+ },
+ "peerDependencies": {
"@typescript-eslint/types": "^8.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@typescript-eslint/types": {
+ "optional": true
+ }
}
},
"node_modules/estree-walker": {
@@ -2726,9 +2808,9 @@
}
},
"node_modules/get-east-asian-width": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz",
- "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.6.0.tgz",
+ "integrity": "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2978,28 +3060,28 @@
}
},
"node_modules/jsdom": {
- "version": "29.0.2",
- "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.0.2.tgz",
- "integrity": "sha512-9VnGEBosc/ZpwyOsJBCQ/3I5p7Q5ngOY14a9bf5btenAORmZfDse1ZEheMiWcJ3h81+Fv7HmJFdS0szo/waF2w==",
+ "version": "29.1.1",
+ "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz",
+ "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@asamuzakjp/css-color": "^5.1.5",
- "@asamuzakjp/dom-selector": "^7.0.6",
+ "@asamuzakjp/css-color": "^5.1.11",
+ "@asamuzakjp/dom-selector": "^7.1.1",
"@bramus/specificity": "^2.4.2",
- "@csstools/css-syntax-patches-for-csstree": "^1.1.1",
+ "@csstools/css-syntax-patches-for-csstree": "^1.1.3",
"@exodus/bytes": "^1.15.0",
"css-tree": "^3.2.1",
"data-urls": "^7.0.0",
"decimal.js": "^10.6.0",
"html-encoding-sniffer": "^6.0.0",
"is-potential-custom-element-name": "^1.0.1",
- "lru-cache": "^11.2.7",
- "parse5": "^8.0.0",
+ "lru-cache": "^11.3.5",
+ "parse5": "^8.0.1",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
"tough-cookie": "^6.0.1",
- "undici": "^7.24.5",
+ "undici": "^7.25.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^8.0.1",
"whatwg-mimetype": "^5.0.0",
@@ -3319,45 +3401,45 @@
}
},
"node_modules/lint-staged": {
- "version": "16.4.0",
- "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz",
- "integrity": "sha512-lBWt8hujh/Cjysw5GYVmZpFHXDCgZzhrOm8vbcUdobADZNOK/bRshr2kM3DfgrrtR1DQhfupW9gnIXOfiFi+bw==",
+ "version": "17.0.5",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-17.0.5.tgz",
+ "integrity": "sha512-d12yC+/e8RhBjZtaxZn71FyrgU/P5e+uAPifhCLwdosQZP/zamSdKRWDC30ocVIbzDKiFG1McHc/LUgB92GIPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "commander": "^14.0.3",
- "listr2": "^9.0.5",
- "picomatch": "^4.0.3",
+ "listr2": "^10.2.1",
+ "picomatch": "^4.0.4",
"string-argv": "^0.3.2",
- "tinyexec": "^1.0.4",
- "yaml": "^2.8.2"
+ "tinyexec": "^1.1.2"
},
"bin": {
"lint-staged": "bin/lint-staged.js"
},
"engines": {
- "node": ">=20.17"
+ "node": ">=22.22.1"
},
"funding": {
"url": "https://opencollective.com/lint-staged"
+ },
+ "optionalDependencies": {
+ "yaml": "^2.8.4"
}
},
"node_modules/listr2": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/listr2/-/listr2-9.0.5.tgz",
- "integrity": "sha512-ME4Fb83LgEgwNw96RKNvKV4VTLuXfoKudAmm2lP8Kk87KaMK0/Xrx/aAkMWmT8mDb+3MlFDspfbCs7adjRxA2g==",
+ "version": "10.2.1",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-10.2.1.tgz",
+ "integrity": "sha512-7I5knELsJKTUjXG+A6BkKAiGkW1i25fNa/xlUl9hFtk15WbE9jndA89xu5FzQKrY5llajE1hfZZFMILXkDHk/Q==",
"dev": true,
"license": "MIT",
"dependencies": {
- "cli-truncate": "^5.0.0",
- "colorette": "^2.0.20",
- "eventemitter3": "^5.0.1",
+ "cli-truncate": "^5.2.0",
+ "eventemitter3": "^5.0.4",
"log-update": "^6.1.0",
"rfdc": "^1.4.1",
- "wrap-ansi": "^9.0.0"
+ "wrap-ansi": "^10.0.0"
},
"engines": {
- "node": ">=20.0.0"
+ "node": ">=22.13.0"
}
},
"node_modules/locate-character": {
@@ -3386,34 +3468,57 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/log-update/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
+ "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==",
"dev": true,
"license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "is-fullwidth-code-point": "^5.0.0"
+ },
"engines": {
- "node": ">=12"
+ "node": ">=18"
},
"funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
- "node_modules/log-update/node_modules/slice-ansi": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz",
- "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==",
+ "node_modules/log-update/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "9.0.2",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
+ "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^6.2.1",
- "is-fullwidth-code-point": "^5.0.0"
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/lru-cache": {
@@ -3473,9 +3578,9 @@
}
},
"node_modules/marked": {
- "version": "18.0.2",
- "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.2.tgz",
- "integrity": "sha512-NsmlUYBS/Zg57rgDWMYdnre6OTj4e+qq/JS2ot3KrYLSoHLw+sDu0Nm1ZGpRgYAq6c+b1ekaY5NzVchMCQnzcg==",
+ "version": "18.0.4",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-18.0.4.tgz",
+ "integrity": "sha512-c/BTaKzg0G6ezQx97DAkYU7k0HM6ys0FqYeKBL6hlBByZwy+ycA1+f0vDdjMHKKeEjdgkx0GOv9Il6D+85cOqA==",
"license": "MIT",
"bin": {
"marked": "bin/marked.js"
@@ -3554,9 +3659,9 @@
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
"node_modules/nanoid": {
- "version": "3.3.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
- "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"funding": [
{
"type": "github",
@@ -3615,13 +3720,13 @@
}
},
"node_modules/parse5": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
- "integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
+ "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==",
"dev": true,
"license": "MIT",
"dependencies": {
- "entities": "^6.0.0"
+ "entities": "^8.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
@@ -3667,13 +3772,13 @@
}
},
"node_modules/playwright": {
- "version": "1.59.1",
- "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.59.1.tgz",
- "integrity": "sha512-C8oWjPR3F81yljW9o5OxcWzfh6avkVwDD2VYdwIGqTkl+OGFISgypqzfu7dOe4QNLL2aqcWBmI3PMtLIK233lw==",
+ "version": "1.60.0",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz",
+ "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.59.1"
+ "playwright-core": "1.60.0"
},
"bin": {
"playwright": "cli.js"
@@ -3686,9 +3791,9 @@
}
},
"node_modules/playwright-core": {
- "version": "1.59.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.59.1.tgz",
- "integrity": "sha512-HBV/RJg81z5BiiZ9yPzIiClYV/QMsDCKUyogwH9p3MCP6IYjUFu/MActgYAvK0oWyV9NlwM3GLBjADyWgydVyg==",
+ "version": "1.60.0",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz",
+ "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -3714,9 +3819,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.8",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
- "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+ "version": "8.5.15",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
+ "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
"funding": [
{
"type": "opencollective",
@@ -3733,7 +3838,7 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.11",
+ "nanoid": "^3.3.12",
"picocolors": "^1.1.1",
"source-map-js": "^1.2.1"
},
@@ -3864,13 +3969,13 @@
"license": "MIT"
},
"node_modules/rolldown": {
- "version": "1.0.0-rc.15",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.0-rc.15.tgz",
- "integrity": "sha512-Ff31guA5zT6WjnGp0SXw76X6hzGRk/OQq2hE+1lcDe+lJdHSgnSX6nK3erbONHyCbpSj9a9E+uX/OvytZoWp2g==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.0.2.tgz",
+ "integrity": "sha512-oZx5zVDtVB44AW3eaifgDml1gWRDZGvjcfdxonE4swNPG98PrrXjaO/KrnUjzlMnztCCRVlUueA1kCXhARGk6g==",
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.124.0",
- "@rolldown/pluginutils": "1.0.0-rc.15"
+ "@oxc-project/types": "=0.132.0",
+ "@rolldown/pluginutils": "^1.0.0"
},
"bin": {
"rolldown": "bin/cli.mjs"
@@ -3879,21 +3984,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm64": "1.0.0-rc.15",
- "@rolldown/binding-darwin-arm64": "1.0.0-rc.15",
- "@rolldown/binding-darwin-x64": "1.0.0-rc.15",
- "@rolldown/binding-freebsd-x64": "1.0.0-rc.15",
- "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.15",
- "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.15",
- "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.15",
- "@rolldown/binding-linux-ppc64-gnu": "1.0.0-rc.15",
- "@rolldown/binding-linux-s390x-gnu": "1.0.0-rc.15",
- "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.15",
- "@rolldown/binding-linux-x64-musl": "1.0.0-rc.15",
- "@rolldown/binding-openharmony-arm64": "1.0.0-rc.15",
- "@rolldown/binding-wasm32-wasi": "1.0.0-rc.15",
- "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.15",
- "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.15"
+ "@rolldown/binding-android-arm64": "1.0.2",
+ "@rolldown/binding-darwin-arm64": "1.0.2",
+ "@rolldown/binding-darwin-x64": "1.0.2",
+ "@rolldown/binding-freebsd-x64": "1.0.2",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.0.2",
+ "@rolldown/binding-linux-arm64-gnu": "1.0.2",
+ "@rolldown/binding-linux-arm64-musl": "1.0.2",
+ "@rolldown/binding-linux-ppc64-gnu": "1.0.2",
+ "@rolldown/binding-linux-s390x-gnu": "1.0.2",
+ "@rolldown/binding-linux-x64-gnu": "1.0.2",
+ "@rolldown/binding-linux-x64-musl": "1.0.2",
+ "@rolldown/binding-openharmony-arm64": "1.0.2",
+ "@rolldown/binding-wasm32-wasi": "1.0.2",
+ "@rolldown/binding-win32-arm64-msvc": "1.0.2",
+ "@rolldown/binding-win32-x64-msvc": "1.0.2"
}
},
"node_modules/rollup": {
@@ -4115,19 +4220,6 @@
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
- "node_modules/slice-ansi/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
"node_modules/source-map-js": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -4162,9 +4254,9 @@
}
},
"node_modules/string-width": {
- "version": "8.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.0.tgz",
- "integrity": "sha512-6hJPQ8N0V0P3SNmP6h2J99RLuzrWz2gvT7VnK5tKvrNqJoyS9W4/Fb8mo31UiPvy00z7DQXkP2hnKBVav76thw==",
+ "version": "8.2.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-8.2.1.tgz",
+ "integrity": "sha512-IIaP0g3iy9Cyy18w3M9YcaDudujEAVHKt3a3QJg1+sr/oX96TbaGUubG0hJyCjCBThFH+tFpcIyoUHUn1ogaLA==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4194,19 +4286,6 @@
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/strip-ansi/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
"node_modules/strip-indent": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
@@ -4246,23 +4325,23 @@
}
},
"node_modules/svelte": {
- "version": "5.55.4",
- "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.4.tgz",
- "integrity": "sha512-q8DFohk6vUswSng95IZb9nzWJnbINZsK7OiM1snAa3qCjJBL0ZQpvMyAaVXjUukdM75J/m8UE8xwqat8Ors/zQ==",
+ "version": "5.55.9",
+ "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.55.9.tgz",
+ "integrity": "sha512-fTjjT8cHLDwigcu2j3pv7Jq04LklXevPB8uBgyHNiTXv+RMNvVnrjS4UEYrLMkhuq1vpCodHjiW+z/95SDs/fg==",
"license": "MIT",
"dependencies": {
"@jridgewell/remapping": "^2.3.4",
"@jridgewell/sourcemap-codec": "^1.5.0",
- "@sveltejs/acorn-typescript": "^1.0.5",
+ "@sveltejs/acorn-typescript": "^1.0.10",
"@types/estree": "^1.0.5",
"@types/trusted-types": "^2.0.7",
"acorn": "^8.12.1",
"aria-query": "5.3.1",
"axobject-query": "^4.1.0",
"clsx": "^2.1.1",
- "devalue": "^5.6.4",
+ "devalue": "^5.8.1",
"esm-env": "^1.2.1",
- "esrap": "^2.2.4",
+ "esrap": "^2.2.9",
"is-reference": "^3.0.3",
"locate-character": "^3.0.0",
"magic-string": "^0.30.11",
@@ -4273,9 +4352,9 @@
}
},
"node_modules/svelte-check": {
- "version": "4.4.6",
- "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.6.tgz",
- "integrity": "sha512-kP1zG81EWaFe9ZyTv4ZXv44Csi6Pkdpb7S3oj6m+K2ec/IcDg/a8LsFsnVLqm2nxtkSwsd5xPj/qFkTBgXHXjg==",
+ "version": "4.4.8",
+ "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-4.4.8.tgz",
+ "integrity": "sha512-67adfgBox5eNSNIvIIwgFizKGdcRrGpiMoNO2obHcYuLz7iTa8Xgm/NGU3ntMFnNm8K1grFOIG6HhMLX/vcN8w==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -4320,9 +4399,9 @@
"license": "MIT"
},
"node_modules/tinyexec": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.4.tgz",
- "integrity": "sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.2.2.tgz",
+ "integrity": "sha512-M/Q0B2cp4K7kynaT/vnED1j8TlLY+Pp7C6Wl2bl/7u/F0mUVwdyOpwomQb8JpYLitHUssAJRmLZdMCGsrx7i+g==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4330,13 +4409,13 @@
}
},
"node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
"license": "MIT",
"dependencies": {
"fdir": "^6.5.0",
- "picomatch": "^4.0.3"
+ "picomatch": "^4.0.4"
},
"engines": {
"node": ">=12.0.0"
@@ -4452,9 +4531,9 @@
}
},
"node_modules/undici": {
- "version": "7.24.5",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.24.5.tgz",
- "integrity": "sha512-3IWdCpjgxp15CbJnsi/Y9TCDE7HWVN19j1hmzVhoAkY/+CJx449tVxT5wZc1Gwg8J+P0LWvzlBzxYRnHJ+1i7Q==",
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.26.0.tgz",
+ "integrity": "sha512-3O9Tf67pGhgOv9jM35AbhkXAKi13f3oy3aE4CSgr+TckGeY+/iu97ZXN+J7DpHPzLbVApFd1IFhcnBjREYXYcg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -4462,9 +4541,9 @@
}
},
"node_modules/undici-types": {
- "version": "7.19.2",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
- "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
+ "version": "7.24.6",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz",
+ "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==",
"devOptional": true,
"license": "MIT"
},
@@ -4478,16 +4557,16 @@
}
},
"node_modules/vite": {
- "version": "8.0.8",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.8.tgz",
- "integrity": "sha512-dbU7/iLVa8KZALJyLOBOQ88nOXtNG8vxKuOT4I2mD+Ya70KPceF4IAmDsmU0h1Qsn5bPrvsY9HJstCRh3hG6Uw==",
+ "version": "8.0.14",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.0.14.tgz",
+ "integrity": "sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==",
"license": "MIT",
"dependencies": {
"lightningcss": "^1.32.0",
"picomatch": "^4.0.4",
- "postcss": "^8.5.8",
- "rolldown": "1.0.0-rc.15",
- "tinyglobby": "^0.2.15"
+ "postcss": "^8.5.15",
+ "rolldown": "1.0.2",
+ "tinyglobby": "^0.2.16"
},
"bin": {
"vite": "bin/vite.js"
@@ -4503,7 +4582,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.1.0",
+ "@vitejs/devtools": "^0.1.18",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -4574,19 +4653,19 @@
}
},
"node_modules/vitest": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.5.tgz",
- "integrity": "sha512-9Xx1v3/ih3m9hN+SbfkUyy0JAs72ap3r7joc87XL6jwF0jGg6mFBvQ1SrwaX+h8BlkX6Hz9shdd1uo6AF+ZGpg==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.1.7.tgz",
+ "integrity": "sha512-flYyaFd2CgoCoU+0UKt3pxksgC+S02iTDN0n3LtqaMeXsI9SBcdNujc2k0DeFLzUn/0k538yNjOSdwgCqcrwJA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@vitest/expect": "4.1.5",
- "@vitest/mocker": "4.1.5",
- "@vitest/pretty-format": "4.1.5",
- "@vitest/runner": "4.1.5",
- "@vitest/snapshot": "4.1.5",
- "@vitest/spy": "4.1.5",
- "@vitest/utils": "4.1.5",
+ "@vitest/expect": "4.1.7",
+ "@vitest/mocker": "4.1.7",
+ "@vitest/pretty-format": "4.1.7",
+ "@vitest/runner": "4.1.7",
+ "@vitest/snapshot": "4.1.7",
+ "@vitest/spy": "4.1.7",
+ "@vitest/utils": "4.1.7",
"es-module-lexer": "^2.0.0",
"expect-type": "^1.3.0",
"magic-string": "^0.30.21",
@@ -4614,12 +4693,12 @@
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "4.1.5",
- "@vitest/browser-preview": "4.1.5",
- "@vitest/browser-webdriverio": "4.1.5",
- "@vitest/coverage-istanbul": "4.1.5",
- "@vitest/coverage-v8": "4.1.5",
- "@vitest/ui": "4.1.5",
+ "@vitest/browser-playwright": "4.1.7",
+ "@vitest/browser-preview": "4.1.7",
+ "@vitest/browser-webdriverio": "4.1.7",
+ "@vitest/coverage-istanbul": "4.1.7",
+ "@vitest/coverage-v8": "4.1.7",
+ "@vitest/ui": "4.1.7",
"happy-dom": "*",
"jsdom": "*",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
@@ -4756,54 +4835,23 @@
}
},
"node_modules/wrap-ansi": {
- "version": "9.0.2",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz",
- "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-10.0.0.tgz",
+ "integrity": "sha512-SGcvg80f0wUy2/fXES19feHMz8E0JoXv2uNgHOu4Dgi2OrCy1lqwFYEJz1BLbDI0exjPMe/ZdzZ/YpGECBG/aQ==",
"dev": true,
"license": "MIT",
"dependencies": {
- "ansi-styles": "^6.2.1",
- "string-width": "^7.0.0",
- "strip-ansi": "^7.1.0"
+ "ansi-styles": "^6.2.3",
+ "string-width": "^8.2.0",
+ "strip-ansi": "^7.1.2"
},
"engines": {
- "node": ">=18"
+ "node": ">=20"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
- "node_modules/wrap-ansi/node_modules/ansi-styles": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz",
- "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/wrap-ansi/node_modules/string-width": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
- "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "emoji-regex": "^10.3.0",
- "get-east-asian-width": "^1.0.0",
- "strip-ansi": "^7.1.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/write-file-atomic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
@@ -4817,9 +4865,10 @@
}
},
"node_modules/ws": {
- "version": "8.19.0",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
- "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+ "version": "8.21.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
+ "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
+ "license": "MIT",
"engines": {
"node": ">=10.0.0"
},
@@ -4854,11 +4903,11 @@
"license": "MIT"
},
"node_modules/yaml": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz",
- "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==",
- "devOptional": true,
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz",
+ "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==",
"license": "ISC",
+ "optional": true,
"bin": {
"yaml": "bin.mjs"
},
diff --git a/package.json b/package.json
index 8899064..1ae2135 100644
--- a/package.json
+++ b/package.json
@@ -38,19 +38,19 @@
"node": ">=24.0.0"
},
"dependencies": {
- "@github/copilot-sdk": "^0.2.2",
+ "@github/copilot-sdk": "1.0.0-beta.8",
"@sveltejs/adapter-node": "^5.5.4",
- "@sveltejs/kit": "^2.57.1",
- "dompurify": "^3.4.0",
+ "@sveltejs/kit": "^2.61.1",
+ "dompurify": "^3.4.7",
"express-session": "^1.18.0",
"highlight.js": "^11.11.1",
"lucide-svelte": "^1.0.1",
- "marked": "^18.0.2",
+ "marked": "^18.0.4",
"session-file-store": "^1.5.0",
- "svelte": "^5.55.4",
- "vite": "^8.0.8",
+ "svelte": "^5.55.9",
+ "vite": "^8.0.14",
"web-push": "^3.6.7",
- "ws": "^8.18.0"
+ "ws": "^8.21.0"
},
"lint-staged": {
"*.{ts,svelte}": [
@@ -61,21 +61,21 @@
"cookie": "^0.7.0"
},
"devDependencies": {
- "@playwright/test": "^1.59.1",
- "@sveltejs/vite-plugin-svelte": "^7.0.0",
+ "@playwright/test": "^1.60.0",
+ "@sveltejs/vite-plugin-svelte": "^7.1.2",
"@testing-library/jest-dom": "^6.9.1",
"@types/express-session": "^1.19.0",
- "@types/node": "^25.6.0",
+ "@types/node": "^25.7.0",
"@types/session-file-store": "^1.2.6",
"@types/web-push": "^3.6.4",
"@types/ws": "^8.5.13",
- "@vitest/coverage-v8": "^4.1.5",
+ "@vitest/coverage-v8": "^4.1.6",
"dotenv": "^17.4.2",
"husky": "^9.1.7",
- "jsdom": "^29.0.2",
- "lint-staged": "^16.4.0",
+ "jsdom": "^29.1.1",
+ "lint-staged": "^17.0.4",
"sharp": "^0.34.5",
- "svelte-check": "^4.4.6",
+ "svelte-check": "^4.4.8",
"typescript": "^6.0.3",
"vitest": "^4.1.3"
}
diff --git a/src/lib/server/config.ts b/src/lib/server/config.ts
index bb86b3e..597f090 100644
--- a/src/lib/server/config.ts
+++ b/src/lib/server/config.ts
@@ -40,6 +40,7 @@ function getConfig() {
otelEndpoint: process.env.OTEL_ENDPOINT?.trim() || '',
otelCaptureContent: process.env.OTEL_CAPTURE_CONTENT === 'true',
otelSourceName: env('OTEL_SOURCE_NAME', 'copilot-unleashed'),
+ enableRemoteSessions: process.env.ENABLE_REMOTE_SESSIONS?.trim().toLowerCase() !== 'false',
};
}
diff --git a/src/lib/server/copilot/client.ts b/src/lib/server/copilot/client.ts
index 9b65551..37bc096 100644
--- a/src/lib/server/copilot/client.ts
+++ b/src/lib/server/copilot/client.ts
@@ -1,5 +1,5 @@
import { homedir } from 'node:os';
-import { CopilotClient } from '@github/copilot-sdk';
+import { CopilotClient, RuntimeConnection } from '@github/copilot-sdk';
import type { TelemetryConfig } from '@github/copilot-sdk';
import { config } from '../config.js';
@@ -13,20 +13,14 @@ function buildTelemetryConfig(): TelemetryConfig | undefined {
}
export function createCopilotClient(githubToken: string, configDir?: string): CopilotClient {
- const clientEnv: Record = { ...process.env, GH_TOKEN: githubToken };
-
- // When configDir is set, pass COPILOT_HOME to the CLI subprocess so it
- // reads and writes session state from the same directory as the CLI.
- if (configDir) {
- clientEnv.COPILOT_HOME = configDir;
- }
-
const telemetry = buildTelemetryConfig();
return new CopilotClient({
- githubToken,
- env: clientEnv,
- cwd: config.copilotCwd || homedir(),
+ connection: RuntimeConnection.forStdio(),
+ gitHubToken: githubToken,
+ workingDirectory: config.copilotCwd || homedir(),
+ ...(configDir && { baseDirectory: configDir }),
...(telemetry && { telemetry }),
+ enableRemoteSessions: config.enableRemoteSessions,
});
}
diff --git a/src/lib/server/copilot/session-fs.ts b/src/lib/server/copilot/session-fs.ts
deleted file mode 100644
index 5134f50..0000000
--- a/src/lib/server/copilot/session-fs.ts
+++ /dev/null
@@ -1,108 +0,0 @@
-import { readFile, writeFile, appendFile, stat, mkdir, readdir, rm, rename, access } from 'node:fs/promises';
-import { join, resolve, relative } from 'node:path';
-import type { SessionFsHandler } from '@github/copilot-sdk';
-import type { CopilotSession } from '@github/copilot-sdk';
-
-/**
- * Creates a SessionFsHandler scoped to the session workspace directory.
- * All path operations are sandboxed — attempts to escape the workspace are rejected.
- */
-export function createSessionFsHandlerFactory(workspaceRoot: string) {
- return (session: CopilotSession): SessionFsHandler => {
- // Scope to per-session directory to prevent cross-session access
- const sessionDir = join(workspaceRoot, session.sessionId ?? 'default');
-
- function safePath(requestedPath: string): string {
- if (requestedPath !== requestedPath.normalize()) {
- throw new Error(`Path traversal blocked: ${requestedPath}`);
- }
- const resolved = resolve(sessionDir, requestedPath);
- const rel = relative(sessionDir, resolved);
- if (rel.startsWith('..') || resolve(rel) !== rel) {
- throw new Error(`Path traversal blocked: ${requestedPath}`);
- }
- return resolved;
- }
-
- return {
- async readFile(params) {
- const filePath = safePath(params.path);
- const content = await readFile(filePath, 'utf8');
- return { content };
- },
-
- async writeFile(params) {
- const filePath = safePath(params.path);
- const dir = join(filePath, '..');
- await mkdir(dir, { recursive: true });
- await writeFile(filePath, params.content, {
- encoding: 'utf8',
- ...(params.mode != null ? { mode: params.mode } : {}),
- });
- },
-
- async appendFile(params) {
- const filePath = safePath(params.path);
- await appendFile(filePath, params.content, 'utf8');
- },
-
- async exists(params) {
- const filePath = safePath(params.path);
- try {
- await access(filePath);
- return { exists: true };
- } catch {
- return { exists: false };
- }
- },
-
- async stat(params) {
- const filePath = safePath(params.path);
- const s = await stat(filePath);
- return {
- size: s.size,
- isFile: s.isFile(),
- isDirectory: s.isDirectory(),
- mtime: s.mtime.toISOString(),
- birthtime: s.birthtime.toISOString(),
- };
- },
-
- async mkdir(params) {
- const dirPath = safePath(params.path);
- await mkdir(dirPath, { recursive: params.recursive ?? true });
- },
-
- async readdir(params) {
- const dirPath = safePath(params.path);
- const entries = await readdir(dirPath);
- return { entries };
- },
-
- async readdirWithTypes(params) {
- const dirPath = safePath(params.path);
- const dirents = await readdir(dirPath, { withFileTypes: true });
- return {
- entries: dirents.map(d => ({
- name: d.name,
- type: d.isDirectory() ? 'directory' as const : 'file' as const,
- })),
- };
- },
-
- async rm(params) {
- const filePath = safePath(params.path);
- await rm(filePath, {
- recursive: params.recursive ?? false,
- force: params.force ?? false,
- });
- },
-
- async rename(params) {
- const oldPath = safePath(params.src);
- const newPath = safePath(params.dest);
- await rename(oldPath, newPath);
- },
- };
- };
-}
diff --git a/src/lib/server/copilot/session.test.ts b/src/lib/server/copilot/session.test.ts
index 4f7e7f5..f993757 100644
--- a/src/lib/server/copilot/session.test.ts
+++ b/src/lib/server/copilot/session.test.ts
@@ -437,6 +437,36 @@ describe('createCopilotSession', () => {
expect(config.hooks).toBeUndefined();
});
+ it('threads remoteSession=on into the SDK session config', async () => {
+ const client = createClientMock();
+
+ await createCopilotSession(client as unknown as Parameters[0], 'gh-token', {
+ remoteSession: 'on',
+ });
+
+ expect(getSessionConfig(client).remoteSession).toBe('on');
+ });
+
+ it('threads remoteSession=export into the SDK session config', async () => {
+ const client = createClientMock();
+
+ await createCopilotSession(client as unknown as Parameters[0], 'gh-token', {
+ remoteSession: 'export',
+ });
+
+ expect(getSessionConfig(client).remoteSession).toBe('export');
+ });
+
+ it('omits remoteSession when set to "off" (local-only)', async () => {
+ const client = createClientMock();
+
+ await createCopilotSession(client as unknown as Parameters[0], 'gh-token', {
+ remoteSession: 'off',
+ });
+
+ expect(getSessionConfig(client).remoteSession).toBeUndefined();
+ });
+
});
describe('buildSessionHooks', () => {
@@ -445,7 +475,7 @@ describe('buildSessionHooks', () => {
const hooks = buildSessionHooks(callback);
hooks!.onPreToolUse!(
- { toolName: 'bash', toolArgs: { command: 'ls' }, timestamp: 1, cwd: '/tmp' },
+ { toolName: 'bash', toolArgs: { command: 'ls' }, timestamp: new Date(1), sessionId: 's1', workingDirectory: '/tmp' },
{ sessionId: 's1' },
);
@@ -461,7 +491,7 @@ describe('buildSessionHooks', () => {
const hooks = buildSessionHooks(callback);
hooks!.onPostToolUse!(
- { toolName: 'read', toolArgs: { path: '/file' }, toolResult: { content: 'ok' } as any, timestamp: 1, cwd: '/tmp' },
+ { toolName: 'read', toolArgs: { path: '/file' }, toolResult: { content: 'ok' } as any, timestamp: new Date(1), sessionId: 's1', workingDirectory: '/tmp' },
{ sessionId: 's1' },
);
@@ -477,7 +507,7 @@ describe('buildSessionHooks', () => {
const hooks = buildSessionHooks(callback);
hooks!.onSessionStart!(
- { source: 'new', timestamp: 1, cwd: '/tmp' },
+ { source: 'new', timestamp: new Date(1), sessionId: 's1', workingDirectory: '/tmp' },
{ sessionId: 's1' },
);
@@ -492,7 +522,7 @@ describe('buildSessionHooks', () => {
const hooks = buildSessionHooks(callback);
hooks!.onSessionEnd!(
- { reason: 'complete', timestamp: 1, cwd: '/tmp' },
+ { reason: 'complete', timestamp: new Date(1), sessionId: 's1', workingDirectory: '/tmp' },
{ sessionId: 's1' },
);
@@ -507,7 +537,7 @@ describe('buildSessionHooks', () => {
const hooks = buildSessionHooks(callback);
hooks!.onErrorOccurred!(
- { error: 'timeout', errorContext: 'tool_execution', recoverable: true, timestamp: 1, cwd: '/tmp' },
+ { error: 'timeout', errorContext: 'tool_execution', recoverable: true, timestamp: new Date(1), sessionId: 's1', workingDirectory: '/tmp' },
{ sessionId: 's1' },
);
diff --git a/src/lib/server/copilot/session.ts b/src/lib/server/copilot/session.ts
index c9e4bbc..b16872d 100644
--- a/src/lib/server/copilot/session.ts
+++ b/src/lib/server/copilot/session.ts
@@ -3,12 +3,11 @@ import { join } from 'node:path';
import { readFile, writeFile, rename } from 'node:fs/promises';
import { createHash, randomUUID } from 'node:crypto';
import { CopilotClient } from '@github/copilot-sdk';
-import type { SessionConfig, SystemPromptSection, SectionOverride, MCPServerConfig, ModelCapabilitiesOverride } from '@github/copilot-sdk';
+import type { SessionConfig, SystemMessageSection, SectionOverride, MCPServerConfig, ModelCapabilitiesOverride, RemoteSessionMode } from '@github/copilot-sdk';
export type HookEventCallback = (message: Record) => void;
import { isIP } from 'node:net';
import { config } from '../config.js';
-import { createSessionFsHandlerFactory } from './session-fs.js';
type ReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh';
@@ -41,11 +40,12 @@ export interface CreateSessionOptions {
agent?: string;
onEvent?: (event: any) => void;
onHookEvent?: HookEventCallback;
- systemPromptSections?: Partial>;
+ systemPromptSections?: Partial>;
modelCapabilities?: ModelCapabilitiesOverride;
enableConfigDiscovery?: boolean;
provider?: SessionConfig['provider'];
onElicitationRequest?: SessionConfig['onElicitationRequest'];
+ remoteSession?: RemoteSessionMode;
}
function isPrivateIpv4(hostname: string): boolean {
@@ -343,7 +343,7 @@ async function loadConfiguredMcpServers(configDir?: string): Promise typeof arg === 'string') : [],
...(normalizeStringRecord(server.env) ? { env: normalizeStringRecord(server.env) } : {}),
- ...(typeof server.cwd === 'string' ? { cwd: server.cwd } : {}),
+ ...(typeof server.cwd === 'string' ? { workingDirectory: server.cwd } : {}),
tools: Array.isArray(server.tools) && server.tools.length > 0 ? server.tools : ['*'],
...(typeof server.timeout === 'number' && server.timeout > 0 ? { timeout: server.timeout } : {}),
};
@@ -456,7 +456,7 @@ export async function createCopilotSession(
}
if (options.systemPromptSections && Object.keys(options.systemPromptSections).length > 0) {
- const sections: Partial> = { ...options.systemPromptSections };
+ const sections: Partial> = { ...options.systemPromptSections };
if (options.customInstructions && !sections.custom_instructions) {
sections.custom_instructions = { action: 'append', content: options.customInstructions };
}
@@ -525,12 +525,14 @@ export async function createCopilotSession(
sessionConfig.provider = options.provider;
}
- // Provide a sandboxed filesystem handler so the SDK can manage session workspace files
- if (config.copilotConfigDir) {
- const workspaceRoot = join(config.copilotConfigDir, 'session-state');
- sessionConfig.createSessionFsHandler = createSessionFsHandlerFactory(workspaceRoot);
+ if (options.remoteSession && options.remoteSession !== 'off') {
+ sessionConfig.remoteSession = options.remoteSession;
}
+ // The SDK 1.0.0-beta runtime writes session state directly to
+ // `/session-state/` (set via CopilotClient `baseDirectory`),
+ // so an explicit per-session FS provider is no longer required.
+
return client.createSession(sessionConfig);
}
diff --git a/src/lib/server/ws/message-handlers/new-session.ts b/src/lib/server/ws/message-handlers/new-session.ts
index 2991b59..f91c60b 100644
--- a/src/lib/server/ws/message-handlers/new-session.ts
+++ b/src/lib/server/ws/message-handlers/new-session.ts
@@ -1,5 +1,5 @@
import { createCopilotSession } from '../../copilot/session.js';
-import type { SystemPromptSection, SectionOverride } from '@github/copilot-sdk';
+import type { SystemMessageSection, SectionOverride } from '@github/copilot-sdk';
import { getSkillDirectories } from '../../skills/scanner.js';
import { config } from '../../config.js';
import { poolSend } from '../session-pool.js';
@@ -52,6 +52,13 @@ export async function handleNewSession(msg: any, ctx: MessageContext): Promise typeof s === 'string')
: undefined;
@@ -85,14 +92,14 @@ export async function handleNewSession(msg: any, ctx: MessageContext): Promise(['replace', 'remove', 'append', 'prepend']);
- let systemPromptSections: Partial> | undefined;
+ let systemPromptSections: Partial> | undefined;
if (msg.systemPromptSections && typeof msg.systemPromptSections === 'object') {
systemPromptSections = {};
for (const [name, override] of Object.entries(msg.systemPromptSections as Record)) {
if (!validSections.has(name)) continue;
const o = override as Record;
if (!o || typeof o !== 'object' || !validActions.has(o.action as string)) continue;
- systemPromptSections[name as SystemPromptSection] = {
+ systemPromptSections[name as SystemMessageSection] = {
action: o.action as SectionOverride['action'],
...(typeof o.content === 'string' ? { content: o.content.slice(0, 5000) } : {}),
};
@@ -131,6 +138,7 @@ export async function handleNewSession(msg: any, ctx: MessageContext): Promise poolSend(connectionEntry, message),
});
diff --git a/src/lib/server/ws/message-handlers/quota-compact.ts b/src/lib/server/ws/message-handlers/quota-compact.ts
index 8b0d052..4bf784a 100644
--- a/src/lib/server/ws/message-handlers/quota-compact.ts
+++ b/src/lib/server/ws/message-handlers/quota-compact.ts
@@ -6,7 +6,7 @@ export async function handleGetQuota(msg: any, ctx: MessageContext): Promise {
await expect(destroyPoolEntry(entry)).resolves.toBeUndefined();
});
+
+ it('falls back to forceStop when stop() does not resolve within 5s', async () => {
+ vi.useFakeTimers();
+ const client = createClientMock() as ClientMock & { forceStop: ReturnType };
+ let resolveStop: (() => void) | null = null;
+ client.stop.mockImplementation(
+ () => new Promise((res) => {
+ resolveStop = res;
+ }),
+ );
+ client.forceStop = vi.fn(async () => undefined);
+
+ const entry = createPoolEntry(client as never, createWsMock() as never);
+ const destroyPromise = destroyPoolEntry(entry);
+
+ // Advance past the 5s timeout window so the fallback fires.
+ await vi.advanceTimersByTimeAsync(5001);
+ await destroyPromise;
+
+ expect(client.forceStop).toHaveBeenCalledTimes(1);
+ // Cleanup the still-pending stop() to avoid leaks across tests.
+ (resolveStop as (() => void) | null)?.();
+ });
+
+ it('does not call forceStop when stop() resolves quickly', async () => {
+ const client = createClientMock() as ClientMock & { forceStop: ReturnType };
+ client.forceStop = vi.fn(async () => undefined);
+
+ const entry = createPoolEntry(client as never, createWsMock() as never);
+ await destroyPoolEntry(entry);
+
+ expect(client.stop).toHaveBeenCalledTimes(1);
+ expect(client.forceStop).not.toHaveBeenCalled();
+ });
});
describe('session pool cleanup', () => {
diff --git a/src/lib/server/ws/session-pool.ts b/src/lib/server/ws/session-pool.ts
index aa6d622..3c8984e 100644
--- a/src/lib/server/ws/session-pool.ts
+++ b/src/lib/server/ws/session-pool.ts
@@ -97,7 +97,32 @@ export async function destroyPoolEntry(entry: PoolEntry): Promise {
entry.pendingUserInputPrompt = null;
entry.pendingPermissionPrompts.clear();
entry.permissionPreferences.clear();
- try { await entry.client.stop(); } catch { /* ignore */ }
+ // Graceful stop with 5s timeout fallback to forceStop().
+ // Prevents hung CLI subprocesses if `stop()` blocks (seen in long-running deployments).
+ let timer: ReturnType | null = null;
+ let settled = false;
+ const stopPromise = entry.client.stop().catch(() => undefined).finally(() => {
+ settled = true;
+ if (timer) {
+ clearTimeout(timer);
+ timer = null;
+ }
+ });
+ const timeoutPromise = new Promise<'timeout'>((resolve) => {
+ timer = setTimeout(() => resolve('timeout'), 5000);
+ });
+
+ const result = await Promise.race([stopPromise.then(() => 'ok' as const), timeoutPromise]);
+ if (result === 'timeout' && !settled) {
+ const maybeForceStop = (entry.client as { forceStop?: () => Promise }).forceStop;
+ if (typeof maybeForceStop === 'function') {
+ try { await maybeForceStop.call(entry.client); } catch { /* ignore */ }
+ }
+ }
+ // Always await the original stop so we don't leak an unhandled promise/timer.
+ if (settled) {
+ await stopPromise;
+ }
}
/** True when the client WS is closed or hasn't sent a ping recently (e.g. iOS backgrounded). */
diff --git a/src/lib/types/config.ts b/src/lib/types/config.ts
index c8a2d56..cbe3b05 100644
--- a/src/lib/types/config.ts
+++ b/src/lib/types/config.ts
@@ -7,7 +7,7 @@ export interface InfiniteSessionsConfig {
bufferThreshold: number;
}
-export type { SystemPromptSection, SectionOverride, SectionOverrideAction } from '@github/copilot-sdk';
+export type { SystemMessageSection, SectionOverride, SectionOverrideAction } from '@github/copilot-sdk';
export type { ModelCapabilitiesOverride } from '@github/copilot-sdk';
export interface SystemPromptSectionInput {
@@ -42,6 +42,14 @@ export interface PersistedSettings {
ttsEnabled?: boolean;
/** TTS speech rate (0.5 to 2.0). */
ttsRate?: number;
+ /**
+ * Per-user default for cloud/remote session publishing.
+ * - "off": local-only (default), no remote visibility.
+ * - "export": stream events to GitHub for monitor-only view on github.com/Mobile.
+ * - "on": full remote monitor + steer via github.com/Mobile.
+ * The active client only honors this when ENABLE_REMOTE_SESSIONS is enabled server-side.
+ */
+ remoteSession?: 'off' | 'export' | 'on';
}
export interface CustomAgentDefinition {
diff --git a/src/routes/api/sessions/last/+server.ts b/src/routes/api/sessions/last/+server.ts
new file mode 100644
index 0000000..f4b010c
--- /dev/null
+++ b/src/routes/api/sessions/last/+server.ts
@@ -0,0 +1,35 @@
+import { json } from '@sveltejs/kit';
+import type { RequestHandler } from './$types';
+import { checkAuth } from '$lib/server/auth/guard';
+import { createCopilotClient } from '$lib/server/copilot/client';
+import { config } from '$lib/server/config.js';
+
+/**
+ * GET /api/sessions/last — returns metadata for the most recent local session
+ * so the UI can offer a one-tap "Resume last conversation" across devices.
+ */
+export const GET: RequestHandler = async ({ locals }) => {
+ const auth = checkAuth(locals.session);
+ if (!auth.authenticated) {
+ return json({ error: auth.error }, { status: 401 });
+ }
+
+ const client = createCopilotClient(locals.session!.githubToken!, config.copilotConfigDir);
+ try {
+ const lastId = await client.getLastSessionId();
+ if (!lastId) {
+ return json({ error: 'No previous session found' }, { status: 404 });
+ }
+ const metadata = await client.getSessionMetadata(lastId);
+ if (!metadata) {
+ return json({ error: 'Session metadata unavailable' }, { status: 404 });
+ }
+ return json({ sessionId: lastId, metadata });
+ } catch (err) {
+ const message = err instanceof Error ? err.message : 'Unknown error';
+ console.error('[api/sessions/last]', message);
+ return json({ error: 'Failed to load last session' }, { status: 500 });
+ } finally {
+ try { await client.stop(); } catch { /* ignore */ }
+ }
+};
diff --git a/src/routes/api/sessions/last/server.test.ts b/src/routes/api/sessions/last/server.test.ts
new file mode 100644
index 0000000..81b1bb7
--- /dev/null
+++ b/src/routes/api/sessions/last/server.test.ts
@@ -0,0 +1,92 @@
+// @vitest-environment node
+import { beforeEach, describe, expect, it, vi } from 'vitest';
+
+vi.mock('$lib/server/auth/guard', () => ({
+ checkAuth: vi.fn(),
+}));
+
+vi.mock('$lib/server/copilot/client', () => ({
+ createCopilotClient: vi.fn(),
+}));
+
+vi.mock('$lib/server/config.js', () => ({
+ config: { copilotConfigDir: '/tmp/test-copilot' },
+}));
+
+import { GET } from './+server';
+import { checkAuth } from '$lib/server/auth/guard';
+import { createCopilotClient } from '$lib/server/copilot/client';
+
+function createEvent(session?: { githubToken?: string }) {
+ return { locals: { session } } as any;
+}
+
+describe('GET /api/sessions/last', () => {
+ const stop = vi.fn(async () => undefined);
+ const getLastSessionId = vi.fn();
+ const getSessionMetadata = vi.fn();
+
+ beforeEach(() => {
+ vi.clearAllMocks();
+ vi.spyOn(console, 'error').mockImplementation(() => undefined);
+ vi.mocked(checkAuth).mockReturnValue({
+ authenticated: true,
+ user: { login: 'octocat', name: 'Octocat' },
+ });
+ vi.mocked(createCopilotClient).mockReturnValue({
+ stop,
+ getLastSessionId,
+ getSessionMetadata,
+ } as never);
+ });
+
+ it('returns 401 when unauthenticated', async () => {
+ vi.mocked(checkAuth).mockReturnValue({
+ authenticated: false,
+ user: null,
+ error: 'unauth',
+ });
+ const res = await GET(createEvent());
+ expect(res.status).toBe(401);
+ expect(createCopilotClient).not.toHaveBeenCalled();
+ });
+
+ it('returns 404 when no previous session exists', async () => {
+ getLastSessionId.mockResolvedValue(undefined);
+ const res = await GET(createEvent({ githubToken: 'tok' }));
+ expect(res.status).toBe(404);
+ expect(stop).toHaveBeenCalled();
+ });
+
+ it('returns 404 when metadata is unavailable', async () => {
+ getLastSessionId.mockResolvedValue('sess-1');
+ getSessionMetadata.mockResolvedValue(undefined);
+ const res = await GET(createEvent({ githubToken: 'tok' }));
+ expect(res.status).toBe(404);
+ });
+
+ it('returns sessionId + metadata on success', async () => {
+ getLastSessionId.mockResolvedValue('sess-1');
+ getSessionMetadata.mockResolvedValue({ id: 'sess-1', title: 'demo' });
+ const res = await GET(createEvent({ githubToken: 'tok' }));
+ expect(res.status).toBe(200);
+ expect(await res.json()).toEqual({
+ sessionId: 'sess-1',
+ metadata: { id: 'sess-1', title: 'demo' },
+ });
+ });
+
+ it('passes copilotConfigDir to the SDK client factory', async () => {
+ getLastSessionId.mockResolvedValue('sess-1');
+ getSessionMetadata.mockResolvedValue({ id: 'sess-1' });
+ await GET(createEvent({ githubToken: 'tok' }));
+ expect(createCopilotClient).toHaveBeenCalledWith('tok', '/tmp/test-copilot');
+ });
+
+ it('returns 500 on unexpected SDK errors', async () => {
+ getLastSessionId.mockRejectedValue(new Error('boom'));
+ const res = await GET(createEvent({ githubToken: 'tok' }));
+ expect(res.status).toBe(500);
+ expect(stop).toHaveBeenCalled();
+ });
+});
diff --git a/tests/sessions-endpoints.spec.ts b/tests/sessions-endpoints.spec.ts
new file mode 100644
index 0000000..350647c
--- /dev/null
+++ b/tests/sessions-endpoints.spec.ts
@@ -0,0 +1,34 @@
+import { test, expect } from '@playwright/test';
+
+/**
+ * End-to-end coverage for the new session endpoints added in the
+ * SDK 1.0.0-beta.8 upgrade. These specs hit the real built server
+ * (booted by the Playwright webServer config) to verify wiring and
+ * auth behaviour beyond what the vitest module-level mocks can prove.
+ *
+ * Per-session `remoteSession: "on"` and the cloud agents endpoint
+ * cannot be exercised in a hermetic test — they would publish real
+ * sessions to production Copilot infrastructure under the test
+ * GitHub account — so those code paths are covered by unit tests
+ * and the manual smoke procedure documented in the PR.
+ */
+
+test.describe('New session endpoints', () => {
+ test('GET /api/sessions/last rejects unauthenticated requests', async ({ request }) => {
+ const response = await request.get('/api/sessions/last');
+ expect(response.status()).toBe(401);
+ const body = await response.json();
+ expect(body.error).toBeTruthy();
+ });
+
+ test('GET /api/sessions/last returns JSON even on auth failure', async ({ request }) => {
+ const response = await request.get('/api/sessions/last');
+ expect(response.headers()['content-type']).toContain('application/json');
+ });
+
+ test('OPTIONS/HEAD do not crash the route', async ({ request }) => {
+ const response = await request.fetch('/api/sessions/last', { method: 'HEAD' });
+ // SvelteKit returns 405 for unsupported methods on a route, not 500.
+ expect([401, 405]).toContain(response.status());
+ });
+});