From e7a91c7d4fc6010f40c549503661e7e95320348a Mon Sep 17 00:00:00 2001 From: Lifei Zhou Date: Fri, 17 Apr 2026 02:46:37 +1000 Subject: [PATCH] Lifei/delete tauri backend acp (#8582) Co-authored-by: Jack Amadeo --- .github/workflows/goose2-ci.yml | 18 +- ui/goose2/AGENTS.md | 5 +- ui/goose2/justfile | 3 +- ui/goose2/package.json | 4 +- ui/goose2/pnpm-lock.yaml | 7615 ----------------- ui/goose2/scripts/check-file-sizes.mjs | 29 +- ui/goose2/src-tauri/Cargo.lock | 180 +- ui/goose2/src-tauri/Cargo.toml | 6 - ui/goose2/src-tauri/src/commands/acp.rs | 331 +- ui/goose2/src-tauri/src/lib.rs | 28 +- .../src-tauri/src/services/acp/goose_serve.rs | 106 +- .../src-tauri/src/services/acp/manager.rs | 308 - .../services/acp/manager/command_dispatch.rs | 258 - .../src/services/acp/manager/dispatcher.rs | 532 -- .../services/acp/manager/dispatcher_tests.rs | 28 - .../src/services/acp/manager/session_ops.rs | 611 -- .../acp/manager/session_ops/prompt_ops.rs | 112 - .../services/acp/manager/session_ops/tests.rs | 192 - .../src/services/acp/manager/thread.rs | 169 - ui/goose2/src-tauri/src/services/acp/mod.rs | 144 - .../src-tauri/src/services/acp/payloads.rs | 106 - .../src-tauri/src/services/acp/registry.rs | 114 - .../src-tauri/src/services/acp/search.rs | 467 - .../src-tauri/src/services/acp/writer.rs | 156 - ui/goose2/src/app/AppShell.tsx | 12 +- ui/goose2/src/app/hooks/useAppStartup.ts | 13 +- .../chat/hooks/__tests__/useAcpStream.test.ts | 567 -- .../__tests__/useChat.attachments.test.ts | 8 - .../chat/hooks/__tests__/useChat.test.ts | 40 +- .../src/features/chat/hooks/acpStreamTypes.ts | 67 - .../src/features/chat/hooks/useAcpStream.ts | 553 -- ui/goose2/src/features/chat/hooks/useChat.ts | 5 +- ui/goose2/src/features/chat/hooks/useSSE.ts | 74 - .../src/features/chat/ui/ContextPanel.tsx | 14 +- .../chat/ui/__tests__/ContextPanel.test.tsx | 4 - ui/goose2/src/features/sidebar/ui/Sidebar.tsx | 127 +- ui/goose2/src/shared/api/acp.ts | 171 +- ui/goose2/src/shared/api/acpApi.ts | 28 +- ui/goose2/src/shared/api/acpConnection.ts | 2 +- ui/goose2/src/shared/api/acpFeatureFlag.ts | 1 - .../src/shared/api/acpNotificationHandler.ts | 6 +- .../src/shared/api/createWebSocketStream.ts | 1 + ui/goose2/src/shared/api/sessionSearch.ts | 2 +- ui/goose2/src/shared/types/agents.ts | 8 +- ui/goose2/src/test/mocks/goose-sdk.ts | 7 + ui/goose2/tests/e2e/fixtures/tauri-mock.ts | 2 - ui/goose2/vitest.config.ts | 1 + ui/pnpm-lock.yaml | 26 +- 48 files changed, 289 insertions(+), 12972 deletions(-) delete mode 100644 ui/goose2/pnpm-lock.yaml delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/command_dispatch.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/dispatcher.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/dispatcher_tests.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/session_ops.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/session_ops/prompt_ops.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/session_ops/tests.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/manager/thread.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/payloads.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/registry.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/search.rs delete mode 100644 ui/goose2/src-tauri/src/services/acp/writer.rs delete mode 100644 ui/goose2/src/features/chat/hooks/__tests__/useAcpStream.test.ts delete mode 100644 ui/goose2/src/features/chat/hooks/acpStreamTypes.ts delete mode 100644 ui/goose2/src/features/chat/hooks/useAcpStream.ts delete mode 100644 ui/goose2/src/features/chat/hooks/useSSE.ts delete mode 100644 ui/goose2/src/shared/api/acpFeatureFlag.ts create mode 100644 ui/goose2/src/test/mocks/goose-sdk.ts diff --git a/.github/workflows/goose2-ci.yml b/.github/workflows/goose2-ci.yml index 68b69c93ea..d45ff04e86 100644 --- a/.github/workflows/goose2-ci.yml +++ b/.github/workflows/goose2-ci.yml @@ -5,10 +5,12 @@ on: branches: [main] paths: - "ui/goose2/**" + - "ui/sdk/**" pull_request: branches: [main] paths: - "ui/goose2/**" + - "ui/sdk/**" merge_group: branches: [main] workflow_dispatch: @@ -35,8 +37,11 @@ jobs: with: node-version: 24 cache: pnpm - cache-dependency-path: ui/goose2/pnpm-lock.yaml + cache-dependency-path: ui/pnpm-lock.yaml - run: pnpm install --frozen-lockfile + - name: Build SDK + run: pnpm build + working-directory: ui/sdk - run: pnpm check - run: pnpm typecheck @@ -53,8 +58,11 @@ jobs: with: node-version: 24 cache: pnpm - cache-dependency-path: ui/goose2/pnpm-lock.yaml + cache-dependency-path: ui/pnpm-lock.yaml - run: pnpm install --frozen-lockfile + - name: Build SDK + run: pnpm build + working-directory: ui/sdk - run: pnpm test desktop: @@ -70,7 +78,7 @@ jobs: with: node-version: 24 cache: pnpm - cache-dependency-path: ui/goose2/pnpm-lock.yaml + cache-dependency-path: ui/pnpm-lock.yaml - name: Install system dependencies run: | @@ -96,6 +104,10 @@ jobs: - run: pnpm install --frozen-lockfile + - name: Build SDK + run: pnpm build + working-directory: ui/sdk + - name: Build frontend run: pnpm build diff --git a/ui/goose2/AGENTS.md b/ui/goose2/AGENTS.md index c135d84053..47c7d3bda7 100644 --- a/ui/goose2/AGENTS.md +++ b/ui/goose2/AGENTS.md @@ -134,9 +134,8 @@ ThemeProvider manages three axes: ## Backend Architecture All AI communication goes through **ACP (Agent Client Protocol)**: -- The Rust backend spawns ACP agent binaries as child processes and communicates via **stdin/stdout JSON-RPC**. -- Responses stream back to the frontend through **Tauri events** (`acp:text`, `acp:tool_call`, `acp:tool_result`, `acp:done`, etc.). -- The frontend listens to these events via `@tauri-apps/api/event` (see `useAcpStream` hook). +- The Tauri app starts a long-lived `goose serve` process and exposes its WebSocket URL. +- The frontend connects directly to `goose serve` over WebSocket and handles ACP notifications in TypeScript. For non AI communication, such as configuration: - Use **Tauri commands** (`invoke()` from `@tauri-apps/api/core`) for request/response operations (sessions, personas, skills, projects, etc.). diff --git a/ui/goose2/justfile b/ui/goose2/justfile index 68d997bd9c..ad8841dcc0 100644 --- a/ui/goose2/justfile +++ b/ui/goose2/justfile @@ -8,9 +8,10 @@ default: # ── Dev Environment ────────────────────────────────────────── -# Install dependencies +# Install dependencies and build workspace packages setup: pnpm install + cd ../sdk && pnpm build cd src-tauri && cargo build # ── Build & Check ──────────────────────────────────────────── diff --git a/ui/goose2/package.json b/ui/goose2/package.json index bdad0be453..f959d27934 100644 --- a/ui/goose2/package.json +++ b/ui/goose2/package.json @@ -27,7 +27,7 @@ "test-driver": "tsx tests/app-e2e/lib/test-driver-cli.ts" }, "dependencies": { - "@aaif/goose-acp": "^0.16.0", + "@aaif/goose-sdk": "workspace:*", "@agentclientprotocol/sdk": "^0.19.0", "@radix-ui/react-accordion": "^1.2.12", "@radix-ui/react-alert-dialog": "^1.1.15", @@ -65,7 +65,7 @@ "@tailwindcss/typography": "^0.5.19", "@tanstack/react-query": "^5.90.21", "@tauri-apps/api": "^2", - "@tauri-apps/plugin-dialog": "^2.6.0", + "@tauri-apps/plugin-dialog": "~2.6.0", "@tauri-apps/plugin-opener": "^2.5.3", "@xyflow/react": "^12.10.2", "ai": "^6.0.142", diff --git a/ui/goose2/pnpm-lock.yaml b/ui/goose2/pnpm-lock.yaml deleted file mode 100644 index ebe76b37fe..0000000000 --- a/ui/goose2/pnpm-lock.yaml +++ /dev/null @@ -1,7615 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - '@aaif/goose-acp': - specifier: ^0.16.0 - version: 0.16.0(@agentclientprotocol/sdk@0.19.0(zod@4.3.6)) - '@agentclientprotocol/sdk': - specifier: ^0.19.0 - version: 0.19.0(zod@4.3.6) - '@radix-ui/react-accordion': - specifier: ^1.2.12 - version: 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-alert-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-aspect-ratio': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-avatar': - specifier: ^1.1.11 - version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-checkbox': - specifier: ^1.3.3 - version: 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-collapsible': - specifier: ^1.1.12 - version: 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-context-menu': - specifier: ^2.2.16 - version: 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-dialog': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-dropdown-menu': - specifier: ^2.1.16 - version: 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-hover-card': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-label': - specifier: ^2.1.8 - version: 2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-menubar': - specifier: ^1.1.16 - version: 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-navigation-menu': - specifier: ^1.2.14 - version: 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-popover': - specifier: ^1.1.15 - version: 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-progress': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-radio-group': - specifier: ^1.3.8 - version: 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-scroll-area': - specifier: ^1.2.10 - version: 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-select': - specifier: ^2.2.6 - version: 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-separator': - specifier: ^1.1.8 - version: 1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slider': - specifier: ^1.3.6 - version: 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': - specifier: ^1.2.4 - version: 1.2.4(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-switch': - specifier: ^1.2.6 - version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tabs': - specifier: ^1.1.13 - version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle': - specifier: ^1.1.10 - version: 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle-group': - specifier: ^1.1.11 - version: 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-tooltip': - specifier: ^1.2.8 - version: 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': - specifier: ^1.2.2 - version: 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@rive-app/react-webgl2': - specifier: ^4.27.3 - version: 4.27.3(react@19.2.4) - '@streamdown/cjk': - specifier: ^1.0.3 - version: 1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.4)(unified@11.0.5) - '@streamdown/code': - specifier: ^1.1.1 - version: 1.1.1(react@19.2.4) - '@streamdown/math': - specifier: ^1.0.2 - version: 1.0.2(react@19.2.4) - '@streamdown/mermaid': - specifier: ^1.0.2 - version: 1.0.2(react@19.2.4) - '@tabler/icons-react': - specifier: ^3.41.1 - version: 3.41.1(react@19.2.4) - '@tailwindcss/typography': - specifier: ^0.5.19 - version: 0.5.19(tailwindcss@4.2.2) - '@tanstack/react-query': - specifier: ^5.90.21 - version: 5.95.2(react@19.2.4) - '@tauri-apps/api': - specifier: ^2 - version: 2.10.1 - '@tauri-apps/plugin-dialog': - specifier: ^2.6.0 - version: 2.6.0 - '@tauri-apps/plugin-opener': - specifier: ^2.5.3 - version: 2.5.3 - '@xyflow/react': - specifier: ^12.10.2 - version: 12.10.2(@types/react@19.2.14)(immer@11.1.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - ai: - specifier: ^6.0.142 - version: 6.0.142(zod@4.3.6) - ansi-to-react: - specifier: ^6.2.6 - version: 6.2.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - class-variance-authority: - specifier: ^0.7.1 - version: 0.7.1 - clsx: - specifier: ^2.1.1 - version: 2.1.1 - cmdk: - specifier: ^1.1.1 - version: 1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - embla-carousel-react: - specifier: ^8.6.0 - version: 8.6.0(react@19.2.4) - gsap: - specifier: ^3.14.2 - version: 3.14.2 - i18next: - specifier: ^26.0.3 - version: 26.0.3(typescript@5.9.3) - i18next-resources-to-backend: - specifier: ^1.2.1 - version: 1.2.1 - input-otp: - specifier: ^1.4.2 - version: 1.4.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - lucide-react: - specifier: ^0.577.0 - version: 0.577.0(react@19.2.4) - media-chrome: - specifier: ^4.18.3 - version: 4.18.3(react@19.2.4) - motion: - specifier: ^12.38.0 - version: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - nanoid: - specifier: ^5.1.7 - version: 5.1.7 - next-themes: - specifier: ^0.4.6 - version: 0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: - specifier: ^19.1.0 - version: 19.2.4 - react-day-picker: - specifier: ^9.14.0 - version: 9.14.0(react@19.2.4) - react-dom: - specifier: ^19.1.0 - version: 19.2.4(react@19.2.4) - react-hook-form: - specifier: ^7.72.0 - version: 7.72.0(react@19.2.4) - react-i18next: - specifier: ^17.0.2 - version: 17.0.2(i18next@26.0.3(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3) - react-jsx-parser: - specifier: ^2.4.1 - version: 2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react-markdown: - specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.14)(react@19.2.4) - react-resizable-panels: - specifier: ^4.8.0 - version: 4.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react-syntax-highlighter: - specifier: ^16.1.1 - version: 16.1.1(react@19.2.4) - recharts: - specifier: ^3.8.1 - version: 3.8.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@17.0.2)(react@19.2.4)(redux@5.0.1) - remark-breaks: - specifier: ^4.0.0 - version: 4.0.0 - remark-gfm: - specifier: ^4.0.1 - version: 4.0.1 - shiki: - specifier: ^4.0.2 - version: 4.0.2 - sonner: - specifier: ^2.0.7 - version: 2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - split-type: - specifier: ^0.3.4 - version: 0.3.4 - streamdown: - specifier: ^2.5.0 - version: 2.5.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tailwind-merge: - specifier: ^3.5.0 - version: 3.5.0 - tokenlens: - specifier: ^1.3.1 - version: 1.3.1 - tw-animate-css: - specifier: ^1.4.0 - version: 1.4.0 - use-stick-to-bottom: - specifier: ^1.1.3 - version: 1.1.3(react@19.2.4) - vaul: - specifier: ^1.1.2 - version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - zustand: - specifier: ^5.0.12 - version: 5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) - devDependencies: - '@biomejs/biome': - specifier: 2.4.9 - version: 2.4.9 - '@playwright/test': - specifier: ^1.52.0 - version: 1.58.2 - '@tailwindcss/postcss': - specifier: ^4.2.2 - version: 4.2.2 - '@tauri-apps/cli': - specifier: ^2 - version: 2.10.1 - '@testing-library/jest-dom': - specifier: ^6.6.3 - version: 6.9.1 - '@testing-library/react': - specifier: ^16.3.0 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@testing-library/user-event': - specifier: ^14.6.1 - version: 14.6.1(@testing-library/dom@10.4.1) - '@types/react': - specifier: ^19.1.8 - version: 19.2.14 - '@types/react-dom': - specifier: ^19.1.6 - version: 19.2.3(@types/react@19.2.14) - '@types/react-syntax-highlighter': - specifier: ^15.5.13 - version: 15.5.13 - '@vitejs/plugin-react': - specifier: ^4.6.0 - version: 4.7.0(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)) - jsdom: - specifier: ^26.1.0 - version: 26.1.0 - postcss: - specifier: ^8.5.8 - version: 8.5.8 - tailwindcss: - specifier: ^4.2.2 - version: 4.2.2 - tsx: - specifier: ^4.21.0 - version: 4.21.0 - typescript: - specifier: ~5.9.0 - version: 5.9.3 - vite: - specifier: ^7.0.4 - version: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0) - vitest: - specifier: ^4.1.0 - version: 4.1.2(@opentelemetry/api@1.9.0)(jsdom@26.1.0)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)) - -packages: - - '@aaif/goose-acp@0.16.0': - resolution: {integrity: sha512-LJLn01pqobvQAsagScROFOnjKRSQPaDuP7v17oyrK1IDfvZzOM20ZkQcvGDWhYCRUHXWBJgJ9dD6iZkVtNYYwg==} - peerDependencies: - '@agentclientprotocol/sdk': '*' - - '@adobe/css-tools@4.4.4': - resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} - - '@agentclientprotocol/sdk@0.19.0': - resolution: {integrity: sha512-U9I8ws9WTOk6jCBAWpXefGSDgVXn14/kV6HFzwWGcstQ02mOQgClMAROHmoIn9GqZbDBDEOkdIbP4P4TEMQdug==} - peerDependencies: - zod: ^3.25.0 || ^4.0.0 - - '@ai-sdk/gateway@3.0.84': - resolution: {integrity: sha512-RnUw6UNvkaw9MEaJU9cIjA+WBP+ZR5+M/9nfbfJHcGKtTbcWXijJuYKx9nYRnm+qU+iiakb0XvQA/vvho6lTsw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/provider-utils@4.0.21': - resolution: {integrity: sha512-MtFUYI1/8mgDvRmaBDjbLJPFFrMG777AvSgyIFQtZHIMzm88R/12vYBBpnk7pfiWLFE1DSZzY4WDYzGbKAcmiw==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - '@ai-sdk/provider@3.0.8': - resolution: {integrity: sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==} - engines: {node: '>=18'} - - '@alloc/quick-lru@5.2.0': - resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} - engines: {node: '>=10'} - - '@antfu/install-pkg@1.1.0': - resolution: {integrity: sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==} - - '@asamuzakjp/css-color@3.2.0': - resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} - - '@babel/code-frame@7.29.0': - resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} - engines: {node: '>=6.9.0'} - - '@babel/compat-data@7.29.0': - resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} - engines: {node: '>=6.9.0'} - - '@babel/core@7.29.0': - resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} - engines: {node: '>=6.9.0'} - - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-compilation-targets@7.28.6': - resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-globals@7.28.0': - resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-imports@7.28.6': - resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-module-transforms@7.28.6': - resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.28.5': - resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-option@7.27.1': - resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} - engines: {node: '>=6.9.0'} - - '@babel/helpers@7.29.2': - resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/plugin-transform-react-jsx-self@7.27.1': - resolution: {integrity: sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/plugin-transform-react-jsx-source@7.27.1': - resolution: {integrity: sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - - '@babel/runtime@7.29.2': - resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} - engines: {node: '>=6.9.0'} - - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - - '@babel/traverse@7.29.0': - resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - - '@biomejs/biome@2.4.9': - resolution: {integrity: sha512-wvZW92FrwitTcacvCBT8xdAbfbxWfDLwjYMmU3djjqQTh7Ni4ZdiWIT/x5VcZ+RQuxiKzIOzi5D+dcyJDFZMsA==} - engines: {node: '>=14.21.3'} - hasBin: true - - '@biomejs/cli-darwin-arm64@2.4.9': - resolution: {integrity: sha512-d5G8Gf2RpH5pYwiHLPA+UpG3G9TLQu4WM+VK6sfL7K68AmhcEQ9r+nkj/DvR/GYhYox6twsHUtmWWWIKfcfQQA==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [darwin] - - '@biomejs/cli-darwin-x64@2.4.9': - resolution: {integrity: sha512-LNCLNgqDMG7BLdc3a8aY/dwKPK7+R8/JXJoXjCvZh2gx8KseqBdFDKbhrr7HCWF8SzNhbTaALhTBoh/I6rf9lA==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [darwin] - - '@biomejs/cli-linux-arm64-musl@2.4.9': - resolution: {integrity: sha512-8RCww5xnPn2wpK4L/QDGDOW0dq80uVWfppPxHIUg6mOs9B6gRmqPp32h1Ls3T8GnW8Wo5A8u7vpTwz4fExN+sw==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@biomejs/cli-linux-arm64@2.4.9': - resolution: {integrity: sha512-4adnkAUi6K4C/emPRgYznMOcLlUqZdXWM6aIui4VP4LraE764g6Q4YguygnAUoxKjKIXIWPteKMgRbN0wsgwcg==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@biomejs/cli-linux-x64-musl@2.4.9': - resolution: {integrity: sha512-5TD+WS9v5vzXKzjetF0hgoaNFHMcpQeBUwKKVi3JbG1e9UCrFuUK3Gt185fyTzvRdwYkJJEMqglRPjmesmVv4A==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@biomejs/cli-linux-x64@2.4.9': - resolution: {integrity: sha512-L10na7POF0Ks/cgLFNF1ZvIe+X4onLkTi5oP9hY+Rh60Q+7fWzKDDCeGyiHUFf1nGIa9dQOOUPGe2MyYg8nMSQ==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@biomejs/cli-win32-arm64@2.4.9': - resolution: {integrity: sha512-aDZr0RBC3sMGJOU10BvG7eZIlWLK/i51HRIfScE2lVhfts2dQTreowLiJJd+UYg/tHKxS470IbzpuKmd0MiD6g==} - engines: {node: '>=14.21.3'} - cpu: [arm64] - os: [win32] - - '@biomejs/cli-win32-x64@2.4.9': - resolution: {integrity: sha512-NS4g/2G9SoQ4ktKtz31pvyc/rmgzlcIDCGU/zWbmHJAqx6gcRj2gj5Q/guXhoWTzCUaQZDIqiCQXHS7BcGYc0w==} - engines: {node: '>=14.21.3'} - cpu: [x64] - os: [win32] - - '@braintree/sanitize-url@7.1.2': - resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} - - '@chevrotain/cst-dts-gen@11.1.2': - resolution: {integrity: sha512-XTsjvDVB5nDZBQB8o0o/0ozNelQtn2KrUVteIHSlPd2VAV2utEb6JzyCJaJ8tGxACR4RiBNWy5uYUHX2eji88Q==} - - '@chevrotain/gast@11.1.2': - resolution: {integrity: sha512-Z9zfXR5jNZb1Hlsd/p+4XWeUFugrHirq36bKzPWDSIacV+GPSVXdk+ahVWZTwjhNwofAWg/sZg58fyucKSQx5g==} - - '@chevrotain/regexp-to-ast@11.1.2': - resolution: {integrity: sha512-nMU3Uj8naWer7xpZTYJdxbAs6RIv/dxYzkYU8GSwgUtcAAlzjcPfX1w+RKRcYG8POlzMeayOQ/znfwxEGo5ulw==} - - '@chevrotain/types@11.1.2': - resolution: {integrity: sha512-U+HFai5+zmJCkK86QsaJtoITlboZHBqrVketcO2ROv865xfCMSFpELQoz1GkX5GzME8pTa+3kbKrZHQtI0gdbw==} - - '@chevrotain/utils@11.1.2': - resolution: {integrity: sha512-4mudFAQ6H+MqBTfqLmU7G1ZwRzCLfJEooL/fsF6rCX5eePMbGhoy5n4g+G4vlh2muDcsCTJtL+uKbOzWxs5LHA==} - - '@csstools/color-helpers@5.1.0': - resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} - engines: {node: '>=18'} - - '@csstools/css-calc@2.1.4': - resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-color-parser@3.1.0': - resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-parser-algorithms': ^3.0.5 - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-parser-algorithms@3.0.5': - resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} - engines: {node: '>=18'} - peerDependencies: - '@csstools/css-tokenizer': ^3.0.4 - - '@csstools/css-tokenizer@3.0.4': - resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} - engines: {node: '>=18'} - - '@date-fns/tz@1.4.1': - resolution: {integrity: sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA==} - - '@esbuild/aix-ppc64@0.27.4': - resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.27.4': - resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.27.4': - resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} - engines: {node: '>=18'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.27.4': - resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} - engines: {node: '>=18'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.27.4': - resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} - engines: {node: '>=18'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.27.4': - resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} - engines: {node: '>=18'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.27.4': - resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} - engines: {node: '>=18'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.27.4': - resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.27.4': - resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} - engines: {node: '>=18'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.27.4': - resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} - engines: {node: '>=18'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.27.4': - resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} - engines: {node: '>=18'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.27.4': - resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} - engines: {node: '>=18'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.27.4': - resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} - engines: {node: '>=18'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.27.4': - resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} - engines: {node: '>=18'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.27.4': - resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} - engines: {node: '>=18'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.27.4': - resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} - engines: {node: '>=18'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.27.4': - resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} - engines: {node: '>=18'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-arm64@0.27.4': - resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} - engines: {node: '>=18'} - cpu: [arm64] - os: [netbsd] - - '@esbuild/netbsd-x64@0.27.4': - resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} - engines: {node: '>=18'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-arm64@0.27.4': - resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openbsd] - - '@esbuild/openbsd-x64@0.27.4': - resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} - engines: {node: '>=18'} - cpu: [x64] - os: [openbsd] - - '@esbuild/openharmony-arm64@0.27.4': - resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [openharmony] - - '@esbuild/sunos-x64@0.27.4': - resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} - engines: {node: '>=18'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.27.4': - resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} - engines: {node: '>=18'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.27.4': - resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} - engines: {node: '>=18'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.27.4': - resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} - engines: {node: '>=18'} - cpu: [x64] - os: [win32] - - '@floating-ui/core@1.7.5': - resolution: {integrity: sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==} - - '@floating-ui/dom@1.7.6': - resolution: {integrity: sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==} - - '@floating-ui/react-dom@2.1.8': - resolution: {integrity: sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==} - peerDependencies: - react: '>=16.8.0' - react-dom: '>=16.8.0' - - '@floating-ui/utils@0.2.11': - resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} - - '@iconify/types@2.0.0': - resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - - '@iconify/utils@3.1.0': - resolution: {integrity: sha512-Zlzem1ZXhI1iHeeERabLNzBHdOa4VhQbqAcOQaMKuTuyZCpwKbC2R4Dd0Zo3g9EAc+Y4fiarO8HIHRAth7+skw==} - - '@jridgewell/gen-mapping@0.3.13': - resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} - - '@jridgewell/remapping@2.3.5': - resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} - - '@jridgewell/resolve-uri@3.1.2': - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - - '@jridgewell/sourcemap-codec@1.5.5': - resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} - - '@jridgewell/trace-mapping@0.3.31': - resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} - - '@mermaid-js/parser@1.1.0': - resolution: {integrity: sha512-gxK9ZX2+Fex5zu8LhRQoMeMPEHbc73UKZ0FQ54YrQtUxE1VVhMwzeNtKRPAu5aXks4FasbMe4xB4bWrmq6Jlxw==} - - '@opentelemetry/api@1.9.0': - resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} - engines: {node: '>=8.0.0'} - - '@playwright/test@1.58.2': - resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} - engines: {node: '>=18'} - hasBin: true - - '@radix-ui/number@1.1.1': - resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} - - '@radix-ui/primitive@1.1.3': - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - - '@radix-ui/react-accordion@1.2.12': - resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-alert-dialog@1.1.15': - resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-arrow@1.1.7': - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-aspect-ratio@1.1.8': - resolution: {integrity: sha512-5nZrJTF7gH+e0nZS7/QxFz6tJV4VimhQb1avEgtsJxvvIp5JilL+c58HICsKzPxghdwaDt48hEfPM1au4zGy+w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-avatar@1.1.11': - resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-checkbox@1.3.3': - resolution: {integrity: sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collapsible@1.1.12': - resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-compose-refs@1.1.2': - resolution: {integrity: sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context-menu@2.2.16': - resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-context@1.1.2': - resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-context@1.1.3': - resolution: {integrity: sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dialog@1.1.15': - resolution: {integrity: sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-direction@1.1.1': - resolution: {integrity: sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-dismissable-layer@1.1.11': - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-hover-card@1.1.15': - resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-id@1.1.1': - resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-label@2.1.8': - resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-menubar@1.1.16': - resolution: {integrity: sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-navigation-menu@1.2.14': - resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popover@1.1.15': - resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-popper@1.2.8': - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-portal@1.1.9': - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-presence@1.1.5': - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.3': - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-primitive@2.1.4': - resolution: {integrity: sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-progress@1.1.8': - resolution: {integrity: sha512-+gISHcSPUJ7ktBy9RnTqbdKW78bcGke3t6taawyZ71pio1JewwGSJizycs7rLhGTvMJYCQB1DBK4KQsxs7U8dA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-radio-group@1.3.8': - resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-scroll-area@1.2.10': - resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-select@2.2.6': - resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-separator@1.1.8': - resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-slider@1.3.6': - resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-slot@1.2.3': - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-slot@1.2.4': - resolution: {integrity: sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-switch@1.2.6': - resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tabs@1.1.13': - resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toggle-group@1.1.11': - resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-toggle@1.1.10': - resolution: {integrity: sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-tooltip@1.2.8': - resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-use-callback-ref@1.1.1': - resolution: {integrity: sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-escape-keydown@1.1.1': - resolution: {integrity: sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-is-hydrated@0.1.0': - resolution: {integrity: sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-layout-effect@1.1.1': - resolution: {integrity: sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-previous@1.1.1': - resolution: {integrity: sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-rect@1.1.1': - resolution: {integrity: sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-size@1.1.1': - resolution: {integrity: sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-visually-hidden@1.2.3': - resolution: {integrity: sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/rect@1.1.1': - resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} - - '@reduxjs/toolkit@2.11.2': - resolution: {integrity: sha512-Kd6kAHTA6/nUpp8mySPqj3en3dm0tdMIgbttnQ1xFMVpufoj+ADi8pXLBsd4xzTRHQa7t/Jv8W5UnCuW4kuWMQ==} - peerDependencies: - react: ^16.9.0 || ^17.0.0 || ^18 || ^19 - react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 - peerDependenciesMeta: - react: - optional: true - react-redux: - optional: true - - '@rive-app/react-webgl2@4.27.3': - resolution: {integrity: sha512-f+i0w/iipxwJWOH2J+0u2se0OdTM5PNWqwndRMO6EwOG5YsHHOc9opmFQCViiwkzT6Sr3vU/hqdrZy8tno6exw==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0 - - '@rive-app/webgl2@2.35.4': - resolution: {integrity: sha512-1dX1axIC6WgrvCkBsH1tjHjPz3xXGoDUuu3CZMdnlCOtGmASq4WM7LOPvuggmLgGl5mLHX9VF7Nr/AakpcMeUw==} - - '@rolldown/pluginutils@1.0.0-beta.27': - resolution: {integrity: sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==} - - '@rollup/rollup-android-arm-eabi@4.60.0': - resolution: {integrity: sha512-WOhNW9K8bR3kf4zLxbfg6Pxu2ybOUbB2AjMDHSQx86LIF4rH4Ft7vmMwNt0loO0eonglSNy4cpD3MKXXKQu0/A==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.60.0': - resolution: {integrity: sha512-u6JHLll5QKRvjciE78bQXDmqRqNs5M/3GVqZeMwvmjaNODJih/WIrJlFVEihvV0MiYFmd+ZyPr9wxOVbPAG2Iw==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.60.0': - resolution: {integrity: sha512-qEF7CsKKzSRc20Ciu2Zw1wRrBz4g56F7r/vRwY430UPp/nt1x21Q/fpJ9N5l47WWvJlkNCPJz3QRVw008fi7yA==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.60.0': - resolution: {integrity: sha512-WADYozJ4QCnXCH4wPB+3FuGmDPoFseVCUrANmA5LWwGmC6FL14BWC7pcq+FstOZv3baGX65tZ378uT6WG8ynTw==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-freebsd-arm64@4.60.0': - resolution: {integrity: sha512-6b8wGHJlDrGeSE3aH5mGNHBjA0TTkxdoNHik5EkvPHCt351XnigA4pS7Wsj/Eo9Y8RBU6f35cjN9SYmCFBtzxw==} - cpu: [arm64] - os: [freebsd] - - '@rollup/rollup-freebsd-x64@4.60.0': - resolution: {integrity: sha512-h25Ga0t4jaylMB8M/JKAyrvvfxGRjnPQIR8lnCayyzEjEOx2EJIlIiMbhpWxDRKGKF8jbNH01NnN663dH638mA==} - cpu: [x64] - os: [freebsd] - - '@rollup/rollup-linux-arm-gnueabihf@4.60.0': - resolution: {integrity: sha512-RzeBwv0B3qtVBWtcuABtSuCzToo2IEAIQrcyB/b2zMvBWVbjo8bZDjACUpnaafaxhTw2W+imQbP2BD1usasK4g==} - cpu: [arm] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm-musleabihf@4.60.0': - resolution: {integrity: sha512-Sf7zusNI2CIU1HLzuu9Tc5YGAHEZs5Lu7N1ssJG4Tkw6e0MEsN7NdjUDDfGNHy2IU+ENyWT+L2obgWiguWibWQ==} - cpu: [arm] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-arm64-gnu@4.60.0': - resolution: {integrity: sha512-DX2x7CMcrJzsE91q7/O02IJQ5/aLkVtYFryqCjduJhUfGKG6yJV8hxaw8pZa93lLEpPTP/ohdN4wFz7yp/ry9A==} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-arm64-musl@4.60.0': - resolution: {integrity: sha512-09EL+yFVbJZlhcQfShpswwRZ0Rg+z/CsSELFCnPt3iK+iqwGsI4zht3secj5vLEs957QvFFXnzAT0FFPIxSrkQ==} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-loong64-gnu@4.60.0': - resolution: {integrity: sha512-i9IcCMPr3EXm8EQg5jnja0Zyc1iFxJjZWlb4wr7U2Wx/GrddOuEafxRdMPRYVaXjgbhvqalp6np07hN1w9kAKw==} - cpu: [loong64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-loong64-musl@4.60.0': - resolution: {integrity: sha512-DGzdJK9kyJ+B78MCkWeGnpXJ91tK/iKA6HwHxF4TAlPIY7GXEvMe8hBFRgdrR9Ly4qebR/7gfUs9y2IoaVEyog==} - cpu: [loong64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-ppc64-gnu@4.60.0': - resolution: {integrity: sha512-RwpnLsqC8qbS8z1H1AxBA1H6qknR4YpPR9w2XX0vo2Sz10miu57PkNcnHVaZkbqyw/kUWfKMI73jhmfi9BRMUQ==} - cpu: [ppc64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-ppc64-musl@4.60.0': - resolution: {integrity: sha512-Z8pPf54Ly3aqtdWC3G4rFigZgNvd+qJlOE52fmko3KST9SoGfAdSRCwyoyG05q1HrrAblLbk1/PSIV+80/pxLg==} - cpu: [ppc64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-riscv64-gnu@4.60.0': - resolution: {integrity: sha512-3a3qQustp3COCGvnP4SvrMHnPQ9d1vzCakQVRTliaz8cIp/wULGjiGpbcqrkv0WrHTEp8bQD/B3HBjzujVWLOA==} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-riscv64-musl@4.60.0': - resolution: {integrity: sha512-pjZDsVH/1VsghMJ2/kAaxt6dL0psT6ZexQVrijczOf+PeP2BUqTHYejk3l6TlPRydggINOeNRhvpLa0AYpCWSQ==} - cpu: [riscv64] - os: [linux] - libc: [musl] - - '@rollup/rollup-linux-s390x-gnu@4.60.0': - resolution: {integrity: sha512-3ObQs0BhvPgiUVZrN7gqCSvmFuMWvWvsjG5ayJ3Lraqv+2KhOsp+pUbigqbeWqueGIsnn+09HBw27rJ+gYK4VQ==} - cpu: [s390x] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-gnu@4.60.0': - resolution: {integrity: sha512-EtylprDtQPdS5rXvAayrNDYoJhIz1/vzN2fEubo3yLE7tfAw+948dO0g4M0vkTVFhKojnF+n6C8bDNe+gDRdTg==} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@rollup/rollup-linux-x64-musl@4.60.0': - resolution: {integrity: sha512-k09oiRCi/bHU9UVFqD17r3eJR9bn03TyKraCrlz5ULFJGdJGi7VOmm9jl44vOJvRJ6P7WuBi/s2A97LxxHGIdw==} - cpu: [x64] - os: [linux] - libc: [musl] - - '@rollup/rollup-openbsd-x64@4.60.0': - resolution: {integrity: sha512-1o/0/pIhozoSaDJoDcec+IVLbnRtQmHwPV730+AOD29lHEEo4F5BEUB24H0OBdhbBBDwIOSuf7vgg0Ywxdfiiw==} - cpu: [x64] - os: [openbsd] - - '@rollup/rollup-openharmony-arm64@4.60.0': - resolution: {integrity: sha512-pESDkos/PDzYwtyzB5p/UoNU/8fJo68vcXM9ZW2V0kjYayj1KaaUfi1NmTUTUpMn4UhU4gTuK8gIaFO4UGuMbA==} - cpu: [arm64] - os: [openharmony] - - '@rollup/rollup-win32-arm64-msvc@4.60.0': - resolution: {integrity: sha512-hj1wFStD7B1YBeYmvY+lWXZ7ey73YGPcViMShYikqKT1GtstIKQAtfUI6yrzPjAy/O7pO0VLXGmUVWXQMaYgTQ==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.60.0': - resolution: {integrity: sha512-SyaIPFoxmUPlNDq5EHkTbiKzmSEmq/gOYFI/3HHJ8iS/v1mbugVa7dXUzcJGQfoytp9DJFLhHH4U3/eTy2Bq4w==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-gnu@4.60.0': - resolution: {integrity: sha512-RdcryEfzZr+lAr5kRm2ucN9aVlCCa2QNq4hXelZxb8GG0NJSazq44Z3PCCc8wISRuCVnGs0lQJVX5Vp6fKA+IA==} - cpu: [x64] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.60.0': - resolution: {integrity: sha512-PrsWNQ8BuE00O3Xsx3ALh2Df8fAj9+cvvX9AIA6o4KpATR98c9mud4XtDWVvsEuyia5U4tVSTKygawyJkjm60w==} - cpu: [x64] - os: [win32] - - '@shikijs/core@3.23.0': - resolution: {integrity: sha512-NSWQz0riNb67xthdm5br6lAkvpDJRTgB36fxlo37ZzM2yq0PQFFzbd8psqC2XMPgCzo1fW6cVi18+ArJ44wqgA==} - - '@shikijs/core@4.0.2': - resolution: {integrity: sha512-hxT0YF4ExEqB8G/qFdtJvpmHXBYJ2lWW7qTHDarVkIudPFE6iCIrqdgWxGn5s+ppkGXI0aEGlibI0PAyzP3zlw==} - engines: {node: '>=20'} - - '@shikijs/engine-javascript@3.23.0': - resolution: {integrity: sha512-aHt9eiGFobmWR5uqJUViySI1bHMqrAgamWE1TYSUoftkAeCCAiGawPMwM+VCadylQtF4V3VNOZ5LmfItH5f3yA==} - - '@shikijs/engine-javascript@4.0.2': - resolution: {integrity: sha512-7PW0Nm49DcoUIQEXlJhNNBHyoGMjalRETTCcjMqEaMoJRLljy1Bi/EGV3/qLBgLKQejdspiiYuHGQW6dX94Nag==} - engines: {node: '>=20'} - - '@shikijs/engine-oniguruma@3.23.0': - resolution: {integrity: sha512-1nWINwKXxKKLqPibT5f4pAFLej9oZzQTsby8942OTlsJzOBZ0MWKiwzMsd+jhzu8YPCHAswGnnN1YtQfirL35g==} - - '@shikijs/engine-oniguruma@4.0.2': - resolution: {integrity: sha512-UpCB9Y2sUKlS9z8juFSKz7ZtysmeXCgnRF0dlhXBkmQnek7lAToPte8DkxmEYGNTMii72zU/lyXiCB6StuZeJg==} - engines: {node: '>=20'} - - '@shikijs/langs@3.23.0': - resolution: {integrity: sha512-2Ep4W3Re5aB1/62RSYQInK9mM3HsLeB91cHqznAJMuylqjzNVAVCMnNWRHFtcNHXsoNRayP9z1qj4Sq3nMqYXg==} - - '@shikijs/langs@4.0.2': - resolution: {integrity: sha512-KaXby5dvoeuZzN0rYQiPMjFoUrz4hgwIE+D6Du9owcHcl6/g16/yT5BQxSW5cGt2MZBz6Hl0YuRqf12omRfUUg==} - engines: {node: '>=20'} - - '@shikijs/primitive@4.0.2': - resolution: {integrity: sha512-M6UMPrSa3fN5ayeJwFVl9qWofl273wtK1VG8ySDZ1mQBfhCpdd8nEx7nPZ/tk7k+TYcpqBZzj/AnwxT9lO+HJw==} - engines: {node: '>=20'} - - '@shikijs/themes@3.23.0': - resolution: {integrity: sha512-5qySYa1ZgAT18HR/ypENL9cUSGOeI2x+4IvYJu4JgVJdizn6kG4ia5Q1jDEOi7gTbN4RbuYtmHh0W3eccOrjMA==} - - '@shikijs/themes@4.0.2': - resolution: {integrity: sha512-mjCafwt8lJJaVSsQvNVrJumbnnj1RI8jbUKrPKgE6E3OvQKxnuRoBaYC51H4IGHePsGN/QtALglWBU7DoKDFnA==} - engines: {node: '>=20'} - - '@shikijs/types@3.23.0': - resolution: {integrity: sha512-3JZ5HXOZfYjsYSk0yPwBrkupyYSLpAE26Qc0HLghhZNGTZg/SKxXIIgoxOpmmeQP0RRSDJTk1/vPfw9tbw+jSQ==} - - '@shikijs/types@4.0.2': - resolution: {integrity: sha512-qzbeRooUTPnLE+sHD/Z8DStmaDgnbbc/pMrU203950aRqjX/6AFHeDYT+j00y2lPdz0ywJKx7o/7qnqTivtlXg==} - engines: {node: '>=20'} - - '@shikijs/vscode-textmate@10.0.2': - resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - - '@standard-schema/spec@1.1.0': - resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} - - '@standard-schema/utils@0.3.0': - resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} - - '@streamdown/cjk@1.0.3': - resolution: {integrity: sha512-WRg8HR/gHbBoTgsMd91OKFUClIoDcEFVofJvluvEAyjx3KpU0aGgD9tGDqHkHj14ShoMSkX0IYetWGegTcwIJw==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - - '@streamdown/code@1.1.1': - resolution: {integrity: sha512-i7HTNuDgZWb+VdrNVOam9gQhIc5MSSDXKWXgbUrn/4vSRaSMM+Rtl10MQj4wLWPNpF7p80waJsAqFP8HZfb0Jg==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - - '@streamdown/math@1.0.2': - resolution: {integrity: sha512-r8Ur9/lBuFnzZAFdEWrLUF2s/gRwRRRwruqltdZibyjbCBnuW7SJbFm26nXqvpJPW/gzpBUMrBVBzd88z05D5g==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - - '@streamdown/mermaid@1.0.2': - resolution: {integrity: sha512-Fr/4sBWnAeSnxM3PcrV/+DiZe5oPMq9gOkUIAH7ZauJeuwrZ/DVzD4g0zlav6AH0axh2m/sOfrfLtY5aLT7niw==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - - '@tabby_ai/hijri-converter@1.0.5': - resolution: {integrity: sha512-r5bClKrcIusDoo049dSL8CawnHR6mRdDwhlQuIgZRNty68q0x8k3Lf1BtPAMxRf/GgnHBnIO4ujd3+GQdLWzxQ==} - engines: {node: '>=16.0.0'} - - '@tabler/icons-react@3.41.1': - resolution: {integrity: sha512-kUgweE+DJtAlMZVIns1FTDdcbpRVnkK7ZpUOXmoxy3JAF0rSHj0TcP4VHF14+gMJGnF+psH2Zt26BLT6owetBA==} - peerDependencies: - react: '>= 16' - - '@tabler/icons@3.41.1': - resolution: {integrity: sha512-OaRnVbRmH2nHtFeg+RmMJ/7m2oBIF9XCJAUD5gQnMrpK9f05ydj8MZrAf3NZQqOXyxGN1UBL0D5IKLLEUfr74Q==} - - '@tailwindcss/node@4.2.2': - resolution: {integrity: sha512-pXS+wJ2gZpVXqFaUEjojq7jzMpTGf8rU6ipJz5ovJV6PUGmlJ+jvIwGrzdHdQ80Sg+wmQxUFuoW1UAAwHNEdFA==} - - '@tailwindcss/oxide-android-arm64@4.2.2': - resolution: {integrity: sha512-dXGR1n+P3B6748jZO/SvHZq7qBOqqzQ+yFrXpoOWWALWndF9MoSKAT3Q0fYgAzYzGhxNYOoysRvYlpixRBBoDg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [android] - - '@tailwindcss/oxide-darwin-arm64@4.2.2': - resolution: {integrity: sha512-iq9Qjr6knfMpZHj55/37ouZeykwbDqF21gPFtfnhCCKGDcPI/21FKC9XdMO/XyBM7qKORx6UIhGgg6jLl7BZlg==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [darwin] - - '@tailwindcss/oxide-darwin-x64@4.2.2': - resolution: {integrity: sha512-BlR+2c3nzc8f2G639LpL89YY4bdcIdUmiOOkv2GQv4/4M0vJlpXEa0JXNHhCHU7VWOKWT/CjqHdTP8aUuDJkuw==} - engines: {node: '>= 20'} - cpu: [x64] - os: [darwin] - - '@tailwindcss/oxide-freebsd-x64@4.2.2': - resolution: {integrity: sha512-YUqUgrGMSu2CDO82hzlQ5qSb5xmx3RUrke/QgnoEx7KvmRJHQuZHZmZTLSuuHwFf0DJPybFMXMYf+WJdxHy/nQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [freebsd] - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - resolution: {integrity: sha512-FPdhvsW6g06T9BWT0qTwiVZYE2WIFo2dY5aCSpjG/S/u1tby+wXoslXS0kl3/KXnULlLr1E3NPRRw0g7t2kgaQ==} - engines: {node: '>= 20'} - cpu: [arm] - os: [linux] - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - resolution: {integrity: sha512-4og1V+ftEPXGttOO7eCmW7VICmzzJWgMx+QXAJRAhjrSjumCwWqMfkDrNu1LXEQzNAwz28NCUpucgQPrR4S2yw==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - resolution: {integrity: sha512-oCfG/mS+/+XRlwNjnsNLVwnMWYH7tn/kYPsNPh+JSOMlnt93mYNCKHYzylRhI51X+TbR+ufNhhKKzm6QkqX8ag==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - resolution: {integrity: sha512-rTAGAkDgqbXHNp/xW0iugLVmX62wOp2PoE39BTCGKjv3Iocf6AFbRP/wZT/kuCxC9QBh9Pu8XPkv/zCZB2mcMg==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@tailwindcss/oxide-linux-x64-musl@4.2.2': - resolution: {integrity: sha512-XW3t3qwbIwiSyRCggeO2zxe3KWaEbM0/kW9e8+0XpBgyKU4ATYzcVSMKteZJ1iukJ3HgHBjbg9P5YPRCVUxlnQ==} - engines: {node: '>= 20'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - resolution: {integrity: sha512-eKSztKsmEsn1O5lJ4ZAfyn41NfG7vzCg496YiGtMDV86jz1q/irhms5O0VrY6ZwTUkFy/EKG3RfWgxSI3VbZ8Q==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - bundledDependencies: - - '@napi-rs/wasm-runtime' - - '@emnapi/core' - - '@emnapi/runtime' - - '@tybys/wasm-util' - - '@emnapi/wasi-threads' - - tslib - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - resolution: {integrity: sha512-qPmaQM4iKu5mxpsrWZMOZRgZv1tOZpUm+zdhhQP0VhJfyGGO3aUKdbh3gDZc/dPLQwW4eSqWGrrcWNBZWUWaXQ==} - engines: {node: '>= 20'} - cpu: [arm64] - os: [win32] - - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - resolution: {integrity: sha512-1T/37VvI7WyH66b+vqHj/cLwnCxt7Qt3WFu5Q8hk65aOvlwAhs7rAp1VkulBJw/N4tMirXjVnylTR72uI0HGcA==} - engines: {node: '>= 20'} - cpu: [x64] - os: [win32] - - '@tailwindcss/oxide@4.2.2': - resolution: {integrity: sha512-qEUA07+E5kehxYp9BVMpq9E8vnJuBHfJEC0vPC5e7iL/hw7HR61aDKoVoKzrG+QKp56vhNZe4qwkRmMC0zDLvg==} - engines: {node: '>= 20'} - - '@tailwindcss/postcss@4.2.2': - resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==} - - '@tailwindcss/typography@0.5.19': - resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==} - peerDependencies: - tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1' - - '@tanstack/query-core@5.95.2': - resolution: {integrity: sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==} - - '@tanstack/react-query@5.95.2': - resolution: {integrity: sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==} - peerDependencies: - react: ^18 || ^19 - - '@tauri-apps/api@2.10.1': - resolution: {integrity: sha512-hKL/jWf293UDSUN09rR69hrToyIXBb8CjGaWC7gfinvnQrBVvnLr08FeFi38gxtugAVyVcTa5/FD/Xnkb1siBw==} - - '@tauri-apps/cli-darwin-arm64@2.10.1': - resolution: {integrity: sha512-Z2OjCXiZ+fbYZy7PmP3WRnOpM9+Fy+oonKDEmUE6MwN4IGaYqgceTjwHucc/kEEYZos5GICve35f7ZiizgqEnQ==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - - '@tauri-apps/cli-darwin-x64@2.10.1': - resolution: {integrity: sha512-V/irQVvjPMGOTQqNj55PnQPVuH4VJP8vZCN7ajnj+ZS8Kom1tEM2hR3qbbIRoS3dBKs5mbG8yg1WC+97dq17Pw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - - '@tauri-apps/cli-linux-arm-gnueabihf@2.10.1': - resolution: {integrity: sha512-Hyzwsb4VnCWKGfTw+wSt15Z2pLw2f0JdFBfq2vHBOBhvg7oi6uhKiF87hmbXOBXUZaGkyRDkCHsdzJcIfoJC2w==} - engines: {node: '>= 10'} - cpu: [arm] - os: [linux] - - '@tauri-apps/cli-linux-arm64-gnu@2.10.1': - resolution: {integrity: sha512-OyOYs2t5GkBIvyWjA1+h4CZxTcdz1OZPCWAPz5DYEfB0cnWHERTnQ/SLayQzncrT0kwRoSfSz9KxenkyJoTelA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - '@tauri-apps/cli-linux-arm64-musl@2.10.1': - resolution: {integrity: sha512-MIj78PDDGjkg3NqGptDOGgfXks7SYJwhiMh8SBoZS+vfdz7yP5jN18bNaLnDhsVIPARcAhE1TlsZe/8Yxo2zqg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - libc: [musl] - - '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': - resolution: {integrity: sha512-X0lvOVUg8PCVaoEtEAnpxmnkwlE1gcMDTqfhbefICKDnOTJ5Est3qL0SrWxizDackIOKBcvtpejrSiVpuJI1kw==} - engines: {node: '>= 10'} - cpu: [riscv64] - os: [linux] - libc: [glibc] - - '@tauri-apps/cli-linux-x64-gnu@2.10.1': - resolution: {integrity: sha512-2/12bEzsJS9fAKybxgicCDFxYD1WEI9kO+tlDwX5znWG2GwMBaiWcmhGlZ8fi+DMe9CXlcVarMTYc0L3REIRxw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [glibc] - - '@tauri-apps/cli-linux-x64-musl@2.10.1': - resolution: {integrity: sha512-Y8J0ZzswPz50UcGOFuXGEMrxbjwKSPgXftx5qnkuMs2rmwQB5ssvLb6tn54wDSYxe7S6vlLob9vt0VKuNOaCIQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - libc: [musl] - - '@tauri-apps/cli-win32-arm64-msvc@2.10.1': - resolution: {integrity: sha512-iSt5B86jHYAPJa/IlYw++SXtFPGnWtFJriHn7X0NFBVunF6zu9+/zOn8OgqIWSl8RgzhLGXQEEtGBdR4wzpVgg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - - '@tauri-apps/cli-win32-ia32-msvc@2.10.1': - resolution: {integrity: sha512-gXyxgEzsFegmnWywYU5pEBURkcFN/Oo45EAwvZrHMh+zUSEAvO5E8TXsgPADYm31d1u7OQU3O3HsYfVBf2moHw==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - - '@tauri-apps/cli-win32-x64-msvc@2.10.1': - resolution: {integrity: sha512-6Cn7YpPFwzChy0ERz6djKEmUehWrYlM+xTaNzGPgZocw3BD7OfwfWHKVWxXzdjEW2KfKkHddfdxK1XXTYqBRLg==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - - '@tauri-apps/cli@2.10.1': - resolution: {integrity: sha512-jQNGF/5quwORdZSSLtTluyKQ+o6SMa/AUICfhf4egCGFdMHqWssApVgYSbg+jmrZoc8e1DscNvjTnXtlHLS11g==} - engines: {node: '>= 10'} - hasBin: true - - '@tauri-apps/plugin-dialog@2.6.0': - resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==} - - '@tauri-apps/plugin-opener@2.5.3': - resolution: {integrity: sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==} - - '@testing-library/dom@10.4.1': - resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} - engines: {node: '>=18'} - - '@testing-library/jest-dom@6.9.1': - resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} - engines: {node: '>=14', npm: '>=6', yarn: '>=1'} - - '@testing-library/react@16.3.2': - resolution: {integrity: sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==} - engines: {node: '>=18'} - peerDependencies: - '@testing-library/dom': ^10.0.0 - '@types/react': ^18.0.0 || ^19.0.0 - '@types/react-dom': ^18.0.0 || ^19.0.0 - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@testing-library/user-event@14.6.1': - resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} - engines: {node: '>=12', npm: '>=6'} - peerDependencies: - '@testing-library/dom': '>=7.21.4' - - '@tokenlens/core@1.3.0': - resolution: {integrity: sha512-d8YNHNC+q10bVpi95fELJwJyPVf1HfvBEI18eFQxRSZTdByXrP+f/ZtlhSzkx0Jl0aEmYVeBA5tPeeYRioLViQ==} - - '@tokenlens/fetch@1.3.0': - resolution: {integrity: sha512-RONDRmETYly9xO8XMKblmrZjKSwCva4s5ebJwQNfNlChZoA5kplPoCgnWceHnn1J1iRjLVlrCNB43ichfmGBKQ==} - - '@tokenlens/helpers@1.3.1': - resolution: {integrity: sha512-t6yL8N6ES8337E6eVSeH4hCKnPdWkZRFpupy9w5E66Q9IeqQ9IO7XQ6gh12JKjvWiRHuyyJ8MBP5I549Cr41EQ==} - - '@tokenlens/models@1.3.0': - resolution: {integrity: sha512-9mx7ZGeewW4ndXAiD7AT1bbCk4OpJeortbjHHyNkgap+pMPPn1chY6R5zqe1ggXIUzZ2l8VOAKfPqOvpcrisJw==} - - '@types/aria-query@5.0.4': - resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} - - '@types/babel__core@7.20.5': - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - - '@types/babel__generator@7.27.0': - resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==} - - '@types/babel__template@7.4.4': - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - - '@types/babel__traverse@7.28.0': - resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} - - '@types/chai@5.2.3': - resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} - - '@types/d3-array@3.2.2': - resolution: {integrity: sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==} - - '@types/d3-axis@3.0.6': - resolution: {integrity: sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==} - - '@types/d3-brush@3.0.6': - resolution: {integrity: sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==} - - '@types/d3-chord@3.0.6': - resolution: {integrity: sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==} - - '@types/d3-color@3.1.3': - resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} - - '@types/d3-contour@3.0.6': - resolution: {integrity: sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==} - - '@types/d3-delaunay@6.0.4': - resolution: {integrity: sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==} - - '@types/d3-dispatch@3.0.7': - resolution: {integrity: sha512-5o9OIAdKkhN1QItV2oqaE5KMIiXAvDWBDPrD85e58Qlz1c1kI/J0NcqbEG88CoTwJrYe7ntUCVfeUl2UJKbWgA==} - - '@types/d3-drag@3.0.7': - resolution: {integrity: sha512-HE3jVKlzU9AaMazNufooRJ5ZpWmLIoc90A37WU2JMmeq28w1FQqCZswHZ3xR+SuxYftzHq6WU6KJHvqxKzTxxQ==} - - '@types/d3-dsv@3.0.7': - resolution: {integrity: sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==} - - '@types/d3-ease@3.0.2': - resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} - - '@types/d3-fetch@3.0.7': - resolution: {integrity: sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==} - - '@types/d3-force@3.0.10': - resolution: {integrity: sha512-ZYeSaCF3p73RdOKcjj+swRlZfnYpK1EbaDiYICEEp5Q6sUiqFaFQ9qgoshp5CzIyyb/yD09kD9o2zEltCexlgw==} - - '@types/d3-format@3.0.4': - resolution: {integrity: sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==} - - '@types/d3-geo@3.1.0': - resolution: {integrity: sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==} - - '@types/d3-hierarchy@3.1.7': - resolution: {integrity: sha512-tJFtNoYBtRtkNysX1Xq4sxtjK8YgoWUNpIiUee0/jHGRwqvzYxkq0hGVbbOGSz+JgFxxRu4K8nb3YpG3CMARtg==} - - '@types/d3-interpolate@3.0.4': - resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} - - '@types/d3-path@3.1.1': - resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} - - '@types/d3-polygon@3.0.2': - resolution: {integrity: sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==} - - '@types/d3-quadtree@3.0.6': - resolution: {integrity: sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==} - - '@types/d3-random@3.0.3': - resolution: {integrity: sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==} - - '@types/d3-scale-chromatic@3.1.0': - resolution: {integrity: sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ==} - - '@types/d3-scale@4.0.9': - resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} - - '@types/d3-selection@3.0.11': - resolution: {integrity: sha512-bhAXu23DJWsrI45xafYpkQ4NtcKMwWnAC/vKrd2l+nxMFuvOT3XMYTIj2opv8vq8AO5Yh7Qac/nSeP/3zjTK0w==} - - '@types/d3-shape@3.1.8': - resolution: {integrity: sha512-lae0iWfcDeR7qt7rA88BNiqdvPS5pFVPpo5OfjElwNaT2yyekbM0C9vK+yqBqEmHr6lDkRnYNoTBYlAgJa7a4w==} - - '@types/d3-time-format@4.0.3': - resolution: {integrity: sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==} - - '@types/d3-time@3.0.4': - resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} - - '@types/d3-timer@3.0.2': - resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} - - '@types/d3-transition@3.0.9': - resolution: {integrity: sha512-uZS5shfxzO3rGlu0cC3bjmMFKsXv+SmZZcgp0KD22ts4uGXp5EVYGzu/0YdwZeKmddhcAccYtREJKkPfXkZuCg==} - - '@types/d3-zoom@3.0.8': - resolution: {integrity: sha512-iqMC4/YlFCSlO8+2Ii1GGGliCAY4XdeG748w5vQUbevlbDu0zSjH/+jojorQVBK/se0j6DUFNPBGSqD3YWYnDw==} - - '@types/d3@7.4.3': - resolution: {integrity: sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==} - - '@types/debug@4.1.13': - resolution: {integrity: sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==} - - '@types/deep-eql@4.0.2': - resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} - - '@types/estree-jsx@1.0.5': - resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} - - '@types/estree@1.0.8': - resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} - - '@types/geojson@7946.0.16': - resolution: {integrity: sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==} - - '@types/hast@3.0.4': - resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - - '@types/katex@0.16.8': - resolution: {integrity: sha512-trgaNyfU+Xh2Tc+ABIb44a5AYUpicB3uwirOioeOkNPPbmgRNtcWyDeeFRzjPZENO9Vq8gvVqfhaaXWLlevVwg==} - - '@types/mdast@4.0.4': - resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} - - '@types/ms@2.1.0': - resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - - '@types/prismjs@1.26.6': - resolution: {integrity: sha512-vqlvI7qlMvcCBbVe0AKAb4f97//Hy0EBTaiW8AalRnG/xAN5zOiWWyrNqNXeq8+KAuvRewjCVY1+IPxk4RdNYw==} - - '@types/prop-types@15.7.15': - resolution: {integrity: sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==} - - '@types/react-dom@18.3.7': - resolution: {integrity: sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==} - peerDependencies: - '@types/react': ^18.0.0 - - '@types/react-dom@19.2.3': - resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} - peerDependencies: - '@types/react': ^19.2.0 - - '@types/react-syntax-highlighter@15.5.13': - resolution: {integrity: sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA==} - - '@types/react@18.3.28': - resolution: {integrity: sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==} - - '@types/react@19.2.14': - resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} - - '@types/trusted-types@2.0.7': - resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} - - '@types/unist@2.0.11': - resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} - - '@types/unist@3.0.3': - resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} - - '@types/use-sync-external-store@0.0.6': - resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - - '@ungap/structured-clone@1.3.0': - resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} - - '@upsetjs/venn.js@2.0.0': - resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==} - - '@vercel/oidc@3.1.0': - resolution: {integrity: sha512-Fw28YZpRnA3cAHHDlkt7xQHiJ0fcL+NRcIqsocZQUSmbzeIKRpwttJjik5ZGanXP+vlA4SbTg+AbA3bP363l+w==} - engines: {node: '>= 20'} - - '@vitejs/plugin-react@4.7.0': - resolution: {integrity: sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==} - engines: {node: ^14.18.0 || >=16.0.0} - peerDependencies: - vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 - - '@vitest/expect@4.1.2': - resolution: {integrity: sha512-gbu+7B0YgUJ2nkdsRJrFFW6X7NTP44WlhiclHniUhxADQJH5Szt9mZ9hWnJPJ8YwOK5zUOSSlSvyzRf0u1DSBQ==} - - '@vitest/mocker@4.1.2': - resolution: {integrity: sha512-Ize4iQtEALHDttPRCmN+FKqOl2vxTiNUhzobQFFt/BM1lRUTG7zRCLOykG/6Vo4E4hnUdfVLo5/eqKPukcWW7Q==} - peerDependencies: - msw: ^2.4.9 - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - msw: - optional: true - vite: - optional: true - - '@vitest/pretty-format@4.1.2': - resolution: {integrity: sha512-dwQga8aejqeuB+TvXCMzSQemvV9hNEtDDpgUKDzOmNQayl2OG241PSWeJwKRH3CiC+sESrmoFd49rfnq7T4RnA==} - - '@vitest/runner@4.1.2': - resolution: {integrity: sha512-Gr+FQan34CdiYAwpGJmQG8PgkyFVmARK8/xSijia3eTFgVfpcpztWLuP6FttGNfPLJhaZVP/euvujeNYar36OQ==} - - '@vitest/snapshot@4.1.2': - resolution: {integrity: sha512-g7yfUmxYS4mNxk31qbOYsSt2F4m1E02LFqO53Xpzg3zKMhLAPZAjjfyl9e6z7HrW6LvUdTwAQR3HHfLjpko16A==} - - '@vitest/spy@4.1.2': - resolution: {integrity: sha512-DU4fBnbVCJGNBwVA6xSToNXrkZNSiw59H8tcuUspVMsBDBST4nfvsPsEHDHGtWRRnqBERBQu7TrTKskmjqTXKA==} - - '@vitest/utils@4.1.2': - resolution: {integrity: sha512-xw2/TiX82lQHA06cgbqRKFb5lCAy3axQ4H4SoUFhUsg+wztiet+co86IAMDtF6Vm1hc7J6j09oh/rgDn+JdKIQ==} - - '@xyflow/react@12.10.2': - resolution: {integrity: sha512-CgIi6HwlcHXwlkTpr0fxLv/0sRVNZ8IdwKLzzeCscaYBwpvfcH1QFOCeaTCuEn1FQEs/B8CjnTSjhs8udgmBgQ==} - peerDependencies: - react: '>=17' - react-dom: '>=17' - - '@xyflow/system@0.0.76': - resolution: {integrity: sha512-hvwvnRS1B3REwVDlWexsq7YQaPZeG3/mKo1jv38UmnpWmxihp14bW6VtEOuHEwJX2FvzFw8k77LyKSk/wiZVNA==} - - acorn-jsx@5.3.2: - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - - acorn@8.16.0: - resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} - engines: {node: '>=0.4.0'} - hasBin: true - - agent-base@7.1.4: - resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} - engines: {node: '>= 14'} - - ai@6.0.142: - resolution: {integrity: sha512-ZoxAsnTL/dFg5WdcwC8QNhKVlLtqwwT3I7p/4i8IJJP+6ZwqF1ljuwMsAsPYYvppZ+RzUxjxxFGb1cbEhNH3dg==} - engines: {node: '>=18'} - peerDependencies: - zod: ^3.25.76 || ^4.1.8 - - anser@2.3.5: - resolution: {integrity: sha512-vcZjxvvVoxTeR5XBNJB38oTu/7eDCZlwdz32N1eNgpyPF7j/Z7Idf+CUwQOkKKpJ7RJyjxgLHCM7vdIK0iCNMQ==} - - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - - ansi-to-react@6.2.6: - resolution: {integrity: sha512-Eqi0iaMK5OZ3jsVFxWvU2B74UZBnGuHlkflKMX6wTOeH+luy9KE2O0gUkc2PxhIP1R4IO0xohv62UMFInQOSeg==} - peerDependencies: - react: ^16.3.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.3.2 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - aria-hidden@1.2.6: - resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} - engines: {node: '>=10'} - - aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - - assertion-error@2.0.1: - resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} - engines: {node: '>=12'} - - bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - - baseline-browser-mapping@2.10.12: - resolution: {integrity: sha512-qyq26DxfY4awP2gIRXhhLWfwzwI+N5Nxk6iQi8EFizIaWIjqicQTE4sLnZZVdeKPRcVNoJOkkpfzoIYuvCKaIQ==} - engines: {node: '>=6.0.0'} - hasBin: true - - browserslist@4.28.1: - resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - - caniuse-lite@1.0.30001781: - resolution: {integrity: sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==} - - ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - - ce-la-react@0.3.2: - resolution: {integrity: sha512-QJ6k4lOD/btI08xG8jBPxRCGXvCnusGGkTsiXk0u3NqUu/W+BXRnFD4PYjwtqh8AWmGa5LDbGk0fLQsqr0nSMA==} - peerDependencies: - react: '>=17.0.0' - - chai@6.2.2: - resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} - engines: {node: '>=18'} - - character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - - character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - - character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - - character-reference-invalid@2.0.1: - resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} - - chevrotain-allstar@0.3.1: - resolution: {integrity: sha512-b7g+y9A0v4mxCW1qUhf3BSVPg+/NvGErk/dOkrDaHA0nQIQGAtrOjlX//9OQtRlSCy+x9rfB5N8yC71lH1nvMw==} - peerDependencies: - chevrotain: ^11.0.0 - - chevrotain@11.1.2: - resolution: {integrity: sha512-opLQzEVriiH1uUQ4Kctsd49bRoFDXGGSC4GUqj7pGyxM3RehRhvTlZJc1FL/Flew2p5uwxa1tUDWKzI4wNM8pg==} - - class-variance-authority@0.7.1: - resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} - - classcat@5.0.5: - resolution: {integrity: sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==} - - clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - - cmdk@1.1.1: - resolution: {integrity: sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==} - peerDependencies: - react: ^18 || ^19 || ^19.0.0-rc - react-dom: ^18 || ^19 || ^19.0.0-rc - - comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - - commander@7.2.0: - resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} - engines: {node: '>= 10'} - - commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - - confbox@0.1.8: - resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} - - convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - - cose-base@1.0.3: - resolution: {integrity: sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg==} - - cose-base@2.2.0: - resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} - - css.escape@1.5.1: - resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} - - cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - - cssstyle@4.6.0: - resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} - engines: {node: '>=18'} - - csstype@3.2.3: - resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} - - cytoscape-cose-bilkent@4.1.0: - resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} - peerDependencies: - cytoscape: ^3.2.0 - - cytoscape-fcose@2.2.0: - resolution: {integrity: sha512-ki1/VuRIHFCzxWNrsshHYPs6L7TvLu3DL+TyIGEsRcvVERmxokbf5Gdk7mFxZnTdiGtnA4cfSmjZJMviqSuZrQ==} - peerDependencies: - cytoscape: ^3.2.0 - - cytoscape@3.33.1: - resolution: {integrity: sha512-iJc4TwyANnOGR1OmWhsS9ayRS3s+XQ185FmuHObThD+5AeJCakAAbWv8KimMTt08xCCLNgneQwFp+JRJOr9qGQ==} - engines: {node: '>=0.10'} - - d3-array@2.12.1: - resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} - - d3-array@3.2.4: - resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} - engines: {node: '>=12'} - - d3-axis@3.0.0: - resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==} - engines: {node: '>=12'} - - d3-brush@3.0.0: - resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==} - engines: {node: '>=12'} - - d3-chord@3.0.1: - resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==} - engines: {node: '>=12'} - - d3-color@3.1.0: - resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} - engines: {node: '>=12'} - - d3-contour@4.0.2: - resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==} - engines: {node: '>=12'} - - d3-delaunay@6.0.4: - resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==} - engines: {node: '>=12'} - - d3-dispatch@3.0.1: - resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==} - engines: {node: '>=12'} - - d3-drag@3.0.0: - resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==} - engines: {node: '>=12'} - - d3-dsv@3.0.1: - resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==} - engines: {node: '>=12'} - hasBin: true - - d3-ease@3.0.1: - resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} - engines: {node: '>=12'} - - d3-fetch@3.0.1: - resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==} - engines: {node: '>=12'} - - d3-force@3.0.0: - resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==} - engines: {node: '>=12'} - - d3-format@3.1.2: - resolution: {integrity: sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==} - engines: {node: '>=12'} - - d3-geo@3.1.1: - resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==} - engines: {node: '>=12'} - - d3-hierarchy@3.1.2: - resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==} - engines: {node: '>=12'} - - d3-interpolate@3.0.1: - resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} - engines: {node: '>=12'} - - d3-path@1.0.9: - resolution: {integrity: sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==} - - d3-path@3.1.0: - resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} - engines: {node: '>=12'} - - d3-polygon@3.0.1: - resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==} - engines: {node: '>=12'} - - d3-quadtree@3.0.1: - resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==} - engines: {node: '>=12'} - - d3-random@3.0.1: - resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==} - engines: {node: '>=12'} - - d3-sankey@0.12.3: - resolution: {integrity: sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ==} - - d3-scale-chromatic@3.1.0: - resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==} - engines: {node: '>=12'} - - d3-scale@4.0.2: - resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} - engines: {node: '>=12'} - - d3-selection@3.0.0: - resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==} - engines: {node: '>=12'} - - d3-shape@1.3.7: - resolution: {integrity: sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==} - - d3-shape@3.2.0: - resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} - engines: {node: '>=12'} - - d3-time-format@4.1.0: - resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} - engines: {node: '>=12'} - - d3-time@3.1.0: - resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} - engines: {node: '>=12'} - - d3-timer@3.0.1: - resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} - engines: {node: '>=12'} - - d3-transition@3.0.1: - resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==} - engines: {node: '>=12'} - peerDependencies: - d3-selection: 2 - 3 - - d3-zoom@3.0.0: - resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==} - engines: {node: '>=12'} - - d3@7.9.0: - resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==} - engines: {node: '>=12'} - - dagre-d3-es@7.0.14: - resolution: {integrity: sha512-P4rFMVq9ESWqmOgK+dlXvOtLwYg0i7u0HBGJER0LZDJT2VHIPAMZ/riPxqJceWMStH5+E61QxFra9kIS3AqdMg==} - - data-urls@5.0.0: - resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} - engines: {node: '>=18'} - - date-fns-jalali@4.1.0-0: - resolution: {integrity: sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg==} - - date-fns@4.1.0: - resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} - - dayjs@1.11.20: - resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} - - debug@4.4.3: - resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - - decimal.js-light@2.5.1: - resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} - - decimal.js@10.6.0: - resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} - - decode-named-character-reference@1.3.0: - resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} - - delaunator@5.1.0: - resolution: {integrity: sha512-AGrQ4QSgssa1NGmWmLPqN5NY2KajF5MqxetNEO+o0n3ZwZZeTmt7bBnvzHWrmkZFxGgr4HdyFgelzgi06otLuQ==} - - dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - - detect-libc@2.1.2: - resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} - engines: {node: '>=8'} - - detect-node-es@1.1.0: - resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} - - devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} - - dom-accessibility-api@0.5.16: - resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} - - dom-accessibility-api@0.6.3: - resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} - - dompurify@3.3.3: - resolution: {integrity: sha512-Oj6pzI2+RqBfFG+qOaOLbFXLQ90ARpcGG6UePL82bJLtdsa6CYJD7nmiU8MW9nQNOtCHV3lZ/Bzq1X0QYbBZCA==} - - electron-to-chromium@1.5.328: - resolution: {integrity: sha512-QNQ5l45DzYytThO21403XN3FvK0hOkWDG8viNf6jqS42msJ8I4tGDSpBCgvDRRPnkffafiwAym2X2eHeGD2V0w==} - - embla-carousel-react@8.6.0: - resolution: {integrity: sha512-0/PjqU7geVmo6F734pmPqpyHqiM99olvyecY7zdweCw+6tKEXnrE90pBiBbMMU8s5tICemzpQ3hi5EpxzGW+JA==} - peerDependencies: - react: ^16.8.0 || ^17.0.1 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - - embla-carousel-reactive-utils@8.6.0: - resolution: {integrity: sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A==} - peerDependencies: - embla-carousel: 8.6.0 - - embla-carousel@8.6.0: - resolution: {integrity: sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA==} - - enhanced-resolve@5.20.1: - resolution: {integrity: sha512-Qohcme7V1inbAfvjItgw0EaxVX5q2rdVEZHRBrEQdRZTssLDGsL8Lwrznl8oQ/6kuTJONLaDcGjkNP247XEhcA==} - engines: {node: '>=10.13.0'} - - entities@6.0.1: - resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} - engines: {node: '>=0.12'} - - es-module-lexer@2.0.0: - resolution: {integrity: sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==} - - es-toolkit@1.45.1: - resolution: {integrity: sha512-/jhoOj/Fx+A+IIyDNOvO3TItGmlMKhtX8ISAHKE90c4b/k1tqaqEZ+uUqfpU8DMnW5cgNJv606zS55jGvza0Xw==} - - esbuild@0.27.4: - resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} - engines: {node: '>=18'} - hasBin: true - - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - - escape-carriage@1.3.1: - resolution: {integrity: sha512-GwBr6yViW3ttx1kb7/Oh+gKQ1/TrhYwxKqVmg5gS+BK+Qe2KrOa/Vh7w3HPBvgGf0LfcDGoY9I6NHKoA5Hozhw==} - - escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - - estree-util-is-identifier-name@3.0.0: - resolution: {integrity: sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==} - - estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} - - eventemitter3@5.0.4: - resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} - - eventsource-parser@3.0.6: - resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==} - engines: {node: '>=18.0.0'} - - expect-type@1.3.0: - resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} - engines: {node: '>=12.0.0'} - - extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - - fault@1.0.4: - resolution: {integrity: sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA==} - - fdir@6.5.0: - resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} - engines: {node: '>=12.0.0'} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - - format@0.2.2: - resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} - engines: {node: '>=0.4.x'} - - framer-motion@12.38.0: - resolution: {integrity: sha512-rFYkY/pigbcswl1XQSb7q424kSTQ8q6eAC+YUsSKooHQYuLdzdHjrt6uxUC+PRAO++q5IS7+TamgIw1AphxR+g==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - fsevents@2.3.2: - resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - - get-east-asian-width@1.5.0: - resolution: {integrity: sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==} - engines: {node: '>=18'} - - get-nonce@1.0.1: - resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} - engines: {node: '>=6'} - - get-tsconfig@4.13.7: - resolution: {integrity: sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q==} - - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - gsap@3.14.2: - resolution: {integrity: sha512-P8/mMxVLU7o4+55+1TCnQrPmgjPKnwkzkXOK1asnR9Jg2lna4tEY5qBJjMmAaOBDDZWtlRjBXjLa0w53G/uBLA==} - - hachure-fill@0.5.2: - resolution: {integrity: sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg==} - - hast-util-from-dom@5.0.1: - resolution: {integrity: sha512-N+LqofjR2zuzTjCPzyDUdSshy4Ma6li7p/c3pA78uTwzFgENbgbUrm2ugwsOdcjI1muO+o6Dgzp9p8WHtn/39Q==} - - hast-util-from-html-isomorphic@2.0.0: - resolution: {integrity: sha512-zJfpXq44yff2hmE0XmwEOzdWin5xwH+QIhMLOScpX91e/NSGPsAzNCvLQDIEPyO2TXi+lBmU6hjLIhV8MwP2kw==} - - hast-util-from-html@2.0.3: - resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} - - hast-util-from-parse5@8.0.3: - resolution: {integrity: sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==} - - hast-util-is-element@3.0.0: - resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} - - hast-util-parse-selector@4.0.0: - resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} - - hast-util-raw@9.1.0: - resolution: {integrity: sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==} - - hast-util-sanitize@5.0.2: - resolution: {integrity: sha512-3yTWghByc50aGS7JlGhk61SPenfE/p1oaFeNwkOOyrscaOkMGrcW9+Cy/QAIOBpZxP1yqDIzFMR0+Np0i0+usg==} - - hast-util-to-html@9.0.5: - resolution: {integrity: sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==} - - hast-util-to-jsx-runtime@2.3.6: - resolution: {integrity: sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==} - - hast-util-to-parse5@8.0.1: - resolution: {integrity: sha512-MlWT6Pjt4CG9lFCjiz4BH7l9wmrMkfkJYCxFwKQic8+RTZgWPuWxwAfjJElsXkex7DJjfSJsQIt931ilUgmwdA==} - - hast-util-to-text@4.0.2: - resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} - - hast-util-whitespace@3.0.0: - resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} - - hastscript@9.0.1: - resolution: {integrity: sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==} - - highlight.js@10.7.3: - resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - - highlightjs-vue@1.0.0: - resolution: {integrity: sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA==} - - html-encoding-sniffer@4.0.0: - resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} - engines: {node: '>=18'} - - html-parse-stringify@3.0.1: - resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} - - html-url-attributes@3.0.1: - resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} - - html-void-elements@3.0.0: - resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.6: - resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} - engines: {node: '>= 14'} - - i18next-resources-to-backend@1.2.1: - resolution: {integrity: sha512-okHbVA+HZ7n1/76MsfhPqDou0fptl2dAlhRDu2ideXloRRduzHsqDOznJBef+R3DFZnbvWoBW+KxJ7fnFjd6Yw==} - - i18next@26.0.3: - resolution: {integrity: sha512-1571kXINxHKY7LksWp8wP+zP0YqHSSpl/OW0Y0owFEf2H3s8gCAffWaZivcz14rMkOvn3R/psiQxVsR9t2Nafg==} - peerDependencies: - typescript: ^5 || ^6 - peerDependenciesMeta: - typescript: - optional: true - - iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - - immer@10.2.0: - resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==} - - immer@11.1.4: - resolution: {integrity: sha512-XREFCPo6ksxVzP4E0ekD5aMdf8WMwmdNaz6vuvxgI40UaEiu6q3p8X52aU6GdyvLY3XXX/8R7JOTXStz/nBbRw==} - - indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - inline-style-parser@0.2.7: - resolution: {integrity: sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==} - - input-otp@1.4.2: - resolution: {integrity: sha512-l3jWwYNvrEa6NTCt7BECfCm48GvwuZzkoeG3gBL2w4CHeOXW3eKFmf9UNYkNfYc3mxMrthMnxjIE07MT0zLBQA==} - peerDependencies: - react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - - internmap@1.0.1: - resolution: {integrity: sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==} - - internmap@2.0.3: - resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} - engines: {node: '>=12'} - - is-alphabetical@2.0.1: - resolution: {integrity: sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==} - - is-alphanumerical@2.0.1: - resolution: {integrity: sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==} - - is-decimal@2.0.1: - resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} - - is-hexadecimal@2.0.1: - resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} - - is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - - is-potential-custom-element-name@1.0.1: - resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} - - jiti@2.6.1: - resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} - hasBin: true - - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - - jsdom@26.1.0: - resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} - engines: {node: '>=18'} - peerDependencies: - canvas: ^3.0.0 - peerDependenciesMeta: - canvas: - optional: true - - jsesc@3.1.0: - resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} - engines: {node: '>=6'} - hasBin: true - - json-schema@0.4.0: - resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} - - json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - - katex@0.16.44: - resolution: {integrity: sha512-EkxoDTk8ufHqHlf9QxGwcxeLkWRR3iOuYfRpfORgYfqc8s13bgb+YtRY59NK5ZpRaCwq1kqA6a5lpX8C/eLphQ==} - hasBin: true - - khroma@2.1.0: - resolution: {integrity: sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw==} - - langium@4.2.1: - resolution: {integrity: sha512-zu9QWmjpzJcomzdJQAHgDVhLGq5bLosVak1KVa40NzQHXfqr4eAHupvnPOVXEoLkg6Ocefvf/93d//SB7du4YQ==} - engines: {node: '>=20.10.0', npm: '>=10.2.3'} - - layout-base@1.0.2: - resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} - - layout-base@2.0.1: - resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - - lightningcss-android-arm64@1.32.0: - resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [android] - - lightningcss-darwin-arm64@1.32.0: - resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [darwin] - - lightningcss-darwin-x64@1.32.0: - resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [darwin] - - lightningcss-freebsd-x64@1.32.0: - resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [freebsd] - - lightningcss-linux-arm-gnueabihf@1.32.0: - resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} - engines: {node: '>= 12.0.0'} - cpu: [arm] - os: [linux] - - lightningcss-linux-arm64-gnu@1.32.0: - resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [glibc] - - lightningcss-linux-arm64-musl@1.32.0: - resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [linux] - libc: [musl] - - lightningcss-linux-x64-gnu@1.32.0: - resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [glibc] - - lightningcss-linux-x64-musl@1.32.0: - resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [linux] - libc: [musl] - - lightningcss-win32-arm64-msvc@1.32.0: - resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} - engines: {node: '>= 12.0.0'} - cpu: [arm64] - os: [win32] - - lightningcss-win32-x64-msvc@1.32.0: - resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} - engines: {node: '>= 12.0.0'} - cpu: [x64] - os: [win32] - - lightningcss@1.32.0: - resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} - engines: {node: '>= 12.0.0'} - - linkify-it@3.0.3: - resolution: {integrity: sha512-ynTsyrFSdE5oZ/O9GEf00kPngmOfVwazR5GKDq6EYfhlpFug3J2zybX56a2PRRpc9P+FuSoGNAwjlbDs9jJBPQ==} - - lodash-es@4.17.23: - resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} - - longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - - lowlight@1.20.0: - resolution: {integrity: sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw==} - - lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - - lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - - lucide-react@0.577.0: - resolution: {integrity: sha512-4LjoFv2eEPwYDPg/CUdBJQSDfPyzXCRrVW1X7jrx/trgxnxkHFjnVZINbzvzxjN70dxychOfg+FTYwBiS3pQ5A==} - peerDependencies: - react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - lz-string@1.5.0: - resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} - hasBin: true - - magic-string@0.30.21: - resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} - - markdown-table@3.0.4: - resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} - - marked@16.4.2: - resolution: {integrity: sha512-TI3V8YYWvkVf3KJe1dRkpnjs68JUPyEa5vjKrp1XEEJUAOaQc+Qj+L1qWbPd0SJuAdQkFU0h73sXXqwDYxsiDA==} - engines: {node: '>= 20'} - hasBin: true - - marked@17.0.5: - resolution: {integrity: sha512-6hLvc0/JEbRjRgzI6wnT2P1XuM1/RrrDEX0kPt0N7jGm1133g6X7DlxFasUIx+72aKAr904GTxhSLDrd5DIlZg==} - engines: {node: '>= 20'} - hasBin: true - - mdast-util-find-and-replace@3.0.2: - resolution: {integrity: sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==} - - mdast-util-from-markdown@2.0.3: - resolution: {integrity: sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==} - - mdast-util-gfm-autolink-literal@2.0.1: - resolution: {integrity: sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==} - - mdast-util-gfm-footnote@2.1.0: - resolution: {integrity: sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==} - - mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} - - mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} - - mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} - - mdast-util-gfm@3.1.0: - resolution: {integrity: sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==} - - mdast-util-math@3.0.0: - resolution: {integrity: sha512-Tl9GBNeG/AhJnQM221bJR2HPvLOSnLE/T9cJI9tlc6zwQk2nPk/4f0cHkOdEixQPC/j8UtKDdITswvLAy1OZ1w==} - - mdast-util-mdx-expression@2.0.1: - resolution: {integrity: sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==} - - mdast-util-mdx-jsx@3.2.0: - resolution: {integrity: sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==} - - mdast-util-mdxjs-esm@2.0.1: - resolution: {integrity: sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==} - - mdast-util-newline-to-break@2.0.0: - resolution: {integrity: sha512-MbgeFca0hLYIEx/2zGsszCSEJJ1JSCdiY5xQxRcLDDGa8EPvlLPupJ4DSajbMPAnC0je8jfb9TiUATnxxrHUog==} - - mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} - - mdast-util-to-hast@13.2.1: - resolution: {integrity: sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==} - - mdast-util-to-markdown@2.1.2: - resolution: {integrity: sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==} - - mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} - - media-chrome@4.18.3: - resolution: {integrity: sha512-YuS2wY0Fn+2nXGijJYn4+IE0n9wFe3v6SvOZHGNkoxh32T/cCcrXHUWskA+9tyYTONa6JKwKAOJJeO6QOlJLKw==} - - mermaid@11.14.0: - resolution: {integrity: sha512-GSGloRsBs+JINmmhl0JDwjpuezCsHB4WGI4NASHxL3fHo3o/BRXTxhDLKnln8/Q0lRFRyDdEjmk1/d5Sn1Xz8g==} - - micromark-core-commonmark@2.0.3: - resolution: {integrity: sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==} - - micromark-extension-cjk-friendly-gfm-strikethrough@2.0.1: - resolution: {integrity: sha512-wVC0zwjJNqQeX+bb07YTPu/CvSAyCTafyYb7sMhX1r62/Lw5M/df3JyYaANyp8g15c1ypJRFSsookTqA1IDsUg==} - engines: {node: '>=18'} - peerDependencies: - micromark: ^4.0.0 - micromark-util-types: ^2.0.0 - peerDependenciesMeta: - micromark-util-types: - optional: true - - micromark-extension-cjk-friendly-util@3.0.1: - resolution: {integrity: sha512-GcbXqTTHOsiZHyF753oIddP/J2eH8j9zpyQPhkof6B2JNxfEJabnQqxbCgzJNuNes0Y2jTNJ3LiYPSXr6eJA8w==} - engines: {node: '>=18'} - peerDependencies: - micromark-util-types: '*' - peerDependenciesMeta: - micromark-util-types: - optional: true - - micromark-extension-cjk-friendly@2.0.1: - resolution: {integrity: sha512-OkzoYVTL1ChbvQ8Cc1ayTIz7paFQz8iS9oIYmewncweUSwmWR+hkJF9spJ1lxB90XldJl26A1F4IkPOKS3bDXw==} - engines: {node: '>=18'} - peerDependencies: - micromark: ^4.0.0 - micromark-util-types: ^2.0.0 - peerDependenciesMeta: - micromark-util-types: - optional: true - - micromark-extension-gfm-autolink-literal@2.1.0: - resolution: {integrity: sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==} - - micromark-extension-gfm-footnote@2.1.0: - resolution: {integrity: sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==} - - micromark-extension-gfm-strikethrough@2.1.0: - resolution: {integrity: sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==} - - micromark-extension-gfm-table@2.1.1: - resolution: {integrity: sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==} - - micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} - - micromark-extension-gfm-task-list-item@2.1.0: - resolution: {integrity: sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==} - - micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} - - micromark-extension-math@3.1.0: - resolution: {integrity: sha512-lvEqd+fHjATVs+2v/8kg9i5Q0AP2k85H0WUOwpIVvUML8BapsMvh1XAogmQjOCsLpoKRCVQqEkQBB3NhVBcsOg==} - - micromark-factory-destination@2.0.1: - resolution: {integrity: sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==} - - micromark-factory-label@2.0.1: - resolution: {integrity: sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==} - - micromark-factory-space@2.0.1: - resolution: {integrity: sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==} - - micromark-factory-title@2.0.1: - resolution: {integrity: sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==} - - micromark-factory-whitespace@2.0.1: - resolution: {integrity: sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==} - - micromark-util-character@2.1.1: - resolution: {integrity: sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==} - - micromark-util-chunked@2.0.1: - resolution: {integrity: sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==} - - micromark-util-classify-character@2.0.1: - resolution: {integrity: sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==} - - micromark-util-combine-extensions@2.0.1: - resolution: {integrity: sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==} - - micromark-util-decode-numeric-character-reference@2.0.2: - resolution: {integrity: sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==} - - micromark-util-decode-string@2.0.1: - resolution: {integrity: sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==} - - micromark-util-encode@2.0.1: - resolution: {integrity: sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==} - - micromark-util-html-tag-name@2.0.1: - resolution: {integrity: sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==} - - micromark-util-normalize-identifier@2.0.1: - resolution: {integrity: sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==} - - micromark-util-resolve-all@2.0.1: - resolution: {integrity: sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==} - - micromark-util-sanitize-uri@2.0.1: - resolution: {integrity: sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==} - - micromark-util-subtokenize@2.1.0: - resolution: {integrity: sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==} - - micromark-util-symbol@2.0.1: - resolution: {integrity: sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==} - - micromark-util-types@2.0.2: - resolution: {integrity: sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==} - - micromark@4.0.2: - resolution: {integrity: sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==} - - min-indent@1.0.1: - resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} - engines: {node: '>=4'} - - mlly@1.8.2: - resolution: {integrity: sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==} - - motion-dom@12.38.0: - resolution: {integrity: sha512-pdkHLD8QYRp8VfiNLb8xIBJis1byQ9gPT3Jnh2jqfFtAsWUA3dEepDlsWe/xMpO8McV+VdpKVcp+E+TGJEtOoA==} - - motion-utils@12.36.0: - resolution: {integrity: sha512-eHWisygbiwVvf6PZ1vhaHCLamvkSbPIeAYxWUuL3a2PD/TROgE7FvfHWTIH4vMl798QLfMw15nRqIaRDXTlYRg==} - - motion@12.38.0: - resolution: {integrity: sha512-uYfXzeHlgThchzwz5Te47dlv5JOUC7OB4rjJ/7XTUgtBZD8CchMN8qEJ4ZVsUmTyYA44zjV0fBwsiktRuFnn+w==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - - ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - nanoid@3.3.11: - resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - nanoid@5.1.7: - resolution: {integrity: sha512-ua3NDgISf6jdwezAheMOk4mbE1LXjm1DfMUDMuJf4AqxLFK3ccGpgWizwa5YV7Yz9EpXwEaWoRXSb/BnV0t5dQ==} - engines: {node: ^18 || >=20} - hasBin: true - - next-themes@0.4.6: - resolution: {integrity: sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA==} - peerDependencies: - react: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - react-dom: ^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc - - node-releases@2.0.36: - resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} - - nwsapi@2.2.23: - resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} - - obug@2.1.1: - resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} - - oniguruma-parser@0.12.1: - resolution: {integrity: sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==} - - oniguruma-to-es@4.3.5: - resolution: {integrity: sha512-Zjygswjpsewa0NLTsiizVuMQZbp0MDyM6lIt66OxsF21npUDlzpHi1Mgb/qhQdkb+dWFTzJmFbEWdvZgRho8eQ==} - - package-manager-detector@1.6.0: - resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} - - parse-entities@4.0.2: - resolution: {integrity: sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==} - - parse5@7.3.0: - resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} - - path-data-parser@0.1.0: - resolution: {integrity: sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w==} - - pathe@2.0.3: - resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - - picomatch@4.0.4: - resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} - engines: {node: '>=12'} - - pkg-types@1.3.1: - resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} - - playwright-core@1.58.2: - resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} - engines: {node: '>=18'} - hasBin: true - - playwright@1.58.2: - resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==} - engines: {node: '>=18'} - hasBin: true - - points-on-curve@0.2.0: - resolution: {integrity: sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A==} - - points-on-path@0.2.1: - resolution: {integrity: sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g==} - - postcss-selector-parser@6.0.10: - resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==} - engines: {node: '>=4'} - - postcss@8.5.8: - resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} - engines: {node: ^10 || ^12 || >=14} - - pretty-format@27.5.1: - resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} - engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} - - prismjs@1.30.0: - resolution: {integrity: sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==} - engines: {node: '>=6'} - - property-information@7.1.0: - resolution: {integrity: sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==} - - punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - - react-day-picker@9.14.0: - resolution: {integrity: sha512-tBaoDWjPwe0M5pGrum4H0SR6Lyk+BO9oHnp9JbKpGKW2mlraNPgP9BMfsg5pWpwrssARmeqk7YBl2oXutZTaHA==} - engines: {node: '>=18'} - peerDependencies: - react: '>=16.8.0' - - react-dom@19.2.4: - resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} - peerDependencies: - react: ^19.2.4 - - react-hook-form@7.72.0: - resolution: {integrity: sha512-V4v6jubaf6JAurEaVnT9aUPKFbNtDgohj5CIgVGyPHvT9wRx5OZHVjz31GsxnPNI278XMu+ruFz+wGOscHaLKw==} - engines: {node: '>=18.0.0'} - peerDependencies: - react: ^16.8.0 || ^17 || ^18 || ^19 - - react-i18next@17.0.2: - resolution: {integrity: sha512-shBftH2vaTWK2Bsp7FiL+cevx3xFJlvFxmsDFQSrJc+6twHkP0tv/bGa01VVWzpreUVVwU+3Hev5iFqRg65RwA==} - peerDependencies: - i18next: '>= 26.0.1' - react: '>= 16.8.0' - react-dom: '*' - react-native: '*' - typescript: ^5 || ^6 - peerDependenciesMeta: - react-dom: - optional: true - react-native: - optional: true - typescript: - optional: true - - react-is@17.0.2: - resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - - react-jsx-parser@2.4.1: - resolution: {integrity: sha512-gE25DiHseuKmSbb5O1K1IkyQ/bwth3zl4z3EdW8XMhwrb2agUpuh8GvqHFvGwh/wdZjDDuadGrSR2lEgjcOvqQ==} - engines: {bun: ^1.1.27} - peerDependencies: - react: '>=18' - react-dom: '>=18' - - react-markdown@10.1.0: - resolution: {integrity: sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ==} - peerDependencies: - '@types/react': '>=18' - react: '>=18' - - react-redux@9.2.0: - resolution: {integrity: sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==} - peerDependencies: - '@types/react': ^18.2.25 || ^19 - react: ^18.0 || ^19 - redux: ^5.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - redux: - optional: true - - react-refresh@0.17.0: - resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} - engines: {node: '>=0.10.0'} - - react-remove-scroll-bar@2.3.8: - resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@types/react': - optional: true - - react-remove-scroll@2.7.2: - resolution: {integrity: sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react-resizable-panels@4.8.0: - resolution: {integrity: sha512-2uEABkewb3ky/ZgIlAUxWa1W/LjsK494fdV1QsXxst7CDRHCzo7h22tWWu3NNaBjmiuriOCt3CvhipnaYcpoIw==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - - react-style-singleton@2.2.3: - resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - react-syntax-highlighter@16.1.1: - resolution: {integrity: sha512-PjVawBGy80C6YbC5DDZJeUjBmC7skaoEUdvfFQediQHgCL7aKyVHe57SaJGfQsloGDac+gCpTfRdtxzWWKmCXA==} - engines: {node: '>= 16.20.2'} - peerDependencies: - react: '>= 0.14.0' - - react@19.2.4: - resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} - engines: {node: '>=0.10.0'} - - recharts@3.8.1: - resolution: {integrity: sha512-mwzmO1s9sFL0TduUpwndxCUNoXsBw3u3E/0+A+cLcrSfQitSG62L32N69GhqUrrT5qKcAE3pCGVINC6pqkBBQg==} - engines: {node: '>=18'} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - react-is: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - redent@3.0.0: - resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} - engines: {node: '>=8'} - - redux-thunk@3.1.0: - resolution: {integrity: sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==} - peerDependencies: - redux: ^5.0.0 - - redux@5.0.1: - resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} - - refractor@5.0.0: - resolution: {integrity: sha512-QXOrHQF5jOpjjLfiNk5GFnWhRXvxjUVnlFxkeDmewR5sXkr3iM46Zo+CnRR8B+MDVqkULW4EcLVcRBNOPXHosw==} - - regex-recursion@6.0.2: - resolution: {integrity: sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==} - - regex-utilities@2.3.0: - resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} - - regex@6.1.0: - resolution: {integrity: sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg==} - - rehype-harden@1.1.8: - resolution: {integrity: sha512-Qn7vR1xrf6fZCrkm9TDWi/AB4ylrHy+jqsNm1EHOAmbARYA6gsnVJBq/sdBh6kmT4NEZxH5vgIjrscefJAOXcw==} - - rehype-katex@7.0.1: - resolution: {integrity: sha512-OiM2wrZ/wuhKkigASodFoo8wimG3H12LWQaH8qSPVJn9apWKFSH3YOCtbKpBorTVw/eI7cuT21XBbvwEswbIOA==} - - rehype-raw@7.0.0: - resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} - - rehype-sanitize@6.0.0: - resolution: {integrity: sha512-CsnhKNsyI8Tub6L4sm5ZFsme4puGfc6pYylvXo1AeqaGbjOYyzNv3qZPwvs0oMJ39eryyeOdmxwUIo94IpEhqg==} - - remark-breaks@4.0.0: - resolution: {integrity: sha512-IjEjJOkH4FuJvHZVIW0QCDWxcG96kCq7An/KVH2NfJe6rKZU2AsHeB3OEjPNRxi4QC34Xdx7I2KGYn6IpT7gxQ==} - - remark-cjk-friendly-gfm-strikethrough@2.0.1: - resolution: {integrity: sha512-pWKj25O2eLXIL1aBupayl1fKhco+Brw8qWUWJPVB9EBzbQNd7nGLj0nLmJpggWsGLR5j5y40PIdjxby9IEYTuA==} - engines: {node: '>=18'} - peerDependencies: - '@types/mdast': ^4.0.0 - unified: ^11.0.0 - peerDependenciesMeta: - '@types/mdast': - optional: true - - remark-cjk-friendly@2.0.1: - resolution: {integrity: sha512-6WwkoQyZf/4j5k53zdFYrR8Ca+UVn992jXdLUSBDZR4eBpFhKyVxmA4gUHra/5fesjGIxrDhHesNr/sVoiiysA==} - engines: {node: '>=18'} - peerDependencies: - '@types/mdast': ^4.0.0 - unified: ^11.0.0 - peerDependenciesMeta: - '@types/mdast': - optional: true - - remark-gfm@4.0.1: - resolution: {integrity: sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==} - - remark-math@6.0.0: - resolution: {integrity: sha512-MMqgnP74Igy+S3WwnhQ7kqGlEerTETXMvJhrUzDikVZ2/uogJCb+WHUg97hK9/jcfc0dkD73s3LN8zU49cTEtA==} - - remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} - - remark-rehype@11.1.2: - resolution: {integrity: sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==} - - remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} - - remend@1.3.0: - resolution: {integrity: sha512-iIhggPkhW3hFImKtB10w0dz4EZbs28mV/dmbcYVonWEJ6UGHHpP+bFZnTh6GNWJONg5m+U56JrL+8IxZRdgWjw==} - - reselect@5.1.1: - resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} - - resolve-pkg-maps@1.0.0: - resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} - - robust-predicates@3.0.3: - resolution: {integrity: sha512-NS3levdsRIUOmiJ8FZWCP7LG3QpJyrs/TE0Zpf1yvZu8cAJJ6QMW92H1c7kWpdIHo8RvmLxN/o2JXTKHp74lUA==} - - rollup@4.60.0: - resolution: {integrity: sha512-yqjxruMGBQJ2gG4HtjZtAfXArHomazDHoFwFFmZZl0r7Pdo7qCIXKqKHZc8yeoMgzJJ+pO6pEEHa+V7uzWlrAQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - roughjs@4.6.6: - resolution: {integrity: sha512-ZUz/69+SYpFN/g/lUlo2FXcIjRkSu3nDarreVdGGndHEBJ6cXPdKguS8JGxwj5HA5xIbVKSmLgr5b3AWxtRfvQ==} - - rrweb-cssom@0.8.0: - resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} - - rw@1.3.3: - resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} - - safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - saxes@6.0.0: - resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} - engines: {node: '>=v12.22.7'} - - scheduler@0.27.0: - resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} - - semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - - shiki@3.23.0: - resolution: {integrity: sha512-55Dj73uq9ZXL5zyeRPzHQsK7Nbyt6Y10k5s7OjuFZGMhpp4r/rsLBH0o/0fstIzX1Lep9VxefWljK/SKCzygIA==} - - shiki@4.0.2: - resolution: {integrity: sha512-eAVKTMedR5ckPo4xne/PjYQYrU3qx78gtJZ+sHlXEg5IHhhoQhMfZVzetTYuaJS0L2Ef3AcCRzCHV8T0WI6nIQ==} - engines: {node: '>=20'} - - siginfo@2.0.0: - resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} - - sonner@2.0.7: - resolution: {integrity: sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^18.0.0 || ^19.0.0 || ^19.0.0-rc - - source-map-js@1.2.1: - resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} - engines: {node: '>=0.10.0'} - - space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - - split-type@0.3.4: - resolution: {integrity: sha512-otEk9vnD8qwfLsk3Lx0gz+qRkNIJCx0mlyL47ImP/DjMuV39d75Lpfwjn9fHteDRz0aoOblSzQjSNT9+Sswxcg==} - - stackback@0.0.2: - resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} - - std-env@4.0.0: - resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} - - streamdown@2.5.0: - resolution: {integrity: sha512-/tTnURfIOxZK/pqJAxsfCvETG/XCJHoWnk3jq9xLcuz6CSpnjjuxSRBTTL4PKGhxiZQf0lqPxGhImdpwcZ2XwA==} - peerDependencies: - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - - stringify-entities@4.0.4: - resolution: {integrity: sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==} - - strip-indent@3.0.0: - resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} - engines: {node: '>=8'} - - style-to-js@1.1.21: - resolution: {integrity: sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==} - - style-to-object@1.0.14: - resolution: {integrity: sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==} - - stylis@4.3.6: - resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} - - symbol-tree@3.2.4: - resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - - tailwind-merge@3.5.0: - resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==} - - tailwindcss@4.2.2: - resolution: {integrity: sha512-KWBIxs1Xb6NoLdMVqhbhgwZf2PGBpPEiwOqgI4pFIYbNTfBXiKYyWoTsXgBQ9WFg/OlhnvHaY+AEpW7wSmFo2Q==} - - tapable@2.3.2: - resolution: {integrity: sha512-1MOpMXuhGzGL5TTCZFItxCc0AARf1EZFQkGqMm7ERKj8+Hgr5oLvJOVFcC+lRmR8hCe2S3jC4T5D7Vg/d7/fhA==} - engines: {node: '>=6'} - - tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - - tinybench@2.9.0: - resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - - tinyexec@1.0.4: - resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} - engines: {node: '>=18'} - - tinyglobby@0.2.15: - resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} - engines: {node: '>=12.0.0'} - - tinyrainbow@3.1.0: - resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} - engines: {node: '>=14.0.0'} - - tldts-core@6.1.86: - resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} - - tldts@6.1.86: - resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} - hasBin: true - - tokenlens@1.3.1: - resolution: {integrity: sha512-7oxmsS5PNCX3z+b+z07hL5vCzlgHKkCGrEQjQmWl5l+v5cUrtL7S1cuST4XThaL1XyjbTX8J5hfP0cjDJRkaLA==} - - tough-cookie@5.1.2: - resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} - engines: {node: '>=16'} - - tr46@5.1.1: - resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} - engines: {node: '>=18'} - - trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - - trough@2.2.0: - resolution: {integrity: sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==} - - ts-dedent@2.2.0: - resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} - engines: {node: '>=6.10'} - - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - - tsx@4.21.0: - resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} - engines: {node: '>=18.0.0'} - hasBin: true - - tw-animate-css@1.4.0: - resolution: {integrity: sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ==} - - typescript@5.9.3: - resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} - engines: {node: '>=14.17'} - hasBin: true - - uc.micro@1.0.6: - resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} - - ufo@1.6.3: - resolution: {integrity: sha512-yDJTmhydvl5lJzBmy/hyOAA0d+aqCBuwl818haVdYCRrWV84o7YyeVm4QlVHStqNrrJSTb6jKuFAVqAFsr+K3Q==} - - unified@11.0.5: - resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} - - unist-util-find-after@5.0.0: - resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} - - unist-util-is@6.0.1: - resolution: {integrity: sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==} - - unist-util-position@5.0.0: - resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} - - unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} - - unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} - - unist-util-visit-parents@6.0.2: - resolution: {integrity: sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==} - - unist-util-visit@5.1.0: - resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} - - update-browserslist-db@1.2.3: - resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - - use-callback-ref@1.3.3: - resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - use-sidecar@1.1.3: - resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} - engines: {node: '>=10'} - peerDependencies: - '@types/react': '*' - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - use-stick-to-bottom@1.1.3: - resolution: {integrity: sha512-GgRLdeGhxBxpcbrBbEIEoOKUQ9d46/eaSII+wyv1r9Du+NbCn1W/OE+VddefvRP4+5w/1kATN/6g2/BAC/yowQ==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - use-sync-external-store@1.6.0: - resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} - peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 - - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - uuid@11.1.0: - resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} - hasBin: true - - vaul@1.1.2: - resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==} - peerDependencies: - react: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0.0 || ^19.0.0-rc - - vfile-location@5.0.3: - resolution: {integrity: sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==} - - vfile-message@4.0.3: - resolution: {integrity: sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==} - - vfile@6.0.3: - resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} - - victory-vendor@37.3.6: - resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} - - vite@7.3.1: - resolution: {integrity: sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - '@types/node': ^20.19.0 || >=22.12.0 - jiti: '>=1.21.0' - less: ^4.0.0 - lightningcss: ^1.21.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 - peerDependenciesMeta: - '@types/node': - optional: true - jiti: - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - sass-embedded: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - tsx: - optional: true - yaml: - optional: true - - vitest@4.1.2: - resolution: {integrity: sha512-xjR1dMTVHlFLh98JE3i/f/WePqJsah4A0FK9cc8Ehp9Udk0AZk6ccpIZhh1qJ/yxVWRZ+Q54ocnD8TXmkhspGg==} - engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@opentelemetry/api': ^1.9.0 - '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 - '@vitest/browser-playwright': 4.1.2 - '@vitest/browser-preview': 4.1.2 - '@vitest/browser-webdriverio': 4.1.2 - '@vitest/ui': 4.1.2 - happy-dom: '*' - jsdom: '*' - vite: ^6.0.0 || ^7.0.0 || ^8.0.0 - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@opentelemetry/api': - optional: true - '@types/node': - optional: true - '@vitest/browser-playwright': - optional: true - '@vitest/browser-preview': - optional: true - '@vitest/browser-webdriverio': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - - void-elements@3.1.0: - resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} - engines: {node: '>=0.10.0'} - - vscode-jsonrpc@8.2.0: - resolution: {integrity: sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==} - engines: {node: '>=14.0.0'} - - vscode-languageserver-protocol@3.17.5: - resolution: {integrity: sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==} - - vscode-languageserver-textdocument@1.0.12: - resolution: {integrity: sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==} - - vscode-languageserver-types@3.17.5: - resolution: {integrity: sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==} - - vscode-languageserver@9.0.1: - resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} - hasBin: true - - vscode-uri@3.1.0: - resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} - - w3c-xmlserializer@5.0.0: - resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} - engines: {node: '>=18'} - - web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - - webidl-conversions@7.0.0: - resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} - engines: {node: '>=12'} - - whatwg-encoding@3.1.1: - resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} - engines: {node: '>=18'} - deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation - - whatwg-mimetype@4.0.0: - resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} - engines: {node: '>=18'} - - whatwg-url@14.2.0: - resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} - engines: {node: '>=18'} - - why-is-node-running@2.3.0: - resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} - engines: {node: '>=8'} - hasBin: true - - ws@8.20.0: - resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - - xml-name-validator@5.0.0: - resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} - engines: {node: '>=18'} - - xmlchars@2.2.0: - resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} - - yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - - zod@4.3.6: - resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} - - zustand@4.5.7: - resolution: {integrity: sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==} - engines: {node: '>=12.7.0'} - peerDependencies: - '@types/react': '>=16.8' - immer: '>=9.0.6' - react: '>=16.8' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - - zustand@5.0.12: - resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} - engines: {node: '>=12.20.0'} - peerDependencies: - '@types/react': '>=18.0.0' - immer: '>=9.0.6' - react: '>=18.0.0' - use-sync-external-store: '>=1.2.0' - peerDependenciesMeta: - '@types/react': - optional: true - immer: - optional: true - react: - optional: true - use-sync-external-store: - optional: true - - zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - -snapshots: - - '@aaif/goose-acp@0.16.0(@agentclientprotocol/sdk@0.19.0(zod@4.3.6))': - dependencies: - '@agentclientprotocol/sdk': 0.19.0(zod@4.3.6) - zod: 3.25.76 - - '@adobe/css-tools@4.4.4': {} - - '@agentclientprotocol/sdk@0.19.0(zod@4.3.6)': - dependencies: - zod: 4.3.6 - - '@ai-sdk/gateway@3.0.84(zod@4.3.6)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) - '@vercel/oidc': 3.1.0 - zod: 4.3.6 - - '@ai-sdk/provider-utils@4.0.21(zod@4.3.6)': - dependencies: - '@ai-sdk/provider': 3.0.8 - '@standard-schema/spec': 1.1.0 - eventsource-parser: 3.0.6 - zod: 4.3.6 - - '@ai-sdk/provider@3.0.8': - dependencies: - json-schema: 0.4.0 - - '@alloc/quick-lru@5.2.0': {} - - '@antfu/install-pkg@1.1.0': - dependencies: - package-manager-detector: 1.6.0 - tinyexec: 1.0.4 - - '@asamuzakjp/css-color@3.2.0': - dependencies: - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - lru-cache: 10.4.3 - - '@babel/code-frame@7.29.0': - dependencies: - '@babel/helper-validator-identifier': 7.28.5 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/compat-data@7.29.0': {} - - '@babel/core@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 - '@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.4.3 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - - '@babel/helper-compilation-targets@7.28.6': - dependencies: - '@babel/compat-data': 7.29.0 - '@babel/helper-validator-option': 7.27.1 - browserslist: 4.28.1 - lru-cache: 5.1.1 - semver: 6.3.1 - - '@babel/helper-globals@7.28.0': {} - - '@babel/helper-module-imports@7.28.6': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-plugin-utils@7.28.6': {} - - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-validator-identifier@7.28.5': {} - - '@babel/helper-validator-option@7.27.1': {} - - '@babel/helpers@7.29.2': - dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.2': - dependencies: - '@babel/types': 7.29.0 - - '@babel/plugin-transform-react-jsx-self@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/plugin-transform-react-jsx-source@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - - '@babel/runtime@7.29.2': {} - - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - - '@babel/traverse@7.29.0': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 - '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@biomejs/biome@2.4.9': - optionalDependencies: - '@biomejs/cli-darwin-arm64': 2.4.9 - '@biomejs/cli-darwin-x64': 2.4.9 - '@biomejs/cli-linux-arm64': 2.4.9 - '@biomejs/cli-linux-arm64-musl': 2.4.9 - '@biomejs/cli-linux-x64': 2.4.9 - '@biomejs/cli-linux-x64-musl': 2.4.9 - '@biomejs/cli-win32-arm64': 2.4.9 - '@biomejs/cli-win32-x64': 2.4.9 - - '@biomejs/cli-darwin-arm64@2.4.9': - optional: true - - '@biomejs/cli-darwin-x64@2.4.9': - optional: true - - '@biomejs/cli-linux-arm64-musl@2.4.9': - optional: true - - '@biomejs/cli-linux-arm64@2.4.9': - optional: true - - '@biomejs/cli-linux-x64-musl@2.4.9': - optional: true - - '@biomejs/cli-linux-x64@2.4.9': - optional: true - - '@biomejs/cli-win32-arm64@2.4.9': - optional: true - - '@biomejs/cli-win32-x64@2.4.9': - optional: true - - '@braintree/sanitize-url@7.1.2': {} - - '@chevrotain/cst-dts-gen@11.1.2': - dependencies: - '@chevrotain/gast': 11.1.2 - '@chevrotain/types': 11.1.2 - lodash-es: 4.17.23 - - '@chevrotain/gast@11.1.2': - dependencies: - '@chevrotain/types': 11.1.2 - lodash-es: 4.17.23 - - '@chevrotain/regexp-to-ast@11.1.2': {} - - '@chevrotain/types@11.1.2': {} - - '@chevrotain/utils@11.1.2': {} - - '@csstools/color-helpers@5.1.0': {} - - '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/color-helpers': 5.1.0 - '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) - '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': - dependencies: - '@csstools/css-tokenizer': 3.0.4 - - '@csstools/css-tokenizer@3.0.4': {} - - '@date-fns/tz@1.4.1': {} - - '@esbuild/aix-ppc64@0.27.4': - optional: true - - '@esbuild/android-arm64@0.27.4': - optional: true - - '@esbuild/android-arm@0.27.4': - optional: true - - '@esbuild/android-x64@0.27.4': - optional: true - - '@esbuild/darwin-arm64@0.27.4': - optional: true - - '@esbuild/darwin-x64@0.27.4': - optional: true - - '@esbuild/freebsd-arm64@0.27.4': - optional: true - - '@esbuild/freebsd-x64@0.27.4': - optional: true - - '@esbuild/linux-arm64@0.27.4': - optional: true - - '@esbuild/linux-arm@0.27.4': - optional: true - - '@esbuild/linux-ia32@0.27.4': - optional: true - - '@esbuild/linux-loong64@0.27.4': - optional: true - - '@esbuild/linux-mips64el@0.27.4': - optional: true - - '@esbuild/linux-ppc64@0.27.4': - optional: true - - '@esbuild/linux-riscv64@0.27.4': - optional: true - - '@esbuild/linux-s390x@0.27.4': - optional: true - - '@esbuild/linux-x64@0.27.4': - optional: true - - '@esbuild/netbsd-arm64@0.27.4': - optional: true - - '@esbuild/netbsd-x64@0.27.4': - optional: true - - '@esbuild/openbsd-arm64@0.27.4': - optional: true - - '@esbuild/openbsd-x64@0.27.4': - optional: true - - '@esbuild/openharmony-arm64@0.27.4': - optional: true - - '@esbuild/sunos-x64@0.27.4': - optional: true - - '@esbuild/win32-arm64@0.27.4': - optional: true - - '@esbuild/win32-ia32@0.27.4': - optional: true - - '@esbuild/win32-x64@0.27.4': - optional: true - - '@floating-ui/core@1.7.5': - dependencies: - '@floating-ui/utils': 0.2.11 - - '@floating-ui/dom@1.7.6': - dependencies: - '@floating-ui/core': 1.7.5 - '@floating-ui/utils': 0.2.11 - - '@floating-ui/react-dom@2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@floating-ui/dom': 1.7.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - '@floating-ui/utils@0.2.11': {} - - '@iconify/types@2.0.0': {} - - '@iconify/utils@3.1.0': - dependencies: - '@antfu/install-pkg': 1.1.0 - '@iconify/types': 2.0.0 - mlly: 1.8.2 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@mermaid-js/parser@1.1.0': - dependencies: - langium: 4.2.1 - - '@opentelemetry/api@1.9.0': {} - - '@playwright/test@1.58.2': - dependencies: - playwright: 1.58.2 - - '@radix-ui/number@1.1.1': {} - - '@radix-ui/primitive@1.1.3': {} - - '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-aspect-ratio@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-avatar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-checkbox@1.3.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-compose-refs@1.1.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-context@1.1.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-context@1.1.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-direction@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-focus-guards@1.1.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-id@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-menu@2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-rect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/rect': 1.1.1 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-portal@1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-presence@1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-primitive@2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-primitive@2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-slot': 1.2.4(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-progress@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-context': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - aria-hidden: 1.2.6 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-remove-scroll: 2.7.2(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/number': 1.1.1 - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-slot@1.2.3(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-slot@1.2.4(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-direction': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-toggle@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-context': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-slot': 1.2.3(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-effect-event@0.0.2(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-is-hydrated@0.1.0(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-previous@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-rect@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/rect': 1.1.1 - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-use-size@1.1.1(@types/react@19.2.14)(react@19.2.4)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.14)(react@19.2.4) - react: 19.2.4 - optionalDependencies: - '@types/react': 19.2.14 - - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@radix-ui/rect@1.1.1': {} - - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4)': - dependencies: - '@standard-schema/spec': 1.1.0 - '@standard-schema/utils': 0.3.0 - immer: 11.1.4 - redux: 5.0.1 - redux-thunk: 3.1.0(redux@5.0.1) - reselect: 5.1.1 - optionalDependencies: - react: 19.2.4 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1) - - '@rive-app/react-webgl2@4.27.3(react@19.2.4)': - dependencies: - '@rive-app/webgl2': 2.35.4 - react: 19.2.4 - - '@rive-app/webgl2@2.35.4': {} - - '@rolldown/pluginutils@1.0.0-beta.27': {} - - '@rollup/rollup-android-arm-eabi@4.60.0': - optional: true - - '@rollup/rollup-android-arm64@4.60.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.60.0': - optional: true - - '@rollup/rollup-darwin-x64@4.60.0': - optional: true - - '@rollup/rollup-freebsd-arm64@4.60.0': - optional: true - - '@rollup/rollup-freebsd-x64@4.60.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.60.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.60.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.60.0': - optional: true - - '@rollup/rollup-linux-loong64-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-loong64-musl@4.60.0': - optional: true - - '@rollup/rollup-linux-ppc64-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-ppc64-musl@4.60.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-riscv64-musl@4.60.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.60.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.60.0': - optional: true - - '@rollup/rollup-openbsd-x64@4.60.0': - optional: true - - '@rollup/rollup-openharmony-arm64@4.60.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.60.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.60.0': - optional: true - - '@rollup/rollup-win32-x64-gnu@4.60.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.60.0': - optional: true - - '@shikijs/core@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - hast-util-to-html: 9.0.5 - - '@shikijs/core@4.0.2': - dependencies: - '@shikijs/primitive': 4.0.2 - '@shikijs/types': 4.0.2 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - hast-util-to-html: 9.0.5 - - '@shikijs/engine-javascript@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - oniguruma-to-es: 4.3.5 - - '@shikijs/engine-javascript@4.0.2': - dependencies: - '@shikijs/types': 4.0.2 - '@shikijs/vscode-textmate': 10.0.2 - oniguruma-to-es: 4.3.5 - - '@shikijs/engine-oniguruma@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - - '@shikijs/engine-oniguruma@4.0.2': - dependencies: - '@shikijs/types': 4.0.2 - '@shikijs/vscode-textmate': 10.0.2 - - '@shikijs/langs@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/langs@4.0.2': - dependencies: - '@shikijs/types': 4.0.2 - - '@shikijs/primitive@4.0.2': - dependencies: - '@shikijs/types': 4.0.2 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - '@shikijs/themes@3.23.0': - dependencies: - '@shikijs/types': 3.23.0 - - '@shikijs/themes@4.0.2': - dependencies: - '@shikijs/types': 4.0.2 - - '@shikijs/types@3.23.0': - dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - '@shikijs/types@4.0.2': - dependencies: - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - '@shikijs/vscode-textmate@10.0.2': {} - - '@standard-schema/spec@1.1.0': {} - - '@standard-schema/utils@0.3.0': {} - - '@streamdown/cjk@1.0.3(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(react@19.2.4)(unified@11.0.5)': - dependencies: - react: 19.2.4 - remark-cjk-friendly: 2.0.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5) - remark-cjk-friendly-gfm-strikethrough: 2.0.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5) - unist-util-visit: 5.1.0 - transitivePeerDependencies: - - '@types/mdast' - - micromark - - micromark-util-types - - unified - - '@streamdown/code@1.1.1(react@19.2.4)': - dependencies: - react: 19.2.4 - shiki: 3.23.0 - - '@streamdown/math@1.0.2(react@19.2.4)': - dependencies: - katex: 0.16.44 - react: 19.2.4 - rehype-katex: 7.0.1 - remark-math: 6.0.0 - transitivePeerDependencies: - - supports-color - - '@streamdown/mermaid@1.0.2(react@19.2.4)': - dependencies: - mermaid: 11.14.0 - react: 19.2.4 - - '@tabby_ai/hijri-converter@1.0.5': {} - - '@tabler/icons-react@3.41.1(react@19.2.4)': - dependencies: - '@tabler/icons': 3.41.1 - react: 19.2.4 - - '@tabler/icons@3.41.1': {} - - '@tailwindcss/node@4.2.2': - dependencies: - '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.20.1 - jiti: 2.6.1 - lightningcss: 1.32.0 - magic-string: 0.30.21 - source-map-js: 1.2.1 - tailwindcss: 4.2.2 - - '@tailwindcss/oxide-android-arm64@4.2.2': - optional: true - - '@tailwindcss/oxide-darwin-arm64@4.2.2': - optional: true - - '@tailwindcss/oxide-darwin-x64@4.2.2': - optional: true - - '@tailwindcss/oxide-freebsd-x64@4.2.2': - optional: true - - '@tailwindcss/oxide-linux-arm-gnueabihf@4.2.2': - optional: true - - '@tailwindcss/oxide-linux-arm64-gnu@4.2.2': - optional: true - - '@tailwindcss/oxide-linux-arm64-musl@4.2.2': - optional: true - - '@tailwindcss/oxide-linux-x64-gnu@4.2.2': - optional: true - - '@tailwindcss/oxide-linux-x64-musl@4.2.2': - optional: true - - '@tailwindcss/oxide-wasm32-wasi@4.2.2': - optional: true - - '@tailwindcss/oxide-win32-arm64-msvc@4.2.2': - optional: true - - '@tailwindcss/oxide-win32-x64-msvc@4.2.2': - optional: true - - '@tailwindcss/oxide@4.2.2': - optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-arm64': 4.2.2 - '@tailwindcss/oxide-darwin-x64': 4.2.2 - '@tailwindcss/oxide-freebsd-x64': 4.2.2 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.2.2 - '@tailwindcss/oxide-linux-arm64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-arm64-musl': 4.2.2 - '@tailwindcss/oxide-linux-x64-gnu': 4.2.2 - '@tailwindcss/oxide-linux-x64-musl': 4.2.2 - '@tailwindcss/oxide-wasm32-wasi': 4.2.2 - '@tailwindcss/oxide-win32-arm64-msvc': 4.2.2 - '@tailwindcss/oxide-win32-x64-msvc': 4.2.2 - - '@tailwindcss/postcss@4.2.2': - dependencies: - '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.2.2 - '@tailwindcss/oxide': 4.2.2 - postcss: 8.5.8 - tailwindcss: 4.2.2 - - '@tailwindcss/typography@0.5.19(tailwindcss@4.2.2)': - dependencies: - postcss-selector-parser: 6.0.10 - tailwindcss: 4.2.2 - - '@tanstack/query-core@5.95.2': {} - - '@tanstack/react-query@5.95.2(react@19.2.4)': - dependencies: - '@tanstack/query-core': 5.95.2 - react: 19.2.4 - - '@tauri-apps/api@2.10.1': {} - - '@tauri-apps/cli-darwin-arm64@2.10.1': - optional: true - - '@tauri-apps/cli-darwin-x64@2.10.1': - optional: true - - '@tauri-apps/cli-linux-arm-gnueabihf@2.10.1': - optional: true - - '@tauri-apps/cli-linux-arm64-gnu@2.10.1': - optional: true - - '@tauri-apps/cli-linux-arm64-musl@2.10.1': - optional: true - - '@tauri-apps/cli-linux-riscv64-gnu@2.10.1': - optional: true - - '@tauri-apps/cli-linux-x64-gnu@2.10.1': - optional: true - - '@tauri-apps/cli-linux-x64-musl@2.10.1': - optional: true - - '@tauri-apps/cli-win32-arm64-msvc@2.10.1': - optional: true - - '@tauri-apps/cli-win32-ia32-msvc@2.10.1': - optional: true - - '@tauri-apps/cli-win32-x64-msvc@2.10.1': - optional: true - - '@tauri-apps/cli@2.10.1': - optionalDependencies: - '@tauri-apps/cli-darwin-arm64': 2.10.1 - '@tauri-apps/cli-darwin-x64': 2.10.1 - '@tauri-apps/cli-linux-arm-gnueabihf': 2.10.1 - '@tauri-apps/cli-linux-arm64-gnu': 2.10.1 - '@tauri-apps/cli-linux-arm64-musl': 2.10.1 - '@tauri-apps/cli-linux-riscv64-gnu': 2.10.1 - '@tauri-apps/cli-linux-x64-gnu': 2.10.1 - '@tauri-apps/cli-linux-x64-musl': 2.10.1 - '@tauri-apps/cli-win32-arm64-msvc': 2.10.1 - '@tauri-apps/cli-win32-ia32-msvc': 2.10.1 - '@tauri-apps/cli-win32-x64-msvc': 2.10.1 - - '@tauri-apps/plugin-dialog@2.6.0': - dependencies: - '@tauri-apps/api': 2.10.1 - - '@tauri-apps/plugin-opener@2.5.3': - dependencies: - '@tauri-apps/api': 2.10.1 - - '@testing-library/dom@10.4.1': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/runtime': 7.29.2 - '@types/aria-query': 5.0.4 - aria-query: 5.3.0 - dom-accessibility-api: 0.5.16 - lz-string: 1.5.0 - picocolors: 1.1.1 - pretty-format: 27.5.1 - - '@testing-library/jest-dom@6.9.1': - dependencies: - '@adobe/css-tools': 4.4.4 - aria-query: 5.3.2 - css.escape: 1.5.1 - dom-accessibility-api: 0.6.3 - picocolors: 1.1.1 - redent: 3.0.0 - - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@babel/runtime': 7.29.2 - '@testing-library/dom': 10.4.1 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - '@types/react-dom': 19.2.3(@types/react@19.2.14) - - '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': - dependencies: - '@testing-library/dom': 10.4.1 - - '@tokenlens/core@1.3.0': {} - - '@tokenlens/fetch@1.3.0': - dependencies: - '@tokenlens/core': 1.3.0 - - '@tokenlens/helpers@1.3.1': - dependencies: - '@tokenlens/core': 1.3.0 - '@tokenlens/fetch': 1.3.0 - - '@tokenlens/models@1.3.0': - dependencies: - '@tokenlens/core': 1.3.0 - - '@types/aria-query@5.0.4': {} - - '@types/babel__core@7.20.5': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@types/babel__generator': 7.27.0 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.28.0 - - '@types/babel__generator@7.27.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/babel__template@7.4.4': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - - '@types/babel__traverse@7.28.0': - dependencies: - '@babel/types': 7.29.0 - - '@types/chai@5.2.3': - dependencies: - '@types/deep-eql': 4.0.2 - assertion-error: 2.0.1 - - '@types/d3-array@3.2.2': {} - - '@types/d3-axis@3.0.6': - dependencies: - '@types/d3-selection': 3.0.11 - - '@types/d3-brush@3.0.6': - dependencies: - '@types/d3-selection': 3.0.11 - - '@types/d3-chord@3.0.6': {} - - '@types/d3-color@3.1.3': {} - - '@types/d3-contour@3.0.6': - dependencies: - '@types/d3-array': 3.2.2 - '@types/geojson': 7946.0.16 - - '@types/d3-delaunay@6.0.4': {} - - '@types/d3-dispatch@3.0.7': {} - - '@types/d3-drag@3.0.7': - dependencies: - '@types/d3-selection': 3.0.11 - - '@types/d3-dsv@3.0.7': {} - - '@types/d3-ease@3.0.2': {} - - '@types/d3-fetch@3.0.7': - dependencies: - '@types/d3-dsv': 3.0.7 - - '@types/d3-force@3.0.10': {} - - '@types/d3-format@3.0.4': {} - - '@types/d3-geo@3.1.0': - dependencies: - '@types/geojson': 7946.0.16 - - '@types/d3-hierarchy@3.1.7': {} - - '@types/d3-interpolate@3.0.4': - dependencies: - '@types/d3-color': 3.1.3 - - '@types/d3-path@3.1.1': {} - - '@types/d3-polygon@3.0.2': {} - - '@types/d3-quadtree@3.0.6': {} - - '@types/d3-random@3.0.3': {} - - '@types/d3-scale-chromatic@3.1.0': {} - - '@types/d3-scale@4.0.9': - dependencies: - '@types/d3-time': 3.0.4 - - '@types/d3-selection@3.0.11': {} - - '@types/d3-shape@3.1.8': - dependencies: - '@types/d3-path': 3.1.1 - - '@types/d3-time-format@4.0.3': {} - - '@types/d3-time@3.0.4': {} - - '@types/d3-timer@3.0.2': {} - - '@types/d3-transition@3.0.9': - dependencies: - '@types/d3-selection': 3.0.11 - - '@types/d3-zoom@3.0.8': - dependencies: - '@types/d3-interpolate': 3.0.4 - '@types/d3-selection': 3.0.11 - - '@types/d3@7.4.3': - dependencies: - '@types/d3-array': 3.2.2 - '@types/d3-axis': 3.0.6 - '@types/d3-brush': 3.0.6 - '@types/d3-chord': 3.0.6 - '@types/d3-color': 3.1.3 - '@types/d3-contour': 3.0.6 - '@types/d3-delaunay': 6.0.4 - '@types/d3-dispatch': 3.0.7 - '@types/d3-drag': 3.0.7 - '@types/d3-dsv': 3.0.7 - '@types/d3-ease': 3.0.2 - '@types/d3-fetch': 3.0.7 - '@types/d3-force': 3.0.10 - '@types/d3-format': 3.0.4 - '@types/d3-geo': 3.1.0 - '@types/d3-hierarchy': 3.1.7 - '@types/d3-interpolate': 3.0.4 - '@types/d3-path': 3.1.1 - '@types/d3-polygon': 3.0.2 - '@types/d3-quadtree': 3.0.6 - '@types/d3-random': 3.0.3 - '@types/d3-scale': 4.0.9 - '@types/d3-scale-chromatic': 3.1.0 - '@types/d3-selection': 3.0.11 - '@types/d3-shape': 3.1.8 - '@types/d3-time': 3.0.4 - '@types/d3-time-format': 4.0.3 - '@types/d3-timer': 3.0.2 - '@types/d3-transition': 3.0.9 - '@types/d3-zoom': 3.0.8 - - '@types/debug@4.1.13': - dependencies: - '@types/ms': 2.1.0 - - '@types/deep-eql@4.0.2': {} - - '@types/estree-jsx@1.0.5': - dependencies: - '@types/estree': 1.0.8 - - '@types/estree@1.0.8': {} - - '@types/geojson@7946.0.16': {} - - '@types/hast@3.0.4': - dependencies: - '@types/unist': 3.0.3 - - '@types/katex@0.16.8': {} - - '@types/mdast@4.0.4': - dependencies: - '@types/unist': 3.0.3 - - '@types/ms@2.1.0': {} - - '@types/prismjs@1.26.6': {} - - '@types/prop-types@15.7.15': - optional: true - - '@types/react-dom@18.3.7(@types/react@18.3.28)': - dependencies: - '@types/react': 18.3.28 - optional: true - - '@types/react-dom@19.2.3(@types/react@19.2.14)': - dependencies: - '@types/react': 19.2.14 - - '@types/react-syntax-highlighter@15.5.13': - dependencies: - '@types/react': 19.2.14 - - '@types/react@18.3.28': - dependencies: - '@types/prop-types': 15.7.15 - csstype: 3.2.3 - optional: true - - '@types/react@19.2.14': - dependencies: - csstype: 3.2.3 - - '@types/trusted-types@2.0.7': - optional: true - - '@types/unist@2.0.11': {} - - '@types/unist@3.0.3': {} - - '@types/use-sync-external-store@0.0.6': {} - - '@ungap/structured-clone@1.3.0': {} - - '@upsetjs/venn.js@2.0.0': - optionalDependencies: - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - - '@vercel/oidc@3.1.0': {} - - '@vitejs/plugin-react@4.7.0(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0))': - dependencies: - '@babel/core': 7.29.0 - '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.29.0) - '@babel/plugin-transform-react-jsx-source': 7.27.1(@babel/core@7.29.0) - '@rolldown/pluginutils': 1.0.0-beta.27 - '@types/babel__core': 7.20.5 - react-refresh: 0.17.0 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0) - transitivePeerDependencies: - - supports-color - - '@vitest/expect@4.1.2': - dependencies: - '@standard-schema/spec': 1.1.0 - '@types/chai': 5.2.3 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - chai: 6.2.2 - tinyrainbow: 3.1.0 - - '@vitest/mocker@4.1.2(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0))': - dependencies: - '@vitest/spy': 4.1.2 - estree-walker: 3.0.3 - magic-string: 0.30.21 - optionalDependencies: - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0) - - '@vitest/pretty-format@4.1.2': - dependencies: - tinyrainbow: 3.1.0 - - '@vitest/runner@4.1.2': - dependencies: - '@vitest/utils': 4.1.2 - pathe: 2.0.3 - - '@vitest/snapshot@4.1.2': - dependencies: - '@vitest/pretty-format': 4.1.2 - '@vitest/utils': 4.1.2 - magic-string: 0.30.21 - pathe: 2.0.3 - - '@vitest/spy@4.1.2': {} - - '@vitest/utils@4.1.2': - dependencies: - '@vitest/pretty-format': 4.1.2 - convert-source-map: 2.0.0 - tinyrainbow: 3.1.0 - - '@xyflow/react@12.10.2(@types/react@19.2.14)(immer@11.1.4)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': - dependencies: - '@xyflow/system': 0.0.76 - classcat: 5.0.5 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - zustand: 4.5.7(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4) - transitivePeerDependencies: - - '@types/react' - - immer - - '@xyflow/system@0.0.76': - dependencies: - '@types/d3-drag': 3.0.7 - '@types/d3-interpolate': 3.0.4 - '@types/d3-selection': 3.0.11 - '@types/d3-transition': 3.0.9 - '@types/d3-zoom': 3.0.8 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-zoom: 3.0.0 - - acorn-jsx@5.3.2(acorn@8.16.0): - dependencies: - acorn: 8.16.0 - - acorn@8.16.0: {} - - agent-base@7.1.4: {} - - ai@6.0.142(zod@4.3.6): - dependencies: - '@ai-sdk/gateway': 3.0.84(zod@4.3.6) - '@ai-sdk/provider': 3.0.8 - '@ai-sdk/provider-utils': 4.0.21(zod@4.3.6) - '@opentelemetry/api': 1.9.0 - zod: 4.3.6 - - anser@2.3.5: {} - - ansi-regex@5.0.1: {} - - ansi-styles@5.2.0: {} - - ansi-to-react@6.2.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - anser: 2.3.5 - escape-carriage: 1.3.1 - linkify-it: 3.0.3 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - aria-hidden@1.2.6: - dependencies: - tslib: 2.8.1 - - aria-query@5.3.0: - dependencies: - dequal: 2.0.3 - - aria-query@5.3.2: {} - - assertion-error@2.0.1: {} - - bail@2.0.2: {} - - baseline-browser-mapping@2.10.12: {} - - browserslist@4.28.1: - dependencies: - baseline-browser-mapping: 2.10.12 - caniuse-lite: 1.0.30001781 - electron-to-chromium: 1.5.328 - node-releases: 2.0.36 - update-browserslist-db: 1.2.3(browserslist@4.28.1) - - caniuse-lite@1.0.30001781: {} - - ccount@2.0.1: {} - - ce-la-react@0.3.2(react@19.2.4): - dependencies: - react: 19.2.4 - - chai@6.2.2: {} - - character-entities-html4@2.1.0: {} - - character-entities-legacy@3.0.0: {} - - character-entities@2.0.2: {} - - character-reference-invalid@2.0.1: {} - - chevrotain-allstar@0.3.1(chevrotain@11.1.2): - dependencies: - chevrotain: 11.1.2 - lodash-es: 4.17.23 - - chevrotain@11.1.2: - dependencies: - '@chevrotain/cst-dts-gen': 11.1.2 - '@chevrotain/gast': 11.1.2 - '@chevrotain/regexp-to-ast': 11.1.2 - '@chevrotain/types': 11.1.2 - '@chevrotain/utils': 11.1.2 - lodash-es: 4.17.23 - - class-variance-authority@0.7.1: - dependencies: - clsx: 2.1.1 - - classcat@5.0.5: {} - - clsx@2.1.1: {} - - cmdk@1.1.1(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@radix-ui/react-id': 1.1.1(@types/react@19.2.14)(react@19.2.4) - '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - comma-separated-tokens@2.0.3: {} - - commander@7.2.0: {} - - commander@8.3.0: {} - - confbox@0.1.8: {} - - convert-source-map@2.0.0: {} - - cose-base@1.0.3: - dependencies: - layout-base: 1.0.2 - - cose-base@2.2.0: - dependencies: - layout-base: 2.0.1 - - css.escape@1.5.1: {} - - cssesc@3.0.0: {} - - cssstyle@4.6.0: - dependencies: - '@asamuzakjp/css-color': 3.2.0 - rrweb-cssom: 0.8.0 - - csstype@3.2.3: {} - - cytoscape-cose-bilkent@4.1.0(cytoscape@3.33.1): - dependencies: - cose-base: 1.0.3 - cytoscape: 3.33.1 - - cytoscape-fcose@2.2.0(cytoscape@3.33.1): - dependencies: - cose-base: 2.2.0 - cytoscape: 3.33.1 - - cytoscape@3.33.1: {} - - d3-array@2.12.1: - dependencies: - internmap: 1.0.1 - - d3-array@3.2.4: - dependencies: - internmap: 2.0.3 - - d3-axis@3.0.0: {} - - d3-brush@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - - d3-chord@3.0.1: - dependencies: - d3-path: 3.1.0 - - d3-color@3.1.0: {} - - d3-contour@4.0.2: - dependencies: - d3-array: 3.2.4 - - d3-delaunay@6.0.4: - dependencies: - delaunator: 5.1.0 - - d3-dispatch@3.0.1: {} - - d3-drag@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-selection: 3.0.0 - - d3-dsv@3.0.1: - dependencies: - commander: 7.2.0 - iconv-lite: 0.6.3 - rw: 1.3.3 - - d3-ease@3.0.1: {} - - d3-fetch@3.0.1: - dependencies: - d3-dsv: 3.0.1 - - d3-force@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-quadtree: 3.0.1 - d3-timer: 3.0.1 - - d3-format@3.1.2: {} - - d3-geo@3.1.1: - dependencies: - d3-array: 3.2.4 - - d3-hierarchy@3.1.2: {} - - d3-interpolate@3.0.1: - dependencies: - d3-color: 3.1.0 - - d3-path@1.0.9: {} - - d3-path@3.1.0: {} - - d3-polygon@3.0.1: {} - - d3-quadtree@3.0.1: {} - - d3-random@3.0.1: {} - - d3-sankey@0.12.3: - dependencies: - d3-array: 2.12.1 - d3-shape: 1.3.7 - - d3-scale-chromatic@3.1.0: - dependencies: - d3-color: 3.1.0 - d3-interpolate: 3.0.1 - - d3-scale@4.0.2: - dependencies: - d3-array: 3.2.4 - d3-format: 3.1.2 - d3-interpolate: 3.0.1 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - - d3-selection@3.0.0: {} - - d3-shape@1.3.7: - dependencies: - d3-path: 1.0.9 - - d3-shape@3.2.0: - dependencies: - d3-path: 3.1.0 - - d3-time-format@4.1.0: - dependencies: - d3-time: 3.1.0 - - d3-time@3.1.0: - dependencies: - d3-array: 3.2.4 - - d3-timer@3.0.1: {} - - d3-transition@3.0.1(d3-selection@3.0.0): - dependencies: - d3-color: 3.1.0 - d3-dispatch: 3.0.1 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-timer: 3.0.1 - - d3-zoom@3.0.0: - dependencies: - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-interpolate: 3.0.1 - d3-selection: 3.0.0 - d3-transition: 3.0.1(d3-selection@3.0.0) - - d3@7.9.0: - dependencies: - d3-array: 3.2.4 - d3-axis: 3.0.0 - d3-brush: 3.0.0 - d3-chord: 3.0.1 - d3-color: 3.1.0 - d3-contour: 4.0.2 - d3-delaunay: 6.0.4 - d3-dispatch: 3.0.1 - d3-drag: 3.0.0 - d3-dsv: 3.0.1 - d3-ease: 3.0.1 - d3-fetch: 3.0.1 - d3-force: 3.0.0 - d3-format: 3.1.2 - d3-geo: 3.1.1 - d3-hierarchy: 3.1.2 - d3-interpolate: 3.0.1 - d3-path: 3.1.0 - d3-polygon: 3.0.1 - d3-quadtree: 3.0.1 - d3-random: 3.0.1 - d3-scale: 4.0.2 - d3-scale-chromatic: 3.1.0 - d3-selection: 3.0.0 - d3-shape: 3.2.0 - d3-time: 3.1.0 - d3-time-format: 4.1.0 - d3-timer: 3.0.1 - d3-transition: 3.0.1(d3-selection@3.0.0) - d3-zoom: 3.0.0 - - dagre-d3-es@7.0.14: - dependencies: - d3: 7.9.0 - lodash-es: 4.17.23 - - data-urls@5.0.0: - dependencies: - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - - date-fns-jalali@4.1.0-0: {} - - date-fns@4.1.0: {} - - dayjs@1.11.20: {} - - debug@4.4.3: - dependencies: - ms: 2.1.3 - - decimal.js-light@2.5.1: {} - - decimal.js@10.6.0: {} - - decode-named-character-reference@1.3.0: - dependencies: - character-entities: 2.0.2 - - delaunator@5.1.0: - dependencies: - robust-predicates: 3.0.3 - - dequal@2.0.3: {} - - detect-libc@2.1.2: {} - - detect-node-es@1.1.0: {} - - devlop@1.1.0: - dependencies: - dequal: 2.0.3 - - dom-accessibility-api@0.5.16: {} - - dom-accessibility-api@0.6.3: {} - - dompurify@3.3.3: - optionalDependencies: - '@types/trusted-types': 2.0.7 - - electron-to-chromium@1.5.328: {} - - embla-carousel-react@8.6.0(react@19.2.4): - dependencies: - embla-carousel: 8.6.0 - embla-carousel-reactive-utils: 8.6.0(embla-carousel@8.6.0) - react: 19.2.4 - - embla-carousel-reactive-utils@8.6.0(embla-carousel@8.6.0): - dependencies: - embla-carousel: 8.6.0 - - embla-carousel@8.6.0: {} - - enhanced-resolve@5.20.1: - dependencies: - graceful-fs: 4.2.11 - tapable: 2.3.2 - - entities@6.0.1: {} - - es-module-lexer@2.0.0: {} - - es-toolkit@1.45.1: {} - - esbuild@0.27.4: - optionalDependencies: - '@esbuild/aix-ppc64': 0.27.4 - '@esbuild/android-arm': 0.27.4 - '@esbuild/android-arm64': 0.27.4 - '@esbuild/android-x64': 0.27.4 - '@esbuild/darwin-arm64': 0.27.4 - '@esbuild/darwin-x64': 0.27.4 - '@esbuild/freebsd-arm64': 0.27.4 - '@esbuild/freebsd-x64': 0.27.4 - '@esbuild/linux-arm': 0.27.4 - '@esbuild/linux-arm64': 0.27.4 - '@esbuild/linux-ia32': 0.27.4 - '@esbuild/linux-loong64': 0.27.4 - '@esbuild/linux-mips64el': 0.27.4 - '@esbuild/linux-ppc64': 0.27.4 - '@esbuild/linux-riscv64': 0.27.4 - '@esbuild/linux-s390x': 0.27.4 - '@esbuild/linux-x64': 0.27.4 - '@esbuild/netbsd-arm64': 0.27.4 - '@esbuild/netbsd-x64': 0.27.4 - '@esbuild/openbsd-arm64': 0.27.4 - '@esbuild/openbsd-x64': 0.27.4 - '@esbuild/openharmony-arm64': 0.27.4 - '@esbuild/sunos-x64': 0.27.4 - '@esbuild/win32-arm64': 0.27.4 - '@esbuild/win32-ia32': 0.27.4 - '@esbuild/win32-x64': 0.27.4 - - escalade@3.2.0: {} - - escape-carriage@1.3.1: {} - - escape-string-regexp@5.0.0: {} - - estree-util-is-identifier-name@3.0.0: {} - - estree-walker@3.0.3: - dependencies: - '@types/estree': 1.0.8 - - eventemitter3@5.0.4: {} - - eventsource-parser@3.0.6: {} - - expect-type@1.3.0: {} - - extend@3.0.2: {} - - fault@1.0.4: - dependencies: - format: 0.2.2 - - fdir@6.5.0(picomatch@4.0.4): - optionalDependencies: - picomatch: 4.0.4 - - format@0.2.2: {} - - framer-motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - motion-dom: 12.38.0 - motion-utils: 12.36.0 - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - fsevents@2.3.2: - optional: true - - fsevents@2.3.3: - optional: true - - gensync@1.0.0-beta.2: {} - - get-east-asian-width@1.5.0: {} - - get-nonce@1.0.1: {} - - get-tsconfig@4.13.7: - dependencies: - resolve-pkg-maps: 1.0.0 - - graceful-fs@4.2.11: {} - - gsap@3.14.2: {} - - hachure-fill@0.5.2: {} - - hast-util-from-dom@5.0.1: - dependencies: - '@types/hast': 3.0.4 - hastscript: 9.0.1 - web-namespaces: 2.0.1 - - hast-util-from-html-isomorphic@2.0.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-from-dom: 5.0.1 - hast-util-from-html: 2.0.3 - unist-util-remove-position: 5.0.0 - - hast-util-from-html@2.0.3: - dependencies: - '@types/hast': 3.0.4 - devlop: 1.1.0 - hast-util-from-parse5: 8.0.3 - parse5: 7.3.0 - vfile: 6.0.3 - vfile-message: 4.0.3 - - hast-util-from-parse5@8.0.3: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - devlop: 1.1.0 - hastscript: 9.0.1 - property-information: 7.1.0 - vfile: 6.0.3 - vfile-location: 5.0.3 - web-namespaces: 2.0.1 - - hast-util-is-element@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-parse-selector@4.0.0: - dependencies: - '@types/hast': 3.0.4 - - hast-util-raw@9.1.0: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - '@ungap/structured-clone': 1.3.0 - hast-util-from-parse5: 8.0.3 - hast-util-to-parse5: 8.0.1 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.1 - parse5: 7.3.0 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - - hast-util-sanitize@5.0.2: - dependencies: - '@types/hast': 3.0.4 - '@ungap/structured-clone': 1.3.0 - unist-util-position: 5.0.0 - - hast-util-to-html@9.0.5: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-whitespace: 3.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.2.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.4 - zwitch: 2.0.4 - - hast-util-to-jsx-runtime@2.3.6: - dependencies: - '@types/estree': 1.0.8 - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - estree-util-is-identifier-name: 3.0.0 - hast-util-whitespace: 3.0.0 - mdast-util-mdx-expression: 2.0.1 - mdast-util-mdx-jsx: 3.2.0 - mdast-util-mdxjs-esm: 2.0.1 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - style-to-js: 1.1.21 - unist-util-position: 5.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - hast-util-to-parse5@8.0.1: - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - devlop: 1.1.0 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - web-namespaces: 2.0.1 - zwitch: 2.0.4 - - hast-util-to-text@4.0.2: - dependencies: - '@types/hast': 3.0.4 - '@types/unist': 3.0.3 - hast-util-is-element: 3.0.0 - unist-util-find-after: 5.0.0 - - hast-util-whitespace@3.0.0: - dependencies: - '@types/hast': 3.0.4 - - hastscript@9.0.1: - dependencies: - '@types/hast': 3.0.4 - comma-separated-tokens: 2.0.3 - hast-util-parse-selector: 4.0.0 - property-information: 7.1.0 - space-separated-tokens: 2.0.2 - - highlight.js@10.7.3: {} - - highlightjs-vue@1.0.0: {} - - html-encoding-sniffer@4.0.0: - dependencies: - whatwg-encoding: 3.1.1 - - html-parse-stringify@3.0.1: - dependencies: - void-elements: 3.1.0 - - html-url-attributes@3.0.1: {} - - html-void-elements@3.0.0: {} - - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.6: - dependencies: - agent-base: 7.1.4 - debug: 4.4.3 - transitivePeerDependencies: - - supports-color - - i18next-resources-to-backend@1.2.1: - dependencies: - '@babel/runtime': 7.29.2 - - i18next@26.0.3(typescript@5.9.3): - dependencies: - '@babel/runtime': 7.29.2 - optionalDependencies: - typescript: 5.9.3 - - iconv-lite@0.6.3: - dependencies: - safer-buffer: 2.1.2 - - immer@10.2.0: {} - - immer@11.1.4: {} - - indent-string@4.0.0: {} - - inline-style-parser@0.2.7: {} - - input-otp@1.4.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - internmap@1.0.1: {} - - internmap@2.0.3: {} - - is-alphabetical@2.0.1: {} - - is-alphanumerical@2.0.1: - dependencies: - is-alphabetical: 2.0.1 - is-decimal: 2.0.1 - - is-decimal@2.0.1: {} - - is-hexadecimal@2.0.1: {} - - is-plain-obj@4.1.0: {} - - is-potential-custom-element-name@1.0.1: {} - - jiti@2.6.1: {} - - js-tokens@4.0.0: {} - - jsdom@26.1.0: - dependencies: - cssstyle: 4.6.0 - data-urls: 5.0.0 - decimal.js: 10.6.0 - html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.6 - is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.23 - parse5: 7.3.0 - rrweb-cssom: 0.8.0 - saxes: 6.0.0 - symbol-tree: 3.2.4 - tough-cookie: 5.1.2 - w3c-xmlserializer: 5.0.0 - webidl-conversions: 7.0.0 - whatwg-encoding: 3.1.1 - whatwg-mimetype: 4.0.0 - whatwg-url: 14.2.0 - ws: 8.20.0 - xml-name-validator: 5.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - jsesc@3.1.0: {} - - json-schema@0.4.0: {} - - json5@2.2.3: {} - - katex@0.16.44: - dependencies: - commander: 8.3.0 - - khroma@2.1.0: {} - - langium@4.2.1: - dependencies: - chevrotain: 11.1.2 - chevrotain-allstar: 0.3.1(chevrotain@11.1.2) - vscode-languageserver: 9.0.1 - vscode-languageserver-textdocument: 1.0.12 - vscode-uri: 3.1.0 - - layout-base@1.0.2: {} - - layout-base@2.0.1: {} - - lightningcss-android-arm64@1.32.0: - optional: true - - lightningcss-darwin-arm64@1.32.0: - optional: true - - lightningcss-darwin-x64@1.32.0: - optional: true - - lightningcss-freebsd-x64@1.32.0: - optional: true - - lightningcss-linux-arm-gnueabihf@1.32.0: - optional: true - - lightningcss-linux-arm64-gnu@1.32.0: - optional: true - - lightningcss-linux-arm64-musl@1.32.0: - optional: true - - lightningcss-linux-x64-gnu@1.32.0: - optional: true - - lightningcss-linux-x64-musl@1.32.0: - optional: true - - lightningcss-win32-arm64-msvc@1.32.0: - optional: true - - lightningcss-win32-x64-msvc@1.32.0: - optional: true - - lightningcss@1.32.0: - dependencies: - detect-libc: 2.1.2 - optionalDependencies: - lightningcss-android-arm64: 1.32.0 - lightningcss-darwin-arm64: 1.32.0 - lightningcss-darwin-x64: 1.32.0 - lightningcss-freebsd-x64: 1.32.0 - lightningcss-linux-arm-gnueabihf: 1.32.0 - lightningcss-linux-arm64-gnu: 1.32.0 - lightningcss-linux-arm64-musl: 1.32.0 - lightningcss-linux-x64-gnu: 1.32.0 - lightningcss-linux-x64-musl: 1.32.0 - lightningcss-win32-arm64-msvc: 1.32.0 - lightningcss-win32-x64-msvc: 1.32.0 - - linkify-it@3.0.3: - dependencies: - uc.micro: 1.0.6 - - lodash-es@4.17.23: {} - - longest-streak@3.1.0: {} - - lowlight@1.20.0: - dependencies: - fault: 1.0.4 - highlight.js: 10.7.3 - - lru-cache@10.4.3: {} - - lru-cache@5.1.1: - dependencies: - yallist: 3.1.1 - - lucide-react@0.577.0(react@19.2.4): - dependencies: - react: 19.2.4 - - lz-string@1.5.0: {} - - magic-string@0.30.21: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - - markdown-table@3.0.4: {} - - marked@16.4.2: {} - - marked@17.0.5: {} - - mdast-util-find-and-replace@3.0.2: - dependencies: - '@types/mdast': 4.0.4 - escape-string-regexp: 5.0.0 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - mdast-util-from-markdown@2.0.3: - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - mdast-util-to-string: 4.0.0 - micromark: 4.0.2 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-decode-string: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - unist-util-stringify-position: 4.0.0 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-autolink-literal@2.0.1: - dependencies: - '@types/mdast': 4.0.4 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-find-and-replace: 3.0.2 - micromark-util-character: 2.1.1 - - mdast-util-gfm-footnote@2.1.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - micromark-util-normalize-identifier: 2.0.1 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-strikethrough@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-table@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - markdown-table: 3.0.4 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm-task-list-item@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-gfm@3.1.0: - dependencies: - mdast-util-from-markdown: 2.0.3 - mdast-util-gfm-autolink-literal: 2.0.1 - mdast-util-gfm-footnote: 2.1.0 - mdast-util-gfm-strikethrough: 2.0.0 - mdast-util-gfm-table: 2.0.0 - mdast-util-gfm-task-list-item: 2.0.0 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-math@3.0.0: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - longest-streak: 3.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - unist-util-remove-position: 5.0.0 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-expression@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-mdx-jsx@3.2.0: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - ccount: 2.0.1 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - parse-entities: 4.0.2 - stringify-entities: 4.0.4 - unist-util-stringify-position: 4.0.0 - vfile-message: 4.0.3 - transitivePeerDependencies: - - supports-color - - mdast-util-mdxjs-esm@2.0.1: - dependencies: - '@types/estree-jsx': 1.0.5 - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - devlop: 1.1.0 - mdast-util-from-markdown: 2.0.3 - mdast-util-to-markdown: 2.1.2 - transitivePeerDependencies: - - supports-color - - mdast-util-newline-to-break@2.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-find-and-replace: 3.0.2 - - mdast-util-phrasing@4.1.0: - dependencies: - '@types/mdast': 4.0.4 - unist-util-is: 6.0.1 - - mdast-util-to-hast@13.2.1: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@ungap/structured-clone': 1.3.0 - devlop: 1.1.0 - micromark-util-sanitize-uri: 2.0.1 - trim-lines: 3.0.1 - unist-util-position: 5.0.0 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - - mdast-util-to-markdown@2.1.2: - dependencies: - '@types/mdast': 4.0.4 - '@types/unist': 3.0.3 - longest-streak: 3.1.0 - mdast-util-phrasing: 4.1.0 - mdast-util-to-string: 4.0.0 - micromark-util-classify-character: 2.0.1 - micromark-util-decode-string: 2.0.1 - unist-util-visit: 5.1.0 - zwitch: 2.0.4 - - mdast-util-to-string@4.0.0: - dependencies: - '@types/mdast': 4.0.4 - - media-chrome@4.18.3(react@19.2.4): - dependencies: - ce-la-react: 0.3.2(react@19.2.4) - transitivePeerDependencies: - - react - - mermaid@11.14.0: - dependencies: - '@braintree/sanitize-url': 7.1.2 - '@iconify/utils': 3.1.0 - '@mermaid-js/parser': 1.1.0 - '@types/d3': 7.4.3 - '@upsetjs/venn.js': 2.0.0 - cytoscape: 3.33.1 - cytoscape-cose-bilkent: 4.1.0(cytoscape@3.33.1) - cytoscape-fcose: 2.2.0(cytoscape@3.33.1) - d3: 7.9.0 - d3-sankey: 0.12.3 - dagre-d3-es: 7.0.14 - dayjs: 1.11.20 - dompurify: 3.3.3 - katex: 0.16.44 - khroma: 2.1.0 - lodash-es: 4.17.23 - marked: 16.4.2 - roughjs: 4.6.6 - stylis: 4.3.6 - ts-dedent: 2.2.0 - uuid: 11.1.0 - - micromark-core-commonmark@2.0.3: - dependencies: - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - micromark-factory-destination: 2.0.1 - micromark-factory-label: 2.0.1 - micromark-factory-space: 2.0.1 - micromark-factory-title: 2.0.1 - micromark-factory-whitespace: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-html-tag-name: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-cjk-friendly-gfm-strikethrough@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2): - dependencies: - devlop: 1.1.0 - get-east-asian-width: 1.5.0 - micromark: 4.0.2 - micromark-extension-cjk-friendly-util: 3.0.1(micromark-util-types@2.0.2) - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - optionalDependencies: - micromark-util-types: 2.0.2 - - micromark-extension-cjk-friendly-util@3.0.1(micromark-util-types@2.0.2): - dependencies: - get-east-asian-width: 1.5.0 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - optionalDependencies: - micromark-util-types: 2.0.2 - - micromark-extension-cjk-friendly@2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2): - dependencies: - devlop: 1.1.0 - micromark: 4.0.2 - micromark-extension-cjk-friendly-util: 3.0.1(micromark-util-types@2.0.2) - micromark-util-chunked: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - optionalDependencies: - micromark-util-types: 2.0.2 - - micromark-extension-gfm-autolink-literal@2.1.0: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-footnote@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-strikethrough@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-classify-character: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-table@2.1.1: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm-tagfilter@2.0.0: - dependencies: - micromark-util-types: 2.0.2 - - micromark-extension-gfm-task-list-item@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-gfm@3.0.0: - dependencies: - micromark-extension-gfm-autolink-literal: 2.1.0 - micromark-extension-gfm-footnote: 2.1.0 - micromark-extension-gfm-strikethrough: 2.1.0 - micromark-extension-gfm-table: 2.1.1 - micromark-extension-gfm-tagfilter: 2.0.0 - micromark-extension-gfm-task-list-item: 2.1.0 - micromark-util-combine-extensions: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-extension-math@3.1.0: - dependencies: - '@types/katex': 0.16.8 - devlop: 1.1.0 - katex: 0.16.44 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-destination@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-label@2.0.1: - dependencies: - devlop: 1.1.0 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-space@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-types: 2.0.2 - - micromark-factory-title@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-factory-whitespace@2.0.1: - dependencies: - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-character@2.1.1: - dependencies: - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-chunked@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-classify-character@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-combine-extensions@2.0.1: - dependencies: - micromark-util-chunked: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-decode-numeric-character-reference@2.0.2: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-decode-string@2.0.1: - dependencies: - decode-named-character-reference: 1.3.0 - micromark-util-character: 2.1.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-symbol: 2.0.1 - - micromark-util-encode@2.0.1: {} - - micromark-util-html-tag-name@2.0.1: {} - - micromark-util-normalize-identifier@2.0.1: - dependencies: - micromark-util-symbol: 2.0.1 - - micromark-util-resolve-all@2.0.1: - dependencies: - micromark-util-types: 2.0.2 - - micromark-util-sanitize-uri@2.0.1: - dependencies: - micromark-util-character: 2.1.1 - micromark-util-encode: 2.0.1 - micromark-util-symbol: 2.0.1 - - micromark-util-subtokenize@2.1.0: - dependencies: - devlop: 1.1.0 - micromark-util-chunked: 2.0.1 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - - micromark-util-symbol@2.0.1: {} - - micromark-util-types@2.0.2: {} - - micromark@4.0.2: - dependencies: - '@types/debug': 4.1.13 - debug: 4.4.3 - decode-named-character-reference: 1.3.0 - devlop: 1.1.0 - micromark-core-commonmark: 2.0.3 - micromark-factory-space: 2.0.1 - micromark-util-character: 2.1.1 - micromark-util-chunked: 2.0.1 - micromark-util-combine-extensions: 2.0.1 - micromark-util-decode-numeric-character-reference: 2.0.2 - micromark-util-encode: 2.0.1 - micromark-util-normalize-identifier: 2.0.1 - micromark-util-resolve-all: 2.0.1 - micromark-util-sanitize-uri: 2.0.1 - micromark-util-subtokenize: 2.1.0 - micromark-util-symbol: 2.0.1 - micromark-util-types: 2.0.2 - transitivePeerDependencies: - - supports-color - - min-indent@1.0.1: {} - - mlly@1.8.2: - dependencies: - acorn: 8.16.0 - pathe: 2.0.3 - pkg-types: 1.3.1 - ufo: 1.6.3 - - motion-dom@12.38.0: - dependencies: - motion-utils: 12.36.0 - - motion-utils@12.36.0: {} - - motion@12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - framer-motion: 12.38.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - tslib: 2.8.1 - optionalDependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - ms@2.1.3: {} - - nanoid@3.3.11: {} - - nanoid@5.1.7: {} - - next-themes@0.4.6(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - node-releases@2.0.36: {} - - nwsapi@2.2.23: {} - - obug@2.1.1: {} - - oniguruma-parser@0.12.1: {} - - oniguruma-to-es@4.3.5: - dependencies: - oniguruma-parser: 0.12.1 - regex: 6.1.0 - regex-recursion: 6.0.2 - - package-manager-detector@1.6.0: {} - - parse-entities@4.0.2: - dependencies: - '@types/unist': 2.0.11 - character-entities-legacy: 3.0.0 - character-reference-invalid: 2.0.1 - decode-named-character-reference: 1.3.0 - is-alphanumerical: 2.0.1 - is-decimal: 2.0.1 - is-hexadecimal: 2.0.1 - - parse5@7.3.0: - dependencies: - entities: 6.0.1 - - path-data-parser@0.1.0: {} - - pathe@2.0.3: {} - - picocolors@1.1.1: {} - - picomatch@4.0.4: {} - - pkg-types@1.3.1: - dependencies: - confbox: 0.1.8 - mlly: 1.8.2 - pathe: 2.0.3 - - playwright-core@1.58.2: {} - - playwright@1.58.2: - dependencies: - playwright-core: 1.58.2 - optionalDependencies: - fsevents: 2.3.2 - - points-on-curve@0.2.0: {} - - points-on-path@0.2.1: - dependencies: - path-data-parser: 0.1.0 - points-on-curve: 0.2.0 - - postcss-selector-parser@6.0.10: - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - - postcss@8.5.8: - dependencies: - nanoid: 3.3.11 - picocolors: 1.1.1 - source-map-js: 1.2.1 - - pretty-format@27.5.1: - dependencies: - ansi-regex: 5.0.1 - ansi-styles: 5.2.0 - react-is: 17.0.2 - - prismjs@1.30.0: {} - - property-information@7.1.0: {} - - punycode@2.3.1: {} - - react-day-picker@9.14.0(react@19.2.4): - dependencies: - '@date-fns/tz': 1.4.1 - '@tabby_ai/hijri-converter': 1.0.5 - date-fns: 4.1.0 - date-fns-jalali: 4.1.0-0 - react: 19.2.4 - - react-dom@19.2.4(react@19.2.4): - dependencies: - react: 19.2.4 - scheduler: 0.27.0 - - react-hook-form@7.72.0(react@19.2.4): - dependencies: - react: 19.2.4 - - react-i18next@17.0.2(i18next@26.0.3(typescript@5.9.3))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(typescript@5.9.3): - dependencies: - '@babel/runtime': 7.29.2 - html-parse-stringify: 3.0.1 - i18next: 26.0.3(typescript@5.9.3) - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - optionalDependencies: - react-dom: 19.2.4(react@19.2.4) - typescript: 5.9.3 - - react-is@17.0.2: {} - - react-jsx-parser@2.4.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - acorn: 8.16.0 - acorn-jsx: 5.3.2(acorn@8.16.0) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - react-markdown@10.1.0(@types/react@19.2.14)(react@19.2.4): - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - '@types/react': 19.2.14 - devlop: 1.1.0 - hast-util-to-jsx-runtime: 2.3.6 - html-url-attributes: 3.0.1 - mdast-util-to-hast: 13.2.1 - react: 19.2.4 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - unified: 11.0.5 - unist-util-visit: 5.1.0 - vfile: 6.0.3 - transitivePeerDependencies: - - supports-color - - react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1): - dependencies: - '@types/use-sync-external-store': 0.0.6 - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - redux: 5.0.1 - - react-refresh@0.17.0: {} - - react-remove-scroll-bar@2.3.8(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - react-remove-scroll@2.7.2(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - react-remove-scroll-bar: 2.3.8(@types/react@19.2.14)(react@19.2.4) - react-style-singleton: 2.2.3(@types/react@19.2.14)(react@19.2.4) - tslib: 2.8.1 - use-callback-ref: 1.3.3(@types/react@19.2.14)(react@19.2.4) - use-sidecar: 1.1.3(@types/react@19.2.14)(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - - react-resizable-panels@4.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - react-style-singleton@2.2.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - get-nonce: 1.0.1 - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - react-syntax-highlighter@16.1.1(react@19.2.4): - dependencies: - '@babel/runtime': 7.29.2 - highlight.js: 10.7.3 - highlightjs-vue: 1.0.0 - lowlight: 1.20.0 - prismjs: 1.30.0 - react: 19.2.4 - refractor: 5.0.0 - - react@19.2.4: {} - - recharts@3.8.1(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react-is@17.0.2)(react@19.2.4)(redux@5.0.1): - dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1))(react@19.2.4) - clsx: 2.1.1 - decimal.js-light: 2.5.1 - es-toolkit: 1.45.1 - eventemitter3: 5.0.4 - immer: 10.2.0 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - react-is: 17.0.2 - react-redux: 9.2.0(@types/react@19.2.14)(react@19.2.4)(redux@5.0.1) - reselect: 5.1.1 - tiny-invariant: 1.3.3 - use-sync-external-store: 1.6.0(react@19.2.4) - victory-vendor: 37.3.6 - transitivePeerDependencies: - - '@types/react' - - redux - - redent@3.0.0: - dependencies: - indent-string: 4.0.0 - strip-indent: 3.0.0 - - redux-thunk@3.1.0(redux@5.0.1): - dependencies: - redux: 5.0.1 - - redux@5.0.1: {} - - refractor@5.0.0: - dependencies: - '@types/hast': 3.0.4 - '@types/prismjs': 1.26.6 - hastscript: 9.0.1 - parse-entities: 4.0.2 - - regex-recursion@6.0.2: - dependencies: - regex-utilities: 2.3.0 - - regex-utilities@2.3.0: {} - - regex@6.1.0: - dependencies: - regex-utilities: 2.3.0 - - rehype-harden@1.1.8: - dependencies: - unist-util-visit: 5.1.0 - - rehype-katex@7.0.1: - dependencies: - '@types/hast': 3.0.4 - '@types/katex': 0.16.8 - hast-util-from-html-isomorphic: 2.0.0 - hast-util-to-text: 4.0.2 - katex: 0.16.44 - unist-util-visit-parents: 6.0.2 - vfile: 6.0.3 - - rehype-raw@7.0.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-raw: 9.1.0 - vfile: 6.0.3 - - rehype-sanitize@6.0.0: - dependencies: - '@types/hast': 3.0.4 - hast-util-sanitize: 5.0.2 - - remark-breaks@4.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-newline-to-break: 2.0.0 - unified: 11.0.5 - - remark-cjk-friendly-gfm-strikethrough@2.0.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5): - dependencies: - micromark-extension-cjk-friendly-gfm-strikethrough: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2) - unified: 11.0.5 - optionalDependencies: - '@types/mdast': 4.0.4 - transitivePeerDependencies: - - micromark - - micromark-util-types - - remark-cjk-friendly@2.0.1(@types/mdast@4.0.4)(micromark-util-types@2.0.2)(micromark@4.0.2)(unified@11.0.5): - dependencies: - micromark-extension-cjk-friendly: 2.0.1(micromark-util-types@2.0.2)(micromark@4.0.2) - unified: 11.0.5 - optionalDependencies: - '@types/mdast': 4.0.4 - transitivePeerDependencies: - - micromark - - micromark-util-types - - remark-gfm@4.0.1: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-gfm: 3.1.0 - micromark-extension-gfm: 3.0.0 - remark-parse: 11.0.0 - remark-stringify: 11.0.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-math@6.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-math: 3.0.0 - micromark-extension-math: 3.1.0 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-parse@11.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-from-markdown: 2.0.3 - micromark-util-types: 2.0.2 - unified: 11.0.5 - transitivePeerDependencies: - - supports-color - - remark-rehype@11.1.2: - dependencies: - '@types/hast': 3.0.4 - '@types/mdast': 4.0.4 - mdast-util-to-hast: 13.2.1 - unified: 11.0.5 - vfile: 6.0.3 - - remark-stringify@11.0.0: - dependencies: - '@types/mdast': 4.0.4 - mdast-util-to-markdown: 2.1.2 - unified: 11.0.5 - - remend@1.3.0: {} - - reselect@5.1.1: {} - - resolve-pkg-maps@1.0.0: {} - - robust-predicates@3.0.3: {} - - rollup@4.60.0: - dependencies: - '@types/estree': 1.0.8 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.60.0 - '@rollup/rollup-android-arm64': 4.60.0 - '@rollup/rollup-darwin-arm64': 4.60.0 - '@rollup/rollup-darwin-x64': 4.60.0 - '@rollup/rollup-freebsd-arm64': 4.60.0 - '@rollup/rollup-freebsd-x64': 4.60.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.60.0 - '@rollup/rollup-linux-arm-musleabihf': 4.60.0 - '@rollup/rollup-linux-arm64-gnu': 4.60.0 - '@rollup/rollup-linux-arm64-musl': 4.60.0 - '@rollup/rollup-linux-loong64-gnu': 4.60.0 - '@rollup/rollup-linux-loong64-musl': 4.60.0 - '@rollup/rollup-linux-ppc64-gnu': 4.60.0 - '@rollup/rollup-linux-ppc64-musl': 4.60.0 - '@rollup/rollup-linux-riscv64-gnu': 4.60.0 - '@rollup/rollup-linux-riscv64-musl': 4.60.0 - '@rollup/rollup-linux-s390x-gnu': 4.60.0 - '@rollup/rollup-linux-x64-gnu': 4.60.0 - '@rollup/rollup-linux-x64-musl': 4.60.0 - '@rollup/rollup-openbsd-x64': 4.60.0 - '@rollup/rollup-openharmony-arm64': 4.60.0 - '@rollup/rollup-win32-arm64-msvc': 4.60.0 - '@rollup/rollup-win32-ia32-msvc': 4.60.0 - '@rollup/rollup-win32-x64-gnu': 4.60.0 - '@rollup/rollup-win32-x64-msvc': 4.60.0 - fsevents: 2.3.3 - - roughjs@4.6.6: - dependencies: - hachure-fill: 0.5.2 - path-data-parser: 0.1.0 - points-on-curve: 0.2.0 - points-on-path: 0.2.1 - - rrweb-cssom@0.8.0: {} - - rw@1.3.3: {} - - safer-buffer@2.1.2: {} - - saxes@6.0.0: - dependencies: - xmlchars: 2.2.0 - - scheduler@0.27.0: {} - - semver@6.3.1: {} - - shiki@3.23.0: - dependencies: - '@shikijs/core': 3.23.0 - '@shikijs/engine-javascript': 3.23.0 - '@shikijs/engine-oniguruma': 3.23.0 - '@shikijs/langs': 3.23.0 - '@shikijs/themes': 3.23.0 - '@shikijs/types': 3.23.0 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - shiki@4.0.2: - dependencies: - '@shikijs/core': 4.0.2 - '@shikijs/engine-javascript': 4.0.2 - '@shikijs/engine-oniguruma': 4.0.2 - '@shikijs/langs': 4.0.2 - '@shikijs/themes': 4.0.2 - '@shikijs/types': 4.0.2 - '@shikijs/vscode-textmate': 10.0.2 - '@types/hast': 3.0.4 - - siginfo@2.0.0: {} - - sonner@2.0.7(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - - source-map-js@1.2.1: {} - - space-separated-tokens@2.0.2: {} - - split-type@0.3.4: {} - - stackback@0.0.2: {} - - std-env@4.0.0: {} - - streamdown@2.5.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - clsx: 2.1.1 - hast-util-to-jsx-runtime: 2.3.6 - html-url-attributes: 3.0.1 - marked: 17.0.5 - mermaid: 11.14.0 - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - rehype-harden: 1.1.8 - rehype-raw: 7.0.0 - rehype-sanitize: 6.0.0 - remark-gfm: 4.0.1 - remark-parse: 11.0.0 - remark-rehype: 11.1.2 - remend: 1.3.0 - tailwind-merge: 3.5.0 - unified: 11.0.5 - unist-util-visit: 5.1.0 - unist-util-visit-parents: 6.0.2 - transitivePeerDependencies: - - supports-color - - stringify-entities@4.0.4: - dependencies: - character-entities-html4: 2.1.0 - character-entities-legacy: 3.0.0 - - strip-indent@3.0.0: - dependencies: - min-indent: 1.0.1 - - style-to-js@1.1.21: - dependencies: - style-to-object: 1.0.14 - - style-to-object@1.0.14: - dependencies: - inline-style-parser: 0.2.7 - - stylis@4.3.6: {} - - symbol-tree@3.2.4: {} - - tailwind-merge@3.5.0: {} - - tailwindcss@4.2.2: {} - - tapable@2.3.2: {} - - tiny-invariant@1.3.3: {} - - tinybench@2.9.0: {} - - tinyexec@1.0.4: {} - - tinyglobby@0.2.15: - dependencies: - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - - tinyrainbow@3.1.0: {} - - tldts-core@6.1.86: {} - - tldts@6.1.86: - dependencies: - tldts-core: 6.1.86 - - tokenlens@1.3.1: - dependencies: - '@tokenlens/core': 1.3.0 - '@tokenlens/fetch': 1.3.0 - '@tokenlens/helpers': 1.3.1 - '@tokenlens/models': 1.3.0 - - tough-cookie@5.1.2: - dependencies: - tldts: 6.1.86 - - tr46@5.1.1: - dependencies: - punycode: 2.3.1 - - trim-lines@3.0.1: {} - - trough@2.2.0: {} - - ts-dedent@2.2.0: {} - - tslib@2.8.1: {} - - tsx@4.21.0: - dependencies: - esbuild: 0.27.4 - get-tsconfig: 4.13.7 - optionalDependencies: - fsevents: 2.3.3 - - tw-animate-css@1.4.0: {} - - typescript@5.9.3: {} - - uc.micro@1.0.6: {} - - ufo@1.6.3: {} - - unified@11.0.5: - dependencies: - '@types/unist': 3.0.3 - bail: 2.0.2 - devlop: 1.1.0 - extend: 3.0.2 - is-plain-obj: 4.1.0 - trough: 2.2.0 - vfile: 6.0.3 - - unist-util-find-after@5.0.0: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - - unist-util-is@6.0.1: - dependencies: - '@types/unist': 3.0.3 - - unist-util-position@5.0.0: - dependencies: - '@types/unist': 3.0.3 - - unist-util-remove-position@5.0.0: - dependencies: - '@types/unist': 3.0.3 - unist-util-visit: 5.1.0 - - unist-util-stringify-position@4.0.0: - dependencies: - '@types/unist': 3.0.3 - - unist-util-visit-parents@6.0.2: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - - unist-util-visit@5.1.0: - dependencies: - '@types/unist': 3.0.3 - unist-util-is: 6.0.1 - unist-util-visit-parents: 6.0.2 - - update-browserslist-db@1.2.3(browserslist@4.28.1): - dependencies: - browserslist: 4.28.1 - escalade: 3.2.0 - picocolors: 1.1.1 - - use-callback-ref@1.3.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - use-sidecar@1.1.3(@types/react@19.2.14)(react@19.2.4): - dependencies: - detect-node-es: 1.1.0 - react: 19.2.4 - tslib: 2.8.1 - optionalDependencies: - '@types/react': 19.2.14 - - use-stick-to-bottom@1.1.3(react@19.2.4): - dependencies: - react: 19.2.4 - - use-sync-external-store@1.6.0(react@19.2.4): - dependencies: - react: 19.2.4 - - util-deprecate@1.0.2: {} - - uuid@11.1.0: {} - - vaul@1.1.2(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): - dependencies: - '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - react: 19.2.4 - react-dom: 19.2.4(react@19.2.4) - transitivePeerDependencies: - - '@types/react' - - '@types/react-dom' - - vfile-location@5.0.3: - dependencies: - '@types/unist': 3.0.3 - vfile: 6.0.3 - - vfile-message@4.0.3: - dependencies: - '@types/unist': 3.0.3 - unist-util-stringify-position: 4.0.0 - - vfile@6.0.3: - dependencies: - '@types/unist': 3.0.3 - vfile-message: 4.0.3 - - victory-vendor@37.3.6: - dependencies: - '@types/d3-array': 3.2.2 - '@types/d3-ease': 3.0.2 - '@types/d3-interpolate': 3.0.4 - '@types/d3-scale': 4.0.9 - '@types/d3-shape': 3.1.8 - '@types/d3-time': 3.0.4 - '@types/d3-timer': 3.0.2 - d3-array: 3.2.4 - d3-ease: 3.0.1 - d3-interpolate: 3.0.1 - d3-scale: 4.0.2 - d3-shape: 3.2.0 - d3-time: 3.1.0 - d3-timer: 3.0.1 - - vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0): - dependencies: - esbuild: 0.27.4 - fdir: 6.5.0(picomatch@4.0.4) - picomatch: 4.0.4 - postcss: 8.5.8 - rollup: 4.60.0 - tinyglobby: 0.2.15 - optionalDependencies: - fsevents: 2.3.3 - jiti: 2.6.1 - lightningcss: 1.32.0 - tsx: 4.21.0 - - vitest@4.1.2(@opentelemetry/api@1.9.0)(jsdom@26.1.0)(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)): - dependencies: - '@vitest/expect': 4.1.2 - '@vitest/mocker': 4.1.2(vite@7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0)) - '@vitest/pretty-format': 4.1.2 - '@vitest/runner': 4.1.2 - '@vitest/snapshot': 4.1.2 - '@vitest/spy': 4.1.2 - '@vitest/utils': 4.1.2 - es-module-lexer: 2.0.0 - expect-type: 1.3.0 - magic-string: 0.30.21 - obug: 2.1.1 - pathe: 2.0.3 - picomatch: 4.0.4 - std-env: 4.0.0 - tinybench: 2.9.0 - tinyexec: 1.0.4 - tinyglobby: 0.2.15 - tinyrainbow: 3.1.0 - vite: 7.3.1(jiti@2.6.1)(lightningcss@1.32.0)(tsx@4.21.0) - why-is-node-running: 2.3.0 - optionalDependencies: - '@opentelemetry/api': 1.9.0 - jsdom: 26.1.0 - transitivePeerDependencies: - - msw - - void-elements@3.1.0: {} - - vscode-jsonrpc@8.2.0: {} - - vscode-languageserver-protocol@3.17.5: - dependencies: - vscode-jsonrpc: 8.2.0 - vscode-languageserver-types: 3.17.5 - - vscode-languageserver-textdocument@1.0.12: {} - - vscode-languageserver-types@3.17.5: {} - - vscode-languageserver@9.0.1: - dependencies: - vscode-languageserver-protocol: 3.17.5 - - vscode-uri@3.1.0: {} - - w3c-xmlserializer@5.0.0: - dependencies: - xml-name-validator: 5.0.0 - - web-namespaces@2.0.1: {} - - webidl-conversions@7.0.0: {} - - whatwg-encoding@3.1.1: - dependencies: - iconv-lite: 0.6.3 - - whatwg-mimetype@4.0.0: {} - - whatwg-url@14.2.0: - dependencies: - tr46: 5.1.1 - webidl-conversions: 7.0.0 - - why-is-node-running@2.3.0: - dependencies: - siginfo: 2.0.0 - stackback: 0.0.2 - - ws@8.20.0: {} - - xml-name-validator@5.0.0: {} - - xmlchars@2.2.0: {} - - yallist@3.1.1: {} - - zod@3.25.76: {} - - zod@4.3.6: {} - - zustand@4.5.7(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4): - dependencies: - use-sync-external-store: 1.6.0(react@19.2.4) - optionalDependencies: - '@types/react': 19.2.14 - immer: 11.1.4 - react: 19.2.4 - - zustand@5.0.12(@types/react@19.2.14)(immer@11.1.4)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): - optionalDependencies: - '@types/react': 19.2.14 - immer: 11.1.4 - react: 19.2.4 - use-sync-external-store: 1.6.0(react@19.2.4) - - zwitch@2.0.4: {} diff --git a/ui/goose2/scripts/check-file-sizes.mjs b/ui/goose2/scripts/check-file-sizes.mjs index 03869a5e23..397f47e0cb 100644 --- a/ui/goose2/scripts/check-file-sizes.mjs +++ b/ui/goose2/scripts/check-file-sizes.mjs @@ -26,19 +26,9 @@ const EXCEPTIONS = { "Search-as-you-type filtering and draft-aware sidebar highlight logic.", }, "src/app/AppShell.tsx": { - limit: 640, + limit: 650, justification: - "Shell still coordinates ACP session loading, project reassignment, and app-level chat routing.", - }, - "src/features/chat/hooks/useAcpStream.ts": { - limit: 580, - justification: - "ACP replay, streaming, session binding, model-state event handling, and replay timeout are still centralized here.", - }, - "src/features/chat/hooks/__tests__/useAcpStream.test.ts": { - limit: 570, - justification: - "Covers replay buffering, timeout error state, streaming edge cases, and provider identity persistence in one cohesive suite.", + "Shell still coordinates ACP session loading, replay-buffer cleanup on load failure, project reassignment, and app-level chat routing.", }, "src/features/chat/stores/__tests__/chatSessionStore.test.ts": { limit: 540, @@ -55,21 +45,6 @@ const EXCEPTIONS = { justification: "Project CRUD plus reorder_projects command for sidebar drag-and-drop ordering.", }, - "src-tauri/src/services/acp/manager/dispatcher.rs": { - limit: 540, - justification: - "ACP replay and live-stream event fan-out share one dispatcher with replay event counting for drain stabilisation.", - }, - "src-tauri/src/services/acp/manager.rs": { - limit: 630, - justification: - "ACP manager command dispatch loop — export/import/fork session ext_method dispatch adds boilerplate.", - }, - "src-tauri/src/services/acp/manager/session_ops.rs": { - limit: 620, - justification: - "Session prepare/load/list logic, working-dir updates, wait_for_replay_drain helper with iteration cap, and composite prepared-session reuse remain colocated while ACP session ownership stabilizes.", - }, "src-tauri/src/commands/system.rs": { limit: 640, justification: diff --git a/ui/goose2/src-tauri/Cargo.lock b/ui/goose2/src-tauri/Cargo.lock index ddaef39fde..6db33f2015 100644 --- a/ui/goose2/src-tauri/Cargo.lock +++ b/ui/goose2/src-tauri/Cargo.lock @@ -2,23 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "acp-client" -version = "0.1.0" -source = "git+https://github.com/block/builderbot?rev=db184d20cb48e0c90bbd3fea4a4a871fc9d8a6ad#db184d20cb48e0c90bbd3fea4a4a871fc9d8a6ad" -dependencies = [ - "agent-client-protocol", - "anyhow", - "async-trait", - "blox-cli", - "log", - "nix", - "serde", - "serde_json", - "tokio", - "tokio-util", -] - [[package]] name = "adler2" version = "2.0.1" @@ -36,37 +19,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "agent-client-protocol" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10eeef5e80864f9c3c148a3f395c3e35a66d37ec7561c7845b2bffae8e841759" -dependencies = [ - "agent-client-protocol-schema", - "anyhow", - "async-broadcast", - "async-trait", - "derive_more 2.1.1", - "futures", - "log", - "serde", - "serde_json", -] - -[[package]] -name = "agent-client-protocol-schema" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca68e7e55681ce56546c0cecc6bc8f20493d24b44c6d93ec46174f310730bba2" -dependencies = [ - "anyhow", - "derive_more 2.1.1", - "schemars 1.2.1", - "serde", - "serde_json", - "strum", -] - [[package]] name = "ahash" version = "0.7.8" @@ -400,18 +352,6 @@ dependencies = [ "piper", ] -[[package]] -name = "blox-cli" -version = "0.1.0" -source = "git+https://github.com/block/builderbot?rev=db184d20cb48e0c90bbd3fea4a4a871fc9d8a6ad#db184d20cb48e0c90bbd3fea4a4a871fc9d8a6ad" -dependencies = [ - "log", - "serde", - "serde_json", - "thiserror 2.0.18", - "wait-timeout", -] - [[package]] name = "borsh" version = "1.6.1" @@ -702,15 +642,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" -[[package]] -name = "convert_case" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "cookie" version = "0.18.1" @@ -917,12 +848,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "data-encoding" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" - [[package]] name = "dbus" version = "0.9.10" @@ -968,7 +893,7 @@ version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "convert_case 0.4.0", + "convert_case", "proc-macro2", "quote", "rustc_version", @@ -990,12 +915,10 @@ version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "convert_case 0.10.0", "proc-macro2", "quote", "rustc_version", "syn 2.0.117", - "unicode-xid", ] [[package]] @@ -1372,21 +1295,6 @@ dependencies = [ "new_debug_unreachable", ] -[[package]] -name = "futures" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - [[package]] name = "futures-channel" version = "0.3.32" @@ -1394,7 +1302,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", - "futures-sink", ] [[package]] @@ -1462,7 +1369,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ - "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -1751,15 +1657,11 @@ dependencies = [ name = "goose2" version = "0.1.0" dependencies = [ - "acp-client", - "agent-client-protocol", - "async-trait", "base64 0.22.1", "chrono", "dirs", "doctor", "etcetera", - "futures", "ignore", "keyring", "log", @@ -1776,8 +1678,6 @@ dependencies = [ "tauri-plugin-window-state", "tempfile", "tokio", - "tokio-tungstenite", - "tokio-util", "uuid", ] @@ -3826,7 +3726,7 @@ checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" dependencies = [ "dyn-clone", "indexmap 1.9.3", - "schemars_derive 0.8.22", + "schemars_derive", "serde", "serde_json", "url", @@ -3853,7 +3753,6 @@ checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" dependencies = [ "dyn-clone", "ref-cast", - "schemars_derive 1.2.1", "serde", "serde_json", ] @@ -3870,18 +3769,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "schemars_derive" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" -dependencies = [ - "proc-macro2", - "quote", - "serde_derive_internals", - "syn 2.0.117", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -4375,27 +4262,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "strum" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.117", -] - [[package]] name = "subtle" version = "2.6.1" @@ -5034,18 +4900,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tokio-tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" -dependencies = [ - "futures-util", - "log", - "tokio", - "tungstenite", -] - [[package]] name = "tokio-util" version = "0.7.18" @@ -5054,9 +4908,7 @@ checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", - "futures-io", "futures-sink", - "futures-util", "pin-project-lite", "tokio", ] @@ -5270,25 +5122,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand 0.8.5", - "sha1", - "thiserror 1.0.69", - "url", - "utf-8", -] - [[package]] name = "typeid" version = "1.0.3" @@ -5476,15 +5309,6 @@ dependencies = [ "libc", ] -[[package]] -name = "wait-timeout" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ac3b126d3914f9849036f826e054cbabdc8519970b8998ddaf3b5bd3c65f11" -dependencies = [ - "libc", -] - [[package]] name = "walkdir" version = "2.5.0" diff --git a/ui/goose2/src-tauri/Cargo.toml b/ui/goose2/src-tauri/Cargo.toml index 3c944ea0d4..230cc32086 100644 --- a/ui/goose2/src-tauri/Cargo.toml +++ b/ui/goose2/src-tauri/Cargo.toml @@ -32,12 +32,6 @@ uuid = { version = "1", features = ["v4", "serde"] } chrono = { version = "0.4", features = ["serde"] } serde_yaml = "0.9" etcetera = "0.8" -futures = "0.3" -tokio-util = { version = "0.7", features = ["compat", "rt"] } -async-trait = "0.1" -agent-client-protocol = { version = "0.10.4", features = ["unstable_session_fork"] } -tokio-tungstenite = "0.21.0" -acp-client = { git = "https://github.com/block/builderbot", rev = "db184d20cb48e0c90bbd3fea4a4a871fc9d8a6ad" } doctor = { git = "https://github.com/block/builderbot", rev = "8e1c3ec145edc0df5f04b4427cfd758378036862" } ignore = "0.4.25" base64 = "0.22" diff --git a/ui/goose2/src-tauri/src/commands/acp.rs b/ui/goose2/src-tauri/src/commands/acp.rs index b18134f7ae..f6b0c7d179 100644 --- a/ui/goose2/src-tauri/src/commands/acp.rs +++ b/ui/goose2/src-tauri/src/commands/acp.rs @@ -1,84 +1,4 @@ -use serde::Serialize; -use std::path::PathBuf; -use std::sync::Arc; -use tauri::{AppHandle, State}; - -use crate::services::acp::{ - make_composite_key, search_sessions_via_exports, AcpRunningSession, AcpService, AcpSessionInfo, - AcpSessionRegistry, GooseAcpManager, GooseServeProcess, SessionSearchResult, -}; - -const DEPRECATED_PROVIDER_IDS: &[&str] = &["claude-code", "codex", "gemini-cli"]; - -/// Response type for an ACP provider, sent to the frontend. -#[derive(Serialize)] -#[serde(rename_all = "camelCase")] -pub struct AcpProviderResponse { - id: String, - label: String, -} - -fn should_include_provider(provider_id: &str) -> bool { - !DEPRECATED_PROVIDER_IDS.contains(&provider_id) -} - -fn default_artifacts_working_dir() -> PathBuf { - if let Some(home_dir) = dirs::home_dir() { - return home_dir.join(".goose").join("artifacts"); - } - PathBuf::from("/tmp").join(".goose").join("artifacts") -} - -fn expand_home_dir(path: PathBuf) -> PathBuf { - let path_string = path.to_string_lossy(); - - if path_string == "~" { - return dirs::home_dir().unwrap_or(path); - } - - if let Some(stripped) = path_string - .strip_prefix("~/") - .or_else(|| path_string.strip_prefix("~\\")) - { - if let Some(home_dir) = dirs::home_dir() { - return home_dir.join(stripped); - } - } - - path -} - -fn resolve_working_dir( - working_dir: Option, - current_dir: &std::path::Path, -) -> Result { - let working_dir = working_dir - .map(|dir| dir.trim().to_string()) - .filter(|dir| !dir.is_empty()) - .map(PathBuf::from) - .unwrap_or_else(default_artifacts_working_dir); - let working_dir = expand_home_dir(working_dir); - - let working_dir = if working_dir.is_relative() { - current_dir.join(&working_dir) - } else { - working_dir - }; - - std::fs::create_dir_all(&working_dir).map_err(|error| { - format!( - "Failed to create working directory '{}': {error}", - working_dir.display() - ) - })?; - - std::fs::canonicalize(&working_dir).map_err(|error| { - format!( - "Failed to resolve working directory '{}': {error}", - working_dir.display() - ) - }) -} +use crate::services::acp::GooseServeProcess; #[tauri::command] pub async fn get_goose_serve_url() -> Result { @@ -86,252 +6,3 @@ pub async fn get_goose_serve_url() -> Result { let process = GooseServeProcess::get()?; Ok(process.ws_url()) } - -/// Return the list of providers available through goose serve. -#[tauri::command] -pub async fn discover_acp_providers( - app_handle: AppHandle, -) -> Result, String> { - let manager = GooseAcpManager::start(app_handle).await?; - let providers = manager.list_providers().await?; - Ok(providers - .into_iter() - .filter(|provider| should_include_provider(&provider.id)) - .map(|provider| AcpProviderResponse { - id: provider.id, - label: provider.label, - }) - .collect()) -} - -/// Send a prompt to an ACP agent and stream the response via Tauri events. -/// -/// The actual content arrives asynchronously through `acp:text`, `acp:tool_call`, -/// `acp:tool_result`, and `acp:done` events. -#[allow(clippy::too_many_arguments)] -#[tauri::command] -pub async fn acp_send_message( - app_handle: AppHandle, - registry: State<'_, Arc>, - session_id: String, - provider_id: String, - prompt: String, - system_prompt: Option, - working_dir: Option, - persona_id: Option, - persona_name: Option, - images: Vec<(String, String)>, -) -> Result<(), String> { - let current_dir = std::env::current_dir() - .map_err(|error| format!("Failed to determine current working directory: {error}"))?; - let working_dir = resolve_working_dir(working_dir, ¤t_dir)?; - - AcpService::send_prompt( - app_handle, - Arc::clone(®istry), - session_id, - provider_id, - prompt, - working_dir, - system_prompt, - persona_id, - persona_name, - images, - ) - .await -} - -#[tauri::command] -pub async fn acp_prepare_session( - app_handle: AppHandle, - session_id: String, - provider_id: String, - working_dir: Option, - persona_id: Option, -) -> Result<(), String> { - let current_dir = std::env::current_dir() - .map_err(|error| format!("Failed to determine current working directory: {error}"))?; - let working_dir = resolve_working_dir(working_dir, ¤t_dir)?; - - AcpService::prepare_session(app_handle, session_id, provider_id, working_dir, persona_id).await -} - -#[tauri::command] -pub async fn acp_set_model( - app_handle: AppHandle, - session_id: String, - model_id: String, -) -> Result<(), String> { - let manager = GooseAcpManager::start(app_handle).await?; - manager.set_model(session_id, model_id).await -} - -/// List all sessions known to the goose binary. -#[tauri::command] -pub async fn acp_list_sessions(app_handle: AppHandle) -> Result, String> { - let manager = GooseAcpManager::start(app_handle).await?; - manager.list_sessions().await -} - -/// Search session message content via exported Goose sessions. -#[tauri::command] -pub async fn acp_search_sessions( - app_handle: AppHandle, - query: String, - session_ids: Vec, -) -> Result, String> { - let manager = GooseAcpManager::start(app_handle).await?; - search_sessions_via_exports(&manager, &query, &session_ids).await -} - -/// Load an existing session, replaying its messages as Tauri events. -/// -/// The goose binary sends `SessionNotification` events for each message in -/// the session history. The frontend's `useAcpStream` hook picks these up -/// the same way it handles live streaming. -#[tauri::command] -pub async fn acp_load_session( - app_handle: AppHandle, - session_id: String, - goose_session_id: String, - working_dir: Option, -) -> Result<(), String> { - let current_dir = std::env::current_dir() - .map_err(|error| format!("Failed to determine current working directory: {error}"))?; - let working_dir = resolve_working_dir(working_dir, ¤t_dir)?; - - let manager = GooseAcpManager::start(app_handle).await?; - manager - .load_session(session_id, goose_session_id, working_dir) - .await -} - -#[cfg(test)] -mod tests { - use super::{expand_home_dir, resolve_working_dir, should_include_provider}; - use std::path::PathBuf; - - #[test] - fn resolve_working_dir_returns_absolute_path_for_existing_relative_directory() { - let temp_dir = tempfile::tempdir().expect("temp dir"); - let nested_dir = temp_dir.path().join("nested"); - std::fs::create_dir(&nested_dir).expect("create nested dir"); - - let resolved = - resolve_working_dir(Some("nested".to_string()), temp_dir.path()).expect("resolve path"); - - assert!(resolved.is_absolute()); - assert_eq!( - resolved, - std::fs::canonicalize(&nested_dir).expect("canonical nested dir") - ); - } - - #[test] - fn resolve_working_dir_creates_missing_directory() { - let temp_dir = tempfile::tempdir().expect("temp dir"); - let missing_dir = temp_dir.path().join("missing"); - let resolved = resolve_working_dir(Some("missing".to_string()), temp_dir.path()) - .expect("resolve path"); - - assert!(missing_dir.exists()); - assert_eq!( - resolved, - std::fs::canonicalize(&missing_dir).expect("canonical missing dir") - ); - } - - #[test] - fn expand_home_dir_replaces_leading_tilde() { - let home_dir = dirs::home_dir().expect("home dir"); - - assert_eq!(expand_home_dir(PathBuf::from("~")), home_dir); - assert_eq!( - expand_home_dir(PathBuf::from("~/Code/goose2")), - home_dir.join("Code/goose2") - ); - } - - #[test] - fn provider_discovery_hides_deprecated_cli_providers() { - assert!(!should_include_provider("claude-code")); - assert!(!should_include_provider("codex")); - assert!(!should_include_provider("gemini-cli")); - assert!(should_include_provider("goose")); - assert!(should_include_provider("claude-acp")); - assert!(should_include_provider("codex-acp")); - } -} - -/// Cancel a running ACP session. -/// -/// When `persona_id` is provided the composite key `{session_id}__{persona_id}` -/// is used so only that persona's stream is cancelled. -#[tauri::command] -pub async fn acp_cancel_session( - app_handle: AppHandle, - registry: State<'_, Arc>, - session_id: String, - persona_id: Option, -) -> Result { - let key = make_composite_key(&session_id, persona_id.as_deref()); - let _assistant_message_id = registry.cancel(&key); - let manager = GooseAcpManager::start(app_handle).await?; - let was_cancelled = manager.cancel_session(key).await?; - - Ok(was_cancelled) -} - -/// List all currently running ACP sessions. -#[tauri::command] -pub async fn acp_list_running( - registry: State<'_, Arc>, -) -> Result, String> { - Ok(registry.list_running()) -} - -/// Cancel all running ACP sessions (used during shutdown). -#[tauri::command] -pub async fn acp_cancel_all(registry: State<'_, Arc>) -> Result<(), String> { - registry.cancel_all(); - Ok(()) -} - -/// Export a session as JSON via the goose binary. -/// -/// The goose binary reads the session from its database and returns -/// an OG-goose-compatible JSON string with a `conversation` field. -#[tauri::command] -pub async fn acp_export_session( - app_handle: AppHandle, - session_id: String, -) -> Result { - let manager = GooseAcpManager::start(app_handle).await?; - manager.export_session(session_id).await -} - -/// Import a session from JSON via the goose binary. -/// -/// The goose binary parses the JSON (detecting OG vs v1 format), -/// creates a new session, populates messages, and returns metadata. -#[tauri::command] -pub async fn acp_import_session( - app_handle: AppHandle, - json: String, -) -> Result { - let manager = GooseAcpManager::start(app_handle).await?; - manager.import_session(json).await -} - -/// Duplicate (fork) a session via the goose binary. -/// -/// The goose binary reads the source session, creates a new one -/// with the same messages, and returns the new session's metadata. -#[tauri::command] -pub async fn acp_duplicate_session( - app_handle: AppHandle, - session_id: String, -) -> Result { - let manager = GooseAcpManager::start(app_handle).await?; - manager.fork_session(session_id).await -} diff --git a/ui/goose2/src-tauri/src/lib.rs b/ui/goose2/src-tauri/src/lib.rs index af479009e4..3648333bd3 100644 --- a/ui/goose2/src-tauri/src/lib.rs +++ b/ui/goose2/src-tauri/src/lib.rs @@ -2,18 +2,12 @@ mod commands; mod services; mod types; -use std::sync::Arc; - -use services::acp::AcpSessionRegistry; use services::goose_config::GooseConfig; use services::personas::PersonaStore; use tauri_plugin_window_state::StateFlags; #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { - let acp_registry = Arc::new(AcpSessionRegistry::new()); - let acp_registry_for_exit = Arc::clone(&acp_registry); - let builder = tauri::Builder::default() .plugin( tauri_plugin_log::Builder::new() @@ -31,8 +25,7 @@ pub fn run() { .build(), ) .manage(PersonaStore::new()) - .manage(GooseConfig::new()) - .manage(acp_registry); + .manage(GooseConfig::new()); #[cfg(feature = "app-test-driver")] let builder = builder.plugin(tauri_plugin_app_test_driver::init()); @@ -50,19 +43,6 @@ pub fn run() { commands::agents::save_persona_avatar_bytes, commands::agents::get_avatars_dir, commands::acp::get_goose_serve_url, - commands::acp::discover_acp_providers, - commands::acp::acp_prepare_session, - commands::acp::acp_set_model, - commands::acp::acp_send_message, - commands::acp::acp_cancel_session, - commands::acp::acp_list_sessions, - commands::acp::acp_search_sessions, - commands::acp::acp_load_session, - commands::acp::acp_list_running, - commands::acp::acp_cancel_all, - commands::acp::acp_export_session, - commands::acp::acp_import_session, - commands::acp::acp_duplicate_session, commands::skills::create_skill, commands::skills::list_skills, commands::skills::delete_skill, @@ -114,9 +94,5 @@ pub fn run() { .setup(|_app| Ok(())) .build(tauri::generate_context!()) .expect("error while building tauri application") - .run(move |_app, event| { - if let tauri::RunEvent::Exit = event { - acp_registry_for_exit.cancel_all(); - } - }); + .run(|_app, _event| {}); } diff --git a/ui/goose2/src-tauri/src/services/acp/goose_serve.rs b/ui/goose2/src-tauri/src/services/acp/goose_serve.rs index 5603f7cdaa..1fbedfdeee 100644 --- a/ui/goose2/src-tauri/src/services/acp/goose_serve.rs +++ b/ui/goose2/src-tauri/src/services/acp/goose_serve.rs @@ -1,16 +1,18 @@ -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::time::{Duration, Instant}; -use futures::{SinkExt, StreamExt}; use tokio::process::{Child, Command}; use tokio::sync::OnceCell; -use tokio_tungstenite::connect_async; const GOOSE_SERVE_CONNECT_TIMEOUT: Duration = Duration::from_secs(30); const GOOSE_SERVE_CONNECT_RETRY_DELAY: Duration = Duration::from_millis(100); const LOCALHOST: &str = "127.0.0.1"; -pub(crate) const WS_BRIDGE_BUFFER_BYTES: usize = 64 * 1024; - +const COMMON_GOOSE_PATHS: &[&str] = &[ + "/opt/homebrew/bin", + "/usr/local/bin", + "/usr/bin", + "/home/linuxbrew/.linuxbrew/bin", +]; // --------------------------------------------------------------------------- // GooseServeProcess — singleton that owns the long-lived `goose serve` child // --------------------------------------------------------------------------- @@ -97,9 +99,7 @@ impl GooseServeProcess { ) })?; - // Wait for the server to become ready by polling the WebSocket endpoint. - let ws_url = format!("ws://{LOCALHOST}:{port}/acp"); - wait_for_server_ready(&ws_url, &mut child).await?; + wait_for_server_ready(port, &mut child).await?; log::info!("Goose serve is ready on port {port}"); @@ -110,22 +110,14 @@ impl GooseServeProcess { } } -/// Wait for the goose serve process to accept WebSocket connections. -/// -/// We do a connect-then-immediately-close loop until the server responds, -/// the child exits, or we time out. -async fn wait_for_server_ready(ws_url: &str, child: &mut Child) -> Result<(), String> { +async fn wait_for_server_ready(port: u16, child: &mut Child) -> Result<(), String> { let deadline = Instant::now() + GOOSE_SERVE_CONNECT_TIMEOUT; + let addr = format!("{LOCALHOST}:{port}"); loop { - match connect_async(ws_url).await { - Ok((ws_stream, _)) => { - // Server is up — close the probe connection. - let (mut writer, _) = ws_stream.split(); - let _ = writer.close().await; - return Ok(()); - } - Err(connect_error) => { + match tokio::net::TcpStream::connect(&addr).await { + Ok(_) => return Ok(()), + Err(_) => { if let Some(status) = child .try_wait() .map_err(|e| format!("Failed to poll goose serve process: {e}"))? @@ -136,9 +128,7 @@ async fn wait_for_server_ready(ws_url: &str, child: &mut Child) -> Result<(), St } if Instant::now() >= deadline { - return Err(format!( - "Timed out waiting for goose serve at {ws_url}: {connect_error}" - )); + return Err(format!("Timed out waiting for goose serve on port {port}")); } tokio::time::sleep(GOOSE_SERVE_CONNECT_RETRY_DELAY).await; @@ -175,21 +165,21 @@ pub(crate) fn resolve_goose_binary() -> Result { log::info!("Using GOOSE_BIN override: {override_path}"); path } else { - let agent = acp_client::find_acp_agent_by_id("goose") + let path = find_goose_binary() .ok_or_else(|| "Unknown or unavailable agent provider: goose".to_string())?; - if !goose_binary_supports_serve(&agent.binary_path)? { + if !goose_binary_supports_serve(&path)? { return Err(format!( "Resolved goose binary does not support `serve`: {}. Set GOOSE_BIN to a newer goose binary.", - agent.binary_path.display() + path.display() )); } log::info!( - "Resolved goose binary via login-shell discovery: {}", - agent.binary_path.display() + "Resolved goose binary via local discovery: {}", + path.display() ); - agent.binary_path + path }; // Log the binary version for debugging. @@ -217,6 +207,62 @@ pub(crate) fn resolve_goose_binary() -> Result { Ok(binary_path) } +fn find_goose_binary() -> Option { + find_goose_via_login_shell().or_else(find_goose_in_common_paths) +} + +fn find_goose_via_login_shell() -> Option { + #[cfg(target_os = "windows")] + { + None + } + + #[cfg(not(target_os = "windows"))] + { + for shell in ["/bin/zsh", "/bin/bash"] { + let Ok(output) = std::process::Command::new(shell) + .args(["-l", "-c", "which goose"]) + .output() + else { + continue; + }; + + if !output.status.success() { + continue; + } + + let stdout = String::from_utf8_lossy(&output.stdout); + if let Some(path_str) = stdout.lines().rfind(|line| !line.trim().is_empty()) { + let path = PathBuf::from(path_str.trim()); + if path.is_file() { + return Some(path); + } + } + } + + None + } +} + +fn find_goose_in_common_paths() -> Option { + COMMON_GOOSE_PATHS + .iter() + .map(|dir| Path::new(dir).join(goose_binary_name())) + .find(|path| path.is_file()) +} + +fn goose_binary_name() -> &'static str { + #[cfg(target_os = "windows")] + { + "goose.exe" + } + + #[cfg(not(target_os = "windows"))] + { + "goose" + } +} + fn goose_binary_supports_serve(binary_path: &PathBuf) -> Result { let output = std::process::Command::new(binary_path) .env("GOOSE_PATH_ROOT", goose_probe_root()) diff --git a/ui/goose2/src-tauri/src/services/acp/manager.rs b/ui/goose2/src-tauri/src/services/acp/manager.rs deleted file mode 100644 index 2da75e7d97..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager.rs +++ /dev/null @@ -1,308 +0,0 @@ -mod command_dispatch; -mod dispatcher; -mod session_ops; -mod thread; - -use std::path::PathBuf; -use std::sync::Arc; - -use acp_client::MessageWriter; -use agent_client_protocol::{Agent, ClientSideConnection, ExtRequest}; -use serde::Deserialize; -use serde_json::value::RawValue; -use tokio::sync::{mpsc, oneshot, OnceCell}; - -pub use session_ops::AcpSessionInfo; - -enum ManagerCommand { - ListProviders { - response: oneshot::Sender, String>>, - }, - ListSessions { - response: oneshot::Sender, String>>, - }, - LoadSession { - local_session_id: String, - goose_session_id: String, - working_dir: PathBuf, - response: oneshot::Sender>, - }, - PrepareSession { - composite_key: String, - local_session_id: String, - provider_id: String, - working_dir: PathBuf, - existing_agent_session_id: Option, - response: oneshot::Sender>, - }, - SendPrompt { - composite_key: String, - local_session_id: String, - provider_id: String, - working_dir: PathBuf, - existing_agent_session_id: Option, - writer: Arc, - prompt: String, - images: Vec<(String, String)>, - response: oneshot::Sender>, - }, - CancelSession { - composite_key: String, - response: oneshot::Sender>, - }, - ExportSession { - session_id: String, - response: oneshot::Sender>, - }, - ImportSession { - json: String, - response: oneshot::Sender>, - }, - ForkSession { - session_id: String, - response: oneshot::Sender>, - }, - SetModel { - local_session_id: String, - model_id: String, - response: oneshot::Sender>, - }, -} - -pub struct GooseAcpManager { - command_tx: mpsc::UnboundedSender, -} - -#[derive(Clone, Debug, Deserialize)] -pub struct GooseAcpProvider { - pub id: String, - pub label: String, -} - -#[derive(Debug, Deserialize)] -struct GooseProvidersResponse { - providers: Vec, -} - -static GOOSE_ACP_MANAGER: OnceCell> = OnceCell::const_new(); - -impl GooseAcpManager { - pub async fn start(app_handle: tauri::AppHandle) -> Result, String> { - GOOSE_ACP_MANAGER - .get_or_try_init(|| async move { - let (command_tx, command_rx) = mpsc::unbounded_channel(); - let manager = Arc::new(Self { command_tx }); - let (ready_tx, ready_rx) = oneshot::channel(); - - std::thread::Builder::new() - .name("goose-acp-manager".to_string()) - .spawn(move || run_manager_thread(app_handle, command_rx, ready_tx)) - .map_err(|error| { - format!("Failed to spawn Goose ACP manager thread: {error}") - })?; - - ready_rx - .await - .map_err(|_| "Goose ACP manager failed before initialization".to_string())??; - - Ok(manager) - }) - .await - .map(Arc::clone) - } - - pub async fn list_sessions(&self) -> Result, String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::ListSessions { - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped list sessions request".to_string())? - } - - pub async fn load_session( - &self, - local_session_id: String, - goose_session_id: String, - working_dir: PathBuf, - ) -> Result<(), String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::LoadSession { - local_session_id, - goose_session_id, - working_dir, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped load session request".to_string())? - } - - pub async fn prepare_session( - &self, - composite_key: String, - local_session_id: String, - provider_id: String, - working_dir: PathBuf, - existing_agent_session_id: Option, - ) -> Result<(), String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::PrepareSession { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped prepare request".to_string())? - } - - pub async fn list_providers(&self) -> Result, String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::ListProviders { - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped provider discovery request".to_string())? - } - - #[allow(clippy::too_many_arguments)] - pub async fn send_prompt( - &self, - composite_key: String, - local_session_id: String, - provider_id: String, - working_dir: PathBuf, - existing_agent_session_id: Option, - writer: Arc, - prompt: String, - images: Vec<(String, String)>, - ) -> Result<(), String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::SendPrompt { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - writer, - prompt, - images, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped prompt request".to_string())? - } - - pub async fn cancel_session(&self, composite_key: String) -> Result { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::CancelSession { - composite_key, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped cancel request".to_string())? - } - - pub async fn set_model( - &self, - local_session_id: String, - model_id: String, - ) -> Result<(), String> { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::SetModel { - local_session_id, - model_id, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped set model request".to_string())? - } - - /// Export a session as JSON via the goose binary. - pub async fn export_session(&self, session_id: String) -> Result { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::ExportSession { - session_id, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped export session request".to_string())? - } - - /// Import a session from JSON via the goose binary. - pub async fn import_session(&self, json: String) -> Result { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::ImportSession { - json, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped import session request".to_string())? - } - - /// Fork (duplicate) a session via the goose binary. - pub async fn fork_session(&self, session_id: String) -> Result { - let (response_tx, response_rx) = oneshot::channel(); - self.command_tx - .send(ManagerCommand::ForkSession { - session_id, - response: response_tx, - }) - .map_err(|_| "Goose ACP manager is unavailable".to_string())?; - response_rx - .await - .map_err(|_| "Goose ACP manager dropped fork session request".to_string())? - } -} - -/// Call a goose ext_method and return the raw JSON response string. -async fn call_ext_method( - connection: &Arc, - method: &str, - params_json: serde_json::Value, -) -> Result { - let params = RawValue::from_string(params_json.to_string()) - .map_err(|e| format!("Failed to build {method} request: {e}"))?; - let resp = connection - .ext_method(ExtRequest::new(method, params.into())) - .await - .map_err(|e| format!("{method} failed via Goose ACP: {e:?}"))?; - Ok(resp.0.get().to_string()) -} - -fn run_manager_thread( - app_handle: tauri::AppHandle, - command_rx: mpsc::UnboundedReceiver, - ready_tx: oneshot::Sender>, -) { - thread::run_manager_thread(app_handle, command_rx, ready_tx); -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/command_dispatch.rs b/ui/goose2/src-tauri/src/services/acp/manager/command_dispatch.rs deleted file mode 100644 index 6ce59a6c52..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/command_dispatch.rs +++ /dev/null @@ -1,258 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::sync::Arc; - -use agent_client_protocol::{Agent, ClientSideConnection, ExtRequest, ForkSessionRequest}; -use serde_json::value::RawValue; -use tokio::sync::{mpsc, Mutex}; - -use super::dispatcher::SessionEventDispatcher; -use super::session_ops::{ - cancel_session_inner, list_sessions_inner, load_session_inner, prepare_session_inner, - send_prompt_inner, set_model_inner, AcpSessionInfo, ManagerState, PrepareSessionInput, -}; -use super::{call_ext_method, GooseProvidersResponse, ManagerCommand}; - -pub(super) async fn dispatch_commands( - mut command_rx: mpsc::UnboundedReceiver, - connection: Arc, - dispatcher: Arc, -) { - let state = Arc::new(Mutex::new(ManagerState { - sessions: HashMap::new(), - op_locks: HashMap::new(), - pending_cancels: HashSet::new(), - preparing_sessions: HashSet::new(), - })); - - while let Some(command) = command_rx.recv().await { - match command { - ManagerCommand::ListProviders { response } => { - let connection = Arc::clone(&connection); - tokio::task::spawn_local(async move { - let result = async { - let params = RawValue::from_string("{}".to_string()).map_err(|error| { - format!("Failed to build ACP request body: {error}") - })?; - let response_value = connection - .ext_method(ExtRequest::new("goose/providers/list", params.into())) - .await - .map_err(|error| { - format!("Failed to list providers via Goose ACP: {error:?}") - })?; - let parsed: GooseProvidersResponse = - serde_json::from_str(response_value.0.get()).map_err(|error| { - format!("Failed to decode Goose provider list: {error}") - })?; - Ok::<_, String>(parsed.providers) - } - .await; - let _ = response.send(result); - }); - } - ManagerCommand::ListSessions { response } => { - let connection = Arc::clone(&connection); - tokio::task::spawn_local(async move { - let result = list_sessions_inner(&connection).await; - let _ = response.send(result); - }); - } - ManagerCommand::LoadSession { - local_session_id, - goose_session_id, - working_dir, - response, - } => { - let connection = Arc::clone(&connection); - let dispatcher = dispatcher.clone(); - let state = Arc::clone(&state); - tokio::task::spawn_local(async move { - let result = load_session_inner( - &connection, - &dispatcher, - &state, - &local_session_id, - &goose_session_id, - working_dir, - ) - .await; - let _ = response.send(result); - }); - } - ManagerCommand::PrepareSession { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - response, - } => { - let connection = Arc::clone(&connection); - let dispatcher = dispatcher.clone(); - let state = Arc::clone(&state); - tokio::task::spawn_local(async move { - let result = prepare_session_inner( - &connection, - &dispatcher, - &state, - PrepareSessionInput { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - }, - ) - .await - .map(|_| ()); - let _ = response.send(result); - }); - } - ManagerCommand::SendPrompt { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - writer, - prompt, - images, - response, - } => { - let connection = Arc::clone(&connection); - let dispatcher = dispatcher.clone(); - let state = Arc::clone(&state); - tokio::task::spawn_local(async move { - let result = send_prompt_inner( - &connection, - &dispatcher, - &state, - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - writer, - prompt, - images, - ) - .await; - let _ = response.send(result); - }); - } - ManagerCommand::CancelSession { - composite_key, - response, - } => { - let connection = Arc::clone(&connection); - let dispatcher = dispatcher.clone(); - let state = Arc::clone(&state); - tokio::task::spawn_local(async move { - let result = - cancel_session_inner(&connection, &dispatcher, &state, &composite_key) - .await; - let _ = response.send(result); - }); - } - ManagerCommand::ExportSession { - session_id, - response, - } => { - let connection = Arc::clone(&connection); - tokio::task::spawn_local(async move { - let result = async { - let raw = call_ext_method( - &connection, - "goose/session/export", - serde_json::json!({ "sessionId": session_id }), - ) - .await?; - // Backend returns { "data": "" } - let resp: serde_json::Value = serde_json::from_str(&raw) - .map_err(|e| format!("Failed to decode export response: {e}"))?; - resp.get("data") - .and_then(|v| v.as_str()) - .map(|s| s.to_string()) - .ok_or_else(|| "Export response missing 'data' field".to_string()) - } - .await; - let _ = response.send(result); - }); - } - ManagerCommand::ImportSession { json, response } => { - let connection = Arc::clone(&connection); - tokio::task::spawn_local(async move { - let result = async { - let raw = call_ext_method( - &connection, - "goose/session/import", - serde_json::json!({ "data": json }), - ) - .await?; - serde_json::from_str(&raw) - .map_err(|e| format!("Failed to decode import response: {e}")) - } - .await; - let _ = response.send(result); - }); - } - ManagerCommand::ForkSession { - session_id, - response, - } => { - let connection = Arc::clone(&connection); - tokio::task::spawn_local(async move { - let result = async { - let req = ForkSessionRequest::new( - session_id, - std::env::current_dir().unwrap_or_default(), - ); - let resp = connection - .fork_session(req) - .await - .map_err(|e| format!("session/fork failed: {e:?}"))?; - let message_count = resp - .meta - .as_ref() - .and_then(|m| m.get("messageCount")) - .and_then(|v| v.as_u64()) - .unwrap_or(0) as usize; - let title = resp - .meta - .as_ref() - .and_then(|m| m.get("title")) - .and_then(|v| v.as_str()) - .map(|s| s.to_string()); - Ok(AcpSessionInfo { - session_id: resp.session_id.to_string(), - title, - updated_at: None, - message_count, - }) - } - .await; - let _ = response.send(result); - }); - } - ManagerCommand::SetModel { - local_session_id, - model_id, - response, - } => { - let connection = Arc::clone(&connection); - let dispatcher = dispatcher.clone(); - let state = Arc::clone(&state); - tokio::task::spawn_local(async move { - let result = set_model_inner( - &connection, - &dispatcher, - &state, - &local_session_id, - &model_id, - ) - .await; - let _ = response.send(result); - }); - } - } - } -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/dispatcher.rs b/ui/goose2/src-tauri/src/services/acp/manager/dispatcher.rs deleted file mode 100644 index 047638ac23..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/dispatcher.rs +++ /dev/null @@ -1,532 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use acp_client::MessageWriter; -use agent_client_protocol::{ - Client, ContentBlock as AcpContentBlock, PermissionOptionId, RequestPermissionOutcome, - RequestPermissionRequest, RequestPermissionResponse, SelectedPermissionOutcome, - SessionConfigKind, SessionConfigOption, SessionConfigOptionCategory, - SessionConfigSelectOptions, SessionInfoUpdate, SessionModelState, SessionNotification, - SessionUpdate, -}; -use async_trait::async_trait; -use tauri::Emitter; -use tokio::sync::Mutex; - -use crate::services::acp::payloads::{ - model_options_from_state, DonePayload, MessageCreatedPayload, ModelOption, ModelStatePayload, - ReplayCompletePayload, SessionBoundPayload, SessionInfoPayload, TextPayload, ToolCallPayload, - ToolResultPayload, ToolTitlePayload, -}; - -fn extract_user_message(raw: &str) -> &str { - const OPEN: &str = "\n"; - const CLOSE: &str = "\n"; - if let Some(start) = raw.find(OPEN) { - let inner = start + OPEN.len(); - if raw[inner..].ends_with(CLOSE) { - return &raw[inner..raw.len() - CLOSE.len()]; - } - } - raw -} -fn model_options_from_select_options(options: &SessionConfigSelectOptions) -> Vec { - match options { - SessionConfigSelectOptions::Ungrouped(values) => values - .iter() - .map(|value| ModelOption { - id: value.value.to_string(), - name: value.name.clone(), - }) - .collect(), - SessionConfigSelectOptions::Grouped(groups) => groups - .iter() - .flat_map(|group| group.options.iter()) - .map(|value| ModelOption { - id: value.value.to_string(), - name: value.name.clone(), - }) - .collect(), - _ => Vec::new(), - } -} - -#[derive(Clone)] -pub(super) struct SessionRoute { - pub(super) local_session_id: String, - pub(super) provider_id: Option, - pub(super) writer: Option>, - pub(super) canceled: bool, - pub(super) replay_message_id: Option, - pub(super) replay_events: u32, -} - -pub(super) struct SessionEventDispatcher { - app_handle: tauri::AppHandle, - routes: Arc>>, -} - -impl SessionEventDispatcher { - pub(super) fn new( - app_handle: tauri::AppHandle, - routes: Arc>>, - ) -> Self { - Self { app_handle, routes } - } - - pub(super) async fn bind_session( - &self, - goose_session_id: &str, - local_session_id: &str, - provider_id: Option<&str>, - ) { - let mut routes = self.routes.lock().await; - routes - .entry(goose_session_id.to_string()) - .and_modify(|route| { - route.local_session_id = local_session_id.to_string(); - if let Some(pid) = provider_id { - route.provider_id = Some(pid.to_string()); - } - }) - .or_insert_with(|| SessionRoute { - local_session_id: local_session_id.to_string(), - provider_id: provider_id.map(ToString::to_string), - writer: None, - canceled: false, - replay_message_id: None, - replay_events: 0, - }); - - let _ = self.app_handle.emit( - "acp:session_bound", - SessionBoundPayload { - session_id: local_session_id.to_string(), - goose_session_id: goose_session_id.to_string(), - }, - ); - } - - pub(super) async fn attach_writer( - &self, - goose_session_id: &str, - local_session_id: &str, - provider_id: Option<&str>, - writer: Arc, - ) { - let mut routes = self.routes.lock().await; - routes.insert( - goose_session_id.to_string(), - SessionRoute { - local_session_id: local_session_id.to_string(), - provider_id: provider_id.map(ToString::to_string), - writer: Some(writer), - canceled: false, - replay_message_id: None, - replay_events: 0, - }, - ); - } - - pub(super) async fn clear_writer(&self, goose_session_id: &str) { - let mut routes = self.routes.lock().await; - if let Some(route) = routes.get_mut(goose_session_id) { - route.writer = None; - route.canceled = false; - } - } - - pub(super) async fn mark_canceled(&self, goose_session_id: &str) -> bool { - let mut routes = self.routes.lock().await; - if let Some(route) = routes.get_mut(goose_session_id) { - let had_writer = route.writer.is_some(); - route.writer = None; - route.canceled = had_writer; - return had_writer; - } - false - } - - pub(super) async fn is_canceled(&self, goose_session_id: &str) -> bool { - let routes = self.routes.lock().await; - routes - .get(goose_session_id) - .is_some_and(|route| route.canceled) - } - - /// Finalize any in-progress replay message and clear the replay state. - /// Called after `load_session` completes to mark the last replayed - /// assistant message as done. - pub(super) async fn finalize_replay(&self, goose_session_id: &str) { - let mut routes = self.routes.lock().await; - if let Some(route) = routes.get_mut(goose_session_id) { - if let Some(message_id) = route.replay_message_id.take() { - let _ = self.app_handle.emit( - "acp:done", - DonePayload { - session_id: route.local_session_id.clone(), - message_id, - }, - ); - } - } - } - - pub(super) fn emit_session_info(&self, local_session_id: &str, info: &SessionInfoUpdate) { - let _ = self.app_handle.emit( - "acp:session_info", - SessionInfoPayload { - session_id: local_session_id.to_string(), - title: info.title.value().cloned(), - }, - ); - } - - pub(super) fn emit_model_state( - &self, - local_session_id: &str, - provider_id: Option<&str>, - state: &SessionModelState, - ) { - let current_model_name = state - .available_models - .iter() - .find(|model| model.model_id == state.current_model_id) - .map(|model| model.name.clone()); - let available_models = model_options_from_state(state); - let _ = self.app_handle.emit( - "acp:model_state", - ModelStatePayload { - session_id: local_session_id.to_string(), - provider_id: provider_id.map(ToString::to_string), - current_model_id: state.current_model_id.to_string(), - current_model_name, - available_models, - }, - ); - } - - pub(super) fn emit_model_state_from_options( - &self, - local_session_id: &str, - provider_id: Option<&str>, - options: &[SessionConfigOption], - ) { - let Some(option) = options - .iter() - .find(|option| option.category == Some(SessionConfigOptionCategory::Model)) - else { - return; - }; - - let SessionConfigKind::Select(select) = &option.kind else { - return; - }; - let current_model_id = select.current_value.to_string(); - let available_models = model_options_from_select_options(&select.options); - let current_model_name = match &select.options { - SessionConfigSelectOptions::Ungrouped(values) => values - .iter() - .find(|value| value.value == select.current_value) - .map(|value| value.name.clone()), - SessionConfigSelectOptions::Grouped(groups) => groups - .iter() - .flat_map(|group| group.options.iter()) - .find(|value| value.value == select.current_value) - .map(|value| value.name.clone()), - _ => None, - }; - - let _ = self.app_handle.emit( - "acp:model_state", - ModelStatePayload { - session_id: local_session_id.to_string(), - provider_id: provider_id.map(ToString::to_string), - current_model_id, - current_model_name, - available_models, - }, - ); - } - - pub(super) fn emit_replay_complete(&self, local_session_id: &str) { - let _ = self.app_handle.emit( - "acp:replay_complete", - ReplayCompletePayload { - session_id: local_session_id.to_string(), - }, - ); - } - - pub(super) async fn get_replay_event_count(&self, goose_session_id: &str) -> u32 { - let routes = self.routes.lock().await; - routes - .get(goose_session_id) - .map(|r| r.replay_events) - .unwrap_or(0) - } -} - -fn extract_content_preview(content: &[agent_client_protocol::ToolCallContent]) -> Option { - for item in content { - match item { - agent_client_protocol::ToolCallContent::Content(content_item) => { - if let AcpContentBlock::Text(text) = &content_item.content { - let preview: String = text.text.chars().take(500).collect(); - return Some(if text.text.len() > 500 { - format!("{preview}…") - } else { - preview - }); - } - } - agent_client_protocol::ToolCallContent::Diff(diff) => { - return Some(format!( - "{}{}", - diff.path.display(), - if diff.old_text.is_some() { - " (modified)" - } else { - " (new)" - } - )); - } - agent_client_protocol::ToolCallContent::Terminal(terminal) => { - return Some(format!("Terminal: {}", terminal.terminal_id.0)); - } - _ => {} - } - } - - None -} - -#[async_trait(?Send)] -impl Client for SessionEventDispatcher { - async fn request_permission( - &self, - args: RequestPermissionRequest, - ) -> agent_client_protocol::Result { - let option_id = args - .options - .first() - .map(|option| option.option_id.clone()) - .unwrap_or_else(|| PermissionOptionId::new("approve")); - - Ok(RequestPermissionResponse::new( - RequestPermissionOutcome::Selected(SelectedPermissionOutcome::new(option_id)), - )) - } - - async fn session_notification( - &self, - notification: SessionNotification, - ) -> agent_client_protocol::Result<()> { - let goose_session_id = notification.session_id.to_string(); - let route = { - let routes = self.routes.lock().await; - routes.get(&goose_session_id).cloned() - }; - - let Some(route) = route else { - return Ok(()); - }; - - match ¬ification.update { - SessionUpdate::SessionInfoUpdate(info) => { - self.emit_session_info(&route.local_session_id, info); - return Ok(()); - } - SessionUpdate::ConfigOptionUpdate(update) => { - self.emit_model_state_from_options( - &route.local_session_id, - route.provider_id.as_deref(), - &update.config_options, - ); - return Ok(()); - } - _ => {} - } - - // Live streaming path — writer is present - if let Some(writer) = route.writer { - match ¬ification.update { - SessionUpdate::AgentMessageChunk(chunk) => { - if let AcpContentBlock::Text(text) = &chunk.content { - writer.append_text(&text.text).await; - } - } - SessionUpdate::ToolCall(tool_call) => { - writer - .record_tool_call( - &tool_call.tool_call_id.0, - &tool_call.title, - tool_call.raw_input.as_ref(), - ) - .await; - } - SessionUpdate::ToolCallUpdate(update) => { - if update.fields.title.is_some() || update.fields.raw_input.is_some() { - writer - .update_tool_call_title( - &update.tool_call_id.0, - update.fields.title.as_deref(), - update.fields.raw_input.as_ref(), - ) - .await; - } - if let Some(content) = &update.fields.content { - if let Some(result) = extract_content_preview(content) { - writer.record_tool_result(&result).await; - } - } - } - _ => {} - } - return Ok(()); - } - - // Replay path — no writer, emit Tauri events directly. - // This handles messages replayed by load_session. - let local_session_id = route.local_session_id.clone(); - match ¬ification.update { - SessionUpdate::UserMessageChunk(chunk) => { - if let AcpContentBlock::Text(text) = &chunk.content { - // Finalize any in-progress assistant message and count replay event - { - let mut routes = self.routes.lock().await; - if let Some(route) = routes.get_mut(&goose_session_id) { - if let Some(prev_msg_id) = route.replay_message_id.take() { - let _ = self.app_handle.emit( - "acp:done", - DonePayload { - session_id: local_session_id.clone(), - message_id: prev_msg_id, - }, - ); - } - route.replay_events += 1; - } - } - - let display_text = extract_user_message(&text.text); - let message_id = uuid::Uuid::new_v4().to_string(); - let _ = self.app_handle.emit( - "acp:replay_user_message", - serde_json::json!({ - "sessionId": local_session_id, - "messageId": message_id, - "text": display_text, - }), - ); - } - } - SessionUpdate::AgentMessageChunk(chunk) => { - if let AcpContentBlock::Text(text) = &chunk.content { - // Check if we already have a replay message in progress - let replay_msg_id = { - let routes = self.routes.lock().await; - routes - .get(&goose_session_id) - .and_then(|r| r.replay_message_id.clone()) - }; - - let message_id = if let Some(id) = replay_msg_id { - id - } else { - // Start a new assistant message - let new_id = uuid::Uuid::new_v4().to_string(); - let _ = self.app_handle.emit( - "acp:message_created", - MessageCreatedPayload { - session_id: local_session_id.clone(), - message_id: new_id.clone(), - persona_id: None, - persona_name: None, - }, - ); - let mut routes = self.routes.lock().await; - if let Some(route) = routes.get_mut(&goose_session_id) { - route.replay_message_id = Some(new_id.clone()); - route.replay_events += 1; - } - new_id - }; - - let _ = self.app_handle.emit( - "acp:text", - TextPayload { - session_id: local_session_id, - message_id: message_id.clone(), - text: text.text.clone(), - }, - ); - } - } - SessionUpdate::ToolCall(tool_call) => { - let replay_msg_id = { - let routes = self.routes.lock().await; - routes - .get(&goose_session_id) - .and_then(|r| r.replay_message_id.clone()) - }; - - if let Some(message_id) = replay_msg_id { - let _ = self.app_handle.emit( - "acp:tool_call", - ToolCallPayload { - session_id: local_session_id, - message_id, - tool_call_id: tool_call.tool_call_id.0.to_string(), - title: tool_call.title.clone(), - }, - ); - } - } - SessionUpdate::ToolCallUpdate(update) => { - let replay_msg_id = { - let routes = self.routes.lock().await; - routes - .get(&goose_session_id) - .and_then(|r| r.replay_message_id.clone()) - }; - - if let Some(message_id) = replay_msg_id { - if let Some(title) = &update.fields.title { - let _ = self.app_handle.emit( - "acp:tool_title", - ToolTitlePayload { - session_id: local_session_id.clone(), - message_id: message_id.clone(), - tool_call_id: update.tool_call_id.0.to_string(), - title: title.clone(), - }, - ); - } - if let Some(content) = &update.fields.content { - // During replay, always emit a tool_result so the - // frontend can mark the tool request as completed. - // Fall back to a generic summary when the content - // type has no preview extractor. - let result = - extract_content_preview(content).unwrap_or_else(|| "Done".to_string()); - let _ = self.app_handle.emit( - "acp:tool_result", - ToolResultPayload { - session_id: local_session_id, - message_id, - content: result, - }, - ); - } - } - } - _ => {} - } - - Ok(()) - } -} -#[cfg(test)] -#[path = "dispatcher_tests.rs"] -mod tests; diff --git a/ui/goose2/src-tauri/src/services/acp/manager/dispatcher_tests.rs b/ui/goose2/src-tauri/src/services/acp/manager/dispatcher_tests.rs deleted file mode 100644 index 7b684780d0..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/dispatcher_tests.rs +++ /dev/null @@ -1,28 +0,0 @@ -use super::*; - -#[test] -fn extract_user_message_strips_xml_wrapper() { - let wrapped = "\nYou are a helpful assistant.\n\n\n\nhello\n"; - assert_eq!(extract_user_message(wrapped), "hello"); -} - -#[test] -fn extract_user_message_multiline() { - let wrapped = "\nstuff\n\n\n\nline one\nline two\n"; - assert_eq!(extract_user_message(wrapped), "line one\nline two"); -} - -#[test] -fn extract_user_message_no_wrapper() { - assert_eq!(extract_user_message("plain text"), "plain text"); -} - -#[test] -fn extract_user_message_preserves_inner_delimiter() { - // User literally typed "" in their message — must not truncate. - let wrapped = "\nstuff\n\n\n\ncheck this tag: cool right?\n"; - assert_eq!( - extract_user_message(wrapped), - "check this tag: cool right?" - ); -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/session_ops.rs b/ui/goose2/src-tauri/src/services/acp/manager/session_ops.rs deleted file mode 100644 index cb00a7f22b..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/session_ops.rs +++ /dev/null @@ -1,611 +0,0 @@ -mod prompt_ops; -#[cfg(test)] -mod tests; - -use std::collections::{HashMap, HashSet}; -use std::path::PathBuf; -use std::sync::Arc; - -use agent_client_protocol::{ - Agent, CancelNotification, ClientSideConnection, ExtRequest, ListSessionsRequest, - LoadSessionRequest, NewSessionRequest, SessionConfigKind, SessionConfigOption, - SessionConfigSelectOptions, SetSessionConfigOptionRequest, -}; -use serde_json::value::RawValue; -use tokio::sync::Mutex; - -use super::dispatcher::SessionEventDispatcher; -use crate::services::acp::split_composite_key; -pub(super) use prompt_ops::send_prompt_inner; - -/// Lightweight session metadata returned by `list_sessions`. -#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct AcpSessionInfo { - pub session_id: String, - pub title: Option, - pub updated_at: Option, - pub message_count: usize, -} - -#[derive(Clone)] -pub(super) struct PreparedSession { - goose_session_id: String, - provider_id: String, - working_dir: PathBuf, -} - -pub(super) struct ManagerState { - pub(super) sessions: HashMap, - pub(super) op_locks: HashMap>>, - pub(super) pending_cancels: HashSet, - pub(super) preparing_sessions: HashSet, -} - -impl ManagerState { - pub(super) fn session_lock(&mut self, composite_key: &str) -> Arc> { - self.op_locks - .entry(composite_key.to_string()) - .or_insert_with(|| Arc::new(Mutex::new(()))) - .clone() - } - - pub(super) fn mark_cancel_requested(&mut self, composite_key: &str) { - self.pending_cancels.insert(composite_key.to_string()); - } - - pub(super) fn take_cancel_requested(&mut self, composite_key: &str) -> bool { - self.pending_cancels.remove(composite_key) - } -} - -fn extract_current_select_value( - options: &[SessionConfigOption], - option_id: &str, -) -> Option { - let option = options - .iter() - .find(|candidate| candidate.id.0.as_ref() == option_id)?; - let SessionConfigKind::Select(select) = &option.kind else { - return None; - }; - - let current_value = select.current_value.to_string(); - match &select.options { - SessionConfigSelectOptions::Ungrouped(values) => values - .iter() - .any(|value| value.value == select.current_value) - .then_some(current_value), - SessionConfigSelectOptions::Grouped(groups) => groups - .iter() - .flat_map(|group| group.options.iter()) - .any(|value| value.value == select.current_value) - .then_some(current_value), - _ => Some(current_value), - } -} - -fn needs_provider_update(current_provider_id: Option<&str>, requested_provider_id: &str) -> bool { - current_provider_id != Some(requested_provider_id) -} - -fn prepared_session_for_key( - sessions: &HashMap, - composite_key: &str, - local_session_id: &str, -) -> Option { - sessions - .get(composite_key) - .cloned() - .or_else(|| sessions.get(local_session_id).cloned()) -} - -fn register_prepared_session_keys( - sessions: &mut HashMap, - composite_key: &str, - local_session_id: &str, - prepared: PreparedSession, -) { - sessions.insert(composite_key.to_string(), prepared.clone()); - sessions.insert(local_session_id.to_string(), prepared); -} - -async fn update_working_dir_inner( - connection: &Arc, - goose_session_id: &str, - working_dir: &PathBuf, -) -> Result<(), String> { - let params = RawValue::from_string( - serde_json::json!({ - "sessionId": goose_session_id, - "workingDir": working_dir, - }) - .to_string(), - ) - .map_err(|error| format!("Failed to build working dir update request: {error}"))?; - - connection - .ext_method(ExtRequest::new("goose/working_dir/update", params.into())) - .await - .map_err(|error| format!("Failed to update Goose ACP working directory: {error:?}"))?; - - Ok(()) -} - -pub(super) struct PrepareSessionInput { - pub(super) composite_key: String, - pub(super) local_session_id: String, - pub(super) provider_id: String, - pub(super) working_dir: PathBuf, - pub(super) existing_agent_session_id: Option, -} - -async fn try_load_existing_session( - connection: &Arc, - dispatcher: &Arc, - local_session_id: &str, - candidate_session_id: &str, - provider_id: &str, - working_dir: &PathBuf, -) -> Result, String> { - let response = match connection - .load_session(LoadSessionRequest::new( - candidate_session_id.to_string(), - working_dir.clone(), - )) - .await - { - Ok(response) => response, - Err(_) => return Ok(None), - }; - - dispatcher - .bind_session(candidate_session_id, local_session_id, Some(provider_id)) - .await; - - if let Some(models) = &response.models { - dispatcher.emit_model_state(local_session_id, Some(provider_id), models); - } - if let Some(options) = &response.config_options { - dispatcher.emit_model_state_from_options(local_session_id, Some(provider_id), options); - } - update_working_dir_inner(connection, candidate_session_id, working_dir).await?; - - let loaded_provider_id = response - .config_options - .as_deref() - .and_then(|options| extract_current_select_value(options, "provider")); - if needs_provider_update(loaded_provider_id.as_deref(), provider_id) { - let response = connection - .set_session_config_option(SetSessionConfigOptionRequest::new( - candidate_session_id.to_string(), - "provider", - provider_id, - )) - .await - .map_err(|error| format!("Failed to update provider via Goose ACP: {error:?}"))?; - dispatcher.emit_model_state_from_options( - local_session_id, - Some(provider_id), - &response.config_options, - ); - } - - Ok(Some(candidate_session_id.to_string())) -} - -pub(super) async fn prepare_session_inner( - connection: &Arc, - dispatcher: &Arc, - state: &Arc>, - input: PrepareSessionInput, -) -> Result { - let PrepareSessionInput { - composite_key, - local_session_id, - provider_id, - working_dir, - existing_agent_session_id, - } = input; - - let session_lock = { - let mut guard = state.lock().await; - guard.session_lock(&composite_key) - }; - let _lock_guard = session_lock.lock().await; - - { - let mut guard = state.lock().await; - guard.preparing_sessions.insert(composite_key.clone()); - } - - let prepare_result: Result<(String, Option), String> = async { - let existing_prepared = { - let guard = state.lock().await; - prepared_session_for_key(&guard.sessions, &composite_key, &local_session_id) - }; - - if let Some(prepared) = existing_prepared { - dispatcher - .bind_session( - &prepared.goose_session_id, - &local_session_id, - Some(&provider_id), - ) - .await; - - { - let mut guard = state.lock().await; - register_prepared_session_keys( - &mut guard.sessions, - &composite_key, - &local_session_id, - prepared.clone(), - ); - } - - if prepared.working_dir != working_dir { - update_working_dir_inner(connection, &prepared.goose_session_id, &working_dir) - .await?; - - let mut guard = state.lock().await; - register_prepared_session_keys( - &mut guard.sessions, - &composite_key, - &local_session_id, - PreparedSession { - goose_session_id: prepared.goose_session_id.clone(), - provider_id: prepared.provider_id.clone(), - working_dir: working_dir.clone(), - }, - ); - } - - if needs_provider_update(Some(&prepared.provider_id), &provider_id) { - let response = connection - .set_session_config_option(SetSessionConfigOptionRequest::new( - prepared.goose_session_id.clone(), - "provider", - provider_id.as_str(), - )) - .await - .map_err(|error| { - format!("Failed to update provider via Goose ACP: {error:?}") - })?; - dispatcher.emit_model_state_from_options( - &local_session_id, - Some(&provider_id), - &response.config_options, - ); - - let mut guard = state.lock().await; - let updated_working_dir = guard - .sessions - .get(&composite_key) - .map(|session| session.working_dir.clone()) - .unwrap_or_else(|| prepared.working_dir.clone()); - let updated = PreparedSession { - goose_session_id: prepared.goose_session_id.clone(), - provider_id: provider_id.clone(), - working_dir: updated_working_dir, - }; - register_prepared_session_keys( - &mut guard.sessions, - &composite_key, - &local_session_id, - updated, - ); - } - - return Ok((prepared.goose_session_id, None)); - } - - let goose_session_id = if let Some(existing_id) = existing_agent_session_id { - try_load_existing_session( - connection, - dispatcher, - &local_session_id, - &existing_id, - &provider_id, - &working_dir, - ) - .await? - .ok_or_else(|| format!("Failed to load Goose session '{existing_id}'"))? - } else if let Some(existing_id) = try_load_existing_session( - connection, - dispatcher, - &local_session_id, - &local_session_id, - &provider_id, - &working_dir, - ) - .await? - { - existing_id - } else { - let mut request = NewSessionRequest::new(working_dir.clone()); - if provider_id != "goose" { - let mut meta = serde_json::Map::new(); - meta.insert( - "provider".into(), - serde_json::Value::String(provider_id.clone()), - ); - request = request.meta(meta); - } - - let response = connection - .new_session(request) - .await - .map_err(|error| format!("Failed to create Goose session: {error:?}"))?; - - let new_id = response.session_id.to_string(); - - dispatcher - .bind_session(&new_id, &local_session_id, Some(&provider_id)) - .await; - - if let Some(models) = &response.models { - dispatcher.emit_model_state(&local_session_id, Some(&provider_id), models); - } - if let Some(options) = &response.config_options { - dispatcher.emit_model_state_from_options( - &local_session_id, - Some(&provider_id), - options, - ); - } - - new_id - }; - - Ok(( - goose_session_id.clone(), - Some(PreparedSession { - goose_session_id, - provider_id, - working_dir, - }), - )) - } - .await; - - { - let mut guard = state.lock().await; - guard.preparing_sessions.remove(&composite_key); - } - - let (goose_session_id, prepared_session) = prepare_result?; - - if let Some(prepared_session) = prepared_session { - let mut guard = state.lock().await; - guard.sessions.insert(composite_key, prepared_session); - } - - Ok(goose_session_id) -} - -/// List all sessions known to the goose binary. -pub(super) async fn list_sessions_inner( - connection: &Arc, -) -> Result, String> { - let response = connection - .list_sessions(ListSessionsRequest::default()) - .await - .map_err(|error| format!("Failed to list sessions via Goose ACP: {error:?}"))?; - - Ok(response - .sessions - .into_iter() - .map(|info| { - let message_count = info - .meta - .as_ref() - .and_then(|m| m.get("messageCount")) - .and_then(|v| v.as_u64()) - .unwrap_or(0) as usize; - AcpSessionInfo { - session_id: info.session_id.to_string(), - title: info.title, - updated_at: info.updated_at, - message_count, - } - }) - .collect()) -} - -/// Load an existing session from the goose binary. -/// -/// This binds the goose session ID to the local session ID in the dispatcher -/// so that replayed `SessionNotification` events are routed to the correct -/// frontend session. It also registers the session in the manager state so -/// that subsequent `send_prompt` calls can reuse the goose session. -pub(super) async fn load_session_inner( - connection: &Arc, - dispatcher: &Arc, - state: &Arc>, - local_session_id: &str, - goose_session_id: &str, - working_dir: PathBuf, -) -> Result<(), String> { - dispatcher - .bind_session(goose_session_id, local_session_id, None) - .await; - - let response = connection - .load_session(LoadSessionRequest::new( - goose_session_id.to_string(), - working_dir.clone(), - )) - .await - .map_err(|error| format!("Failed to load Goose session: {error:?}"))?; - - // The ACP RPC layer resolves responses synchronously but dispatches - // notifications asynchronously via spawned tasks. After load_session - // returns, replay notifications may still be queued. Yield repeatedly - // to let the single-threaded runtime drain them before counting. - wait_for_replay_drain(|| async { dispatcher.get_replay_event_count(goose_session_id).await }) - .await; - - // Finalize any in-progress replay assistant message - dispatcher.finalize_replay(goose_session_id).await; - - dispatcher.emit_replay_complete(local_session_id); - - if let Some(models) = &response.models { - dispatcher.emit_model_state(local_session_id, None, models); - } - if let Some(options) = &response.config_options { - dispatcher.emit_model_state_from_options(local_session_id, None, options); - } - - // Register the session so future prompts reuse this goose session - let mut guard = state.lock().await; - guard.sessions.insert( - local_session_id.to_string(), - PreparedSession { - goose_session_id: goose_session_id.to_string(), - provider_id: "goose".to_string(), // will be updated on next prepare - working_dir, - }, - ); - - Ok(()) -} - -pub(super) async fn cancel_session_inner( - connection: &Arc, - dispatcher: &Arc, - state: &Arc>, - composite_key: &str, -) -> Result { - let (goose_session_id, is_preparing) = { - let mut guard = state.lock().await; - let goose_session_id = guard - .sessions - .get(composite_key) - .map(|session| session.goose_session_id.clone()); - let is_preparing = guard.preparing_sessions.contains(composite_key); - if goose_session_id.is_some() || is_preparing { - guard.mark_cancel_requested(composite_key); - } - (goose_session_id, is_preparing) - }; - - let Some(goose_session_id) = goose_session_id else { - return Ok(is_preparing); - }; - - let had_writer = dispatcher.mark_canceled(&goose_session_id).await; - if !had_writer { - return Ok(true); - } - - connection - .cancel(CancelNotification::new(goose_session_id)) - .await - .map_err(|error| format!("Failed to cancel Goose ACP session: {error:?}"))?; - - Ok(true) -} - -pub(super) async fn set_model_inner( - connection: &Arc, - dispatcher: &Arc, - state: &Arc>, - local_session_id: &str, - model_id: &str, -) -> Result<(), String> { - let prepared_sessions = { - let guard = state.lock().await; - guard - .sessions - .iter() - .filter_map(|(composite_key, session)| { - let (session_id, _) = split_composite_key(composite_key); - (session_id == local_session_id).then_some(( - composite_key.clone(), - session.goose_session_id.clone(), - session.provider_id.clone(), - )) - }) - .collect::>() - }; - - if prepared_sessions.is_empty() { - return Err(format!( - "Failed to update model for session '{local_session_id}': no prepared ACP session" - )); - } - - let mut updated_goose_sessions = HashSet::new(); - for (composite_key, goose_session_id, provider_id) in prepared_sessions { - if !updated_goose_sessions.insert(goose_session_id.clone()) { - continue; - } - - let session_lock = { - let mut guard = state.lock().await; - guard.session_lock(&composite_key) - }; - let _lock_guard = session_lock.lock().await; - - let response = connection - .set_session_config_option(SetSessionConfigOptionRequest::new( - goose_session_id, - "model", - model_id, - )) - .await - .map_err(|error| format!("Failed to update model via Goose ACP: {error:?}"))?; - dispatcher.emit_model_state_from_options( - local_session_id, - Some(&provider_id), - &response.config_options, - ); - } - - Ok(()) -} - -/// Yield repeatedly until an async counter stabilises for 3 consecutive rounds. -/// -/// After `load_session` returns, the ACP RPC layer may still have spawned -/// notification tasks that haven't run yet. This function yields to the -/// runtime between polls so those tasks get a chance to execute, and only -/// returns once the count has been stable for 3 consecutive yields — giving -/// us confidence that all replay events have been dispatched. -/// -/// A safety cap of 100 iterations prevents infinite spinning if a bug causes -/// the counter to increment indefinitely. -const MAX_DRAIN_ITERATIONS: u32 = 100; - -async fn wait_for_replay_drain(mut get_count: F) -> u32 -where - F: FnMut() -> Fut, - Fut: std::future::Future, -{ - let mut prev_total = 0u32; - let mut stable_rounds = 0u8; - let mut iterations = 0u32; - loop { - tokio::task::yield_now().await; - let total = get_count().await; - iterations += 1; - if total == prev_total { - stable_rounds += 1; - if stable_rounds >= 3 { - return total; - } - } else { - stable_rounds = 0; - prev_total = total; - } - if iterations >= MAX_DRAIN_ITERATIONS { - log::warn!( - "wait_for_replay_drain hit iteration cap ({MAX_DRAIN_ITERATIONS}); \ - returning partial count {total}" - ); - return total; - } - } -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/session_ops/prompt_ops.rs b/ui/goose2/src-tauri/src/services/acp/manager/session_ops/prompt_ops.rs deleted file mode 100644 index 4c2ec2ca9c..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/session_ops/prompt_ops.rs +++ /dev/null @@ -1,112 +0,0 @@ -use std::path::PathBuf; -use std::sync::Arc; - -use acp_client::MessageWriter; -use agent_client_protocol::{ - Agent, ClientSideConnection, ContentBlock as AcpContentBlock, ImageContent, PromptRequest, - TextContent, -}; -use tokio::sync::Mutex; - -use super::super::dispatcher::SessionEventDispatcher; -use super::{prepare_session_inner, ManagerState, PrepareSessionInput}; - -async fn take_cancel_requested(state: &Arc>, composite_key: &str) -> bool { - let mut guard = state.lock().await; - guard.take_cancel_requested(composite_key) -} - -async fn clear_cancel_requested(state: &Arc>, composite_key: &str) { - let mut guard = state.lock().await; - guard.pending_cancels.remove(composite_key); -} - -pub(super) fn build_content_blocks( - prompt: String, - images: Vec<(String, String)>, -) -> Vec { - let mut content_blocks = Vec::with_capacity(images.len() + 1); - for (data, mime_type) in images { - content_blocks.push(AcpContentBlock::Image(ImageContent::new( - data.as_str(), - mime_type.as_str(), - ))); - } - content_blocks.push(AcpContentBlock::Text(TextContent::new(prompt))); - content_blocks -} - -#[allow(clippy::too_many_arguments)] -pub(in super::super) async fn send_prompt_inner( - connection: &Arc, - dispatcher: &Arc, - state: &Arc>, - composite_key: String, - local_session_id: String, - provider_id: String, - working_dir: PathBuf, - existing_agent_session_id: Option, - writer: Arc, - prompt: String, - images: Vec<(String, String)>, -) -> Result<(), String> { - let provider_id_for_writer = provider_id.clone(); - let goose_session_id = match prepare_session_inner( - connection, - dispatcher, - state, - PrepareSessionInput { - composite_key: composite_key.clone(), - local_session_id: local_session_id.clone(), - provider_id, - working_dir, - existing_agent_session_id, - }, - ) - .await - { - Ok(goose_session_id) => goose_session_id, - Err(error) => { - clear_cancel_requested(state, &composite_key).await; - return Err(error); - } - }; - - if take_cancel_requested(state, &composite_key).await { - return Ok(()); - } - - dispatcher - .attach_writer( - &goose_session_id, - &local_session_id, - Some(&provider_id_for_writer), - writer.clone(), - ) - .await; - - if dispatcher.is_canceled(&goose_session_id).await - || take_cancel_requested(state, &composite_key).await - { - dispatcher.clear_writer(&goose_session_id).await; - return Ok(()); - } - - let content_blocks = build_content_blocks(prompt, images); - - let result = connection - .prompt(PromptRequest::new(goose_session_id.clone(), content_blocks)) - .await - .map(|_| ()) - .map_err(|error| format!("Prompt failed via Goose ACP: {error:?}")); - - let canceled = dispatcher.is_canceled(&goose_session_id).await; - dispatcher.clear_writer(&goose_session_id).await; - clear_cancel_requested(state, &composite_key).await; - - if result.is_ok() && !canceled { - writer.finalize().await; - } - - result -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/session_ops/tests.rs b/ui/goose2/src-tauri/src/services/acp/manager/session_ops/tests.rs deleted file mode 100644 index fbc26327ee..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/session_ops/tests.rs +++ /dev/null @@ -1,192 +0,0 @@ -use std::collections::{HashMap, HashSet}; -use std::path::PathBuf; -use std::sync::atomic::{AtomicU32, Ordering}; -use std::sync::Arc; - -use agent_client_protocol::ContentBlock as AcpContentBlock; - -use super::{ - needs_provider_update, prepared_session_for_key, prompt_ops::build_content_blocks, - register_prepared_session_keys, wait_for_replay_drain, ManagerState, PreparedSession, - MAX_DRAIN_ITERATIONS, -}; -use crate::services::acp::split_composite_key; - -#[test] -fn provider_update_detects_switch_back_to_goose() { - assert!(needs_provider_update(Some("openai"), "goose")); - assert!(needs_provider_update(Some("claude-acp"), "goose")); - assert!(!needs_provider_update(Some("goose"), "goose")); - assert!(needs_provider_update(None, "goose")); -} - -#[test] -fn pending_cancel_is_consumed_once() { - let mut state = ManagerState { - sessions: HashMap::new(), - op_locks: HashMap::new(), - pending_cancels: HashSet::new(), - preparing_sessions: HashSet::new(), - }; - - state.mark_cancel_requested("session-1"); - - assert!(state.take_cancel_requested("session-1")); - assert!(!state.take_cancel_requested("session-1")); -} - -#[test] -fn split_composite_key_extracts_local_session_id() { - assert_eq!( - split_composite_key("session-1__persona-1"), - ("session-1", Some("persona-1")) - ); - assert_eq!(split_composite_key("session-1"), ("session-1", None)); -} - -#[test] -fn prepared_session_lookup_falls_back_to_local_session_id() { - let mut sessions = HashMap::new(); - sessions.insert( - "session-1".to_string(), - PreparedSession { - goose_session_id: "goose-1".to_string(), - provider_id: "goose".to_string(), - working_dir: PathBuf::from("/tmp/project"), - }, - ); - - let prepared = prepared_session_for_key(&sessions, "session-1__persona-1", "session-1") - .expect("prepared session"); - - assert_eq!(prepared.goose_session_id, "goose-1"); - assert_eq!(prepared.provider_id, "goose"); - assert_eq!(prepared.working_dir, PathBuf::from("/tmp/project")); -} - -#[test] -fn register_prepared_session_keys_preserves_composite_and_local_entries() { - let mut sessions = HashMap::new(); - let prepared = PreparedSession { - goose_session_id: "goose-1".to_string(), - provider_id: "goose".to_string(), - working_dir: PathBuf::from("/tmp/project"), - }; - - register_prepared_session_keys(&mut sessions, "session-1__persona-1", "session-1", prepared); - - assert!(sessions.contains_key("session-1__persona-1")); - assert!(sessions.contains_key("session-1")); - assert_eq!( - sessions - .get("session-1__persona-1") - .expect("composite session") - .goose_session_id, - "goose-1" - ); -} - -#[tokio::test] -async fn replay_drain_returns_immediately_when_count_is_zero() { - let final_count = wait_for_replay_drain(|| async { 0u32 }).await; - assert_eq!(final_count, 0); -} - -#[tokio::test] -async fn replay_drain_returns_stable_count() { - let counter = Arc::new(AtomicU32::new(42)); - let c = counter.clone(); - let final_count = wait_for_replay_drain(|| { - let c = c.clone(); - async move { c.load(Ordering::SeqCst) } - }) - .await; - assert_eq!(final_count, 42); -} - -#[tokio::test] -async fn replay_drain_waits_for_spawned_notifications() { - let counter = Arc::new(AtomicU32::new(0)); - let c = counter.clone(); - - // Simulate async notifications arriving over multiple yields, like - // the real ACP RPC layer does after load_session returns. - tokio::spawn(async move { - for i in 1..=5 { - tokio::task::yield_now().await; - c.store(i, Ordering::SeqCst); - } - }); - - let c2 = counter.clone(); - let final_count = wait_for_replay_drain(|| { - let c = c2.clone(); - async move { c.load(Ordering::SeqCst) } - }) - .await; - - assert_eq!(final_count, 5); -} - -#[tokio::test] -async fn replay_drain_resets_stability_on_late_arrival() { - // Simulate: counter jumps to 3, stabilises for 2 rounds, then a late - // notification bumps it to 4. The drain must NOT stop at 3. - let poll_count = Arc::new(AtomicU32::new(0)); - - let pc = poll_count.clone(); - let final_count = wait_for_replay_drain(|| { - let pc = pc.clone(); - async move { - let poll = pc.fetch_add(1, Ordering::SeqCst); - // Polls 0..2 return 3 (2 stable rounds), then poll 3 bumps - // to 4 — simulating a late notification just before the drain - // would have declared stability. The drain must reset and - // wait for 4 to stabilise. - if poll < 3 { - 3 - } else { - 4 - } - } - }) - .await; - - // Must see the late arrival, not stop at 3 - assert_eq!(final_count, 4); - // Verify the stability window truly reset: 3 polls to see 3, 1 poll - // to see the bump to 4, then 3 more polls for 4 to stabilise = 7 min. - assert!( - poll_count.load(Ordering::SeqCst) >= 7, - "expected at least 7 polls to confirm stability window reset, got {}", - poll_count.load(Ordering::SeqCst) - ); -} - -#[tokio::test] -async fn replay_drain_caps_iterations_on_runaway_counter() { - // Simulate a counter that never stabilises — increments every poll. - let poll_count = Arc::new(AtomicU32::new(0)); - let pc = poll_count.clone(); - let final_count = wait_for_replay_drain(|| { - let pc = pc.clone(); - async move { pc.fetch_add(1, Ordering::SeqCst) + 1 } - }) - .await; - - // Should have stopped at the cap rather than spinning forever. - assert_eq!(final_count, MAX_DRAIN_ITERATIONS); - assert_eq!(poll_count.load(Ordering::SeqCst), MAX_DRAIN_ITERATIONS); -} - -#[test] -fn build_content_blocks_places_images_before_prompt_text() { - let blocks = build_content_blocks( - "Please inspect all three attachments".to_string(), - vec![("abc123".to_string(), "image/png".to_string())], - ); - - assert_eq!(blocks.len(), 2); - assert!(matches!(blocks[0], AcpContentBlock::Image(_))); - assert!(matches!(blocks[1], AcpContentBlock::Text(_))); -} diff --git a/ui/goose2/src-tauri/src/services/acp/manager/thread.rs b/ui/goose2/src-tauri/src/services/acp/manager/thread.rs deleted file mode 100644 index da3d4ecd6c..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/manager/thread.rs +++ /dev/null @@ -1,169 +0,0 @@ -use std::collections::HashMap; -use std::sync::Arc; - -use agent_client_protocol::{ - Agent, ClientSideConnection, Implementation, InitializeRequest, ProtocolVersion, -}; -use futures::{SinkExt, StreamExt}; -use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader}; -use tokio::sync::{mpsc, oneshot, Mutex}; -use tokio_tungstenite::connect_async; -use tokio_tungstenite::tungstenite::Message; -use tokio_util::compat::{TokioAsyncReadCompatExt, TokioAsyncWriteCompatExt}; - -use crate::services::acp::goose_serve::{GooseServeProcess, WS_BRIDGE_BUFFER_BYTES}; - -use super::command_dispatch; -use super::dispatcher::{SessionEventDispatcher, SessionRoute}; -use super::ManagerCommand; - -pub(super) fn run_manager_thread( - app_handle: tauri::AppHandle, - command_rx: mpsc::UnboundedReceiver, - ready_tx: oneshot::Sender>, -) { - let runtime = match tokio::runtime::Builder::new_current_thread() - .enable_all() - .build() - { - Ok(runtime) => runtime, - Err(error) => { - let _ = ready_tx.send(Err(format!( - "Failed to build Goose ACP manager runtime: {error}" - ))); - return; - } - }; - - let local = tokio::task::LocalSet::new(); - local.block_on(&runtime, async move { - let setup_result = async { - GooseServeProcess::start().await?; - let process = GooseServeProcess::get()?; - let ws_stream = connect_async(process.ws_url()) - .await - .map(|(stream, _)| stream) - .map_err(|error| format!("Failed to connect to goose serve: {error}"))?; - - let (mut ws_writer, mut ws_reader) = ws_stream.split(); - let (connection_outgoing, bridge_outgoing_reader) = - tokio::io::duplex(WS_BRIDGE_BUFFER_BYTES); - let (bridge_incoming_writer, connection_incoming) = - tokio::io::duplex(WS_BRIDGE_BUFFER_BYTES); - - tokio::task::spawn_local(async move { - let mut reader = BufReader::new(bridge_outgoing_reader); - let mut line = String::new(); - - loop { - line.clear(); - let bytes_read = match reader.read_line(&mut line).await { - Ok(bytes_read) => bytes_read, - Err(error) => { - log::error!("Failed to read ACP output for Goose WebSocket: {error}"); - break; - } - }; - if bytes_read == 0 { - break; - } - - let payload = line.trim_end_matches(['\r', '\n']); - if payload.is_empty() { - continue; - } - - if let Err(error) = ws_writer.send(Message::Text(payload.to_string())).await { - log::error!("Failed to write Goose WebSocket frame: {error}"); - break; - } - } - - let _ = ws_writer.close().await; - }); - - tokio::task::spawn_local(async move { - let mut writer = bridge_incoming_writer; - - while let Some(message) = ws_reader.next().await { - match message { - Ok(Message::Text(text)) => { - if let Err(error) = writer.write_all(text.as_bytes()).await { - log::error!( - "Failed to forward Goose WebSocket payload to ACP client: {error}" - ); - break; - } - if let Err(error) = writer.write_all(b"\n").await { - log::error!( - "Failed to delimit Goose WebSocket payload for ACP client: {error}" - ); - break; - } - if let Err(error) = writer.flush().await { - log::error!("Failed to flush Goose WebSocket payload: {error}"); - break; - } - } - Ok(Message::Close(_)) => break, - Ok(Message::Binary(_)) - | Ok(Message::Ping(_)) - | Ok(Message::Pong(_)) - | Ok(Message::Frame(_)) => {} - Err(error) => { - log::error!("Goose WebSocket read failed: {error}"); - break; - } - } - } - - let _ = writer.shutdown().await; - }); - - let routes = Arc::new(Mutex::new(HashMap::::new())); - let dispatcher = Arc::new(SessionEventDispatcher::new( - app_handle.clone(), - Arc::clone(&routes), - )); - let (connection, io_future) = ClientSideConnection::new( - dispatcher.clone(), - connection_outgoing.compat_write(), - connection_incoming.compat(), - |future| { - tokio::task::spawn_local(future); - }, - ); - let connection = Arc::new(connection); - - tokio::task::spawn_local(async move { - if let Err(error) = io_future.await { - log::error!("Goose ACP IO error: {error:?}"); - } - }); - - connection - .initialize( - InitializeRequest::new(ProtocolVersion::LATEST) - .client_info(Implementation::new("goose2", env!("CARGO_PKG_VERSION"))), - ) - .await - .map_err(|error| format!("Goose ACP initialize failed: {error:?}"))?; - - Ok::<_, String>((connection, dispatcher)) - } - .await; - - let (connection, dispatcher) = match setup_result { - Ok(parts) => { - let _ = ready_tx.send(Ok(())); - parts - } - Err(error) => { - let _ = ready_tx.send(Err(error)); - return; - } - }; - - command_dispatch::dispatch_commands(command_rx, connection, dispatcher).await; - }); -} diff --git a/ui/goose2/src-tauri/src/services/acp/mod.rs b/ui/goose2/src-tauri/src/services/acp/mod.rs index 7ddea1abad..08e7d11a8a 100644 --- a/ui/goose2/src-tauri/src/services/acp/mod.rs +++ b/ui/goose2/src-tauri/src/services/acp/mod.rs @@ -1,148 +1,4 @@ pub(crate) mod goose_serve; -mod manager; -mod payloads; -mod registry; -mod search; -mod writer; pub(crate) use goose_serve::resolve_goose_binary; pub(crate) use goose_serve::GooseServeProcess; -pub use manager::{AcpSessionInfo, GooseAcpManager}; -pub use registry::{AcpRunningSession, AcpSessionRegistry}; -pub use search::{search_sessions_via_exports, SessionSearchResult}; -pub use writer::TauriMessageWriter; - -use std::path::PathBuf; -use std::sync::Arc; - -use acp_client::MessageWriter; -use tauri::Emitter; - -/// Build a composite registry key: `{session_id}__{persona_id}` when a -/// persona is active, or plain `session_id` for backward compatibility. -/// -/// This assumes neither component contains `__`. -pub fn make_composite_key(session_id: &str, persona_id: Option<&str>) -> String { - match persona_id { - Some(pid) if !pid.is_empty() => format!("{session_id}__{pid}"), - _ => session_id.to_string(), - } -} - -pub fn split_composite_key(key: &str) -> (&str, Option<&str>) { - match key.split_once("__") { - Some((session_id, persona_id)) if !persona_id.is_empty() => (session_id, Some(persona_id)), - _ => (key, None), - } -} - -/// High-level service for running ACP prompts through an agent driver. -/// -/// The actual response content is streamed to the frontend via Tauri events -/// emitted by [`TauriMessageWriter`]; the returned `Result` only signals -/// whether the request was successfully dispatched. -pub struct AcpService; - -impl AcpService { - pub async fn prepare_session( - app_handle: tauri::AppHandle, - session_id: String, - provider_id: String, - working_dir: PathBuf, - persona_id: Option, - ) -> Result<(), String> { - let manager = GooseAcpManager::start(app_handle).await?; - - manager - .prepare_session( - make_composite_key(&session_id, persona_id.as_deref()), - session_id, - provider_id, - working_dir, - None, // no existing agent session ID — goose binary owns sessions - ) - .await - } - - /// Send a prompt to the given ACP provider and stream the response via - /// Tauri events. - #[allow(clippy::too_many_arguments)] - pub async fn send_prompt( - app_handle: tauri::AppHandle, - registry: Arc, - session_id: String, - provider_id: String, - prompt: String, - working_dir: PathBuf, - system_prompt: Option, - persona_id: Option, - persona_name: Option, - images: Vec<(String, String)>, - ) -> Result<(), String> { - let registry_key = make_composite_key(&session_id, persona_id.as_deref()); - let cancel_token = registry.register(®istry_key, &provider_id); - - let writer_impl = Arc::new(TauriMessageWriter::new( - app_handle.clone(), - session_id.clone(), - Some(provider_id.clone()), - persona_id.clone(), - persona_name.clone(), - )); - registry.set_assistant_message_id( - ®istry_key, - writer_impl.assistant_message_id().to_string(), - ); - let writer: Arc = writer_impl.clone(); - - // Build the effective prompt, including persona instructions when - // available. When there is no extra context we pass the raw prompt - // for backward compatibility. - let has_system = system_prompt.as_ref().is_some_and(|s| !s.is_empty()); - let effective_prompt = if has_system { - let mut parts = Vec::new(); - if let Some(ref sp) = system_prompt { - if !sp.is_empty() { - parts.push(format!( - "\n{sp}\n" - )); - } - } - parts.push(format!("\n{prompt}\n")); - parts.join("\n\n") - } else { - prompt.clone() - }; - - let manager = GooseAcpManager::start(app_handle.clone()).await?; - let result = manager - .send_prompt( - registry_key.clone(), - session_id.clone(), - provider_id.clone(), - working_dir, - None, // no existing agent session ID — goose binary owns sessions - writer, - effective_prompt, - images, - ) - .await; - - registry.deregister(®istry_key); - drop(cancel_token); - - if let Err(ref error) = result { - // Emit an error event so the frontend can display it - let _ = app_handle.emit( - "acp:error", - serde_json::json!({ - "sessionId": session_id, - "messageId": writer_impl.assistant_message_id(), - "error": error, - }), - ); - } - - result - } -} diff --git a/ui/goose2/src-tauri/src/services/acp/payloads.rs b/ui/goose2/src-tauri/src/services/acp/payloads.rs deleted file mode 100644 index 4c6031c5c1..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/payloads.rs +++ /dev/null @@ -1,106 +0,0 @@ -use acp_client::SessionModelState; -use serde::Serialize; - -/// Payload for the `acp:message_created` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct MessageCreatedPayload { - pub session_id: String, - pub message_id: String, - pub persona_id: Option, - pub persona_name: Option, -} - -/// Payload for the `acp:text` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct TextPayload { - pub session_id: String, - pub message_id: String, - pub text: String, -} - -/// Payload for the `acp:done` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct DonePayload { - pub session_id: String, - pub message_id: String, -} - -/// Payload for the `acp:tool_call` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ToolCallPayload { - pub session_id: String, - pub message_id: String, - pub tool_call_id: String, - pub title: String, -} - -/// Payload for the `acp:tool_title` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ToolTitlePayload { - pub session_id: String, - pub message_id: String, - pub tool_call_id: String, - pub title: String, -} - -/// Payload for the `acp:tool_result` event. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ToolResultPayload { - pub session_id: String, - pub message_id: String, - pub content: String, -} - -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct SessionInfoPayload { - pub session_id: String, - pub title: Option, -} - -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct SessionBoundPayload { - pub session_id: String, - pub goose_session_id: String, -} - -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ReplayCompletePayload { - pub session_id: String, -} - -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ModelOption { - pub id: String, - pub name: String, -} - -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub(crate) struct ModelStatePayload { - pub session_id: String, - pub provider_id: Option, - pub current_model_id: String, - pub current_model_name: Option, - pub available_models: Vec, -} - -pub(crate) fn model_options_from_state(state: &SessionModelState) -> Vec { - state - .available_models - .iter() - .map(|model| ModelOption { - id: model.model_id.to_string(), - name: model.name.clone(), - }) - .collect() -} diff --git a/ui/goose2/src-tauri/src/services/acp/registry.rs b/ui/goose2/src-tauri/src/services/acp/registry.rs deleted file mode 100644 index 03f4573d1a..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/registry.rs +++ /dev/null @@ -1,114 +0,0 @@ -use std::collections::HashMap; - -use serde::Serialize; -use tokio_util::sync::CancellationToken; - -use super::split_composite_key; - -/// Info about a running ACP session, returned to the frontend. -#[derive(Clone, Serialize)] -#[serde(rename_all = "camelCase")] -pub struct AcpRunningSession { - pub session_id: String, - pub persona_id: Option, - pub provider_id: String, - pub running_for_secs: u64, -} - -struct AcpSessionEntry { - cancel_token: CancellationToken, - provider_id: String, - started_at: std::time::Instant, - assistant_message_id: Option, - /// PID of the process that owns this session (for orphan detection). - #[allow(dead_code)] - owner_pid: u32, -} - -/// Tracks running ACP sessions for cancellation and cleanup. -/// -/// Each running session is registered with a `CancellationToken` so it can -/// be cancelled from the frontend or cleaned up on shutdown. -pub struct AcpSessionRegistry { - sessions: std::sync::Mutex>, -} - -impl AcpSessionRegistry { - pub fn new() -> Self { - Self { - sessions: std::sync::Mutex::new(HashMap::new()), - } - } - - /// Register a new session and return its cancellation token. - pub fn register(&self, session_id: &str, provider_id: &str) -> CancellationToken { - let token = CancellationToken::new(); - let entry = AcpSessionEntry { - cancel_token: token.clone(), - provider_id: provider_id.to_string(), - started_at: std::time::Instant::now(), - assistant_message_id: None, - owner_pid: std::process::id(), - }; - self.sessions - .lock() - .expect("session registry lock") - .insert(session_id.to_string(), entry); - token - } - - /// Deregister a session (called when it completes or errors). - pub fn deregister(&self, session_id: &str) { - self.sessions - .lock() - .expect("session registry lock") - .remove(session_id); - } - - /// Cancel a running session by signalling its cancellation token. - pub fn cancel(&self, session_id: &str) -> Option { - let guard = self.sessions.lock().expect("session registry lock"); - if let Some(entry) = guard.get(session_id) { - entry.cancel_token.cancel(); - entry.assistant_message_id.clone() - } else { - None - } - } - - pub fn set_assistant_message_id(&self, session_id: &str, message_id: String) { - if let Some(entry) = self - .sessions - .lock() - .expect("session registry lock") - .get_mut(session_id) - { - entry.assistant_message_id = Some(message_id); - } - } - - /// Cancel all running sessions (used during app shutdown). - pub fn cancel_all(&self) { - let guard = self.sessions.lock().expect("session registry lock"); - for entry in guard.values() { - entry.cancel_token.cancel(); - } - } - - /// Return info about all currently running sessions (for the frontend). - pub fn list_running(&self) -> Vec { - let guard = self.sessions.lock().expect("session registry lock"); - guard - .iter() - .map(|(id, entry)| { - let (session_id, persona_id) = split_composite_key(id); - AcpRunningSession { - session_id: session_id.to_string(), - persona_id: persona_id.map(str::to_string), - provider_id: entry.provider_id.clone(), - running_for_secs: entry.started_at.elapsed().as_secs(), - } - }) - .collect() - } -} diff --git a/ui/goose2/src-tauri/src/services/acp/search.rs b/ui/goose2/src-tauri/src/services/acp/search.rs deleted file mode 100644 index 015f4a4c7f..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/search.rs +++ /dev/null @@ -1,467 +0,0 @@ -use std::collections::HashSet; - -use serde::Serialize; -use serde_json::{Map, Value}; - -use super::GooseAcpManager; - -const SNIPPET_PREFIX_BYTES: usize = 40; -const SNIPPET_SUFFIX_BYTES: usize = 60; - -#[derive(Clone, Debug, Serialize, PartialEq, Eq)] -#[serde(rename_all = "camelCase")] -pub struct SessionSearchResult { - pub session_id: String, - pub snippet: String, - pub message_id: String, - #[serde(skip_serializing_if = "Option::is_none")] - pub message_role: Option, - pub match_count: usize, -} - -#[derive(Clone, Debug, PartialEq, Eq)] -struct ExportedMessage { - id: String, - role: Option, - searchable_texts: Vec, -} - -pub async fn search_sessions_via_exports( - manager: &GooseAcpManager, - query: &str, - session_ids: &[String], -) -> Result, String> { - let trimmed = query.trim(); - if trimmed.is_empty() { - return Ok(Vec::new()); - } - - let mut seen = HashSet::new(); - let mut results = Vec::new(); - - for session_id in session_ids { - if !seen.insert(session_id.clone()) { - continue; - } - - let exported = manager.export_session(session_id.clone()).await?; - if let Some(result) = search_exported_session(session_id, &exported, trimmed)? { - results.push(result); - } - } - - Ok(results) -} - -fn search_exported_session( - session_id: &str, - exported_json: &str, - query: &str, -) -> Result, String> { - let root: Value = serde_json::from_str(exported_json) - .map_err(|error| format!("Failed to parse exported session JSON: {error}"))?; - let Some(conversation) = root.get("conversation").or_else(|| root.get("messages")) else { - return Ok(None); - }; - - let messages = extract_messages(conversation); - if messages.is_empty() { - return Ok(None); - } - - let mut first_match: Option<(String, Option, String)> = None; - let mut match_count = 0; - - for message in messages { - for text in message.searchable_texts { - let occurrence_count = count_occurrences(&text, query); - if occurrence_count == 0 { - continue; - } - - match_count += occurrence_count; - - if first_match.is_none() { - first_match = Some(( - message.id.clone(), - message.role.clone(), - build_snippet(&text, query), - )); - } - } - } - - let Some((message_id, message_role, snippet)) = first_match else { - return Ok(None); - }; - - Ok(Some(SessionSearchResult { - session_id: session_id.to_string(), - snippet, - message_id, - message_role, - match_count, - })) -} - -fn extract_messages(value: &Value) -> Vec { - let mut messages = Vec::new(); - collect_messages(value, &mut messages); - messages -} - -fn collect_messages(value: &Value, messages: &mut Vec) { - match value { - Value::Array(items) => { - for item in items { - collect_messages(item, messages); - } - } - Value::Object(map) => { - if let Some(message_value) = map.get("message") { - collect_messages(message_value, messages); - return; - } - - if let Some(messages_value) = map.get("messages") { - collect_messages(messages_value, messages); - return; - } - - if looks_like_message(map) { - let fallback_id = format!("message-{}", messages.len()); - if let Some(message) = extract_message(map, fallback_id) { - messages.push(message); - } - } - } - _ => {} - } -} - -fn looks_like_message(map: &Map) -> bool { - map.contains_key("role") && (map.contains_key("content") || map.contains_key("text")) -} - -fn extract_message(map: &Map, fallback_id: String) -> Option { - let role = normalize_role(map.get("role").and_then(Value::as_str)); - let mut searchable_texts = Vec::new(); - - if let Some(content) = map.get("content") { - searchable_texts.extend(extract_searchable_texts(content, role.as_deref())); - } else if let Some(text) = map.get("text").and_then(Value::as_str) { - if role.is_some() && !text.trim().is_empty() { - searchable_texts.push(text.trim().to_string()); - } - } - - if searchable_texts.is_empty() { - return None; - } - - Some(ExportedMessage { - id: map - .get("id") - .and_then(Value::as_str) - .unwrap_or(&fallback_id) - .to_string(), - role, - searchable_texts, - }) -} - -fn extract_searchable_texts(value: &Value, role: Option<&str>) -> Vec { - match value { - Value::String(text) => role - .filter(|supported_role| is_searchable_role(supported_role)) - .and_then(|_| normalized_text(text)) - .into_iter() - .collect(), - Value::Array(items) => items - .iter() - .flat_map(|item| extract_searchable_block_text(item, role)) - .collect(), - Value::Object(_) => extract_searchable_block_text(value, role), - _ => Vec::new(), - } -} - -fn extract_searchable_block_text(value: &Value, role: Option<&str>) -> Vec { - let Value::Object(map) = value else { - return Vec::new(); - }; - - let block_type = map.get("type").and_then(Value::as_str); - let text = map.get("text").and_then(Value::as_str); - - match block_type { - Some("text") | Some("input_text") | Some("output_text") => { - text.and_then(normalized_text).into_iter().collect() - } - Some("systemNotification") | Some("system_notification") => { - text.and_then(normalized_text).into_iter().collect() - } - Some("toolRequest") - | Some("toolResponse") - | Some("thinking") - | Some("redactedThinking") - | Some("reasoning") - | Some("image") => Vec::new(), - _ => { - if role.is_some_and(is_searchable_role) { - return text.and_then(normalized_text).into_iter().collect(); - } - Vec::new() - } - } -} - -fn normalize_role(role: Option<&str>) -> Option { - let normalized = role?.trim(); - if normalized.eq_ignore_ascii_case("user") { - return Some("user".to_string()); - } - if normalized.eq_ignore_ascii_case("assistant") { - return Some("assistant".to_string()); - } - if normalized.eq_ignore_ascii_case("system") { - return Some("system".to_string()); - } - None -} - -fn is_searchable_role(role: &str) -> bool { - matches!(role, "user" | "assistant" | "system") -} - -fn normalized_text(text: &str) -> Option { - let trimmed = text.trim(); - (!trimmed.is_empty()).then(|| trimmed.to_string()) -} - -fn count_occurrences(text: &str, query: &str) -> usize { - let haystack = text.to_ascii_lowercase(); - let needle = query.to_ascii_lowercase(); - if needle.is_empty() { - return 0; - } - - let mut count = 0; - let mut search_start = 0; - - while let Some(relative_index) = haystack[search_start..].find(&needle) { - count += 1; - search_start += relative_index + needle.len(); - } - - count -} - -fn build_snippet(text: &str, query: &str) -> String { - let haystack = text.to_ascii_lowercase(); - let needle = query.to_ascii_lowercase(); - let match_index = haystack.find(&needle).unwrap_or(0); - - let start = floor_char_boundary(text, match_index.saturating_sub(SNIPPET_PREFIX_BYTES)); - let end = ceil_char_boundary( - text, - match_index - .saturating_add(query.len()) - .saturating_add(SNIPPET_SUFFIX_BYTES) - .min(text.len()), - ); - - let prefix = if start > 0 { "..." } else { "" }; - let suffix = if end < text.len() { "..." } else { "" }; - let body = text.get(start..end).unwrap_or(text).trim(); - - format!("{prefix}{body}{suffix}") -} - -fn floor_char_boundary(text: &str, mut index: usize) -> usize { - index = index.min(text.len()); - while index > 0 && !text.is_char_boundary(index) { - index -= 1; - } - index -} - -fn ceil_char_boundary(text: &str, mut index: usize) -> usize { - index = index.min(text.len()); - while index < text.len() && !text.is_char_boundary(index) { - index += 1; - } - index -} - -#[cfg(test)] -mod tests { - use super::{build_snippet, search_exported_session, SessionSearchResult}; - - #[test] - fn finds_user_and_assistant_text_matches() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "user-1", - "role": "user", - "content": [{ "type": "text", "text": "searchable user prompt" }] - }, - { - "id": "assistant-1", - "role": "assistant", - "content": [{ "type": "text", "text": "assistant searchable response" }] - } - ] - }) - .to_string(); - - let user_result = search_exported_session("session-1", &exported, "prompt") - .expect("search succeeds") - .expect("user result"); - let assistant_result = search_exported_session("session-1", &exported, "response") - .expect("search succeeds") - .expect("assistant result"); - - assert_eq!(user_result.message_id, "user-1"); - assert_eq!(user_result.message_role.as_deref(), Some("user")); - assert_eq!(assistant_result.message_id, "assistant-1"); - assert_eq!(assistant_result.message_role.as_deref(), Some("assistant")); - } - - #[test] - fn includes_system_notifications() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "system-1", - "role": "system", - "content": [{ - "type": "systemNotification", - "text": "Compaction completed successfully" - }] - } - ] - }) - .to_string(); - - let result = search_exported_session("session-1", &exported, "completed") - .expect("search succeeds") - .expect("system result"); - - assert_eq!(result.message_id, "system-1"); - assert_eq!(result.message_role.as_deref(), Some("system")); - } - - #[test] - fn skips_tool_and_reasoning_content() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "assistant-1", - "role": "assistant", - "content": [ - { "type": "toolRequest", "text": "tool request text" }, - { "type": "toolResponse", "text": "tool response text" }, - { "type": "thinking", "text": "private thinking" }, - { "type": "reasoning", "text": "private reasoning" } - ] - } - ] - }) - .to_string(); - - let result = - search_exported_session("session-1", &exported, "tool").expect("search succeeds"); - assert!(result.is_none()); - } - - #[test] - fn skips_single_object_tool_and_reasoning_blocks() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "assistant-1", - "role": "assistant", - "content": { "type": "toolResponse", "text": "tool response text" } - }, - { - "id": "assistant-2", - "role": "assistant", - "content": { "type": "reasoning", "text": "private reasoning" } - } - ] - }) - .to_string(); - - let tool_result = - search_exported_session("session-1", &exported, "tool").expect("search succeeds"); - let reasoning_result = - search_exported_session("session-1", &exported, "reasoning").expect("search succeeds"); - - assert!(tool_result.is_none()); - assert!(reasoning_result.is_none()); - } - - #[test] - fn includes_single_object_text_blocks() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "assistant-1", - "role": "assistant", - "content": { "type": "text", "text": "needle in a single object block" } - } - ] - }) - .to_string(); - - let result = search_exported_session("session-1", &exported, "needle") - .expect("search succeeds") - .expect("text result"); - - assert_eq!(result.message_id, "assistant-1"); - assert_eq!(result.message_role.as_deref(), Some("assistant")); - } - - #[test] - fn counts_multiple_matches_in_one_session() { - let exported = serde_json::json!({ - "conversation": [ - { - "id": "assistant-1", - "role": "assistant", - "content": [ - { "type": "text", "text": "needle once" }, - { "type": "text", "text": "needle twice needle" } - ] - } - ] - }) - .to_string(); - - let result = search_exported_session("session-1", &exported, "needle") - .expect("search succeeds") - .expect("result"); - - assert_eq!( - result, - SessionSearchResult { - session_id: "session-1".to_string(), - snippet: "needle once".to_string(), - message_id: "assistant-1".to_string(), - message_role: Some("assistant".to_string()), - match_count: 3, - } - ); - } - - #[test] - fn builds_trimmed_snippets_around_first_match() { - let text = "abcdefghijklmnopqrstuvwxyz0123456789prefix padding before needle and some trailing text that keeps going"; - let snippet = build_snippet(text, "needle"); - - assert!(snippet.starts_with("...")); - assert!(snippet.contains("needle and some trailing text")); - } -} diff --git a/ui/goose2/src-tauri/src/services/acp/writer.rs b/ui/goose2/src-tauri/src/services/acp/writer.rs deleted file mode 100644 index e693f4b1a0..0000000000 --- a/ui/goose2/src-tauri/src/services/acp/writer.rs +++ /dev/null @@ -1,156 +0,0 @@ -use async_trait::async_trait; -use tauri::Emitter; - -use acp_client::{MessageWriter, SessionInfoUpdate, SessionModelState}; - -use super::payloads::{ - model_options_from_state, DonePayload, MessageCreatedPayload, ModelStatePayload, - SessionInfoPayload, TextPayload, ToolCallPayload, ToolResultPayload, ToolTitlePayload, -}; - -/// A [`MessageWriter`] implementation that streams ACP output to the frontend -/// via Tauri events. No local persistence — the goose binary is the sole -/// source of truth for messages. -pub struct TauriMessageWriter { - app_handle: tauri::AppHandle, - session_id: String, - provider_id: Option, - assistant_message_id: String, -} - -impl TauriMessageWriter { - pub fn new( - app_handle: tauri::AppHandle, - session_id: String, - provider_id: Option, - persona_id: Option, - persona_name: Option, - ) -> Self { - let assistant_message_id = uuid::Uuid::new_v4().to_string(); - - let _ = app_handle.emit( - "acp:message_created", - MessageCreatedPayload { - session_id: session_id.clone(), - message_id: assistant_message_id.clone(), - persona_id: persona_id.clone(), - persona_name: persona_name.clone(), - }, - ); - - Self { - app_handle, - session_id, - provider_id, - assistant_message_id, - } - } - - pub fn assistant_message_id(&self) -> &str { - &self.assistant_message_id - } -} - -#[async_trait] -impl MessageWriter for TauriMessageWriter { - async fn append_text(&self, text: &str) { - if text.is_empty() { - return; - } - - let _ = self.app_handle.emit( - "acp:text", - TextPayload { - session_id: self.session_id.clone(), - message_id: self.assistant_message_id.clone(), - text: text.to_string(), - }, - ); - } - - async fn finalize(&self) { - let _ = self.app_handle.emit( - "acp:done", - DonePayload { - session_id: self.session_id.clone(), - message_id: self.assistant_message_id.clone(), - }, - ); - } - - async fn record_tool_call( - &self, - tool_call_id: &str, - title: &str, - _raw_input: Option<&serde_json::Value>, - ) { - let _ = self.app_handle.emit( - "acp:tool_call", - ToolCallPayload { - session_id: self.session_id.clone(), - message_id: self.assistant_message_id.clone(), - tool_call_id: tool_call_id.to_string(), - title: title.to_string(), - }, - ); - } - - async fn update_tool_call_title( - &self, - tool_call_id: &str, - title: Option<&str>, - _raw_input: Option<&serde_json::Value>, - ) { - if let Some(title) = title { - let _ = self.app_handle.emit( - "acp:tool_title", - ToolTitlePayload { - session_id: self.session_id.clone(), - message_id: self.assistant_message_id.clone(), - tool_call_id: tool_call_id.to_string(), - title: title.to_string(), - }, - ); - } - } - - async fn record_tool_result(&self, content: &str) { - let _ = self.app_handle.emit( - "acp:tool_result", - ToolResultPayload { - session_id: self.session_id.clone(), - message_id: self.assistant_message_id.clone(), - content: content.to_string(), - }, - ); - } - - async fn on_session_info_update(&self, info: &SessionInfoUpdate) { - let _ = self.app_handle.emit( - "acp:session_info", - SessionInfoPayload { - session_id: self.session_id.clone(), - title: info.title.value().cloned(), - }, - ); - } - - async fn on_model_state_update(&self, state: &SessionModelState) { - let current_model_name = state - .available_models - .iter() - .find(|m| m.model_id == state.current_model_id) - .map(|m| m.name.clone()); - let available_models = model_options_from_state(state); - let _ = self.app_handle.emit( - "acp:model_state", - ModelStatePayload { - session_id: self.session_id.clone(), - provider_id: self.provider_id.clone(), - current_model_id: state.current_model_id.to_string(), - current_model_name, - available_models, - }, - ); - } -} diff --git a/ui/goose2/src/app/AppShell.tsx b/ui/goose2/src/app/AppShell.tsx index 93dd0675e9..6c316b98f9 100644 --- a/ui/goose2/src/app/AppShell.tsx +++ b/ui/goose2/src/app/AppShell.tsx @@ -10,7 +10,6 @@ import type { SectionId } from "@/features/settings/ui/SettingsModal"; import { TopBar } from "./ui/TopBar"; import { useChatStore } from "@/features/chat/stores/chatStore"; import { useChatSessionStore } from "@/features/chat/stores/chatSessionStore"; -import { useAcpStream } from "@/features/chat/hooks/useAcpStream"; import { useAgentStore } from "@/features/agents/stores/agentStore"; import { useProjectStore } from "@/features/projects/stores/projectStore"; import { findExistingDraft } from "@/features/chat/lib/newChat"; @@ -18,6 +17,10 @@ import { DEFAULT_CHAT_TITLE } from "@/features/chat/lib/sessionTitle"; import { useAppStartup } from "./hooks/useAppStartup"; import { AppShellContent } from "./ui/AppShellContent"; import { acpPrepareSession } from "@/shared/api/acp"; +import { + clearReplayBuffer, + getAndDeleteReplayBuffer, +} from "@/features/chat/hooks/replayBuffer"; import { getHomeDir } from "@/shared/api/system"; import { resolveEffectiveWorkingDir } from "@/features/projects/lib/chatProjectContext"; @@ -58,8 +61,6 @@ export function AppShell({ children }: { children?: React.ReactNode }) { const agentStore = useAgentStore(); const projectStore = useProjectStore(); - useAcpStream(true); - const pendingProjectCreatedRef = useRef<((projectId: string) => void) | null>( null, ); @@ -99,12 +100,17 @@ export function AppShell({ children }: { children?: React.ReactNode }) { : undefined); await acpLoadSession(sessionId, gooseSessionId, workingDir); useChatStore.getState().setSessionLoading(sessionId, false); + const buffer = getAndDeleteReplayBuffer(sessionId); + if (buffer && buffer.length > 0) { + useChatStore.getState().setMessages(sessionId, buffer); + } const t3 = performance.now(); console.log( `[perf:load] ${sessionId.slice(0, 8)} acpLoadSession resolved in ${(t3 - t2).toFixed(1)}ms (total ${(t3 - t0).toFixed(1)}ms)`, ); } catch (err) { console.error("Failed to load session messages:", err); + clearReplayBuffer(sessionId); useChatStore.getState().setSessionLoading(sessionId, false); } }, []); diff --git a/ui/goose2/src/app/hooks/useAppStartup.ts b/ui/goose2/src/app/hooks/useAppStartup.ts index 97526e0ae2..0622715451 100644 --- a/ui/goose2/src/app/hooks/useAppStartup.ts +++ b/ui/goose2/src/app/hooks/useAppStartup.ts @@ -1,20 +1,17 @@ import { useEffect } from "react"; import { useAgentStore } from "@/features/agents/stores/agentStore"; import { useChatSessionStore } from "@/features/chat/stores/chatSessionStore"; -import { USE_DIRECT_ACP } from "@/shared/api/acpFeatureFlag"; import { setNotificationHandler, getClient } from "@/shared/api/acpConnection"; import notificationHandler from "@/shared/api/acpNotificationHandler"; export function useAppStartup() { useEffect(() => { (async () => { - if (USE_DIRECT_ACP) { - try { - setNotificationHandler(notificationHandler); - await getClient(); - } catch (err) { - console.error("Failed to initialize ACP connection:", err); - } + try { + setNotificationHandler(notificationHandler); + await getClient(); + } catch (err) { + console.error("Failed to initialize ACP connection:", err); } const store = useAgentStore.getState(); diff --git a/ui/goose2/src/features/chat/hooks/__tests__/useAcpStream.test.ts b/ui/goose2/src/features/chat/hooks/__tests__/useAcpStream.test.ts deleted file mode 100644 index f960701cf9..0000000000 --- a/ui/goose2/src/features/chat/hooks/__tests__/useAcpStream.test.ts +++ /dev/null @@ -1,567 +0,0 @@ -import { act, cleanup, renderHook } from "@testing-library/react"; -import { beforeEach, describe, expect, it, vi } from "vitest"; -import type { Message } from "@/shared/types/messages"; -import { useChatSessionStore } from "../../stores/chatSessionStore"; -import { useChatStore } from "../../stores/chatStore"; - -type EventCallback = (event: { payload: Record }) => void; - -const listeners = new Map(); - -function emit(eventName: string, payload: Record) { - const callbacks = listeners.get(eventName) ?? []; - for (const callback of callbacks) { - callback({ payload }); - } -} - -vi.mock("@tauri-apps/api/event", () => ({ - listen: vi.fn( - (eventName: string, callback: EventCallback): Promise<() => void> => { - const callbacks = listeners.get(eventName) ?? []; - callbacks.push(callback); - listeners.set(eventName, callbacks); - return Promise.resolve(() => { - const current = listeners.get(eventName) ?? []; - listeners.set( - eventName, - current.filter((entry) => entry !== callback), - ); - }); - }, - ), -})); - -import { useAcpStream } from "../useAcpStream"; - -function makeStreamingMessage(overrides: Partial = {}): Message { - return { - id: "msg-1", - role: "assistant", - created: Date.now(), - content: [{ type: "text", text: "" }], - metadata: { userVisible: true }, - ...overrides, - }; -} - -function setupStreaming(sessionId: string, messageId = "msg-1") { - const store = useChatStore.getState(); - store.addMessage(sessionId, makeStreamingMessage({ id: messageId })); - store.setStreamingMessageId(sessionId, messageId); - store.setChatState(sessionId, "streaming"); -} - -describe("useAcpStream", () => { - const sessionId = "test-session"; - - beforeEach(() => { - listeners.clear(); - cleanup(); - useChatStore.setState({ - messagesBySession: {}, - sessionStateById: {}, - activeSessionId: sessionId, - isConnected: true, - }); - useChatSessionStore.setState({ - sessions: [ - { - id: sessionId, - title: "New Chat", - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - messageCount: 0, - }, - ], - activeSessionId: sessionId, - isLoading: false, - modelsBySession: {}, - }); - }); - - it("accumulates text chunks for the targeted session", async () => { - setupStreaming(sessionId); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => expect(listeners.get("acp:text")).toBeDefined()); - - act(() => { - emit("acp:text", { sessionId, messageId: "msg-1", text: "Hello" }); - emit("acp:text", { sessionId, messageId: "msg-1", text: " world" }); - }); - - const messages = useChatStore.getState().messagesBySession[sessionId]; - const text = messages[0].content.find((content) => content.type === "text"); - if (text && "text" in text) { - expect(text.text).toBe("Hello world"); - } - }); - - it("clears runtime state on acp:done for the completed session", async () => { - setupStreaming(sessionId); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => expect(listeners.get("acp:done")).toBeDefined()); - - act(() => { - emit("acp:text", { sessionId, messageId: "msg-1", text: "partial" }); - emit("acp:done", { sessionId, messageId: "msg-1" }); - }); - - const runtime = useChatStore.getState().getSessionRuntime(sessionId); - const message = useChatStore.getState().messagesBySession[sessionId][0]; - expect(runtime.chatState).toBe("idle"); - expect(runtime.streamingMessageId).toBeNull(); - expect(runtime.hasUnread).toBe(false); - expect(message.metadata?.completionStatus).toBe("completed"); - }); - - it("marks a background session unread when it completes", async () => { - const backgroundSessionId = "background-session"; - - setupStreaming(backgroundSessionId); - useChatSessionStore.setState((state) => ({ - ...state, - sessions: [ - ...state.sessions, - { - id: backgroundSessionId, - title: "Background Chat", - createdAt: new Date().toISOString(), - updatedAt: new Date().toISOString(), - messageCount: 0, - }, - ], - activeSessionId: sessionId, - })); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => expect(listeners.get("acp:done")).toBeDefined()); - - act(() => { - emit("acp:done", { sessionId: backgroundSessionId, messageId: "msg-1" }); - }); - - expect( - useChatStore.getState().getSessionRuntime(backgroundSessionId).hasUnread, - ).toBe(true); - expect(useChatStore.getState().getSessionRuntime(sessionId).hasUnread).toBe( - false, - ); - }); - - it("updates multiple sessions independently", async () => { - const otherSessionId = "other-session"; - - setupStreaming(sessionId, "msg-1"); - setupStreaming(otherSessionId, "msg-2"); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => expect(listeners.get("acp:text")).toBeDefined()); - - act(() => { - emit("acp:text", { sessionId, messageId: "msg-1", text: "Alpha" }); - emit("acp:text", { - sessionId: otherSessionId, - messageId: "msg-2", - text: "Beta", - }); - emit("acp:done", { sessionId: otherSessionId, messageId: "msg-2" }); - }); - - const primary = useChatStore.getState().messagesBySession[sessionId]; - const secondary = useChatStore.getState().messagesBySession[otherSessionId]; - const primaryText = primary[0].content.find( - (content) => content.type === "text", - ); - const secondaryText = secondary[0].content.find( - (content) => content.type === "text", - ); - - if (primaryText && "text" in primaryText) { - expect(primaryText.text).toBe("Alpha"); - } - if (secondaryText && "text" in secondaryText) { - expect(secondaryText.text).toBe("Beta"); - } - - expect(useChatStore.getState().getSessionRuntime(sessionId).chatState).toBe( - "streaming", - ); - expect( - useChatStore.getState().getSessionRuntime(otherSessionId).chatState, - ).toBe("idle"); - }); - - it("does not register listeners when disabled", () => { - renderHook(() => useAcpStream(false)); - expect(listeners.size).toBe(0); - }); - - it("flushes replayed history only after acp:replay_complete", async () => { - useChatStore.getState().setSessionLoading(sessionId, true); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:message_created")).toBeDefined(), - ); - - act(() => { - emit("acp:message_created", { - sessionId, - messageId: "replay-msg", - }); - emit("acp:text", { - sessionId, - messageId: "replay-msg", - text: "replayed history", - }); - emit("acp:done", { - sessionId, - messageId: "replay-msg", - }); - }); - - expect( - useChatStore.getState().messagesBySession[sessionId], - ).toBeUndefined(); - expect(useChatStore.getState().loadingSessionIds.has(sessionId)).toBe(true); - - act(() => { - emit("acp:replay_complete", { sessionId }); - }); - - const messages = useChatStore.getState().messagesBySession[sessionId]; - expect(useChatStore.getState().loadingSessionIds.has(sessionId)).toBe( - false, - ); - expect(messages).toHaveLength(1); - const text = messages[0].content.find((content) => content.type === "text"); - if (text && "text" in text) { - expect(text.text).toBe("replayed history"); - } - }); - - it("stores model state for the targeted session", async () => { - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:model_state")).toBeDefined(), - ); - - act(() => { - emit("acp:model_state", { - sessionId, - currentModelId: "claude-sonnet-4", - currentModelName: "Claude Sonnet 4", - availableModels: [ - { id: "claude-sonnet-4", name: "Claude Sonnet 4" }, - { id: "gpt-4o", name: "GPT-4o" }, - ], - }); - }); - - expect( - useChatSessionStore.getState().getSession(sessionId)?.modelName, - ).toBe("Claude Sonnet 4"); - expect(useChatSessionStore.getState().getSession(sessionId)?.modelId).toBe( - "claude-sonnet-4", - ); - expect(useChatSessionStore.getState().getSessionModels(sessionId)).toEqual([ - { id: "claude-sonnet-4", name: "Claude Sonnet 4" }, - { id: "gpt-4o", name: "GPT-4o" }, - ]); - }); - - it("accepts providerless model state when the session already has a provider", async () => { - useChatSessionStore.setState((state) => ({ - ...state, - sessions: state.sessions.map((session) => - session.id === sessionId - ? { ...session, providerId: "openai" } - : session, - ), - })); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:model_state")).toBeDefined(), - ); - - act(() => { - emit("acp:model_state", { - sessionId, - currentModelId: "gpt-4.1", - currentModelName: "GPT-4.1", - availableModels: [ - { id: "gpt-4.1", name: "GPT-4.1" }, - { id: "gpt-4o", name: "GPT-4o" }, - ], - }); - }); - - expect( - useChatSessionStore.getState().getSession(sessionId)?.modelName, - ).toBe("GPT-4.1"); - expect(useChatSessionStore.getState().getSession(sessionId)?.modelId).toBe( - "gpt-4.1", - ); - expect(useChatSessionStore.getState().getSessionModels(sessionId)).toEqual([ - { id: "gpt-4.1", name: "GPT-4.1" }, - { id: "gpt-4o", name: "GPT-4o" }, - ]); - }); - - it("creates the streaming assistant message from backend metadata", async () => { - useChatStore.getState().setChatState(sessionId, "streaming"); - useChatStore - .getState() - .setPendingAssistantProvider(sessionId, "claude-acp"); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:message_created")).toBeDefined(), - ); - - act(() => { - emit("acp:message_created", { - sessionId, - messageId: "msg-created", - personaId: "persona-1", - personaName: "Planner", - }); - }); - - const messages = useChatStore.getState().messagesBySession[sessionId]; - expect(messages).toHaveLength(1); - expect(messages[0]).toMatchObject({ - id: "msg-created", - role: "assistant", - metadata: { - personaId: "persona-1", - personaName: "Planner", - providerId: "claude-acp", - completionStatus: "inProgress", - }, - }); - expect( - useChatStore.getState().getSessionRuntime(sessionId).streamingMessageId, - ).toBe("msg-created"); - }); - - it("keeps the original pending provider when the session provider changes before message creation", async () => { - useChatStore.getState().setChatState(sessionId, "streaming"); - useChatStore - .getState() - .setPendingAssistantProvider(sessionId, "claude-acp"); - useChatSessionStore.setState((state) => ({ - ...state, - sessions: state.sessions.map((session) => - session.id === sessionId - ? { ...session, providerId: "codex-acp" } - : session, - ), - })); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:message_created")).toBeDefined(), - ); - - act(() => { - emit("acp:message_created", { - sessionId, - messageId: "msg-provider-lock", - }); - }); - - const message = useChatStore.getState().messagesBySession[sessionId][0]; - const runtime = useChatStore.getState().getSessionRuntime(sessionId); - expect(message.metadata?.providerId).toBe("claude-acp"); - expect(runtime.pendingAssistantProviderId).toBeNull(); - }); - - it("ignores late message_created events after local streaming state is cleared", async () => { - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:message_created")).toBeDefined(), - ); - - act(() => { - emit("acp:message_created", { - sessionId, - messageId: "late-msg", - personaId: "persona-1", - personaName: "Planner", - }); - }); - - expect( - useChatStore.getState().messagesBySession[sessionId], - ).toBeUndefined(); - expect( - useChatStore.getState().getSessionRuntime(sessionId).streamingMessageId, - ).toBeNull(); - }); - - it("unregisters listeners on unmount", async () => { - const { unmount } = renderHook(() => useAcpStream(true)); - await vi.waitFor(() => expect(listeners.get("acp:text")).toBeDefined()); - - expect(listeners.get("acp:text")?.length).toBe(1); - - unmount(); - - await vi.waitFor(() => - expect(listeners.get("acp:text")?.length ?? 0).toBe(0), - ); - }); - - it("ignores late tool title updates after a message is completed", async () => { - const store = useChatStore.getState(); - store.addMessage(sessionId, { - id: "msg-1", - role: "assistant", - created: Date.now(), - content: [ - { - type: "toolRequest", - id: "tool-1", - name: "Original title", - arguments: {}, - status: "executing", - }, - ], - metadata: { - userVisible: true, - completionStatus: "completed", - }, - }); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:tool_title")).toBeDefined(), - ); - - act(() => { - emit("acp:tool_title", { - sessionId, - messageId: "msg-1", - toolCallId: "tool-1", - title: "Late title", - }); - }); - - const message = useChatStore.getState().messagesBySession[sessionId][0]; - expect(message.content).toContainEqual({ - type: "toolRequest", - id: "tool-1", - name: "Original title", - arguments: {}, - status: "executing", - }); - }); - - it("shows an error state when replay_complete is not received within the timeout", async () => { - vi.useFakeTimers(); - try { - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:replay_complete")).toBeDefined(), - ); - - // Start loading AFTER the hook subscribes so the subscription sees the transition - act(() => { - useChatStore.getState().setSessionLoading(sessionId, true); - }); - - // Simulate time passing without replay_complete - act(() => { - vi.advanceTimersByTime(30_000); - }); - - expect(useChatStore.getState().loadingSessionIds.has(sessionId)).toBe( - false, - ); - const runtime = useChatStore.getState().getSessionRuntime(sessionId); - expect(runtime.error).toBeTruthy(); - } finally { - vi.useRealTimers(); - } - }); - - it("clears the replay timeout when replay_complete arrives in time", async () => { - vi.useFakeTimers(); - try { - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:replay_complete")).toBeDefined(), - ); - - act(() => { - useChatStore.getState().setSessionLoading(sessionId, true); - }); - - // replay_complete arrives before timeout - act(() => { - emit("acp:replay_complete", { sessionId }); - }); - - // Advance past the timeout — should NOT set error - act(() => { - vi.advanceTimersByTime(30_000); - }); - - const runtime = useChatStore.getState().getSessionRuntime(sessionId); - expect(runtime.error).toBeFalsy(); - expect(useChatStore.getState().loadingSessionIds.has(sessionId)).toBe( - false, - ); - } finally { - vi.useRealTimers(); - } - }); - - it("ignores late tool results after a message is stopped", async () => { - const store = useChatStore.getState(); - store.addMessage(sessionId, { - id: "msg-1", - role: "assistant", - created: Date.now(), - content: [ - { - type: "toolRequest", - id: "tool-1", - name: "Lookup", - arguments: {}, - status: "executing", - }, - ], - metadata: { - userVisible: true, - completionStatus: "stopped", - }, - }); - - renderHook(() => useAcpStream(true)); - await vi.waitFor(() => - expect(listeners.get("acp:tool_result")).toBeDefined(), - ); - - act(() => { - emit("acp:tool_result", { - sessionId, - messageId: "msg-1", - content: "late result", - }); - }); - - const message = useChatStore.getState().messagesBySession[sessionId][0]; - expect(message.content).toHaveLength(1); - expect(message.content[0]).toMatchObject({ - type: "toolRequest", - id: "tool-1", - status: "executing", - }); - }); -}); diff --git a/ui/goose2/src/features/chat/hooks/__tests__/useChat.attachments.test.ts b/ui/goose2/src/features/chat/hooks/__tests__/useChat.attachments.test.ts index 975d5bc564..da14807a07 100644 --- a/ui/goose2/src/features/chat/hooks/__tests__/useChat.attachments.test.ts +++ b/ui/goose2/src/features/chat/hooks/__tests__/useChat.attachments.test.ts @@ -94,11 +94,9 @@ describe("useChat attachments", () => { ]); expect(mockAcpSendMessage).toHaveBeenCalledWith( "session-1", - "goose", "Attached items:\n- [file] /tmp/report.pdf\n- [directory] /tmp/screenshots\nPlease review these", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: undefined, @@ -147,11 +145,9 @@ describe("useChat attachments", () => { ]); expect(mockAcpSendMessage).toHaveBeenCalledWith( "session-1", - "goose", "Attached items:\n- [image] diagram.png (image attached)\n ", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: [["abc123", "image/png"]], @@ -196,11 +192,9 @@ describe("useChat attachments", () => { expect(mockAcpSendMessage).toHaveBeenCalledWith( "session-1", - "goose", "Attached items:\n- [file] /tmp/mobile-confirmation.html\n- [directory] /tmp/neighborhood block\n- [image] Screenshot 2026-04-09 at 1.25.32 PM.png (image attached)\ncan you see the attachments i attached?", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: [["abc123", "image/png"]], @@ -238,11 +232,9 @@ describe("useChat attachments", () => { ]); expect(mockAcpSendMessage).toHaveBeenCalledWith( "session-1", - "goose", "Attached items:\n- [file] report.pdf\nPlease review this", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: undefined, diff --git a/ui/goose2/src/features/chat/hooks/__tests__/useChat.test.ts b/ui/goose2/src/features/chat/hooks/__tests__/useChat.test.ts index 141826952f..546bcfc7c4 100644 --- a/ui/goose2/src/features/chat/hooks/__tests__/useChat.test.ts +++ b/ui/goose2/src/features/chat/hooks/__tests__/useChat.test.ts @@ -125,18 +125,12 @@ describe("useChat", () => { result.current.stopGeneration(); }); - expect(mockAcpSendMessage).toHaveBeenCalledWith( - "session-1", - "goose", - "Hello", - { - systemPrompt: undefined, - workingDir: undefined, - personaId: "persona-b", - personaName: "Persona B", - images: undefined, - }, - ); + expect(mockAcpSendMessage).toHaveBeenCalledWith("session-1", "Hello", { + systemPrompt: undefined, + personaId: "persona-b", + personaName: "Persona B", + images: undefined, + }); expect(mockAcpCancelSession).toHaveBeenCalledWith("session-1", "persona-b"); deferred.resolve(); @@ -316,11 +310,9 @@ describe("useChat", () => { expect(mockAcpSendMessage).toHaveBeenNthCalledWith( 1, "session-1", - "goose", "First", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: undefined, @@ -329,11 +321,9 @@ describe("useChat", () => { expect(mockAcpSendMessage).toHaveBeenNthCalledWith( 2, "session-2", - "goose", "Second", { systemPrompt: undefined, - workingDir: undefined, personaId: undefined, personaName: undefined, images: undefined, @@ -374,18 +364,12 @@ describe("useChat", () => { personaId: undefined, }); expect(mockAcpSetModel).toHaveBeenCalledWith("session-1", "gpt-4.1"); - expect(mockAcpSendMessage).toHaveBeenCalledWith( - "session-1", - "openai", - "Hello", - { - systemPrompt: undefined, - workingDir: undefined, - personaId: undefined, - personaName: undefined, - images: undefined, - }, - ); + expect(mockAcpSendMessage).toHaveBeenCalledWith("session-1", "Hello", { + systemPrompt: undefined, + personaId: undefined, + personaName: undefined, + images: undefined, + }); }); it("appends an error message and removes the empty assistant placeholder when send fails", async () => { diff --git a/ui/goose2/src/features/chat/hooks/acpStreamTypes.ts b/ui/goose2/src/features/chat/hooks/acpStreamTypes.ts deleted file mode 100644 index bd652bfb63..0000000000 --- a/ui/goose2/src/features/chat/hooks/acpStreamTypes.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { ModelOption } from "../types"; - -export interface AcpMessageCreatedPayload { - sessionId: string; - messageId: string; - personaId?: string; - personaName?: string; -} - -export interface AcpTextPayload { - sessionId: string; - messageId: string; - text: string; -} - -export interface AcpDonePayload { - sessionId: string; - messageId: string; -} - -export interface AcpToolCallPayload { - sessionId: string; - messageId: string; - toolCallId: string; - title: string; -} - -export interface AcpToolTitlePayload { - sessionId: string; - messageId: string; - toolCallId: string; - title: string; -} - -export interface AcpToolResultPayload { - sessionId: string; - messageId: string; - content: string; -} - -export interface AcpSessionInfoPayload { - sessionId: string; - title?: string; -} - -export interface AcpSessionBoundPayload { - sessionId: string; - gooseSessionId: string; -} - -export interface AcpModelStatePayload { - sessionId: string; - providerId?: string | null; - currentModelId: string; - currentModelName?: string; - availableModels: ModelOption[]; -} - -export interface AcpUsageUpdatePayload { - sessionId: string; - used: number; - size: number; -} - -export interface AcpReplayCompletePayload { - sessionId: string; -} diff --git a/ui/goose2/src/features/chat/hooks/useAcpStream.ts b/ui/goose2/src/features/chat/hooks/useAcpStream.ts deleted file mode 100644 index c70ee68042..0000000000 --- a/ui/goose2/src/features/chat/hooks/useAcpStream.ts +++ /dev/null @@ -1,553 +0,0 @@ -import { useEffect } from "react"; -import { listen, type UnlistenFn } from "@tauri-apps/api/event"; -import { useChatStore } from "../stores/chatStore"; -import { useChatSessionStore } from "../stores/chatSessionStore"; -import { isDefaultChatTitle } from "../lib/sessionTitle"; -import type { - Message, - MessageCompletionStatus, - ToolRequestContent, - ToolResponseContent, -} from "@/shared/types/messages"; -import { - ensureReplayBuffer, - getBufferedMessage, - getAndDeleteReplayBuffer, - findLatestUnpairedToolRequest, -} from "./replayBuffer"; -import type { - AcpMessageCreatedPayload, - AcpTextPayload, - AcpDonePayload, - AcpToolCallPayload, - AcpToolTitlePayload, - AcpToolResultPayload, - AcpSessionInfoPayload, - AcpSessionBoundPayload, - AcpModelStatePayload, - AcpUsageUpdatePayload, - AcpReplayCompletePayload, -} from "./acpStreamTypes"; - -function getAssistantProviderId(sessionId: string): string | undefined { - const pending = useChatStore - .getState() - .getSessionRuntime(sessionId).pendingAssistantProviderId; - if (pending) return pending; - return useChatSessionStore.getState().getSession(sessionId)?.providerId; -} - -function updateCompletionStatus( - message: Message, - completionStatus: MessageCompletionStatus, -): Message { - if ( - completionStatus === "completed" && - (message.metadata?.completionStatus === "stopped" || - message.metadata?.completionStatus === "error") - ) { - return message; - } - - return { - ...message, - metadata: { - ...message.metadata, - completionStatus, - }, - }; -} - -function shouldTrackStreamingEvent( - store: ReturnType, - sessionId: string, - messageId: string, -): boolean { - const runtime = store.getSessionRuntime(sessionId); - const existingMessage = store.messagesBySession[sessionId]?.find( - (message) => message.id === messageId, - ); - - if ( - existingMessage && - (existingMessage.metadata?.completionStatus === "completed" || - existingMessage.metadata?.completionStatus === "stopped" || - existingMessage.metadata?.completionStatus === "error") - ) { - return false; - } - - if (existingMessage || runtime.streamingMessageId === messageId) { - return true; - } - - return runtime.chatState === "thinking" || runtime.chatState === "streaming"; -} - -export function useAcpStream(enabled: boolean): void { - useEffect(() => { - if (!enabled) return; - - let active = true; - const unlisteners: Promise[] = []; - const replayTimeouts = new Map>(); - - const REPLAY_TIMEOUT_MS = 30_000; - - const unsubscribeFlush = useChatStore.subscribe((state, prevState) => { - if (!active) return; - - // Start timeout for newly-loading sessions - for (const sid of state.loadingSessionIds) { - if (!prevState.loadingSessionIds.has(sid) && !replayTimeouts.has(sid)) { - const timer = setTimeout(() => { - replayTimeouts.delete(sid); - const store = useChatStore.getState(); - if (store.loadingSessionIds.has(sid)) { - console.warn( - `[stream] ${sid.slice(0, 8)} replay_complete not received within ${REPLAY_TIMEOUT_MS / 1000}s — showing error`, - ); - store.setSessionLoading(sid, false); - store.setError( - sid, - "Session history failed to load. Try reloading.", - ); - } - }, REPLAY_TIMEOUT_MS); - replayTimeouts.set(sid, timer); - } - } - - // Clear timeouts and flush buffers for sessions that finished loading - for (const sid of prevState.loadingSessionIds) { - if (!state.loadingSessionIds.has(sid)) { - const timer = replayTimeouts.get(sid); - if (timer) { - clearTimeout(timer); - replayTimeouts.delete(sid); - } - const buffer = getAndDeleteReplayBuffer(sid); - if (buffer && buffer.length > 0) { - useChatStore.getState().setMessages(sid, buffer); - } - } - } - }); - - unlisteners.push( - listen("acp:replay_complete", (event) => { - if (!active) return; - useChatStore - .getState() - .setSessionLoading(event.payload.sessionId, false); - }), - ); - - unlisteners.push( - listen("acp:message_created", (event) => { - if (!active) return; - console.log( - `[perf:stream] ${event.payload.sessionId.slice(0, 8)} message_created mid=${event.payload.messageId.slice(0, 8)} at ${performance.now().toFixed(1)}ms`, - ); - const store = useChatStore.getState(); - const { sessionId, messageId, personaId, personaName } = event.payload; - const providerId = getAssistantProviderId(sessionId); - - if (store.loadingSessionIds.has(sessionId)) { - if (!getBufferedMessage(sessionId, messageId)) { - ensureReplayBuffer(sessionId).push({ - id: messageId, - role: "assistant", - created: Date.now(), - content: [], - metadata: { - userVisible: true, - agentVisible: true, - personaId, - personaName, - providerId, - completionStatus: "inProgress", - }, - }); - } - return; - } - - if (!shouldTrackStreamingEvent(store, sessionId, messageId)) { - return; - } - - const existing = store.messagesBySession[sessionId]?.find( - (message) => message.id === messageId, - ); - - if (existing) { - store.updateMessage(sessionId, messageId, (message) => ({ - ...message, - metadata: { - ...message.metadata, - personaId: message.metadata?.personaId ?? personaId, - personaName: message.metadata?.personaName ?? personaName, - providerId: message.metadata?.providerId ?? providerId, - }, - })); - } else { - store.addMessage(sessionId, { - id: messageId, - role: "assistant", - created: Date.now(), - content: [], - metadata: { - userVisible: true, - agentVisible: true, - personaId, - personaName, - providerId, - completionStatus: "inProgress", - }, - }); - } - - store.setPendingAssistantProvider(sessionId, null); - store.setStreamingMessageId(sessionId, messageId); - }), - ); - - unlisteners.push( - listen("acp:text", (event) => { - if (!active) return; - console.log( - `[perf:stream] ${event.payload.sessionId.slice(0, 8)} text mid=${event.payload.messageId.slice(0, 8)} len=${event.payload.text.length} at ${performance.now().toFixed(1)}ms`, - ); - const store = useChatStore.getState(); - const { sessionId, messageId, text } = event.payload; - - if (store.loadingSessionIds.has(sessionId)) { - const msg = getBufferedMessage(sessionId, messageId); - if (msg) { - const last = msg.content[msg.content.length - 1]; - if (last?.type === "text") { - (last as { type: "text"; text: string }).text += text; - } else { - msg.content.push({ type: "text", text }); - } - } - return; - } - - if (!shouldTrackStreamingEvent(store, sessionId, messageId)) { - return; - } - store.setStreamingMessageId(sessionId, messageId); - store.updateStreamingText(sessionId, text); - }), - ); - - unlisteners.push( - listen("acp:done", (event) => { - if (!active) return; - console.log( - `[perf:stream] ${event.payload.sessionId.slice(0, 8)} done mid=${event.payload.messageId.slice(0, 8)} at ${performance.now().toFixed(1)}ms`, - ); - const store = useChatStore.getState(); - const { sessionId, messageId } = event.payload; - const isLoading = store.loadingSessionIds.has(sessionId); - - if (isLoading) { - const msg = getBufferedMessage(sessionId, messageId); - if (msg) { - msg.content = msg.content.map((block) => - block.type === "toolRequest" && block.status === "executing" - ? { ...block, status: "completed" as const } - : block, - ); - const updated = updateCompletionStatus(msg, "completed"); - if (updated !== msg && updated.metadata) { - msg.metadata = updated.metadata; - } - } - return; - } - - store.updateMessage(sessionId, messageId, (message) => { - const content = message.content.map((block) => - block.type === "toolRequest" && block.status === "executing" - ? { ...block, status: "completed" as const } - : block, - ); - return updateCompletionStatus({ ...message, content }, "completed"); - }); - store.setPendingAssistantProvider(sessionId, null); - store.setStreamingMessageId(sessionId, null); - - store.setChatState(sessionId, "idle"); - if (useChatSessionStore.getState().activeSessionId !== sessionId) { - store.markSessionUnread(sessionId); - } - - const sessionStore = useChatSessionStore.getState(); - const session = sessionStore.getSession(sessionId); - if (session && isDefaultChatTitle(session.title)) { - const messages = store.messagesBySession[sessionId]; - const firstUserMsg = messages?.find((m) => m.role === "user"); - if (firstUserMsg) { - const textContent = firstUserMsg.content.find( - (c) => c.type === "text" && "text" in c, - ); - if (textContent && "text" in textContent) { - const title = textContent.text.slice(0, 100); - sessionStore.updateSession( - sessionId, - { - title, - updatedAt: new Date().toISOString(), - }, - { persistOverlay: false }, - ); - } - } - } - }), - ); - - unlisteners.push( - listen("acp:tool_call", (event) => { - if (!active) return; - const store = useChatStore.getState(); - const { sessionId, messageId, toolCallId, title } = event.payload; - - if (store.loadingSessionIds.has(sessionId)) { - const msg = getBufferedMessage(sessionId, messageId); - if (msg) { - msg.content.push({ - type: "toolRequest", - id: toolCallId, - name: title, - arguments: {}, - status: "executing", - startedAt: Date.now(), - }); - } - return; - } - - if (!shouldTrackStreamingEvent(store, sessionId, messageId)) { - return; - } - - const toolRequest: ToolRequestContent = { - type: "toolRequest", - id: toolCallId, - name: title, - arguments: {}, - status: "executing", - startedAt: Date.now(), - }; - store.setStreamingMessageId(sessionId, messageId); - store.appendToStreamingMessage(sessionId, toolRequest); - }), - ); - - unlisteners.push( - listen("acp:tool_title", (event) => { - if (!active) return; - const { sessionId: sid, messageId, toolCallId, title } = event.payload; - const store = useChatStore.getState(); - - if (store.loadingSessionIds.has(sid)) { - const msg = getBufferedMessage(sid, messageId); - if (msg) { - const tc = msg.content.find( - (c) => c.type === "toolRequest" && c.id === toolCallId, - ); - if (tc && tc.type === "toolRequest") { - (tc as ToolRequestContent).name = title; - } - } - return; - } - - if (!shouldTrackStreamingEvent(store, sid, messageId)) { - return; - } - store.updateMessage(sid, messageId, (msg) => ({ - ...msg, - content: msg.content.map((c) => - c.type === "toolRequest" && c.id === toolCallId - ? { ...c, name: title } - : c, - ), - })); - }), - ); - - unlisteners.push( - listen("acp:tool_result", (event) => { - if (!active) return; - const store = useChatStore.getState(); - const { sessionId, messageId, content } = event.payload; - - if (store.loadingSessionIds.has(sessionId)) { - const msg = getBufferedMessage(sessionId, messageId); - if (msg) { - const toolRequest = findLatestUnpairedToolRequest(msg.content); - if (toolRequest) { - const idx = msg.content.indexOf(toolRequest); - if (idx >= 0) { - msg.content[idx] = { ...toolRequest, status: "completed" }; - } - } - msg.content.push({ - type: "toolResponse", - id: toolRequest?.id ?? crypto.randomUUID(), - name: toolRequest?.name ?? "", - result: content, - isError: false, - }); - } - return; - } - - if (!shouldTrackStreamingEvent(store, sessionId, messageId)) { - return; - } - const streamingMessage = messageId - ? store.messagesBySession[sessionId]?.find( - (message) => message.id === messageId, - ) - : undefined; - const toolRequest = streamingMessage - ? findLatestUnpairedToolRequest(streamingMessage.content) - : null; - store.updateMessage(sessionId, messageId, (message) => ({ - ...message, - content: message.content.map((block) => - block.type === "toolRequest" && block.id === toolRequest?.id - ? { ...block, status: "completed" } - : block, - ), - })); - const toolResponse: ToolResponseContent = { - type: "toolResponse", - id: toolRequest?.id ?? crypto.randomUUID(), - name: toolRequest?.name ?? "", - result: content, - isError: false, - }; - store.setStreamingMessageId(sessionId, messageId); - store.appendToStreamingMessage(sessionId, toolResponse); - }), - ); - - unlisteners.push( - listen<{ sessionId: string; messageId: string; text: string }>( - "acp:replay_user_message", - (event) => { - if (!active) return; - console.log( - `[perf:stream] ${event.payload.sessionId.slice(0, 8)} replay_user_message at ${performance.now().toFixed(1)}ms`, - ); - const { sessionId, messageId, text } = event.payload; - ensureReplayBuffer(sessionId).push({ - id: messageId, - role: "user", - created: Date.now(), - content: [{ type: "text", text }], - metadata: { userVisible: true, agentVisible: true }, - }); - }, - ), - ); - - unlisteners.push( - listen("acp:session_bound", (event) => { - if (!active) return; - - useChatSessionStore - .getState() - .setSessionAcpId( - event.payload.sessionId, - event.payload.gooseSessionId, - ); - }), - ); - - unlisteners.push( - listen("acp:session_info", (event) => { - if (!active) return; - const session = useChatSessionStore - .getState() - .getSession(event.payload.sessionId); - if (event.payload.title && !session?.userSetName) { - useChatSessionStore.getState().updateSession( - event.payload.sessionId, - { - title: event.payload.title, - }, - { persistOverlay: false }, - ); - } - }), - ); - - unlisteners.push( - listen("acp:model_state", (event) => { - if (!active) return; - const { - sessionId, - providerId, - currentModelId, - currentModelName, - availableModels, - } = event.payload; - const sessionStore = useChatSessionStore.getState(); - if (providerId) { - sessionStore.cacheModelsForProvider(providerId, availableModels); - } - const session = sessionStore.getSession(sessionId); - const sessionProvider = session?.providerId; - if (providerId && sessionProvider && providerId !== sessionProvider) { - console.debug( - `[acp:model_state] Ignoring event: provider mismatch (event: ${providerId}, session: ${sessionProvider})`, - ); - return; - } - const modelName = currentModelName ?? currentModelId; - sessionStore.setSessionModels(sessionId, availableModels); - if (!providerId && session?.modelId) { - return; - } - sessionStore.updateSession( - sessionId, - { - modelId: currentModelId, - modelName, - }, - { persistOverlay: false }, - ); - }), - ); - - unlisteners.push( - listen("acp:usage_update", (event) => { - if (!active) return; - useChatStore.getState().updateTokenState(event.payload.sessionId, { - accumulatedTotal: event.payload.used, - contextLimit: event.payload.size, - }); - }), - ); - - return () => { - active = false; - unsubscribeFlush(); - for (const timer of replayTimeouts.values()) { - clearTimeout(timer); - } - replayTimeouts.clear(); - for (const unlistenPromise of unlisteners) { - unlistenPromise.then((unlisten) => unlisten()); - } - }; - }, [enabled]); -} diff --git a/ui/goose2/src/features/chat/hooks/useChat.ts b/ui/goose2/src/features/chat/hooks/useChat.ts index 8bd70cda50..1150f1074a 100644 --- a/ui/goose2/src/features/chat/hooks/useChat.ts +++ b/ui/goose2/src/features/chat/hooks/useChat.ts @@ -227,8 +227,6 @@ export function useChat( } } - // Send via ACP — response streams back through Tauri events - // which are handled by the global useAcpStream listener in AppShell. store.setChatState(sessionId, "streaming"); // When images are present with no text, pass a single space so the ACP // driver doesn't send an empty text content block that goose rejects. @@ -236,9 +234,8 @@ export function useChat( buildAttachmentPromptPreamble(attachments); const promptBody = text.trim() || (images?.length ? " " : text); const acpPrompt = `${attachmentPromptPreamble}${promptBody}`; - await acpSendMessage(sessionId, providerId, acpPrompt, { + await acpSendMessage(sessionId, acpPrompt, { systemPrompt, - workingDir: workingDirOverride, personaId: effectivePersonaInfo?.id, personaName: effectivePersonaInfo?.name, images: images?.map( diff --git a/ui/goose2/src/features/chat/hooks/useSSE.ts b/ui/goose2/src/features/chat/hooks/useSSE.ts deleted file mode 100644 index 0efbd2d938..0000000000 --- a/ui/goose2/src/features/chat/hooks/useSSE.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { useEffect, useRef, useState, useCallback } from "react"; - -interface UseSSEOptions { - onMessage?: (event: MessageEvent) => void; - onError?: (error: Event) => void; - onOpen?: () => void; - enabled?: boolean; -} - -interface UseSSEReturn { - close: () => void; - readyState: number; -} - -/** - * Hook for managing an EventSource (SSE) connection lifecycle. - * - * Automatically connects when `enabled` is true (default) and disconnects - * on unmount or when `enabled` becomes false. - */ -export function useSSE(url: string, options?: UseSSEOptions): UseSSEReturn { - const { onMessage, onError, onOpen, enabled = true } = options ?? {}; - const sourceRef = useRef(null); - const [readyState, setReadyState] = useState(EventSource.CLOSED); - - // Stable refs for callbacks to avoid reconnecting when handlers change - const onMessageRef = useRef(onMessage); - onMessageRef.current = onMessage; - const onErrorRef = useRef(onError); - onErrorRef.current = onError; - const onOpenRef = useRef(onOpen); - onOpenRef.current = onOpen; - - const close = useCallback(() => { - if (sourceRef.current) { - sourceRef.current.close(); - sourceRef.current = null; - setReadyState(EventSource.CLOSED); - } - }, []); - - useEffect(() => { - if (!enabled || !url) { - close(); - return; - } - - const source = new EventSource(url); - sourceRef.current = source; - - source.onopen = () => { - setReadyState(EventSource.OPEN); - onOpenRef.current?.(); - }; - - source.onmessage = (event) => { - onMessageRef.current?.(event); - }; - - source.onerror = (event) => { - setReadyState(source.readyState); - onErrorRef.current?.(event); - }; - - setReadyState(EventSource.CONNECTING); - - return () => { - source.close(); - sourceRef.current = null; - }; - }, [url, enabled, close]); - - return { close, readyState }; -} diff --git a/ui/goose2/src/features/chat/ui/ContextPanel.tsx b/ui/goose2/src/features/chat/ui/ContextPanel.tsx index ce199a5f44..69e804d0a4 100644 --- a/ui/goose2/src/features/chat/ui/ContextPanel.tsx +++ b/ui/goose2/src/features/chat/ui/ContextPanel.tsx @@ -1,6 +1,5 @@ -import { useCallback, useEffect, useState } from "react"; +import { useCallback, useState } from "react"; import { useTranslation } from "react-i18next"; -import { listen } from "@tauri-apps/api/event"; import { FilesList } from "./FilesList"; import { useGitState } from "@/shared/hooks/useGitState"; import { useChangedFiles } from "@/shared/hooks/useChangedFiles"; @@ -161,17 +160,6 @@ export function ContextPanel({ void refetchAll(); }, [refetchAll]); - useEffect(() => { - const unlisten = listen<{ sessionId: string }>("acp:done", (event) => { - if (event.payload.sessionId === sessionId) { - void refetchFiles(); - } - }); - return () => { - void unlisten.then((fn) => fn()); - }; - }, [sessionId, refetchFiles]); - return ( ({ }), })); -vi.mock("@tauri-apps/api/event", () => ({ - listen: () => Promise.resolve(() => {}), -})); - vi.mock("@tauri-apps/plugin-opener", () => ({ openPath: vi.fn(), })); diff --git a/ui/goose2/src/features/sidebar/ui/Sidebar.tsx b/ui/goose2/src/features/sidebar/ui/Sidebar.tsx index 8cba65c48c..56dae4b75d 100644 --- a/ui/goose2/src/features/sidebar/ui/Sidebar.tsx +++ b/ui/goose2/src/features/sidebar/ui/Sidebar.tsx @@ -491,73 +491,70 @@ export function Sidebar({ })} - {!collapsed && ( - <> - {sidebarSearch.submittedQuery ? ( -
- {sidebarSearch.error && ( -

- {t("search.error")} -

+ {!collapsed && + (sidebarSearch.submittedQuery ? ( +
+ {sidebarSearch.error && ( +

+ {t("search.error")} +

+ )} + + {sidebarSearch.isSearching && + sidebarSearch.results.length === 0 && ( +
+ {t("search.searching")} +
)} - {sidebarSearch.isSearching && - sidebarSearch.results.length === 0 && ( -
- {t("search.searching")} -
- )} - - {(!sidebarSearch.isSearching || - sidebarSearch.results.length > 0) && ( - { - if (messageId) { - onSelectSearchResult?.( - sessionId, - messageId, - sidebarSearch.submittedQuery, - ); - return; - } - onSelectSession?.(sessionId); - }} - getPersonaName={sidebarResolvers.getPersonaName} - getProjectName={sidebarResolvers.getProjectName} - /> - )} -
- ) : ( - - )} - - )} + {(!sidebarSearch.isSearching || + sidebarSearch.results.length > 0) && ( + { + if (messageId) { + onSelectSearchResult?.( + sessionId, + messageId, + sidebarSearch.submittedQuery, + ); + return; + } + onSelectSession?.(sessionId); + }} + getPersonaName={sidebarResolvers.getPersonaName} + getProjectName={sidebarResolvers.getProjectName} + /> + )} +
+ ) : ( + + ))} diff --git a/ui/goose2/src/shared/api/acp.ts b/ui/goose2/src/shared/api/acp.ts index 642d3b381b..8bfd8914fd 100644 --- a/ui/goose2/src/shared/api/acp.ts +++ b/ui/goose2/src/shared/api/acp.ts @@ -1,5 +1,4 @@ -import { invoke } from "@tauri-apps/api/core"; -import { USE_DIRECT_ACP } from "./acpFeatureFlag"; +import type { ContentBlock } from "@agentclientprotocol/sdk"; import * as directAcp from "./acpApi"; import * as sessionTracker from "./acpSessionTracker"; import { @@ -15,7 +14,6 @@ export interface AcpProvider { export interface AcpSendMessageOptions { systemPrompt?: string; - workingDir?: string; personaId?: string; personaName?: string; /** Image attachments as [base64Data, mimeType] pairs. */ @@ -29,63 +27,40 @@ export interface AcpPrepareSessionOptions { /** Discover ACP providers installed on the system. */ export async function discoverAcpProviders(): Promise { - if (USE_DIRECT_ACP) { - return directAcp.listProviders(); - } - return invoke("discover_acp_providers"); + return directAcp.listProviders(); } /** Send a message to an ACP agent. Response streams via Tauri events. */ export async function acpSendMessage( sessionId: string, - providerId: string, prompt: string, options: AcpSendMessageOptions = {}, ): Promise { - if (USE_DIRECT_ACP) { - const { systemPrompt, personaId, images } = options; + const { systemPrompt, personaId, images } = options; - const gooseSessionId = sessionTracker.getGooseSessionId( - sessionId, - personaId, - ); - if (!gooseSessionId) { - throw new Error("Session not prepared. Call acpPrepareSession first."); - } - - const hasSystem = systemPrompt && systemPrompt.trim().length > 0; - const effectivePrompt = hasSystem - ? `\n${systemPrompt}\n\n\n\n${prompt}\n` - : prompt; - - const content: import("@agentclientprotocol/sdk").ContentBlock[] = [ - { type: "text", text: effectivePrompt }, - ]; - if (images) { - for (const [data, mimeType] of images) { - content.push({ type: "image", data, mimeType } as any); - } - } - - const messageId = crypto.randomUUID(); - setActiveMessageId(gooseSessionId, messageId); - - await directAcp.prompt(gooseSessionId, content); - - clearActiveMessageId(gooseSessionId); - return; + const gooseSessionId = sessionTracker.getGooseSessionId(sessionId, personaId); + if (!gooseSessionId) { + throw new Error("Session not prepared. Call acpPrepareSession first."); } - const { systemPrompt, workingDir, personaId, personaName, images } = options; - return invoke("acp_send_message", { - sessionId, - providerId, - prompt, - systemPrompt: systemPrompt ?? null, - workingDir: workingDir ?? null, - personaId: personaId ?? null, - personaName: personaName ?? null, - images: images ?? [], - }); + + const hasSystem = systemPrompt && systemPrompt.trim().length > 0; + const effectivePrompt = hasSystem + ? `\n${systemPrompt}\n\n\n\n${prompt}\n` + : prompt; + + const content: ContentBlock[] = [{ type: "text", text: effectivePrompt }]; + if (images) { + for (const [data, mimeType] of images) { + content.push({ type: "image", data, mimeType } as ContentBlock); + } + } + + const messageId = crypto.randomUUID(); + setActiveMessageId(gooseSessionId, messageId); + + await directAcp.prompt(gooseSessionId, content); + + clearActiveMessageId(gooseSessionId); } /** Prepare or warm an ACP session ahead of the first prompt. */ @@ -94,37 +69,21 @@ export async function acpPrepareSession( providerId: string, options: AcpPrepareSessionOptions = {}, ): Promise { - if (USE_DIRECT_ACP) { - const workingDir = options.workingDir ?? "~/.goose/artifacts"; - await sessionTracker.prepareSession( - sessionId, - providerId, - workingDir, - options.personaId, - ); - return; - } - const { workingDir, personaId } = options; - return invoke("acp_prepare_session", { + const workingDir = options.workingDir ?? "~/.goose/artifacts"; + await sessionTracker.prepareSession( sessionId, providerId, - workingDir: workingDir ?? null, - personaId: personaId ?? null, - }); + workingDir, + options.personaId, + ); } export async function acpSetModel( sessionId: string, modelId: string, ): Promise { - if (USE_DIRECT_ACP) { - const gooseSessionId = sessionTracker.getGooseSessionId(sessionId); - return directAcp.setModel(gooseSessionId ?? sessionId, modelId); - } - return invoke("acp_set_model", { - sessionId, - modelId, - }); + const gooseSessionId = sessionTracker.getGooseSessionId(sessionId); + return directAcp.setModel(gooseSessionId ?? sessionId, modelId); } /** Session info returned by the goose binary's list_sessions. */ @@ -145,77 +104,54 @@ export interface AcpSessionSearchResult { /** List all sessions known to the goose binary. */ export async function acpListSessions(): Promise { - if (USE_DIRECT_ACP) { - return directAcp.listSessions(); - } - return invoke("acp_list_sessions"); + return directAcp.listSessions(); } export async function acpSearchSessions( query: string, sessionIds: string[], ): Promise { - if (USE_DIRECT_ACP) { - return searchSessionsViaExports(query, sessionIds); - } - return invoke("acp_search_sessions", { query, sessionIds }); + return searchSessionsViaExports(query, sessionIds); } /** * Load an existing session from the goose binary. * * This triggers message replay via SessionNotification events that the - * frontend's useAcpStream hook picks up automatically. + * notification handler picks up automatically. */ export async function acpLoadSession( sessionId: string, gooseSessionId: string, workingDir?: string, ): Promise { - if (USE_DIRECT_ACP) { - const effectiveWorkingDir = workingDir ?? "~/.goose/artifacts"; - await directAcp.loadSession(gooseSessionId, effectiveWorkingDir); - sessionTracker.registerSession( - sessionId, - gooseSessionId, - "goose", - effectiveWorkingDir, - ); - return; - } - return invoke("acp_load_session", { + const effectiveWorkingDir = workingDir ?? "~/.goose/artifacts"; + await directAcp.loadSession(gooseSessionId, effectiveWorkingDir); + sessionTracker.registerSession( sessionId, gooseSessionId, - workingDir: workingDir ?? null, - }); + "goose", + effectiveWorkingDir, + ); } /** Export a session as JSON via the goose binary. */ export async function acpExportSession(sessionId: string): Promise { - if (USE_DIRECT_ACP) { - return directAcp.exportSession(sessionId); - } - return invoke("acp_export_session", { sessionId }); + return directAcp.exportSession(sessionId); } /** Import a session from JSON via the goose binary. Returns new session metadata. */ export async function acpImportSession(json: string): Promise { - if (USE_DIRECT_ACP) { - return directAcp.importSession(json); - } - return invoke("acp_import_session", { json }); + return directAcp.importSession(json); } /** Duplicate (fork) a session via the goose binary. Returns new session metadata. */ export async function acpDuplicateSession( sessionId: string, ): Promise { - if (USE_DIRECT_ACP) { - const gooseSessionId = - sessionTracker.getGooseSessionId(sessionId) ?? sessionId; - return directAcp.forkSession(gooseSessionId); - } - return invoke("acp_duplicate_session", { sessionId }); + const gooseSessionId = + sessionTracker.getGooseSessionId(sessionId) ?? sessionId; + return directAcp.forkSession(gooseSessionId); } /** Cancel an in-progress ACP session so the backend stops streaming. */ @@ -223,16 +159,7 @@ export async function acpCancelSession( sessionId: string, personaId?: string, ): Promise { - if (USE_DIRECT_ACP) { - const gooseSessionId = sessionTracker.getGooseSessionId( - sessionId, - personaId, - ); - await directAcp.cancelSession(gooseSessionId ?? sessionId); - return true; - } - return invoke("acp_cancel_session", { - sessionId, - personaId: personaId ?? null, - }); + const gooseSessionId = sessionTracker.getGooseSessionId(sessionId, personaId); + await directAcp.cancelSession(gooseSessionId ?? sessionId); + return true; } diff --git a/ui/goose2/src/shared/api/acpApi.ts b/ui/goose2/src/shared/api/acpApi.ts index 72007f753e..b992c1be05 100644 --- a/ui/goose2/src/shared/api/acpApi.ts +++ b/ui/goose2/src/shared/api/acpApi.ts @@ -23,28 +23,40 @@ const DEPRECATED_PROVIDER_IDS = new Set(["claude-code", "codex", "gemini-cli"]); export async function listProviders(): Promise { const client = await getClient(); const result = await client.goose.GooseProvidersList({}); + // biome-ignore lint/suspicious/noExplicitAny: ACP SDK types don't expose providers field return (result as any).providers - .filter((p: any) => !DEPRECATED_PROVIDER_IDS.has(p.id)) - .map((p: any) => ({ id: p.id, label: p.label })); + .filter( + (p: { id: string; label: string }) => !DEPRECATED_PROVIDER_IDS.has(p.id), + ) + .map((p: { id: string; label: string }) => ({ id: p.id, label: p.label })); } export async function listSessions(): Promise { const client = await getClient(); // GooseClient.unstable_listSessions doesn't work with SDK 0.19 (renamed to listSessions). // Bypass GooseClient and call the connection directly. Fix when ui/acp is updated. + // biome-ignore lint/suspicious/noExplicitAny: SDK doesn't expose conn property const conn = (client as any).conn; const response = await conn.listSessions({}); - return response.sessions.map((info: any) => ({ - sessionId: info.sessionId, - title: info.title ?? null, - updatedAt: info.updatedAt ?? null, - messageCount: (info._meta?.messageCount as number) ?? 0, - })); + return response.sessions.map( + (info: { + sessionId: string; + title?: string; + updatedAt?: string; + _meta?: Record; + }) => ({ + sessionId: info.sessionId, + title: info.title ?? null, + updatedAt: info.updatedAt ?? null, + messageCount: (info._meta?.messageCount as number) ?? 0, + }), + ); } export async function exportSession(sessionId: string): Promise { const client = await getClient(); const result = await client.goose.GooseSessionExport({ sessionId }); + // biome-ignore lint/suspicious/noExplicitAny: SDK doesn't expose data field on export result return (result as any).data; } diff --git a/ui/goose2/src/shared/api/acpConnection.ts b/ui/goose2/src/shared/api/acpConnection.ts index 86b821d9b6..cac618b2da 100644 --- a/ui/goose2/src/shared/api/acpConnection.ts +++ b/ui/goose2/src/shared/api/acpConnection.ts @@ -1,5 +1,5 @@ import { invoke } from "@tauri-apps/api/core"; -import { GooseClient } from "@aaif/goose-acp"; +import { GooseClient } from "@aaif/goose-sdk"; import { PROTOCOL_VERSION, type Client, diff --git a/ui/goose2/src/shared/api/acpFeatureFlag.ts b/ui/goose2/src/shared/api/acpFeatureFlag.ts deleted file mode 100644 index 59ae61e5bb..0000000000 --- a/ui/goose2/src/shared/api/acpFeatureFlag.ts +++ /dev/null @@ -1 +0,0 @@ -export const USE_DIRECT_ACP = true; diff --git a/ui/goose2/src/shared/api/acpNotificationHandler.ts b/ui/goose2/src/shared/api/acpNotificationHandler.ts index 02d385833a..cc2156139f 100644 --- a/ui/goose2/src/shared/api/acpNotificationHandler.ts +++ b/ui/goose2/src/shared/api/acpNotificationHandler.ts @@ -235,7 +235,7 @@ function handleLive( ...msg, content: msg.content.map((c) => c.type === "toolRequest" && c.id === update.toolCallId - ? { ...c, name: update.title! } + ? { ...c, name: update.title ?? "" } : c, ), })); @@ -310,7 +310,8 @@ function handleShared(sessionId: string, update: SessionUpdate): void { }; if ("options" in configUpdate && Array.isArray(configUpdate.options)) { const modelOption = configUpdate.options.find( - (opt: any) => opt.category === "model", + (opt: { category?: string; kind?: Record }) => + opt.category === "model", ); if (modelOption?.kind?.type === "select") { const select = modelOption.kind; @@ -391,6 +392,7 @@ function findMessageWithToolCall( } function extractToolResultText(update: { + // biome-ignore lint/suspicious/noExplicitAny: ACP SDK ToolCallContent type is complex content?: Array | null; rawOutput?: unknown; }): string { diff --git a/ui/goose2/src/shared/api/createWebSocketStream.ts b/ui/goose2/src/shared/api/createWebSocketStream.ts index d785ce5b89..d059044ea5 100644 --- a/ui/goose2/src/shared/api/createWebSocketStream.ts +++ b/ui/goose2/src/shared/api/createWebSocketStream.ts @@ -55,6 +55,7 @@ export function createWebSocketStream(wsUrl: string): Stream { async pull(controller) { await waitForMessage(); while (incoming.length > 0) { + // biome-ignore lint/style/noNonNullAssertion: length checked in while condition controller.enqueue(incoming.shift()!); } if (closed && incoming.length === 0) { diff --git a/ui/goose2/src/shared/api/sessionSearch.ts b/ui/goose2/src/shared/api/sessionSearch.ts index 4dd21efc2b..871b6f2d5a 100644 --- a/ui/goose2/src/shared/api/sessionSearch.ts +++ b/ui/goose2/src/shared/api/sessionSearch.ts @@ -106,7 +106,7 @@ function searchSession( }; } -function safeParse(json: string): Record | null { +function safeParse(json: string): Record | null { try { return JSON.parse(json); } catch { diff --git a/ui/goose2/src/shared/types/agents.ts b/ui/goose2/src/shared/types/agents.ts index bfdc234cf0..df4380085b 100644 --- a/ui/goose2/src/shared/types/agents.ts +++ b/ui/goose2/src/shared/types/agents.ts @@ -1,8 +1,6 @@ -// Provider types — these map to goose serve provider names. -// All sessions run through goose serve; the provider ID selects which -// backend provider goose uses for inference. The list is dynamic -// (fetched from the backend via discover_acp_providers) so this is a -// plain string rather than a narrow union. +// Provider types map to goose serve provider names. +// The provider list is dynamic, so this remains a plain string rather than +// a narrow union. export type ProviderType = string; export interface ProviderConfig { diff --git a/ui/goose2/src/test/mocks/goose-sdk.ts b/ui/goose2/src/test/mocks/goose-sdk.ts new file mode 100644 index 0000000000..0443a49f10 --- /dev/null +++ b/ui/goose2/src/test/mocks/goose-sdk.ts @@ -0,0 +1,7 @@ +export class GooseClient { + closed = Promise.resolve(); + + constructor(..._args: unknown[]) {} + + async initialize(..._args: unknown[]): Promise {} +} diff --git a/ui/goose2/tests/e2e/fixtures/tauri-mock.ts b/ui/goose2/tests/e2e/fixtures/tauri-mock.ts index 56e28dd66f..fa1bd8cbad 100644 --- a/ui/goose2/tests/e2e/fixtures/tauri-mock.ts +++ b/ui/goose2/tests/e2e/fixtures/tauri-mock.ts @@ -124,8 +124,6 @@ export function buildInitScript(options?: { return Promise.resolve("/tmp/avatars"); case "save_persona_avatar_bytes": return Promise.resolve("avatar.png"); - case "discover_acp_providers": - return Promise.resolve([]); case "list_files_for_mentions": return Promise.resolve([]); case "get_home_dir": diff --git a/ui/goose2/vitest.config.ts b/ui/goose2/vitest.config.ts index 6f66312cda..158d7a49f2 100644 --- a/ui/goose2/vitest.config.ts +++ b/ui/goose2/vitest.config.ts @@ -7,6 +7,7 @@ export default defineConfig({ resolve: { alias: { "@": resolve(__dirname, "./src"), + "@aaif/goose-sdk": resolve(__dirname, "./src/test/mocks/goose-sdk.ts"), }, }, test: { diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 3def31fa90..1d310b57a7 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -353,9 +353,9 @@ importers: goose2: dependencies: - '@aaif/goose-acp': - specifier: ^0.16.0 - version: 0.16.0(@agentclientprotocol/sdk@0.19.0(zod@4.3.6)) + '@aaif/goose-sdk': + specifier: workspace:* + version: link:../sdk '@agentclientprotocol/sdk': specifier: ^0.19.0 version: 0.19.0(zod@4.3.6) @@ -468,8 +468,8 @@ importers: specifier: ^2 version: 2.10.1 '@tauri-apps/plugin-dialog': - specifier: ^2.6.0 - version: 2.7.0 + specifier: ~2.6.0 + version: 2.6.0 '@tauri-apps/plugin-opener': specifier: ^2.5.3 version: 2.5.3 @@ -735,11 +735,6 @@ importers: packages: - '@aaif/goose-acp@0.16.0': - resolution: {integrity: sha512-LJLn01pqobvQAsagScROFOnjKRSQPaDuP7v17oyrK1IDfvZzOM20ZkQcvGDWhYCRUHXWBJgJ9dD6iZkVtNYYwg==} - peerDependencies: - '@agentclientprotocol/sdk': '*' - '@acemir/cssom@0.9.31': resolution: {integrity: sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==} @@ -3500,8 +3495,8 @@ packages: engines: {node: '>= 10'} hasBin: true - '@tauri-apps/plugin-dialog@2.7.0': - resolution: {integrity: sha512-4nS/hfGMGCXiAS3LtVjH9AgsSAPJeG/7R+q8agTFqytjnMa4Zq95Bq8WzVDkckpanX+yyRHXnRtrKXkANKDHvw==} + '@tauri-apps/plugin-dialog@2.6.0': + resolution: {integrity: sha512-q4Uq3eY87TdcYzXACiYSPhmpBA76shgmQswGkSVio4C82Sz2W4iehe9TnKYwbq7weHiL88Yw19XZm7v28+Micg==} '@tauri-apps/plugin-opener@2.5.3': resolution: {integrity: sha512-CCcUltXMOfUEArbf3db3kCE7Ggy1ExBEBl51Ko2ODJ6GDYHRp1nSNlQm5uNCFY5k7/ufaK5Ib3Du/Zir19IYQQ==} @@ -8854,11 +8849,6 @@ packages: snapshots: - '@aaif/goose-acp@0.16.0(@agentclientprotocol/sdk@0.19.0(zod@4.3.6))': - dependencies: - '@agentclientprotocol/sdk': 0.19.0(zod@4.3.6) - zod: 3.25.76 - '@acemir/cssom@0.9.31': {} '@adobe/css-tools@4.4.4': {} @@ -11804,7 +11794,7 @@ snapshots: '@tauri-apps/cli-win32-ia32-msvc': 2.10.1 '@tauri-apps/cli-win32-x64-msvc': 2.10.1 - '@tauri-apps/plugin-dialog@2.7.0': + '@tauri-apps/plugin-dialog@2.6.0': dependencies: '@tauri-apps/api': 2.10.1