authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-11 17:21:25-08:00
committergravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-02-11 17:21:25-08:00
log1768d3166965187f6d769e228783ae1250a2f6f0
tree5bd6c760711f62087103ce529f7d30c489be40a3
parent39390c0b9a8751a9a7213daafd9f1797cbca04ae
parent16b81f72689f4347753762112f76ccd5828fe2fa

Merge origin/main into codex/add-github-commit-push-ui

Co-authored-by: codex <codex@users.noreply.github.com>

53 files changed, 2194 insertions(+), 536 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
...@@ -286,6 +286,32 @@ describe("WebSocket Server", () => {...@@ -286,6 +286,32 @@ describe("WebSocket Server", () => {
286 expect(afterRemove.result).toEqual([]);286 expect(afterRemove.result).toEqual([]);
287 });287 });
288288
289 it("supports git methods over websocket", async () => {
290 const repoCwd = makeTempDir("t3code-ws-git-project-");
291
292 server = createTestServer({ cwd: "/test" });
293 await server.start();
294 const addr = server.httpServer.address();
295 const port = typeof addr === "object" && addr !== null ? addr.port : 0;
296
297 const ws = await connectWs(port);
298 connections.push(ws);
299 await waitForMessage(ws);
300
301 const beforeInit = await sendRequest(ws, WS_METHODS.gitListBranches, { cwd: repoCwd });
302 expect(beforeInit.error).toBeUndefined();
303 expect(beforeInit.result).toEqual({ branches: [], isRepo: false });
304
305 const initResponse = await sendRequest(ws, WS_METHODS.gitInit, { cwd: repoCwd });
306 expect(initResponse.error).toBeUndefined();
307
308 const afterInit = await sendRequest(ws, WS_METHODS.gitListBranches, {
309 cwd: repoCwd,
310 });
311 expect(afterInit.error).toBeUndefined();
312 expect((afterInit.result as { isRepo: boolean }).isRepo).toBe(true);
313 });
314
289 it("responds to git.status via the git manager", async () => {315 it("responds to git.status via the git manager", async () => {
290 const gitManager = {316 const gitManager = {
291 status: vi.fn().mockResolvedValue({317 status: vi.fn().mockResolvedValue({
apps/server/src/wsServer.ts+29-1
...@@ -20,6 +20,14 @@ import { createLogger } from "./logger";...@@ -20,6 +20,14 @@ import { createLogger } from "./logger";
20import { ProjectRegistry } from "./projectRegistry";20import { ProjectRegistry } from "./projectRegistry";
21import { ProviderManager } from "./providerManager";21import { ProviderManager } from "./providerManager";
22import { GitManager } from "./gitManager";22import { GitManager } from "./gitManager";
23import {
24 checkoutGitBranch,
25 createGitBranch,
26 createGitWorktree,
27 initGitRepo,
28 listGitBranches,
29 removeGitWorktree,
30} from "./git";
2331
24const MIME_TYPES: Record<string, string> = {32const MIME_TYPES: Record<string, string> = {
25 ".html": "text/html; charset=utf-8",33 ".html": "text/html; charset=utf-8",
...@@ -313,6 +321,23 @@ export function createServer(options: ServerOptions) {...@@ -313,6 +321,23 @@ export function createServer(options: ServerOptions) {
313321
314 case WS_METHODS.gitRunStackedAction:322 case WS_METHODS.gitRunStackedAction:
315 return gitManager.runStackedAction(request.params as never);323 return gitManager.runStackedAction(request.params as never);
324 case WS_METHODS.gitListBranches:
325 return listGitBranches(request.params as never);
326
327 case WS_METHODS.gitCreateWorktree:
328 return createGitWorktree(request.params as never);
329
330 case WS_METHODS.gitRemoveWorktree:
331 return removeGitWorktree(request.params as never);
332
333 case WS_METHODS.gitCreateBranch:
334 return createGitBranch(request.params as never);
335
336 case WS_METHODS.gitCheckout:
337 return checkoutGitBranch(request.params as never);
338
339 case WS_METHODS.gitInit:
340 return initGitRepo(request.params as never);
316341
317 case WS_METHODS.serverGetConfig:342 case WS_METHODS.serverGetConfig:
318 return { cwd };343 return { cwd };
...@@ -353,7 +378,10 @@ export function createServer(options: ServerOptions) {...@@ -353,7 +378,10 @@ export function createServer(options: ServerOptions) {
353 const isServerNotRunningError = (error: unknown): boolean => {378 const isServerNotRunningError = (error: unknown): boolean => {
354 if (!(error instanceof Error)) return false;379 if (!(error instanceof Error)) return false;
355 const maybeCode = (error as NodeJS.ErrnoException).code;380 const maybeCode = (error as NodeJS.ErrnoException).code;
356 return maybeCode === "ERR_SERVER_NOT_RUNNING" || error.message.toLowerCase().includes("not running");381 return (
382 maybeCode === "ERR_SERVER_NOT_RUNNING" ||
383 error.message.toLowerCase().includes("not running")
384 );
357 };385 };
358386
359 const closeWebSocketServer = new Promise<void>((resolve, reject) => {387 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+124-145
...@@ -37,6 +37,7 @@ import {...@@ -37,6 +37,7 @@ import {
37 readNativeApi,37 readNativeApi,
38} from "../session-logic";38} from "../session-logic";
39import { useStore } from "../store";39import { useStore } from "../store";
40import BranchToolbar from "./BranchToolbar";
40import ChatMarkdown from "./ChatMarkdown";41import ChatMarkdown from "./ChatMarkdown";
4142
42function formatMessageMeta(createdAt: string, duration: string | null): string {43function formatMessageMeta(createdAt: string, duration: string | null): string {
...@@ -103,23 +104,17 @@ function approvalDetail(event: ProviderEvent): string | undefined {...@@ -103,23 +104,17 @@ function approvalDetail(event: ProviderEvent): string | undefined {
103 return asString(payload?.reason);104 return asString(payload?.reason);
104}105}
105106
106function derivePendingApprovals(107function derivePendingApprovals(events: ProviderEvent[]): PendingApprovalCard[] {
107 events: ProviderEvent[],
108): PendingApprovalCard[] {
109 const pending = new Map<string, PendingApprovalCard>();108 const pending = new Map<string, PendingApprovalCard>();
110 const ordered = [...events].toReversed();109 const ordered = [...events].toReversed();
111110
112 for (const event of ordered) {111 for (const event of ordered) {
113 if (112 if (event.method === "session/closed" || event.method === "session/exited") {
114 event.method === "session/closed" ||
115 event.method === "session/exited"
116 ) {
117 pending.clear();113 pending.clear();
118 continue;114 continue;
119 }115 }
120116
121 const requestId =117 const requestId = event.requestId ?? asString(asRecord(event.payload)?.requestId);
122 event.requestId ?? asString(asRecord(event.payload)?.requestId);
123 if (!requestId) continue;118 if (!requestId) continue;
124119
125 if (120 if (
...@@ -188,19 +183,13 @@ export default function ChatView() {...@@ -188,19 +183,13 @@ export default function ChatView() {
188 const [gitActionError, setGitActionError] = useState<string | null>(null);183 const [gitActionError, setGitActionError] = useState<string | null>(null);
189 const [lastEditor, setLastEditor] = useState<EditorId>(() => {184 const [lastEditor, setLastEditor] = useState<EditorId>(() => {
190 const stored = localStorage.getItem(LAST_EDITOR_KEY);185 const stored = localStorage.getItem(LAST_EDITOR_KEY);
191 return EDITORS.some((e) => e.id === stored)186 return EDITORS.some((e) => e.id === stored) ? (stored as EditorId) : EDITORS[0].id;
192 ? (stored as EditorId)
193 : EDITORS[0].id;
194 });187 });
195 const [selectedEffort, setSelectedEffort] =188 const [selectedEffort, setSelectedEffort] = useState<string>(DEFAULT_REASONING);
196 useState<string>(DEFAULT_REASONING);189 const [envMode, setEnvMode] = useState<"local" | "worktree">("local");
197 const [isSwitchingRuntimeMode, setIsSwitchingRuntimeMode] = useState(false);190 const [isSwitchingRuntimeMode, setIsSwitchingRuntimeMode] = useState(false);
198 const [respondingRequestIds, setRespondingRequestIds] = useState<string[]>(191 const [respondingRequestIds, setRespondingRequestIds] = useState<string[]>([]);
199 [],192 const [expandedWorkGroups, setExpandedWorkGroups] = useState<Record<string, boolean>>({});
200 );
201 const [expandedWorkGroups, setExpandedWorkGroups] = useState<
202 Record<string, boolean>
203 >({});
204 const [nowTick, setNowTick] = useState(() => Date.now());193 const [nowTick, setNowTick] = useState(() => Date.now());
205 const messagesEndRef = useRef<HTMLDivElement>(null);194 const messagesEndRef = useRef<HTMLDivElement>(null);
206 const textareaRef = useRef<HTMLTextAreaElement>(null);195 const textareaRef = useRef<HTMLTextAreaElement>(null);
...@@ -222,11 +211,7 @@ export default function ChatView() {...@@ -222,11 +211,7 @@ export default function ChatView() {
222 [activeThread?.events],211 [activeThread?.events],
223 );212 );
224 const latestTurnWorkEntries = useMemo(213 const latestTurnWorkEntries = useMemo(
225 () =>214 () => deriveWorkLogEntries(activeThread?.events ?? [], activeThread?.latestTurnId),
226 deriveWorkLogEntries(
227 activeThread?.events ?? [],
228 activeThread?.latestTurnId,
229 ),
230 [activeThread?.events, activeThread?.latestTurnId],215 [activeThread?.events, activeThread?.latestTurnId],
231 );216 );
232 const pendingApprovals = useMemo(217 const pendingApprovals = useMemo(
...@@ -312,23 +297,24 @@ export default function ChatView() {...@@ -312,23 +297,24 @@ export default function ChatView() {
312 approvalPolicy: "on-request",297 approvalPolicy: "on-request",
313 sandboxMode: "workspace-write",298 sandboxMode: "workspace-write",
314 } as const);299 } as const);
300 const gitCwd = activeThread?.worktreePath ?? activeProject?.cwd ?? null;
315 const gitActionsDisabled =301 const gitActionsDisabled =
316 !api || !activeProject || !gitStatus || isGitActionRunning;302 !api || !gitCwd || !gitStatus || isGitActionRunning;
317 const pushActionDisabled = gitActionsDisabled || gitStatus.branch === null;303 const pushActionDisabled = gitActionsDisabled || gitStatus.branch === null;
318304
319 const refreshGitStatus = useCallback(async () => {305 const refreshGitStatus = useCallback(async () => {
320 if (!api || !activeProject) {306 if (!api || !gitCwd) {
321 setGitStatus(null);307 setGitStatus(null);
322 return;308 return;
323 }309 }
324310
325 const nextStatus = await api.git.status({ cwd: activeProject.cwd });311 const nextStatus = await api.git.status({ cwd: gitCwd });
326 setGitStatus(nextStatus);312 setGitStatus(nextStatus);
327 }, [api, activeProject]);313 }, [api, gitCwd]);
328314
329 const runGitAction = useCallback(315 const runGitAction = useCallback(
330 async (action: GitStackedAction) => {316 async (action: GitStackedAction) => {
331 if (!api || !activeProject) return;317 if (!api || !gitCwd) return;
332318
333 setIsGitMenuOpen(false);319 setIsGitMenuOpen(false);
334 setIsGitActionRunning(true);320 setIsGitActionRunning(true);
...@@ -336,7 +322,7 @@ export default function ChatView() {...@@ -336,7 +322,7 @@ export default function ChatView() {
336 setGitActionNotice(null);322 setGitActionNotice(null);
337 try {323 try {
338 const result = await api.git.runStackedAction({324 const result = await api.git.runStackedAction({
339 cwd: activeProject.cwd,325 cwd: gitCwd,
340 action,326 action,
341 });327 });
342 setGitActionNotice(summarizeGitActionResult(result));328 setGitActionNotice(summarizeGitActionResult(result));
...@@ -353,21 +339,23 @@ export default function ChatView() {...@@ -353,21 +339,23 @@ export default function ChatView() {
353 }339 }
354 }340 }
355 },341 },
356 [api, activeProject, refreshGitStatus],342 [api, gitCwd, refreshGitStatus],
343 );
344
345 const envLocked = Boolean(
346 activeThread &&
347 (activeThread.messages.length > 0 ||
348 (activeThread.session !== null && activeThread.session.status !== "closed")),
357 );349 );
358350
359 const handleRuntimeModeChange = async (351 const handleRuntimeModeChange = async (mode: "approval-required" | "full-access") => {
360 mode: "approval-required" | "full-access",
361 ) => {
362 if (mode === state.runtimeMode) return;352 if (mode === state.runtimeMode) return;
363 dispatch({ type: "SET_RUNTIME_MODE", mode });353 dispatch({ type: "SET_RUNTIME_MODE", mode });
364 if (!api) return;354 if (!api) return;
365355
366 const sessionIds = state.threads356 const sessionIds = state.threads
367 .map((t) => t.session)357 .map((t) => t.session)
368 .filter(358 .filter((s): s is NonNullable<typeof s> => s !== null && s.status !== "closed")
369 (s): s is NonNullable<typeof s> => s !== null && s.status !== "closed",
370 )
371 .map((s) => s.sessionId);359 .map((s) => s.sessionId);
372360
373 if (sessionIds.length === 0) return;361 if (sessionIds.length === 0) return;
...@@ -375,9 +363,7 @@ export default function ChatView() {...@@ -375,9 +363,7 @@ export default function ChatView() {
375 setIsSwitchingRuntimeMode(true);363 setIsSwitchingRuntimeMode(true);
376 try {364 try {
377 await Promise.all(365 await Promise.all(
378 sessionIds.map((id) =>366 sessionIds.map((id) => api.providers.stopSession({ sessionId: id }).catch(() => undefined)),
379 api.providers.stopSession({ sessionId: id }).catch(() => undefined),
380 ),
381 );367 );
382 } finally {368 } finally {
383 setIsSwitchingRuntimeMode(false);369 setIsSwitchingRuntimeMode(false);
...@@ -399,21 +385,23 @@ export default function ChatView() {...@@ -399,21 +385,23 @@ export default function ChatView() {
399 setExpandedWorkGroups({});385 setExpandedWorkGroups({});
400 }, [activeThread?.id]);386 }, [activeThread?.id]);
401387
388 const activeWorktreePath = activeThread?.worktreePath;
389
402 useEffect(() => {390 useEffect(() => {
403 setGitActionNotice(null);391 setGitActionNotice(null);
404 setGitActionError(null);392 setGitActionError(null);
405 }, [activeProject?.id]);393 }, [activeProject?.id, activeWorktreePath]);
406394
407 useEffect(() => {395 useEffect(() => {
408 let cancelled = false;396 let cancelled = false;
409 if (!api || !activeProject) {397 if (!api || !gitCwd) {
410 setGitStatus(null);398 setGitStatus(null);
411 return;399 return;
412 }400 }
413401
414 const load = async () => {402 const load = async () => {
415 try {403 try {
416 const nextStatus = await api.git.status({ cwd: activeProject.cwd });404 const nextStatus = await api.git.status({ cwd: gitCwd });
417 if (!cancelled) {405 if (!cancelled) {
418 setGitStatus(nextStatus);406 setGitStatus(nextStatus);
419 }407 }
...@@ -433,7 +421,12 @@ export default function ChatView() {...@@ -433,7 +421,12 @@ export default function ChatView() {
433 return () => {421 return () => {
434 cancelled = true;422 cancelled = true;
435 };423 };
436 }, [api, activeProject]);424 }, [api, gitCwd]);
425
426 useEffect(() => {
427 if (!activeThread?.id) return;
428 setEnvMode(activeWorktreePath ? "worktree" : "local");
429 }, [activeThread?.id, activeWorktreePath]);
437430
438 // Auto-resize textarea431 // Auto-resize textarea
439 useEffect(() => {432 useEffect(() => {
...@@ -474,10 +467,7 @@ export default function ChatView() {...@@ -474,10 +467,7 @@ export default function ChatView() {
474467
475 const handleClickOutside = (event: MouseEvent) => {468 const handleClickOutside = (event: MouseEvent) => {
476 if (!editorMenuRef.current) return;469 if (!editorMenuRef.current) return;
477 if (470 if (event.target instanceof Node && !editorMenuRef.current.contains(event.target)) {
478 event.target instanceof Node &&
479 !editorMenuRef.current.contains(event.target)
480 ) {
481 setIsEditorMenuOpen(false);471 setIsEditorMenuOpen(false);
482 }472 }
483 };473 };
...@@ -510,23 +500,25 @@ export default function ChatView() {...@@ -510,23 +500,25 @@ export default function ChatView() {
510 if (e.key === "o" && (e.metaKey || e.ctrlKey) && !e.shiftKey) {500 if (e.key === "o" && (e.metaKey || e.ctrlKey) && !e.shiftKey) {
511 if (api && activeProject) {501 if (api && activeProject) {
512 e.preventDefault();502 e.preventDefault();
513 void api.shell.openInEditor(activeProject.cwd, lastEditor);503 const cwd = activeThread?.worktreePath ?? activeProject.cwd;
504 void api.shell.openInEditor(cwd, lastEditor);
514 }505 }
515 }506 }
516 };507 };
517 window.addEventListener("keydown", handler);508 window.addEventListener("keydown", handler);
518 return () => window.removeEventListener("keydown", handler);509 return () => window.removeEventListener("keydown", handler);
519 }, [api, activeProject, lastEditor]);510 }, [api, activeProject, activeThread, lastEditor]);
520511
521 const openInEditor = (editorId: EditorId) => {512 const openInEditor = (editorId: EditorId) => {
522 if (!api || !activeProject) return;513 if (!api || !activeProject) return;
523 void api.shell.openInEditor(activeProject.cwd, editorId);514 const cwd = activeThread?.worktreePath ?? activeProject.cwd;
515 void api.shell.openInEditor(cwd, editorId);
524 setLastEditor(editorId);516 setLastEditor(editorId);
525 localStorage.setItem(LAST_EDITOR_KEY, editorId);517 localStorage.setItem(LAST_EDITOR_KEY, editorId);
526 setIsEditorMenuOpen(false);518 setIsEditorMenuOpen(false);
527 };519 };
528520
529 const ensureSession = async (): Promise<EnsuredSessionInfo | null> => {521 const ensureSession = async (cwdOverride?: string): Promise<EnsuredSessionInfo | null> => {
530 if (!api || !activeThread || !activeProject) return null;522 if (!api || !activeThread || !activeProject) return null;
531 if (activeThread.session && activeThread.session.status !== "closed") {523 if (activeThread.session && activeThread.session.status !== "closed") {
532 const sessionThreadId = activeThread.session.threadId ?? null;524 const sessionThreadId = activeThread.session.threadId ?? null;
...@@ -548,7 +540,7 @@ export default function ChatView() {...@@ -548,7 +540,7 @@ export default function ChatView() {
548 try {540 try {
549 const session = await api.providers.startSession({541 const session = await api.providers.startSession({
550 provider: "codex",542 provider: "codex",
551 cwd: activeProject.cwd || undefined,543 cwd: cwdOverride ?? activeThread.worktreePath ?? activeProject.cwd,
552 model: selectedModel || undefined,544 model: selectedModel || undefined,
553 resumeThreadId: priorCodexThreadId ?? undefined,545 resumeThreadId: priorCodexThreadId ?? undefined,
554 approvalPolicy: runtimeSessionConfig.approvalPolicy,546 approvalPolicy: runtimeSessionConfig.approvalPolicy,
...@@ -588,6 +580,39 @@ export default function ChatView() {...@@ -588,6 +580,39 @@ export default function ChatView() {
588 if (!api || !activeThread || isSending || isConnecting) return;580 if (!api || !activeThread || isSending || isConnecting) return;
589 const trimmed = prompt.trim();581 const trimmed = prompt.trim();
590 if (!trimmed) return;582 if (!trimmed) return;
583 if (!activeProject) return;
584
585 // On first message: lock in branch + create worktree if needed.
586 let sessionCwd: string | undefined;
587 if (
588 activeThread.messages.length === 0 &&
589 activeThread.branch &&
590 envMode === "worktree" &&
591 !activeThread.worktreePath
592 ) {
593 try {
594 const newBranch = `codething/${crypto.randomUUID().slice(0, 8)}`;
595 const result = await api.git.createWorktree({
596 cwd: activeProject.cwd,
597 branch: activeThread.branch,
598 newBranch,
599 });
600 sessionCwd = result.worktree.path;
601 dispatch({
602 type: "SET_THREAD_BRANCH",
603 threadId: activeThread.id,
604 branch: result.worktree.branch,
605 worktreePath: result.worktree.path,
606 });
607 } catch (err) {
608 dispatch({
609 type: "SET_ERROR",
610 threadId: activeThread.id,
611 error: err instanceof Error ? err.message : "Failed to create worktree",
612 });
613 return;
614 }
615 }
591616
592 // Auto-title from first message617 // Auto-title from first message
593 if (activeThread.messages.length === 0) {618 if (activeThread.messages.length === 0) {
...@@ -613,21 +638,16 @@ export default function ChatView() {...@@ -613,21 +638,16 @@ export default function ChatView() {
613 const previousMessages = activeThread.messages;638 const previousMessages = activeThread.messages;
614 setPrompt("");639 setPrompt("");
615640
616 const sessionInfo = await ensureSession();641 const sessionInfo = await ensureSession(sessionCwd);
617 if (!sessionInfo) return;642 if (!sessionInfo) return;
618643
619 setIsSending(true);644 setIsSending(true);
620 try {645 try {
621 const shouldBootstrap =646 const shouldBootstrap =
622 previousMessages.length > 0 &&647 previousMessages.length > 0 &&
623 (sessionInfo.continuityState === "new" ||648 (sessionInfo.continuityState === "new" || sessionInfo.continuityState === "fallback_new");
624 sessionInfo.continuityState === "fallback_new");
625 const input = shouldBootstrap649 const input = shouldBootstrap
626 ? buildBootstrapInput(650 ? buildBootstrapInput(previousMessages, trimmed, PROVIDER_SEND_TURN_MAX_INPUT_CHARS).text
627 previousMessages,
628 trimmed,
629 PROVIDER_SEND_TURN_MAX_INPUT_CHARS,
630 ).text
631 : trimmed;651 : trimmed;
632 await api.providers.sendTurn({652 await api.providers.sendTurn({
633 sessionId: sessionInfo.sessionId,653 sessionId: sessionInfo.sessionId,
...@@ -654,10 +674,7 @@ export default function ChatView() {...@@ -654,10 +674,7 @@ export default function ChatView() {
654 });674 });
655 };675 };
656676
657 const onRespondToApproval = async (677 const onRespondToApproval = async (requestId: string, decision: ProviderApprovalDecision) => {
658 requestId: string,
659 decision: ProviderApprovalDecision,
660 ) => {
661 if (!api || !activeThread?.session) return;678 if (!api || !activeThread?.session) return;
662679
663 setRespondingRequestIds((existing) =>680 setRespondingRequestIds((existing) =>
...@@ -673,15 +690,10 @@ export default function ChatView() {...@@ -673,15 +690,10 @@ export default function ChatView() {
673 dispatch({690 dispatch({
674 type: "SET_ERROR",691 type: "SET_ERROR",
675 threadId: activeThread.id,692 threadId: activeThread.id,
676 error:693 error: err instanceof Error ? err.message : "Failed to submit approval decision.",
677 err instanceof Error
678 ? err.message
679 : "Failed to submit approval decision.",
680 });694 });
681 } finally {695 } finally {
682 setRespondingRequestIds((existing) =>696 setRespondingRequestIds((existing) => existing.filter((id) => id !== requestId));
683 existing.filter((id) => id !== requestId),
684 );
685 }697 }
686 };698 };
687699
...@@ -719,11 +731,22 @@ export default function ChatView() {...@@ -719,11 +731,22 @@ export default function ChatView() {
719 return (731 return (
720 <div className="flex flex-1 flex-col bg-background">732 <div className="flex flex-1 flex-col bg-background">
721 {/* Top bar */}733 {/* Top bar */}
722 <header className={`flex items-center justify-between border-b border-border px-5 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}>734 <header
735 className={`flex items-center justify-between border-b border-border px-5 pb-3 ${isElectron ? "drag-region pt-[28px]" : "pt-3"}`}
736 >
723 <div className="flex items-center gap-3">737 <div className="flex items-center gap-3">
724 <h2 className="text-sm font-medium text-foreground">738 <h2 className="text-sm font-medium text-foreground">{activeThread.title}</h2>
725 {activeThread.title}739 {activeProject && (
726 </h2>740 <span className="rounded-full bg-accent px-2 py-0.5 text-[10px] text-muted-foreground/50">
741 {activeProject.name}
742 </span>
743 )}
744 {activeThread.branch && (
745 <span className="rounded-full bg-accent px-2 py-0.5 font-mono text-[10px] text-muted-foreground/50">
746 {activeThread.branch}
747 {activeThread.worktreePath ? " (worktree)" : ""}
748 </span>
749 )}
727 </div>750 </div>
728 <div className="flex items-center gap-3">751 <div className="flex items-center gap-3">
729 {/* Open in editor */}752 {/* Open in editor */}
...@@ -748,9 +771,7 @@ export default function ChatView() {...@@ -748,9 +771,7 @@ export default function ChatView() {
748 {editorLabel(editor)}771 {editorLabel(editor)}
749 {editor.id === lastEditor && (772 {editor.id === lastEditor && (
750 <kbd className="ml-auto text-[9px] text-muted-foreground/40">773 <kbd className="ml-auto text-[9px] text-muted-foreground/40">
751 {navigator.platform.includes("Mac")774 {navigator.platform.includes("Mac") ? "\u2318O" : "Ctrl+O"}
752 ? "\u2318O"
753 : "Ctrl+O"}
754 </kbd>775 </kbd>
755 )}776 )}
756 </button>777 </button>
...@@ -819,7 +840,7 @@ export default function ChatView() {...@@ -819,7 +840,7 @@ export default function ChatView() {
819840
820 {/* Error banner */}841 {/* Error banner */}
821 {activeThread.error && (842 {activeThread.error && (
822 <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">843 <div className="mx-4 mt-3 rounded-lg border border-destructive/20 bg-destructive/10 px-3 py-2 text-xs text-destructive">
823 {activeThread.error}844 {activeThread.error}
824 </div>845 </div>
825 )}846 )}
...@@ -839,9 +860,7 @@ export default function ChatView() {...@@ -839,9 +860,7 @@ export default function ChatView() {
839 {pendingApprovals.length > 0 && (860 {pendingApprovals.length > 0 && (
840 <div className="mx-4 mt-3 space-y-2">861 <div className="mx-4 mt-3 space-y-2">
841 {pendingApprovals.map((approval) => {862 {pendingApprovals.map((approval) => {
842 const isResponding = respondingRequestIds.includes(863 const isResponding = respondingRequestIds.includes(approval.requestId);
843 approval.requestId,
844 );
845 return (864 return (
846 <div865 <div
847 key={approval.requestId}866 key={approval.requestId}
...@@ -865,9 +884,7 @@ export default function ChatView() {...@@ -865,9 +884,7 @@ export default function ChatView() {
865 type="button"884 type="button"
866 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"885 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"
867 disabled={isResponding}886 disabled={isResponding}
868 onClick={() =>887 onClick={() => void onRespondToApproval(approval.requestId, "accept")}
869 void onRespondToApproval(approval.requestId, "accept")
870 }
871 >888 >
872 Approve once889 Approve once
873 </button>890 </button>
...@@ -875,12 +892,7 @@ export default function ChatView() {...@@ -875,12 +892,7 @@ export default function ChatView() {
875 type="button"892 type="button"
876 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"893 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"
877 disabled={isResponding}894 disabled={isResponding}
878 onClick={() =>895 onClick={() => void onRespondToApproval(approval.requestId, "acceptForSession")}
879 void onRespondToApproval(
880 approval.requestId,
881 "acceptForSession",
882 )
883 }
884 >896 >
885 Always allow this session897 Always allow this session
886 </button>898 </button>
...@@ -888,9 +900,7 @@ export default function ChatView() {...@@ -888,9 +900,7 @@ export default function ChatView() {
888 type="button"900 type="button"
889 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"901 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"
890 disabled={isResponding}902 disabled={isResponding}
891 onClick={() =>903 onClick={() => void onRespondToApproval(approval.requestId, "decline")}
892 void onRespondToApproval(approval.requestId, "decline")
893 }
894 >904 >
895 Decline905 Decline
896 </button>906 </button>
...@@ -898,9 +908,7 @@ export default function ChatView() {...@@ -898,9 +908,7 @@ export default function ChatView() {
898 type="button"908 type="button"
899 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"909 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"
900 disabled={isResponding}910 disabled={isResponding}
901 onClick={() =>911 onClick={() => void onRespondToApproval(approval.requestId, "cancel")}
902 void onRespondToApproval(approval.requestId, "cancel")
903 }
904 >912 >
905 Cancel turn913 Cancel turn
906 </button>914 </button>
...@@ -915,15 +923,14 @@ export default function ChatView() {...@@ -915,15 +923,14 @@ export default function ChatView() {
915 <div className="flex-1 overflow-y-auto px-5 py-4">923 <div className="flex-1 overflow-y-auto px-5 py-4">
916 {activeThread.messages.length === 0 && !isWorking ? (924 {activeThread.messages.length === 0 && !isWorking ? (
917 <div className="flex h-full items-center justify-center">925 <div className="flex h-full items-center justify-center">
918 <p className="text-sm text-muted-foreground/30">Send a message to start the conversation.</p>926 <p className="text-sm text-muted-foreground/30">
927 Send a message to start the conversation.
928 </p>
919 </div>929 </div>
920 ) : (930 ) : (
921 <div className="mx-auto max-w-3xl space-y-4">931 <div className="mx-auto max-w-3xl space-y-4">
922 {timelineEntries.map((timelineEntry, index) => {932 {timelineEntries.map((timelineEntry, index) => {
923 if (933 if (timelineEntry.kind === "work" && timelineEntries[index - 1]?.kind === "work") {
924 timelineEntry.kind === "work" &&
925 timelineEntries[index - 1]?.kind === "work"
926 ) {
927 return null;934 return null;
928 }935 }
929936
...@@ -944,16 +951,13 @@ export default function ChatView() {...@@ -944,16 +951,13 @@ export default function ChatView() {
944951
945 const groupId = timelineEntry.id;952 const groupId = timelineEntry.id;
946 const isExpanded = expandedWorkGroups[groupId] ?? false;953 const isExpanded = expandedWorkGroups[groupId] ?? false;
947 const hasOverflow =954 const hasOverflow = groupedEntries.length > MAX_VISIBLE_WORK_LOG_ENTRIES;
948 groupedEntries.length > MAX_VISIBLE_WORK_LOG_ENTRIES;
949 const visibleEntries =955 const visibleEntries =
950 hasOverflow && !isExpanded956 hasOverflow && !isExpanded
951 ? groupedEntries.slice(-MAX_VISIBLE_WORK_LOG_ENTRIES)957 ? groupedEntries.slice(-MAX_VISIBLE_WORK_LOG_ENTRIES)
952 : groupedEntries;958 : groupedEntries;
953 const hiddenCount = groupedEntries.length - visibleEntries.length;959 const hiddenCount = groupedEntries.length - visibleEntries.length;
954 const onlyToolEntries = groupedEntries.every(960 const onlyToolEntries = groupedEntries.every((entry) => entry.tone === "tool");
955 (entry) => entry.tone === "tool",
956 );
957 const groupLabel = onlyToolEntries961 const groupLabel = onlyToolEntries
958 ? groupedEntries.length === 1962 ? groupedEntries.length === 1
959 ? "Tool call"963 ? "Tool call"
...@@ -1039,9 +1043,7 @@ export default function ChatView() {...@@ -1039,9 +1043,7 @@ export default function ChatView() {
1039 <div className="my-3 flex items-center gap-3">1043 <div className="my-3 flex items-center gap-3">
1040 <span className="h-px flex-1 bg-border" />1044 <span className="h-px flex-1 bg-border" />
1041 <span className="rounded-full border border-border bg-background px-2.5 py-1 text-[10px] uppercase tracking-[0.14em] text-muted-foreground/80">1045 <span className="rounded-full border border-border bg-background px-2.5 py-1 text-[10px] uppercase tracking-[0.14em] text-muted-foreground/80">
1042 {completionSummary1046 {completionSummary ? `Response • ${completionSummary}` : "Response"}
1043 ? `Response • ${completionSummary}`
1044 : "Response"}
1045 </span>1047 </span>
1046 <span className="h-px flex-1 bg-border" />1048 <span className="h-px flex-1 bg-border" />
1047 </div>1049 </div>
...@@ -1050,24 +1052,17 @@ export default function ChatView() {...@@ -1050,24 +1052,17 @@ export default function ChatView() {
1050 <ChatMarkdown1052 <ChatMarkdown
1051 text={1053 text={
1052 timelineEntry.message.text ||1054 timelineEntry.message.text ||
1053 (timelineEntry.message.streaming1055 (timelineEntry.message.streaming ? "" : "(empty response)")
1054 ? ""
1055 : "(empty response)")
1056 }1056 }
1057 />1057 />
1058 <p className="mt-1.5 text-[10px] text-muted-foreground/30">1058 <p className="mt-1.5 text-[10px] text-muted-foreground/30">
1059 {formatMessageMeta(1059 {formatMessageMeta(
1060 timelineEntry.message.createdAt,1060 timelineEntry.message.createdAt,
1061 timelineEntry.message.streaming1061 timelineEntry.message.streaming
1062 ? formatElapsed(1062 ? formatElapsed(timelineEntry.message.createdAt, nowIso)
1063 timelineEntry.message.createdAt,
1064 nowIso,
1065 )
1066 : formatElapsed(1063 : formatElapsed(
1067 timelineEntry.message.createdAt,1064 timelineEntry.message.createdAt,
1068 assistantCompletionByItemId.get(1065 assistantCompletionByItemId.get(timelineEntry.message.id),
1069 timelineEntry.message.id,
1070 ),
1071 ),1066 ),
1072 )}1067 )}
1073 </p>1068 </p>
...@@ -1093,7 +1088,7 @@ export default function ChatView() {...@@ -1093,7 +1088,7 @@ export default function ChatView() {
1093 </div>1088 </div>
10941089
1095 {/* Input bar */}1090 {/* Input bar */}
1096 <div className="px-5 pb-4 pt-2">1091 <div className="px-5 pb-1 pt-2">
1097 <form onSubmit={onSend} className="mx-auto max-w-3xl">1092 <form onSubmit={onSend} className="mx-auto max-w-3xl">
1098 <div className="group rounded-[20px] border border-border bg-card transition-colors duration-200 focus-within:border-ring">1093 <div className="group rounded-[20px] border border-border bg-card transition-colors duration-200 focus-within:border-ring">
1099 {/* Textarea area */}1094 {/* Textarea area */}
...@@ -1223,9 +1218,7 @@ export default function ChatView() {...@@ -1223,9 +1218,7 @@ export default function ChatView() {
1223 disabled={isSwitchingRuntimeMode}1218 disabled={isSwitchingRuntimeMode}
1224 onClick={() =>1219 onClick={() =>
1225 void handleRuntimeModeChange(1220 void handleRuntimeModeChange(
1226 state.runtimeMode === "full-access"1221 state.runtimeMode === "full-access" ? "approval-required" : "full-access",
1227 ? "approval-required"
1228 : "full-access",
1229 )1222 )
1230 }1223 }
1231 title={1224 title={
...@@ -1235,13 +1228,7 @@ export default function ChatView() {...@@ -1235,13 +1228,7 @@ export default function ChatView() {
1235 }1228 }
1236 >1229 >
1237 {state.runtimeMode === "full-access" ? (1230 {state.runtimeMode === "full-access" ? (
1238 <svg1231 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
1239 width="14"
1240 height="14"
1241 viewBox="0 0 14 14"
1242 fill="none"
1243 aria-hidden="true"
1244 >
1245 <rect1232 <rect
1246 x="2"1233 x="2"
1247 y="5.5"1234 y="5.5"
...@@ -1259,13 +1246,7 @@ export default function ChatView() {...@@ -1259,13 +1246,7 @@ export default function ChatView() {
1259 />1246 />
1260 </svg>1247 </svg>
1261 ) : (1248 ) : (
1262 <svg1249 <svg width="14" height="14" viewBox="0 0 14 14" fill="none" aria-hidden="true">
1263 width="14"
1264 height="14"
1265 viewBox="0 0 14 14"
1266 fill="none"
1267 aria-hidden="true"
1268 >
1269 <rect1250 <rect
1270 x="2"1251 x="2"
1271 y="5.5"1252 y="5.5"
...@@ -1283,11 +1264,7 @@ export default function ChatView() {...@@ -1283,11 +1264,7 @@ export default function ChatView() {
1283 />1264 />
1284 </svg>1265 </svg>
1285 )}1266 )}
1286 <span>1267 <span>{state.runtimeMode === "full-access" ? "Full access" : "Supervised"}</span>
1287 {state.runtimeMode === "full-access"
1288 ? "Full access"
1289 : "Supervised"}
1290 </span>
1291 </button>1268 </button>
1292 </div>1269 </div>
12931270
...@@ -1362,6 +1339,8 @@ export default function ChatView() {...@@ -1362,6 +1339,8 @@ export default function ChatView() {
1362 </div>1339 </div>
1363 </form>1340 </form>
1364 </div>1341 </div>
1342
1343 <BranchToolbar envMode={envMode} onEnvModeChange={setEnvMode} envLocked={envLocked} />
1365 </div>1344 </div>
1366 );1345 );
1367}1346}
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+6
...@@ -99,6 +99,12 @@ export function createWsNativeApi(): NativeApi {...@@ -99,6 +99,12 @@ export function createWsNativeApi(): NativeApi {
99 git: {99 git: {
100 status: (input) => transport.request(WS_METHODS.gitStatus, input),100 status: (input) => transport.request(WS_METHODS.gitStatus, input),
101 runStackedAction: (input) => transport.request(WS_METHODS.gitRunStackedAction, input),101 runStackedAction: (input) => transport.request(WS_METHODS.gitRunStackedAction, input),
102 listBranches: (input) => transport.request(WS_METHODS.gitListBranches, input),
103 createWorktree: (input) => transport.request(WS_METHODS.gitCreateWorktree, input),
104 removeWorktree: (input) => transport.request(WS_METHODS.gitRemoveWorktree, input),
105 createBranch: (input) => transport.request(WS_METHODS.gitCreateBranch, input),
106 checkout: (input) => transport.request(WS_METHODS.gitCheckout, input),
107 init: (input) => transport.request(WS_METHODS.gitInit, input),
102 },108 },
103 contextMenu: {109 contextMenu: {
104 show: async <T extends string>(110 show: async <T extends 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+64
...@@ -1,5 +1,69 @@...@@ -1,5 +1,69 @@
1import { z } from "zod";1import { z } from "zod";
22
3// ── Existing branch/worktree Git API ─────────────────────────────────
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 branch: z.string().min(1),
12 newBranch: z.string().min(1),
13 path: z.string().min(1).optional(),
14});
15
16export const gitRemoveWorktreeInputSchema = z.object({
17 cwd: z.string().min(1),
18 path: z.string().min(1),
19});
20
21export const gitCreateBranchInputSchema = z.object({
22 cwd: z.string().min(1),
23 branch: z.string().min(1),
24});
25
26export const gitCheckoutInputSchema = z.object({
27 cwd: z.string().min(1),
28 branch: z.string().min(1),
29});
30
31export const gitInitInputSchema = z.object({
32 cwd: z.string().min(1),
33});
34
35export const gitBranchSchema = z.object({
36 name: z.string().min(1),
37 current: z.boolean(),
38 isDefault: z.boolean(),
39 worktreePath: z.string().min(1).nullable(),
40});
41
42export const gitWorktreeSchema = z.object({
43 path: z.string().min(1),
44 branch: z.string().min(1),
45});
46
47export type GitListBranchesInput = z.infer<typeof gitListBranchesInputSchema>;
48export type GitBranch = z.infer<typeof gitBranchSchema>;
49export type GitCreateWorktreeInput = z.infer<typeof gitCreateWorktreeInputSchema>;
50export type GitWorktree = z.infer<typeof gitWorktreeSchema>;
51export type GitRemoveWorktreeInput = z.infer<typeof gitRemoveWorktreeInputSchema>;
52export type GitCreateBranchInput = z.infer<typeof gitCreateBranchInputSchema>;
53export type GitCheckoutInput = z.infer<typeof gitCheckoutInputSchema>;
54export type GitInitInput = z.infer<typeof gitInitInputSchema>;
55
56export interface GitListBranchesResult {
57 branches: GitBranch[];
58 isRepo: boolean;
59}
60
61export interface GitCreateWorktreeResult {
62 worktree: GitWorktree;
63}
64
65// ── Stacked action Git API ───────────────────────────────────────────
66
3export const gitStatusInputSchema = z.object({67export const gitStatusInputSchema = z.object({
4 cwd: z.string().trim().min(1),68 cwd: z.string().trim().min(1),
5});69});
packages/contracts/src/ipc.ts+17
...@@ -1,5 +1,13 @@...@@ -1,5 +1,13 @@
1import type { AgentConfig, AgentExit, OutputChunk } from "./agent";1import type { AgentConfig, AgentExit, OutputChunk } from "./agent";
2import type {2import type {
3 GitCheckoutInput,
4 GitCreateBranchInput,
5 GitCreateWorktreeInput,
6 GitCreateWorktreeResult,
7 GitInitInput,
8 GitListBranchesInput,
9 GitListBranchesResult,
10 GitRemoveWorktreeInput,
3 GitRunStackedActionInput,11 GitRunStackedActionInput,
4 GitRunStackedActionResult,12 GitRunStackedActionResult,
5 GitStatusInput,13 GitStatusInput,
...@@ -69,6 +77,14 @@ export interface NativeApi {...@@ -69,6 +77,14 @@ export interface NativeApi {
69 openInEditor: (cwd: string, editor: EditorId) => Promise<void>;77 openInEditor: (cwd: string, editor: EditorId) => Promise<void>;
70 };78 };
71 git: {79 git: {
80 // Existing branch/worktree API
81 listBranches: (input: GitListBranchesInput) => Promise<GitListBranchesResult>;
82 createWorktree: (input: GitCreateWorktreeInput) => Promise<GitCreateWorktreeResult>;
83 removeWorktree: (input: GitRemoveWorktreeInput) => Promise<void>;
84 createBranch: (input: GitCreateBranchInput) => Promise<void>;
85 checkout: (input: GitCheckoutInput) => Promise<void>;
86 init: (input: GitInitInput) => Promise<void>;
87 // Stacked action API
72 status: (input: GitStatusInput) => Promise<GitStatusResult>;88 status: (input: GitStatusInput) => Promise<GitStatusResult>;
73 runStackedAction: (89 runStackedAction: (
74 input: GitRunStackedActionInput,90 input: GitRunStackedActionInput,
...@@ -81,3 +97,4 @@ export interface NativeApi {...@@ -81,3 +97,4 @@ export interface NativeApi {
81 ) => Promise<T | null>;97 ) => Promise<T | null>;
82 };98 };
83}99}
100
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+6
...@@ -22,6 +22,12 @@ export const WS_METHODS = {...@@ -22,6 +22,12 @@ export const WS_METHODS = {
22 // Git methods22 // Git methods
23 gitStatus: "git.status",23 gitStatus: "git.status",
24 gitRunStackedAction: "git.runStackedAction",24 gitRunStackedAction: "git.runStackedAction",
25 gitListBranches: "git.listBranches",
26 gitCreateWorktree: "git.createWorktree",
27 gitRemoveWorktree: "git.removeWorktree",
28 gitCreateBranch: "git.createBranch",
29 gitCheckout: "git.checkout",
30 gitInit: "git.init",
2531
26 // Server meta32 // Server meta
27 serverGetConfig: "server.getConfig",33 serverGetConfig: "server.getConfig",
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});