authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-11 15:53:31-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-02-11 15:53:31-08:00
log16b81f72689f4347753762112f76ccd5828fe2fa
tree92c5841054415f1d8a25830cab2d3ac21e30ff80
parent169d06f05b543433278a123b3512fddad05f9f2a
parent94420192359d68c03241f03f47cf8d670abafa15
signature Signed by PGP key B5690EEEBB952194

Merge pull request #3 from pingdotgg/juliusmarminge/git-integration


54 files changed, 2192 insertions(+), 525 deletions(-)

.plans/branch-environment-picker-in-chatview-input.md created+74
...@@ -0,0 +1,74 @@
1# Branch/Environment Picker in ChatView Input
2
3## Summary
4
5Add a secondary toolbar below the ChatView input area (similar to Codex UI) that lets users select the target branch and environment mode (Local vs New worktree) before sending their first message.
6
7## UX
8
9- A toolbar appears **below** the input form (always visible when it's a git repo)
10- Two controls:
11 1. **Environment mode** (left side): toggles between "Local" and "New worktree" — **locked after first message** (no longer clickable, just shows current mode as label)
12 2. **Branch picker** (right side): dropdown showing local branches — **always changeable**, even after messages are sent
13- If not a git repo, the toolbar is hidden entirely (thread uses project cwd as-is)
14
15## Changes
16
17### 0. Install `@tanstack/react-query` in `apps/renderer`
18
19Add dependency + wrap app in `QueryClientProvider`.
20
21### 1. `apps/renderer/src/store.ts` — MODIFY
22
23Add a new action to the reducer:
24
25```ts
26| { type: "SET_THREAD_BRANCH"; threadId: string; branch: string | null; worktreePath: string | null }
27```
28
29Reducer case updates `branch` and `worktreePath` on the thread.
30
31### 2. `apps/renderer/src/components/ChatView.tsx` — MODIFY
32
33**Fetch branches** via `useQuery`:
34
35```ts
36const branchQuery = useQuery({
37 queryKey: ["git-branches", activeProject?.cwd],
38 queryFn: () => api.git.listBranches({ cwd: activeProject!.cwd }),
39 enabled: !!activeProject,
40});
41```
42
43**Local state:**
44
45- `envMode: "local" | "worktree"` — environment mode (local component state)
46
47**UI:** Below the `<form>`, render a toolbar bar (hidden if `!branchQuery.data?.isRepo`):
48
49- Left side: env mode button ("Local" / "New worktree") — disabled after first message (locked in)
50- Right side: branch dropdown from `branchQuery.data.branches`
51- Both styled like existing model picker (small text, chevron, dropdown menus)
52
53**Behavior:**
54
55- Branch picker is always active — changing branch dispatches `SET_THREAD_BRANCH` immediately
56- Env mode is only clickable when `activeThread.messages.length === 0`. After first message, it becomes a static label showing the locked-in mode
57- On first send (`onSend`): if `envMode === "worktree"` and a branch is selected, call `api.git.createWorktree` before starting the session, then dispatch `SET_THREAD_BRANCH` with the worktreePath
58- `ensureSession` already uses `activeThread.worktreePath ?? activeProject.cwd`
59
60### Files to modify
61
621. `apps/renderer/package.json` — add `@tanstack/react-query`
632. `apps/renderer/src/main.tsx` (or App entry) — wrap in `QueryClientProvider`
643. `apps/renderer/src/store.ts` — add `SET_THREAD_BRANCH` action
654. `apps/renderer/src/components/ChatView.tsx` — branch/env picker UI with `useQuery`
66
67## Verification
68
691. `turbo build` — compiles
702. Create a new thread → branch bar appears below input with "Local" + current branch
713. Change branch in dropdown → branch updates on thread
724. Toggle "New worktree" → send message → worktree created, session uses worktree cwd
735. After first message: env mode label locks to "Worktree" (not clickable), branch picker still works
746. Non-git project → no branch bar shown
.plans/git-flows-integration-tests.md created+99
...@@ -0,0 +1,99 @@
1# Git Flows Integration Tests
2
3## Overview
4
5Real integration tests that run actual git commands against temporary repos. No mocking.
6
7## Step 1: Extract git functions into `apps/desktop/src/git.ts`
8
9The git functions (`listGitBranches`, `createGitWorktree`, `removeGitWorktree`, `createGitBranch`, `checkoutGitBranch`, `initGitRepo`) and their helper `runTerminalCommand` are currently private in `main.ts`. Extract them into a new `apps/desktop/src/git.ts` module with named exports.
10
11`main.ts` will import and re-use them — no behavior change, just moving code.
12
13**Files modified:**
14
15- `apps/desktop/src/git.ts` — new file with all git functions exported
16- `apps/desktop/src/main.ts` — import from `./git` instead of defining inline
17
18## Step 2: Create `apps/desktop/src/git.test.ts`
19
20Integration tests using real temp git repos. Each test group creates a fresh temp directory with `git init`, makes commits, creates branches as needed, and cleans up after.
21
22### Setup/teardown pattern
23
24```ts
25import { mkdtemp, rm, writeFile } from "node:fs/promises";
26import { tmpdir } from "node:os";
27import path from "node:path";
28import { afterEach, beforeEach, describe, expect, it } from "vitest";
29import {
30 listGitBranches,
31 createGitBranch,
32 checkoutGitBranch,
33 createGitWorktree,
34 removeGitWorktree,
35 initGitRepo,
36} from "./git";
37
38// Helper: run a raw git command in a dir (for test setup, not under test)
39// Helper: create an initial commit (git needs at least one commit for branches)
40```
41
42### Test groups
43
44**1. initGitRepo**
45
46- Creates a valid git repo in a temp dir
47- listGitBranches reports `isRepo: true` after init
48
49**2. listGitBranches**
50
51- Returns `isRepo: false` for non-git directory
52- Returns the current branch with `current: true`
53- Sorts current branch first
54- Lists multiple branches after creating them
55- `isDefault` is false when no remote (no origin/HEAD)
56
57**3. checkoutGitBranch**
58
59- Checks out an existing branch (current flag moves)
60- Throws when branch doesn't exist
61- Throws when checkout would overwrite uncommitted changes (dirty working tree)
62
63**4. createGitBranch**
64
65- Creates a new branch (appears in listGitBranches)
66- Throws when branch already exists
67
68**5. createGitWorktree + removeGitWorktree**
69
70- Creates a worktree directory at the expected path
71- Worktree has the correct branch checked out
72- Throws when branch is already checked out in another worktree
73- removeGitWorktree cleans up the worktree
74
75**6. Full flow: local branch checkout**
76
77- init → commit → create branch → checkout → verify current
78
79**7. Full flow: worktree creation from selected branch**
80
81- init → commit → create branch → create worktree → verify worktree dir exists and has correct branch
82
83**8. Full flow: thread switching simulation**
84
85- init → commit → create branch-a, branch-b → checkout a → checkout b → checkout a → verify current matches
86
87**9. Full flow: checkout conflict**
88
89- init → commit → create branch → modify file (unstaged) → checkout other branch → expect error
90
91## Verification
92
93```bash
94# Run the git integration tests
95cd apps/desktop && bun run test
96
97# Or just the git test file
98npx vitest run apps/desktop/src/git.test.ts
99```
.plans/git-flows-test-plan.md created+103
...@@ -0,0 +1,103 @@
1# Git Flows Test Plan
2
3## Overview
4
5Add tests for git branch/worktree flows. Two files:
6
71. **Extend** `apps/renderer/src/store.test.ts` — reducer tests for `SET_THREAD_BRANCH`
82. **Create** `apps/renderer/src/git-flows.test.ts` — flow logic tests
9
10All tests are pure Vitest unit tests (no React rendering). They test the reducer directly and simulate handler logic via sequential reducer dispatches + mocked API calls.
11
12## File 1: `apps/renderer/src/store.test.ts` (extend)
13
14Add `describe("SET_THREAD_BRANCH reducer")` with 6 tests:
15
16- Sets branch + worktreePath atomically
17- Clears both to null
18- Updates branch while preserving worktreePath
19- Does not affect other threads (multi-thread state)
20- No-op for nonexistent thread id
21- Does not mutate messages, error, or session fields
22
23Uses existing `makeThread`, `makeState` factories.
24
25## File 2: `apps/renderer/src/git-flows.test.ts` (new)
26
27### Factories
28
29- `makeThread()`, `makeState()`, `makeSession()` — same pattern as store.test.ts
30- `makeBranch()` — creates `GitBranch` objects
31- `makeMessage()` — creates `ChatMessage` objects
32- `makeGitApi()` — returns `{ checkout, createWorktree, createBranch, listBranches }` with `vi.fn()` mocks
33
34### Test groups (~30 tests total)
35
36**1. Local branch checkout flow** (2 tests)
37
38- Successful checkout → SET_THREAD_BRANCH updates branch
39- Checkout failure → SET_ERROR, branch unchanged
40
41**2. Thread branch conflict on send** (3 tests)
42
43- Two threads maintain independent branch state after SET_ACTIVE_THREAD
44- Branch state preserved through multiple thread switches + updates
45- Checkout failure on thread switch sets error only on target thread
46
47**3. Worktree creation on send** (5 tests)
48
49- First message in worktree mode → createWorktree → SET_THREAD_BRANCH with worktreePath
50- No worktree when messages already exist
51- No worktree in local envMode
52- No worktree when worktreePath already set
53- createWorktree failure → SET_ERROR, send aborted, no messages pushed
54
55**4. Env mode locking** (4 tests)
56
57- envLocked=false when no messages
58- envLocked=true with messages
59- Transitions false→true after PUSH_USER_MESSAGE
60- Remains true after SET_ERROR and UPDATE_SESSION
61
62**5. Auto-fill current branch** (3 tests)
63
64- Dispatches SET_THREAD_BRANCH when thread has no branch and current branch exists
65- Does not overwrite existing branch
66- No-op when no branch is marked current
67
68**6. Default branch detection** (2 tests)
69
70- isDefault flag on branch objects
71- current and isDefault can be on different branches
72
73**7. Branch creation + checkout** (3 tests)
74
75- Successful create + checkout updates branch
76- createBranch failure → error, branch unchanged
77- checkout failure after successful create → error, branch unchanged
78
79**8. Session CWD resolution** (3 tests)
80
81- Uses worktreePath when available
82- cwdOverride takes precedence over worktreePath
83- Falls back to project cwd when no worktree
84
85**9. Error handling patterns** (4 tests)
86
87- SET_ERROR sets error on correct thread
88- SET_ERROR with null clears error
89- Error on one thread doesn't affect others
90- Error cleared before successful branch operations
91
92## Verification
93
94```bash
95# Run all renderer tests
96cd apps/renderer && bun run test
97
98# Run just the new test file
99npx vitest run apps/renderer/src/git-flows.test.ts
100
101# Run just the store tests
102npx vitest run apps/renderer/src/store.test.ts
103```
.plans/git-integration-branch-picker-worktrees.md created+115
...@@ -0,0 +1,115 @@
1# Git Integration: Branch Picker + Worktrees
2
3## Summary
4
5Add git integration to let users start new threads from a specific branch, optionally creating a git worktree for isolated agent work.
6
7## UX Flow
8
9- **Left click** "+ New thread" → immediately creates a thread (current behavior, unchanged)
10- **Right click** "+ New thread" → opens a context menu with git options:
11 - List of local branches → clicking one creates a thread on that branch (uses project cwd)
12 - Each branch has a "worktree" sub-option → creates a worktree, then creates thread with worktree as cwd
13- When thread has a worktree, the agent session uses the worktree path as its cwd
14- If git fails (not a repo), context menu shows "Not a git repository" disabled item
15
16## Changes
17
18### 1. `packages/contracts/src/git.ts` — CREATE
19
20New Zod schemas and types:
21
22- `gitListBranchesInputSchema` — `{ cwd: string }`
23- `gitCreateWorktreeInputSchema` — `{ cwd: string, branch: string, path?: string }`
24- `gitRemoveWorktreeInputSchema` — `{ cwd: string, path: string }`
25- `gitBranchSchema` — `{ name: string, current: boolean }`
26- Result types for each
27
28### 2. `packages/contracts/src/ipc.ts` — MODIFY
29
30- Add 3 IPC channels: `git:list-branches`, `git:create-worktree`, `git:remove-worktree`
31- Add `git` namespace to `NativeApi` with `listBranches`, `createWorktree`, `removeWorktree`
32
33### 3. `packages/contracts/src/index.ts` — MODIFY
34
35- Add `export * from "./git"`
36
37### 4. `apps/desktop/src/main.ts` — MODIFY
38
39Add 3 IPC handlers + helper functions:
40
41- `listGitBranches()` — runs `git branch --no-color`, parses output into `{ name, current }[]`
42- `createGitWorktree()` — runs `git worktree add <path> <branch>`, defaults path to `../{repo}-worktrees/{branch}`
43- `removeGitWorktree()` — runs `git worktree remove <path>`
44
45Reuses existing `runTerminalCommand()`.
46
47### 5. `apps/desktop/src/preload.ts` — MODIFY
48
49Add `git` namespace with 3 `ipcRenderer.invoke` calls.
50
51### 6. `apps/renderer/src/types.ts` — MODIFY
52
53Add to `Thread`:
54
55```
56branch: string | null
57worktreePath: string | null
58```
59
60### 7. `apps/renderer/src/persistenceSchema.ts` — MODIFY
61
62- Add optional `branch`/`worktreePath` to persisted thread schema (`.nullable().optional()` for backwards compat)
63- Add V3 schema, update union
64- Update `hydrateThread` to default new fields to `null`
65- Update `toPersistedState` to serialize new fields
66
67### 8. `apps/renderer/src/store.ts` — MODIFY
68
69- Update persisted state key to v3, keep v2 as legacy fallback
70
71### 9. `apps/renderer/src/components/Sidebar.tsx` — MODIFY (main UI work)
72
73- Keep existing left-click `handleNewThread` unchanged (immediate thread creation)
74- Add `onContextMenu` handler to "+ New thread" buttons (both global and per-project)
75- On right-click: fetch branches via `api.git.listBranches`, show a custom context menu
76- Context menu items: branch names, each with a nested option to create with worktree
77- Clicking a branch → creates thread with `branch` set, title = branch name
78- Clicking "with worktree" → calls `api.git.createWorktree` first, then creates thread with `worktreePath`
79- Show branch badge on thread list items
80- If not a git repo, show "Not a git repository" as disabled menu item
81
82Context menu component: a positioned `<div>` with `position: fixed` anchored to the click position, dismissed on click-outside or Escape. Follows the existing dropdown pattern from ChatView's model picker.
83
84### 10. `apps/renderer/src/components/ChatView.tsx` — MODIFY
85
86- Line 157: use `activeThread.worktreePath ?? activeProject.cwd` as session cwd
87- Show branch/worktree badge in header bar
88
89## Implementation Order
90
911. `packages/contracts/src/git.ts` (new schemas)
922. `packages/contracts/src/ipc.ts` + `index.ts` (wire up channels)
933. `apps/desktop/src/main.ts` (git command handlers)
944. `apps/desktop/src/preload.ts` (bridge methods)
955. `apps/renderer/src/types.ts` (Thread type update)
966. `apps/renderer/src/persistenceSchema.ts` + `store.ts` (persistence migration)
977. `apps/renderer/src/components/Sidebar.tsx` (branch picker UI)
988. `apps/renderer/src/components/ChatView.tsx` (worktree cwd + badge)
99
100## Edge Cases
101
102- **Not a git repo**: `git branch` fails → context menu shows "Not a git repository" disabled item
103- **Branch has slashes**: `feature/foo` → worktree dir becomes `feature-foo`
104- **Worktree exists**: git error surfaces to user via inline error message in context menu
105- **No persistence breakage**: `.nullable().optional()` fields parse fine with old data
106
107## Verification
108
1091. `turbo build` — confirm contracts/desktop/renderer all compile
1102. Launch app, add a project pointing to a git repo
1113. Click "+ New thread" → verify branch list loads
1124. Select a branch, click Start → thread created with branch in title
1135. Enable worktree checkbox, pick branch, Start → verify worktree directory created on disk
1146. Send a message in worktree thread → verify agent runs in worktree cwd
1157. Add a non-git project → verify graceful error, can still create thread
AGENTS.md+7
...@@ -1,11 +1,13 @@...@@ -1,11 +1,13 @@
1# CLAUDE.md1# CLAUDE.md
22
3## Project Snapshot3## Project Snapshot
4
4T3 Code is a minimal web GUI for using code agents like Codex and Claude Code (coming soon).5T3 Code is a minimal web GUI for using code agents like Codex and Claude Code (coming soon).
56
6This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.7This repository is a VERY EARLY WIP. Proposing sweeping changes that improve long-term maintainability is encouraged.
78
8## Core Priorities9## Core Priorities
10
91. Performance first.111. Performance first.
102. Reliability first.122. Reliability first.
113. Keep behavior predictable under load and during failures (session restarts, reconnects, partial streams).133. Keep behavior predictable under load and during failures (session restarts, reconnects, partial streams).
...@@ -13,23 +15,28 @@ This repository is a VERY EARLY WIP. Proposing sweeping changes that improve lon...@@ -13,23 +15,28 @@ This repository is a VERY EARLY WIP. Proposing sweeping changes that improve lon
13If a tradeoff is required, choose correctness and robustness over short-term convenience.15If a tradeoff is required, choose correctness and robustness over short-term convenience.
1416
15## Package Roles17## Package Roles
18
16- `apps/server`: Node.js WebSocket server. Wraps Codex app-server (JSON-RPC over stdio), serves the React web app, and manages provider sessions.19- `apps/server`: Node.js WebSocket server. Wraps Codex app-server (JSON-RPC over stdio), serves the React web app, and manages provider sessions.
17- `apps/web`: React/Vite UI. Owns session UX, conversation/event rendering, and client-side state. Connects to the server via WebSocket.20- `apps/web`: React/Vite UI. Owns session UX, conversation/event rendering, and client-side state. Connects to the server via WebSocket.
18- `packages/contracts`: Shared Zod schemas and TypeScript contracts for provider events, WebSocket protocol, and model/session types.21- `packages/contracts`: Shared Zod schemas and TypeScript contracts for provider events, WebSocket protocol, and model/session types.
1922
20## Codex App Server (Important)23## Codex App Server (Important)
24
21T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.25T3 Code is currently Codex-first. The server starts `codex app-server` (JSON-RPC over stdio) per provider session, then streams structured events to the browser through WebSocket push messages.
2226
23How we use it in this codebase:27How we use it in this codebase:
28
24- Session startup/resume and turn lifecycle are brokered in `apps/server/src/codexAppServerManager.ts`.29- Session startup/resume and turn lifecycle are brokered in `apps/server/src/codexAppServerManager.ts`.
25- Provider dispatch and thread event logging are coordinated in `apps/server/src/providerManager.ts`.30- Provider dispatch and thread event logging are coordinated in `apps/server/src/providerManager.ts`.
26- WebSocket server routes NativeApi methods in `apps/server/src/wsServer.ts`.31- WebSocket server routes NativeApi methods in `apps/server/src/wsServer.ts`.
27- Web app consumes provider event streams via WebSocket push on channel `providers.event`.32- Web app consumes provider event streams via WebSocket push on channel `providers.event`.
2833
29Docs:34Docs:
35
30- Codex App Server docs: https://developers.openai.com/codex/sdk/#app-server36- Codex App Server docs: https://developers.openai.com/codex/sdk/#app-server
3137
32## Reference Repos38## Reference Repos
39
33- Open-source Codex repo: https://github.com/openai/codex40- Open-source Codex repo: https://github.com/openai/codex
34- Codex-Monitor (Tauri, feature-complete, strong reference implementation): https://github.com/Dimillian/CodexMonitor41- Codex-Monitor (Tauri, feature-complete, strong reference implementation): https://github.com/Dimillian/CodexMonitor
3542
README.md+2-2
...@@ -59,8 +59,8 @@ npx t3...@@ -59,8 +59,8 @@ npx t3
5959
60## Scripts60## Scripts
6161
62- `bun run dev` — Starts contracts, server, and web dev tasks via Turborepo's parallel task runner.62- `bun run dev` — Starts contracts, server, and web in `turbo watch` mode.
63- `bun run dev:server` — Starts just the WebSocket server (uses tsx for TS execution).63- `bun run dev:server` — Starts just the WebSocket server (uses Bun TypeScript execution).
64- `bun run dev:web` — Starts just the Vite dev server for the web app.64- `bun run dev:web` — Starts just the Vite dev server for the web app.
65- `bun run start` — Runs the production server (serves built web app as static files).65- `bun run start` — Runs the production server (serves built web app as static files).
66- `bun run build` — Builds contracts, web app, and server through Turbo.66- `bun run build` — Builds contracts, web app, and server through Turbo.
apps/desktop/package.json+5-6
...@@ -4,10 +4,10 @@...@@ -4,10 +4,10 @@
4 "private": true,4 "private": true,
5 "main": "dist-electron/main.js",5 "main": "dist-electron/main.js",
6 "scripts": {6 "scripts": {
7 "dev": "bun run --cwd ../server build && concurrently -k -n BUNDLE,WEB,ELECTRON \"bun run dev:bundle\" \"bun run --cwd ../web dev\" \"bun run dev:electron\"",7 "dev": "bun run --parallel dev:bundle dev:electron",
8 "dev:bundle": "tsup --watch",8 "dev:bundle": "tsdown --watch",
9 "dev:electron": "bun run scripts/dev-electron.mjs",9 "dev:electron": "bun run scripts/dev-electron.mjs",
10 "build": "tsup",10 "build": "tsdown",
11 "start": "electron dist-electron/main.js",11 "start": "electron dist-electron/main.js",
12 "typecheck": "tsc --noEmit",12 "typecheck": "tsc --noEmit",
13 "test": "vitest run --passWithNoTests",13 "test": "vitest run --passWithNoTests",
...@@ -18,11 +18,10 @@...@@ -18,11 +18,10 @@
18 },18 },
19 "devDependencies": {19 "devDependencies": {
20 "@types/node": "^22.10.2",20 "@types/node": "^22.10.2",
21 "concurrently": "^9.1.2",
22 "electronmon": "^2.0.2",21 "electronmon": "^2.0.2",
23 "tsup": "^8.3.5",22 "tsdown": "^0.20.3",
24 "typescript": "^5.7.3",23 "typescript": "^5.7.3",
25 "vitest": "^3.0.0",24 "vitest": "^4.0.0",
26 "wait-on": "^8.0.2"25 "wait-on": "^8.0.2"
27 }26 }
28}27}
apps/desktop/scripts/dev-electron.mjs+1-1
...@@ -10,7 +10,7 @@ await waitOn({...@@ -10,7 +10,7 @@ await waitOn({
10 `tcp:${port}`,10 `tcp:${port}`,
11 "file:dist-electron/main.js",11 "file:dist-electron/main.js",
12 "file:dist-electron/preload.js",12 "file:dist-electron/preload.js",
13 "file:../server/dist/index.js",13 "file:../server/dist/index.mjs",
14 ],14 ],
15});15});
1616
apps/desktop/scripts/smoke-test.mjs+1-5
...@@ -1,16 +1,12 @@...@@ -1,16 +1,12 @@
1import { execSync, spawn } from "node:child_process";1import { spawn } from "node:child_process";
2import { dirname, resolve } from "node:path";2import { dirname, resolve } from "node:path";
3import { fileURLToPath } from "node:url";3import { fileURLToPath } from "node:url";
44
5const __dirname = dirname(fileURLToPath(import.meta.url));5const __dirname = dirname(fileURLToPath(import.meta.url));
6const desktopDir = resolve(__dirname, "..");6const desktopDir = resolve(__dirname, "..");
7const rootDir = resolve(__dirname, "../../..");
8const electronBin = resolve(desktopDir, "node_modules/.bin/electron");7const electronBin = resolve(desktopDir, "node_modules/.bin/electron");
9const mainJs = resolve(desktopDir, "dist-electron/main.js");8const mainJs = resolve(desktopDir, "dist-electron/main.js");
109
11console.log("Building contracts + web + server + desktop...");
12execSync("bun run build", { cwd: rootDir, stdio: "inherit" });
13
14console.log("\nLaunching Electron smoke test...");10console.log("\nLaunching Electron smoke test...");
1511
16const child = spawn(electronBin, [mainJs], {12const child = spawn(electronBin, [mainJs], {
apps/desktop/src/main.ts+2-1
...@@ -14,7 +14,7 @@ fixPath();...@@ -14,7 +14,7 @@ fixPath();
14const PICK_FOLDER_CHANNEL = "desktop:pick-folder";14const PICK_FOLDER_CHANNEL = "desktop:pick-folder";
15const CONTEXT_MENU_CHANNEL = "desktop:context-menu";15const CONTEXT_MENU_CHANNEL = "desktop:context-menu";
16const ROOT_DIR = path.resolve(__dirname, "../../..");16const ROOT_DIR = path.resolve(__dirname, "../../..");
17const BACKEND_ENTRY = path.join(ROOT_DIR, "apps/server/dist/index.js");17const BACKEND_ENTRY = path.join(ROOT_DIR, "apps/server/dist/index.mjs");
18const WEB_ENTRY = path.join(ROOT_DIR, "apps/web/dist/index.html");18const WEB_ENTRY = path.join(ROOT_DIR, "apps/web/dist/index.html");
19const STATE_DIR = path.join(os.homedir(), ".t3", "userdata");19const STATE_DIR = path.join(os.homedir(), ".t3", "userdata");
20const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);20const isDevelopment = Boolean(process.env.VITE_DEV_SERVER_URL);
...@@ -186,6 +186,7 @@ function createWindow(): BrowserWindow {...@@ -186,6 +186,7 @@ function createWindow(): BrowserWindow {
186186
187 if (isDevelopment) {187 if (isDevelopment) {
188 void window.loadURL(process.env.VITE_DEV_SERVER_URL as string);188 void window.loadURL(process.env.VITE_DEV_SERVER_URL as string);
189 window.webContents.openDevTools({ mode: "detach" });
189 } else {190 } else {
190 if (!fs.existsSync(WEB_ENTRY)) {191 if (!fs.existsSync(WEB_ENTRY)) {
191 throw new Error(`Web bundle missing at ${WEB_ENTRY}`);192 throw new Error(`Web bundle missing at ${WEB_ENTRY}`);
apps/desktop/tsconfig.json+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3 "compilerOptions": {3 "compilerOptions": {
4 "composite": true,4 "composite": true,
5 "types": ["node", "electron"],5 "types": ["node", "electron"],
6 "lib": ["ES2023", "DOM"]6 "lib": ["ES2023", "DOM", "esnext.disposable"]
7 },7 },
8 "include": ["src", "tsup.config.ts"]8 "include": ["src", "tsdown.config.ts"]
9}9}
apps/desktop/tsdown.config.ts created+21
...@@ -0,0 +1,21 @@
1import { defineConfig } from "tsdown";
2
3const shared = {
4 format: "cjs" as const,
5 outDir: "dist-electron",
6 sourcemap: true,
7 outExtensions: () => ({ js: ".js" }),
8};
9
10export default defineConfig([
11 {
12 ...shared,
13 entry: ["src/main.ts"],
14 clean: true,
15 noExternal: ["@t3tools/contracts"],
16 },
17 {
18 ...shared,
19 entry: ["src/preload.ts"],
20 },
21]);
apps/desktop/tsup.config.ts deleted-10
...@@ -1,10 +0,0 @@
1import { defineConfig } from "tsup";
2
3export default defineConfig({
4 entry: ["src/main.ts", "src/preload.ts"],
5 format: "cjs",
6 outDir: "dist-electron",
7 sourcemap: true,
8 clean: true,
9 noExternal: ["@t3tools/contracts"],
10});
apps/desktop/turbo.jsonc created+24
...@@ -0,0 +1,24 @@
1{
2 "$schema": "https://turbo.build/schema.json",
3 "extends": ["//"],
4 "tasks": {
5 "build": {
6 "dependsOn": ["^build"],
7 "outputs": ["dist-electron/**"],
8 },
9 "dev": {
10 "dependsOn": ["t3#build"],
11 "persistent": true,
12 },
13 "start": {
14 "dependsOn": ["build", "@t3tools/web#build", "t3#build"],
15 "cache": false,
16 "persistent": true,
17 },
18 "smoke-test": {
19 "dependsOn": ["build", "@t3tools/web#build", "t3#build"],
20 "cache": false,
21 "outputs": [],
22 },
23 },
24}
apps/server/package.json+6-9
...@@ -2,19 +2,17 @@...@@ -2,19 +2,17 @@
2 "name": "t3",2 "name": "t3",
3 "version": "0.1.0",3 "version": "0.1.0",
4 "bin": {4 "bin": {
5 "t3": "./dist/index.js"5 "t3": "./dist/index.mjs"
6 },6 },
7 "files": [7 "files": [
8 "dist"8 "dist"
9 ],9 ],
10 "type": "module",10 "type": "module",
11 "main": "./dist/index.js",11 "main": "./dist/index.mjs",
12 "scripts": {12 "scripts": {
13 "dev": "VITE_DEV_SERVER_URL=http://localhost:5173 tsx src/index.ts",13 "dev": "VITE_DEV_SERVER_URL=http://localhost:5173 bun run src/index.ts",
14 "dev:desktop": "T3CODE_MODE=desktop T3CODE_NO_BROWSER=1 tsx src/index.ts",14 "build": "tsdown && node scripts/bundle-client.mjs",
15 "build": "tsup && node scripts/bundle-client.mjs",15 "start": "node dist/index.mjs",
16 "start": "node dist/index.js",
17 "start:desktop": "T3CODE_MODE=desktop T3CODE_NO_BROWSER=1 node dist/index.js",
18 "typecheck": "tsc --noEmit",16 "typecheck": "tsc --noEmit",
19 "test": "vitest run"17 "test": "vitest run"
20 },18 },
...@@ -27,8 +25,7 @@...@@ -27,8 +25,7 @@
27 "@t3tools/web": "workspace:*",25 "@t3tools/web": "workspace:*",
28 "@types/node": "^22.10.2",26 "@types/node": "^22.10.2",
29 "@types/ws": "^8.5.13",27 "@types/ws": "^8.5.13",
30 "tsup": "^8.3.5",28 "tsdown": "^0.20.3",
31 "tsx": "^4.19.0",
32 "typescript": "^5.7.3"29 "typescript": "^5.7.3"
33 }30 }
34}31}
apps/server/src/codexAppServerManager.test.ts+2-6
...@@ -57,17 +57,13 @@ describe("normalizeCodexModelSlug", () => {...@@ -57,17 +57,13 @@ describe("normalizeCodexModelSlug", () => {
57describe("isRecoverableThreadResumeError", () => {57describe("isRecoverableThreadResumeError", () => {
58 it("matches not-found resume errors", () => {58 it("matches not-found resume errors", () => {
59 expect(59 expect(
60 isRecoverableThreadResumeError(60 isRecoverableThreadResumeError(new Error("thread/resume failed: thread not found")),
61 new Error("thread/resume failed: thread not found"),
62 ),
63 ).toBe(true);61 ).toBe(true);
64 });62 });
6563
66 it("ignores non-resume errors", () => {64 it("ignores non-resume errors", () => {
67 expect(65 expect(
68 isRecoverableThreadResumeError(66 isRecoverableThreadResumeError(new Error("thread/start failed: permission denied")),
69 new Error("thread/start failed: permission denied"),
70 ),
71 ).toBe(false);67 ).toBe(false);
72 });68 });
7369
apps/server/src/codexAppServerManager.ts+11-33
...@@ -26,9 +26,7 @@ interface PendingRequest {...@@ -26,9 +26,7 @@ interface PendingRequest {
26interface PendingApprovalRequest {26interface PendingApprovalRequest {
27 requestId: string;27 requestId: string;
28 jsonRpcId: string | number;28 jsonRpcId: string | number;
29 method:29 method: "item/commandExecution/requestApproval" | "item/fileChange/requestApproval";
30 | "item/commandExecution/requestApproval"
31 | "item/fileChange/requestApproval";
32 requestKind: ProviderRequestKind;30 requestKind: ProviderRequestKind;
33 threadId?: string;31 threadId?: string;
34 turnId?: string;32 turnId?: string;
...@@ -122,16 +120,12 @@ export function classifyCodexStderrLine(rawLine: string): { message: string } |...@@ -122,16 +120,12 @@ export function classifyCodexStderrLine(rawLine: string): { message: string } |
122}120}
123121
124export function isRecoverableThreadResumeError(error: unknown): boolean {122export function isRecoverableThreadResumeError(error: unknown): boolean {
125 const message = (123 const message = (error instanceof Error ? error.message : String(error)).toLowerCase();
126 error instanceof Error ? error.message : String(error)
127 ).toLowerCase();
128 if (!message.includes("thread/resume")) {124 if (!message.includes("thread/resume")) {
129 return false;125 return false;
130 }126 }
131127
132 return RECOVERABLE_THREAD_RESUME_ERROR_SNIPPETS.some((snippet) =>128 return RECOVERABLE_THREAD_RESUME_ERROR_SNIPPETS.some((snippet) => message.includes(snippet));
133 message.includes(snippet),
134 );
135}129}
136130
137export interface CodexAppServerManagerEvents {131export interface CodexAppServerManagerEvents {
...@@ -209,14 +203,10 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve...@@ -209,14 +203,10 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
209 if (input.resumeThreadId) {203 if (input.resumeThreadId) {
210 try {204 try {
211 threadOpenMethod = "thread/resume";205 threadOpenMethod = "thread/resume";
212 threadOpenResponse = await this.sendRequest(206 threadOpenResponse = await this.sendRequest(context, "thread/resume", {
213 context,207 ...sessionOverrides,
214 "thread/resume",208 threadId: input.resumeThreadId,
215 {209 });
216 ...sessionOverrides,
217 threadId: input.resumeThreadId,
218 },
219 );
220 } catch (error) {210 } catch (error) {
221 if (!isRecoverableThreadResumeError(error)) {211 if (!isRecoverableThreadResumeError(error)) {
222 throw error;212 throw error;
...@@ -228,19 +218,11 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve...@@ -228,19 +218,11 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
228 "session/threadResumeFallback",218 "session/threadResumeFallback",
229 `Could not resume thread ${input.resumeThreadId}; started a new thread instead.`,219 `Could not resume thread ${input.resumeThreadId}; started a new thread instead.`,
230 );220 );
231 threadOpenResponse = await this.sendRequest(221 threadOpenResponse = await this.sendRequest(context, "thread/start", threadStartParams);
232 context,
233 "thread/start",
234 threadStartParams,
235 );
236 }222 }
237 } else {223 } else {
238 threadOpenMethod = "thread/start";224 threadOpenMethod = "thread/start";
239 threadOpenResponse = await this.sendRequest(225 threadOpenResponse = await this.sendRequest(context, "thread/start", threadStartParams);
240 context,
241 "thread/start",
242 threadStartParams,
243 );
244 }226 }
245227
246 const threadOpenRecord = this.readObject(threadOpenResponse);228 const threadOpenRecord = this.readObject(threadOpenResponse);
...@@ -248,9 +230,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve...@@ -248,9 +230,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
248 this.readString(this.readObject(threadOpenRecord, "thread"), "id") ??230 this.readString(this.readObject(threadOpenRecord, "thread"), "id") ??
249 this.readString(threadOpenRecord, "threadId");231 this.readString(threadOpenRecord, "threadId");
250 if (!threadId) {232 if (!threadId) {
251 throw new Error(233 throw new Error(`${threadOpenMethod} response did not include a thread id.`);
252 `${threadOpenMethod} response did not include a thread id.`,
253 );
254 }234 }
255235
256 this.updateSession(context, {236 this.updateSession(context, {
...@@ -732,9 +712,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve...@@ -732,9 +712,7 @@ export class CodexAppServerManager extends EventEmitter<CodexAppServerManagerEve
732 };712 };
733 }713 }
734714
735 private requestKindForMethod(715 private requestKindForMethod(method: string): ProviderRequestKind | undefined {
736 method: string,
737 ): ProviderRequestKind | undefined {
738 if (method === "item/commandExecution/requestApproval") {716 if (method === "item/commandExecution/requestApproval") {
739 return "command";717 return "command";
740 }718 }
apps/server/src/git.test.ts created+423
...@@ -0,0 +1,423 @@
1import { existsSync } from "node:fs";
2import { mkdtemp, rm, writeFile } from "node:fs/promises";
3import { tmpdir } from "node:os";
4import path from "node:path";
5import { describe, expect, it } from "vitest";
6
7import {
8 checkoutGitBranch,
9 createGitBranch,
10 createGitWorktree,
11 initGitRepo,
12 listGitBranches,
13 removeGitWorktree,
14 runTerminalCommand,
15} from "./git";
16
17// ── Helpers ──
18
19/** Run a raw git command for test setup (not under test). */
20async function git(cwd: string, command: string): Promise<string> {
21 const result = await runTerminalCommand({
22 command: `git ${command}`,
23 cwd,
24 timeoutMs: 10_000,
25 });
26 if (result.code !== 0) {
27 throw new Error(`git ${command} failed: ${result.stderr}`);
28 }
29 return result.stdout.trim();
30}
31
32/** Create a disposable temp directory that cleans up automatically. */
33async function makeTmpDir() {
34 const dir = await mkdtemp(path.join(tmpdir(), "git-test-"));
35 return {
36 path: dir,
37 [Symbol.asyncDispose]: async () => {
38 await rm(dir, { recursive: true, force: true });
39 },
40 };
41}
42
43/** Create a repo with an initial commit so branches work. */
44async function initRepoWithCommit(cwd: string): Promise<void> {
45 await initGitRepo({ cwd });
46 await git(cwd, "config user.email 'test@test.com'");
47 await git(cwd, "config user.name 'Test'");
48 await writeFile(path.join(cwd, "README.md"), "# test\n");
49 await git(cwd, "add .");
50 await git(cwd, "commit -m 'initial commit'");
51}
52
53// ── Tests ──
54
55describe("git integration", () => {
56 // ── initGitRepo ──
57
58 describe("initGitRepo", () => {
59 it("creates a valid git repo", async () => {
60 await using tmp = await makeTmpDir();
61 await initGitRepo({ cwd: tmp.path });
62 expect(existsSync(path.join(tmp.path, ".git"))).toBe(true);
63 });
64
65 it("listGitBranches reports isRepo: true after init + commit", async () => {
66 await using tmp = await makeTmpDir();
67 await initRepoWithCommit(tmp.path);
68 const result = await listGitBranches({ cwd: tmp.path });
69 expect(result.isRepo).toBe(true);
70 expect(result.branches.length).toBeGreaterThanOrEqual(1);
71 });
72 });
73
74 // ── listGitBranches ──
75
76 describe("listGitBranches", () => {
77 it("returns isRepo: false for non-git directory", async () => {
78 await using tmp = await makeTmpDir();
79 const result = await listGitBranches({ cwd: tmp.path });
80 expect(result.isRepo).toBe(false);
81 expect(result.branches).toEqual([]);
82 });
83
84 it("returns the current branch with current: true", async () => {
85 await using tmp = await makeTmpDir();
86 await initRepoWithCommit(tmp.path);
87 const result = await listGitBranches({ cwd: tmp.path });
88 const current = result.branches.find((b) => b.current);
89 expect(current).toBeDefined();
90 expect(current!.current).toBe(true);
91 });
92
93 it("sorts current branch first", async () => {
94 await using tmp = await makeTmpDir();
95 await initRepoWithCommit(tmp.path);
96 await createGitBranch({ cwd: tmp.path, branch: "aaa-first-alpha" });
97 await createGitBranch({ cwd: tmp.path, branch: "zzz-last" });
98
99 const result = await listGitBranches({ cwd: tmp.path });
100 expect(result.branches[0]!.current).toBe(true);
101 });
102
103 it("lists multiple branches after creating them", async () => {
104 await using tmp = await makeTmpDir();
105 await initRepoWithCommit(tmp.path);
106 await createGitBranch({ cwd: tmp.path, branch: "feature-a" });
107 await createGitBranch({ cwd: tmp.path, branch: "feature-b" });
108
109 const result = await listGitBranches({ cwd: tmp.path });
110 const names = result.branches.map((b) => b.name);
111 expect(names).toContain("feature-a");
112 expect(names).toContain("feature-b");
113 });
114
115 it("isDefault is false when no remote exists", async () => {
116 await using tmp = await makeTmpDir();
117 await initRepoWithCommit(tmp.path);
118 const result = await listGitBranches({ cwd: tmp.path });
119 expect(result.branches.every((b) => b.isDefault === false)).toBe(true);
120 });
121 });
122
123 // ── checkoutGitBranch ──
124
125 describe("checkoutGitBranch", () => {
126 it("checks out an existing branch", async () => {
127 await using tmp = await makeTmpDir();
128 await initRepoWithCommit(tmp.path);
129 await createGitBranch({ cwd: tmp.path, branch: "feature" });
130
131 await checkoutGitBranch({ cwd: tmp.path, branch: "feature" });
132
133 const result = await listGitBranches({ cwd: tmp.path });
134 const current = result.branches.find((b) => b.current);
135 expect(current!.name).toBe("feature");
136 });
137
138 it("throws when branch does not exist", async () => {
139 await using tmp = await makeTmpDir();
140 await initRepoWithCommit(tmp.path);
141 await expect(checkoutGitBranch({ cwd: tmp.path, branch: "nonexistent" })).rejects.toThrow();
142 });
143
144 it("throws when checkout would overwrite uncommitted changes", async () => {
145 await using tmp = await makeTmpDir();
146 await initRepoWithCommit(tmp.path);
147 await createGitBranch({ cwd: tmp.path, branch: "other" });
148
149 // Create a conflicting change: modify README on current branch
150 await writeFile(path.join(tmp.path, "README.md"), "modified\n");
151 await git(tmp.path, "add README.md");
152
153 // First, checkout other branch cleanly
154 await git(tmp.path, "stash");
155 await checkoutGitBranch({ cwd: tmp.path, branch: "other" });
156 await writeFile(path.join(tmp.path, "README.md"), "other content\n");
157 await git(tmp.path, "add .");
158 await git(tmp.path, "commit -m 'other change'");
159
160 // Go back to default branch
161 const defaultBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
162 (b) => !b.current,
163 )!.name;
164 await checkoutGitBranch({ cwd: tmp.path, branch: defaultBranch });
165
166 // Make uncommitted changes to the same file
167 await writeFile(path.join(tmp.path, "README.md"), "conflicting local\n");
168
169 // Checkout should fail due to uncommitted changes
170 await expect(checkoutGitBranch({ cwd: tmp.path, branch: "other" })).rejects.toThrow();
171 });
172 });
173
174 // ── createGitBranch ──
175
176 describe("createGitBranch", () => {
177 it("creates a new branch visible in listGitBranches", async () => {
178 await using tmp = await makeTmpDir();
179 await initRepoWithCommit(tmp.path);
180 await createGitBranch({ cwd: tmp.path, branch: "new-feature" });
181
182 const result = await listGitBranches({ cwd: tmp.path });
183 expect(result.branches.some((b) => b.name === "new-feature")).toBe(true);
184 });
185
186 it("throws when branch already exists", async () => {
187 await using tmp = await makeTmpDir();
188 await initRepoWithCommit(tmp.path);
189 await createGitBranch({ cwd: tmp.path, branch: "dupe" });
190 await expect(createGitBranch({ cwd: tmp.path, branch: "dupe" })).rejects.toThrow();
191 });
192 });
193
194 // ── createGitWorktree + removeGitWorktree ──
195
196 describe("createGitWorktree", () => {
197 it("creates a worktree with a new branch from the base branch", async () => {
198 await using tmp = await makeTmpDir();
199 await initRepoWithCommit(tmp.path);
200
201 const wtPath = path.join(tmp.path, "worktree-out");
202 const currentBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
203 (b) => b.current,
204 )!.name;
205
206 const result = await createGitWorktree({
207 cwd: tmp.path,
208 branch: currentBranch,
209 newBranch: "wt-branch",
210 path: wtPath,
211 });
212
213 expect(result.worktree.path).toBe(wtPath);
214 expect(result.worktree.branch).toBe("wt-branch");
215 expect(existsSync(wtPath)).toBe(true);
216 expect(existsSync(path.join(wtPath, "README.md"))).toBe(true);
217
218 // Clean up worktree before tmp dir disposal
219 await removeGitWorktree({ cwd: tmp.path, path: wtPath });
220 });
221
222 it("worktree has the new branch checked out", async () => {
223 await using tmp = await makeTmpDir();
224 await initRepoWithCommit(tmp.path);
225
226 const wtPath = path.join(tmp.path, "wt-check-dir");
227 const currentBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
228 (b) => b.current,
229 )!.name;
230
231 await createGitWorktree({
232 cwd: tmp.path,
233 branch: currentBranch,
234 newBranch: "wt-check",
235 path: wtPath,
236 });
237
238 // Verify the worktree is on the new branch
239 const branchOutput = await git(wtPath, "branch --show-current");
240 expect(branchOutput).toBe("wt-check");
241
242 await removeGitWorktree({ cwd: tmp.path, path: wtPath });
243 });
244
245 it("throws when new branch name already exists", async () => {
246 await using tmp = await makeTmpDir();
247 await initRepoWithCommit(tmp.path);
248 await createGitBranch({ cwd: tmp.path, branch: "existing" });
249
250 const wtPath = path.join(tmp.path, "wt-conflict");
251 const currentBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
252 (b) => b.current,
253 )!.name;
254
255 await expect(
256 createGitWorktree({
257 cwd: tmp.path,
258 branch: currentBranch,
259 newBranch: "existing",
260 path: wtPath,
261 }),
262 ).rejects.toThrow();
263 });
264
265 it("listGitBranches from worktree cwd reports worktree branch as current", async () => {
266 await using tmp = await makeTmpDir();
267 await initRepoWithCommit(tmp.path);
268
269 const wtPath = path.join(tmp.path, "wt-list-dir");
270 const mainBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
271 (b) => b.current,
272 )!.name;
273
274 await createGitWorktree({
275 cwd: tmp.path,
276 branch: mainBranch,
277 newBranch: "wt-list",
278 path: wtPath,
279 });
280
281 // listGitBranches from the worktree should show wt-list as current
282 const wtBranches = await listGitBranches({ cwd: wtPath });
283 expect(wtBranches.isRepo).toBe(true);
284 const wtCurrent = wtBranches.branches.find((b) => b.current);
285 expect(wtCurrent!.name).toBe("wt-list");
286
287 // Main repo should still show the original branch as current
288 const mainBranches = await listGitBranches({ cwd: tmp.path });
289 const mainCurrent = mainBranches.branches.find((b) => b.current);
290 expect(mainCurrent!.name).toBe(mainBranch);
291
292 await removeGitWorktree({ cwd: tmp.path, path: wtPath });
293 });
294
295 it("removeGitWorktree cleans up the worktree", async () => {
296 await using tmp = await makeTmpDir();
297 await initRepoWithCommit(tmp.path);
298
299 const wtPath = path.join(tmp.path, "wt-remove-dir");
300 const currentBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
301 (b) => b.current,
302 )!.name;
303
304 await createGitWorktree({
305 cwd: tmp.path,
306 branch: currentBranch,
307 newBranch: "wt-remove",
308 path: wtPath,
309 });
310 expect(existsSync(wtPath)).toBe(true);
311
312 await removeGitWorktree({ cwd: tmp.path, path: wtPath });
313 expect(existsSync(wtPath)).toBe(false);
314 });
315 });
316
317 // ── Full flow: local branch checkout ──
318
319 describe("full flow: local branch checkout", () => {
320 it("init → commit → create branch → checkout → verify current", async () => {
321 await using tmp = await makeTmpDir();
322 await initRepoWithCommit(tmp.path);
323 await createGitBranch({ cwd: tmp.path, branch: "feature-login" });
324 await checkoutGitBranch({ cwd: tmp.path, branch: "feature-login" });
325
326 const result = await listGitBranches({ cwd: tmp.path });
327 const current = result.branches.find((b) => b.current);
328 expect(current!.name).toBe("feature-login");
329 });
330 });
331
332 // ── Full flow: worktree creation from base branch ──
333
334 describe("full flow: worktree creation", () => {
335 it("creates worktree with new branch from current branch", async () => {
336 await using tmp = await makeTmpDir();
337 await initRepoWithCommit(tmp.path);
338
339 const currentBranch = (await listGitBranches({ cwd: tmp.path })).branches.find(
340 (b) => b.current,
341 )!.name;
342
343 const wtPath = path.join(tmp.path, "my-worktree");
344 const result = await createGitWorktree({
345 cwd: tmp.path,
346 branch: currentBranch,
347 newBranch: "feature-wt",
348 path: wtPath,
349 });
350
351 // Worktree exists
352 expect(existsSync(result.worktree.path)).toBe(true);
353
354 // Main repo still on original branch
355 const mainBranches = await listGitBranches({ cwd: tmp.path });
356 const mainCurrent = mainBranches.branches.find((b) => b.current);
357 expect(mainCurrent!.name).toBe(currentBranch);
358
359 // Worktree is on the new branch
360 const wtBranch = await git(wtPath, "branch --show-current");
361 expect(wtBranch).toBe("feature-wt");
362
363 await removeGitWorktree({ cwd: tmp.path, path: wtPath });
364 });
365 });
366
367 // ── Full flow: thread switching simulation ──
368
369 describe("full flow: thread switching (checkout toggling)", () => {
370 it("checkout a → checkout b → checkout a → current matches", async () => {
371 await using tmp = await makeTmpDir();
372 await initRepoWithCommit(tmp.path);
373 await createGitBranch({ cwd: tmp.path, branch: "branch-a" });
374 await createGitBranch({ cwd: tmp.path, branch: "branch-b" });
375
376 // Simulate switching to thread A's branch
377 await checkoutGitBranch({ cwd: tmp.path, branch: "branch-a" });
378 let branches = await listGitBranches({ cwd: tmp.path });
379 expect(branches.branches.find((b) => b.current)!.name).toBe("branch-a");
380
381 // Simulate switching to thread B's branch
382 await checkoutGitBranch({ cwd: tmp.path, branch: "branch-b" });
383 branches = await listGitBranches({ cwd: tmp.path });
384 expect(branches.branches.find((b) => b.current)!.name).toBe("branch-b");
385
386 // Switch back to thread A
387 await checkoutGitBranch({ cwd: tmp.path, branch: "branch-a" });
388 branches = await listGitBranches({ cwd: tmp.path });
389 expect(branches.branches.find((b) => b.current)!.name).toBe("branch-a");
390 });
391 });
392
393 // ── Full flow: checkout conflict ──
394
395 describe("full flow: checkout conflict", () => {
396 it("uncommitted changes prevent checkout to a diverged branch", async () => {
397 await using tmp = await makeTmpDir();
398 await initRepoWithCommit(tmp.path);
399 await createGitBranch({ cwd: tmp.path, branch: "diverged" });
400
401 // Make diverged branch have different file content
402 await checkoutGitBranch({ cwd: tmp.path, branch: "diverged" });
403 await writeFile(path.join(tmp.path, "README.md"), "diverged content\n");
404 await git(tmp.path, "add .");
405 await git(tmp.path, "commit -m 'diverge'");
406
407 // Actually, let's just get back to the initial branch explicitly
408 const allBranches = await listGitBranches({ cwd: tmp.path });
409 const initialBranch = allBranches.branches.find((b) => b.name !== "diverged")!.name;
410 await checkoutGitBranch({ cwd: tmp.path, branch: initialBranch });
411
412 // Make local uncommitted changes to the same file
413 await writeFile(path.join(tmp.path, "README.md"), "local uncommitted\n");
414
415 // Attempt checkout should fail
416 await expect(checkoutGitBranch({ cwd: tmp.path, branch: "diverged" })).rejects.toThrow();
417
418 // Current branch should still be the initial one
419 const result = await listGitBranches({ cwd: tmp.path });
420 expect(result.branches.find((b) => b.current)!.name).toBe(initialBranch);
421 });
422 });
423});
apps/server/src/git.ts created+229
...@@ -0,0 +1,229 @@
1import { spawn } from "node:child_process";
2import fs from "node:fs";
3import os from "node:os";
4import path from "node:path";
5
6import type {
7 GitCheckoutInput,
8 GitCreateBranchInput,
9 GitCreateWorktreeInput,
10 GitCreateWorktreeResult,
11 GitInitInput,
12 GitListBranchesInput,
13 GitListBranchesResult,
14 GitRemoveWorktreeInput,
15 TerminalCommandInput,
16 TerminalCommandResult,
17} from "@t3tools/contracts";
18
19/** Spawn git directly with an argv array — no shell, no quoting needed. */
20function runGit(args: string[], cwd: string, timeoutMs = 30_000): Promise<TerminalCommandResult> {
21 return new Promise((resolve, reject) => {
22 const child = spawn("git", args, {
23 cwd,
24 env: process.env,
25 stdio: ["ignore", "pipe", "pipe"],
26 });
27
28 let stdout = "";
29 let stderr = "";
30 let timedOut = false;
31
32 const timeout = setTimeout(() => {
33 timedOut = true;
34 child.kill("SIGTERM");
35 setTimeout(() => {
36 if (!child.killed) child.kill("SIGKILL");
37 }, 1_000).unref();
38 }, timeoutMs);
39
40 child.stdout?.on("data", (chunk: Buffer) => {
41 stdout += chunk.toString();
42 });
43 child.stderr?.on("data", (chunk: Buffer) => {
44 stderr += chunk.toString();
45 });
46 child.on("error", (error) => {
47 clearTimeout(timeout);
48 reject(error);
49 });
50 child.on("close", (code, signal) => {
51 clearTimeout(timeout);
52 resolve({ stdout, stderr, code: code ?? null, signal: signal ?? null, timedOut });
53 });
54 });
55}
56
57export async function runTerminalCommand(
58 input: TerminalCommandInput,
59): Promise<TerminalCommandResult> {
60 const shellPath =
61 process.platform === "win32"
62 ? (process.env.ComSpec ?? "cmd.exe")
63 : (process.env.SHELL ?? "/bin/sh");
64
65 const args =
66 process.platform === "win32" ? ["/d", "/s", "/c", input.command] : ["-lc", input.command];
67
68 return new Promise((resolve, reject) => {
69 const child = spawn(shellPath, args, {
70 cwd: input.cwd,
71 env: process.env,
72 stdio: ["ignore", "pipe", "pipe"],
73 });
74
75 let stdout = "";
76 let stderr = "";
77 let timedOut = false;
78
79 const timeout = setTimeout(() => {
80 timedOut = true;
81 child.kill("SIGTERM");
82 setTimeout(() => {
83 if (!child.killed) {
84 child.kill("SIGKILL");
85 }
86 }, 1_000).unref();
87 }, input.timeoutMs ?? 30_000);
88
89 child.stdout?.on("data", (chunk: Buffer) => {
90 stdout += chunk.toString();
91 });
92
93 child.stderr?.on("data", (chunk: Buffer) => {
94 stderr += chunk.toString();
95 });
96
97 child.on("error", (error) => {
98 clearTimeout(timeout);
99 reject(error);
100 });
101
102 child.on("close", (code, signal) => {
103 clearTimeout(timeout);
104 resolve({
105 stdout,
106 stderr,
107 code: code ?? null,
108 signal: signal ?? null,
109 timedOut,
110 });
111 });
112 });
113}
114
115export async function listGitBranches(input: GitListBranchesInput): Promise<GitListBranchesResult> {
116 const result = await runGit(["branch", "--no-color"], input.cwd, 10_000);
117
118 if (result.code !== 0) {
119 const stderr = result.stderr.trim();
120 if (stderr.includes("not a git repository")) {
121 return { branches: [], isRepo: false };
122 }
123 throw new Error(stderr || "git branch failed");
124 }
125
126 // Resolve the real default branch from the remote
127 const [defaultRef, worktreeList] = await Promise.all([
128 runGit(["symbolic-ref", "refs/remotes/origin/HEAD"], input.cwd, 5_000),
129 runGit(["worktree", "list", "--porcelain"], input.cwd, 5_000),
130 ]);
131 const defaultBranch =
132 defaultRef.code === 0 ? defaultRef.stdout.trim().replace(/^refs\/remotes\/origin\//, "") : null;
133
134 // Build branch-name → worktree-path map from porcelain output.
135 // Only include worktrees whose directories still exist on disk (skip prunable/stale ones).
136 const worktreeMap = new Map<string, string>();
137 if (worktreeList.code === 0) {
138 let currentPath: string | null = null;
139 for (const line of worktreeList.stdout.split("\n")) {
140 if (line.startsWith("worktree ")) {
141 currentPath = line.slice("worktree ".length);
142 if (!fs.existsSync(currentPath)) currentPath = null;
143 } else if (line.startsWith("branch refs/heads/") && currentPath) {
144 worktreeMap.set(line.slice("branch refs/heads/".length), currentPath);
145 } else if (line === "") {
146 currentPath = null;
147 }
148 }
149 }
150
151 const branches = result.stdout
152 .split("\n")
153 .map((line) => line.trim())
154 .filter((line) => line.length > 0)
155 .map((line) => {
156 const name = line.replace(/^[*+]\s+/, "");
157 return {
158 name,
159 current: line.startsWith("* "),
160 isDefault: name === defaultBranch,
161 worktreePath: worktreeMap.get(name) ?? null,
162 };
163 })
164 .toSorted((a, b) => {
165 if (a.current !== b.current) return a.current ? -1 : 1;
166 if (a.isDefault !== b.isDefault) return a.isDefault ? -1 : 1;
167 return a.name.localeCompare(b.name);
168 });
169
170 return { branches, isRepo: true };
171}
172
173export async function createGitWorktree(
174 input: GitCreateWorktreeInput,
175): Promise<GitCreateWorktreeResult> {
176 const sanitizedBranch = input.newBranch.replace(/\//g, "-");
177 const repoName = path.basename(input.cwd);
178 const worktreePath =
179 input.path ?? path.join(os.homedir(), ".t3", "worktrees", repoName, sanitizedBranch);
180
181 // Create a new branch from the base branch in a new worktree
182 const result = await runGit(
183 ["worktree", "add", "-b", input.newBranch, worktreePath, input.branch],
184 input.cwd,
185 );
186
187 if (result.code !== 0) {
188 throw new Error(result.stderr.trim() || "git worktree add failed");
189 }
190
191 return {
192 worktree: {
193 path: worktreePath,
194 branch: input.newBranch,
195 },
196 };
197}
198
199export async function removeGitWorktree(input: GitRemoveWorktreeInput): Promise<void> {
200 const result = await runGit(["worktree", "remove", input.path], input.cwd, 15_000);
201
202 if (result.code !== 0) {
203 throw new Error(result.stderr.trim() || "git worktree remove failed");
204 }
205}
206
207export async function createGitBranch(input: GitCreateBranchInput): Promise<void> {
208 const result = await runGit(["branch", input.branch], input.cwd, 10_000);
209
210 if (result.code !== 0) {
211 throw new Error(result.stderr.trim() || "git branch create failed");
212 }
213}
214
215export async function checkoutGitBranch(input: GitCheckoutInput): Promise<void> {
216 const result = await runGit(["checkout", input.branch], input.cwd, 10_000);
217
218 if (result.code !== 0) {
219 throw new Error(result.stderr.trim() || "git checkout failed");
220 }
221}
222
223export async function initGitRepo(input: GitInitInput): Promise<void> {
224 const result = await runGit(["init"], input.cwd, 10_000);
225
226 if (result.code !== 0) {
227 throw new Error(result.stderr.trim() || "git init failed");
228 }
229}
apps/server/src/providerManager.test.ts+1-4
...@@ -16,10 +16,7 @@ describe("ProviderManager", () => {...@@ -16,10 +16,7 @@ describe("ProviderManager", () => {
16 method: string;16 method: string;
17 threadId: string;17 threadId: string;
18 }) => void;18 }) => void;
19 threadLogStreams: Map<19 threadLogStreams: Map<string, { writableEnded: boolean; destroyed: boolean }>;
20 string,
21 { writableEnded: boolean; destroyed: boolean }
22 >;
23 };20 };
24 internals.onCodexEvent({21 internals.onCodexEvent({
25 id: "evt-1",22 id: "evt-1",
apps/server/src/providerManager.ts+2-9
...@@ -87,11 +87,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -87,11 +87,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
87 throw new Error(`Unknown provider session: ${input.sessionId}`);87 throw new Error(`Unknown provider session: ${input.sessionId}`);
88 }88 }
8989
90 await this.codex.respondToRequest(90 await this.codex.respondToRequest(input.sessionId, input.requestId, input.decision);
91 input.sessionId,
92 input.requestId,
93 input.decision,
94 );
95 }91 }
9692
97 stopSession(raw: ProviderStopSessionInput): void {93 stopSession(raw: ProviderStopSessionInput): void {
...@@ -151,10 +147,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {...@@ -151,10 +147,7 @@ export class ProviderManager extends EventEmitter<ProviderManagerEvents> {
151147
152 private resolveThreadId(event: ProviderEvent): string | undefined {148 private resolveThreadId(event: ProviderEvent): string | undefined {
153 const fromPayload = this.readThreadIdFromPayload(event.payload);149 const fromPayload = this.readThreadIdFromPayload(event.payload);
154 const threadId =150 const threadId = event.threadId ?? fromPayload ?? this.sessionThreadIds.get(event.sessionId);
155 event.threadId ??
156 fromPayload ??
157 this.sessionThreadIds.get(event.sessionId);
158151
159 if (threadId) {152 if (threadId) {
160 this.sessionThreadIds.set(event.sessionId, threadId);153 this.sessionThreadIds.set(event.sessionId, threadId);
apps/server/src/wsServer.test.ts+26
...@@ -281,6 +281,32 @@ describe("WebSocket Server", () => {...@@ -281,6 +281,32 @@ describe("WebSocket Server", () => {
281 expect(afterRemove.result).toEqual([]);281 expect(afterRemove.result).toEqual([]);
282 });282 });
283283
284 it("supports git methods over websocket", async () => {
285 const repoCwd = makeTempDir("t3code-ws-git-project-");
286
287 server = createTestServer({ cwd: "/test" });
288 await server.start();
289 const addr = server.httpServer.address();
290 const port = typeof addr === "object" && addr !== null ? addr.port : 0;
291
292 const ws = await connectWs(port);
293 connections.push(ws);
294 await waitForMessage(ws);
295
296 const beforeInit = await sendRequest(ws, WS_METHODS.gitListBranches, { cwd: repoCwd });
297 expect(beforeInit.error).toBeUndefined();
298 expect(beforeInit.result).toEqual({ branches: [], isRepo: false });
299
300 const initResponse = await sendRequest(ws, WS_METHODS.gitInit, { cwd: repoCwd });
301 expect(initResponse.error).toBeUndefined();
302
303 const afterInit = await sendRequest(ws, WS_METHODS.gitListBranches, {
304 cwd: repoCwd,
305 });
306 expect(afterInit.error).toBeUndefined();
307 expect((afterInit.result as { isRepo: boolean }).isRepo).toBe(true);
308 });
309
284 it("prunes missing projects on startup", async () => {310 it("prunes missing projects on startup", async () => {
285 const stateDir = makeTempDir("t3code-ws-prune-state-");311 const stateDir = makeTempDir("t3code-ws-prune-state-");
286 const existing = makeTempDir("t3code-ws-existing-project-");312 const existing = makeTempDir("t3code-ws-existing-project-");
apps/server/src/wsServer.ts+30-1
...@@ -19,6 +19,14 @@ import { WebSocketServer, type WebSocket } from "ws";...@@ -19,6 +19,14 @@ import { WebSocketServer, type WebSocket } from "ws";
19import { createLogger } from "./logger";19import { createLogger } from "./logger";
20import { ProjectRegistry } from "./projectRegistry";20import { ProjectRegistry } from "./projectRegistry";
21import { ProviderManager } from "./providerManager";21import { ProviderManager } from "./providerManager";
22import {
23 checkoutGitBranch,
24 createGitBranch,
25 createGitWorktree,
26 initGitRepo,
27 listGitBranches,
28 removeGitWorktree,
29} from "./git";
2230
23const MIME_TYPES: Record<string, string> = {31const MIME_TYPES: Record<string, string> = {
24 ".html": "text/html; charset=utf-8",32 ".html": "text/html; charset=utf-8",
...@@ -304,6 +312,24 @@ export function createServer(options: ServerOptions) {...@@ -304,6 +312,24 @@ export function createServer(options: ServerOptions) {
304 return undefined;312 return undefined;
305 }313 }
306314
315 case WS_METHODS.gitListBranches:
316 return listGitBranches(request.params as never);
317
318 case WS_METHODS.gitCreateWorktree:
319 return createGitWorktree(request.params as never);
320
321 case WS_METHODS.gitRemoveWorktree:
322 return removeGitWorktree(request.params as never);
323
324 case WS_METHODS.gitCreateBranch:
325 return createGitBranch(request.params as never);
326
327 case WS_METHODS.gitCheckout:
328 return checkoutGitBranch(request.params as never);
329
330 case WS_METHODS.gitInit:
331 return initGitRepo(request.params as never);
332
307 case WS_METHODS.serverGetConfig:333 case WS_METHODS.serverGetConfig:
308 return { cwd };334 return { cwd };
309335
...@@ -343,7 +369,10 @@ export function createServer(options: ServerOptions) {...@@ -343,7 +369,10 @@ export function createServer(options: ServerOptions) {
343 const isServerNotRunningError = (error: unknown): boolean => {369 const isServerNotRunningError = (error: unknown): boolean => {
344 if (!(error instanceof Error)) return false;370 if (!(error instanceof Error)) return false;
345 const maybeCode = (error as NodeJS.ErrnoException).code;371 const maybeCode = (error as NodeJS.ErrnoException).code;
346 return maybeCode === "ERR_SERVER_NOT_RUNNING" || error.message.toLowerCase().includes("not running");372 return (
373 maybeCode === "ERR_SERVER_NOT_RUNNING" ||
374 error.message.toLowerCase().includes("not running")
375 );
347 };376 };
348377
349 const closeWebSocketServer = new Promise<void>((resolve, reject) => {378 const closeWebSocketServer = new Promise<void>((resolve, reject) => {
apps/server/tsconfig.json+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3 "compilerOptions": {3 "compilerOptions": {
4 "composite": true,4 "composite": true,
5 "types": ["node"],5 "types": ["node"],
6 "lib": ["ES2023"]6 "lib": ["ES2023", "esnext.disposable"]
7 },7 },
8 "include": ["src", "tsup.config.ts"]8 "include": ["src", "tsdown.config.ts"]
9}9}
apps/server/tsdown.config.ts created+14
...@@ -0,0 +1,14 @@
1import { defineConfig } from "tsdown";
2
3export default defineConfig({
4 entry: ["src/index.ts"],
5 format: ["esm", "cjs"],
6 outDir: "dist",
7 sourcemap: true,
8 clean: true,
9 noExternal: ["@t3tools/contracts", "zod"],
10 inlineOnly: false,
11 banner: {
12 js: "#!/usr/bin/env node\n",
13 },
14});
apps/server/tsup.config.ts deleted-13
...@@ -1,13 +0,0 @@
1import { defineConfig } from "tsup";
2
3export default defineConfig({
4 entry: ["src/index.ts"],
5 format: "esm",
6 outDir: "dist",
7 sourcemap: true,
8 clean: true,
9 noExternal: ["@t3tools/contracts"],
10 banner: {
11 js: '#!/usr/bin/env node\n',
12 },
13});
apps/server/turbo.jsonc created+11
...@@ -0,0 +1,11 @@
1{
2 "$schema": "https://turbo.build/schema.json",
3 "extends": ["//"],
4 "tasks": {
5 "start": {
6 "dependsOn": ["build"],
7 "cache": false,
8 "persistent": true,
9 },
10 },
11}
apps/web/index.html+4-1
...@@ -5,7 +5,10 @@...@@ -5,7 +5,10 @@
5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />5 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6 <link rel="preconnect" href="https://fonts.googleapis.com" />6 <link rel="preconnect" href="https://fonts.googleapis.com" />
7 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />7 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
8 <link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..800;1,9..40,300..800&display=swap" rel="stylesheet" />8 <link
9 href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300..800;1,9..40,300..800&display=swap"
10 rel="stylesheet"
11 />
9 <title>T3 Code</title>12 <title>T3 Code</title>
10 </head>13 </head>
11 <body>14 <body>
apps/web/package.json+3-2
...@@ -12,6 +12,7 @@...@@ -12,6 +12,7 @@
12 },12 },
13 "dependencies": {13 "dependencies": {
14 "@t3tools/contracts": "workspace:*",14 "@t3tools/contracts": "workspace:*",
15 "@tanstack/react-query": "^5.90.0",
15 "highlight.js": "^11.11.1",16 "highlight.js": "^11.11.1",
16 "lucide-react": "^0.563.0",17 "lucide-react": "^0.563.0",
17 "react": "^19.0.0",18 "react": "^19.0.0",
...@@ -25,10 +26,10 @@...@@ -25,10 +26,10 @@
25 "@tailwindcss/vite": "^4.0.0",26 "@tailwindcss/vite": "^4.0.0",
26 "@types/react": "^19.0.0",27 "@types/react": "^19.0.0",
27 "@types/react-dom": "^19.0.0",28 "@types/react-dom": "^19.0.0",
28 "@vitejs/plugin-react": "^4.3.4",29 "@vitejs/plugin-react": "^5.1.4",
29 "babel-plugin-react-compiler": "^19.0.0-beta-e552027-20250112",30 "babel-plugin-react-compiler": "^19.0.0-beta-e552027-20250112",
30 "tailwindcss": "^4.0.0",31 "tailwindcss": "^4.0.0",
31 "typescript": "^5.7.3",32 "typescript": "^5.7.3",
32 "vite": "^6.0.5"33 "vite": "^8.0.0-beta.12"
33 }34 }
34}35}
apps/web/src/App.tsx+10-3
...@@ -1,3 +1,4 @@...@@ -1,3 +1,4 @@
1import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
1import { useEffect, useMemo, useRef } from "react";2import { useEffect, useMemo, useRef } from "react";
23
3import ChatView from "./components/ChatView";4import ChatView from "./components/ChatView";
...@@ -82,6 +83,8 @@ function AutoProjectBootstrap() {...@@ -82,6 +83,8 @@ function AutoProjectBootstrap() {
82 events: [],83 events: [],
83 error: null,84 error: null,
84 createdAt: new Date().toISOString(),85 createdAt: new Date().toISOString(),
86 branch: null,
87 worktreePath: null,
85 },88 },
86 });89 });
87 });90 });
...@@ -166,10 +169,14 @@ function Layout() {...@@ -166,10 +169,14 @@ function Layout() {
166 );169 );
167}170}
168171
172const queryClient = new QueryClient();
173
169export default function App() {174export default function App() {
170 return (175 return (
171 <StoreProvider>176 <QueryClientProvider client={queryClient}>
172 <Layout />177 <StoreProvider>
173 </StoreProvider>178 <Layout />
179 </StoreProvider>
180 </QueryClientProvider>
174 );181 );
175}182}
apps/web/src/components/BranchToolbar.tsx created+315
...@@ -0,0 +1,315 @@
1import type { GitBranch } from "@t3tools/contracts";
2import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
3import { useEffect, useMemo, useRef, useState } from "react";
4
5import { readNativeApi } from "../session-logic";
6import { useStore } from "../store";
7
8interface BranchToolbarProps {
9 envMode: "local" | "worktree";
10 onEnvModeChange: (mode: "local" | "worktree") => void;
11 envLocked: boolean;
12}
13
14export default function BranchToolbar({ envMode, onEnvModeChange, envLocked }: BranchToolbarProps) {
15 const { state, dispatch } = useStore();
16 const api = useMemo(() => readNativeApi(), []);
17 const queryClient = useQueryClient();
18
19 const [isBranchMenuOpen, setIsBranchMenuOpen] = useState(false);
20 const [isCreatingBranch, setIsCreatingBranch] = useState(false);
21 const [newBranchName, setNewBranchName] = useState("");
22 const branchMenuRef = useRef<HTMLDivElement>(null);
23
24 const activeThread = state.threads.find((thread) => thread.id === state.activeThreadId);
25 const activeProject = state.projects.find((project) => project.id === activeThread?.projectId);
26 const activeThreadId = activeThread?.id;
27 const activeThreadBranch = activeThread?.branch ?? null;
28 const activeWorktreePath = activeThread?.worktreePath ?? null;
29 const branchCwd = activeWorktreePath ?? activeProject?.cwd;
30
31 // ── Queries ───────────────────────────────────────────────────────────
32
33 const branchesQuery = useQuery({
34 queryKey: ["git", "branches", branchCwd],
35 queryFn: () => api!.git.listBranches({ cwd: branchCwd! }),
36 enabled: !!api && !!branchCwd,
37 });
38
39 const branches = branchesQuery.data?.branches ?? [];
40 // Default to true while loading — showing "Initialize git" during a fetch is wrong,
41 // and worktrees are inherently git repos.
42 const isRepo = branchesQuery.data?.isRepo ?? !branchesQuery.isLoading;
43
44 // ── Mutations ─────────────────────────────────────────────────────────
45
46 const checkoutMutation = useMutation({
47 mutationFn: (branch: string) => api!.git.checkout({ cwd: branchCwd!, branch }),
48 onSuccess: () => queryClient.invalidateQueries({ queryKey: ["git", "branches", branchCwd] }),
49 onError: (error) =>
50 setThreadError(error instanceof Error ? error.message : "Failed to checkout branch."),
51 });
52
53 const createBranchMutation = useMutation({
54 mutationFn: (branch: string) =>
55 api!.git
56 .createBranch({ cwd: branchCwd!, branch })
57 .then(() => api!.git.checkout({ cwd: branchCwd!, branch })),
58 onSuccess: () => queryClient.invalidateQueries({ queryKey: ["git", "branches", branchCwd] }),
59 onError: (error) =>
60 setThreadError(error instanceof Error ? error.message : "Failed to create branch."),
61 });
62
63 const initMutation = useMutation({
64 mutationFn: () => api!.git.init({ cwd: branchCwd! }),
65 onSuccess: () => {
66 setThreadError(null);
67 queryClient.invalidateQueries({ queryKey: ["git", "branches", branchCwd] });
68 },
69 onError: (error) =>
70 setThreadError(error instanceof Error ? error.message : "Failed to initialize git repo."),
71 });
72
73 // ── Effects ───────────────────────────────────────────────────────────
74
75 // Keep thread branch synced to git current branch for local threads.
76 const queryBranches = branchesQuery.data?.branches;
77 useEffect(() => {
78 if (!activeThreadId || activeWorktreePath) return;
79 const current = queryBranches?.find((branch) => branch.current);
80 if (!current) return;
81 if (current.name === activeThreadBranch) return;
82 dispatch({
83 type: "SET_THREAD_BRANCH",
84 threadId: activeThreadId,
85 branch: current.name,
86 worktreePath: null,
87 });
88 }, [activeThreadId, activeWorktreePath, activeThreadBranch, queryBranches, dispatch]);
89
90 useEffect(() => {
91 if (!isBranchMenuOpen) return;
92 const handleClickOutside = (event: MouseEvent) => {
93 if (!branchMenuRef.current) return;
94 if (event.target instanceof Node && !branchMenuRef.current.contains(event.target)) {
95 setIsBranchMenuOpen(false);
96 }
97 };
98 window.addEventListener("mousedown", handleClickOutside);
99 return () => {
100 window.removeEventListener("mousedown", handleClickOutside);
101 };
102 }, [isBranchMenuOpen]);
103
104 // ── Helpers ───────────────────────────────────────────────────────────
105
106 const setThreadError = (error: string | null) => {
107 if (!activeThreadId) return;
108 dispatch({ type: "SET_ERROR", threadId: activeThreadId, error });
109 };
110
111 const setThreadBranch = (branch: string | null, worktreePath: string | null) => {
112 if (!activeThreadId) return;
113 // If the effective cwd is about to change, stop the running session so the
114 // next message creates a new one with the correct cwd.
115 const sessionId = activeThread?.session?.sessionId;
116 if (sessionId && worktreePath !== activeWorktreePath) {
117 void api?.providers.stopSession({ sessionId }).catch(() => undefined);
118 }
119 dispatch({ type: "SET_THREAD_BRANCH", threadId: activeThreadId, branch, worktreePath });
120 };
121
122 const selectBranch = (branch: GitBranch) => {
123 if (!api || !activeThreadId || !branchCwd) return;
124
125 // For new worktree mode, selecting a branch picks the base branch.
126 if (envMode === "worktree" && !envLocked && !activeWorktreePath) {
127 setThreadError(null);
128 setThreadBranch(branch.name, null);
129 setIsBranchMenuOpen(false);
130 return;
131 }
132
133 // If the branch already lives in a worktree, redirect there instead of
134 // trying to checkout (which git would reject with "already used by worktree").
135 if (branch.worktreePath) {
136 const isMainWorktree = branch.worktreePath === activeProject?.cwd;
137 setThreadError(null);
138 // Main worktree → switch back to local (project cwd, worktreePath=null).
139 // Secondary worktree → point the thread at that worktree path.
140 setThreadBranch(branch.name, isMainWorktree ? null : branch.worktreePath);
141 setIsBranchMenuOpen(false);
142 return;
143 }
144
145 checkoutMutation.mutate(branch.name, {
146 onSuccess: () => {
147 setThreadError(null);
148 setThreadBranch(branch.name, activeWorktreePath);
149 setIsBranchMenuOpen(false);
150 },
151 });
152 };
153
154 const createBranch = () => {
155 const name = newBranchName.trim();
156 if (!api || !activeThreadId || !branchCwd || !name) return;
157 createBranchMutation.mutate(name, {
158 onSuccess: () => {
159 setThreadError(null);
160 setThreadBranch(name, activeWorktreePath);
161 setNewBranchName("");
162 setIsCreatingBranch(false);
163 setIsBranchMenuOpen(false);
164 },
165 });
166 };
167
168 if (!activeThread || !activeProject) return null;
169
170 return (
171 <div className="mx-auto flex w-full max-w-3xl items-center justify-between px-5 pb-3 pt-1">
172 <div className="flex items-center gap-2">
173 {envLocked || activeWorktreePath ? (
174 <span className="inline-flex items-center gap-1.5 px-1 text-[12px] text-muted-foreground/55">
175 {activeWorktreePath ? "Worktree" : "Local"}
176 </span>
177 ) : (
178 <button
179 type="button"
180 className={`inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-[12px] transition-colors duration-150 ${
181 envMode === "worktree"
182 ? "bg-accent text-foreground/80"
183 : "text-muted-foreground/60 hover:bg-accent/50 hover:text-muted-foreground/80"
184 }`}
185 onClick={() => onEnvModeChange(envMode === "local" ? "worktree" : "local")}
186 >
187 {envMode === "worktree" ? "New worktree" : "Local"}
188 </button>
189 )}
190 </div>
191
192 {!isRepo ? (
193 <button
194 type="button"
195 className="inline-flex items-center gap-1.5 rounded-lg border border-border px-2 py-1 text-[12px] text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground/80 disabled:cursor-not-allowed disabled:opacity-50"
196 disabled={!branchCwd || initMutation.isPending}
197 onClick={() => initMutation.mutate()}
198 >
199 {initMutation.isPending ? "Initializing\u2026" : "Initialize git"}
200 </button>
201 ) : (
202 <div className="relative" ref={branchMenuRef}>
203 <button
204 type="button"
205 className="inline-flex items-center gap-1.5 rounded-lg px-2 py-1 text-[12px] text-muted-foreground/60 transition-colors duration-150 hover:bg-accent/50 hover:text-muted-foreground/80"
206 onClick={() => setIsBranchMenuOpen((open) => !open)}
207 disabled={branchesQuery.isLoading}
208 >
209 <span className="max-w-[240px] truncate font-mono">
210 {activeThread.branch
211 ? envMode === "worktree" && !activeWorktreePath
212 ? `From ${activeThread.branch}`
213 : activeThread.branch
214 : "Select branch"}
215 </span>
216 <svg
217 width="10"
218 height="10"
219 viewBox="0 0 10 10"
220 fill="none"
221 className="opacity-40"
222 aria-hidden="true"
223 >
224 <path
225 d="M2.5 4L5 6.5L7.5 4"
226 stroke="currentColor"
227 strokeWidth="1.2"
228 strokeLinecap="round"
229 strokeLinejoin="round"
230 />
231 </svg>
232 </button>
233 {isBranchMenuOpen && (
234 <div className="absolute bottom-full right-0 z-20 mb-2 w-[320px] rounded-2xl border border-border bg-popover/95 p-2 shadow-[0_16px_40px_rgba(0,0,0,0.55)] backdrop-blur">
235 <p className="px-2 py-1 text-[10px] font-medium uppercase tracking-wider text-muted-foreground/55">
236 Branch
237 </p>
238 <div className="max-h-64 overflow-y-auto">
239 {branches.map((branch) => {
240 const isSelected = branch.name === activeThread.branch;
241 const hasSecondaryWorktree =
242 branch.worktreePath && branch.worktreePath !== activeProject.cwd;
243 return (
244 <button
245 key={branch.name}
246 type="button"
247 className={`mb-0.5 flex w-full items-center justify-between gap-2 rounded-xl px-2 py-1.5 text-left font-mono text-xs transition-colors duration-150 ${
248 isSelected
249 ? "bg-accent text-foreground"
250 : "text-foreground/90 hover:bg-accent/50"
251 }`}
252 onClick={() => selectBranch(branch)}
253 >
254 <span className="truncate">{branch.name}</span>
255 {(branch.current || branch.isDefault || hasSecondaryWorktree) && (
256 <span className="shrink-0 text-[10px] text-muted-foreground/45">
257 {branch.current ? "current" : hasSecondaryWorktree ? "worktree" : "default"}
258 </span>
259 )}
260 </button>
261 );
262 })}
263 </div>
264 {envMode === "local" && (
265 <>
266 <div className="mx-1 my-1 h-px bg-border" />
267 {isCreatingBranch ? (
268 <form
269 className="flex items-center gap-1 px-1"
270 onSubmit={(event) => {
271 event.preventDefault();
272 createBranch();
273 }}
274 >
275 <input
276 type="text"
277 className="flex-1 rounded-lg border border-border bg-background px-2 py-1.5 font-mono text-xs text-foreground placeholder:text-muted-foreground/30 focus:border-ring focus:outline-none"
278 placeholder="branch-name"
279 value={newBranchName}
280 onChange={(event) => setNewBranchName(event.target.value)}
281 onKeyDown={(event) => {
282 if (event.key === "Escape") {
283 setIsCreatingBranch(false);
284 setNewBranchName("");
285 }
286 }}
287 // biome-ignore lint/a11y/noAutofocus: branch name input should focus when shown
288 autoFocus
289 />
290 <button
291 type="submit"
292 disabled={!newBranchName.trim() || createBranchMutation.isPending}
293 className="rounded-lg px-2 py-1.5 text-xs text-muted-foreground/70 transition-colors hover:bg-accent hover:text-foreground/80 disabled:opacity-30"
294 >
295 Create
296 </button>
297 </form>
298 ) : (
299 <button
300 type="button"
301 className="w-full rounded-lg px-2 py-1.5 text-left text-xs text-muted-foreground/70 transition-colors duration-150 hover:bg-accent hover:text-foreground/80"
302 onClick={() => setIsCreatingBranch(true)}
303 >
304 + New branch
305 </button>
306 )}
307 </>
308 )}
309 </div>
310 )}
311 </div>
312 )}
313 </div>
314 );
315}
apps/web/src/components/ChatView.tsx+110-134
...@@ -33,6 +33,7 @@ import {...@@ -33,6 +33,7 @@ import {
33 readNativeApi,33 readNativeApi,
34} from "../session-logic";34} from "../session-logic";
35import { useStore } from "../store";35import { useStore } from "../store";
36import BranchToolbar from "./BranchToolbar";
36import ChatMarkdown from "./ChatMarkdown";37import ChatMarkdown from "./ChatMarkdown";
3738
38function formatMessageMeta(createdAt: string, duration: string | null): string {39function formatMessageMeta(createdAt: string, duration: string | null): string {
...@@ -91,23 +92,17 @@ function approvalDetail(event: ProviderEvent): string | undefined {...@@ -91,23 +92,17 @@ function approvalDetail(event: ProviderEvent): string | undefined {
91 return asString(payload?.reason);92 return asString(payload?.reason);
92}93}
9394
94function derivePendingApprovals(95function derivePendingApprovals(events: ProviderEvent[]): PendingApprovalCard[] {
95 events: ProviderEvent[],
96): PendingApprovalCard[] {
97 const pending = new Map<string, PendingApprovalCard>();96 const pending = new Map<string, PendingApprovalCard>();
98 const ordered = [...events].toReversed();97 const ordered = [...events].toReversed();
9998
100 for (const event of ordered) {99 for (const event of ordered) {
101 if (100 if (event.method === "session/closed" || event.method === "session/exited") {
102 event.method === "session/closed" ||
103 event.method === "session/exited"
104 ) {
105 pending.clear();101 pending.clear();
106 continue;102 continue;
107 }103 }
108104
109 const requestId =105 const requestId = event.requestId ?? asString(asRecord(event.payload)?.requestId);
110 event.requestId ?? asString(asRecord(event.payload)?.requestId);
111 if (!requestId) continue;106 if (!requestId) continue;
112107
113 if (108 if (
...@@ -142,19 +137,13 @@ export default function ChatView() {...@@ -142,19 +137,13 @@ export default function ChatView() {
142 const [isEditorMenuOpen, setIsEditorMenuOpen] = useState(false);137 const [isEditorMenuOpen, setIsEditorMenuOpen] = useState(false);
143 const [lastEditor, setLastEditor] = useState<EditorId>(() => {138 const [lastEditor, setLastEditor] = useState<EditorId>(() => {
144 const stored = localStorage.getItem(LAST_EDITOR_KEY);139 const stored = localStorage.getItem(LAST_EDITOR_KEY);
145 return EDITORS.some((e) => e.id === stored)140 return EDITORS.some((e) => e.id === stored) ? (stored as EditorId) : EDITORS[0].id;
146 ? (stored as EditorId)
147 : EDITORS[0].id;
148 });141 });
149 const [selectedEffort, setSelectedEffort] =142 const [selectedEffort, setSelectedEffort] = useState<string>(DEFAULT_REASONING);
150 useState<string>(DEFAULT_REASONING);143 const [envMode, setEnvMode] = useState<"local" | "worktree">("local");
151 const [isSwitchingRuntimeMode, setIsSwitchingRuntimeMode] = useState(false);144 const [isSwitchingRuntimeMode, setIsSwitchingRuntimeMode] = useState(false);
152 const [respondingRequestIds, setRespondingRequestIds] = useState<string[]>(145 const [respondingRequestIds, setRespondingRequestIds] = useState<string[]>([]);
153 [],146 const [expandedWorkGroups, setExpandedWorkGroups] = useState<Record<string, boolean>>({});
154 );
155 const [expandedWorkGroups, setExpandedWorkGroups] = useState<
156 Record<string, boolean>
157 >({});
158 const [nowTick, setNowTick] = useState(() => Date.now());147 const [nowTick, setNowTick] = useState(() => Date.now());
159 const messagesEndRef = useRef<HTMLDivElement>(null);148 const messagesEndRef = useRef<HTMLDivElement>(null);
160 const textareaRef = useRef<HTMLTextAreaElement>(null);149 const textareaRef = useRef<HTMLTextAreaElement>(null);
...@@ -175,11 +164,7 @@ export default function ChatView() {...@@ -175,11 +164,7 @@ export default function ChatView() {
175 [activeThread?.events],164 [activeThread?.events],
176 );165 );
177 const latestTurnWorkEntries = useMemo(166 const latestTurnWorkEntries = useMemo(
178 () =>167 () => deriveWorkLogEntries(activeThread?.events ?? [], activeThread?.latestTurnId),
179 deriveWorkLogEntries(
180 activeThread?.events ?? [],
181 activeThread?.latestTurnId,
182 ),
183 [activeThread?.events, activeThread?.latestTurnId],168 [activeThread?.events, activeThread?.latestTurnId],
184 );169 );
185 const pendingApprovals = useMemo(170 const pendingApprovals = useMemo(
...@@ -265,19 +250,20 @@ export default function ChatView() {...@@ -265,19 +250,20 @@ export default function ChatView() {
265 approvalPolicy: "on-request",250 approvalPolicy: "on-request",
266 sandboxMode: "workspace-write",251 sandboxMode: "workspace-write",
267 } as const);252 } as const);
253 const envLocked = Boolean(
254 activeThread &&
255 (activeThread.messages.length > 0 ||
256 (activeThread.session !== null && activeThread.session.status !== "closed")),
257 );
268258
269 const handleRuntimeModeChange = async (259 const handleRuntimeModeChange = async (mode: "approval-required" | "full-access") => {
270 mode: "approval-required" | "full-access",
271 ) => {
272 if (mode === state.runtimeMode) return;260 if (mode === state.runtimeMode) return;
273 dispatch({ type: "SET_RUNTIME_MODE", mode });261 dispatch({ type: "SET_RUNTIME_MODE", mode });
274 if (!api) return;262 if (!api) return;
275263
276 const sessionIds = state.threads264 const sessionIds = state.threads
277 .map((t) => t.session)265 .map((t) => t.session)
278 .filter(266 .filter((s): s is NonNullable<typeof s> => s !== null && s.status !== "closed")
279 (s): s is NonNullable<typeof s> => s !== null && s.status !== "closed",
280 )
281 .map((s) => s.sessionId);267 .map((s) => s.sessionId);
282268
283 if (sessionIds.length === 0) return;269 if (sessionIds.length === 0) return;
...@@ -285,9 +271,7 @@ export default function ChatView() {...@@ -285,9 +271,7 @@ export default function ChatView() {
285 setIsSwitchingRuntimeMode(true);271 setIsSwitchingRuntimeMode(true);
286 try {272 try {
287 await Promise.all(273 await Promise.all(
288 sessionIds.map((id) =>274 sessionIds.map((id) => api.providers.stopSession({ sessionId: id }).catch(() => undefined)),
289 api.providers.stopSession({ sessionId: id }).catch(() => undefined),
290 ),
291 );275 );
292 } finally {276 } finally {
293 setIsSwitchingRuntimeMode(false);277 setIsSwitchingRuntimeMode(false);
...@@ -309,6 +293,12 @@ export default function ChatView() {...@@ -309,6 +293,12 @@ export default function ChatView() {
309 setExpandedWorkGroups({});293 setExpandedWorkGroups({});
310 }, [activeThread?.id]);294 }, [activeThread?.id]);
311295
296 const activeWorktreePath = activeThread?.worktreePath;
297 useEffect(() => {
298 if (!activeThread?.id) return;
299 setEnvMode(activeWorktreePath ? "worktree" : "local");
300 }, [activeThread?.id, activeWorktreePath]);
301
312 // Auto-resize textarea302 // Auto-resize textarea
313 useEffect(() => {303 useEffect(() => {
314 const ta = textareaRef.current;304 const ta = textareaRef.current;
...@@ -348,10 +338,7 @@ export default function ChatView() {...@@ -348,10 +338,7 @@ export default function ChatView() {
348338
349 const handleClickOutside = (event: MouseEvent) => {339 const handleClickOutside = (event: MouseEvent) => {
350 if (!editorMenuRef.current) return;340 if (!editorMenuRef.current) return;
351 if (341 if (event.target instanceof Node && !editorMenuRef.current.contains(event.target)) {
352 event.target instanceof Node &&
353 !editorMenuRef.current.contains(event.target)
354 ) {
355 setIsEditorMenuOpen(false);342 setIsEditorMenuOpen(false);
356 }343 }
357 };344 };
...@@ -368,23 +355,25 @@ export default function ChatView() {...@@ -368,23 +355,25 @@ export default function ChatView() {
368 if (e.key === "o" && (e.metaKey || e.ctrlKey) && !e.shiftKey) {355 if (e.key === "o" && (e.metaKey || e.ctrlKey) && !e.shiftKey) {
369 if (api && activeProject) {356 if (api && activeProject) {
370 e.preventDefault();357 e.preventDefault();
371 void api.shell.openInEditor(activeProject.cwd, lastEditor);358 const cwd = activeThread?.worktreePath ?? activeProject.cwd;
359 void api.shell.openInEditor(cwd, lastEditor);
372 }360 }
373 }361 }
374 };362 };
375 window.addEventListener("keydown", handler);363 window.addEventListener("keydown", handler);
376 return () => window.removeEventListener("keydown", handler);364 return () => window.removeEventListener("keydown", handler);
377 }, [api, activeProject, lastEditor]);365 }, [api, activeProject, activeThread, lastEditor]);
378366
379 const openInEditor = (editorId: EditorId) => {367 const openInEditor = (editorId: EditorId) => {
380 if (!api || !activeProject) return;368 if (!api || !activeProject) return;
381 void api.shell.openInEditor(activeProject.cwd, editorId);369 const cwd = activeThread?.worktreePath ?? activeProject.cwd;
370 void api.shell.openInEditor(cwd, editorId);
382 setLastEditor(editorId);371 setLastEditor(editorId);
383 localStorage.setItem(LAST_EDITOR_KEY, editorId);372 localStorage.setItem(LAST_EDITOR_KEY, editorId);
384 setIsEditorMenuOpen(false);373 setIsEditorMenuOpen(false);
385 };374 };
386375
387 const ensureSession = async (): Promise<EnsuredSessionInfo | null> => {376 const ensureSession = async (cwdOverride?: string): Promise<EnsuredSessionInfo | null> => {
388 if (!api || !activeThread || !activeProject) return null;377 if (!api || !activeThread || !activeProject) return null;
389 if (activeThread.session && activeThread.session.status !== "closed") {378 if (activeThread.session && activeThread.session.status !== "closed") {
390 const sessionThreadId = activeThread.session.threadId ?? null;379 const sessionThreadId = activeThread.session.threadId ?? null;
...@@ -406,7 +395,7 @@ export default function ChatView() {...@@ -406,7 +395,7 @@ export default function ChatView() {
406 try {395 try {
407 const session = await api.providers.startSession({396 const session = await api.providers.startSession({
408 provider: "codex",397 provider: "codex",
409 cwd: activeProject.cwd || undefined,398 cwd: cwdOverride ?? activeThread.worktreePath ?? activeProject.cwd,
410 model: selectedModel || undefined,399 model: selectedModel || undefined,
411 resumeThreadId: priorCodexThreadId ?? undefined,400 resumeThreadId: priorCodexThreadId ?? undefined,
412 approvalPolicy: runtimeSessionConfig.approvalPolicy,401 approvalPolicy: runtimeSessionConfig.approvalPolicy,
...@@ -446,6 +435,39 @@ export default function ChatView() {...@@ -446,6 +435,39 @@ export default function ChatView() {
446 if (!api || !activeThread || isSending || isConnecting) return;435 if (!api || !activeThread || isSending || isConnecting) return;
447 const trimmed = prompt.trim();436 const trimmed = prompt.trim();
448 if (!trimmed) return;437 if (!trimmed) return;
438 if (!activeProject) return;
439
440 // On first message: lock in branch + create worktree if needed.
441 let sessionCwd: string | undefined;
442 if (
443 activeThread.messages.length === 0 &&
444 activeThread.branch &&
445 envMode === "worktree" &&
446 !activeThread.worktreePath
447 ) {
448 try {
449 const newBranch = `codething/${crypto.randomUUID().slice(0, 8)}`;
450 const result = await api.git.createWorktree({
451 cwd: activeProject.cwd,
452 branch: activeThread.branch,
453 newBranch,
454 });
455 sessionCwd = result.worktree.path;
456 dispatch({
457 type: "SET_THREAD_BRANCH",
458 threadId: activeThread.id,
459 branch: result.worktree.branch,
460 worktreePath: result.worktree.path,
461 });
462 } catch (err) {
463 dispatch({
464 type: "SET_ERROR",
465 threadId: activeThread.id,
466 error: err instanceof Error ? err.message : "Failed to create worktree",
467 });
468 return;
469 }
470 }
449471
450 // Auto-title from first message472 // Auto-title from first message
451 if (activeThread.messages.length === 0) {473 if (activeThread.messages.length === 0) {
...@@ -471,21 +493,16 @@ export default function ChatView() {...@@ -471,21 +493,16 @@ export default function ChatView() {
471 const previousMessages = activeThread.messages;493 const previousMessages = activeThread.messages;
472 setPrompt("");494 setPrompt("");
473495
474 const sessionInfo = await ensureSession();496 const sessionInfo = await ensureSession(sessionCwd);
475 if (!sessionInfo) return;497 if (!sessionInfo) return;
476498
477 setIsSending(true);499 setIsSending(true);
478 try {500 try {
479 const shouldBootstrap =501 const shouldBootstrap =
480 previousMessages.length > 0 &&502 previousMessages.length > 0 &&
481 (sessionInfo.continuityState === "new" ||503 (sessionInfo.continuityState === "new" || sessionInfo.continuityState === "fallback_new");
482 sessionInfo.continuityState === "fallback_new");
483 const input = shouldBootstrap504 const input = shouldBootstrap
484 ? buildBootstrapInput(505 ? buildBootstrapInput(previousMessages, trimmed, PROVIDER_SEND_TURN_MAX_INPUT_CHARS).text
485 previousMessages,
486 trimmed,
487 PROVIDER_SEND_TURN_MAX_INPUT_CHARS,
488 ).text
489 : trimmed;506 : trimmed;
490 await api.providers.sendTurn({507 await api.providers.sendTurn({
491 sessionId: sessionInfo.sessionId,508 sessionId: sessionInfo.sessionId,
...@@ -512,10 +529,7 @@ export default function ChatView() {...@@ -512,10 +529,7 @@ export default function ChatView() {
512 });529 });
513 };530 };
514531
515 const onRespondToApproval = async (532 const onRespondToApproval = async (requestId: string, decision: ProviderApprovalDecision) => {
516 requestId: string,
517 decision: ProviderApprovalDecision,
518 ) => {
519 if (!api || !activeThread?.session) return;533 if (!api || !activeThread?.session) return;
520534
521 setRespondingRequestIds((existing) =>535 setRespondingRequestIds((existing) =>
...@@ -531,15 +545,10 @@ export default function ChatView() {...@@ -531,15 +545,10 @@ export default function ChatView() {
531 dispatch({545 dispatch({
532 type: "SET_ERROR",546 type: "SET_ERROR",
533 threadId: activeThread.id,547 threadId: activeThread.id,
534 error:548 error: err instanceof Error ? err.message : "Failed to submit approval decision.",
535 err instanceof Error
536 ? err.message
537 : "Failed to submit approval decision.",
538 });549 });
539 } finally {550 } finally {
540 setRespondingRequestIds((existing) =>551 setRespondingRequestIds((existing) => existing.filter((id) => id !== requestId));
541 existing.filter((id) => id !== requestId),
542 );
543 }552 }
544 };553 };
545554
...@@ -577,11 +586,22 @@ export default function ChatView() {...@@ -577,11 +586,22 @@ export default function ChatView() {
577 return (586 return (
578 <div className="flex flex-1 flex-col bg-background">587 <div className="flex flex-1 flex-col bg-background">
579 {/* Top bar */}588 {/* Top bar */}
580 <header className={`flex items-center justify-between border-b border-border px-5 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}>589 <header
590 className={`flex items-center justify-between border-b border-border px-5 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}
591 >
581 <div className="flex items-center gap-3">592 <div className="flex items-center gap-3">
582 <h2 className="text-sm font-medium text-foreground">593 <h2 className="text-sm font-medium text-foreground">{activeThread.title}</h2>
583 {activeThread.title}594 {activeProject && (
584 </h2>595 <span className="rounded-full bg-accent px-2 py-0.5 text-[10px] text-muted-foreground/50">
596 {activeProject.name}
597 </span>
598 )}
599 {activeThread.branch && (
600 <span className="rounded-full bg-accent px-2 py-0.5 font-mono text-[10px] text-muted-foreground/50">
601 {activeThread.branch}
602 {activeThread.worktreePath ? " (worktree)" : ""}
603 </span>
604 )}
585 </div>605 </div>
586 <div className="flex items-center gap-3">606 <div className="flex items-center gap-3">
587 {/* Open in editor */}607 {/* Open in editor */}
...@@ -606,9 +626,7 @@ export default function ChatView() {...@@ -606,9 +626,7 @@ export default function ChatView() {
606 {editorLabel(editor)}626 {editorLabel(editor)}
607 {editor.id === lastEditor && (627 {editor.id === lastEditor && (
608 <kbd className="ml-auto text-[9px] text-muted-foreground/40">628 <kbd className="ml-auto text-[9px] text-muted-foreground/40">
609 {navigator.platform.includes("Mac")629 {navigator.platform.includes("Mac") ? "\u2318O" : "Ctrl+O"}
610 ? "\u2318O"
611 : "Ctrl+O"}
612 </kbd>630 </kbd>
613 )}631 )}
614 </button>632 </button>
...@@ -634,7 +652,7 @@ export default function ChatView() {...@@ -634,7 +652,7 @@ export default function ChatView() {
634652
635 {/* Error banner */}653 {/* Error banner */}
636 {activeThread.error && (654 {activeThread.error && (
637 <div className="mx-4 mt-3 rounded-lg border border-rose-400/20 bg-rose-900/20 px-3 py-2 text-xs text-rose-200">655 <div className="mx-4 mt-3 rounded-lg border border-destructive/20 bg-destructive/10 px-3 py-2 text-xs text-destructive">
638 {activeThread.error}656 {activeThread.error}
639 </div>657 </div>
640 )}658 )}
...@@ -642,9 +660,7 @@ export default function ChatView() {...@@ -642,9 +660,7 @@ export default function ChatView() {
642 {pendingApprovals.length > 0 && (660 {pendingApprovals.length > 0 && (
643 <div className="mx-4 mt-3 space-y-2">661 <div className="mx-4 mt-3 space-y-2">
644 {pendingApprovals.map((approval) => {662 {pendingApprovals.map((approval) => {
645 const isResponding = respondingRequestIds.includes(663 const isResponding = respondingRequestIds.includes(approval.requestId);
646 approval.requestId,
647 );
648 return (664 return (
649 <div665 <div
650 key={approval.requestId}666 key={approval.requestId}
...@@ -668,9 +684,7 @@ export default function ChatView() {...@@ -668,9 +684,7 @@ export default function ChatView() {
668 type="button"684 type="button"
669 className="rounded-md border border-border bg-accent px-2 py-1 text-[11px] text-foreground transition-colors duration-150 hover:bg-accent/80 disabled:cursor-not-allowed disabled:opacity-50"685 className="rounded-md border border-border bg-accent px-2 py-1 text-[11px] text-foreground transition-colors duration-150 hover:bg-accent/80 disabled:cursor-not-allowed disabled:opacity-50"
670 disabled={isResponding}686 disabled={isResponding}
671 onClick={() =>687 onClick={() => void onRespondToApproval(approval.requestId, "accept")}
672 void onRespondToApproval(approval.requestId, "accept")
673 }
674 >688 >
675 Approve once689 Approve once
676 </button>690 </button>
...@@ -678,12 +692,7 @@ export default function ChatView() {...@@ -678,12 +692,7 @@ export default function ChatView() {
678 type="button"692 type="button"
679 className="rounded-md border border-sky-300/30 bg-sky-500/[0.15] px-2 py-1 text-[11px] text-sky-100 transition-colors duration-150 hover:bg-sky-500/[0.22] disabled:cursor-not-allowed disabled:opacity-50"693 className="rounded-md border border-sky-300/30 bg-sky-500/[0.15] px-2 py-1 text-[11px] text-sky-100 transition-colors duration-150 hover:bg-sky-500/[0.22] disabled:cursor-not-allowed disabled:opacity-50"
680 disabled={isResponding}694 disabled={isResponding}
681 onClick={() =>695 onClick={() => void onRespondToApproval(approval.requestId, "acceptForSession")}
682 void onRespondToApproval(
683 approval.requestId,
684 "acceptForSession",
685 )
686 }
687 >696 >
688 Always allow this session697 Always allow this session
689 </button>698 </button>
...@@ -691,9 +700,7 @@ export default function ChatView() {...@@ -691,9 +700,7 @@ export default function ChatView() {
691 type="button"700 type="button"
692 className="rounded-md border border-border px-2 py-1 text-[11px] text-foreground/90 transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50"701 className="rounded-md border border-border px-2 py-1 text-[11px] text-foreground/90 transition-colors duration-150 hover:bg-accent disabled:cursor-not-allowed disabled:opacity-50"
693 disabled={isResponding}702 disabled={isResponding}
694 onClick={() =>703 onClick={() => void onRespondToApproval(approval.requestId, "decline")}
695 void onRespondToApproval(approval.requestId, "decline")
696 }
697 >704 >
698 Decline705 Decline
699 </button>706 </button>
...@@ -701,9 +708,7 @@ export default function ChatView() {...@@ -701,9 +708,7 @@ export default function ChatView() {
701 type="button"708 type="button"
702 className="rounded-md border border-rose-300/30 bg-rose-500/[0.12] px-2 py-1 text-[11px] text-rose-100 transition-colors duration-150 hover:bg-rose-500/[0.2] disabled:cursor-not-allowed disabled:opacity-50"709 className="rounded-md border border-rose-300/30 bg-rose-500/[0.12] px-2 py-1 text-[11px] text-rose-100 transition-colors duration-150 hover:bg-rose-500/[0.2] disabled:cursor-not-allowed disabled:opacity-50"
703 disabled={isResponding}710 disabled={isResponding}
704 onClick={() =>711 onClick={() => void onRespondToApproval(approval.requestId, "cancel")}
705 void onRespondToApproval(approval.requestId, "cancel")
706 }
707 >712 >
708 Cancel turn713 Cancel turn
709 </button>714 </button>
...@@ -718,15 +723,14 @@ export default function ChatView() {...@@ -718,15 +723,14 @@ export default function ChatView() {
718 <div className="flex-1 overflow-y-auto px-5 py-4">723 <div className="flex-1 overflow-y-auto px-5 py-4">
719 {activeThread.messages.length === 0 && !isWorking ? (724 {activeThread.messages.length === 0 && !isWorking ? (
720 <div className="flex h-full items-center justify-center">725 <div className="flex h-full items-center justify-center">
721 <p className="text-sm text-muted-foreground/30">Send a message to start the conversation.</p>726 <p className="text-sm text-muted-foreground/30">
727 Send a message to start the conversation.
728 </p>
722 </div>729 </div>
723 ) : (730 ) : (
724 <div className="mx-auto max-w-3xl space-y-4">731 <div className="mx-auto max-w-3xl space-y-4">
725 {timelineEntries.map((timelineEntry, index) => {732 {timelineEntries.map((timelineEntry, index) => {
726 if (733 if (timelineEntry.kind === "work" && timelineEntries[index - 1]?.kind === "work") {
727 timelineEntry.kind === "work" &&
728 timelineEntries[index - 1]?.kind === "work"
729 ) {
730 return null;734 return null;
731 }735 }
732736
...@@ -747,16 +751,13 @@ export default function ChatView() {...@@ -747,16 +751,13 @@ export default function ChatView() {
747751
748 const groupId = timelineEntry.id;752 const groupId = timelineEntry.id;
749 const isExpanded = expandedWorkGroups[groupId] ?? false;753 const isExpanded = expandedWorkGroups[groupId] ?? false;
750 const hasOverflow =754 const hasOverflow = groupedEntries.length > MAX_VISIBLE_WORK_LOG_ENTRIES;
751 groupedEntries.length > MAX_VISIBLE_WORK_LOG_ENTRIES;
752 const visibleEntries =755 const visibleEntries =
753 hasOverflow && !isExpanded756 hasOverflow && !isExpanded
754 ? groupedEntries.slice(-MAX_VISIBLE_WORK_LOG_ENTRIES)757 ? groupedEntries.slice(-MAX_VISIBLE_WORK_LOG_ENTRIES)
755 : groupedEntries;758 : groupedEntries;
756 const hiddenCount = groupedEntries.length - visibleEntries.length;759 const hiddenCount = groupedEntries.length - visibleEntries.length;
757 const onlyToolEntries = groupedEntries.every(760 const onlyToolEntries = groupedEntries.every((entry) => entry.tone === "tool");
758 (entry) => entry.tone === "tool",
759 );
760 const groupLabel = onlyToolEntries761 const groupLabel = onlyToolEntries
761 ? groupedEntries.length === 1762 ? groupedEntries.length === 1
762 ? "Tool call"763 ? "Tool call"
...@@ -842,9 +843,7 @@ export default function ChatView() {...@@ -842,9 +843,7 @@ export default function ChatView() {
842 <div className="my-3 flex items-center gap-3">843 <div className="my-3 flex items-center gap-3">
843 <span className="h-px flex-1 bg-border" />844 <span className="h-px flex-1 bg-border" />
844 <span className="rounded-full border border-border bg-background px-2.5 py-1 text-[10px] uppercase tracking-[0.14em] text-muted-foreground/80">845 <span className="rounded-full border border-border bg-background px-2.5 py-1 text-[10px] uppercase tracking-[0.14em] text-muted-foreground/80">
845 {completionSummary846 {completionSummary ? `Response • ${completionSummary}` : "Response"}
846 ? `Response • ${completionSummary}`
847 : "Response"}
848 </span>847 </span>
849 <span className="h-px flex-1 bg-border" />848 <span className="h-px flex-1 bg-border" />
850 </div>849 </div>
...@@ -853,24 +852,17 @@ export default function ChatView() {...@@ -853,24 +852,17 @@ export default function ChatView() {
853 <ChatMarkdown852 <ChatMarkdown
854 text={853 text={
855 timelineEntry.message.text ||854 timelineEntry.message.text ||
856 (timelineEntry.message.streaming855 (timelineEntry.message.streaming ? "" : "(empty response)")
857 ? ""
858 : "(empty response)")
859 }856 }
860 />857 />
861 <p className="mt-1.5 text-[10px] text-muted-foreground/30">858 <p className="mt-1.5 text-[10px] text-muted-foreground/30">
862 {formatMessageMeta(859 {formatMessageMeta(
863 timelineEntry.message.createdAt,860 timelineEntry.message.createdAt,
864 timelineEntry.message.streaming861 timelineEntry.message.streaming
865 ? formatElapsed(862 ? formatElapsed(timelineEntry.message.createdAt, nowIso)
866 timelineEntry.message.createdAt,
867 nowIso,
868 )
869 : formatElapsed(863 : formatElapsed(
870 timelineEntry.message.createdAt,864 timelineEntry.message.createdAt,
871 assistantCompletionByItemId.get(865 assistantCompletionByItemId.get(timelineEntry.message.id),
872 timelineEntry.message.id,
873 ),
874 ),866 ),
875 )}867 )}
876 </p>868 </p>
...@@ -896,7 +888,7 @@ export default function ChatView() {...@@ -896,7 +888,7 @@ export default function ChatView() {
896 </div>888 </div>
897889
898 {/* Input bar */}890 {/* Input bar */}
899 <div className="px-5 pb-4 pt-2">891 <div className="px-5 pb-1 pt-2">
900 <form onSubmit={onSend} className="mx-auto max-w-3xl">892 <form onSubmit={onSend} className="mx-auto max-w-3xl">
901 <div className="group rounded-[20px] border border-border bg-card transition-colors duration-200 focus-within:border-ring">893 <div className="group rounded-[20px] border border-border bg-card transition-colors duration-200 focus-within:border-ring">
902 {/* Textarea area */}894 {/* Textarea area */}
...@@ -1026,9 +1018,7 @@ export default function ChatView() {...@@ -1026,9 +1018,7 @@ export default function ChatView() {
1026 disabled={isSwitchingRuntimeMode}1018 disabled={isSwitchingRuntimeMode}
1027 onClick={() =>1019 onClick={() =>
1028 void handleRuntimeModeChange(1020 void handleRuntimeModeChange(
1029 state.runtimeMode === "full-access"1021 state.runtimeMode === "full-access" ? "approval-required" : "full-access",
1030 ? "approval-required"
1031 : "full-access",
1032 )1022 )
1033 }1023 }
1034 title={1024 title={
...@@ -1038,13 +1028,7 @@ export default function ChatView() {...@@ -1038,13 +1028,7 @@ export default function ChatView() {
1038 }1028 }
1039 >1029 >
1040 {state.runtimeMode === "full-access" ? (1030 {state.runtimeMode === "full-access" ? (
1041 <svg1031 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
1042 width="14"
1043 height="14"
1044 viewBox="0 0 14 14"
1045 fill="none"
1046 aria-hidden="true"
1047 >
1048 <rect1032 <rect
1049 x="2"1033 x="2"
1050 y="5.5"1034 y="5.5"
...@@ -1062,13 +1046,7 @@ export default function ChatView() {...@@ -1062,13 +1046,7 @@ export default function ChatView() {
1062 />1046 />
1063 </svg>1047 </svg>
1064 ) : (1048 ) : (
1065 <svg1049 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
1066 width="14"
1067 height="14"
1068 viewBox="0 0 14 14"
1069 fill="none"
1070 aria-hidden="true"
1071 >
1072 <rect1050 <rect
1073 x="2"1051 x="2"
1074 y="5.5"1052 y="5.5"
...@@ -1086,11 +1064,7 @@ export default function ChatView() {...@@ -1086,11 +1064,7 @@ export default function ChatView() {
1086 />1064 />
1087 </svg>1065 </svg>
1088 )}1066 )}
1089 <span>1067 <span>{state.runtimeMode === "full-access" ? "Full access" : "Supervised"}</span>
1090 {state.runtimeMode === "full-access"
1091 ? "Full access"
1092 : "Supervised"}
1093 </span>
1094 </button>1068 </button>
1095 </div>1069 </div>
10961070
...@@ -1165,6 +1139,8 @@ export default function ChatView() {...@@ -1165,6 +1139,8 @@ export default function ChatView() {
1165 </div>1139 </div>
1166 </form>1140 </form>
1167 </div>1141 </div>
1142
1143 <BranchToolbar envMode={envMode} onEnvModeChange={setEnvMode} envLocked={envLocked} />
1168 </div>1144 </div>
1169 );1145 );
1170}1146}
apps/web/src/components/DiffPanel.tsx+3-1
...@@ -7,7 +7,9 @@ export default function DiffPanel() {...@@ -7,7 +7,9 @@ export default function DiffPanel() {
7 return (7 return (
8 <aside className="flex h-full w-[400px] shrink-0 flex-col border-l border-border bg-card">8 <aside className="flex h-full w-[400px] shrink-0 flex-col border-l border-border bg-card">
9 {/* Header */}9 {/* Header */}
10 <div className={`flex items-center justify-between border-b border-border px-4 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}>10 <div
11 className={`flex items-center justify-between border-b border-border px-4 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}
12 >
11 <h3 className="text-xs font-medium text-foreground">Uncommitted changes</h3>13 <h3 className="text-xs font-medium text-foreground">Uncommitted changes</h3>
12 <button14 <button
13 type="button"15 type="button"
apps/web/src/components/Sidebar.tsx+2
...@@ -57,6 +57,8 @@ export default function Sidebar() {...@@ -57,6 +57,8 @@ export default function Sidebar() {
57 events: [],57 events: [],
58 error: null,58 error: null,
59 createdAt: new Date().toISOString(),59 createdAt: new Date().toISOString(),
60 branch: null,
61 worktreePath: null,
60 },62 },
61 });63 });
62 },64 },
apps/web/src/historyBootstrap.ts+4-11
...@@ -36,13 +36,8 @@ export function buildBootstrapInput(...@@ -36,13 +36,8 @@ export function buildBootstrapInput(
36 latestPrompt: string,36 latestPrompt: string,
37 maxChars: number,37 maxChars: number,
38): BootstrapInputResult {38): BootstrapInputResult {
39 const budget = Number.isFinite(maxChars)39 const budget = Number.isFinite(maxChars) ? Math.max(1, Math.floor(maxChars)) : 1;
40 ? Math.max(1, Math.floor(maxChars))40 const promptOnly = latestPrompt.length <= budget ? latestPrompt : latestPrompt.slice(0, budget);
41 : 1;
42 const promptOnly =
43 latestPrompt.length <= budget
44 ? latestPrompt
45 : latestPrompt.slice(0, budget);
4641
47 if (previousMessages.length === 0) {42 if (previousMessages.length === 0) {
48 return {43 return {
...@@ -87,8 +82,7 @@ export function buildBootstrapInput(...@@ -87,8 +82,7 @@ export function buildBootstrapInput(
8782
88 let includedChronological = [...includedNewestFirst].reverse();83 let includedChronological = [...includedNewestFirst].reverse();
89 while (true) {84 while (true) {
90 const omittedCount =85 const omittedCount = newestFirstBlocks.length - includedChronological.length;
91 newestFirstBlocks.length - includedChronological.length;
92 const transcriptBody =86 const transcriptBody =
93 omittedCount > 087 omittedCount > 0
94 ? includedChronological.length > 088 ? includedChronological.length > 0
...@@ -101,8 +95,7 @@ export function buildBootstrapInput(...@@ -101,8 +95,7 @@ export function buildBootstrapInput(
101 text: finalized,95 text: finalized,
102 includedCount: includedChronological.length,96 includedCount: includedChronological.length,
103 omittedCount,97 omittedCount,
104 truncated:98 truncated: omittedCount > 0 || latestPrompt.length !== promptOnly.length,
105 omittedCount > 0 || latestPrompt.length !== promptOnly.length,
106 };99 };
107 }100 }
108101
apps/web/src/index.css+11-26
...@@ -88,11 +88,7 @@...@@ -88,11 +88,7 @@
88 --secondary: --alpha(var(--color-black) / 4%);88 --secondary: --alpha(var(--color-black) / 4%);
89 --secondary-foreground: var(--color-neutral-800);89 --secondary-foreground: var(--color-neutral-800);
90 --muted: --alpha(var(--color-black) / 4%);90 --muted: --alpha(var(--color-black) / 4%);
91 --muted-foreground: color-mix(91 --muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-black));
92 in srgb,
93 var(--color-neutral-500) 90%,
94 var(--color-black)
95 );
96 --accent: --alpha(var(--color-black) / 5%);92 --accent: --alpha(var(--color-black) / 5%);
97 --accent-foreground: var(--color-neutral-800);93 --accent-foreground: var(--color-neutral-800);
98 --destructive: var(--color-red-500);94 --destructive: var(--color-red-500);
...@@ -122,11 +118,7 @@...@@ -122,11 +118,7 @@
122118
123 @variant dark {119 @variant dark {
124 color-scheme: dark;120 color-scheme: dark;
125 --background: color-mix(121 --background: color-mix(in srgb, var(--color-neutral-950) 95%, var(--color-white));
126 in srgb,
127 var(--color-neutral-950) 95%,
128 var(--color-white)
129 );
130 --foreground: var(--color-neutral-100);122 --foreground: var(--color-neutral-100);
131 --card: color-mix(in srgb, var(--background) 98%, var(--color-white));123 --card: color-mix(in srgb, var(--background) 98%, var(--color-white));
132 --card-foreground: var(--color-neutral-100);124 --card-foreground: var(--color-neutral-100);
...@@ -137,18 +129,10 @@...@@ -137,18 +129,10 @@
137 --secondary: --alpha(var(--color-white) / 4%);129 --secondary: --alpha(var(--color-white) / 4%);
138 --secondary-foreground: var(--color-neutral-100);130 --secondary-foreground: var(--color-neutral-100);
139 --muted: --alpha(var(--color-white) / 4%);131 --muted: --alpha(var(--color-white) / 4%);
140 --muted-foreground: color-mix(132 --muted-foreground: color-mix(in srgb, var(--color-neutral-500) 90%, var(--color-white));
141 in srgb,
142 var(--color-neutral-500) 90%,
143 var(--color-white)
144 );
145 --accent: --alpha(var(--color-white) / 4%);133 --accent: --alpha(var(--color-white) / 4%);
146 --accent-foreground: var(--color-neutral-100);134 --accent-foreground: var(--color-neutral-100);
147 --destructive: color-mix(135 --destructive: color-mix(in srgb, var(--color-red-500) 90%, var(--color-white));
148 in srgb,
149 var(--color-red-500) 90%,
150 var(--color-white)
151 );
152 --border: --alpha(var(--color-white) / 6%);136 --border: --alpha(var(--color-white) / 6%);
153 --input: --alpha(var(--color-white) / 8%);137 --input: --alpha(var(--color-white) / 8%);
154 --ring: oklch(0.588 0.217 264);138 --ring: oklch(0.588 0.217 264);
...@@ -177,7 +161,12 @@...@@ -177,7 +161,12 @@
177161
178body {162body {
179 font-family:163 font-family:
180 "DM Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;164 "DM Sans",
165 -apple-system,
166 BlinkMacSystemFont,
167 "Segoe UI",
168 system-ui,
169 sans-serif;
181 margin: 0;170 margin: 0;
182 padding: 0;171 padding: 0;
183 min-height: 100vh;172 min-height: 100vh;
...@@ -287,11 +276,7 @@ label:has(> select#reasoning-effort) select {...@@ -287,11 +276,7 @@ label:has(> select#reasoning-effort) select {
287.chat-markdown a {276.chat-markdown a {
288 color: var(--info-foreground);277 color: var(--info-foreground);
289 text-decoration: underline;278 text-decoration: underline;
290 text-decoration-color: color-mix(279 text-decoration-color: color-mix(in srgb, var(--info-foreground) 40%, transparent);
291 in srgb,
292 var(--info-foreground) 40%,
293 transparent
294 );
295}280}
296281
297.chat-markdown a:hover {282.chat-markdown a:hover {
apps/web/src/persistenceSchema.test.ts+4
...@@ -134,6 +134,8 @@ describe("toPersistedState", () => {...@@ -134,6 +134,8 @@ describe("toPersistedState", () => {
134 events: [],134 events: [],
135 error: "boom",135 error: "boom",
136 createdAt: "2026-02-08T10:00:00.000Z",136 createdAt: "2026-02-08T10:00:00.000Z",
137 branch: null,
138 worktreePath: null,
137 };139 };
138140
139 const persisted = toPersistedState({141 const persisted = toPersistedState({
...@@ -161,6 +163,8 @@ describe("toPersistedState", () => {...@@ -161,6 +163,8 @@ describe("toPersistedState", () => {
161 model: "gpt-5.3-codex",163 model: "gpt-5.3-codex",
162 messages: thread.messages,164 messages: thread.messages,
163 createdAt: thread.createdAt,165 createdAt: thread.createdAt,
166 branch: null,
167 worktreePath: null,
164 });168 });
165 const persistedThread = persisted.threads[0];169 const persistedThread = persisted.threads[0];
166 expect(persistedThread).toBeDefined();170 expect(persistedThread).toBeDefined();
apps/web/src/persistenceSchema.ts+9-12
...@@ -1,12 +1,7 @@...@@ -1,12 +1,7 @@
1import { z } from "zod";1import { z } from "zod";
22
3import { DEFAULT_MODEL, resolveModelSlug } from "./model-logic";3import { DEFAULT_MODEL, resolveModelSlug } from "./model-logic";
4import {4import { DEFAULT_RUNTIME_MODE, type Project, type RuntimeMode, type Thread } from "./types";
5 DEFAULT_RUNTIME_MODE,
6 type Project,
7 type RuntimeMode,
8 type Thread,
9} from "./types";
105
11const LEGACY_DEFAULT_MODEL = "gpt-5.2-codex";6const LEGACY_DEFAULT_MODEL = "gpt-5.2-codex";
127
...@@ -34,6 +29,8 @@ const persistedThreadSchema = z.object({...@@ -34,6 +29,8 @@ const persistedThreadSchema = z.object({
34 model: z.string().min(1),29 model: z.string().min(1),
35 messages: z.array(persistedMessageSchema),30 messages: z.array(persistedMessageSchema),
36 createdAt: z.string().min(1),31 createdAt: z.string().min(1),
32 branch: z.string().min(1).nullable().optional(),
33 worktreePath: z.string().min(1).nullable().optional(),
37});34});
3835
39const persistedStateBodySchema = z.object({36const persistedStateBodySchema = z.object({
...@@ -112,6 +109,8 @@ function hydrateThread(...@@ -112,6 +109,8 @@ function hydrateThread(
112 events: [],109 events: [],
113 error: null,110 error: null,
114 createdAt: thread.createdAt,111 createdAt: thread.createdAt,
112 branch: thread.branch ?? null,
113 worktreePath: thread.worktreePath ?? null,
115 };114 };
116}115}
117116
...@@ -146,13 +145,9 @@ export function hydratePersistedState(...@@ -146,13 +145,9 @@ export function hydratePersistedState(
146 return {145 return {
147 projects,146 projects,
148 threads,147 threads,
149 activeThreadId: hasActiveThread148 activeThreadId: hasActiveThread ? parsedState.data.activeThreadId : (threads[0]?.id ?? null),
150 ? parsedState.data.activeThreadId
151 : (threads[0]?.id ?? null),
152 runtimeMode:149 runtimeMode:
153 "runtimeMode" in parsedState.data150 "runtimeMode" in parsedState.data ? parsedState.data.runtimeMode : DEFAULT_RUNTIME_MODE,
154 ? parsedState.data.runtimeMode
155 : DEFAULT_RUNTIME_MODE,
156 };151 };
157}152}
158153
...@@ -170,6 +165,8 @@ export function toPersistedState(...@@ -170,6 +165,8 @@ export function toPersistedState(
170 model: thread.model,165 model: thread.model,
171 messages: thread.messages,166 messages: thread.messages,
172 createdAt: thread.createdAt,167 createdAt: thread.createdAt,
168 branch: thread.branch,
169 worktreePath: thread.worktreePath,
173 })),170 })),
174 activeThreadId: state.activeThreadId,171 activeThreadId: state.activeThreadId,
175 runtimeMode: state.runtimeMode,172 runtimeMode: state.runtimeMode,
apps/web/src/session-logic.ts+5-20
...@@ -109,11 +109,7 @@ function normalizeItemType(raw: string | undefined): string {...@@ -109,11 +109,7 @@ function normalizeItemType(raw: string | undefined): string {
109}109}
110110
111function shouldDropItemType(type: string): boolean {111function shouldDropItemType(type: string): boolean {
112 if (112 if (type.includes("preamble") || type.includes("reasoning") || type.includes("thought")) {
113 type.includes("preamble") ||
114 type.includes("reasoning") ||
115 type.includes("thought")
116 ) {
117 return true;113 return true;
118 }114 }
119115
...@@ -121,11 +117,7 @@ function shouldDropItemType(type: string): boolean {...@@ -121,11 +117,7 @@ function shouldDropItemType(type: string): boolean {
121}117}
122118
123function shouldShowItemLifecycle(type: string): boolean {119function shouldShowItemLifecycle(type: string): boolean {
124 return (120 return type.includes("tool") || type.includes("command") || type.includes("file change");
125 type.includes("tool") ||
126 type.includes("command") ||
127 type.includes("file change")
128 );
129}121}
130122
131function shouldDropMethod(method: string): boolean {123function shouldDropMethod(method: string): boolean {
...@@ -182,9 +174,7 @@ function extractDetail(...@@ -182,9 +174,7 @@ function extractDetail(
182 return undefined;174 return undefined;
183}175}
184176
185function lifecycleCandidateFromItemEvent(177function lifecycleCandidateFromItemEvent(event: ProviderEvent): ItemLifecycleCandidate | null {
186 event: ProviderEvent,
187): ItemLifecycleCandidate | null {
188 const payload = asObject(event.payload);178 const payload = asObject(event.payload);
189 const item = asObject(payload?.item);179 const item = asObject(payload?.item);
190 const normalizedType = normalizeItemType(asString(item?.type));180 const normalizedType = normalizeItemType(asString(item?.type));
...@@ -360,10 +350,7 @@ export function deriveWorkLogEntries(...@@ -360,10 +350,7 @@ export function deriveWorkLogEntries(
360 ) {350 ) {
361 continue;351 continue;
362 }352 }
363 if (353 if (lifecycleCandidate.label === "Tool call" && !lifecycleCandidate.detail) {
364 lifecycleCandidate.label === "Tool call" &&
365 !lifecycleCandidate.detail
366 ) {
367 continue;354 continue;
368 }355 }
369356
...@@ -371,9 +358,7 @@ export function deriveWorkLogEntries(...@@ -371,9 +358,7 @@ export function deriveWorkLogEntries(
371 id: lifecycleCandidate.id,358 id: lifecycleCandidate.id,
372 createdAt: lifecycleCandidate.createdAt,359 createdAt: lifecycleCandidate.createdAt,
373 label: lifecycleCandidate.label,360 label: lifecycleCandidate.label,
374 ...(lifecycleCandidate.detail361 ...(lifecycleCandidate.detail ? { detail: lifecycleCandidate.detail } : {}),
375 ? { detail: lifecycleCandidate.detail }
376 : {}),
377 tone: lifecycleCandidate.tone,362 tone: lifecycleCandidate.tone,
378 });363 });
379 continue;364 continue;
apps/web/src/store.test.ts+2
...@@ -39,6 +39,8 @@ function makeThread(overrides: Partial<Thread> = {}): Thread {...@@ -39,6 +39,8 @@ function makeThread(overrides: Partial<Thread> = {}): Thread {
39 events: [],39 events: [],
40 error: null,40 error: null,
41 createdAt: "2026-02-09T00:00:00.000Z",41 createdAt: "2026-02-09T00:00:00.000Z",
42 branch: null,
43 worktreePath: null,
42 ...overrides,44 ...overrides,
43 };45 };
44}46}
apps/web/src/store.ts+25-3
...@@ -33,6 +33,12 @@ type Action =...@@ -33,6 +33,12 @@ type Action =
33 | { type: "SET_ERROR"; threadId: string; error: string | null }33 | { type: "SET_ERROR"; threadId: string; error: string | null }
34 | { type: "SET_THREAD_TITLE"; threadId: string; title: string }34 | { type: "SET_THREAD_TITLE"; threadId: string; title: string }
35 | { type: "SET_THREAD_MODEL"; threadId: string; model: string }35 | { type: "SET_THREAD_MODEL"; threadId: string; model: string }
36 | {
37 type: "SET_THREAD_BRANCH";
38 threadId: string;
39 branch: string | null;
40 worktreePath: string | null;
41 }
36 | { type: "SET_RUNTIME_MODE"; mode: RuntimeMode }42 | { type: "SET_RUNTIME_MODE"; mode: RuntimeMode }
37 | { type: "DELETE_THREAD"; threadId: string };43 | { type: "DELETE_THREAD"; threadId: string };
3844
...@@ -370,6 +376,24 @@ export function reducer(state: AppState, action: Action): AppState {...@@ -370,6 +376,24 @@ export function reducer(state: AppState, action: Action): AppState {
370 })),376 })),
371 };377 };
372378
379 case "SET_THREAD_BRANCH": {
380 return {
381 ...state,
382 threads: updateThread(state.threads, action.threadId, (t) => {
383 // When the effective cwd changes (worktreePath differs), the old
384 // session is no longer valid — clear it so ensureSession creates a
385 // new one with the correct cwd on the next message.
386 const cwdChanged = t.worktreePath !== action.worktreePath;
387 return {
388 ...t,
389 branch: action.branch,
390 worktreePath: action.worktreePath,
391 ...(cwdChanged ? { session: null } : {}),
392 };
393 }),
394 };
395 }
396
373 case "SET_RUNTIME_MODE":397 case "SET_RUNTIME_MODE":
374 return {398 return {
375 ...state,399 ...state,
...@@ -379,9 +403,7 @@ export function reducer(state: AppState, action: Action): AppState {...@@ -379,9 +403,7 @@ export function reducer(state: AppState, action: Action): AppState {
379 case "DELETE_THREAD": {403 case "DELETE_THREAD": {
380 const threads = state.threads.filter((t) => t.id !== action.threadId);404 const threads = state.threads.filter((t) => t.id !== action.threadId);
381 const activeThreadId =405 const activeThreadId =
382 state.activeThreadId === action.threadId406 state.activeThreadId === action.threadId ? (threads[0]?.id ?? null) : state.activeThreadId;
383 ? (threads[0]?.id ?? null)
384 : state.activeThreadId;
385 return { ...state, threads, activeThreadId };407 return { ...state, threads, activeThreadId };
386 }408 }
387409
apps/web/src/types.ts+2
...@@ -35,4 +35,6 @@ export interface Thread {...@@ -35,4 +35,6 @@ export interface Thread {
35 latestTurnStartedAt?: string | undefined;35 latestTurnStartedAt?: string | undefined;
36 latestTurnCompletedAt?: string | undefined;36 latestTurnCompletedAt?: string | undefined;
37 latestTurnDurationMs?: number | undefined;37 latestTurnDurationMs?: number | undefined;
38 branch: string | null;
39 worktreePath: string | null;
38}40}
apps/web/src/wsNativeApi.ts+8
...@@ -96,6 +96,14 @@ export function createWsNativeApi(): NativeApi {...@@ -96,6 +96,14 @@ export function createWsNativeApi(): NativeApi {
96 openInEditor: (cwd, editor) =>96 openInEditor: (cwd, editor) =>
97 transport.request(WS_METHODS.shellOpenInEditor, { cwd, editor }),97 transport.request(WS_METHODS.shellOpenInEditor, { cwd, editor }),
98 },98 },
99 git: {
100 listBranches: (input) => transport.request(WS_METHODS.gitListBranches, input),
101 createWorktree: (input) => transport.request(WS_METHODS.gitCreateWorktree, input),
102 removeWorktree: (input) => transport.request(WS_METHODS.gitRemoveWorktree, input),
103 createBranch: (input) => transport.request(WS_METHODS.gitCreateBranch, input),
104 checkout: (input) => transport.request(WS_METHODS.gitCheckout, input),
105 init: (input) => transport.request(WS_METHODS.gitInit, input),
106 },
99 contextMenu: {107 contextMenu: {
100 show: async <T extends string>(108 show: async <T extends string>(
101 items: readonly { id: T; label: string }[],109 items: readonly { id: T; label: string }[],
apps/web/turbo.jsonc created+9
...@@ -0,0 +1,9 @@
1{
2 "$schema": "https://turbo.build/schema.json",
3 "extends": ["//"],
4 "tasks": {
5 "dev": {
6 "persistent": true,
7 },
8 },
9}
apps/web/vite.config.ts+11-4
...@@ -2,6 +2,8 @@ import tailwindcss from "@tailwindcss/vite";...@@ -2,6 +2,8 @@ import tailwindcss from "@tailwindcss/vite";
2import react from "@vitejs/plugin-react";2import react from "@vitejs/plugin-react";
3import { defineConfig } from "vite";3import { defineConfig } from "vite";
44
5const port = Number(process.env.PORT ?? 5173);
6
5export default defineConfig({7export default defineConfig({
6 plugins: [8 plugins: [
7 react({9 react({
...@@ -13,13 +15,18 @@ export default defineConfig({...@@ -13,13 +15,18 @@ export default defineConfig({
13 ],15 ],
14 define: {16 define: {
15 // In dev mode, tell the web app where the WebSocket server lives17 // In dev mode, tell the web app where the WebSocket server lives
16 "import.meta.env.VITE_WS_URL": JSON.stringify(18 "import.meta.env.VITE_WS_URL": JSON.stringify(process.env.VITE_WS_URL ?? ""),
17 process.env.VITE_WS_URL ?? "",
18 ),
19 },19 },
20 server: {20 server: {
21 port: Number(process.env.PORT ?? 5173),21 port,
22 strictPort: true,22 strictPort: true,
23 hmr: {
24 // Explicit config so Vite's HMR WebSocket connects reliably
25 // inside Electron's BrowserWindow. Vite 8 uses console.debug for
26 // connection logs — enable "Verbose" in DevTools to see them.
27 protocol: "ws",
28 host: "localhost",
29 },
23 },30 },
24 build: {31 build: {
25 outDir: "dist",32 outDir: "dist",
bun.lock+315-168
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9 "oxlint": "^1.43.0",9 "oxlint": "^1.43.0",
10 "turbo": "^2.3.3",10 "turbo": "^2.3.3",
11 "typescript": "^5.7.3",11 "typescript": "^5.7.3",
12 "vitest": "^3.0.0",12 "vitest": "^4.0.0",
13 },13 },
14 },14 },
15 "apps/desktop": {15 "apps/desktop": {
...@@ -20,11 +20,10 @@...@@ -20,11 +20,10 @@
20 },20 },
21 "devDependencies": {21 "devDependencies": {
22 "@types/node": "^22.10.2",22 "@types/node": "^22.10.2",
23 "concurrently": "^9.1.2",
24 "electronmon": "^2.0.2",23 "electronmon": "^2.0.2",
25 "tsup": "^8.3.5",24 "tsdown": "^0.20.3",
26 "typescript": "^5.7.3",25 "typescript": "^5.7.3",
27 "vitest": "^3.0.0",26 "vitest": "^4.0.0",
28 "wait-on": "^8.0.2",27 "wait-on": "^8.0.2",
29 },28 },
30 },29 },
...@@ -43,8 +42,7 @@...@@ -43,8 +42,7 @@
43 "@t3tools/web": "workspace:*",42 "@t3tools/web": "workspace:*",
44 "@types/node": "^22.10.2",43 "@types/node": "^22.10.2",
45 "@types/ws": "^8.5.13",44 "@types/ws": "^8.5.13",
46 "tsup": "^8.3.5",45 "tsdown": "^0.20.3",
47 "tsx": "^4.19.0",
48 "typescript": "^5.7.3",46 "typescript": "^5.7.3",
49 },47 },
50 },48 },
...@@ -53,6 +51,7 @@...@@ -53,6 +51,7 @@
53 "version": "0.0.0",51 "version": "0.0.0",
54 "dependencies": {52 "dependencies": {
55 "@t3tools/contracts": "workspace:*",53 "@t3tools/contracts": "workspace:*",
54 "@tanstack/react-query": "^5.90.0",
56 "highlight.js": "^11.11.1",55 "highlight.js": "^11.11.1",
57 "lucide-react": "^0.563.0",56 "lucide-react": "^0.563.0",
58 "react": "^19.0.0",57 "react": "^19.0.0",
...@@ -66,11 +65,11 @@...@@ -66,11 +65,11 @@
66 "@tailwindcss/vite": "^4.0.0",65 "@tailwindcss/vite": "^4.0.0",
67 "@types/react": "^19.0.0",66 "@types/react": "^19.0.0",
68 "@types/react-dom": "^19.0.0",67 "@types/react-dom": "^19.0.0",
69 "@vitejs/plugin-react": "^4.3.4",68 "@vitejs/plugin-react": "^5.1.4",
70 "babel-plugin-react-compiler": "^19.0.0-beta-e552027-20250112",69 "babel-plugin-react-compiler": "^19.0.0-beta-e552027-20250112",
71 "tailwindcss": "^4.0.0",70 "tailwindcss": "^4.0.0",
72 "typescript": "^5.7.3",71 "typescript": "^5.7.3",
73 "vite": "^6.0.5",72 "vite": "^8.0.0-beta.12",
74 },73 },
75 },74 },
76 "packages/contracts": {75 "packages/contracts": {
...@@ -80,7 +79,7 @@...@@ -80,7 +79,7 @@
80 "zod": "^3.24.1",79 "zod": "^3.24.1",
81 },80 },
82 "devDependencies": {81 "devDependencies": {
83 "tsup": "^8.3.5",82 "tsdown": "^0.20.3",
84 "typescript": "^5.7.3",83 "typescript": "^5.7.3",
85 },84 },
86 },85 },
...@@ -92,7 +91,7 @@...@@ -92,7 +91,7 @@
9291
93 "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],92 "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="],
9493
95 "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],94 "@babel/generator": ["@babel/generator@8.0.0-rc.1", "", { "dependencies": { "@babel/parser": "^8.0.0-rc.1", "@babel/types": "^8.0.0-rc.1", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "@types/jsesc": "^2.5.0", "jsesc": "^3.0.2" } }, "sha512-3ypWOOiC4AYHKr8vYRVtWtWmyvcoItHtVqF8paFax+ydpmUdPsJpLBkBBs5ItmhdrwC3a0ZSqqFAdzls4ODP3w=="],
9695
97 "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],96 "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="],
9897
...@@ -106,13 +105,13 @@...@@ -106,13 +105,13 @@
106105
107 "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],106 "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
108107
109 "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],108 "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@8.0.0-rc.1", "", {}, "sha512-I4YnARytXC2RzkLNVnf5qFNFMzp679qZpmtw/V3Jt2uGnWiIxyJtaukjG7R8pSx8nG2NamICpGfljQsogj+FbQ=="],
110109
111 "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],110 "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
112111
113 "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="],112 "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="],
114113
115 "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],114 "@babel/parser": ["@babel/parser@8.0.0-rc.1", "", { "dependencies": { "@babel/types": "^8.0.0-rc.1" }, "bin": "./bin/babel-parser.js" }, "sha512-6HyyU5l1yK/7h9Ki52i5h6mDAx4qJdiLQO4FdCyJNoB/gy3T3GGJdhQzzbZgvgZCugYBvwtQiWRt94QKedHnkA=="],
116115
117 "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],116 "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="],
118117
...@@ -126,6 +125,12 @@...@@ -126,6 +125,12 @@
126125
127 "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],126 "@electron/get": ["@electron/get@2.0.3", "", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="],
128127
128 "@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
129
130 "@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
131
132 "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="],
133
129 "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],134 "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="],
130135
131 "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],136 "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="],
...@@ -200,6 +205,12 @@...@@ -200,6 +205,12 @@
200205
201 "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],206 "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
202207
208 "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="],
209
210 "@oxc-project/runtime": ["@oxc-project/runtime@0.112.0", "", {}, "sha512-4vYtWXMnXM6EaweCxbJ6bISAhkNHeN33SihvuX3wrpqaSJA4ZEoW35i9mSvE74+GDf1yTeVE+aEHA+WBpjDk/g=="],
211
212 "@oxc-project/types": ["@oxc-project/types@0.112.0", "", {}, "sha512-m6RebKHIRsax2iCwVpYW2ErQwa4ywHJrE4sCK3/8JK8ZZAWOKXaRJFl/uP51gaVyyXlaS4+chU1nSCdzYf6QqQ=="],
213
203 "@oxfmt/darwin-arm64": ["@oxfmt/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jmUfF7cNJPw57bEK7sMIqrYRgn4LH428tSgtgLTCtjuGuu1ShREyrkeB7y8HtkXRfhBs4lVY+HMLhqElJvZ6ww=="],214 "@oxfmt/darwin-arm64": ["@oxfmt/darwin-arm64@0.28.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-jmUfF7cNJPw57bEK7sMIqrYRgn4LH428tSgtgLTCtjuGuu1ShREyrkeB7y8HtkXRfhBs4lVY+HMLhqElJvZ6ww=="],
204215
205 "@oxfmt/darwin-x64": ["@oxfmt/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-S6vlV8S7jbjzJOSjfVg2CimUC0r7/aHDLdUm/3+/B/SU/s1jV7ivqWkMv1/8EB43d1BBwT9JQ60ZMTkBqeXSFA=="],216 "@oxfmt/darwin-x64": ["@oxfmt/darwin-x64@0.28.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-S6vlV8S7jbjzJOSjfVg2CimUC0r7/aHDLdUm/3+/B/SU/s1jV7ivqWkMv1/8EB43d1BBwT9JQ60ZMTkBqeXSFA=="],
...@@ -232,7 +243,35 @@...@@ -232,7 +243,35 @@
232243
233 "@oxlint/win32-x64": ["@oxlint/win32-x64@1.43.0", "", { "os": "win32", "cpu": "x64" }, "sha512-bSuItSU8mTSDsvmmLTepTdCL2FkJI6dwt9tot/k0EmiYF+ArRzmsl4lXVLssJNRV5lJEc5IViyTrh7oiwrjUqA=="],244 "@oxlint/win32-x64": ["@oxlint/win32-x64@1.43.0", "", { "os": "win32", "cpu": "x64" }, "sha512-bSuItSU8mTSDsvmmLTepTdCL2FkJI6dwt9tot/k0EmiYF+ArRzmsl4lXVLssJNRV5lJEc5IViyTrh7oiwrjUqA=="],
234245
235 "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="],246 "@quansync/fs": ["@quansync/fs@1.0.0", "", { "dependencies": { "quansync": "^1.0.0" } }, "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ=="],
247
248 "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-rc.3", "", { "os": "android", "cpu": "arm64" }, "sha512-0T1k9FinuBZ/t7rZ8jN6OpUKPnUjNdYHoj/cESWrQ3ZraAJ4OMm6z7QjSfCxqj8mOp9kTKc1zHK3kGz5vMu+nQ=="],
249
250 "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-rc.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-JWWLzvcmc/3pe7qdJqPpuPk91SoE/N+f3PcWx/6ZwuyDVyungAEJPvKm/eEldiDdwTmaEzWfIR+HORxYWrCi1A=="],
251
252 "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-rc.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-MTakBxfx3tde5WSmbHxuqlDsIW0EzQym+PJYGF4P6lG2NmKzi128OGynoFUqoD5ryCySEY85dug4v+LWGBElIw=="],
253
254 "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-rc.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-jje3oopyOLs7IwfvXoS6Lxnmie5JJO7vW29fdGFu5YGY1EDbVDhD+P9vDihqS5X6fFiqL3ZQZCMBg6jyHkSVww=="],
255
256 "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.3", "", { "os": "linux", "cpu": "arm" }, "sha512-A0n8P3hdLAaqzSFrQoA42p23ZKBYQOw+8EH5r15Sa9X1kD9/JXe0YT2gph2QTWvdr0CVK2BOXiK6ENfy6DXOag=="],
257
258 "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-rc.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kWXkoxxarYISBJ4bLNf5vFkEbb4JvccOwxWDxuK9yee8lg5XA7OpvlTptfRuwEvYcOZf+7VS69Uenpmpyo5Bjw=="],
259
260 "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-rc.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-Z03/wrqau9Bicfgb3Dbs6SYTHliELk2PM2LpG2nFd+cGupTMF5kanLEcj2vuuJLLhptNyS61rtk7SOZ+lPsTUA=="],
261
262 "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-rc.3", "", { "os": "linux", "cpu": "x64" }, "sha512-iSXXZsQp08CSilff/DCTFZHSVEpEwdicV3W8idHyrByrcsRDVh9sGC3sev6d8BygSGj3vt8GvUKBPCoyMA4tgQ=="],
263
264 "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-rc.3", "", { "os": "linux", "cpu": "x64" }, "sha512-qaj+MFudtdCv9xZo9znFvkgoajLdc+vwf0Kz5N44g+LU5XMe+IsACgn3UG7uTRlCCvhMAGXm1XlpEA5bZBrOcw=="],
265
266 "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-rc.3", "", { "os": "none", "cpu": "arm64" }, "sha512-U662UnMETyjT65gFmG9ma+XziENrs7BBnENi/27swZPYagubfHRirXHG2oMl+pEax2WvO7Kb9gHZmMakpYqBHQ=="],
267
268 "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-rc.3", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.1.1" }, "cpu": "none" }, "sha512-gekrQ3Q2HiC1T5njGyuUJoGpK/l6B/TNXKed3fZXNf9YRTJn3L5MOZsFBn4bN2+UX+8+7hgdlTcEsexX988G4g=="],
269
270 "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-rc.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-85y5JifyMgs8m5K2XzR/VDsapKbiFiohl7s5lEj7nmNGO0pkTXE7q6TQScei96BNAsoK7JC3pA7ukA8WRHVJpg=="],
271
272 "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-rc.3", "", { "os": "win32", "cpu": "x64" }, "sha512-a4VUQZH7LxGbUJ3qJ/TzQG8HxdHvf+jOnqf7B7oFx1TEBm+j2KNL2zr5SQ7wHkNAcaPevF6gf9tQnVBnC4mD+A=="],
273
274 "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="],
236275
237 "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="],276 "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="],
238277
...@@ -326,6 +365,12 @@...@@ -326,6 +365,12 @@
326365
327 "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],366 "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="],
328367
368 "@tanstack/query-core": ["@tanstack/query-core@5.90.20", "", {}, "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg=="],
369
370 "@tanstack/react-query": ["@tanstack/react-query@5.90.21", "", { "dependencies": { "@tanstack/query-core": "5.90.20" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg=="],
371
372 "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="],
373
329 "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],374 "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="],
330375
331 "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],376 "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="],
...@@ -350,6 +395,8 @@...@@ -350,6 +395,8 @@
350395
351 "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="],396 "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="],
352397
398 "@types/jsesc": ["@types/jsesc@2.5.1", "", {}, "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw=="],
399
353 "@types/keyv": ["@types/keyv@3.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="],400 "@types/keyv": ["@types/keyv@3.1.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="],
354401
355 "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],402 "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
...@@ -372,32 +419,30 @@...@@ -372,32 +419,30 @@
372419
373 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],420 "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
374421
375 "@vitejs/plugin-react": ["@vitejs/plugin-react@4.7.0", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.27", "@types/babel__core": "^7.20.5", "react-refresh": "^0.17.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA=="],422 "@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.4", "", { "dependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.3", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA=="],
376
377 "@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
378
379 "@vitest/mocker": ["@vitest/mocker@3.2.4", "", { "dependencies": { "@vitest/spy": "3.2.4", "estree-walker": "^3.0.3", "magic-string": "^0.30.17" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ=="],
380423
381 "@vitest/pretty-format": ["@vitest/pretty-format@3.2.4", "", { "dependencies": { "tinyrainbow": "^2.0.0" } }, "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA=="],424 "@vitest/expect": ["@vitest/expect@4.0.18", "", { "dependencies": { "@standard-schema/spec": "^1.0.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "chai": "^6.2.1", "tinyrainbow": "^3.0.3" } }, "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ=="],
382425
383 "@vitest/runner": ["@vitest/runner@3.2.4", "", { "dependencies": { "@vitest/utils": "3.2.4", "pathe": "^2.0.3", "strip-literal": "^3.0.0" } }, "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ=="],426 "@vitest/mocker": ["@vitest/mocker@4.0.18", "", { "dependencies": { "@vitest/spy": "4.0.18", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0-0" }, "optionalPeers": ["msw", "vite"] }, "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ=="],
384427
385 "@vitest/snapshot": ["@vitest/snapshot@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "magic-string": "^0.30.17", "pathe": "^2.0.3" } }, "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ=="],428 "@vitest/pretty-format": ["@vitest/pretty-format@4.0.18", "", { "dependencies": { "tinyrainbow": "^3.0.3" } }, "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw=="],
386429
387 "@vitest/spy": ["@vitest/spy@3.2.4", "", { "dependencies": { "tinyspy": "^4.0.3" } }, "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw=="],430 "@vitest/runner": ["@vitest/runner@4.0.18", "", { "dependencies": { "@vitest/utils": "4.0.18", "pathe": "^2.0.3" } }, "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw=="],
388431
389 "@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],432 "@vitest/snapshot": ["@vitest/snapshot@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "magic-string": "^0.30.21", "pathe": "^2.0.3" } }, "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA=="],
390433
391 "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="],434 "@vitest/spy": ["@vitest/spy@4.0.18", "", {}, "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw=="],
392435
393 "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],436 "@vitest/utils": ["@vitest/utils@4.0.18", "", { "dependencies": { "@vitest/pretty-format": "4.0.18", "tinyrainbow": "^3.0.3" } }, "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA=="],
394437
395 "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],438 "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
396439
397 "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="],440 "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="],
398441
399 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],442 "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="],
400443
444 "ast-kit": ["ast-kit@3.0.0-beta.1", "", { "dependencies": { "@babel/parser": "^8.0.0-beta.4", "estree-walker": "^3.0.3", "pathe": "^2.0.3" } }, "sha512-trmleAnZ2PxN/loHWVhhx1qeOHSRXq4TDsBBxq3GqeJitfk3+jTQ+v/C1km/KYq9M7wKqCewMh+/NAvVH7m+bw=="],
445
401 "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],446 "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
402447
403 "axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],448 "axios": ["axios@1.13.5", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-cz4ur7Vb0xS4/KUN0tPWe44eqxrIu31me+fbang3ijiNscE129POzipJJA6zniq2C/Z6sJCjMimjS8Lc/GAs8Q=="],
...@@ -408,6 +453,8 @@...@@ -408,6 +453,8 @@
408453
409 "baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],454 "baseline-browser-mapping": ["baseline-browser-mapping@2.9.19", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg=="],
410455
456 "birpc": ["birpc@4.0.0", "", {}, "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw=="],
457
411 "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],458 "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="],
412459
413 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],460 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
...@@ -418,8 +465,6 @@...@@ -418,8 +465,6 @@
418465
419 "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],466 "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="],
420467
421 "bundle-require": ["bundle-require@5.1.0", "", { "dependencies": { "load-tsconfig": "^0.2.3" }, "peerDependencies": { "esbuild": ">=0.18" } }, "sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA=="],
422
423 "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],468 "cac": ["cac@6.7.14", "", {}, "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ=="],
424469
425 "cacheable-lookup": ["cacheable-lookup@5.0.4", "", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="],470 "cacheable-lookup": ["cacheable-lookup@5.0.4", "", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="],
...@@ -432,9 +477,9 @@...@@ -432,9 +477,9 @@
432477
433 "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],478 "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="],
434479
435 "chai": ["chai@5.3.3", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw=="],480 "chai": ["chai@6.2.2", "", {}, "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg=="],
436481
437 "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],482 "chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
438483
439 "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],484 "character-entities": ["character-entities@2.0.2", "", {}, "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="],
440485
...@@ -444,12 +489,6 @@...@@ -444,12 +489,6 @@
444489
445 "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],490 "character-reference-invalid": ["character-reference-invalid@2.0.1", "", {}, "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="],
446491
447 "check-error": ["check-error@2.1.3", "", {}, "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA=="],
448
449 "chokidar": ["chokidar@4.0.3", "", { "dependencies": { "readdirp": "^4.0.1" } }, "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA=="],
450
451 "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="],
452
453 "clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],492 "clone-response": ["clone-response@1.0.3", "", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="],
454493
455 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],494 "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="],
...@@ -460,14 +499,6 @@...@@ -460,14 +499,6 @@
460499
461 "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],500 "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="],
462501
463 "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="],
464
465 "concurrently": ["concurrently@9.2.1", "", { "dependencies": { "chalk": "4.1.2", "rxjs": "7.8.2", "shell-quote": "1.8.3", "supports-color": "8.1.1", "tree-kill": "1.2.2", "yargs": "17.7.2" }, "bin": { "conc": "dist/bin/concurrently.js", "concurrently": "dist/bin/concurrently.js" } }, "sha512-fsfrO0MxV64Znoy8/l1vVIjjHa29SZyyqPgQBwhiDcaW8wJc2W3XWVOGx4M3oJBnv/zdUZIIp1gDeS98GzP8Ng=="],
466
467 "confbox": ["confbox@0.1.8", "", {}, "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w=="],
468
469 "consola": ["consola@3.4.2", "", {}, "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA=="],
470
471 "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],502 "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
472503
473 "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],504 "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="],
...@@ -478,8 +509,6 @@...@@ -478,8 +509,6 @@
478509
479 "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],510 "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="],
480511
481 "deep-eql": ["deep-eql@5.0.2", "", {}, "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q=="],
482
483 "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],512 "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="],
484513
485 "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],514 "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="],
...@@ -492,6 +521,8 @@...@@ -492,6 +521,8 @@
492521
493 "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],522 "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="],
494523
524 "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="],
525
495 "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],526 "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
496527
497 "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],528 "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="],
...@@ -502,6 +533,8 @@...@@ -502,6 +533,8 @@
502533
503 "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],534 "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
504535
536 "dts-resolver": ["dts-resolver@2.1.3", "", { "peerDependencies": { "oxc-resolver": ">=11.0.0" }, "optionalPeers": ["oxc-resolver"] }, "sha512-bihc7jPC90VrosXNzK0LTE2cuLP6jr0Ro8jk+kMugHReJVLIpHz/xadeq3MhuwyO4TD4OA3L1Q8pBBFRc08Tsw=="],
537
505 "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],538 "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="],
506539
507 "electron": ["electron@33.4.11", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^20.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg=="],540 "electron": ["electron@33.4.11", "", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^20.9.0", "extract-zip": "^2.0.1" }, "bin": { "electron": "cli.js" } }, "sha512-xmdAs5QWRkInC7TpXGNvzo/7exojubk+72jn1oJL7keNeIlw7xNglf8TGtJtkR4rWC5FJq0oXiIXPS9BcK2Irg=="],
...@@ -510,7 +543,7 @@...@@ -510,7 +543,7 @@
510543
511 "electronmon": ["electronmon@2.0.4", "", { "dependencies": { "chalk": "^3.0.0", "import-from": "^3.0.0", "runtime-required": "^1.1.0", "watchboy": "^0.4.3" }, "bin": { "electronmon": "bin/cli.js" } }, "sha512-u6eDrvUbqa+wsnMrhG2vHmo5neL1owLg2e5i1avGWcOb4rHsUf9lSfbs0FvfPsBNpLxxlPO98nrMhAGV+zw/fQ=="],544 "electronmon": ["electronmon@2.0.4", "", { "dependencies": { "chalk": "^3.0.0", "import-from": "^3.0.0", "runtime-required": "^1.1.0", "watchboy": "^0.4.3" }, "bin": { "electronmon": "bin/cli.js" } }, "sha512-u6eDrvUbqa+wsnMrhG2vHmo5neL1owLg2e5i1avGWcOb4rHsUf9lSfbs0FvfPsBNpLxxlPO98nrMhAGV+zw/fQ=="],
512545
513 "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],546 "empathic": ["empathic@2.0.0", "", {}, "sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA=="],
514547
515 "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],548 "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="],
516549
...@@ -552,8 +585,6 @@...@@ -552,8 +585,6 @@
552585
553 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],586 "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
554587
555 "fix-dts-default-cjs-exports": ["fix-dts-default-cjs-exports@1.0.1", "", { "dependencies": { "magic-string": "^0.30.17", "mlly": "^1.7.4", "rollup": "^4.34.8" } }, "sha512-pVIECanWFC61Hzl2+oOCtoJ3F17kglZC/6N94eRWycFgBH35hHx0Li604ZIzhseh97mf2p0cv7vVrOZGoqhlEg=="],
556
557 "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],588 "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="],
558589
559 "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],590 "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="],
...@@ -566,8 +597,6 @@...@@ -566,8 +597,6 @@
566597
567 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],598 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="],
568599
569 "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="],
570
571 "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],600 "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="],
572601
573 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],602 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="],
...@@ -606,6 +635,8 @@...@@ -606,6 +635,8 @@
606635
607 "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],636 "highlight.js": ["highlight.js@11.11.1", "", {}, "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="],
608637
638 "hookable": ["hookable@6.0.1", "", {}, "sha512-uKGyY8BuzN/a5gvzvA+3FVWo0+wUjgtfSdnmjtrOVwQCZPHpHDH2WRO3VZSOeluYrHoDCiXFffZXs8Dj1ULWtw=="],
639
609 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],640 "html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
610641
611 "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],642 "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="],
...@@ -614,6 +645,8 @@...@@ -614,6 +645,8 @@
614645
615 "import-from": ["import-from@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ=="],646 "import-from": ["import-from@3.0.0", "", { "dependencies": { "resolve-from": "^5.0.0" } }, "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ=="],
616647
648 "import-without-cache": ["import-without-cache@0.2.5", "", {}, "sha512-B6Lc2s6yApwnD2/pMzFh/d5AVjdsDXjgkeJ766FmFuJELIGHNycKRj+l3A39yZPM4CchqNCB4RITEAYB1KUM6A=="],
649
617 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],650 "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="],
618651
619 "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],652 "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="],
...@@ -624,8 +657,6 @@...@@ -624,8 +657,6 @@
624657
625 "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],658 "is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="],
626659
627 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="],
628
629 "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],660 "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="],
630661
631 "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],662 "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="],
...@@ -640,9 +671,7 @@...@@ -640,9 +671,7 @@
640671
641 "joi": ["joi@18.0.2", "", { "dependencies": { "@hapi/address": "^5.1.1", "@hapi/formula": "^3.0.2", "@hapi/hoek": "^11.0.7", "@hapi/pinpoint": "^2.0.1", "@hapi/tlds": "^1.1.1", "@hapi/topo": "^6.0.2", "@standard-schema/spec": "^1.0.0" } }, "sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA=="],672 "joi": ["joi@18.0.2", "", { "dependencies": { "@hapi/address": "^5.1.1", "@hapi/formula": "^3.0.2", "@hapi/hoek": "^11.0.7", "@hapi/pinpoint": "^2.0.1", "@hapi/tlds": "^1.1.1", "@hapi/topo": "^6.0.2", "@standard-schema/spec": "^1.0.0" } }, "sha512-RuCOQMIt78LWnktPoeBL0GErkNaJPTBGcYuyaBvUOQSpcpcLfWrHPPihYdOGbV5pam9VTWbeoF7TsGiHugcjGA=="],
642673
643 "joycon": ["joycon@3.1.1", "", {}, "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw=="],674 "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
644
645 "js-tokens": ["js-tokens@9.0.1", "", {}, "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ=="],
646675
647 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],676 "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
648677
...@@ -656,35 +685,29 @@...@@ -656,35 +685,29 @@
656685
657 "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],686 "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
658687
659 "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],688 "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="],
660
661 "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
662
663 "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
664689
665 "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],690 "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="],
666691
667 "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],692 "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="],
668693
669 "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],694 "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="],
670695
671 "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],696 "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="],
672697
673 "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],698 "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="],
674699
675 "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],700 "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="],
676701
677 "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],702 "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="],
678703
679 "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],704 "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="],
680705
681 "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],706 "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="],
682707
683 "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="],708 "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="],
684709
685 "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],710 "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="],
686
687 "load-tsconfig": ["load-tsconfig@0.2.5", "", {}, "sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg=="],
688711
689 "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],712 "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="],
690713
...@@ -692,8 +715,6 @@...@@ -692,8 +715,6 @@
692715
693 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],716 "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="],
694717
695 "loupe": ["loupe@3.2.1", "", {}, "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ=="],
696
697 "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],718 "lowercase-keys": ["lowercase-keys@2.0.0", "", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="],
698719
699 "lowlight": ["lowlight@3.3.0", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.0.0", "highlight.js": "~11.11.0" } }, "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ=="],720 "lowlight": ["lowlight@3.3.0", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.0.0", "highlight.js": "~11.11.0" } }, "sha512-0JNhgFoPvP6U6lE/UdVsSq99tn6DhjjpAj5MxG49ewd2mOBVtwWYIT8ClyABhq198aXXODMU6Ox8DrGy/CpTZQ=="],
...@@ -806,12 +827,8 @@...@@ -806,12 +827,8 @@
806827
807 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],828 "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
808829
809 "mlly": ["mlly@1.8.0", "", { "dependencies": { "acorn": "^8.15.0", "pathe": "^2.0.3", "pkg-types": "^1.3.1", "ufo": "^1.6.1" } }, "sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g=="],
810
811 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],830 "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
812831
813 "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="],
814
815 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],832 "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
816833
817 "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],834 "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="],
...@@ -820,10 +837,10 @@...@@ -820,10 +837,10 @@
820837
821 "normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="],838 "normalize-url": ["normalize-url@6.1.0", "", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="],
822839
823 "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="],
824
825 "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],840 "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="],
826841
842 "obug": ["obug@2.1.1", "", {}, "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ=="],
843
827 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],844 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
828845
829 "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],846 "open": ["open@10.2.0", "", { "dependencies": { "default-browser": "^5.2.1", "define-lazy-prop": "^3.0.0", "is-inside-container": "^1.0.0", "wsl-utils": "^0.1.0" } }, "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA=="],
...@@ -838,8 +855,6 @@...@@ -838,8 +855,6 @@
838855
839 "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],856 "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="],
840857
841 "pathval": ["pathval@2.0.1", "", {}, "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ=="],
842
843 "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],858 "pend": ["pend@1.2.0", "", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="],
844859
845 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],860 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="],
...@@ -848,14 +863,8 @@...@@ -848,14 +863,8 @@
848863
849 "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],864 "pify": ["pify@4.0.1", "", {}, "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g=="],
850865
851 "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="],
852
853 "pkg-types": ["pkg-types@1.3.1", "", { "dependencies": { "confbox": "^0.1.8", "mlly": "^1.7.4", "pathe": "^2.0.1" } }, "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ=="],
854
855 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],866 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="],
856867
857 "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="],
858
859 "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],868 "progress": ["progress@2.0.3", "", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="],
860869
861 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],870 "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="],
...@@ -864,6 +873,8 @@...@@ -864,6 +873,8 @@
864873
865 "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],874 "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="],
866875
876 "quansync": ["quansync@1.0.0", "", {}, "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA=="],
877
867 "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],878 "quick-lru": ["quick-lru@5.1.1", "", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="],
868879
869 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],880 "react": ["react@19.2.4", "", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="],
...@@ -872,9 +883,7 @@...@@ -872,9 +883,7 @@
872883
873 "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],884 "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="],
874885
875 "react-refresh": ["react-refresh@0.17.0", "", {}, "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ=="],886 "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="],
876
877 "readdirp": ["readdirp@4.1.2", "", {}, "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg=="],
878887
879 "rehype-highlight": ["rehype-highlight@7.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-text": "^4.0.0", "lowlight": "^3.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA=="],888 "rehype-highlight": ["rehype-highlight@7.0.2", "", { "dependencies": { "@types/hast": "^3.0.0", "hast-util-to-text": "^4.0.0", "lowlight": "^3.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-k158pK7wdC2qL3M5NcZROZ2tR/l7zOzjxXd5VGdcfIyoijjQqpHd3JKtYSBDpDZ38UI2WJWuFAtkMDxmx5kstA=="],
880889
...@@ -888,8 +897,6 @@...@@ -888,8 +897,6 @@
888897
889 "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="],898 "remove-trailing-separator": ["remove-trailing-separator@1.1.0", "", {}, "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="],
890899
891 "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
892
893 "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],900 "resolve-alpn": ["resolve-alpn@1.2.1", "", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="],
894901
895 "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],902 "resolve-from": ["resolve-from@5.0.0", "", {}, "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw=="],
...@@ -900,6 +907,10 @@...@@ -900,6 +907,10 @@
900907
901 "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="],908 "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="],
902909
910 "rolldown": ["rolldown@1.0.0-rc.3", "", { "dependencies": { "@oxc-project/types": "=0.112.0", "@rolldown/pluginutils": "1.0.0-rc.3" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-rc.3", "@rolldown/binding-darwin-arm64": "1.0.0-rc.3", "@rolldown/binding-darwin-x64": "1.0.0-rc.3", "@rolldown/binding-freebsd-x64": "1.0.0-rc.3", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-arm64-musl": "1.0.0-rc.3", "@rolldown/binding-linux-x64-gnu": "1.0.0-rc.3", "@rolldown/binding-linux-x64-musl": "1.0.0-rc.3", "@rolldown/binding-openharmony-arm64": "1.0.0-rc.3", "@rolldown/binding-wasm32-wasi": "1.0.0-rc.3", "@rolldown/binding-win32-arm64-msvc": "1.0.0-rc.3", "@rolldown/binding-win32-x64-msvc": "1.0.0-rc.3" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-Po/YZECDOqVXjIXrtC5h++a5NLvKAQNrd9ggrIG3sbDfGO5BqTUsrI6l8zdniKRp3r5Tp/2JTrXqx4GIguFCMw=="],
911
912 "rolldown-plugin-dts": ["rolldown-plugin-dts@0.22.1", "", { "dependencies": { "@babel/generator": "8.0.0-rc.1", "@babel/helper-validator-identifier": "8.0.0-rc.1", "@babel/parser": "8.0.0-rc.1", "@babel/types": "8.0.0-rc.1", "ast-kit": "^3.0.0-beta.1", "birpc": "^4.0.0", "dts-resolver": "^2.1.3", "get-tsconfig": "^4.13.1", "obug": "^2.1.1" }, "peerDependencies": { "@ts-macro/tsc": "^0.3.6", "@typescript/native-preview": ">=7.0.0-dev.20250601.1", "rolldown": "^1.0.0-rc.3", "typescript": "^5.0.0", "vue-tsc": "~3.2.0" }, "optionalPeers": ["@ts-macro/tsc", "@typescript/native-preview", "typescript", "vue-tsc"] }, "sha512-5E0AiM5RSQhU6cjtkDFWH6laW4IrMu0j1Mo8x04Xo1ALHmaRMs9/7zej7P3RrryVHW/DdZAp85MA7Be55p0iUw=="],
913
903 "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="],914 "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="],
904915
905 "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],916 "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="],
...@@ -910,18 +921,14 @@...@@ -910,18 +921,14 @@
910921
911 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],922 "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="],
912923
913 "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],924 "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],
914925
915 "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],926 "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="],
916927
917 "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="],928 "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="],
918929
919 "shell-quote": ["shell-quote@1.8.3", "", {}, "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw=="],
920
921 "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],930 "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
922931
923 "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
924
925 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],932 "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
926933
927 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],934 "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="],
...@@ -932,23 +939,15 @@...@@ -932,23 +939,15 @@
932939
933 "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],940 "std-env": ["std-env@3.10.0", "", {}, "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg=="],
934941
935 "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
936
937 "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],942 "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="],
938943
939 "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
940
941 "strip-literal": ["strip-literal@3.1.0", "", { "dependencies": { "js-tokens": "^9.0.1" } }, "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg=="],
942
943 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],944 "style-to-js": ["style-to-js@1.1.21", "", { "dependencies": { "style-to-object": "1.0.14" } }, "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ=="],
944945
945 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],946 "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="],
946947
947 "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="],
948
949 "sumchecker": ["sumchecker@3.0.1", "", { "dependencies": { "debug": "^4.1.0" } }, "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg=="],948 "sumchecker": ["sumchecker@3.0.1", "", { "dependencies": { "debug": "^4.1.0" } }, "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg=="],
950949
951 "supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="],950 "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
952951
953 "t3": ["t3@workspace:apps/server"],952 "t3": ["t3@workspace:apps/server"],
954953
...@@ -956,21 +955,15 @@...@@ -956,21 +955,15 @@
956955
957 "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],956 "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="],
958957
959 "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="],
960
961 "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="],
962
963 "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],958 "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
964959
965 "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],960 "tinyexec": ["tinyexec@1.0.2", "", {}, "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg=="],
966961
967 "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],962 "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="],
968963
969 "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],964 "tinypool": ["tinypool@2.1.0", "", {}, "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw=="],
970965
971 "tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="],966 "tinyrainbow": ["tinyrainbow@3.0.3", "", {}, "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q=="],
972
973 "tinyspy": ["tinyspy@4.0.4", "", {}, "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q=="],
974967
975 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],968 "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
976969
...@@ -980,12 +973,10 @@...@@ -980,12 +973,10 @@
980973
981 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],974 "trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
982975
983 "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="],976 "tsdown": ["tsdown@0.20.3", "", { "dependencies": { "ansis": "^4.2.0", "cac": "^6.7.14", "defu": "^6.1.4", "empathic": "^2.0.0", "hookable": "^6.0.1", "import-without-cache": "^0.2.5", "obug": "^2.1.1", "picomatch": "^4.0.3", "rolldown": "1.0.0-rc.3", "rolldown-plugin-dts": "^0.22.1", "semver": "^7.7.3", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tree-kill": "^1.2.2", "unconfig-core": "^7.4.2", "unrun": "^0.2.27" }, "peerDependencies": { "@arethetypeswrong/core": "^0.18.1", "@vitejs/devtools": "*", "publint": "^0.3.0", "typescript": "^5.0.0", "unplugin-lightningcss": "^0.4.0", "unplugin-unused": "^0.5.0" }, "optionalPeers": ["@arethetypeswrong/core", "@vitejs/devtools", "publint", "typescript", "unplugin-lightningcss", "unplugin-unused"], "bin": { "tsdown": "dist/run.mjs" } }, "sha512-qWOUXSbe4jN8JZEgrkc/uhJpC8VN2QpNu3eZkBWwNuTEjc/Ik1kcc54ycfcQ5QPRHeu9OQXaLfCI3o7pEJgB2w=="],
984977
985 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],978 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
986979
987 "tsup": ["tsup@8.5.1", "", { "dependencies": { "bundle-require": "^5.1.0", "cac": "^6.7.14", "chokidar": "^4.0.3", "consola": "^3.4.0", "debug": "^4.4.0", "esbuild": "^0.27.0", "fix-dts-default-cjs-exports": "^1.0.0", "joycon": "^3.1.1", "picocolors": "^1.1.1", "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", "rollup": "^4.34.8", "source-map": "^0.7.6", "sucrase": "^3.35.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.11", "tree-kill": "^1.2.2" }, "peerDependencies": { "@microsoft/api-extractor": "^7.36.0", "@swc/core": "^1", "postcss": "^8.4.12", "typescript": ">=4.5.0" }, "optionalPeers": ["@microsoft/api-extractor", "@swc/core", "postcss", "typescript"], "bin": { "tsup": "dist/cli-default.js", "tsup-node": "dist/cli-node.js" } }, "sha512-xtgkqwdhpKWr3tKPmCkvYmS9xnQK3m3XgxZHwSUjvfTjp7YfXe5tT3GgWi0F2N+ZSMsOeWeZFh7ZZFg5iPhing=="],
988
989 "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],980 "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="],
990981
991 "turbo": ["turbo@2.8.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.3", "turbo-darwin-arm64": "2.8.3", "turbo-linux-64": "2.8.3", "turbo-linux-arm64": "2.8.3", "turbo-windows-64": "2.8.3", "turbo-windows-arm64": "2.8.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-8Osxz5Tu/Dw2kb31EAY+nhq/YZ3wzmQSmYa1nIArqxgCAldxv9TPlrAiaBUDVnKA4aiPn0OFBD1ACcpc5VFOAQ=="],982 "turbo": ["turbo@2.8.3", "", { "optionalDependencies": { "turbo-darwin-64": "2.8.3", "turbo-darwin-arm64": "2.8.3", "turbo-linux-64": "2.8.3", "turbo-linux-arm64": "2.8.3", "turbo-windows-64": "2.8.3", "turbo-windows-arm64": "2.8.3" }, "bin": { "turbo": "bin/turbo" } }, "sha512-8Osxz5Tu/Dw2kb31EAY+nhq/YZ3wzmQSmYa1nIArqxgCAldxv9TPlrAiaBUDVnKA4aiPn0OFBD1ACcpc5VFOAQ=="],
...@@ -1006,7 +997,7 @@...@@ -1006,7 +997,7 @@
1006997
1007 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],998 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
1008999
1009 "ufo": ["ufo@1.6.3", "", {}, "sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q=="],1000 "unconfig-core": ["unconfig-core@7.4.2", "", { "dependencies": { "@quansync/fs": "^1.0.0", "quansync": "^1.0.0" } }, "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg=="],
10101001
1011 "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],1002 "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="],
10121003
...@@ -1028,17 +1019,17 @@...@@ -1028,17 +1019,17 @@
10281019
1029 "unixify": ["unixify@1.0.0", "", { "dependencies": { "normalize-path": "^2.1.1" } }, "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg=="],1020 "unixify": ["unixify@1.0.0", "", { "dependencies": { "normalize-path": "^2.1.1" } }, "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg=="],
10301021
1022 "unrun": ["unrun@0.2.27", "", { "dependencies": { "rolldown": "1.0.0-rc.3" }, "peerDependencies": { "synckit": "^0.11.11" }, "optionalPeers": ["synckit"], "bin": { "unrun": "dist/cli.mjs" } }, "sha512-Mmur1UJpIbfxasLOhPRvox/QS4xBiDii71hMP7smfRthGcwFL2OAmYRgduLANOAU4LUkvVamuP+02U+c90jlrw=="],
1023
1031 "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],1024 "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="],
10321025
1033 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],1026 "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="],
10341027
1035 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],1028 "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="],
10361029
1037 "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],1030 "vite": ["vite@8.0.0-beta.13", "", { "dependencies": { "@oxc-project/runtime": "0.112.0", "fdir": "^6.5.0", "lightningcss": "^1.31.1", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-rc.3", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "@vitejs/devtools": "^0.0.0-alpha.24", "esbuild": "^0.27.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "@vitejs/devtools", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-7s/rfpYOAo7WUHh9irzaGjhhKb12hGv0BpDegAMV5A391wdyvM45WtX6VMV7hvEtZF2j/QtpDpR6ldXI3GgARQ=="],
1038
1039 "vite-node": ["vite-node@3.2.4", "", { "dependencies": { "cac": "^6.7.14", "debug": "^4.4.1", "es-module-lexer": "^1.7.0", "pathe": "^2.0.3", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" }, "bin": { "vite-node": "vite-node.mjs" } }, "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg=="],
10401031
1041 "vitest": ["vitest@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/expect": "3.2.4", "@vitest/mocker": "3.2.4", "@vitest/pretty-format": "^3.2.4", "@vitest/runner": "3.2.4", "@vitest/snapshot": "3.2.4", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "debug": "^4.4.1", "expect-type": "^1.2.1", "magic-string": "^0.30.17", "pathe": "^2.0.3", "picomatch": "^4.0.2", "std-env": "^3.9.0", "tinybench": "^2.9.0", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.14", "tinypool": "^1.1.1", "tinyrainbow": "^2.0.0", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", "vite-node": "3.2.4", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@types/debug": "^4.1.12", "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "@vitest/browser": "3.2.4", "@vitest/ui": "3.2.4", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@types/debug", "@types/node", "@vitest/browser", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A=="],1032 "vitest": ["vitest@4.0.18", "", { "dependencies": { "@vitest/expect": "4.0.18", "@vitest/mocker": "4.0.18", "@vitest/pretty-format": "4.0.18", "@vitest/runner": "4.0.18", "@vitest/snapshot": "4.0.18", "@vitest/spy": "4.0.18", "@vitest/utils": "4.0.18", "es-module-lexer": "^1.7.0", "expect-type": "^1.2.2", "magic-string": "^0.30.21", "obug": "^2.1.1", "pathe": "^2.0.3", "picomatch": "^4.0.3", "std-env": "^3.10.0", "tinybench": "^2.9.0", "tinyexec": "^1.0.2", "tinyglobby": "^0.2.15", "tinyrainbow": "^3.0.3", "vite": "^6.0.0 || ^7.0.0", "why-is-node-running": "^2.3.0" }, "peerDependencies": { "@edge-runtime/vm": "*", "@opentelemetry/api": "^1.9.0", "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", "@vitest/browser-playwright": "4.0.18", "@vitest/browser-preview": "4.0.18", "@vitest/browser-webdriverio": "4.0.18", "@vitest/ui": "4.0.18", "happy-dom": "*", "jsdom": "*" }, "optionalPeers": ["@edge-runtime/vm", "@opentelemetry/api", "@types/node", "@vitest/browser-playwright", "@vitest/browser-preview", "@vitest/browser-webdriverio", "@vitest/ui", "happy-dom", "jsdom"], "bin": { "vitest": "vitest.mjs" } }, "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ=="],
10421033
1043 "wait-on": ["wait-on@8.0.5", "", { "dependencies": { "axios": "^1.12.1", "joi": "^18.0.1", "lodash": "^4.17.21", "minimist": "^1.2.8", "rxjs": "^7.8.2" }, "bin": { "wait-on": "bin/wait-on" } }, "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag=="],1034 "wait-on": ["wait-on@8.0.5", "", { "dependencies": { "axios": "^1.12.1", "joi": "^18.0.1", "lodash": "^4.17.21", "minimist": "^1.2.8", "rxjs": "^7.8.2" }, "bin": { "wait-on": "bin/wait-on" } }, "sha512-J3WlS0txVHkhLRb2FsmRg3dkMTCV1+M6Xra3Ho7HzZDHpE7DCOnoSoCJsZotrmW3uRMhvIJGSKUKrh/MeF4iag=="],
10441035
...@@ -1046,32 +1037,50 @@...@@ -1046,32 +1037,50 @@
10461037
1047 "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],1038 "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
10481039
1049 "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="],
1050
1051 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],1040 "wrappy": ["wrappy@1.0.2", "", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="],
10521041
1053 "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],1042 "ws": ["ws@8.19.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg=="],
10541043
1055 "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],1044 "wsl-utils": ["wsl-utils@0.1.0", "", { "dependencies": { "is-wsl": "^3.1.0" } }, "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw=="],
10561045
1057 "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="],
1058
1059 "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],1046 "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="],
10601047
1061 "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="],
1062
1063 "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="],
1064
1065 "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],1048 "yauzl": ["yauzl@2.10.0", "", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="],
10661049
1067 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],1050 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="],
10681051
1069 "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],1052 "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
10701053
1071 "@babel/code-frame/js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],1054 "@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
1055
1056 "@babel/core/@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
1057
1058 "@babel/core/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
1059
1060 "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
1061
1062 "@babel/generator/@babel/types": ["@babel/types@8.0.0-rc.1", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.1", "@babel/helper-validator-identifier": "^8.0.0-rc.1" } }, "sha512-ubmJ6TShyaD69VE9DQrlXcdkvJbmwWPB8qYj0H2kaJi29O7vJT9ajSdBd2W8CG34pwL9pYA74fi7RHC1qbLoVQ=="],
1063
1064 "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
1065
1066 "@babel/helper-module-transforms/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
1067
1068 "@babel/parser/@babel/types": ["@babel/types@8.0.0-rc.1", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.1", "@babel/helper-validator-identifier": "^8.0.0-rc.1" } }, "sha512-ubmJ6TShyaD69VE9DQrlXcdkvJbmwWPB8qYj0H2kaJi29O7vJT9ajSdBd2W8CG34pwL9pYA74fi7RHC1qbLoVQ=="],
1069
1070 "@babel/template/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
1071
1072 "@babel/traverse/@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="],
1073
1074 "@babel/traverse/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
1075
1076 "@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="],
1077
1078 "@electron/get/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
10721079
1073 "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],1080 "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="],
10741081
1082 "@tailwindcss/node/lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="],
1083
1075 "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],1084 "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="],
10761085
1077 "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],1086 "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="],
...@@ -1084,15 +1093,17 @@...@@ -1084,15 +1093,17 @@
10841093
1085 "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],1094 "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
10861095
1087 "chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],1096 "@tailwindcss/vite/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
10881097
1089 "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],1098 "@types/babel__core/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
10901099
1091 "electron/@types/node": ["@types/node@20.19.33", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw=="],1100 "@types/babel__template/@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="],
10921101
1093 "electronmon/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],1102 "@vitejs/plugin-react/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
10941103
1095 "global-agent/semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="],1104 "clone-response/mimic-response": ["mimic-response@1.0.1", "", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="],
1105
1106 "electron/@types/node": ["@types/node@20.19.33", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw=="],
10961107
1097 "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],1108 "mdast-util-find-and-replace/escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="],
10981109
...@@ -1100,62 +1111,198 @@...@@ -1100,62 +1111,198 @@
11001111
1101 "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],1112 "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="],
11021113
1103 "vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],1114 "rolldown-plugin-dts/@babel/types": ["@babel/types@8.0.0-rc.1", "", { "dependencies": { "@babel/helper-string-parser": "^8.0.0-rc.1", "@babel/helper-validator-identifier": "^8.0.0-rc.1" } }, "sha512-ubmJ6TShyaD69VE9DQrlXcdkvJbmwWPB8qYj0H2kaJi29O7vJT9ajSdBd2W8CG34pwL9pYA74fi7RHC1qbLoVQ=="],
1115
1116 "vitest/vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="],
1117
1118 "@babel/generator/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],
1119
1120 "@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],
1121
1122 "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="],
1123
1124 "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="],
1125
1126 "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="],
1127
1128 "@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="],
1129
1130 "@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="],
1131
1132 "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="],
1133
1134 "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="],
1135
1136 "@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="],
1137
1138 "@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="],
1139
1140 "@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="],
1141
1142 "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="],
1143
1144 "@tailwindcss/vite/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
1145
1146 "@vitejs/plugin-react/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
1147
1148 "rolldown-plugin-dts/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@8.0.0-rc.1", "", {}, "sha512-vi/pfmbrOtQmqgfboaBhaCU50G7mcySVu69VU8z+lYoPPB6WzI9VgV7WQfL908M4oeSH5fDkmoupIqoE0SdApw=="],
1149
1150 "vitest/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="],
1151
1152 "@tailwindcss/vite/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
1153
1154 "@tailwindcss/vite/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
1155
1156 "@tailwindcss/vite/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
1157
1158 "@tailwindcss/vite/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
1159
1160 "@tailwindcss/vite/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
1161
1162 "@tailwindcss/vite/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
1163
1164 "@tailwindcss/vite/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
1165
1166 "@tailwindcss/vite/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
1167
1168 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
1169
1170 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
1171
1172 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
1173
1174 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
1175
1176 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
1177
1178 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
1179
1180 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
1181
1182 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
1183
1184 "@tailwindcss/vite/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
1185
1186 "@tailwindcss/vite/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
1187
1188 "@tailwindcss/vite/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
1189
1190 "@tailwindcss/vite/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
1191
1192 "@tailwindcss/vite/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
1193
1194 "@tailwindcss/vite/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
1195
1196 "@tailwindcss/vite/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
1197
1198 "@tailwindcss/vite/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
1199
1200 "@tailwindcss/vite/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
1201
1202 "@tailwindcss/vite/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
1203
1204 "@vitejs/plugin-react/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
1205
1206 "@vitejs/plugin-react/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
1207
1208 "@vitejs/plugin-react/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
1209
1210 "@vitejs/plugin-react/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
1211
1212 "@vitejs/plugin-react/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
1213
1214 "@vitejs/plugin-react/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
1215
1216 "@vitejs/plugin-react/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
1217
1218 "@vitejs/plugin-react/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
1219
1220 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
1221
1222 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
1223
1224 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
1225
1226 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
1227
1228 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
1229
1230 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
1231
1232 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
1233
1234 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
1235
1236 "@vitejs/plugin-react/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
1237
1238 "@vitejs/plugin-react/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
1239
1240 "@vitejs/plugin-react/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
1241
1242 "@vitejs/plugin-react/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
1243
1244 "@vitejs/plugin-react/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
1245
1246 "@vitejs/plugin-react/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
1247
1248 "@vitejs/plugin-react/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
1249
1250 "@vitejs/plugin-react/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
11041251
1105 "vitest/tinypool": ["tinypool@1.1.1", "", {}, "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg=="],1252 "@vitejs/plugin-react/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
11061253
1107 "electronmon/chalk/supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],1254 "@vitejs/plugin-react/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
11081255
1109 "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],1256 "vitest/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="],
11101257
1111 "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],1258 "vitest/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="],
11121259
1113 "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],1260 "vitest/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="],
11141261
1115 "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],1262 "vitest/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="],
11161263
1117 "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],1264 "vitest/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="],
11181265
1119 "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],1266 "vitest/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="],
11201267
1121 "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],1268 "vitest/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="],
11221269
1123 "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],1270 "vitest/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="],
11241271
1125 "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],1272 "vitest/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="],
11261273
1127 "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],1274 "vitest/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="],
11281275
1129 "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],1276 "vitest/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="],
11301277
1131 "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],1278 "vitest/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="],
11321279
1133 "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],1280 "vitest/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="],
11341281
1135 "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],1282 "vitest/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="],
11361283
1137 "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],1284 "vitest/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="],
11381285
1139 "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],1286 "vitest/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="],
11401287
1141 "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],1288 "vitest/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="],
11421289
1143 "vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],1290 "vitest/vite/esbuild/@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="],
11441291
1145 "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],1292 "vitest/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="],
11461293
1147 "vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],1294 "vitest/vite/esbuild/@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="],
11481295
1149 "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],1296 "vitest/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="],
11501297
1151 "vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],1298 "vitest/vite/esbuild/@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="],
11521299
1153 "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],1300 "vitest/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="],
11541301
1155 "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],1302 "vitest/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="],
11561303
1157 "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],1304 "vitest/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="],
11581305
1159 "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],1306 "vitest/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="],
1160 }1307 }
1161}1308}
package.json+9-9
...@@ -7,26 +7,26 @@...@@ -7,26 +7,26 @@
7 ],7 ],
8 "scripts": {8 "scripts": {
9 "dev": "T3CODE_LOG_WS_EVENTS=1 VITE_WS_URL=ws://localhost:3773 turbo run dev --ui=tui --filter=@t3tools/contracts --filter=@t3tools/web --filter=t3 --parallel",9 "dev": "T3CODE_LOG_WS_EVENTS=1 VITE_WS_URL=ws://localhost:3773 turbo run dev --ui=tui --filter=@t3tools/contracts --filter=@t3tools/web --filter=t3 --parallel",
10 "dev:server": "bun run build:contracts && bun run --cwd apps/server dev",10 "dev:server": "turbo run dev --filter=t3",
11 "dev:web": "VITE_WS_URL=ws://localhost:3773 bun run --cwd apps/web dev",11 "dev:web": "VITE_WS_URL=ws://localhost:3773 turbo run dev --filter=@t3tools/web",
12 "dev:desktop": "bun run --cwd apps/desktop dev",12 "dev:desktop": "turbo run dev --filter=@t3tools/desktop --filter=@t3tools/web --parallel",
13 "start": "node apps/server/dist/index.js",13 "start": "turbo run start --filter=t3",
14 "start:desktop": "bun run --cwd apps/desktop start",14 "start:desktop": "turbo run start --filter=@t3tools/desktop",
15 "build": "turbo run build",15 "build": "turbo run build",
16 "build:desktop": "bun run build:contracts && bun run --cwd apps/web build && bun run --cwd apps/server build && bun run --cwd apps/desktop build",16 "build:desktop": "turbo run build --filter=@t3tools/desktop --filter=t3",
17 "typecheck": "turbo run typecheck",17 "typecheck": "turbo run typecheck",
18 "lint": "oxlint --report-unused-disable-directives",18 "lint": "oxlint --report-unused-disable-directives",
19 "test": "turbo run test",19 "test": "turbo run test",
20 "test:desktop-smoke": "bun run --cwd apps/desktop smoke-test",20 "test:desktop-smoke": "turbo run smoke-test --filter=@t3tools/desktop",
21 "fmt": "oxfmt",21 "fmt": "oxfmt",
22 "build:contracts": "bun run --cwd packages/contracts build"22 "build:contracts": "turbo run build --filter=@t3tools/contracts"
23 },23 },
24 "devDependencies": {24 "devDependencies": {
25 "oxfmt": "^0.28.0",25 "oxfmt": "^0.28.0",
26 "oxlint": "^1.43.0",26 "oxlint": "^1.43.0",
27 "turbo": "^2.3.3",27 "turbo": "^2.3.3",
28 "typescript": "^5.7.3",28 "typescript": "^5.7.3",
29 "vitest": "^3.0.0"29 "vitest": "^4.0.0"
30 },30 },
31 "engines": {31 "engines": {
32 "bun": ">=1.3.9"32 "bun": ">=1.3.9"
packages/contracts/package.json+5-5
...@@ -7,18 +7,18 @@...@@ -7,18 +7,18 @@
7 ],7 ],
8 "type": "module",8 "type": "module",
9 "main": "./dist/index.cjs",9 "main": "./dist/index.cjs",
10 "module": "./dist/index.js",10 "module": "./dist/index.mjs",
11 "types": "./src/index.ts",11 "types": "./src/index.ts",
12 "exports": {12 "exports": {
13 ".": {13 ".": {
14 "types": "./src/index.ts",14 "types": "./src/index.ts",
15 "import": "./dist/index.js",15 "import": "./dist/index.mjs",
16 "require": "./dist/index.cjs"16 "require": "./dist/index.cjs"
17 }17 }
18 },18 },
19 "scripts": {19 "scripts": {
20 "dev": "tsup src/index.ts --format esm,cjs --dts --watch --clean",20 "dev": "tsdown src/index.ts --format esm,cjs --dts --watch --clean",
21 "build": "tsup src/index.ts --format esm,cjs --dts --clean",21 "build": "tsdown src/index.ts --format esm,cjs --dts --clean",
22 "typecheck": "tsc --noEmit",22 "typecheck": "tsc --noEmit",
23 "test": "vitest run"23 "test": "vitest run"
24 },24 },
...@@ -26,7 +26,7 @@...@@ -26,7 +26,7 @@
26 "zod": "^3.24.1"26 "zod": "^3.24.1"
27 },27 },
28 "devDependencies": {28 "devDependencies": {
29 "tsup": "^8.3.5",29 "tsdown": "^0.20.3",
30 "typescript": "^5.7.3"30 "typescript": "^5.7.3"
31 }31 }
32}32}
packages/contracts/src/git.ts created+69
...@@ -0,0 +1,69 @@
1import { z } from "zod";
2
3// ── Input schemas ──
4
5export const gitListBranchesInputSchema = z.object({
6 cwd: z.string().min(1),
7});
8
9export const gitCreateWorktreeInputSchema = z.object({
10 cwd: z.string().min(1),
11 /** Base branch to create the worktree from. */
12 branch: z.string().min(1),
13 /** New branch name to create in the worktree. */
14 newBranch: z.string().min(1),
15 path: z.string().min(1).optional(),
16});
17
18export const gitRemoveWorktreeInputSchema = z.object({
19 cwd: z.string().min(1),
20 path: z.string().min(1),
21});
22
23export const gitCreateBranchInputSchema = z.object({
24 cwd: z.string().min(1),
25 branch: z.string().min(1),
26});
27
28export const gitCheckoutInputSchema = z.object({
29 cwd: z.string().min(1),
30 branch: z.string().min(1),
31});
32
33export const gitInitInputSchema = z.object({
34 cwd: z.string().min(1),
35});
36
37// ── Output schemas ──
38
39export const gitBranchSchema = z.object({
40 name: z.string().min(1),
41 current: z.boolean(),
42 isDefault: z.boolean(),
43 worktreePath: z.string().min(1).nullable(),
44});
45
46export const gitWorktreeSchema = z.object({
47 path: z.string().min(1),
48 branch: z.string().min(1),
49});
50
51// ── Types ──
52
53export type GitListBranchesInput = z.infer<typeof gitListBranchesInputSchema>;
54export type GitBranch = z.infer<typeof gitBranchSchema>;
55export type GitCreateWorktreeInput = z.infer<typeof gitCreateWorktreeInputSchema>;
56export type GitWorktree = z.infer<typeof gitWorktreeSchema>;
57export type GitRemoveWorktreeInput = z.infer<typeof gitRemoveWorktreeInputSchema>;
58export type GitCreateBranchInput = z.infer<typeof gitCreateBranchInputSchema>;
59export type GitCheckoutInput = z.infer<typeof gitCheckoutInputSchema>;
60export type GitInitInput = z.infer<typeof gitInitInputSchema>;
61
62export interface GitListBranchesResult {
63 branches: GitBranch[];
64 isRepo: boolean;
65}
66
67export interface GitCreateWorktreeResult {
68 worktree: GitWorktree;
69}
packages/contracts/src/index.ts+1
...@@ -6,3 +6,4 @@ export * from "./provider";...@@ -6,3 +6,4 @@ export * from "./provider";
6export * from "./model";6export * from "./model";
7export * from "./ws";7export * from "./ws";
8export * from "./project";8export * from "./project";
9export * from "./git";
packages/contracts/src/ipc.ts+18
...@@ -1,4 +1,14 @@...@@ -1,4 +1,14 @@
1import type { AgentConfig, AgentExit, OutputChunk } from "./agent";1import type { AgentConfig, AgentExit, OutputChunk } from "./agent";
2import type {
3 GitCheckoutInput,
4 GitCreateBranchInput,
5 GitCreateWorktreeInput,
6 GitCreateWorktreeResult,
7 GitInitInput,
8 GitListBranchesInput,
9 GitListBranchesResult,
10 GitRemoveWorktreeInput,
11} from "./git";
2import type {12import type {
3 ProviderEvent,13 ProviderEvent,
4 ProviderInterruptTurnInput,14 ProviderInterruptTurnInput,
...@@ -62,6 +72,14 @@ export interface NativeApi {...@@ -62,6 +72,14 @@ export interface NativeApi {
62 shell: {72 shell: {
63 openInEditor: (cwd: string, editor: EditorId) => Promise<void>;73 openInEditor: (cwd: string, editor: EditorId) => Promise<void>;
64 };74 };
75 git: {
76 listBranches: (input: GitListBranchesInput) => Promise<GitListBranchesResult>;
77 createWorktree: (input: GitCreateWorktreeInput) => Promise<GitCreateWorktreeResult>;
78 removeWorktree: (input: GitRemoveWorktreeInput) => Promise<void>;
79 createBranch: (input: GitCreateBranchInput) => Promise<void>;
80 checkout: (input: GitCheckoutInput) => Promise<void>;
81 init: (input: GitInitInput) => Promise<void>;
82 };
65 contextMenu: {83 contextMenu: {
66 show: <T extends string>(84 show: <T extends string>(
67 items: readonly { id: T; label: string }[],85 items: readonly { id: T; label: string }[],
packages/contracts/src/provider.ts+6-21
...@@ -83,12 +83,7 @@ export const providerRespondToRequestInputSchema = z.object({...@@ -83,12 +83,7 @@ export const providerRespondToRequestInputSchema = z.object({
83 decision: providerApprovalDecisionSchema,83 decision: providerApprovalDecisionSchema,
84});84});
8585
86export const providerEventKindSchema = z.enum([86export const providerEventKindSchema = z.enum(["session", "notification", "request", "error"]);
87 "session",
88 "notification",
89 "request",
90 "error",
91]);
9287
93export const providerEventSchema = z.object({88export const providerEventSchema = z.object({
94 id: z.string().min(1),89 id: z.string().min(1),
...@@ -111,24 +106,14 @@ export type ProviderKind = z.infer<typeof providerKindSchema>;...@@ -111,24 +106,14 @@ export type ProviderKind = z.infer<typeof providerKindSchema>;
111export type ProviderApprovalPolicy = z.infer<typeof providerApprovalPolicySchema>;106export type ProviderApprovalPolicy = z.infer<typeof providerApprovalPolicySchema>;
112export type ProviderSandboxMode = z.infer<typeof providerSandboxModeSchema>;107export type ProviderSandboxMode = z.infer<typeof providerSandboxModeSchema>;
113export type ProviderRequestKind = z.infer<typeof providerRequestKindSchema>;108export type ProviderRequestKind = z.infer<typeof providerRequestKindSchema>;
114export type ProviderApprovalDecision = z.infer<109export type ProviderApprovalDecision = z.infer<typeof providerApprovalDecisionSchema>;
115 typeof providerApprovalDecisionSchema
116>;
117export type ProviderSessionStatus = z.infer<typeof providerSessionStatusSchema>;110export type ProviderSessionStatus = z.infer<typeof providerSessionStatusSchema>;
118export type ProviderSession = z.infer<typeof providerSessionSchema>;111export type ProviderSession = z.infer<typeof providerSessionSchema>;
119export type ProviderSessionStartInput = z.input<typeof providerSessionStartInputSchema>;112export type ProviderSessionStartInput = z.input<typeof providerSessionStartInputSchema>;
120export type ProviderSendTurnInput = z.input<typeof providerSendTurnInputSchema>;113export type ProviderSendTurnInput = z.input<typeof providerSendTurnInputSchema>;
121export type ProviderTurnStartResult = z.infer<114export type ProviderTurnStartResult = z.infer<typeof providerTurnStartResultSchema>;
122 typeof providerTurnStartResultSchema115export type ProviderInterruptTurnInput = z.input<typeof providerInterruptTurnInputSchema>;
123>;116export type ProviderStopSessionInput = z.input<typeof providerStopSessionInputSchema>;
124export type ProviderInterruptTurnInput = z.input<117export type ProviderRespondToRequestInput = z.input<typeof providerRespondToRequestInputSchema>;
125 typeof providerInterruptTurnInputSchema
126>;
127export type ProviderStopSessionInput = z.input<
128 typeof providerStopSessionInputSchema
129>;
130export type ProviderRespondToRequestInput = z.input<
131 typeof providerRespondToRequestInputSchema
132>;
133export type ProviderEventKind = z.infer<typeof providerEventKindSchema>;118export type ProviderEventKind = z.infer<typeof providerEventKindSchema>;
134export type ProviderEvent = z.infer<typeof providerEventSchema>;119export type ProviderEvent = z.infer<typeof providerEventSchema>;
packages/contracts/src/ws.ts+8
...@@ -19,6 +19,14 @@ export const WS_METHODS = {...@@ -19,6 +19,14 @@ export const WS_METHODS = {
19 // Shell methods19 // Shell methods
20 shellOpenInEditor: "shell.openInEditor",20 shellOpenInEditor: "shell.openInEditor",
2121
22 // Git methods
23 gitListBranches: "git.listBranches",
24 gitCreateWorktree: "git.createWorktree",
25 gitRemoveWorktree: "git.removeWorktree",
26 gitCreateBranch: "git.createBranch",
27 gitCheckout: "git.checkout",
28 gitInit: "git.init",
29
22 // Server meta30 // Server meta
23 serverGetConfig: "server.getConfig",31 serverGetConfig: "server.getConfig",
24} as const;32} as const;
vitest.config.ts+11-1
...@@ -1,3 +1,13 @@...@@ -1,3 +1,13 @@
1import * as path from "node:path";
1import { defineConfig } from "vitest/config";2import { defineConfig } from "vitest/config";
23
3export default defineConfig({});4export default defineConfig({
5 resolve: {
6 alias: [
7 {
8 find: /^@t3tools\/contracts$/,
9 replacement: path.resolve(import.meta.dirname, "./packages/contracts/src/index.ts"),
10 },
11 ],
12 },
13});