diff --git a/AGENTS.md b/AGENTS.md index fc81296..a77eceb 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -149,6 +149,11 @@ Repository-wide constraints: - Keep platform behavior behind Effect services and Layers. The browser, Tauri host, and macOS Swift code are adapters to shared application capabilities, not alternate homes for product workflows or interface state. +- Every user-triggered native operation, including window chrome such as + dragging or resizing, must enter through a named Effect capability and its + provided runtime. React components and page scripts must not import or call + `@tauri-apps/api/*` directly; only the named platform Layer may adapt that + API. Tests provide that capability through a test Layer. - Test observable behavior through exported contracts, HTTP requests, and the rendered interface. Do not assert that source files contain selected text. - Treat documentation as guidance, not proof that a boundary or lifecycle is diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 5db18d3..3a2a282 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -67,7 +67,12 @@ model responses. The static view-only route fetches neither the Preact renderer nor Effect. Compiler, package, shell, Worker, and Wasm implementations are separate dynamic boundaries after workspace activation. Astro production uses Preact compatibility for the protected components; the direct Vite SPA remains -a React fallback. +a React fallback. UI primitives follow the official Shadcn v4 composition +model with its Radix primitives and the official AI Elements registry. Radix +and Tailwind are workspace implementation details behind the Astro island +boundary; they do not +own workflows, persistence, or the static view-only route, and each added +primitive must preserve the browser budgets. ## Effect application kernel diff --git a/DESIGN.md b/DESIGN.md index eca9e87..2a5a92b 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -10,8 +10,8 @@ colors: muted: "oklch(0.690 0.012 340)" quiet: "oklch(0.500 0.012 340)" line: "oklch(0.300 0.010 340)" - flect-rose: "oklch(0.630 0.180 340)" - flect-rose-hover: "oklch(0.690 0.170 340)" + primary: "oklch(0.922 0 0)" + primary-hover: "oklch(0.870 0 0)" ready: "oklch(0.780 0.120 158)" danger: "oklch(0.660 0.170 27)" typography: @@ -53,7 +53,7 @@ components: rounded: "{rounded.pill}" size: "40px" button-primary-hover: - backgroundColor: "{colors.flect-rose-hover}" + backgroundColor: "{colors.primary-hover}" textColor: "{colors.void}" rounded: "{rounded.pill}" size: "40px" @@ -72,9 +72,9 @@ components: Flect feels like working at a black anodized drafting desk after everything unnecessary has been cleared away. The interface recedes so the person's intent -and the surface being shaped remain central. One restrained rose signal carries -identity; it appears as a precise indication of agency, never as ambient -decoration. +and the surface being shaped remain central. A neutral hierarchy carries the +interface; state is communicated with contrast, type, icons, and copy rather +than a decorative product accent. The system is familiar enough to trust immediately and exact enough to feel first-party. It rejects widget-dashboard density, chatbot sidecars, @@ -83,12 +83,28 @@ affordances, short labels, and restrained state motion. **Key Characteristics:** -- Near-black neutral architecture with one precise rose signal. +- Shadcn's neutral light and dark defaults, with no product accent color yet. - System typography tuned for calm density and high legibility. - Tonal layering before shadows; boundaries appear only when useful. - One centered agent composer that expands naturally into a conversation rail. - Protected recovery controls that remain quiet but always reachable. +### Component implementation + +Flect vendors the official Shadcn v4 component source. The protected workspace +uses Shadcn's Radix primitives and the official AI Elements registry for the +conversation, messages, composer, reasoning, and tool activity. The initial +visual baseline is Shadcn's neutral default; product-specific styling is a +later, deliberate layer instead of a parallel component system. + +Tailwind v4 compiles only the vendored workspace component sources. It does not +enter the static Astro activation shell, does not replace the Effect workflow +kernel, and does not authorize large registry-wide installs. Add primitives one +at a time, keep them behind the island or feature boundary that needs them, and +measure both the initial protected workspace and the on-demand chunk. A native +host control still wins whenever a WebView primitive fails the platform-native +quality contract. + ## 2. Platform-native quality contract Flect must feel like first-party software on every platform it claims to @@ -174,15 +190,15 @@ keyboard behavior, or a design that only works at the demo viewport. ## 3. Colors -The palette is monochrome at rest and reveals color only when state or agency -needs to be communicated. +The palette is neutral by default. Color appears only for semantic success, +warning, or failure states. ### Primary -- **Flect Rose** (`oklch(0.630 0.180 340)`): focus, active agent state, - selected controls, and the rare brand signal. -- **Flect Rose Hover** (`oklch(0.690 0.170 340)`): interactive emphasis when a - primary action needs more presence. +- **Primary** (`oklch(0.922 0 0)` dark, `oklch(0.205 0 0)` light): actions, + focus, and selected controls using Shadcn's neutral defaults. +- **Primary Hover**: a neighboring neutral tone that preserves contrast without + introducing a product accent. ### Secondary @@ -207,8 +223,8 @@ needs to be communicated. ### Named Rules -**The One Signal Rule.** Flect Rose occupies less than ten percent of a screen. -Its rarity makes agency unmistakable. +**The Semantic Color Rule.** Non-neutral color must communicate a named state +and must never be the only carrier of meaning. ## 4. Typography @@ -260,8 +276,9 @@ to communicate focus, movement, or temporary hierarchy. ### Buttons - **Shape:** circular for icon-only controls; 8px for labeled controls. -- **Primary:** Ink fill with Void content, reversing to Flect Rose when active. -- **Hover / Focus:** 180ms tonal transition and a visible 2px Flect Rose focus +- **Primary:** Ink fill with Void content, using the neighboring neutral when + active. +- **Hover / Focus:** 180ms tonal transition and a visible 2px primary focus ring with offset. - **Ghost:** transparent at rest, Raised Surface on hover, never a faint outline box. @@ -269,8 +286,8 @@ to communicate focus, movement, or temporary hierarchy. ### Chips - **Style:** tonal Surface or Raised Surface background with Ink or Muted text. -- **State:** selected chips use a low-chroma rose tint plus an explicit icon or - label change. +- **State:** selected chips use neutral contrast plus an explicit icon or label + change. ### Cards / Containers @@ -285,8 +302,8 @@ to communicate focus, movement, or temporary hierarchy. - **Style:** a 16px prompt surface without a resting outline. The text area and its action rail read as one instrument. -- **Focus:** Flect Rose appears as a precise inner seam; Prompt Lift signals the - active surface. +- **Focus:** Primary contrast appears as a precise inner seam; Prompt Lift + signals the active surface. - **Error / Disabled:** errors use Failure Red plus direct recovery copy; disabled controls retain readable text and expose their reason. @@ -356,19 +373,36 @@ existing Surface, Raised Surface, Line, Ink, and Muted tokens; code is `0.875rem` mono and table content is `0.8125rem`. Their own viewports own horizontal overflow, while copy, wrap, and expand actions stay dense on desktop and reach `44px` at compact widths. Details remain native disclosures, -links use Flect Rose only as an interaction cue, and footnotes remain subdued. +links use underline and neutral contrast as interaction cues, and footnotes +remain subdued. The complete rendering and trust contract lives in [`docs/superpowers/specs/2026-07-31-flect-chat-markdown-design.md`](docs/superpowers/specs/2026-07-31-flect-chat-markdown-design.md). ### Activity, Follow, and Diagnostics Tool use is a compact instrument in the conversation timeline, not a generic assistant -sentence and not a developer-console dump. A card always names the tool and -shows queued, running, completed, or failed state. Duration stays visible; +sentence and not a developer-console dump. An expanded row names the action +and shows queued, running, completed, or failed state. Duration stays visible; bounded commands, output, exit status, preview links, validation paths, and operation identifiers live in a native disclosure. Ready Mint and Failure Red support the label but never carry meaning alone. +Completed work is collapsed by default into one quiet turn-level disclosure +such as “Worked for 1.4 s.” The final assistant message remains visible. A +running turn uses the same line-level treatment, and individual commands appear +as borderless rows only after disclosure; command output uses a subtle inset +rule rather than nested cards. Failed work that ends the turn opens for +attention. Raw tool names, repeated completion badges, and one duration column +per command must not dominate the ordinary conversation. + +Every submitted request, its tool activity, and its final response share one +typed turn identity. Once a newer turn begins, the older request and work fold +behind one quiet `Asked …` line while that turn's final assistant response +remains visible. Expanding the line restores the complete request and work in +place. Historical user prompts must not remain as a stack of dominant cards, +and legacy records without turn identity remain readable rather than being +guessed into the wrong turn. + Conversation follow respects the reader. Content follows while the viewport is within 48px of its bottom. Once the person scrolls away, streaming and tool updates preserve that position and surface a quiet, keyboard-operable **Jump @@ -386,7 +420,7 @@ ordinary product surface into infrastructure chrome. ### Do: - **Do** keep the person's work and current prompt visually central. -- **Do** reserve Flect Rose for focus, selection, and active shaping. +- **Do** use neutral contrast for focus, selection, and active shaping. - **Do** use known platform affordances with visible keyboard focus. - **Do** use host-native surfaces when the WebView cannot meet the platform contract. diff --git a/README.md b/README.md index ce9df57..684cb3d 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,12 @@ until that stylesheet has loaded and the island is ready. Compiler, package, shell, Worker, and Wasm substrates remain on demand until a typed operation needs them. Production Astro uses Preact's React compatibility renderer for the existing workspace components; the direct Vite SPA remains a React fallback. +Official Shadcn v4 components, its Radix primitives, and the official AI +Elements conversation, message, composer, reasoning, and tool components +compile inside that deferred workspace stylesheet/chunk only. +The product intentionally starts from Shadcn's neutral defaults; Flect-specific +styling comes later, without forking interaction behavior. The static Astro +route carries none of the component runtime. The measured production gates and exact budgets are documented below. Flect remains under active development. The published v0.2.0 macOS preview is diff --git a/biome.json b/biome.json index 64b580e..5465979 100644 --- a/biome.json +++ b/biome.json @@ -22,6 +22,11 @@ "enabled": true, "indentStyle": "space" }, + "css": { + "parser": { + "tailwindDirectives": true + } + }, "linter": { "enabled": true, "rules": { @@ -34,5 +39,18 @@ "organizeImports": "on" } } - } + }, + "overrides": [ + { + "includes": ["src/components/ui/**"], + "linter": { + "rules": { + "a11y": { + "useKeyWithClickEvents": "off", + "useSemanticElements": "off" + } + } + } + } + ] } diff --git a/bun.lock b/bun.lock index 1bfea2d..3a0df00 100644 --- a/bun.lock +++ b/bun.lock @@ -12,6 +12,7 @@ "@flect/product": "workspace:*", "@jitl/quickjs-ng-wasmfile-release-sync": "0.32.0", "@modelcontextprotocol/server": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.2.6", "@riftydev/npm-client": "0.2.0", "@riftydev/runtime-js": "0.2.0", "@riftydev/runtime-wasi": "0.2.0", @@ -22,12 +23,16 @@ "@types/semver": "7.7.1", "@vue/compiler-sfc": "3.5.41", "acorn": "8.18.0", + "class-variance-authority": "0.7.1", + "clsx": "2.1.1", "effect": "4.0.0-beta.102", "esbuild-wasm": "0.28.1", "fflate": "0.8.3", "just-bash": "3.2.0", + "lucide-react": "1.30.0", "preact": "10.29.8", "quickjs-emscripten-core": "0.32.0", + "radix-ui": "1.6.7", "react": "19.2.8", "react-dom": "19.2.8", "react-markdown": "10.1.0", @@ -40,6 +45,7 @@ "shiki": "4.3.1", "svelte": "5.56.8", "typebox": "1.1.38", + "use-stick-to-bottom": "1.1.6", "wasm-git": "0.0.17", "zod": "4.2.0", }, @@ -50,6 +56,7 @@ "@effect/vitest": "4.0.0-beta.102", "@modelcontextprotocol/client": "2.0.0", "@playwright/test": "1.62.0", + "@tailwindcss/vite": "4.1.18", "@tauri-apps/cli": "2.11.4", "@testing-library/jest-dom": "7.0.0", "@testing-library/react": "16.3.2", @@ -62,6 +69,8 @@ "astro": "7.2.0", "concurrently": "10.0.4", "jsdom": "30.0.1", + "shadcn": "4.16.2", + "tailwindcss": "4.1.18", "typescript": "7.0.2", "vite": "8.1.5", "vitest": "4.1.10", @@ -183,14 +192,24 @@ "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.29.7", "", { "dependencies": { "@babel/compat-data": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g=="], + "@babel/helper-create-class-features-plugin": ["@babel/helper-create-class-features-plugin@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/helper-replace-supers": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/traverse": "^7.29.7", "semver": "^6.3.1" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg=="], + "@babel/helper-globals": ["@babel/helper-globals@7.29.7", "", {}, "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA=="], + "@babel/helper-member-expression-to-functions": ["@babel/helper-member-expression-to-functions@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg=="], + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g=="], "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.29.7", "", { "dependencies": { "@babel/helper-module-imports": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg=="], + "@babel/helper-optimise-call-expression": ["@babel/helper-optimise-call-expression@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" } }, "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong=="], + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.29.7", "", {}, "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw=="], + "@babel/helper-replace-supers": ["@babel/helper-replace-supers@7.29.7", "", { "dependencies": { "@babel/helper-member-expression-to-functions": "^7.29.7", "@babel/helper-optimise-call-expression": "^7.29.7", "@babel/traverse": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ=="], + + "@babel/helper-skip-transparent-expression-wrappers": ["@babel/helper-skip-transparent-expression-wrappers@7.29.7", "", { "dependencies": { "@babel/traverse": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ=="], + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="], @@ -203,10 +222,18 @@ "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A=="], + "@babel/plugin-syntax-typescript": ["@babel/plugin-syntax-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA=="], + + "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.29.7", "", { "dependencies": { "@babel/helper-module-transforms": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ=="], + "@babel/plugin-transform-react-jsx": ["@babel/plugin-transform-react-jsx@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-module-imports": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/types": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-WsZulLVBUHXVj2cUcPVx6UE21TpalB6bHbSFErKT0Ib++ax24jjXe73FqlWvdylFOjiuPHYi6VCcgRad1ItN+A=="], "@babel/plugin-transform-react-jsx-development": ["@babel/plugin-transform-react-jsx-development@7.29.7", "", { "dependencies": { "@babel/plugin-transform-react-jsx": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-Xfy3UVMF04+ypnFbkhvfqtmvwfe92qwQdbGZVonhE+6v35GzlofmOnA1szaZqzb9xYWr0nl1e5EMmzi0DNON1g=="], + "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.29.7", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.29.7", "@babel/helper-create-class-features-plugin": "^7.29.7", "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", "@babel/plugin-syntax-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw=="], + + "@babel/preset-typescript": ["@babel/preset-typescript@7.29.7", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.29.7", "@babel/helper-validator-option": "^7.29.7", "@babel/plugin-syntax-jsx": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@babel/plugin-transform-typescript": "^7.29.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-/Foi8vKY2EVbed/1eZx0gJEEwHAIxogrySI7rULcRIvhZzbvoE/b5qG5Ghc0WKAFKOHA9SD1x7RsFlOYdutIiQ=="], + "@babel/runtime": ["@babel/runtime@7.29.7", "", {}, "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw=="], "@babel/template": ["@babel/template@7.29.7", "", { "dependencies": { "@babel/code-frame": "^7.29.7", "@babel/parser": "^7.29.7", "@babel/types": "^7.29.7" } }, "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg=="], @@ -273,6 +300,10 @@ "@csstools/css-tokenizer": ["@csstools/css-tokenizer@4.0.0", "", {}, "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA=="], + "@dotenvx/dotenvx": ["@dotenvx/dotenvx@1.75.1", "", { "dependencies": { "@dotenvx/primitives": "^0.8.0", "commander": "^11.1.0", "conf": "^10.2.0", "dotenv": "^17.2.1", "enquirer": "^2.4.1", "env-paths": "^2.2.1", "execa": "^5.1.1", "fdir": "^6.2.0", "ignore": "^5.3.0", "object-treeify": "1.1.33", "open": "^8.4.2", "picomatch": "^4.0.4", "systeminformation": "^5.22.11", "undici": "^7.11.0", "which": "^4.0.0", "yocto-spinner": "^1.1.0" }, "bin": { "dotenvx": "src/cli/dotenvx.js" } }, "sha512-/BITOC9dmS/edY2zQwZNicQ059O6RKabtQfyEafV0nGtfYRNHYy1DIPiYVcov40+tob9hfmBnbR963dS+EQ1DQ=="], + + "@dotenvx/primitives": ["@dotenvx/primitives@0.8.0", "", {}, "sha512-VYJy0uhFm9zTJ1TxBaW/pA8bjbOM/OttaNMwZ1RHG4JKyRG7DhSdiqD1ipQoAyoD22olUtxbP78W9xY3Wd11bg=="], + "@earendil-works/pi-agent-core": ["@earendil-works/pi-agent-core@0.82.1", "", { "dependencies": { "@earendil-works/pi-ai": "^0.82.1", "diff": "8.0.4", "ignore": "7.0.5", "typebox": "1.1.38", "yaml": "2.9.0" } }, "sha512-Z3kloziJIE2dmrisRckZX8zDca/gIv9/YdFAzeoqpHiLV2wsni6bL4hInNSjVKLbqT+4kqLIkph2JQLKvSepjg=="], "@earendil-works/pi-ai": ["@earendil-works/pi-ai@0.82.1", "", { "dependencies": { "@anthropic-ai/sdk": "0.91.1", "@aws-sdk/client-bedrock-runtime": "3.1048.0", "@google/genai": "1.52.0", "@mistralai/mistralai": "2.2.6", "@opentelemetry/api": "1.9.0", "@smithy/node-http-handler": "4.7.3", "http-proxy-agent": "7.0.2", "https-proxy-agent": "7.0.6", "openai": "6.26.0", "partial-json": "0.1.7", "typebox": "1.1.38" }, "bin": { "pi-ai": "dist/cli.js" } }, "sha512-3WFYRhEp3lQB3444EhPMBcM7zSaEUE3eJgHOR7s4081NLqbw/FsWilIKWXSua0Gv3sRr7m9xMidR3pPDE7jI/A=="], @@ -351,8 +382,18 @@ "@flect/product": ["@flect/product@workspace:packages/product"], + "@floating-ui/core": ["@floating-ui/core@1.8.0", "", { "dependencies": { "@floating-ui/utils": "^0.2.12" } }, "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.8.0", "", { "dependencies": { "@floating-ui/core": "^1.8.0", "@floating-ui/utils": "^0.2.12" } }, "sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg=="], + + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.9", "", { "dependencies": { "@floating-ui/dom": "^1.8.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-JDjEFGCpImxDCA7JJKviA0M9+RtmJdj0m/NVU5IMgBK+AmZouAQQ7/+2GLH0GXXY0YMw9oXPB8hKdbPYg5QLYg=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.12", "", {}, "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="], + "@google/genai": ["@google/genai@1.52.0", "", { "dependencies": { "google-auth-library": "^10.3.0", "p-retry": "^4.6.2", "protobufjs": "^7.5.4", "ws": "^8.18.0" }, "peerDependencies": { "@modelcontextprotocol/sdk": "^1.25.2" }, "optionalPeers": ["@modelcontextprotocol/sdk"] }, "sha512-gwSvbpiN/17O9TbsqSsE/OzZcpv5Fo4RQjdngGgogtuB9RsyJ8ZHhX5KjHj1bp5N9snN2eK8LDGXSaWW2hof8Q=="], + "@hono/node-server": ["@hono/node-server@2.1.0", "", { "peerDependencies": { "hono": "^4" } }, "sha512-XovyyCCnBzW+zKu+z/zq8hwNs4KOR5rEMAOxo2f40Q5xoOI37IMm6MIg2COOUtUApo0i6850MTBKH2u4QLGIqg=="], + "@img/colour": ["@img/colour@1.1.0", "", {}, "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.35.3", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.3.2" }, "os": "darwin", "cpu": "arm64" }, "sha512-RMnFX7YQsMoh7lWfcM4NEHHymBX/rLuKNPVM84XE9ONPcaSCDgE7CHIHpSgPcO2xcRthgBy1HfNO319mwhIAkg=="], @@ -459,6 +500,8 @@ "@modelcontextprotocol/core": ["@modelcontextprotocol/core@2.0.0", "", { "dependencies": { "zod": "^4.2.0" } }, "sha512-pJCEwGG7Lfr/+PQp9ZTwKXNeO5wzbfKL7H3MYpCorM4oFBoQrdjnBgEoqG+RjhsvS1FKrDbKux+M1HhlnGWqcA=="], + "@modelcontextprotocol/sdk": ["@modelcontextprotocol/sdk@1.30.0", "", { "dependencies": { "@hono/node-server": "^1.19.9 || ^2.0.5", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", "content-type": "^1.0.5", "cors": "^2.8.5", "cross-spawn": "^7.0.5", "eventsource": "^3.0.2", "eventsource-parser": "^3.0.0", "express": "^5.2.1", "express-rate-limit": "^8.2.1", "hono": "^4.11.4", "jose": "^6.1.3", "json-schema-typed": "^8.0.2", "pkce-challenge": "^5.0.0", "raw-body": "^3.0.0", "zod": "^3.25 || ^4.0", "zod-to-json-schema": "^3.25.1" }, "peerDependencies": { "@cfworker/json-schema": "^4.1.1" }, "optionalPeers": ["@cfworker/json-schema"] }, "sha512-xKd8OIzlqNzcqcNumGAa6g+PW2kjD5vrpcKOnfldAUPP3j7lnqMPwlTXQm8gF+UwH72z0lqaRbjr9hqGz0eITA=="], + "@modelcontextprotocol/server": ["@modelcontextprotocol/server@2.0.0", "", { "dependencies": { "@modelcontextprotocol/core": "2.0.0", "zod": "^4.2.0" } }, "sha512-YhHWdHfpFMQfd0prsEnxKeS3Qz3ytIGmsS0sth4KDjnacIT7hxk6hXHkJ9KysxlkvTM+WZAtQbbcUhdoP4Hvtw=="], "@mongodb-js/zstd": ["@mongodb-js/zstd@7.0.0", "", { "dependencies": { "node-addon-api": "^8.5.0", "prebuild-install": "^7.1.3" } }, "sha512-mQ2s0pYYiav+tzCDR05Zptem8Ey2v8s11lri5RKGhTtL4COVCvVCk5vtyRYNT+9L8qSfyOqqefF9UtnW8mC5jA=="], @@ -479,6 +522,12 @@ "@nodable/entities": ["@nodable/entities@3.0.0", "", {}, "sha512-8L9xFeTYKhm49xfIypoe2W5wV1m/3Z58kT+7kR9A8OyFxcPduI4VmxaUMQyKYrRjUoLLSXv6EKKID5Tvj9cUVw=="], + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.43.0", "", {}, "sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg=="], @@ -521,6 +570,126 @@ "@protobufjs/utf8": ["@protobufjs/utf8@1.1.2", "", {}, "sha512-b1UQwcEZ4yCnMCD8DAL1VlbvBJE9/IX4FTIp7BG1xYpf29SLazLSrqUkj4w7Y5y7cCVP6E5tcqqcI0xemPkHug=="], + "@radix-ui/number": ["@radix-ui/number@1.1.3", "", {}, "sha512-Road2bidD0uu/1BGDOWNdPI06g0lIRy6IF9GZcIrDK2KGItfor8IQwQa+yM2ERgHM1MmHxaxpTzk0/Jp42lNfA=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.7", "", {}, "sha512-rqWnm76nYT8HoNNqEjpgJ7Pw/DrBj5iBTrmEPo6HTX5+VJyBNOqTdv4g89G63HuR5g0AaENoAcH7Is5fF2kZ8Q=="], + + "@radix-ui/react-accessible-icon": ["@radix-ui/react-accessible-icon@1.1.15", "", { "dependencies": { "@radix-ui/react-visually-hidden": "1.2.11" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WTQwcAvQf5sOcuUyi90lKPbhwcvQ+j55cjrSmeaN+L2vKU3DooOvlKw2MDeiJ5IkV5N905KW0/fGojKOBhD11A=="], + + "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.20", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collapsible": "1.1.20", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-jDhG9FvAEnlhnjrsINbNXcUa4G+L1KqSkJSunkbKEzFRcAb52jvM0PjPxPRvhe1HNc5F5yc0yzzWeeqlH4yBIg=="], + + "@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dialog": "1.1.23", "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VAYOiQRqj3GPpYJE0I9J+X8Ip05cyVlNdKOFeiGS2Ou1HHGfpl0BxOyZm6nmVDyU+W+NF3/XLzmjHmVGydhwgA=="], + + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-v4zggRcjadnI+ClKDuijlQEW4tw3NoaeHc/PwpKnLoLLKNUG4InLegkstooLcRIUWCs+8L22dGURCVuFfOKfnA=="], + + "@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-fy+dyVR+90nelK8rqIznFlxzx7uPcGbhxH8Nfr2bHb4UfSe+e3hklOC0luK0hDwVwnRX7xTRySpsrQVeW+/oNQ=="], + + "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4ULOTJ/mqy2hT9GlWa/MFHxHSvH3nJzHnZM1waNsc5Bonv7i70aNenghXmD97S6OJ81ekXONGGt4nT1r0PfEdA=="], + + "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Gnptr9pDDQxD3hgq2dtPbtrp/c2qH1mBwIzw3X/ivrMb2e1t0jMTi606fVEqFPaQR1ggXIVQWKj3P2WW9v7zGQ=="], + + "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.20", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mcGesGplBnzN2sbvJETzpCNfSMyPnb29q1GRLU+Ib7bJrpIG2ywmRoh2V5VbA2uNvKikKUlVbAPks7JDjz4A8Q=="], + + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.15", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-9W+B9NPF0NaaPh/1NJd3+KqsnlLqU9H7T2rvww+fp+T/evVXdNAyYcnfRQZFOjkR1ajQp3yORlqnI8soawLvNA=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.5", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+48PbAAbq3didjJxa+OaWY2ZwgAKsNiRGyeHKszblZMQ+kcpd9pAaT11cMkGEie0vsOi3QdeTE6d5Fe3Gn61kA=="], + + "@radix-ui/react-context": ["@radix-ui/react-context@1.2.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RHCUGwKHDr0hDGg4X7ma4JG4/+12qxw8rkh5QKdDldlCvtja6nUx1Ef/8HVrJze81lEsgLQlqjzjGNHantgnQA=="], + + "@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.3.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-CtXP35dxaB5T3zXSd+E3uHe/QpXcpYnZmxp6OaIbfthtfW4wyb77M23BG+bwIJDtsMwEP/YssdsmNyZu7jhWew=="], + + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ksw4WeROkO4rC9k/onilX/Ao2Cr1ku1unMNH+XSCcP4jSXYu7HDsg9n4ojMjVb22XpYjAQ9qfrFlVbru1vXDUA=="], + + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-5pzg4FGQNpExhnhT2zlrP1wZFaYCd1K0nYWoFAdcYoYK868IEigqMX3B3f8yIoRlAhAeDWciLI6ZdCKHF9P4Vg=="], + + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-effect-event": "0.0.5" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-8g4pfOL9HoKKLWGiypT+dphVqjFfmcXO5GBnhsG6zI+lxAx/8feQpr+1LSN8Re3hiZ+XkLNS4O9ztK11/LzQ6w=="], + + "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-geq8l2rJkxvkXsT9RMgtUE3P8pITFpTsvYpbySi1IH4fZEABD/Gp85myayFgxk0ktljGMJnCbeFkyTusvSvv7g=="], + + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.6", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RNOJjfZMTyBM6xYmV3IVGXkPjIhcBAuv48POevAXwrGJhkWZ9p1rFoIS1JFooPuT193AZmRsCPhpoVJxx6OPoQ=="], + + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.16", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wmRZ2WWLvmt6KHy2rNPOdPUjwq5xOHY02+m+udwJTn0aNIox/rkskAvJTyTLGhPK6KgrUjlJUJpgmx/+wFiFIQ=="], + + "@radix-ui/react-form": ["@radix-ui/react-form@0.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-label": "2.1.15", "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Q4TLEn2A7TAypxwmd6R9EwrlXDvkfYSDMrq9/887AXAGh+G1rH+kYJKSTv+Si9Y0JPKTwKYv6PviAJosysNimA=="], + + "@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-H8qONfZd3ltrU3+jHCIgITbWo6e1iTKvP9DHdrvYbX48ooRM5FjEDTn16AMwdfuOGkWdZEhpl3PLL/Wk/AnHDQ=="], + + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-TMQp2llA+RYn7JcjnrMnz7wN4pcVttPZnRZo52PLQsoLVKzNlVwUeHmfePgTgRluXFvlD3GD5g5MOVVTJCO0qA=="], + + "@radix-ui/react-label": ["@radix-ui/react-label@2.1.15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-o/rdYEwZTTo5tjknnPeyQFU45kUC4i/XyeDPP+HGyi6XqpOP6Zf5Ya5vh/Yfe9Id5JiuWnnAx2XqIeD3UYZt0g=="], + + "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-uW7RVuU6Lp/ZtfeY4b3kL32zccgEWvPv1+cf17ubYzHa9cL8AHokmk36cG/XEiH/smbQvumnieXX9j/e9RqJWA=="], + + "@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.24", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-eeVs0vf7cuqXaM0qLQCPcufImiJNVBXdJDLu7ZGYl2732UH23Qat/foNGrr6vYV3/DdTsBqASoggUFgH14OcZA=="], + + "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.22", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ou7iLEJ+yrhQndkkA4U21XIdS/CS45F4iXIkTZcb6/Ne9EMsOuDudVmCwmDnfFZZ+y1FZqXRNSIgBy+YMvZVZg=="], + + "@radix-ui/react-one-time-password-field": ["@radix-ui/react-one-time-password-field@0.1.16", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Tj9P6ntAJEw52oq/F0AGknXR4XncxEt7XU47O3xJQOiWfLzEy3d9gtgKfvjSzGxzHkfL+VzvxGu2KTFsloJqXw=="], + + "@radix-ui/react-password-toggle-field": ["@radix-ui/react-password-toggle-field@0.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-is-hydrated": "0.1.3" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4gvFnmDXu3dgj21CqsufzIameRvlRd4SBqaWhcrlrNhRo0Y5i/49AmRJYe1fdAM3G2VNBbmin4b0D6cdQocwgw=="], + + "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mw58MrBlyHWFisTOYignD0vf/3gdcgAR+9of1s9G/38CbFiUwH1nCDkc0AUM9IrXFgN5Ue8n45j9WCgyM1sbiQ=="], + + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.3.7", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-rect": "1.1.4", "@radix-ui/react-use-size": "1.1.4", "@radix-ui/rect": "1.1.3" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UsJrrd7w4wuKKTdvd/DNERVlwSlUcyXzjhyDwBk+3aPOsCjOY6ZSbxuw8E6lZTjjfP8Cpd0J8VVkrYUWyGYXyg=="], + + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.17", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vKQLcWypUnwZVvfV7UkGahH2g6ySe8M8R+zYBwPrv5byZ9QAW6cQVvNKo7GgmD+p8aYb6D9JBuvy8/WhOno2wQ=="], + + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.10", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3wyzCQ6+ubRA+D4uv9m95JYLXxmOHp05qjrkjeA7uKHHtjpPggQzc6DAb0URl7j67oR0K2foO4ip27TiX037Bw=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.10", "", { "dependencies": { "@radix-ui/react-slot": "1.3.3" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-MucOnzh6hR5mid6VpkbglRAMYMjKLqRnGBbjXkzjK52fuQDd1qbkx78a5P40mkcnVXJdEVxm26E9OPAiUq7nBg=="], + + "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.16", "", { "dependencies": { "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5XnomAsoZZCY+KNTxbIghpGqPruZvKFNlvcAljVAOdDRDsH4/OZQxhtwo5wdtoDM5R6MhJBb2sPnDuRFep3lzg=="], + + "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.4.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-cgYFEkntCxppHZgtSZ+7vh0wbZQ+IC7PPMw8DSnRG27B6kDd32/Zw0OJt7dGDigCoprMuWHjg2PvUn3PYvPFoQ=="], + + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V9jI6hDjT7l3jsCQD9bLNvDLM3tH/gdbOTp7Tefp3hbbgCGQoK7tUvrWiRlcoBHIZ809ElXwNQwVo0B98LuTXQ=="], + + "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.18", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-layout-effect": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Zn5Cd171wxsO3Dfg8HaW6RifTb9CYTKQJHs/G4+LN1GfmJpaQMZQyQxMprVPHpaz7QY4l9BxK2JwQuzHsXC8nA=="], + + "@radix-ui/react-select": ["@radix-ui/react-select@2.3.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.7.2" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-WFGImkmbzcfxeIwq/+4HvRN0pizBwbwQUED4I13ezQsDdfl38ZntN6TmR8XaSzPBqoCToe8rF75j6NPNDSzhbg=="], + + "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.15", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-jOLO4lssEzWpoDu7G+Ze4VjwMRUBt291pnZD0gmalREZipnTX3wadQo7Fy48GCTfe14/YRN6rw/rOJqrE85Wxw=="], + + "@radix-ui/react-slider": ["@radix-ui/react-slider@1.4.7", "", { "dependencies": { "@radix-ui/number": "1.1.3", "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-previous": "1.1.4", "@radix-ui/react-use-size": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mTSLf1GC/C0moWjTbvCM6Qn/gBjvlFt1azuWF2v7MN5C3Zq2U2J2lN3ZEYkpujuOU5Ro7A28wkviSxaKnG0BYg=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.3.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.5" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-qx7oqnYbxnK9kYI9m317qmFmEgo6ywqWvbTogdj7cL9p3/yx4M48p7Rnw5z3H890cL/ow/EeWJsuTykeZVXP5Q=="], + + "@radix-ui/react-switch": ["@radix-ui/react-switch@1.3.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-size": "1.1.4" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-48tB/4dn2UVLBCYhTu9AuR63IHl73l/qLbLgxd86noTUor4/K4LFDAcYjK+isP5313qxaFpjPVogE7+Y0/V3Kw=="], + + "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.21", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-UKxJlZid7FVtsk/WTxj4i4uSEgj2Au+KBbS7SQyTlzMhhn+86Cz3tISZdTa87bfEfcuvZezf2ZsxD4xuEKtkog=="], + + "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.23", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ofhyAsYaocRGOs/n0XWdUOSVzEAG6BfrMVM8z0c0kLEWY38w/0WuMFPTJP/HVaZPYkMvHZoKIIhNcjbTCBILPg=="], + + "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.18", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7lonPlKfSacd20GlOBx2ltuVKz9oqWYZz+oMQyOltw6t1y2nyftj2ZmwwUHYn49kqfDWcp8dNZm5NgV+5Z+mug=="], + + "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-toggle": "1.1.18", "@radix-ui/react-use-controllable-state": "1.2.6" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-OtnwuSVjd1Ofi+AdnvhsjQdyuhCDwYs1w9RyB5BN/OavXOVQo42SYqQjwUnbPnaiPFBpQ9aX70dWeee+v2oBLA=="], + + "@radix-ui/react-toolbar": ["@radix-ui/react-toolbar@1.1.19", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-separator": "1.1.15", "@radix-ui/react-toggle-group": "1.1.19" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Ph0IvtYw4VB12ZnZg+YtrGs8yJQsnizwo/zu0R4Y/nWugtJzA7Pg1eWeuDR9+LSqn+xjamss+UOSOJJJ4gx8jw=="], + + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-id": "1.1.4", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-6EamKFRRnlpdadndbZ6LMwycfwkwPte1B42hs6QA0gYhjaOKqW4PZ4pjaW9UrlDX5eVt/OjncE7BFTPL5nmZhg=="], + + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-R6OUY2e2fA6Yn6s+VSx5KBV6Nx8LQEhu+cz7LCej18rQ1HLyg9PSC9jP/ZNx0o6FAIK9c0F1kHylzSxKsdlkrQ=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-uEQJGT97ZA/TgP/Hydw47lHu+/vQj6z/0jA+WeTbK1o9Rx45GImjpD0tc3W5ad3D6XTSR6e1yEO0FvGq6WQfVQ=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.5", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-7cshFL8HGS/7HEiHH+9kL9HBwp2sa9yX18Knwek6KYWmXwM7pegMgta2AXMQKI+rq3JnfSj9x8wYqFMTdG1Jgg=="], + + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.5", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ge3ipobwSXTj4JyVtswQ7qZj0ZHdtbGuOno/LrgAAeSxtsJ6Vs4Gz5IkPH2bmqpjcLUFoqGhA/mueuIf63UXlA=="], + + "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-umO/aJ+82CpOnhDZUTbILCQf7kU/g0iv+oGs/Q8jw7IkhWBzaEP4sA268PhFAJTFetbwp3ICc6ktpI4TqtxcIw=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-K20DkRkUwDnxEYMBPcg3Y6voLkEy5p5QQmszZgLngKKiC7dzBR/aEuK3w1qlx2JWDUNH6FluahYdgR3BP+QbYw=="], + + "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.4", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XoSLhbRbqxFtgJoi2fNHA3C6pDlY34x508vUpUGoFZfvePfHXHbE1lC4FYFMnJWgiCRroSTw6fOsXQoVS9RwZg=="], + + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.4", "", { "dependencies": { "@radix-ui/rect": "1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-cSOCh6JlkmfjLyNcLiu2nB4v+nm+dkZ+Q5KHWk/soo4U7ZLiEQFKHK9/YmtBHjfCEaU43IBKQOc4/uJmCaiCTQ=="], + + "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.4", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.4" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-D3anSY15EJoxrihpsXI6SMrmmonnQtR2ni7arO+Lfdg3O95b9hNXxONk8jA5C8ANdF/h5HMAxejgs8PWJ6rlhw=="], + + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.11", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.10" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-NFS86RYYZb4/exihaESBGOpMJFz8MGLAfu3mOBSGByVnVPC9JPASfYubxd/8KbkQK0sYAv8lVQDEQukDX/qXvQ=="], + + "@radix-ui/rect": ["@radix-ui/rect@1.1.3", "", {}, "sha512-JtyZR+mqgBibTo8xea3B6ZRmzZiM/YeVBtUkas6zMuXjAlfIFIW2FgqeM9eLyvEaYX66vr6DJMK+4U6LV0KhNw=="], + "@riftydev/io": ["@riftydev/io@0.2.0", "", {}, "sha512-zPIDVk0PWVe8medszLjCbGUSg1v92y3eu7SsAdtwU6Pi6gvc7/YSzza/eCDWFfHIVvOxoelzKPV6/l7X5451TA=="], "@riftydev/kernel": ["@riftydev/kernel@0.2.0", "", { "dependencies": { "@riftydev/io": "0.2.0" } }, "sha512-YiQnYbnhGdj7J5UKxSgrllTIoaw6ScL/3SXzjywdzR4iwiZkpDjHxNTdI7NnGtlLP9dvcxPtqnlv22u0Wldjew=="], @@ -571,6 +740,8 @@ "@rollup/pluginutils": ["@rollup/pluginutils@5.4.0", "", { "dependencies": { "@types/estree": "^1.0.0", "estree-walker": "^2.0.2", "picomatch": "^4.0.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" }, "optionalPeers": ["rollup"] }, "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg=="], + "@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="], + "@shikijs/core": ["@shikijs/core@4.3.1", "", { "dependencies": { "@shikijs/primitive": "4.3.1", "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.5" } }, "sha512-ANMDxuaPsNMdDC1m4vfvhlDmJweMwkE5XitTwrq2rWHx5jM+dlm4MmHt2PP6t0uejfR77SuhrhJ0zEijIF/uhA=="], "@shikijs/engine-javascript": ["@shikijs/engine-javascript@4.3.1", "", { "dependencies": { "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "oniguruma-to-es": "^4.3.6" } }, "sha512-JBItcnPuYq7jVJdZo/vMj94r+szT7XEjHFX+mvFDGSEIbVAXAGyHAHzhbWzpGOwYidCZrErJLLgn2PVeiokHnQ=="], @@ -589,6 +760,8 @@ "@silvia-odwyer/photon-node": ["@silvia-odwyer/photon-node@0.3.4", "", {}, "sha512-bnly4BKB3KDTFxrUIcgCLbaeVVS8lrAkri1pEzskpmxu9MdfGQTy8b8EgcD83ywD3RPMsIulY8xJH5Awa+t9fA=="], + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], + "@smithy/core": ["@smithy/core@3.31.0", "", { "dependencies": { "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-sylYk2l9d7CmRv8ts8p0SDQUr3VO+HMeS1nrjL6+UtbO8ktJHTOeQ1McX+aAyvGGccp5aZX9eNtdcXrSwzoZaw=="], "@smithy/credential-provider-imds": ["@smithy/credential-provider-imds@4.4.15", "", { "dependencies": { "@smithy/core": "^3.31.0", "@smithy/types": "^4.16.1", "tslib": "^2.6.2" } }, "sha512-xYVGrisQqTJWhOnScUhbx8s9H63TMtoxzuUoxG6mP8J+B/YbX3vZxVsgV0xDf43abJnJP0fjP7BkQh7OESwuRA=="], @@ -611,6 +784,36 @@ "@sveltejs/acorn-typescript": ["@sveltejs/acorn-typescript@1.0.12", "", { "peerDependencies": { "acorn": "^8.9.0" } }, "sha512-J1jNYG23QWd67UfrQSFHtjhV37r9mVi0gdc12A3MWPldOjRK35Xk+um+qACPVjgw3AleiqoyEAhok8Wm3q46NA=="], + "@tailwindcss/node": ["@tailwindcss/node@4.1.18", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.18" } }, "sha512-DoR7U1P7iYhw16qJ49fgXUlry1t4CpXeErJHnQ44JgTSKMaZUdf17cfn5mHchfJ4KRBZRFA/Coo+MUF5+gOaCQ=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.18", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.18", "@tailwindcss/oxide-darwin-arm64": "4.1.18", "@tailwindcss/oxide-darwin-x64": "4.1.18", "@tailwindcss/oxide-freebsd-x64": "4.1.18", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.18", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.18", "@tailwindcss/oxide-linux-arm64-musl": "4.1.18", "@tailwindcss/oxide-linux-x64-gnu": "4.1.18", "@tailwindcss/oxide-linux-x64-musl": "4.1.18", "@tailwindcss/oxide-wasm32-wasi": "4.1.18", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.18", "@tailwindcss/oxide-win32-x64-msvc": "4.1.18" } }, "sha512-EgCR5tTS5bUSKQgzeMClT6iCY3ToqE1y+ZB0AKldj809QXk1Y+3jB0upOYZrn9aGIzPtUsP7sX4QQ4XtjBB95A=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.18", "", { "os": "android", "cpu": "arm64" }, "sha512-dJHz7+Ugr9U/diKJA0W6N/6/cjI+ZTAoxPf9Iz9BFRF2GzEX8IvXxFIi/dZBloVJX/MZGvRuFA9rqwdiIEZQ0Q=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.18", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Gc2q4Qhs660bhjyBSKgq6BYvwDz4G+BuyJ5H1xfhmDR3D8HnHCmT/BSkvSL0vQLy/nkMLY20PQ2OoYMO15Jd0A=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.18", "", { "os": "darwin", "cpu": "x64" }, "sha512-FL5oxr2xQsFrc3X9o1fjHKBYBMD1QZNyc1Xzw/h5Qu4XnEBi3dZn96HcHm41c/euGV+GRiXFfh2hUCyKi/e+yw=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.18", "", { "os": "freebsd", "cpu": "x64" }, "sha512-Fj+RHgu5bDodmV1dM9yAxlfJwkkWvLiRjbhuO2LEtwtlYlBgiAT4x/j5wQr1tC3SANAgD+0YcmWVrj8R9trVMA=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.18", "", { "os": "linux", "cpu": "arm" }, "sha512-Fp+Wzk/Ws4dZn+LV2Nqx3IilnhH51YZoRaYHQsVq3RQvEl+71VGKFpkfHrLM/Li+kt5c0DJe/bHXK1eHgDmdiA=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-S0n3jboLysNbh55Vrt7pk9wgpyTTPD0fdQeh7wQfMqLPM/Hrxi+dVsLsPrycQjGKEQk85Kgbx+6+QnYNiHalnw=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.18", "", { "os": "linux", "cpu": "arm64" }, "sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.18", "", { "os": "linux", "cpu": "x64" }, "sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.18", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.0", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.18", "", { "os": "win32", "cpu": "arm64" }, "sha512-HjSA7mr9HmC8fu6bdsZvZ+dhjyGCLdotjVOgLA2vEqxEBZaQo9YTX4kwgEvPCpRh8o4uWc4J/wEoFzhEmjvPbA=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.18", "", { "os": "win32", "cpu": "x64" }, "sha512-bJWbyYpUlqamC8dpR7pfjA0I7vdF6t5VpUGMWRkXVE3AXgIZjYUYAK7II1GNaxR8J1SSrSrppRar8G++JekE3Q=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="], + "@tauri-apps/api": ["@tauri-apps/api@2.11.1", "", {}, "sha512-M2FPuYND2m+wh5hfW9ZpSdxMPdEJovPBWwoHJmwUpysTYNHaOkVFN419m/K0LIgjb/7KU2vBgsUepJWugQCvAA=="], "@tauri-apps/cli": ["@tauri-apps/cli@2.11.4", "", { "optionalDependencies": { "@tauri-apps/cli-darwin-arm64": "2.11.4", "@tauri-apps/cli-darwin-x64": "2.11.4", "@tauri-apps/cli-linux-arm-gnueabihf": "2.11.4", "@tauri-apps/cli-linux-arm64-gnu": "2.11.4", "@tauri-apps/cli-linux-arm64-musl": "2.11.4", "@tauri-apps/cli-linux-riscv64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-gnu": "2.11.4", "@tauri-apps/cli-linux-x64-musl": "2.11.4", "@tauri-apps/cli-win32-arm64-msvc": "2.11.4", "@tauri-apps/cli-win32-ia32-msvc": "2.11.4", "@tauri-apps/cli-win32-x64-msvc": "2.11.4" }, "bin": { "tauri": "tauri.js" } }, "sha512-R8xGtMpwyetawSqm9kYOuMmEqkhUbvcUy8n0aNXIxollKBLESUu5f4Fx+64hgASYm1H+jSWq6jCW6zqTnH6hqQ=="], @@ -651,6 +854,8 @@ "@toon-format/toon": ["@toon-format/toon@4.1.0", "", {}, "sha512-dBB3pkEx9QYvHnHR6rtkaBAh+7x4W/oA5ONur4G0fh7Ow69PbPuM7OFxzNRABqyxC0t6SZ3RixiGbCuaFjPDAQ=="], + "@ts-morph/common": ["@ts-morph/common@0.27.0", "", { "dependencies": { "fast-glob": "^3.3.3", "minimatch": "^10.0.1", "path-browserify": "^1.0.1" } }, "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ=="], + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], "@types/aria-query": ["@types/aria-query@5.0.4", "", {}, "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw=="], @@ -689,6 +894,8 @@ "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + "@types/validate-npm-package-name": ["@types/validate-npm-package-name@4.0.2", "", {}, "sha512-lrpDziQipxCEeK5kWxvljWYhUvOiB2A9izZd9B2AFarYAkqZshb4lPbRs7zKEic6eGtH8V/2qJW+dPp9OtF6bw=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], "@typescript/typescript-aix-ppc64": ["@typescript/typescript-aix-ppc64@7.0.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ=="], @@ -759,12 +966,20 @@ "@vue/shared": ["@vue/shared@3.5.41", "", {}, "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA=="], + "accepts": ["accepts@2.0.0", "", { "dependencies": { "mime-types": "^3.0.0", "negotiator": "^1.0.0" } }, "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng=="], + "acorn": ["acorn@8.18.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ=="], "agent-base": ["agent-base@7.1.4", "", {}, "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ=="], + "ajv": ["ajv@8.20.0", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA=="], + + "ajv-formats": ["ajv-formats@3.0.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ=="], + "am-i-vibing": ["am-i-vibing@0.4.0", "", { "dependencies": { "process-ancestry": "^0.1.0" }, "bin": { "am-i-vibing": "dist/cli.mjs" } }, "sha512-MxT4XZL7pzLHpuvhDKdMaQHMGGkJDLluKBLsbstn+8wv9sWcFT6h+0ve9qkml95amVTZtZV83gQe2hY+ojgHLg=="], + "ansi-colors": ["ansi-colors@4.1.3", "", {}, "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw=="], + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-styles": ["ansi-styles@5.2.0", "", {}, "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA=="], @@ -775,12 +990,18 @@ "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], "assertion-error": ["assertion-error@2.0.1", "", {}, "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA=="], + "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], + "astro": ["astro@7.2.0", "", { "dependencies": { "@astrojs/compiler-rs": "^0.3.2", "@astrojs/internal-helpers": "0.10.2", "@astrojs/markdown-satteri": "0.3.5", "@astrojs/telemetry": "3.3.3", "@capsizecss/unpack": "^4.0.0", "@clack/prompts": "^1.1.0", "@oslojs/encoding": "^1.1.0", "am-i-vibing": "^0.4.0", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "ci-info": "^4.4.0", "clsx": "^2.1.1", "common-ancestor-path": "^2.0.0", "cookie": "^2.0.1", "devalue": "^5.8.1", "diff": "^8.0.3", "dset": "^3.1.4", "es-module-lexer": "^2.0.0", "esbuild": "^0.28.0", "flattie": "^1.1.1", "fontace": "~0.4.1", "get-tsconfig": "5.0.0-beta.4", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.2.0", "js-yaml": "^4.3.0", "jsonc-parser": "^3.3.1", "magic-string": "^1.0.0", "magicast": "^0.5.2", "mrmime": "^2.0.1", "neotraverse": "^1.0.1", "obug": "^2.1.1", "p-limit": "^7.3.0", "p-queue": "^9.1.0", "package-manager-detector": "^1.6.0", "piccolore": "^0.1.3", "picomatch": "^4.0.4", "semver": "^7.7.4", "shiki": "^4.0.2", "smol-toml": "^1.6.0", "svgo": "^4.0.1", "tinyclip": "^0.1.12", "tinyexec": "^1.0.4", "tinyglobby": "^0.2.15", "ultrahtml": "^1.6.0", "unifont": "~0.7.4", "unstorage": "^1.17.5", "vite": "^8.0.13", "vitefu": "^1.1.2", "xxhash-wasm": "^1.1.0", "yargs-parser": "^22.0.0", "zod": "^4.3.6" }, "optionalDependencies": { "sharp": "^0.34.0 || ^0.35.0" }, "peerDependencies": { "@astrojs/markdown-remark": "7.2.2" }, "optionalPeers": ["@astrojs/markdown-remark"], "bin": { "astro": "./bin/astro.mjs" } }, "sha512-lLTYzx3fOvCmtwD3JVBLQcbORbIOW1/j0R+3IvJx/XKwMGrk7mFnF0BYSOeRiNw1qHUR5mdA6+hRnyvyDfqrWQ=="], + "atomically": ["atomically@1.7.0", "", {}, "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w=="], + "axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="], "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], @@ -801,12 +1022,16 @@ "bl": ["bl@4.1.0", "", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + "body-parser": ["body-parser@2.3.0", "", { "dependencies": { "bytes": "^3.1.2", "content-type": "^2.0.0", "debug": "^4.4.3", "http-errors": "^2.0.1", "iconv-lite": "^0.7.2", "on-finished": "^2.4.1", "qs": "^6.15.2", "raw-body": "^3.0.2", "type-is": "^2.1.0" } }, "sha512-2cGmJupaNgg+QUwVLAucDuWuoMZ6EX9iHDRswZ5lsNYEmwPaRknMPCLZz07yTzVq/83p4o/wzbDZbBrTvGGTIw=="], + "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], "bowser": ["bowser@2.14.1", "", {}, "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg=="], "brace-expansion": ["brace-expansion@5.0.8", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg=="], + "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + "browserslist": ["browserslist@4.28.7", "", { "dependencies": { "baseline-browser-mapping": "^2.10.44", "caniuse-lite": "^1.0.30001806", "electron-to-chromium": "^1.5.393", "node-releases": "^2.0.51", "update-browserslist-db": "^1.2.3" }, "bin": { "browserslist": "cli.js" } }, "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw=="], "buffer": ["buffer@5.7.1", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], @@ -815,6 +1040,16 @@ "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "bundle-name": ["bundle-name@4.1.0", "", { "dependencies": { "run-applescript": "^7.0.0" } }, "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q=="], + + "bytes": ["bytes@3.1.2", "", {}, "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + "caniuse-lite": ["caniuse-lite@1.0.30001809", "", {}, "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ=="], "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], @@ -837,24 +1072,44 @@ "ci-info": ["ci-info@4.4.0", "", {}, "sha512-77PSwercCZU2Fc4sX94eF8k8Pxte6JAwL4/ICZLFjJLqegs7kCuAsqqj/70NQF6TvDpgFjkubQB2FW2ZZddvQg=="], + "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + + "cli-cursor": ["cli-cursor@5.0.0", "", { "dependencies": { "restore-cursor": "^5.0.0" } }, "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw=="], + + "cli-spinners": ["cli-spinners@2.9.2", "", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + "code-block-writer": ["code-block-writer@13.0.3", "", {}, "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg=="], + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], - "commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + "commander": ["commander@14.0.3", "", {}, "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw=="], "common-ancestor-path": ["common-ancestor-path@2.0.0", "", {}, "sha512-dnN3ibLeoRf2HNC+OlCiNc5d2zxbLJXOtiZUudNFSXZrNSydxcCsSpRzXwfu7BBWCIfHPw+xTayeBvJCP/D8Ng=="], "concurrently": ["concurrently@10.0.4", "", { "dependencies": { "chalk": "5.6.2", "rxjs": "7.8.2", "shell-quote": "1.9.0", "supports-color": "10.2.2", "tree-kill": "1.2.2", "yargs": "18.0.0" }, "bin": { "conc": "dist/bin/index.js", "concurrently": "dist/bin/index.js" } }, "sha512-trZql+7l/0+WRAsAnEdctr4+iiOS6ZrViI6H8QWcCF9MFS/LT0dKpe8vluB1to6it+OxSI4VospFTIFMW8DJRw=="], + "conf": ["conf@10.2.0", "", { "dependencies": { "ajv": "^8.6.3", "ajv-formats": "^2.1.1", "atomically": "^1.7.0", "debounce-fn": "^4.0.0", "dot-prop": "^6.0.1", "env-paths": "^2.2.1", "json-schema-typed": "^7.0.3", "onetime": "^5.1.2", "pkg-up": "^3.1.0", "semver": "^7.3.5" } }, "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg=="], + + "content-disposition": ["content-disposition@1.1.0", "", {}, "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g=="], + + "content-type": ["content-type@1.0.5", "", {}, "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="], + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "cookie": ["cookie@2.0.1", "", {}, "sha512-yuToqVvRrj6pfDXREyQAAv8SkAEk/8GS3jQRTiUMm66TVtBYmqQeoEjL2Lmq8Rpo6271vH76InTChTitEAm65w=="], "cookie-es": ["cookie-es@1.2.3", "", {}, "sha512-lXVyvUvrNXblMqzIRrxHb57UUVmqsSWlxqt3XIjCkUP0wDAf6uicO6KMbEgYrMNtEvWgWHwe42CKxPu9MYAnWw=="], + "cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="], + + "cors": ["cors@2.8.6", "", { "dependencies": { "object-assign": "^4", "vary": "^1" } }, "sha512-tJtZBBHA6vjIAaF6EnIaq6laBBP9aq/Y3ouVJjEfoHbRBcHBAHYcMh/w8LDrk2PvIMMq8gmopa5D4V8RmbrxGw=="], + + "cosmiconfig": ["cosmiconfig@9.0.2", "", { "dependencies": { "env-paths": "^2.2.1", "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", "parse-json": "^5.2.0" }, "peerDependencies": { "typescript": ">=4.9.5" }, "optionalPeers": ["typescript"] }, "sha512-gtTZxTDau1wL7Y7zifc2dd8jHSK/k6BTx/2Xp/BpdlAdnlYWFVt7qhJqgwi7637yRwRQ3qL4ZidbB4I8tA5VOg=="], + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], "crossws": ["crossws@0.3.5", "", { "dependencies": { "uncrypto": "^0.1.3" } }, "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA=="], @@ -867,6 +1122,8 @@ "css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="], + "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], + "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], @@ -875,6 +1132,8 @@ "data-urls": ["data-urls@7.0.0", "", { "dependencies": { "whatwg-mimetype": "^5.0.0", "whatwg-url": "^16.0.0" } }, "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA=="], + "debounce-fn": ["debounce-fn@4.0.0", "", { "dependencies": { "mimic-fn": "^3.0.0" } }, "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ=="], + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="], @@ -883,16 +1142,30 @@ "decompress-response": ["decompress-response@6.0.0", "", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + "dedent": ["dedent@1.7.2", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA=="], + "deep-extend": ["deep-extend@0.6.0", "", {}, "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="], + "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], + + "default-browser": ["default-browser@5.5.0", "", { "dependencies": { "bundle-name": "^4.1.0", "default-browser-id": "^5.0.0" } }, "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw=="], + + "default-browser-id": ["default-browser-id@5.0.1", "", {}, "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q=="], + + "define-lazy-prop": ["define-lazy-prop@3.0.0", "", {}, "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg=="], + "defu": ["defu@6.1.7", "", {}, "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ=="], + "depd": ["depd@2.0.0", "", {}, "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="], + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], "destr": ["destr@2.0.5", "", {}, "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="], "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + "devalue": ["devalue@5.9.0", "", {}, "sha512-RWrqdArjvPbsATEhOPUo6Wndc/iWnkWKlhIrdlF3zMMYo/c3CVtoaVAyLtWxz5h8nSlkHzxnzV2uLydPXmtF+A=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], @@ -909,72 +1182,124 @@ "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], + "dot-prop": ["dot-prop@6.0.1", "", { "dependencies": { "is-obj": "^2.0.0" } }, "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA=="], + + "dotenv": ["dotenv@17.4.2", "", {}, "sha512-nI4U3TottKAcAD9LLud4Cb7b2QztQMUEfHbvhTH09bqXTxnSie8WnjPALV/WMCrJZ6UV/qHJ6L03OqO3LcdYZw=="], + "dset": ["dset@3.1.4", "", {}, "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA=="], + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + "ecdsa-sig-formatter": ["ecdsa-sig-formatter@1.0.11", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ=="], + "ee-first": ["ee-first@1.1.1", "", {}, "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="], + "effect": ["effect@4.0.0-beta.102", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.9.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.4", "multipasta": "^0.2.8", "toml": "^4.1.2", "uuid": "^14.0.1", "yaml": "^2.9.0" } }, "sha512-z8Y+Q76Hh/kjLFZrXu8tGn6e+tDsg45R+UHhxd190pXxD53OGwf/G/zDxXTkse4HJ5mobNZfitLfUCp4fMvu6w=="], "electron-to-chromium": ["electron-to-chromium@1.5.402", "", {}, "sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA=="], "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], + "encodeurl": ["encodeurl@2.0.0", "", {}, "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg=="], + "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + "enhanced-resolve": ["enhanced-resolve@5.24.5", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.3" } }, "sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A=="], + + "enquirer": ["enquirer@2.4.1", "", { "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" } }, "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ=="], + "entities": ["entities@8.0.0", "", {}, "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA=="], + "env-paths": ["env-paths@2.2.1", "", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "error-ex": ["error-ex@1.3.4", "", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + "es-module-lexer": ["es-module-lexer@2.3.1", "", {}, "sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA=="], + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + "esbuild": ["esbuild@0.28.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.28.1", "@esbuild/android-arm": "0.28.1", "@esbuild/android-arm64": "0.28.1", "@esbuild/android-x64": "0.28.1", "@esbuild/darwin-arm64": "0.28.1", "@esbuild/darwin-x64": "0.28.1", "@esbuild/freebsd-arm64": "0.28.1", "@esbuild/freebsd-x64": "0.28.1", "@esbuild/linux-arm": "0.28.1", "@esbuild/linux-arm64": "0.28.1", "@esbuild/linux-ia32": "0.28.1", "@esbuild/linux-loong64": "0.28.1", "@esbuild/linux-mips64el": "0.28.1", "@esbuild/linux-ppc64": "0.28.1", "@esbuild/linux-riscv64": "0.28.1", "@esbuild/linux-s390x": "0.28.1", "@esbuild/linux-x64": "0.28.1", "@esbuild/netbsd-arm64": "0.28.1", "@esbuild/netbsd-x64": "0.28.1", "@esbuild/openbsd-arm64": "0.28.1", "@esbuild/openbsd-x64": "0.28.1", "@esbuild/openharmony-arm64": "0.28.1", "@esbuild/sunos-x64": "0.28.1", "@esbuild/win32-arm64": "0.28.1", "@esbuild/win32-ia32": "0.28.1", "@esbuild/win32-x64": "0.28.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw=="], "esbuild-wasm": ["esbuild-wasm@0.28.1", "", { "bin": { "esbuild": "bin/esbuild" } }, "sha512-p/GD4E8oYRjg3kjdKrnMb0s4PzXgJF42e0MF4H0+ACyK/kIlFRp3e0fzOleIG+wBBm6MM3XQrbpe7soEA+vJIA=="], "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + "escape-html": ["escape-html@1.0.3", "", {}, "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="], + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], "esm-env": ["esm-env@1.2.2", "", {}, "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="], + "esprima": ["esprima@4.0.1", "", { "bin": { "esparse": "./bin/esparse.js", "esvalidate": "./bin/esvalidate.js" } }, "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="], + "esrap": ["esrap@2.3.1", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" }, "peerDependencies": { "@typescript-eslint/types": "^8.2.0" }, "optionalPeers": ["@typescript-eslint/types"] }, "sha512-MXjVkrBAjuwIZ8xq9+a1MOOnLIwANZOx/4gtdWHfSJtXOrUh2QQK2I5mMC3urLli559jTlq2j+kSqht80uRgog=="], "estree-util-is-identifier-name": ["estree-util-is-identifier-name@3.0.0", "", {}, "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="], "estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], + "etag": ["etag@1.8.1", "", {}, "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="], + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], "eventsource": ["eventsource@3.0.7", "", { "dependencies": { "eventsource-parser": "^3.0.1" } }, "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA=="], "eventsource-parser": ["eventsource-parser@3.1.0", "", {}, "sha512-kJezFj9YFAMLeORyi7aCLxLbD5/qWMQnoMVlVPyHIll7lgRJCc3JVln9Vgl9nwQi0YkMnhdGTMNn7CkRRAptMg=="], + "execa": ["execa@9.6.1", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.6", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.1", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.2.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.1.1" } }, "sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA=="], + "expand-template": ["expand-template@2.0.3", "", {}, "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="], "expect-type": ["expect-type@1.4.0", "", {}, "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA=="], + "express": ["express@5.2.1", "", { "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", "content-disposition": "^1.0.0", "content-type": "^1.0.5", "cookie": "^0.7.1", "cookie-signature": "^1.2.1", "debug": "^4.4.0", "depd": "^2.0.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "finalhandler": "^2.1.0", "fresh": "^2.0.0", "http-errors": "^2.0.0", "merge-descriptors": "^2.0.0", "mime-types": "^3.0.0", "on-finished": "^2.4.1", "once": "^1.4.0", "parseurl": "^1.3.3", "proxy-addr": "^2.0.7", "qs": "^6.14.0", "range-parser": "^1.2.1", "router": "^2.2.0", "send": "^1.1.0", "serve-static": "^2.2.0", "statuses": "^2.0.1", "type-is": "^2.0.1", "vary": "^1.1.2" } }, "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw=="], + + "express-rate-limit": ["express-rate-limit@8.6.2", "", { "dependencies": { "debug": "^4.4.3", "ip-address": "^10.2.0" }, "peerDependencies": { "express": ">= 4.11" } }, "sha512-YH4ru+eOJxQABscKFfRCy9R7x9QFGdezclVMwwgFFndzS2Xnm0uo6B0ABZsLhcpeptGv2qvuJVWlQr9gQZoC3A=="], + "extend": ["extend@3.0.2", "", {}, "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="], "fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="], + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + "fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="], "fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="], + "fast-uri": ["fast-uri@3.1.5", "", {}, "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw=="], + "fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="], "fast-xml-builder": ["fast-xml-builder@1.3.0", "", { "dependencies": { "path-expression-matcher": "^1.6.2", "xml-naming": "^0.3.0" } }, "sha512-F74cZEdCvuw9P41GAC3rod4X04jjWGM1JPEv/GWSqFTWLsdyMSBMBMlm9Hk3GLBgLBbdBNY8yee0pQh2RBVESQ=="], "fast-xml-parser": ["fast-xml-parser@5.10.1", "", { "dependencies": { "@nodable/entities": "^3.0.0", "fast-xml-builder": "^1.2.0", "is-unsafe": "^2.0.0", "path-expression-matcher": "^1.6.2", "strnum": "^2.4.1", "xml-naming": "^0.3.0" }, "bin": { "fxparser": "src/cli/cli.js" } }, "sha512-IEMIf7298kXuZSRFoGfMYrl7is8LpavODgbNz1cwIudv7KwVFnuU+UsMporfq6PD6aXSlawZlARiA3UywCTfMw=="], + "fastq": ["fastq@1.20.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], "fetch-blob": ["fetch-blob@3.2.0", "", { "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" } }, "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ=="], "fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="], + "figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="], + "file-type": ["file-type@21.3.4", "", { "dependencies": { "@tokenizer/inflate": "^0.4.1", "strtok3": "^10.3.4", "token-types": "^6.1.1", "uint8array-extras": "^1.4.0" } }, "sha512-Ievi/yy8DS3ygGvT47PjSfdFoX+2isQueoYP1cntFW1JLYAuS4GD7NUPGg4zv2iZfV52uDyk5w5Z0TdpRS6Q1g=="], + "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "finalhandler": ["finalhandler@2.1.1", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA=="], + "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], + "find-up": ["find-up@3.0.0", "", { "dependencies": { "locate-path": "^3.0.0" } }, "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg=="], + "flattie": ["flattie@1.1.1", "", {}, "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ=="], "fontace": ["fontace@0.4.1", "", { "dependencies": { "fontkitten": "^1.0.2" } }, "sha512-lDMvbAzSnHmbYMTEld5qdtvNH2/pWpICOqpean9IgC7vUbUJc3k+k5Dokp85CegamqQpFbXf0rAVkbzpyTA8aw=="], @@ -983,10 +1308,20 @@ "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], + "forwarded": ["forwarded@0.2.0", "", {}, "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="], + + "fresh": ["fresh@2.0.0", "", {}, "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A=="], + "fs-constants": ["fs-constants@1.0.0", "", {}, "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="], + "fs-extra": ["fs-extra@11.4.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA=="], + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "fuzzysort": ["fuzzysort@3.1.0", "", {}, "sha512-sR9BNCjBg6LNgwvxlBd0sBABvQitkLzoVY9MYYROQVX/FvfJ4Mai9LsGhDgd8qYdds0bY77VzYd5iuB+v5rwQQ=="], + "gaxios": ["gaxios@7.3.0", "", { "dependencies": { "extend": "^3.0.2", "https-proxy-agent": "^7.0.1", "node-fetch": "^3.3.2" } }, "sha512-RB5vLV+vvQeoFPCX4QMK6/hjVkbIamPp1QSUD0CiZcnj12qbpiL+pLbYtgD+oZkWl0tl9z+o2Utp+MpM3QRhBA=="], "gcp-metadata": ["gcp-metadata@8.1.2", "", { "dependencies": { "gaxios": "^7.0.0", "google-logging-utils": "^1.0.0", "json-bigint": "^1.0.0" } }, "sha512-zV/5HKTfCeKWnxG0Dmrw51hEWFGfcF2xiXqcA3+J90WDuP0SvoiSO5ORvcBsifmx/FoIjgQN3oNOGaQ5PhLFkg=="], @@ -997,6 +1332,16 @@ "get-east-asian-width": ["get-east-asian-width@1.6.0", "", {}, "sha512-QRbvDIbx6YklUe6RxeTeleMR0yv3cYH6PsPZHcnVn7xv7zO1BHN8r0XETu8n6Ye3Q+ahtSarc3WgtNWmehIBfA=="], + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + + "get-own-enumerable-keys": ["get-own-enumerable-keys@1.0.0", "", {}, "sha512-PKsK2FSrQCyxcGHsGrLDcK0lx+0Ke+6e8KFFozA9/fIQLhQzPaRvJFdcz7+Axg3jUH/Mq+NI4xa5u/UT2tQskA=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="], + "get-tsconfig": ["get-tsconfig@5.0.0-beta.4", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7nF7C9fIPFEMHgEMEfgIlO9wDdZ8CyHw27rWciFZfHvHDReIiPhsYuzPRXsfvBCqFy1l8RRyyWV7QLM+ZhUJsQ=="], "github-from-package": ["github-from-package@0.0.0", "", {}, "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="], @@ -1005,14 +1350,22 @@ "glob": ["glob@13.0.6", "", { "dependencies": { "minimatch": "^10.2.2", "minipass": "^7.1.3", "path-scurry": "^2.0.2" } }, "sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw=="], + "glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "google-auth-library": ["google-auth-library@10.9.1", "", { "dependencies": { "base64-js": "^1.3.0", "ecdsa-sig-formatter": "^1.0.11", "gaxios": "^7.1.4", "gcp-metadata": "8.1.2", "google-logging-utils": "1.1.3", "jws": "^4.0.0" } }, "sha512-i1ydyHrqcIxXkWh/uBmVkzCvIuq5yiK2ATndIe5XxKholrG/MTYP9xGYka4sQhrbIAgGjL2B6NOE7rFaiF3fXw=="], "google-logging-utils": ["google-logging-utils@1.1.3", "", {}, "sha512-eAmLkjDjAFCVXg7A1unxHsLf961m6y17QFqXqAXGj/gVkKFrEICfStRfwUlGNfeCEjNRa32JEWOUTlYXPyyKvA=="], + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "h3": ["h3@1.15.11", "", { "dependencies": { "cookie-es": "^1.2.3", "crossws": "^0.3.5", "defu": "^6.1.6", "destr": "^2.0.5", "iron-webcrypto": "^1.2.1", "node-mock-http": "^1.0.4", "radix3": "^1.1.2", "ufo": "^1.6.3", "uncrypto": "^0.1.3" } }, "sha512-L3THSe2MPeBwgIZVSH5zLdBBU90TOxarvhK9d04IDY2AmVS8j2Jz2LIWtwsGOU3lu2I5jCN7FNvVfY2+XyF+mg=="], + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + "hast-util-from-html": ["hast-util-from-html@2.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "devlop": "^1.1.0", "hast-util-from-parse5": "^8.0.0", "parse5": "^7.0.0", "vfile": "^6.0.0", "vfile-message": "^4.0.0" } }, "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw=="], "hast-util-from-parse5": ["hast-util-from-parse5@8.0.3", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "devlop": "^1.0.0", "hastscript": "^9.0.0", "property-information": "^7.0.0", "vfile": "^6.0.0", "vfile-location": "^5.0.0", "web-namespaces": "^2.0.0" } }, "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg=="], @@ -1037,6 +1390,8 @@ "highlight.js": ["highlight.js@10.7.3", "", {}, "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A=="], + "hono": ["hono@4.13.1", "", {}, "sha512-kdJoFVv2xmayw6cY09H7AbMJMt8Jn5jdlEdXsP7AGBdF2DIptVlKlOLKXP41yPip4/a3yQPv9gVcJYI8YY04dw=="], + "hosted-git-info": ["hosted-git-info@9.0.3", "", { "dependencies": { "lru-cache": "^11.1.0" } }, "sha512-Hc+ghLoSt6QaYZUv0WBiIvmMDZuZZ7oaDvdH8MbfOO4lOsxdXLEvuC6ePoGs9H1X9oCLyq6+NVN0MKqD+ydxyg=="], "html-encoding-sniffer": ["html-encoding-sniffer@6.0.0", "", { "dependencies": { "@exodus/bytes": "^1.6.0" } }, "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg=="], @@ -1049,14 +1404,22 @@ "http-cache-semantics": ["http-cache-semantics@4.2.0", "", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + "http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="], + "http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="], "https-proxy-agent": ["https-proxy-agent@7.0.6", "", { "dependencies": { "agent-base": "^7.1.2", "debug": "4" } }, "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw=="], + "human-signals": ["human-signals@8.0.1", "", {}, "sha512-eKCa6bwnJhvxj14kZk5NCPc6Hb6BdsU9DZcOnmQKSnO1VKrfV0zCvtttPZUsBvjmNDn8rpcJfpwSYnHBjc95MQ=="], + + "iconv-lite": ["iconv-lite@0.7.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ=="], + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], @@ -1065,26 +1428,56 @@ "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], + "ip-address": ["ip-address@10.4.0", "", {}, "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ=="], + + "ipaddr.js": ["ipaddr.js@1.9.1", "", {}, "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="], + "iron-webcrypto": ["iron-webcrypto@1.2.1", "", {}, "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg=="], "is-alphabetical": ["is-alphabetical@2.0.1", "", {}, "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="], "is-alphanumerical": ["is-alphanumerical@2.0.1", "", { "dependencies": { "is-alphabetical": "^2.0.0", "is-decimal": "^2.0.0" } }, "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw=="], + "is-arrayish": ["is-arrayish@0.2.1", "", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + "is-decimal": ["is-decimal@2.0.1", "", {}, "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="], "is-docker": ["is-docker@4.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-LHE+wROyG/Y/0ZnbktRCoTix2c1RhgWaZraMZ8o1Q7zCh0VSrICJQO5oqIIISrcSBtrXv0o233w1IYwsWCjTzA=="], + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + "is-hexadecimal": ["is-hexadecimal@2.0.1", "", {}, "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="], + "is-in-ssh": ["is-in-ssh@1.0.0", "", {}, "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw=="], + + "is-inside-container": ["is-inside-container@1.0.0", "", { "dependencies": { "is-docker": "^3.0.0" }, "bin": { "is-inside-container": "cli.js" } }, "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA=="], + + "is-interactive": ["is-interactive@2.0.0", "", {}, "sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ=="], + + "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-obj": ["is-obj@3.0.0", "", {}, "sha512-IlsXEHOjtKhpN8r/tRFj2nDyTmHvcfNeu/nrRIcXE17ROeatXchkojffa1SpdqW4cr/Fj6QkEf/Gn4zf6KKvEQ=="], + "is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="], "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="], + "is-promise": ["is-promise@4.0.0", "", {}, "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ=="], + "is-reference": ["is-reference@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.6" } }, "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw=="], + "is-regexp": ["is-regexp@3.1.0", "", {}, "sha512-rbku49cWloU5bSMI+zaRaXdQHXnthP6DZ/vLnfdSKyL4zUzuWnomtOEiZZOd+ioQ+avFo/qau3KPTc7Fjy1uPA=="], + + "is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="], + + "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], + "is-unsafe": ["is-unsafe@2.0.0", "", {}, "sha512-2LdV822R+wmI86unXA93WCFpL6g+av8ynWk0nrHyJqGop5VoocYsSLFgN8jrfalT6iGeLNM4KXuVSsULP53kEA=="], + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], "jiti": ["jiti@2.7.0", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ=="], @@ -1101,18 +1494,28 @@ "json-bigint": ["json-bigint@1.0.0", "", { "dependencies": { "bignumber.js": "^9.0.0" } }, "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ=="], + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "json-schema-to-ts": ["json-schema-to-ts@3.1.1", "", { "dependencies": { "@babel/runtime": "^7.18.3", "ts-algebra": "^2.0.0" } }, "sha512-+DWg8jCJG2TEnpy7kOm/7/AxaYoaRbjVB4LFZLySZlWn8exGs3A4OLJR966cVvU26N7X9TWxl+Jsw7dzAqKT6g=="], + "json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "json-schema-typed": ["json-schema-typed@8.0.2", "", {}, "sha512-fQhoXdcvc3V28x7C7BMs4P5+kNlgUURe2jmUT1T//oBRMDrqy1QPelJimwZGo7Hg9VPV3EQV5Bnq4hbFy2vetA=="], + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "jsonc-parser": ["jsonc-parser@3.3.1", "", {}, "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ=="], + "jsonfile": ["jsonfile@6.2.1", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q=="], + "just-bash": ["just-bash@3.2.0", "", { "dependencies": { "diff": "^8.0.2", "fast-xml-parser": "^5.7.3", "file-type": "^21.2.0", "ini": "^6.0.0", "minimatch": "^10.1.1", "modern-tar": "^0.7.3", "papaparse": "^5.5.3", "quickjs-emscripten": "^0.32.0", "re2js": "^1.2.1", "seek-bzip": "^2.0.0", "smol-toml": "^1.6.0", "sprintf-js": "^1.1.3", "sql.js": "^1.13.0", "turndown": "^7.2.2", "undici": "^7.25.0", "yaml": "^2.8.2" }, "optionalDependencies": { "@mongodb-js/zstd": "^7.0.0", "node-liblzma": "^2.0.3" }, "bin": { "just-bash": "dist/bin/just-bash.js", "just-bash-shell": "dist/bin/shell/shell.js" } }, "sha512-hRTLLWBXCKuosjaNFJR7uPYBza+T2vjG3NdPBz4wxlctlnxwrbLjtLQf6RtSKmy/jzNJ6/URCtvxrXjy6yFGeQ=="], "jwa": ["jwa@2.0.1", "", { "dependencies": { "buffer-equal-constant-time": "^1.0.1", "ecdsa-sig-formatter": "1.0.11", "safe-buffer": "^5.0.1" } }, "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg=="], "jws": ["jws@4.0.1", "", { "dependencies": { "jwa": "^2.0.1", "safe-buffer": "^5.0.1" } }, "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA=="], + "kleur": ["kleur@4.1.5", "", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + "kolorist": ["kolorist@1.8.0", "", {}, "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ=="], "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], @@ -1141,14 +1544,22 @@ "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.33.0", "", { "os": "win32", "cpu": "x64" }, "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA=="], + "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], + "locate-character": ["locate-character@3.0.0", "", {}, "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA=="], + "locate-path": ["locate-path@3.0.0", "", { "dependencies": { "p-locate": "^3.0.0", "path-exists": "^3.0.0" } }, "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A=="], + + "log-symbols": ["log-symbols@6.0.0", "", { "dependencies": { "chalk": "^5.3.0", "is-unicode-supported": "^1.3.0" } }, "sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw=="], + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], "longest-streak": ["longest-streak@3.1.0", "", {}, "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="], "lru-cache": ["lru-cache@11.5.2", "", {}, "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g=="], + "lucide-react": ["lucide-react@1.30.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-tUIr2jXLbWpCkdtH8XP7P7YppM9ueWgTky99lpWDY6z5REs6B+O6ZQ3U5tHkUUY59ANyOv/PBcs8E4Fe3KO3eA=="], + "lz-string": ["lz-string@1.5.0", "", { "bin": { "lz-string": "bin/bin.js" } }, "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ=="], "magic-string": ["magic-string@1.1.0", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-kS3VHe0nEPST2saQV4Rbkchcd3UBRkVTQHo1D3h/ZTwFDhai/mfKkmtPAtD129EOI7K3HlHIsFOt0WrI2/oU9g=="], @@ -1159,6 +1570,8 @@ "marked": ["marked@18.0.5", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w=="], + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + "mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="], "mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="], @@ -1193,6 +1606,14 @@ "mdn-data": ["mdn-data@2.27.1", "", {}, "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ=="], + "media-typer": ["media-typer@1.1.1", "", {}, "sha512-yz3xRaG20c6/BOzvYoDaGtPmGscs7YivItZEEqe6GbwNfHuxu9YNmvnEkMzKldAGY4/80pRcQRZSEnhquk9XuQ=="], + + "merge-descriptors": ["merge-descriptors@2.0.0", "", {}, "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g=="], + + "merge-stream": ["merge-stream@2.0.0", "", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + + "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + "micromark": ["micromark@4.0.2", "", { "dependencies": { "@types/debug": "^4.0.0", "debug": "^4.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-core-commonmark": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-combine-extensions": "^2.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-sanitize-uri": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA=="], "micromark-core-commonmark": ["micromark-core-commonmark@2.0.3", "", { "dependencies": { "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "micromark-factory-destination": "^2.0.0", "micromark-factory-label": "^2.0.0", "micromark-factory-space": "^2.0.0", "micromark-factory-title": "^2.0.0", "micromark-factory-whitespace": "^2.0.0", "micromark-util-character": "^2.0.0", "micromark-util-chunked": "^2.0.0", "micromark-util-classify-character": "^2.0.0", "micromark-util-html-tag-name": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-resolve-all": "^2.0.0", "micromark-util-subtokenize": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg=="], @@ -1249,6 +1670,16 @@ "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime-db": ["mime-db@1.54.0", "", {}, "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ=="], + + "mime-types": ["mime-types@3.0.2", "", { "dependencies": { "mime-db": "^1.54.0" } }, "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A=="], + + "mimic-fn": ["mimic-fn@3.1.0", "", {}, "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ=="], + + "mimic-function": ["mimic-function@5.0.1", "", {}, "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA=="], + "mimic-response": ["mimic-response@3.1.0", "", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], "min-indent": ["min-indent@1.0.1", "", {}, "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg=="], @@ -1277,6 +1708,8 @@ "napi-build-utils": ["napi-build-utils@2.0.0", "", {}, "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA=="], + "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + "neotraverse": ["neotraverse@1.0.1", "", {}, "sha512-WmmLty1YWwJl9yZi77v2dVIV6X2kuYV8YYBI/G3LWGKdGHmHUvL1z7FW0iDvEvGAwNEoc5x1tOOOyDnf5jJw/w=="], "nlcst-to-string": ["nlcst-to-string@4.0.0", "", { "dependencies": { "@types/nlcst": "^2.0.0" } }, "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA=="], @@ -1305,46 +1738,80 @@ "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], + "npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="], + "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "object-treeify": ["object-treeify@1.1.33", "", {}, "sha512-EFVjAYfzWqWsBMRHPMAXLCDIJnpMhdWAqR7xG6M6a2cs6PMFpl/+Z20w9zDW4vkxOFfddegBKq9Rehd0bxWE7A=="], + "obug": ["obug@2.1.4", "", {}, "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA=="], "ofetch": ["ofetch@1.5.1", "", { "dependencies": { "destr": "^2.0.5", "node-fetch-native": "^1.6.7", "ufo": "^1.6.1" } }, "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA=="], "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], + "on-finished": ["on-finished@2.4.1", "", { "dependencies": { "ee-first": "1.1.1" } }, "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg=="], + "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + "onetime": ["onetime@5.1.2", "", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + "oniguruma-parser": ["oniguruma-parser@0.12.2", "", {}, "sha512-6HVa5oIrgMC6aA6WF6XyyqbhRPJrKR02L20+2+zpDtO5QAzGHAUGw5TKQvwi5vctNnRHkJYmjAhRVQF2EKdTQw=="], "oniguruma-to-es": ["oniguruma-to-es@4.3.6", "", { "dependencies": { "oniguruma-parser": "^0.12.2", "regex": "^6.1.0", "regex-recursion": "^6.0.2" } }, "sha512-csuQ9x3Yr0cEIs/Zgx/OEt9iBw9vqIunAPQkx19R/fiMq2oGVTgcMqO/V3Ybqefr1TBvosI6jU539ksaBULJyA=="], + "open": ["open@11.0.0", "", { "dependencies": { "default-browser": "^5.4.0", "define-lazy-prop": "^3.0.0", "is-in-ssh": "^1.0.0", "is-inside-container": "^1.0.0", "powershell-utils": "^0.1.0", "wsl-utils": "^0.3.0" } }, "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw=="], + "openai": ["openai@6.26.0", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.25 || ^4.0" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-zd23dbWTjiJ6sSAX6s0HrCZi41JwTA1bQVs0wLQPZ2/5o2gxOJA5wh7yOAUgwYybfhDXyhwlpeQf7Mlgx8EOCA=="], + "ora": ["ora@8.2.0", "", { "dependencies": { "chalk": "^5.3.0", "cli-cursor": "^5.0.0", "cli-spinners": "^2.9.2", "is-interactive": "^2.0.0", "is-unicode-supported": "^2.0.0", "log-symbols": "^6.0.0", "stdin-discarder": "^0.2.2", "string-width": "^7.2.0", "strip-ansi": "^7.1.0" } }, "sha512-weP+BZ8MVNnlCm8c0Qdc1WSWq4Qn7I+9CJGm7Qali6g44e/PUzbjNqJX5NJ9ljlNMosfJvg1fKEGILklK9cwnw=="], + "p-limit": ["p-limit@7.3.1", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-0trZaiG7Y7kN/Egy9a8j47t9osC0Tch4PaIWd9yGF6bvmlk7muExRvGNYb8sXBwEKMoNKsbNN9P8EefuQekE4Q=="], + "p-locate": ["p-locate@3.0.0", "", { "dependencies": { "p-limit": "^2.0.0" } }, "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ=="], + "p-queue": ["p-queue@9.3.3", "", { "dependencies": { "eventemitter3": "^5.0.4", "p-timeout": "^7.0.0" } }, "sha512-NXAOdnEe5FsZJfT4oK84lE1Y5cFFdWlRuOo5tww8DyNMxyRXwn39fIkUtNLKppcPC+UYU/bXujNCUGDv01y7CA=="], "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], "p-timeout": ["p-timeout@7.0.1", "", {}, "sha512-AxTM2wDGORHGEkPCt8yqxOTMgpfbEHqF51f/5fJCmwFC3C/zNcGT63SymH2ttOAaiIws2zVg4+izQCjrakcwHg=="], + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + "package-manager-detector": ["package-manager-detector@1.8.0", "", {}, "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A=="], "papaparse": ["papaparse@5.5.4", "", {}, "sha512-SwzWD9gl/ElwYLCI0nUja1mFJzjq2D8ziShfNBa7zCHzkOozeOGDwHWQ+tvCzEZcewecWZ5U7kUopDnG+DFYEQ=="], + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + "parse-entities": ["parse-entities@4.0.2", "", { "dependencies": { "@types/unist": "^2.0.0", "character-entities-legacy": "^3.0.0", "character-reference-invalid": "^2.0.0", "decode-named-character-reference": "^1.0.0", "is-alphanumerical": "^2.0.0", "is-decimal": "^2.0.0", "is-hexadecimal": "^2.0.0" } }, "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw=="], + "parse-json": ["parse-json@5.2.0", "", { "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg=="], + + "parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="], + "parse5": ["parse5@8.0.1", "", { "dependencies": { "entities": "^8.0.0" } }, "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw=="], + "parseurl": ["parseurl@1.3.3", "", {}, "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="], + "partial-json": ["partial-json@0.1.7", "", {}, "sha512-Njv/59hHaokb/hRUjce3Hdv12wd60MtM9Z5Olmn+nehe0QDAsRtRbJPvJ0Z91TusF0SuZRIvnM+S4l6EIP8leA=="], + "path-browserify": ["path-browserify@1.0.1", "", {}, "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g=="], + + "path-exists": ["path-exists@3.0.0", "", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + "path-expression-matcher": ["path-expression-matcher@1.6.2", "", {}, "sha512-enSlaiat05iasnzmgNxRj8reFdj3puY2QpNgP1aPIaVfT6nn9ICuPoFlKHk8EN22HcwewshO+mN2DGbkCEOtqQ=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-scurry": ["path-scurry@2.0.2", "", { "dependencies": { "lru-cache": "^11.0.0", "minipass": "^7.1.2" } }, "sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg=="], + "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="], + "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], "piccolore": ["piccolore@0.1.3", "", {}, "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw=="], @@ -1355,12 +1822,18 @@ "pkce-challenge": ["pkce-challenge@5.0.1", "", {}, "sha512-wQ0b/W4Fr01qtpHlqSqspcj3EhBvimsdh0KlHhH8HRZnMsEa0ea2fTULOXOS9ccQr3om+GcGRk4e+isrZWV8qQ=="], + "pkg-up": ["pkg-up@3.1.0", "", { "dependencies": { "find-up": "^3.0.0" } }, "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA=="], + "playwright": ["playwright@1.62.0", "", { "dependencies": { "playwright-core": "1.62.0" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-Z14dG305dgaLu6foB1TXQagFiW8JfSUIUaUuPaKQ6NtBPKF1P/qXcqfh6c6K/icPqdy37JmjbiBXf6JNg6Sylw=="], "playwright-core": ["playwright-core@1.62.0", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-nsNRyq0r2zsG8AcRHWknc9QRA5XCueC7gWMrs+Gx2tlZn9hcl8zudfh00lhJPY1DE7NmZ6bDsT9g2yey8mXljA=="], "postcss": ["postcss@8.5.25", "", { "dependencies": { "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw=="], + "postcss-selector-parser": ["postcss-selector-parser@7.1.5", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-KvvtD7SrlBP7dlgkBghEE3r84CABm5SmV2aNcG4oCA+qDnJ/tvKonFVvwWAyyWUEwxuNawdfEAZKP9zM3oZ2Uw=="], + + "powershell-utils": ["powershell-utils@0.1.0", "", {}, "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A=="], + "preact": ["preact@10.29.8", "", { "peerDependencies": { "preact-render-to-string": ">=5" }, "optionalPeers": ["preact-render-to-string"] }, "sha512-ej2aVZ+vZ8WO7tvlQWRM9N63A0KzF9q4mWJfDUHgYaIofWY9hu74QdnQrjoPMmZi2/nZ5gN0bJCQF49xQqx09Q=="], "preact-render-to-string": ["preact-render-to-string@6.7.0", "", { "peerDependencies": { "preact": ">=10 || >= 11.0.0-0" } }, "sha512-Z4WR8fmLMRpdYqJ9i7vrlXSsSrxVJydwrkEXHapexfARbWfGb7vGcnvNQnIzN0cXciMVOlz/XLoiMCi9gUsy9Q=="], @@ -1369,28 +1842,44 @@ "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], + "pretty-ms": ["pretty-ms@9.3.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ=="], + "prismjs": ["prismjs@1.30.0", "", {}, "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw=="], "process-ancestry": ["process-ancestry@0.1.0", "", {}, "sha512-tGqJW/UnclpYASFcM6Xh8D8l/BMtaQ9+CSG0vlJSJTcdMM4lDRv4c6H0Pdcsfted+bVczdYSfk2fdukg2gQkZg=="], + "prompts": ["prompts@2.4.2", "", { "dependencies": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" } }, "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q=="], + "proper-lockfile": ["proper-lockfile@4.1.2", "", { "dependencies": { "graceful-fs": "^4.2.4", "retry": "^0.12.0", "signal-exit": "^3.0.2" } }, "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA=="], "property-information": ["property-information@7.2.0", "", {}, "sha512-IAtzIB6sUiWaJYrX9smp3V46pBGbBeLFRGdh25kg1334VcBlD8HzhPeNIWQH9zhGmo2itIe25EHt9dQP7G5hmg=="], "protobufjs": ["protobufjs@7.6.5", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-/FPD0nUc9jH6rfFjji9IBqOz4pcSE3CsT1m7Ep6Mdb0LxSUMj8hgl6GomOvZzpNpAqqGaXA0P3VSrZLFzIhQrw=="], + "proxy-addr": ["proxy-addr@2.0.7", "", { "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" } }, "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg=="], + "pump": ["pump@3.0.4", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], "pure-rand": ["pure-rand@8.4.2", "", {}, "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng=="], + "qs": ["qs@6.15.3", "", { "dependencies": { "es-define-property": "^1.0.1", "side-channel": "^1.1.1" } }, "sha512-O9gl3zCl5h5blw1KGUzQKhA5oUXSl8rwUIM5o0S3nCXMliSvy5Dzx7/DJcI+SwgICv+IneSZwhBh1oSyEHA71A=="], + + "queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + "quickjs-emscripten": ["quickjs-emscripten@0.32.0", "", { "dependencies": { "@jitl/quickjs-wasmfile-debug-asyncify": "0.32.0", "@jitl/quickjs-wasmfile-debug-sync": "0.32.0", "@jitl/quickjs-wasmfile-release-asyncify": "0.32.0", "@jitl/quickjs-wasmfile-release-sync": "0.32.0", "quickjs-emscripten-core": "0.32.0" } }, "sha512-So0Sqw869y/S2oE3Nuc0uT3Dhqgvsj8FSrwBdsuTosVsG8ME5/OcudU1GxsrIFdFABgy17GHnTVO9TYV/bLQcA=="], "quickjs-emscripten-core": ["quickjs-emscripten-core@0.32.0", "", { "dependencies": { "@jitl/quickjs-ffi-types": "0.32.0" } }, "sha512-QFnPfjFey8EqknSrSxe1hZrf1/8z7/6s1QzGOmKo6++02r7QRRX7ZoyNaZh7JuVjWsVW87KnQrbZqnHkOAzUyg=="], + "radix-ui": ["radix-ui@1.6.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.7", "@radix-ui/react-accessible-icon": "1.1.15", "@radix-ui/react-accordion": "1.2.20", "@radix-ui/react-alert-dialog": "1.1.23", "@radix-ui/react-arrow": "1.1.15", "@radix-ui/react-aspect-ratio": "1.1.15", "@radix-ui/react-avatar": "1.2.6", "@radix-ui/react-checkbox": "1.3.11", "@radix-ui/react-collapsible": "1.1.20", "@radix-ui/react-collection": "1.1.15", "@radix-ui/react-compose-refs": "1.1.5", "@radix-ui/react-context": "1.2.2", "@radix-ui/react-context-menu": "2.3.7", "@radix-ui/react-dialog": "1.1.23", "@radix-ui/react-direction": "1.1.4", "@radix-ui/react-dismissable-layer": "1.1.19", "@radix-ui/react-dropdown-menu": "2.1.24", "@radix-ui/react-focus-guards": "1.1.6", "@radix-ui/react-focus-scope": "1.1.16", "@radix-ui/react-form": "0.1.16", "@radix-ui/react-hover-card": "1.1.23", "@radix-ui/react-label": "2.1.15", "@radix-ui/react-menu": "2.1.24", "@radix-ui/react-menubar": "1.1.24", "@radix-ui/react-navigation-menu": "1.2.22", "@radix-ui/react-one-time-password-field": "0.1.16", "@radix-ui/react-password-toggle-field": "0.1.11", "@radix-ui/react-popover": "1.1.23", "@radix-ui/react-popper": "1.3.7", "@radix-ui/react-portal": "1.1.17", "@radix-ui/react-presence": "1.1.10", "@radix-ui/react-primitive": "2.1.10", "@radix-ui/react-progress": "1.1.16", "@radix-ui/react-radio-group": "1.4.7", "@radix-ui/react-roving-focus": "1.1.19", "@radix-ui/react-scroll-area": "1.2.18", "@radix-ui/react-select": "2.3.7", "@radix-ui/react-separator": "1.1.15", "@radix-ui/react-slider": "1.4.7", "@radix-ui/react-slot": "1.3.3", "@radix-ui/react-switch": "1.3.7", "@radix-ui/react-tabs": "1.1.21", "@radix-ui/react-toast": "1.2.23", "@radix-ui/react-toggle": "1.1.18", "@radix-ui/react-toggle-group": "1.1.19", "@radix-ui/react-toolbar": "1.1.19", "@radix-ui/react-tooltip": "1.2.16", "@radix-ui/react-use-callback-ref": "1.1.4", "@radix-ui/react-use-controllable-state": "1.2.6", "@radix-ui/react-use-effect-event": "0.0.5", "@radix-ui/react-use-escape-keydown": "1.1.5", "@radix-ui/react-use-is-hydrated": "0.1.3", "@radix-ui/react-use-layout-effect": "1.1.4", "@radix-ui/react-use-size": "1.1.4", "@radix-ui/react-visually-hidden": "1.2.11" }, "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" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QBdhh1arIEUvPC0dQ5+nwWAxt7+N+oP/9jPwjJkGFoSk/sqxg32gJtSXGtFh8frAIcS6oC9cx2Q+7KYCQLOAeA=="], + "radix3": ["radix3@1.1.2", "", {}, "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA=="], + "range-parser": ["range-parser@1.3.0", "", {}, "sha512-hek2mFQpPuI4E1BBKrSto+BU3e3x4xuarsbiwr3+lf7p44juvFMV0XFWQAP3xUyqXA4RrXLIoaSUGbSt056ZMw=="], + + "raw-body": ["raw-body@3.0.2", "", { "dependencies": { "bytes": "~3.1.2", "http-errors": "~2.0.1", "iconv-lite": "~0.7.0", "unpipe": "~1.0.0" } }, "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA=="], + "rc": ["rc@1.2.8", "", { "dependencies": { "deep-extend": "^0.6.0", "ini": "~1.3.0", "minimist": "^1.2.0", "strip-json-comments": "~2.0.1" }, "bin": { "rc": "./cli.js" } }, "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw=="], "re2js": ["re2js@1.4.0", "", {}, "sha512-KTOIcZTSOpOxbu3i0+T6mFQ6tkxXKlTxfcMFs1trQbsMnG84qNq+DjXr8Afu+FEFjvF1NNlldpC7roPyazFI8g=="], @@ -1403,10 +1892,18 @@ "react-markdown": ["react-markdown@10.1.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "hast-util-to-jsx-runtime": "^2.0.0", "html-url-attributes": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "remark-parse": "^11.0.0", "remark-rehype": "^11.0.0", "unified": "^11.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" }, "peerDependencies": { "@types/react": ">=18", "react": ">=18" } }, "sha512-qKxVopLT/TyA6BX3Ue5NwabOsAzm0Q7kAPwq6L+wWDwisYs7R8vZ0nRXqq6rkueboxpkjvLGU9fWifiX/ZZFxQ=="], + "react-remove-scroll": ["react-remove-scroll@2.7.2", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + "readable-stream": ["readable-stream@3.6.2", "", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], "readdirp": ["readdirp@5.1.1", "", {}, "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA=="], + "recast": ["recast@0.23.19", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-T98lym7kH+pnZmRaD8yDRdaNqyUbwnbEBx0MuchrzMFOEMray4AO3ZJoTUZ5r78Ao78X/OhzW0DL8GB85w/I2w=="], + "redent": ["redent@3.0.0", "", { "dependencies": { "indent-string": "^4.0.0", "strip-indent": "^3.0.0" } }, "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg=="], "regex": ["regex@6.1.0", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-6VwtthbV4o/7+OaAF9I5L5V3llLEsoPyq9P1JVXkedTP33c7MfCG0/5NOPcSJn0TzXcG9YUrR0gQSWioew3LDg=="], @@ -1431,18 +1928,32 @@ "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + "resolve-pkg-maps": ["resolve-pkg-maps@1.0.0", "", {}, "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw=="], + "restore-cursor": ["restore-cursor@5.1.0", "", { "dependencies": { "onetime": "^7.0.0", "signal-exit": "^4.1.0" } }, "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA=="], + "retext-smartypants": ["retext-smartypants@6.2.0", "", { "dependencies": { "@types/nlcst": "^2.0.0", "nlcst-to-string": "^4.0.0", "unist-util-visit": "^5.0.0" } }, "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ=="], "retry": ["retry@0.12.0", "", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + "rolldown": ["rolldown@1.1.5", "", { "dependencies": { "@oxc-project/types": "=0.139.0", "@rolldown/pluginutils": "^1.0.0" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.1.5", "@rolldown/binding-darwin-arm64": "1.1.5", "@rolldown/binding-darwin-x64": "1.1.5", "@rolldown/binding-freebsd-x64": "1.1.5", "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", "@rolldown/binding-linux-arm64-gnu": "1.1.5", "@rolldown/binding-linux-arm64-musl": "1.1.5", "@rolldown/binding-linux-ppc64-gnu": "1.1.5", "@rolldown/binding-linux-s390x-gnu": "1.1.5", "@rolldown/binding-linux-x64-gnu": "1.1.5", "@rolldown/binding-linux-x64-musl": "1.1.5", "@rolldown/binding-openharmony-arm64": "1.1.5", "@rolldown/binding-wasm32-wasi": "1.1.5", "@rolldown/binding-win32-arm64-msvc": "1.1.5", "@rolldown/binding-win32-x64-msvc": "1.1.5" }, "bin": { "rolldown": "./bin/cli.mjs" } }, "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA=="], + "router": ["router@2.2.0", "", { "dependencies": { "debug": "^4.4.0", "depd": "^2.0.0", "is-promise": "^4.0.0", "parseurl": "^1.3.3", "path-to-regexp": "^8.0.0" } }, "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ=="], + + "run-applescript": ["run-applescript@7.1.0", "", {}, "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q=="], + + "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + "rxjs": ["rxjs@7.8.2", "", { "dependencies": { "tslib": "^2.1.0" } }, "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA=="], "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + "satteri": ["satteri@0.9.5", "", { "dependencies": { "@types/estree-jsx": "^1.0.5", "@types/hast": "^3.0.4", "@types/mdast": "^4.0.4", "@types/unist": "^3.0.3" }, "optionalDependencies": { "@bruits/satteri-darwin-arm64": "0.9.5", "@bruits/satteri-darwin-x64": "0.9.5", "@bruits/satteri-linux-arm64-gnu": "0.9.5", "@bruits/satteri-linux-arm64-musl": "0.9.5", "@bruits/satteri-linux-x64-gnu": "0.9.5", "@bruits/satteri-linux-x64-musl": "0.9.5", "@bruits/satteri-wasm32-wasi": "0.9.5", "@bruits/satteri-win32-arm64-msvc": "0.9.5", "@bruits/satteri-win32-x64-msvc": "0.9.5" } }, "sha512-ZuWVl+vnM64y+/TtX8Kosv2c00W+hLQiiwnEL6H0UKVVrxFqMw4D2CJHHQaouVd89OAhtBBfjWLqhKi3TVUV4w=="], "sax": ["sax@1.6.1", "", {}, "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q=="], @@ -1455,6 +1966,14 @@ "semver": ["semver@7.8.5", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA=="], + "send": ["send@1.2.1", "", { "dependencies": { "debug": "^4.4.3", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "etag": "^1.8.1", "fresh": "^2.0.0", "http-errors": "^2.0.1", "mime-types": "^3.0.2", "ms": "^2.1.3", "on-finished": "^2.4.1", "range-parser": "^1.2.1", "statuses": "^2.0.2" } }, "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ=="], + + "serve-static": ["serve-static@2.2.1", "", { "dependencies": { "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "parseurl": "^1.3.3", "send": "^1.2.0" } }, "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw=="], + + "setprototypeof": ["setprototypeof@1.2.0", "", {}, "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="], + + "shadcn": ["shadcn@4.16.2", "", { "dependencies": { "@babel/core": "^7.28.0", "@babel/parser": "^7.28.0", "@babel/plugin-transform-typescript": "^7.28.0", "@babel/preset-typescript": "^7.27.1", "@dotenvx/dotenvx": "^1.48.4", "@modelcontextprotocol/sdk": "^1.26.0", "@types/validate-npm-package-name": "^4.0.2", "browserslist": "^4.26.2", "commander": "^14.0.0", "cosmiconfig": "^9.0.0", "dedent": "^1.6.0", "deepmerge": "^4.3.1", "diff": "^8.0.2", "execa": "^9.6.0", "fast-glob": "^3.3.3", "fs-extra": "^11.3.1", "fuzzysort": "^3.1.0", "kleur": "^4.1.5", "open": "^11.0.0", "ora": "^8.2.0", "postcss": "^8.5.6", "postcss-selector-parser": "^7.1.0", "prompts": "^2.4.2", "recast": "^0.23.11", "stringify-object": "^5.0.0", "tailwind-merge": "^3.0.1", "ts-morph": "^26.0.0", "tsconfig-paths": "^4.2.0", "undici": "^7.27.2", "validate-npm-package-name": "^7.0.1", "zod": "^3.24.1", "zod-to-json-schema": "^3.24.6" }, "bin": { "shadcn": "dist/index.js" } }, "sha512-M1AvZKFWcCzWRDoyApIqJMSLIpY8Ev4uBGuiPLSFmiTbixXhPmzotSTvLzFmBrfoIxG9aIg2dZOETblEaXGUnQ=="], + "sharp": ["sharp@0.35.3", "", { "dependencies": { "@img/colour": "^1.1.0", "detect-libc": "^2.1.2", "semver": "^7.8.5" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.35.3", "@img/sharp-darwin-x64": "0.35.3", "@img/sharp-freebsd-wasm32": "0.35.3", "@img/sharp-libvips-darwin-arm64": "1.3.2", "@img/sharp-libvips-darwin-x64": "1.3.2", "@img/sharp-libvips-linux-arm": "1.3.2", "@img/sharp-libvips-linux-arm64": "1.3.2", "@img/sharp-libvips-linux-ppc64": "1.3.2", "@img/sharp-libvips-linux-riscv64": "1.3.2", "@img/sharp-libvips-linux-s390x": "1.3.2", "@img/sharp-libvips-linux-x64": "1.3.2", "@img/sharp-libvips-linuxmusl-arm64": "1.3.2", "@img/sharp-libvips-linuxmusl-x64": "1.3.2", "@img/sharp-linux-arm": "0.35.3", "@img/sharp-linux-arm64": "0.35.3", "@img/sharp-linux-ppc64": "0.35.3", "@img/sharp-linux-riscv64": "0.35.3", "@img/sharp-linux-s390x": "0.35.3", "@img/sharp-linux-x64": "0.35.3", "@img/sharp-linuxmusl-arm64": "0.35.3", "@img/sharp-linuxmusl-x64": "0.35.3", "@img/sharp-webcontainers-wasm32": "0.35.3", "@img/sharp-win32-arm64": "0.35.3", "@img/sharp-win32-ia32": "0.35.3", "@img/sharp-win32-x64": "0.35.3" }, "peerDependencies": { "@types/node": "*" }, "optionalPeers": ["@types/node"] }, "sha512-ej0zVHuZGHCiABXcNxeYhpRnPNPAcvbG8RMdBAhDAxLKkCRVSpK3Iyu7qbqw3JMzoj0REeM6f3tJLtVwl0023Q=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], @@ -1465,9 +1984,17 @@ "shiki": ["shiki@4.3.1", "", { "dependencies": { "@shikijs/core": "4.3.1", "@shikijs/engine-javascript": "4.3.1", "@shikijs/engine-oniguruma": "4.3.1", "@shikijs/langs": "4.3.1", "@shikijs/themes": "4.3.1", "@shikijs/types": "4.3.1", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-oR+qDVi2OjX1tmDpyv+3KviX01KzO6Af+0NNnKnsp9491UEGz2YpxTuJboS/6VhYpTdqzmuJBuiTlrAWWJAssw=="], + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + "siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="], - "signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], "simple-code-frame": ["simple-code-frame@1.3.0", "", { "dependencies": { "kolorist": "^1.6.0" } }, "sha512-MB4pQmETUBlNs62BBeRjIFGeuy/x6gGKh7+eRUemn1rCFhqo7K+4slPqsyizCbcbYLnaYqaoZ2FWsZ/jN06D8w=="], @@ -1479,7 +2006,7 @@ "smol-toml": ["smol-toml@1.7.1", "", {}, "sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ=="], - "source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], @@ -1493,16 +2020,26 @@ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + "statuses": ["statuses@2.0.2", "", {}, "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw=="], + "std-env": ["std-env@4.2.0", "", {}, "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw=="], + "stdin-discarder": ["stdin-discarder@0.2.2", "", {}, "sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ=="], + "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + "stringify-object": ["stringify-object@5.0.0", "", { "dependencies": { "get-own-enumerable-keys": "^1.0.0", "is-obj": "^3.0.0", "is-regexp": "^3.1.0" } }, "sha512-zaJYxz2FtcMb4f+g60KsRNFOpVMUyuJgA51Zi5Z1DOTC3S59+OQiVOzE9GZt0x72uBGWKsQIuBKeF9iusmKFsg=="], + "strip-ansi": ["strip-ansi@7.2.0", "", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="], + "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], "strip-json-comments": ["strip-json-comments@2.0.1", "", {}, "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ=="], @@ -1523,12 +2060,22 @@ "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], + "systeminformation": ["systeminformation@5.33.1", "", { "os": "!aix", "bin": { "systeminformation": "lib/cli.js" } }, "sha512-DEN6ICHk3Tk0Uf/hrAHh7xlt7iL5CJFBtPZinA0H62DrGG/KPKqq/Nzj6lCXPS4Ay/sf/14zNnk9LpqKzBIc+w=="], + + "tailwind-merge": ["tailwind-merge@3.6.0", "", {}, "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w=="], + + "tailwindcss": ["tailwindcss@4.1.18", "", {}, "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw=="], + + "tapable": ["tapable@2.3.3", "", {}, "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A=="], + "tar-fs": ["tar-fs@2.1.5", "", { "dependencies": { "chownr": "^1.1.1", "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" } }, "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw=="], "tar-stream": ["tar-stream@2.2.0", "", { "dependencies": { "bl": "^4.0.3", "end-of-stream": "^1.4.1", "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" } }, "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ=="], "tiny-inflate": ["tiny-inflate@1.0.3", "", {}, "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw=="], + "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], + "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinyclip": ["tinyclip@0.1.15", "", {}, "sha512-uo33abH+Ays0xYaDysoBt494Hb3hsEczMpcC0MwFl773pazORx4fmvKhclhR1wonUbB6vvpRsvVMwnhfqeMc+A=="], @@ -1543,6 +2090,10 @@ "tldts-core": ["tldts-core@7.4.9", "", {}, "sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg=="], + "to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "toidentifier": ["toidentifier@1.0.1", "", {}, "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="], + "token-types": ["token-types@6.1.2", "", { "dependencies": { "@borewit/text-codec": "^0.2.1", "@tokenizer/token": "^0.3.0", "ieee754": "^1.2.1" } }, "sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww=="], "toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="], @@ -1559,12 +2110,18 @@ "ts-algebra": ["ts-algebra@2.0.0", "", {}, "sha512-FPAhNPFMrkwz76P7cdjdmiShwMynZYN6SgOujD1urY4oNm80Ou9oMdmbR45LotcKOXoy7wSmHkRFE6Mxbrhefw=="], + "ts-morph": ["ts-morph@26.0.0", "", { "dependencies": { "@ts-morph/common": "~0.27.0", "code-block-writer": "^13.0.3" } }, "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug=="], + + "tsconfig-paths": ["tsconfig-paths@4.2.0", "", { "dependencies": { "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg=="], + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tunnel-agent": ["tunnel-agent@0.6.0", "", { "dependencies": { "safe-buffer": "^5.0.1" } }, "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w=="], "turndown": ["turndown@7.2.4", "", { "dependencies": { "@mixmark-io/domino": "^2.2.0" } }, "sha512-I8yFsfRzmzK0WV1pNNOA4A7y4RDfFxPRxb3t+e3ui14qSGOxGtiSP6GjeX+Y6CHb7HYaFj7ECUD7VE5kQMZWGQ=="], + "type-is": ["type-is@2.1.0", "", { "dependencies": { "content-type": "^2.0.0", "media-typer": "^1.1.0", "mime-types": "^3.0.0" } }, "sha512-faYHw0anBbc/kWF3zFTEnxSFOAGUX9GFbOBthvDdLsIlEoWOFOtS0zgCiQYwIskL9iGXZL3kAXD8OoZ4GmMATA=="], + "typebox": ["typebox@1.1.38", "", {}, "sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA=="], "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], @@ -1581,6 +2138,8 @@ "undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="], + "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], + "unified": ["unified@11.0.5", "", { "dependencies": { "@types/unist": "^3.0.0", "bail": "^2.0.0", "devlop": "^1.0.0", "extend": "^3.0.0", "is-plain-obj": "^4.0.0", "trough": "^2.0.0", "vfile": "^6.0.0" } }, "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA=="], "unifont": ["unifont@0.7.4", "", { "dependencies": { "css-tree": "^3.1.0", "ofetch": "^1.5.1", "ohash": "^2.0.11" } }, "sha512-oHeis4/xl42HUIeHuNZRGEvxj5AaIKR+bHPNegRq5LV1gdc3jundpONbjglKpihmJf+dswygdMJn3eftGIMemg=="], @@ -1595,14 +2154,28 @@ "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + "universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "unpipe": ["unpipe@1.0.0", "", {}, "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="], + "unstorage": ["unstorage@1.17.5", "", { "dependencies": { "anymatch": "^3.1.3", "chokidar": "^5.0.0", "destr": "^2.0.5", "h3": "^1.15.10", "lru-cache": "^11.2.7", "node-fetch-native": "^1.6.7", "ofetch": "^1.5.1", "ufo": "^1.6.3" }, "peerDependencies": { "@azure/app-configuration": "^1.8.0", "@azure/cosmos": "^4.2.0", "@azure/data-tables": "^13.3.0", "@azure/identity": "^4.6.0", "@azure/keyvault-secrets": "^4.9.0", "@azure/storage-blob": "^12.26.0", "@capacitor/preferences": "^6 || ^7 || ^8", "@deno/kv": ">=0.9.0", "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", "@planetscale/database": "^1.19.0", "@upstash/redis": "^1.34.3", "@vercel/blob": ">=0.27.1", "@vercel/functions": "^2.2.12 || ^3.0.0", "@vercel/kv": "^1 || ^2 || ^3", "aws4fetch": "^1.0.20", "db0": ">=0.2.1", "idb-keyval": "^6.2.1", "ioredis": "^5.4.2", "uploadthing": "^7.4.4" }, "optionalPeers": ["@azure/app-configuration", "@azure/cosmos", "@azure/data-tables", "@azure/identity", "@azure/keyvault-secrets", "@azure/storage-blob", "@capacitor/preferences", "@deno/kv", "@netlify/blobs", "@planetscale/database", "@upstash/redis", "@vercel/blob", "@vercel/functions", "@vercel/kv", "aws4fetch", "db0", "idb-keyval", "ioredis", "uploadthing"] }, "sha512-0i3iqvRfx29hkNntHyQvJTpf5W9dQ9ZadSoRU8+xVlhVtT7jAX57fazYO9EHvcRCfBCyi5YRya7XCDOsbTgkPg=="], "update-browserslist-db": ["update-browserslist-db@1.3.0", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA=="], + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + + "use-stick-to-bottom": ["use-stick-to-bottom@1.1.6", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-z3Up8jYQGTkUCsGBnwg6/wj70KgXoW5Kz1AAc1j8MtQuYMBo6ZsdhrIXoegxa7gaMMilgQYyTohTrt3p94jHog=="], + "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], "uuid": ["uuid@14.0.1", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-6ZxzVpzDXDa3bJWaHilVayA+BH/1zmxCJoVgvmqJnid/gPoKHxUrS/aC/T6LGQtNHT+XHG9fXPJB4d+IrU30Ew=="], + "validate-npm-package-name": ["validate-npm-package-name@7.0.2", "", {}, "sha512-hVDIBwsRruT73PbK7uP5ebUt+ezEtCmzZz3F59BSr2F6OVFnJ/6h8liuvdLrQ88Xmnk6/+xGGuq+pG9WwTuy3A=="], + + "vary": ["vary@1.1.2", "", {}, "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="], + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], "vfile-location": ["vfile-location@5.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile": "^6.0.0" } }, "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg=="], @@ -1641,6 +2214,8 @@ "ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], + "wsl-utils": ["wsl-utils@0.3.1", "", { "dependencies": { "is-wsl": "^3.1.0", "powershell-utils": "^0.1.0" } }, "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg=="], + "xml-name-validator": ["xml-name-validator@5.0.0", "", {}, "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg=="], "xml-naming": ["xml-naming@0.3.0", "", {}, "sha512-ghig2TBE/H11aOVgmahA3MhimvkBr6JIYknH/Dhdk10nXwdbIqBJsbfMxpvFPG8bAw77gN29aQWvKpmVoPlvPQ=="], @@ -1661,6 +2236,10 @@ "yocto-queue": ["yocto-queue@1.2.2", "", {}, "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ=="], + "yocto-spinner": ["yocto-spinner@1.2.2", "", { "dependencies": { "yoctocolors": "^2.1.1" } }, "sha512-DODGl1wJjA/s5pnJFKau9lIYHT81lnhob1i3e1TjxZRxEhWRKl74nTbWE6H5KlkViQQTo/Z29YFdxzTZAMY3ng=="], + + "yoctocolors": ["yoctocolors@2.2.0", "", {}, "sha512-xYqdZFUK/VYazNl/oCDYN+3WloWQwMfZxBoiNt6qNyk+xfOdi598muWE42rNZFp1kNOiqW936q5RhUdnpqElSg=="], + "zimmerframe": ["zimmerframe@1.1.4", "", {}, "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ=="], "zod": ["zod@4.2.0", "", {}, "sha512-Bd5fw9wlIhtqCCxotZgdTOMwGm1a0u75wARVEY9HMs1X17trvA/lMi4+MGK5EUfYkXVTbX8UDiDKW4OgzHVUZw=="], @@ -1681,10 +2260,24 @@ "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "@bruits/satteri-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], "@bruits/satteri-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + "@dotenvx/dotenvx/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "@dotenvx/dotenvx/execa": ["execa@5.1.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^6.0.0", "human-signals": "^2.1.0", "is-stream": "^2.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^4.0.1", "onetime": "^5.1.2", "signal-exit": "^3.0.3", "strip-final-newline": "^2.0.0" } }, "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg=="], + + "@dotenvx/dotenvx/ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "@dotenvx/dotenvx/open": ["open@8.4.2", "", { "dependencies": { "define-lazy-prop": "^2.0.0", "is-docker": "^2.1.1", "is-wsl": "^2.2.0" } }, "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ=="], + + "@dotenvx/dotenvx/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], + + "@dotenvx/dotenvx/which": ["which@4.0.0", "", { "dependencies": { "isexe": "^3.1.1" }, "bin": { "node-which": "bin/which.js" } }, "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg=="], + "@earendil-works/pi-coding-agent/semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], "@earendil-works/pi-coding-agent/undici": ["undici@8.5.0", "", {}, "sha512-xamtWoB1EshgjpmlXd7GGm2VfdDtw1+rD8uhry8pSNW3If6S8E0m2T2+orSKeZXEn/aPJMviCpDBA65WJt8zhg=="], @@ -1697,6 +2290,8 @@ "@modelcontextprotocol/core/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + "@modelcontextprotocol/sdk/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + "@modelcontextprotocol/server/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], "@preact/preset-vite/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], @@ -1709,6 +2304,22 @@ "@rolldown/binding-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + "@tailwindcss/node/lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], + + "@tailwindcss/node/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" }, "bundled": true }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.11.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.2.0", "", { "dependencies": { "@tybys/wasm-util": "^0.10.3" }, "peerDependencies": { "@emnapi/core": "^2.0.0-alpha.3", "@emnapi/runtime": "^2.0.0-alpha.3" }, "bundled": true }, "sha512-kDoONqMa+VnZ4vvvu/ZUurpJ4gkZU57e7g69qpNgWhYcZFPUHZM2CEMKm+cG6ufDVALbjMvfmMjFVqaK7uEMnA=="], + + "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.3", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg=="], + + "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@testing-library/dom/aria-query": ["aria-query@5.3.0", "", { "dependencies": { "dequal": "^2.0.3" } }, "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], @@ -1727,54 +2338,144 @@ "astro/zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + "body-parser/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + + "conf/ajv-formats": ["ajv-formats@2.1.1", "", { "dependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], + + "conf/json-schema-typed": ["json-schema-typed@7.0.3", "", {}, "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A=="], + "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], "data-urls/whatwg-url": ["whatwg-url@16.0.1", "", { "dependencies": { "@exodus/bytes": "^1.11.0", "tr46": "^6.0.0", "webidl-conversions": "^8.0.1" } }, "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw=="], "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], + "dot-prop/is-obj": ["is-obj@2.0.0", "", {}, "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w=="], + + "enquirer/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="], + "hast-util-from-html/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], "hast-util-raw/parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + "is-inside-container/is-docker": ["is-docker@3.0.0", "", { "bin": { "is-docker": "cli.js" } }, "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ=="], + + "is-wsl/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + "just-bash/ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="], "just-bash/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], + "log-symbols/is-unicode-supported": ["is-unicode-supported@1.3.0", "", {}, "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="], + + "micromatch/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], + "node-abi/semver": ["semver@7.8.0", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA=="], + "npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="], + + "onetime/mimic-fn": ["mimic-fn@2.1.0", "", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + + "p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + "p-retry/retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], "parse-entities/@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "playwright/fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="], + "prompts/kleur": ["kleur@3.0.3", "", {}, "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w=="], + + "proper-lockfile/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + "rc/ini": ["ini@1.3.8", "", {}, "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="], + "restore-cursor/onetime": ["onetime@7.0.0", "", { "dependencies": { "mimic-function": "^5.0.0" } }, "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ=="], + "seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="], + "shadcn/undici": ["undici@7.29.0", "", {}, "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw=="], + + "shadcn/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], "svelte/aria-query": ["aria-query@5.3.1", "", {}, "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g=="], "svelte/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "svgo/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "type-is/content-type": ["content-type@2.0.0", "", {}, "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ=="], + "vite-prerender-plugin/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + "vite-prerender-plugin/source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="], + "vitest/magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + "wsl-utils/is-wsl": ["is-wsl@3.1.1", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw=="], + "@bruits/satteri-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + "@dotenvx/dotenvx/execa/get-stream": ["get-stream@6.0.1", "", {}, "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg=="], + + "@dotenvx/dotenvx/execa/human-signals": ["human-signals@2.1.0", "", {}, "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw=="], + + "@dotenvx/dotenvx/execa/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "@dotenvx/dotenvx/execa/npm-run-path": ["npm-run-path@4.0.1", "", { "dependencies": { "path-key": "^3.0.0" } }, "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw=="], + + "@dotenvx/dotenvx/execa/signal-exit": ["signal-exit@3.0.7", "", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "@dotenvx/dotenvx/execa/strip-final-newline": ["strip-final-newline@2.0.0", "", {}, "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA=="], + + "@dotenvx/dotenvx/open/define-lazy-prop": ["define-lazy-prop@2.0.0", "", {}, "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="], + + "@dotenvx/dotenvx/open/is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + + "@dotenvx/dotenvx/which/isexe": ["isexe@3.1.5", "", {}, "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w=="], + "@prefresh/vite/@rollup/pluginutils/picomatch": ["picomatch@2.3.2", "", {}, "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA=="], "@rolldown/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="], + "@tailwindcss/node/lightningcss/lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], + + "@tailwindcss/node/lightningcss/lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="], + + "@tailwindcss/node/lightningcss/lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="], + + "@tailwindcss/node/lightningcss/lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="], + + "@tailwindcss/node/lightningcss/lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="], + + "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="], + + "@tailwindcss/node/lightningcss/lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="], + + "@tailwindcss/node/lightningcss/lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="], + + "@tailwindcss/node/lightningcss/lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="], + + "@tailwindcss/node/lightningcss/lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="], + + "@tailwindcss/node/lightningcss/lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/core": ["@emnapi/core@2.0.0-alpha.3", "", { "dependencies": { "@emnapi/wasi-threads": "2.0.1", "tslib": "^2.4.0" } }, "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/runtime": ["@emnapi/runtime@2.0.0-alpha.3", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA=="], + "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], "hast-util-from-html/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], "hast-util-raw/parse5/entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@2.0.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ=="], } } diff --git a/components.json b/components.json new file mode 100644 index 0000000..85ed348 --- /dev/null +++ b/components.json @@ -0,0 +1,27 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "radix-nova", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "", + "css": "src/styles.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "rtl": false, + "menuColor": "default", + "menuAccent": "subtle", + "aliases": { + "components": "@/components", + "utils": "@/lib/class-names", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": { + "@ai-elements": "https://ai-sdk.dev/elements/api/registry/{name}.json" + } +} diff --git a/docs/performance.md b/docs/performance.md index 8d992f9..7280b75 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -15,6 +15,11 @@ must stay within these user-visible classes: initial CSS at or below 25 KiB gzip; - composer p95 acknowledgement within 50 ms and ordinary interaction within 100 ms; +- after Send, the submitted message, responding state, and cancellation control + appear within 100 ms; deterministic agent activity appears within 500 ms; +- a deterministic schema-interface request visibly changes the running canvas + within 2,500 ms, including controller, sandbox, validation, checkpoint, and + render work; - text/CSS patch within 150 ms and component patch within 500 ms; - external candidate rebuild and representative complete Markdown within 1,000 ms; @@ -29,8 +34,9 @@ must stay within these user-visible classes: the release repetition run. The budgets include Flect orchestration and rendering, not provider inference -latency. Model latency is reported separately and never hidden by extending a -spinner budget. +latency. The deterministic canvas-change fixture supplies bounded agent events +without a provider call. Live model latency is reported separately and never +hidden by extending a spinner budget. ## Measurement contract @@ -50,6 +56,11 @@ at least once per gate. Warm target switching uses multiple samples and fails on the worst sample; release dogfood records three native samples and uses the median while also rejecting any sample above 150 percent of its budget. +Logical time-dependent Effect workflows use Effect test services such as +`TestClock`. User-visible acknowledgement, activity, and canvas-change budgets +use Chromium's monotonic `performance.now()` around rendered DOM observations; +advancing a simulated clock cannot prove a paint or interaction deadline. + The dedicated supported-device browser run and release dogfood fail warm activation at the exact 300 ms product threshold. Shared hosted CI cannot be a hardware baseline: it reports that same metric, restores the browser cache diff --git a/docs/verification/2026-08-12-pr-39-handoff-verification.md b/docs/verification/2026-08-12-pr-39-handoff-verification.md new file mode 100644 index 0000000..808cdd6 --- /dev/null +++ b/docs/verification/2026-08-12-pr-39-handoff-verification.md @@ -0,0 +1,105 @@ +# PR #39 handoff verification — 2026-08-12 + +## Scope and result + +- Pull request: [#39](https://github.com/akua-dev/flect/pull/39) +- Revision: working tree based on `db0c8c0` on `codex/shadcn-ui-system`; the + final commit and hosted gate are recorded in PR #39 +- Host: Apple Silicon macOS, Bun 1.3.14, Chromium 151 +- Scope: the PR-description P0/P1 handoff items that can be proved on this + host, plus the locally discovered product regressions they exposed + +This evidence supplements, rather than changes, the immutable AI Elements +baseline in +[`2026-08-12-shadcn-ai-elements-verification.md`](2026-08-12-shadcn-ai-elements-verification.md). + +## Proven on this host + +| Handoff item | Classification | Public evidence | +| --- | --- | --- | +| Authenticated Pi session | proven | `bun run test:pi-smoke` completed a private App turn and Shaper proposal-command turn. No credentials or model output were recorded. | +| Browser product loop | proven | Production browser inspection opened the deferred workspace, selected an authenticated Pi model, created a session (`201`), and received the bounded `OK` reply to a private prompt. Safe-mode restore returned the protected workspace. | +| Git/recovery continuity | proven | `PATH=/Users/robin/.cargo/bin:$PATH bun run test:desktop:local` passed against a random-ID, ad-hoc-signed bundle: editable first draft, sidecar loss survival, restored draft, one restarted sidecar, and one native window. | +| Session ownership/cancellation | implemented and automated | The established contract suite covers isolated App/Preview/Shaper session slots, Effect-fiber cancellation, pending shell cleanup, and busy conflicts. `bun run check` passed 891 tests with one intentional skip. This is not a substitute for an AgentOS-cluster repeated-workspace run. | +| Deferred-island dependency visibility | proven | `bun run build` emits `islands[0]` in the bundle-gate JSON: sorted entry assets and every measured protected-workspace dependency. The gate continues to enforce the canonical 600 KiB decoded / 200 KiB gzip budget. | + +## Regressions found and fixed + +1. The normal Astro development origins `localhost:4321` and + `127.0.0.1:4321` were missing from the server's strict loopback allowlist. + A real browser therefore received `403 Origin not allowed` when creating a + session. The allowlist now includes only those two loopback origins, with a + HTTP-contract regression test. +2. The packaged macOS verifier assumed a fragile nested accessibility-group + path. It now finds the labelled `Message Flect` text area by its public AX + role and name, and the entire isolated recovery flow passes again. +3. The controlled composer could accept a stale continuity snapshot after a + local edit began. Local typing now owns the visible draft for that mounted + composer; an asynchronous persistence update cannot overwrite it. A + component regression test covers the race. +4. Protected Flect controls were cramped into the conversation rail. Settings + now opens as a dedicated full-height workspace: it fills the left canvas at + wide sizes while the conversation remains on the right, and it takes the + complete viewport at compact sizes. The close action restores focus to the + Settings trigger. A component regression test and production-Chromium flow + verify geometry, compact behavior, and keyboard focus. The workspace also + exposed an existing low-contrast failed-operation label; its semantic + background and neutral text now pass the WCAG A/AA audit. +5. The default interface exposed canvas-only actions before a canvas existed. + The starter state now asks only for the desired outcome, hides selection and + product-action affordances until a real interface is present, and gives the + static home page one concrete creation action. The left product surface no + longer carries a Flect wordmark; Flect remains identified in the agent rail. + The native drag region is now a clear 64 px strip above the product surface. + Targeted component and production-Chromium tests cover the starter state; + the ad-hoc macOS bundle and isolated native lifecycle verifier passed. +6. A generic native-button colour rule could override the primary recovery + action's foreground token. In one appearance this produced light text on a + light `Restore interface` button. Primary decision actions now carry the + intended semantic foreground with matching selector specificity. Production + Chromium checks every enabled recovery decision action in light and dark + appearance, runs Axe's WCAG A/AA audit, and measures the rendered text and + background contrast before and during the primary action's hover state. + The desktop development command now targets Astro's actual loopback dev + origin (`127.0.0.1:4321`), so the development window automatically reloads + interface changes instead of waiting for the unused port 5173. +7. The title-area drag marker previously depended on a declarative region, + while the native build's unused-command hardening removed Tauri's + `start_dragging` command. The visible 64 px title-area handle now invokes + the narrowly permitted native window-drag operation on primary pointer + press, with the declarative region retained as a fallback. The build log + proves that `start_dragging` remains in the signed macOS app; the browser + contract covers the affordance's geometry and the component contract covers + primary versus secondary pointer behavior. + +## Host limits and unproven gates + +- `xcrun xctrace list templates` reports that `xctrace` is unavailable. This + host cannot produce the required Instruments launch, first-input, frame-time, + or INP traces; no native performance claim is made. +- The environment has no AgentOS cluster, no second host, and no Windows or + Linux target. AgentOS concurrent-workspace ownership, supported-device + sleep/wake/offline traces, and Windows/Linux matrices remain external gates. +- Manual macOS VoiceOver, trackpad, drag/drop/file-panel, and clean-machine + distribution evidence remain outside this automated host. Existing issue + #22 and the supported-device work tracked by #36 remain the owning gaps. + +## Required final validation + +`PATH=/Users/robin/.cargo/bin:$PATH bun run check:all` completed successfully +on this working tree: 891 Vitest tests passed with one intentional skip, all 86 +production Chromium workflows passed, 26 Rust tests passed, and the ad-hoc +macOS application bundled successfully. `bun run test:pi-smoke` and +`bun run test:desktop:local` also passed afterward. + +The hosted required quality gate still must pass on the final pushed revision +before merging. Its browser phase supplies the authoritative shared-runner +coverage; this report's live Pi verification deliberately stores no private +transcript. + +## Current repair validation + +On the working tree containing the recovery-contrast repair, `bun run check` +passed with 893 tests and one intentional skip. The focused production-browser +command `bun run test:e2e -- tests/e2e/accessibility.spec.ts` passed all eight +workflows, including the new light/dark recovery contrast and hover checks. diff --git a/docs/verification/2026-08-12-shadcn-ai-elements-verification.md b/docs/verification/2026-08-12-shadcn-ai-elements-verification.md new file mode 100644 index 0000000..c0eba80 --- /dev/null +++ b/docs/verification/2026-08-12-shadcn-ai-elements-verification.md @@ -0,0 +1,82 @@ +# Shadcn AI Elements verification — 2026-08-12 + +## Scope and result + +- Pull request: [#39](https://github.com/akua-dev/flect/pull/39) +- Behavior revision: `4511688` on `codex/shadcn-ui-system` +- Host: Apple Silicon macOS, Bun 1.3.14, Playwright Chromium 151 +- Scope: the protected conversation, messages, composer, reasoning, tool + activity, neutral appearance, accessibility, and activation boundary +- Product-quality criteria reviewed: FQ-13.2–FQ-13.8, FQ-15.1–FQ-15.9, + FQ-18.1–FQ-18.8, and FQ-19.1–FQ-19.7 + +The affected behavior is implemented and its automated Contract, Browser, +Accessibility, performance, Rust-host, and local packaged-build evidence is +green. This report does not classify the criteria as fully `proven`: the exact +published head still requires the hosted pull-request gate, and the existing +manual VoiceOver and supported-device experience residuals remain open. + +The review found that the earlier pull-request head had raised the decoded +protected-client gate from the canonical 600 KiB threshold to 652 KiB. The +final change restores the threshold from `shared/performance-budgets.ts` and +moves the AI Elements conversation timeline behind actual conversation or +activity content. The empty protected composer and model chooser remain +immediately usable; the model chooser was deliberately kept eager after an +experimental deferred version measured 109 ms against the 100 ms interaction +limit. + +## Automated evidence + +`bun run check:all` produced: + +- 889 Vitest tests passed with one intentional skip; +- all 86 production Chromium workflows passed; +- model-menu response of 69 ms; +- cold/warm protected activation of 235/218 ms; +- composer acknowledgement p95 of 4 ms; +- Fast/Slow-4G LCP of 354/1,189 ms with zero CLS and no long task; +- cancellation acknowledgement of 0 ms; and +- 7,752,144 bytes retained across 50 complete cycles, below the 8 MiB + threshold. + +The shell running `check:all` did not include Cargo on `PATH`, so the command +stopped after the complete browser suite. The remaining canonical phases were +then run with the documented toolchain path: + +```bash +PATH=/Users/robin/.cargo/bin:$PATH bun run check:rust +PATH=/Users/robin/.cargo/bin:$PATH bun run build:desktop -- --bundles app +``` + +All 26 Rust tests passed. The release-mode macOS application compiled, bundled, +and received the expected ad-hoc signature. No notarization identity was +present or claimed. + +The final production bundle gate reported: + +| Boundary | Decoded | Gzip | +| --- | ---: | ---: | +| View-only document | 6,849 B | 2,919 B | +| Activation bootstrap | 4,646 B | 2,199 B | +| Initial CSS | 2,976 B | 1,094 B | +| Deferred workspace CSS | 100,550 B | 17,534 B | +| Protected pre-tool client | 612,799 B | 191,277 B | + +The protected client is below the unchanged canonical limits of 614,400 +decoded bytes and 204,800 gzip bytes. Shell, compiler, package, Worker, and +Wasm substrates remain separate on-demand boundaries. + +The model-menu performance workflow was also repeated three times after the +final eager-control decision. It passed at 47, 58, and 47 ms. + +## Limitations and release impact + +- The automated browser coverage proves keyboard behavior, focus restoration, + scroll retention, WCAG checks, reflow, reduced motion, forced colors, and + light/dark contrast. It does not replace the manual VoiceOver walkthrough + owned by issue #22. +- The local packaged build proves compilation and ad-hoc signing, not + Developer ID signing, notarization, clean-machine distribution, or the + supported-device experience matrix owned by issues #23 and #36. +- The exact pull-request head must receive the required hosted `Flect quality + gate` before #39 is ready to merge. diff --git a/docs/verification/2026-08-13-chat-turn-folding-verification.md b/docs/verification/2026-08-13-chat-turn-folding-verification.md new file mode 100644 index 0000000..42d121b --- /dev/null +++ b/docs/verification/2026-08-13-chat-turn-folding-verification.md @@ -0,0 +1,62 @@ +# Chat turn-folding verification — 2026-08-13 + +## Scope and result + +- Pull request: [#39](https://github.com/akua-dev/flect/pull/39) +- Revision: working tree based on `fb20e26` on `codex/shadcn-ui-system`; the + final commit and hosted gate are recorded in PR #39 +- Host: Apple Silicon macOS, Bun 1.3.14, Playwright Chromium 151 +- Scope: typed conversation-turn identity, persisted turn continuity, + chronological Prompt → Work → Answer rendering, and compact historical turns +- Product-quality criteria reviewed: FQ-13, FQ-18, and FQ-19 + +Every new App Agent and Shaper operation now projects one typed operation ID +onto its prompt, tool activity, and final response. The same ID survives the +bounded continuity projection and restore path. The renderer therefore groups +work by the turn that caused it instead of guessing from adjacency or +timestamps. + +Completed earlier turns fold their prompt and tool work behind one quiet +`Asked …` disclosure while leaving their final assistant response visible. +The latest turn remains expanded and follows the semantic order Prompt → Work +→ Answer, including while the assistant response is still streaming. Legacy +saved messages without a turn ID remain readable and are not assigned to a +guessed turn. + +## Observable evidence + +- Effect Schema and runtime tests prove that prompt, tool activity, and final + response share one operation-backed turn ID and that consecutive operations + receive distinct IDs. +- Continuity tests round-trip turn IDs through projection and restore. +- Rendered component tests prove an earlier prompt and its work are hidden by + default, its final answer remains visible, expansion restores the context, + and the latest typed turn renders Prompt → Work → Answer. +- A production-Chromium workflow completes two routed turns, observes the + earlier `Asked …` disclosure, keeps the earlier final answer visible, opens + the disclosure, and repeats the assertions after reload. +- The running native development app was inspected with the current hot-loaded + shell for overlay containment. Its public `flect` command-line link is not + installed and local control is disabled, so native turn submission was not + claimed as evidence; no private runtime or storage path was used instead. + +## Validation + +- `bun run check` passed: Effect checkout and concurrency policy, generated + Flect skill, quality coverage, Biome, TypeScript, and 911 Vitest tests passed + with one intentional skip. +- The full production-Chromium run passed 92 of 93 workflows on its first run. + The remaining existing warm-activation budget sampled 336 ms against its + 300 ms limit; its immediate isolated rerun passed at 239 ms (cold activation + 260 ms). All chat-turn workflows passed in both focused and full runs. +- `bun run check:rust` passed all 26 Rust tests. +- `bun run build:desktop -- --bundles app` produced an ad-hoc-signed macOS + application successfully. + +## Limitations + +- This evidence does not replace the manual VoiceOver walkthrough, supported + device matrix, Developer ID signing, notarization, or clean-machine checks + owned by existing release issues. +- The exact pushed revision still requires the hosted `Flect quality gate` + before merge. diff --git a/docs/verification/2026-08-13-chat-worklog-recovery-verification.md b/docs/verification/2026-08-13-chat-worklog-recovery-verification.md new file mode 100644 index 0000000..793c965 --- /dev/null +++ b/docs/verification/2026-08-13-chat-worklog-recovery-verification.md @@ -0,0 +1,69 @@ +# Chat work-log and recovery verification — 2026-08-13 + +## Scope and result + +- Pull request: [#39](https://github.com/akua-dev/flect/pull/39) +- Revision: working tree based on `82fdd97` on `codex/shadcn-ui-system`; the + final commit and hosted gate are recorded in PR #39 +- Host: Apple Silicon macOS, Bun 1.3.14, Playwright Chromium 151 +- Scope: compact agent work, final-answer prominence, rail containment, + recovery language, immediate send feedback, and the native development + startup path +- Product-quality criteria reviewed: FQ-02.2, FQ-05.4, FQ-13.2–FQ-13.6, + FQ-18.3, FQ-18.5, FQ-18.7, and FQ-19.1–FQ-19.4, FQ-19.6–FQ-19.7 + +The chat now keeps consecutive tool activity behind one quiet `Worked for …` +disclosure and leaves the final assistant answer visible. Expanded command +rows are borderless; command output uses one inset rule instead of nested +cards. Command names and durations remain contained at rail width. The canvas +and agent overlay no longer have a vertical separator crossing the shell's +rounded edge. + +Recovery is named for its outcome rather than exposing an internal mode. +Technical continuity reasons remain available to deterministic recovery code +but are not rendered as user-facing instructions. The protected surface says +what happened, preserves the last working interface, and offers restore, +backup, discard, and retry actions. + +## Observable evidence + +- A production-Chromium workflow sends a prompt, observes the immediate busy + state, waits for the changed canvas and final answer, proves the completed + work is collapsed, expands it, and measures every command row and detail + edge for containment. +- The established performance workflow measured visible send acknowledgement + before the canvas completed; its timing is emitted by the canonical full + gate rather than asserted from source text. +- Light and dark recovery workflows run Axe WCAG A/AA checks and rendered + foreground/background contrast checks, including the primary recovery + action's hover state. +- Embedded AXI, portable-extension, sharing, and chronological-conversation + workflows open the collapsed work disclosure before inspecting bounded + command evidence. Completion is otherwise proved through the visible final + outcome and the re-enabled composer. +- The native Tauri development app was restarted against Astro's loopback dev + origin, accepted the prompt `Replace the canvas with a centered heading that + says Chat flow verified.`, showed an immediate running send control, and + rendered `Chat flow verified.` on the live canvas. No private model output or + credentials are recorded here. +- Vite now warms the lazy Wasm Git browser entry before serving the native + shell. A clean native restart hydrated successfully without the prior + `Outdated Optimize Dep` invalidation during workspace activation. + +## Limitations + +- This evidence does not replace the manual VoiceOver walkthrough, supported + device matrix, Developer ID signing, notarization, or clean-machine checks + owned by the existing release issues. +- The exact pushed revision still requires the hosted `Flect quality gate` + before merge. + +## Required final validation + +`PATH=/Users/robin/.cargo/bin:$PATH bun run check:all` passed on this working +tree: 909 Vitest tests passed with one intentional skip, all 93 production +Chromium workflows passed, all 26 Rust tests passed, and the ad-hoc-signed +macOS application bundled successfully. The response workflow measured 19 ms +to visible send acknowledgement, 23 ms to the first visible activity, and 306 +ms to the completed canvas change. The exact pushed revision still requires +the hosted pull-request gate. diff --git a/package.json b/package.json index d5753e3..b858b53 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "prepare": "./scripts/prepare-effect.sh", "dev": "concurrently --kill-others --names runtime,shell \"bun run dev:server\" \"bun run dev:web\"", "dev:server": "bun --watch server/index.ts", - "dev:web": "ASTRO_TELEMETRY_DISABLED=1 astro dev", + "dev:web": "ASTRO_TELEMETRY_DISABLED=1 astro dev --host 127.0.0.1", "dev:desktop": "bun run build:sidecar && tauri dev", "build": "bun run build:product && tsc -b && ASTRO_TELEMETRY_DISABLED=1 astro build && bun run check:bundle", "build:spa": "bun run build:product && tsc -b && vite build --outDir dist-spa", @@ -55,6 +55,7 @@ "@flect/product": "workspace:*", "@jitl/quickjs-ng-wasmfile-release-sync": "0.32.0", "@modelcontextprotocol/server": "2.0.0", + "@radix-ui/react-use-controllable-state": "1.2.6", "@riftydev/npm-client": "0.2.0", "@riftydev/runtime-js": "0.2.0", "@riftydev/runtime-wasi": "0.2.0", @@ -65,12 +66,16 @@ "@types/semver": "7.7.1", "@vue/compiler-sfc": "3.5.41", "acorn": "8.18.0", + "class-variance-authority": "0.7.1", + "clsx": "2.1.1", "effect": "4.0.0-beta.102", "esbuild-wasm": "0.28.1", "fflate": "0.8.3", "just-bash": "3.2.0", + "lucide-react": "1.30.0", "preact": "10.29.8", "quickjs-emscripten-core": "0.32.0", + "radix-ui": "1.6.7", "react": "19.2.8", "react-dom": "19.2.8", "react-markdown": "10.1.0", @@ -83,6 +88,7 @@ "shiki": "4.3.1", "svelte": "5.56.8", "typebox": "1.1.38", + "use-stick-to-bottom": "1.1.6", "wasm-git": "0.0.17", "zod": "4.2.0" }, @@ -93,6 +99,7 @@ "@effect/vitest": "4.0.0-beta.102", "@modelcontextprotocol/client": "2.0.0", "@playwright/test": "1.62.0", + "@tailwindcss/vite": "4.1.18", "@tauri-apps/cli": "2.11.4", "@testing-library/jest-dom": "7.0.0", "@testing-library/react": "16.3.2", @@ -105,6 +112,8 @@ "astro": "7.2.0", "concurrently": "10.0.4", "jsdom": "30.0.1", + "shadcn": "4.16.2", + "tailwindcss": "4.1.18", "typescript": "7.0.2", "vite": "8.1.5", "vitest": "4.1.10", diff --git a/scripts/check-browser-bundle.ts b/scripts/check-browser-bundle.ts index 91f2f44..d7519ba 100644 --- a/scripts/check-browser-bundle.ts +++ b/scripts/check-browser-bundle.ts @@ -1,9 +1,16 @@ -import { basename, dirname, join, resolve } from "node:path"; +import { basename, dirname, join, relative, resolve } from "node:path"; import { parse } from "acorn"; +import { FlectPerformanceBudgets } from "../shared/performance-budgets"; const DIST = join(import.meta.dir, "..", "dist"); const ASSETS = join(DIST, "assets"); const KIB = 1_024; +const WORKSPACE_CSS_GZIP_BUDGET = 20 * KIB; +const WORKSPACE_CSS_DECODED_BUDGET = 112 * KIB; +const WORKSPACE_GZIP_BUDGET = + FlectPerformanceBudgets.browser.initialShellGzipBytes; +const WORKSPACE_DECODED_BUDGET = + FlectPerformanceBudgets.browser.initialShellDecodedBytes; const fail = (message: string): never => { throw new Error(`Browser bundle gate failed: ${message}`); @@ -65,6 +72,23 @@ const graphSize = async (paths: ReadonlySet) => { return { decoded, gzip }; }; +const graphDependencies = async (paths: ReadonlySet) => { + const dependencies: Array<{ + readonly asset: string; + readonly decoded: number; + readonly gzip: number; + }> = []; + for (const path of [...paths].sort((left, right) => + left.localeCompare(right), + )) { + dependencies.push({ + asset: relative(DIST, path), + ...(await size(path)), + }); + } + return dependencies; +}; + const htmlPath = join(DIST, "index.html"); const html = await Bun.file(htmlPath).text(); const initialReferences = [...html.matchAll(/(?:src|href)="([^"]+)"/g)].map( @@ -169,15 +193,21 @@ if (initialNames.includes(workspaceCssReference)) { fail("view-only HTML eagerly references workspace CSS"); } const workspaceCss = await size(assetPath(`/assets/${workspaceCssReference}`)); -if (workspaceCss.gzip > 16 * KIB || workspaceCss.decoded > 80 * KIB) { +if ( + workspaceCss.gzip > WORKSPACE_CSS_GZIP_BUDGET || + workspaceCss.decoded > WORKSPACE_CSS_DECODED_BUDGET +) { fail( - `deferred workspace CSS is ${workspaceCss.gzip} bytes gzip / ${workspaceCss.decoded} decoded (limits 16384 / 81920)`, + `deferred workspace CSS is ${workspaceCss.gzip} bytes gzip / ${workspaceCss.decoded} decoded (limits ${WORKSPACE_CSS_GZIP_BUDGET} / ${WORKSPACE_CSS_DECODED_BUDGET})`, ); } const workspace = await graphSize(workspaceGraph); -if (workspace.gzip > 200 * KIB || workspace.decoded > 600 * KIB) { +if ( + workspace.gzip > WORKSPACE_GZIP_BUDGET || + workspace.decoded > WORKSPACE_DECODED_BUDGET +) { fail( - `protected workspace is ${workspace.gzip} bytes gzip / ${workspace.decoded} decoded (limits 204800 / 614400)`, + `protected workspace is ${workspace.gzip} bytes gzip / ${workspace.decoded} decoded (limits ${WORKSPACE_GZIP_BUDGET} / ${WORKSPACE_DECODED_BUDGET})`, ); } @@ -216,6 +246,20 @@ console.log( ...workspace, modules: workspaceGraph.size, }, + islands: [ + { + name: "flect-workspace", + entryAssets: [ + relative(DIST, assetPath(componentReference)), + relative(DIST, assetPath(rendererReference)), + relative( + DIST, + assetPath(`/assets/${workspaceActivationReference}`), + ), + ].sort((left, right) => left.localeCompare(right)), + dependencies: await graphDependencies(workspaceGraph), + }, + ], onDemandBoundaries: ["shell", "compiler", "package", "worker", "wasm"], }, undefined, diff --git a/scripts/verify-packaged-macos.ts b/scripts/verify-packaged-macos.ts index a67a26c..1cae454 100644 --- a/scripts/verify-packaged-macos.ts +++ b/scripts/verify-packaged-macos.ts @@ -90,15 +90,32 @@ const numberPair = (value: string) => { return [first, second] as const; }; +const textareaOperation = (pid: number, operation: string) => + appleScript(` +tell application "System Events" + tell (first process whose unix id is ${pid}) + tell front window + set composer to missing value + repeat with candidate in (get entire contents) + try + if (role of candidate is "AXTextArea") and (name of candidate is "Message Flect") then + set composer to contents of candidate + exit repeat + end if + end try + end repeat + if composer is missing value then error "The protected composer is missing from the accessibility tree." + tell composer to ${operation} + end tell + end tell +end tell +`); + const textarea = (pid: number, operation: string) => - appleScript( - `${appProcess(pid)} to tell front window to tell group 1 to tell group 1 to tell scroll area 1 to tell UI element 1 to tell group "Flect agent" to tell group 3 to ${operation} of text area "Message Flect"`, - ); + textareaOperation(pid, operation); const setTextareaValue = (pid: number, value: string) => - appleScript( - `${appProcess(pid)} to tell front window to tell group 1 to tell group 1 to tell scroll area 1 to tell UI element 1 to tell group "Flect agent" to tell group 3 to set value of text area "Message Flect" to "${value}"`, - ); + textareaOperation(pid, `set value to "${value}"`); const terminate = async (pid: number | undefined, signal: NodeJS.Signals) => { if (pid === undefined) return; diff --git a/server/app.test.ts b/server/app.test.ts index 0dd507d..e3da2bd 100644 --- a/server/app.test.ts +++ b/server/app.test.ts @@ -182,6 +182,31 @@ describe("Flect HTTP application", () => { }), ); + it.effect("accepts the Astro development origin", () => + Effect.gen(function* () { + const app = yield* useApp(createFakeRuntime()); + const response = yield* send( + app, + request( + "/api/sessions", + { + method: "POST", + body: JSON.stringify({ + model: { provider: "openai-codex", id: "gpt-5.6" }, + }), + }, + "http://localhost:4321", + ), + ); + + expect(response.status).toBe(201); + expect(yield* readJson(response)).toEqual({ + version: 1, + sessionId: "session-1", + }); + }), + ); + it.effect( "ends a revoked browser command poll with an empty successful response", () => diff --git a/server/app.ts b/server/app.ts index b45d260..6879ef1 100644 --- a/server/app.ts +++ b/server/app.ts @@ -56,6 +56,8 @@ const defaultAllowedOrigins = new Set([ "http://localhost:5173", "http://127.0.0.1:4173", "http://localhost:4173", + "http://127.0.0.1:4321", + "http://localhost:4321", "http://127.0.0.1:3210", "http://localhost:3210", ]); diff --git a/server/pi-runtime.test.ts b/server/pi-runtime.test.ts index 1e0eea4..520055d 100644 --- a/server/pi-runtime.test.ts +++ b/server/pi-runtime.test.ts @@ -1303,6 +1303,35 @@ describe("FlectRuntimeLive", () => { }).pipe(Effect.provide(fake.layer)); }); + it.effect("aborts a Shaper that stalls while generating a tool call", () => { + const promptStarted = Deferred.makeUnsafe(); + const promptGate = Deferred.makeUnsafe(); + const fake = createFakePi({ + shaperPromptStarted: promptStarted, + shaperPromptGate: promptGate, + }); + + return Effect.gen(function* () { + const runtime = yield* FlectRuntime; + const sessionId = yield* runtime.createSession(new SessionSelection({})); + const shapeFiber = yield* runtime + .shape(sessionId, "Shape this", defaultInterfaceDocument) + .pipe(Stream.runDrain, Effect.forkChild({ startImmediately: true })); + yield* Deferred.await(promptStarted); + + yield* TestClock.adjust("60 seconds"); + const error = yield* Fiber.join(shapeFiber).pipe(Effect.flip); + + expect(error).toEqual( + new PiOperationFailed({ + operation: "shape", + message: "The model runtime could not complete the request.", + }), + ); + expect(fake.shaperAbort).toHaveBeenCalledOnce(); + }).pipe(Effect.provide(fake.layer)); + }); + it.effect("does not treat Shaper prose as an interface document", () => { const fake = createFakePi({ promptResponse: '{"version":2,"name":"Unsafe","root":{"type":"script"}}', diff --git a/server/pi-runtime.ts b/server/pi-runtime.ts index 77a4095..4d4b999 100644 --- a/server/pi-runtime.ts +++ b/server/pi-runtime.ts @@ -230,6 +230,8 @@ const appSystemPrompt = const shaperSystemPrompt = "You are Flect Shaper, the user-facing interface agent. Help the user describe and shape schema-defined interfaces. You may use the bash tool only inside Flect's disposable browser workspace. It cannot access the host filesystem, credentials, parent UI, canonical workspace, or ambient network; the reserved compatible bun command provides bounded run, build, package, preview, and stop operations. You cannot activate revisions, modify Guardian or safe mode, or load user resources."; +const SHAPER_GENERATION_TIMEOUT = "60 seconds"; + const systemPrompt = (policy: PiSessionPolicy) => { const extensionBoundary = policy.extensions === "enabled" @@ -873,6 +875,13 @@ Run \`flect interface schema\`, write the candidate to \`flect interface propose /workspace/interface.json\` exactly once as your final action. Never return the document as prose, Markdown, or a JSON code block. Preserve stable node IDs when possible. +The candidate must be strict JSON: use double-quoted keys and strings, with +no comments or trailing commas. Use \`flect interface validate\` as the only +validation step. If it fails, rewrite the file with corrected strict JSON and +validate again. Do not probe with \`cat\`, \`node\`, \`python\`, or commands +outside the provided browser shell. +Keep the candidate compact (at most 18 nodes), combine related detail into text +nodes, and complete every Bash tool argument promptly. Never invent executable code, URLs, credentials, HTML, CSS, scripts, tools, or capabilities. @@ -1368,9 +1377,19 @@ export const FlectRuntimeLive = Layer.effect( }, ); - yield* record.shaper + const completion = yield* record.shaper .prompt(promptText) - .pipe(Effect.ensuring(Effect.sync(() => unsubscribe()))); + .pipe( + Effect.timeoutOption(SHAPER_GENERATION_TIMEOUT), + Effect.ensuring(Effect.sync(() => unsubscribe())), + ); + + if (Option.isNone(completion)) { + yield* record.shaper + .abort() + .pipe(Effect.catch(() => Effect.void)); + return yield* Effect.fail(piFailure("shape")); + } if (response.isExceeded()) { return yield* Effect.fail(piFailure("shape")); diff --git a/server/test-runtime.ts b/server/test-runtime.ts index b213227..8b9daff 100644 --- a/server/test-runtime.ts +++ b/server/test-runtime.ts @@ -76,44 +76,110 @@ This fixture is reproducible.[^1] `; -const shapedDocument = (_current: InterfaceDocument): InterfaceDocument => - InterfaceDocumentSchema.make({ - version: 2, - name: "Focused project overview", - root: { - id: "root", - type: "stack", - direction: "column", - gap: "lg", - children: [ - { - id: "headline", - type: "text", - text: "Focused project overview", - style: "headline", - }, - { - id: "prompt", - type: "prompt", - placeholder: "Ask Flect to shape this workspace", +const shapedDocument = ( + _current: InterfaceDocument, + instruction = "", +): InterfaceDocument => + instruction.includes("Northstar AI meeting-notes page") + ? InterfaceDocumentSchema.make({ + version: 2, + name: "Northstar AI meeting notes", + root: { + id: "northstar-root", + type: "stack", + direction: "column", + gap: "lg", + children: [ + { + id: "northstar-nav", + type: "text", + text: "Northstar · Product · Customers · Pricing", + style: "body", + }, + { + id: "northstar-hero", + type: "text", + text: "Meetings, remembered. Work, unblocked.", + style: "headline", + }, + { + id: "northstar-copy", + type: "text", + text: "AI meeting notes that turn every conversation into clear decisions, owners, and next steps.", + style: "body", + }, + { + id: "northstar-actions", + type: "stack", + direction: "row", + gap: "sm", + children: [ + { + id: "northstar-start", + type: "button", + label: "Start free", + action: "shape", + }, + { + id: "northstar-demo", + type: "button", + label: "Watch demo", + action: "shape", + }, + ], + }, + { + id: "northstar-proof", + type: "text", + text: "Trusted by Linear · Vercel · Loom · Notion", + style: "body", + }, + { + id: "northstar-features", + type: "text", + text: "Live capture · Instant summaries · Action tracking", + style: "body", + }, + ], }, - { - id: "secondary-actions", + }) + : InterfaceDocumentSchema.make({ + version: 2, + name: "Focused project overview", + root: { + id: "root", type: "stack", - direction: "row", - gap: "sm", + direction: "column", + gap: "lg", children: [ { - id: "shape-interface", - type: "button", - label: "Shape interface", - action: "shape", + id: "headline", + type: "text", + text: "Focused project overview", + style: "headline", + }, + { + id: "prompt", + type: "prompt", + placeholder: "Ask Flect to shape this workspace", + }, + { + id: "secondary-actions", + type: "stack", + direction: "row", + gap: "sm", + children: [ + { + id: "shape-interface", + type: "button", + label: "Shape interface", + action: "shape", + }, + ], }, ], }, - ], - }, - }); + }); const shellQuote = (value: string) => `'${value.replaceAll("'", `'"'"'`)}'`; @@ -380,7 +446,7 @@ export const FlectTestRuntimeLive = Layer.effect( : Stream.unwrap( Effect.gen(function* () { const document = yield* validateInterfaceDocument(input); - const candidate = shapedDocument(document); + const candidate = shapedDocument(document, instruction); const requestId = `shell-${crypto.randomUUID()}`; const deniedRequestId = `shell-${crypto.randomUUID()}`; const startedAt = Date.now(); @@ -393,6 +459,7 @@ export const FlectTestRuntimeLive = Layer.effect( return next; }); const proposalCommands = [ + "flect interface schema", `printf %s ${shellQuote(JSON.stringify(candidate))} > /workspace/interface.json`, "flect interface validate /workspace/interface.json", "flect interface propose /workspace/interface.json", diff --git a/shared/control.ts b/shared/control.ts index d2ba7cf..0312f54 100644 --- a/shared/control.ts +++ b/shared/control.ts @@ -53,7 +53,7 @@ const Sequence = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0)); const CommandId = Identifier("cmd"); const WorkspaceId = Identifier("workspace"); const ClientId = Identifier("client"); -const OperationId = Identifier("operation"); +export const OperationId = Identifier("operation"); const EventId = Identifier("event"); const ActivityId = Identifier("activity"); const ToolCallId = Schema.String.check( @@ -317,6 +317,13 @@ export class SubmitAppPrompt extends Schema.Class( text: BoundedText(1, 100_000), }) {} +export class SubmitConversationPrompt extends Schema.Class( + "SubmitConversationPrompt", +)({ + type: Schema.Literal("submit-conversation-prompt"), + text: BoundedText(1, 100_000), +}) {} + export class SubmitShaperInstruction extends Schema.Class( "SubmitShaperInstruction", )({ @@ -528,6 +535,7 @@ export const FlectCommand = Schema.Union([ RemovePortableExtension, InvokePortableExtension, SubmitAppPrompt, + SubmitConversationPrompt, SubmitShaperInstruction, RequestShapeHandoff, CancelRole, @@ -590,6 +598,7 @@ export class ToolActivity extends Schema.Class("ToolActivity")({ id: ActivityId, callId: ToolCallId, operationId: OperationId, + turnId: Schema.optionalKey(OperationId), role: InteractiveAgentRole, toolName: BoundedText(1, 80), phase: Schema.Literals(["queued", "running", "succeeded", "failed"]), @@ -618,6 +627,7 @@ export class ConversationMessage extends Schema.Class( )({ version: Schema.Literal(1), id: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(100)), + turnId: Schema.optionalKey(OperationId), role: Schema.Literals(["user", "assistant"]), content: Schema.String.check(Schema.isMaxLength(100_000)), createdAt: Timestamp, diff --git a/shared/performance-budgets.ts b/shared/performance-budgets.ts index 1e1ef08..334b33b 100644 --- a/shared/performance-budgets.ts +++ b/shared/performance-budgets.ts @@ -10,6 +10,9 @@ export const FlectPerformanceBudgets = { initialCssGzipBytes: 25 * 1024, composerP95Ms: 50, interactionLatencyMs: 100, + sendVisualAcknowledgeMs: 100, + firstVisibleActivityMs: 500, + deterministicCanvasChangeMs: 2_500, textCssPatchMs: 150, componentPatchMs: 500, candidateRebuildMs: 1_000, diff --git a/shared/role-continuity.ts b/shared/role-continuity.ts index a96be48..dedc56b 100644 --- a/shared/role-continuity.ts +++ b/shared/role-continuity.ts @@ -1,4 +1,5 @@ import { Effect, Schema, type SchemaAST } from "effect"; +import { OperationId } from "./control"; import { RevisionId } from "./revisions"; export const ROLE_CONTINUITY_MAX_BYTES = 512 * 1_024; @@ -25,6 +26,7 @@ export class ContinuityMessage extends Schema.Class( )({ version: Schema.Literal(1), id: Schema.String.check(Schema.isMinLength(1), Schema.isMaxLength(100)), + turnId: Schema.optionalKey(OperationId), role: Schema.Literals(["user", "assistant"]), content: Schema.String.check(Schema.isMaxLength(100_000)), createdAt: Timestamp, diff --git a/src-tauri/capabilities/main.json b/src-tauri/capabilities/main.json index b387e19..b6d78b0 100644 --- a/src-tauri/capabilities/main.json +++ b/src-tauri/capabilities/main.json @@ -3,5 +3,5 @@ "identifier": "main", "description": "The Flect main window receives only core WebView authority.", "windows": ["main"], - "permissions": ["core:default"] + "permissions": ["core:default", "core:window:allow-start-dragging"] } diff --git a/src-tauri/gen/schemas/capabilities.json b/src-tauri/gen/schemas/capabilities.json index f0c7bd1..9a1f82d 100644 --- a/src-tauri/gen/schemas/capabilities.json +++ b/src-tauri/gen/schemas/capabilities.json @@ -1 +1 @@ -{"main":{"identifier":"main","description":"The Flect main window receives only core WebView authority.","local":true,"windows":["main"],"permissions":["core:default"]}} \ No newline at end of file +{"main":{"identifier":"main","description":"The Flect main window receives only core WebView authority.","local":true,"windows":["main"],"permissions":["core:default","core:window:allow-start-dragging"]}} \ No newline at end of file diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 1ab9483..1cdbe95 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -5,7 +5,7 @@ "identifier": "dev.akua.flect", "build": { "beforeDevCommand": "bun run dev:web", - "devUrl": "http://127.0.0.1:5173", + "devUrl": "http://127.0.0.1:4321", "beforeBuildCommand": "bun run build", "frontendDist": "../dist", "removeUnusedCommands": true @@ -40,6 +40,18 @@ "base-uri": "'none'", "frame-ancestors": "'none'" }, + "devCsp": { + "default-src": "'self' flect-capsule: http://flect-capsule.localhost", + "script-src": "'self' 'wasm-unsafe-eval'", + "style-src": "'self' 'unsafe-inline'", + "img-src": "'self' data:", + "font-src": "'self'", + "connect-src": "ipc: http://ipc.localhost http://127.0.0.1:4321 ws://127.0.0.1:4321", + "worker-src": "'self'", + "object-src": "'none'", + "base-uri": "'none'", + "frame-ancestors": "'none'" + }, "pattern": { "use": "isolation", "options": { diff --git a/src/activation-shell.css b/src/activation-shell.css index 9b24e6b..ca0d3f3 100644 --- a/src/activation-shell.css +++ b/src/activation-shell.css @@ -38,7 +38,7 @@ textarea { .activation-shell { min-height: 100vh; display: grid; - grid-template-rows: 52px 1fr; + grid-template-rows: 64px 1fr; } .activation-shell[hidden], @@ -49,17 +49,26 @@ textarea { .activation-shell__bar { display: flex; align-items: center; + justify-content: center; padding: 0 22px; border-bottom: 1px solid rgba(255, 255, 255, 0.07); + cursor: grab; + user-select: none; -webkit-app-region: drag; + -webkit-user-select: none; } -.activation-shell__wordmark { - color: inherit; - font-size: 14px; - font-weight: 650; - letter-spacing: -0.01em; - text-decoration: none; +.activation-shell__bar::after { + width: 68px; + height: 5px; + border-radius: 999px; + background: currentColor; + content: ""; + opacity: 0.32; +} + +.activation-shell__bar:active { + cursor: grabbing; } .activation-shell__main { @@ -142,6 +151,32 @@ textarea { outline-offset: 3px; } +.activation-shell__examples { + display: flex; + flex-wrap: wrap; + gap: 8px; + padding: 2px 2px 0; +} + +.activation-shell__examples button { + width: auto; + min-height: 36px; + padding: 7px 10px; + border: 1px solid rgba(255, 255, 255, 0.16); + border-radius: 999px; + color: #c7c7c1; + background: transparent; + font-size: 13px; + font-weight: 520; + text-align: left; +} + +.activation-shell__examples button:hover { + border-color: rgba(255, 255, 255, 0.3); + color: #f5f5f3; + background: rgba(255, 255, 255, 0.06); +} + .activation-shell__composer textarea:focus-visible { box-shadow: inset 0 0 0 2px #8ab4ff; } @@ -193,6 +228,18 @@ textarea { background: #000; } + .activation-shell__examples button { + border-color: rgba(0, 0, 0, 0.16); + color: #454540; + background: transparent; + } + + .activation-shell__examples button:hover { + border-color: rgba(0, 0, 0, 0.3); + color: #161615; + background: rgba(0, 0, 0, 0.045); + } + .activation-shell__composer textarea::placeholder { color: #777772; } @@ -200,7 +247,7 @@ textarea { @media (max-width: 600px) { .activation-shell { - grid-template-rows: 48px 1fr; + grid-template-rows: 56px 1fr; } .activation-shell__bar { diff --git a/src/activation/activate-flect.test.ts b/src/activation/activate-flect.test.ts index 2c63941..23fd1ac 100644 --- a/src/activation/activate-flect.test.ts +++ b/src/activation/activate-flect.test.ts @@ -5,12 +5,14 @@ import { fireEvent } from "@testing-library/react"; import { afterEach, describe, expect, it, vi } from "vitest"; import { installFlectActivation, + isFlectDesktop, shouldActivateFlectImmediately, } from "./activate-flect"; afterEach(() => { document.body.innerHTML = ""; document.documentElement.removeAttribute("data-flect-state"); + Reflect.deleteProperty(globalThis, "isTauri"); }); const shell = () => { @@ -27,6 +29,14 @@ const shell = () => { }; describe("Flect activation boundary", () => { + it("recognizes the native host marker exposed by Tauri isolation", () => { + Reflect.set(globalThis, "isTauri", true); + + expect(isFlectDesktop({ hostname: "127.0.0.1", protocol: "http:" })).toBe( + true, + ); + }); + it("keeps an ordinary browser view static until the user activates it", async () => { shell(); const mountFlect = vi.fn(() => Promise.resolve()); @@ -94,6 +104,37 @@ describe("Flect activation boundary", () => { expect(await submitted).toBe("Make a calm notes app"); }); + it("fills a starter idea before the user decides to submit it", () => { + shell(); + const load = vi.fn(() => + Promise.resolve({ mountFlect: vi.fn(() => Promise.resolve()) }), + ); + installFlectActivation({ + document, + location: { + href: "https://flect.local/?view=1", + hostname: "flect.local", + protocol: "https:", + }, + testMode: false, + desktop: false, + load, + }); + const form = document.querySelector("form"); + const prompt = document.querySelector("textarea"); + expect(form).not.toBeNull(); + expect(prompt).not.toBeNull(); + if (form === null || prompt === null) return; + + const example = document.createElement("button"); + example.dataset.flectExample = "A calm project planner for this week"; + form.append(example); + fireEvent.click(example); + + expect(prompt).toHaveValue("A calm project planner for this week"); + expect(load).not.toHaveBeenCalled(); + }); + it.each([ ["test", { href: "https://flect.local/", testMode: true, desktop: false }], ["desktop", { href: "tauri://localhost/", testMode: false, desktop: true }], diff --git a/src/activation/activate-flect.ts b/src/activation/activate-flect.ts index 9e73e31..ecca75b 100644 --- a/src/activation/activate-flect.ts +++ b/src/activation/activate-flect.ts @@ -1,3 +1,5 @@ +import { isNativeHost } from "../lib/native-host"; + export interface FlectClientModule { readonly mountFlect: (root: HTMLElement) => Promise; } @@ -27,12 +29,15 @@ const diagnosticParameters = [ "product-adoption-diagnostic", ] as const; -export const isFlectDesktop = ( - location: Pick = globalThis.location, -) => - "__TAURI_INTERNALS__" in globalThis || - location.protocol === "tauri:" || - location.hostname === "tauri.localhost"; +export const isFlectDesktop = isNativeHost; + +if (import.meta.hot && isFlectDesktop()) { + const reloadNativeWorkspace = () => globalThis.location.reload(); + import.meta.hot.on("vite:beforeUpdate", reloadNativeWorkspace); + import.meta.hot.dispose(() => + import.meta.hot?.off("vite:beforeUpdate", reloadNativeWorkspace), + ); +} export const shouldActivateFlectImmediately = ({ href, @@ -147,6 +152,22 @@ export const installFlectActivation = ( document.addEventListener("pointerdown", (event) => activateFromTarget(event.target), ); + document.addEventListener("click", (event) => { + const target = event.target; + if (!(target instanceof Element)) return; + const example = target.closest("[data-flect-example]"); + const prompt = example?.dataset.flectExample; + if (prompt === undefined || prompt.length === 0) return; + const input = shell.querySelector( + 'textarea[name="prompt"]', + ); + if (input === null) return; + input.value = prompt; + input.focus(); + if (status !== null) { + status.textContent = "Edit this idea or describe the outcome you need."; + } + }); document.addEventListener("submit", (event) => { const form = event.target; if ( diff --git a/src/activation/workspace-activation-runtime.test.ts b/src/activation/workspace-activation-runtime.test.ts new file mode 100644 index 0000000..fdeab5f --- /dev/null +++ b/src/activation/workspace-activation-runtime.test.ts @@ -0,0 +1,37 @@ +// @vitest-environment jsdom + +import { assert, it } from "@effect/vitest"; +import { Effect, Fiber } from "effect"; +import { TestClock } from "effect/testing"; +import { waitForAstroIsland } from "./workspace-activation-runtime"; + +it.effect("completes when the deferred workspace reports readiness", () => + Effect.gen(function* () { + const activation = yield* waitForAstroIsland(document).pipe( + Effect.forkChild, + ); + yield* Effect.yieldNow; + + document.dispatchEvent(new CustomEvent("flect:workspace-ready")); + + yield* Fiber.join(activation); + assert.strictEqual( + document.documentElement.dataset.flectOpenRequested, + "true", + ); + }), +); + +it.effect("fails closed instead of leaving activation pending forever", () => + Effect.gen(function* () { + const activation = yield* waitForAstroIsland(document, "1 second").pipe( + Effect.forkChild, + ); + + yield* TestClock.adjust("1 second"); + const failure = yield* Fiber.join(activation).pipe(Effect.flip); + + assert.strictEqual(failure._tag, "WorkspaceActivationError"); + assert.strictEqual(failure.reason, "timed-out"); + }), +); diff --git a/src/activation/workspace-activation-runtime.ts b/src/activation/workspace-activation-runtime.ts index 0596a9e..a40c413 100644 --- a/src/activation/workspace-activation-runtime.ts +++ b/src/activation/workspace-activation-runtime.ts @@ -1,4 +1,11 @@ -import { Effect } from "effect"; +import { type Duration, Effect, Schema } from "effect"; + +export class WorkspaceActivationError extends Schema.TaggedErrorClass()( + "WorkspaceActivationError", + { + reason: Schema.Literals(["hydration-failed", "timed-out"]), + }, +) {} interface WorkspaceClientModule { readonly mountFlect: (root: HTMLElement) => Promise; @@ -12,14 +19,18 @@ interface ActivateWorkspaceOptions { readonly onError: () => void; } -const errorFrom = (error: unknown, fallback: string) => - error instanceof Error ? error : new Error(fallback); - -const waitForAstroIsland = (document: Document) => - Effect.callback((resume) => { +export const waitForAstroIsland = ( + document: Document, + timeout: Duration.Input = "20 seconds", +) => + Effect.callback((resume) => { const ready = () => resume(Effect.void); const failed = () => - resume(Effect.fail(new Error("Flect workspace hydration failed."))); + resume( + Effect.fail( + WorkspaceActivationError.make({ reason: "hydration-failed" }), + ), + ); document.addEventListener("flect:workspace-ready", ready, { once: true }); document.addEventListener("flect:workspace-error", failed, { once: true }); document.documentElement.dataset.flectOpenRequested = "true"; @@ -28,7 +39,12 @@ const waitForAstroIsland = (document: Document) => document.removeEventListener("flect:workspace-ready", ready); document.removeEventListener("flect:workspace-error", failed); }); - }); + }).pipe( + Effect.timeout(timeout), + Effect.catchTag("TimeoutError", () => + Effect.fail(WorkspaceActivationError.make({ reason: "timed-out" })), + ), + ); export const activateWorkspace = ({ document, @@ -45,8 +61,8 @@ export const activateWorkspace = ({ const { mountFlect } = await load(); await mountFlect(root); }, - catch: (error) => - errorFrom(error, "Flect client module failed to load."), + catch: () => + WorkspaceActivationError.make({ reason: "hydration-failed" }), }) ).pipe( Effect.tap(() => Effect.sync(onReady)), diff --git a/src/app.test.tsx b/src/app.test.tsx index e1427b8..256e97f 100644 --- a/src/app.test.tsx +++ b/src/app.test.tsx @@ -158,7 +158,8 @@ const makeRuntime = (safeMode = false) => { const sequence = current.sequence + 1; const command = envelope.command; const next = - command.type === "submit-shaper-instruction" + command.type === "submit-shaper-instruction" || + command.type === "submit-conversation-prompt" ? (() => { const proposal = InterfaceRevision.make({ version: 1, @@ -273,7 +274,8 @@ describe("App", () => { await waitFor(() => expect( dispatch.mock.calls.some( - ([envelope]) => envelope.command.type === "submit-shaper-instruction", + ([envelope]) => + envelope.command.type === "submit-conversation-prompt", ), ).toBe(true), ); @@ -291,7 +293,7 @@ describe("App", () => { ), ).toBe(false); - await user.click(screen.getByRole("button", { name: "Diagnostics" })); + await user.click(screen.getByRole("button", { name: "Open settings" })); await user.click( await screen.findByRole("button", { name: "Enable local control" }), ); @@ -324,7 +326,7 @@ describe("App", () => { render(); expect( - await screen.findByText("Custom interface state is bypassed."), + await screen.findByText("Your interface is protected."), ).toBeVisible(); expect( screen.getByRole("textbox", { name: "Message Flect" }), diff --git a/src/app.tsx b/src/app.tsx index b6002c9..6a5fb9e 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -44,6 +44,7 @@ import { SetRailCollapsed, SetRailWidth, SubmitAppPrompt, + SubmitConversationPrompt, SubmitShaperInstruction, TestPortableExtension, WorkbenchHandoff, @@ -53,6 +54,7 @@ import { isRollbackAvailable } from "../shared/revisions"; import { ShellPreferencesValue } from "../shared/shell-preferences"; import type { ShapingController } from "./components/agent-rail"; import { RoleAwareShell } from "./components/role-aware-shell"; +import { WindowDragRegion } from "./components/window-drag-region"; import type { AgentWorkspaceController, ConversationMessage, @@ -70,6 +72,7 @@ export interface AppProps { const toMessages = ( messages: ReadonlyArray<{ readonly id: string; + readonly turnId?: string; readonly role: "user" | "assistant"; readonly content: string; readonly createdAt: number; @@ -77,6 +80,7 @@ const toMessages = ( ): ReadonlyArray => messages.map((message) => ({ id: message.id, + ...(message.turnId === undefined ? {} : { turnId: message.turnId }), role: message.role, content: message.content, createdAt: message.createdAt, @@ -150,15 +154,10 @@ export function App({ runtime = flectRuntime, initialPrompt }: AppProps = {}) { } initialPromptSent.current = true; void command( - workspacePhase(snapshot.shaping, false) === "blank" - ? SubmitShaperInstruction.make({ - type: "submit-shaper-instruction", - instruction: initialPrompt, - }) - : SubmitAppPrompt.make({ - type: "submit-app-prompt", - text: initialPrompt, - }), + SubmitConversationPrompt.make({ + type: "submit-conversation-prompt", + text: initialPrompt, + }), ); }, [command, initialPrompt, snapshot]); @@ -240,6 +239,13 @@ export function App({ runtime = flectRuntime, initialPrompt }: AppProps = {}) { enabled: !snapshot.agent.externalExtensions[interactiveRole], }), ), + submitConversation: (text) => + command( + SubmitConversationPrompt.make({ + type: "submit-conversation-prompt", + text, + }), + ), app: { ...app, role: "app", @@ -359,11 +365,7 @@ export function App({ runtime = flectRuntime, initialPrompt }: AppProps = {}) { ) { return (
-
- - Flect - -
+

Opening workspace diff --git a/src/axi/program.test.ts b/src/axi/program.test.ts index c3ca61d..9f91c1d 100644 --- a/src/axi/program.test.ts +++ b/src/axi/program.test.ts @@ -169,6 +169,23 @@ const permission = (state: "granted" | "revoked") => }); describe("Flect AXI program", () => { + it.effect("returns a complete bounded interface authoring contract", () => { + const { layer } = makeGateway(); + return Effect.gen(function* () { + const result = yield* runFlect(["--json", "interface", "schema"]); + + assert.strictEqual(result.exitCode, 0); + assert.include(result.stdout, '"required":["version","name","root"]'); + assert.include(result.stdout, '"required":["id","type","text","style"]'); + assert.include( + result.stdout, + '"required":["id","type","direction","gap","children"]', + ); + assert.include(result.stdout, '"name":"Example"'); + assert.include(result.stdout, '"text":"Example"'); + }).pipe(Effect.provide(layer)); + }); + it.effect( "lists and inspects only bounded protected share projections", () => { diff --git a/src/axi/program.ts b/src/axi/program.ts index a8777f9..b156baf 100644 --- a/src/axi/program.ts +++ b/src/axi/program.ts @@ -69,6 +69,74 @@ const fallbackFailure = (format: AxiFormat) => stderr: "", }); +const interfaceAuthoringContract = { + version: 2, + strict: true, + document: { + required: ["version", "name", "root"], + version: 2, + name: "non-empty string, at most 80 characters", + root: "one interface node", + }, + commonNode: { + required: ["id", "type"], + id: "unique lowercase identifier matching ^[a-z][a-z0-9-]*$, at most 64 characters", + }, + nodes: { + stack: { + required: ["id", "type", "direction", "gap", "children"], + direction: ["row", "column"], + gap: ["sm", "md", "lg"], + children: "0 to 30 interface nodes", + }, + text: { + required: ["id", "type", "text", "style"], + text: "non-empty string, at most 2000 characters", + style: ["headline", "body", "muted"], + }, + prompt: { + required: ["id", "type", "placeholder"], + placeholder: "non-empty string, at most 120 characters", + }, + button: { + required: ["id", "type", "label", "action"], + label: "non-empty string, at most 80 characters", + action: [ + "shape", + "safe-mode", + "accept-revision", + "reject-revision", + "rollback-revision", + ], + }, + divider: { required: ["id", "type"] }, + "agent-panel": { + required: ["id", "type", "title"], + title: "non-empty string, at most 80 characters", + }, + }, + limits: { treeDepth: 10, treeNodes: 100 }, + example: { + version: 2, + name: "Example", + root: { + id: "root", + type: "stack", + direction: "column", + gap: "md", + children: [ + { + id: "headline", + type: "text", + text: "Example", + style: "headline", + }, + ], + }, + }, + next: "Write strict JSON, then run `flect interface validate ` before proposing it.", +}; + const failure = (error: AxiPublicError, format: AxiFormat, exitCode: 1 | 2) => renderAxiFailure(error, format, exitCode).pipe( Effect.orElseSucceed(() => fallbackFailure(format)), @@ -564,18 +632,7 @@ const execute = Effect.fn("Flect.Axi.execute")(function* ( case "interface-inspect": return (yield* gateway.inspect).document; case "interface-schema": - return { - version: 2, - nodeTypes: [ - "stack", - "text", - "prompt", - "button", - "divider", - "agent-panel", - ], - note: "Use `flect interface validate ` before proposing a candidate.", - }; + return interfaceAuthoringContract; case "revision-list": { const shaping = (yield* gateway.inspect).shaping; const revisions = [ diff --git a/src/components/activity-card.test.tsx b/src/components/activity-card.test.tsx index a29a11b..07c8f1c 100644 --- a/src/components/activity-card.test.tsx +++ b/src/components/activity-card.test.tsx @@ -34,10 +34,10 @@ describe("ActivityCard", () => { />, ); - expect(screen.getByText("Bash")).toBeVisible(); - expect(screen.getByText("Failed")).toBeVisible(); + expect(screen.getByText("Command failed")).toBeVisible(); + expect(screen.queryByText("Error")).not.toBeInTheDocument(); await user.click(screen.getByRole("button", { name: /Bash details/i })); - expect(screen.getByText("bun test")).toBeVisible(); + expect(screen.getAllByText("bun test")).toHaveLength(2); expect(screen.getByText("1 test failed")).toBeVisible(); expect(screen.getByText("Exit 1")).toBeVisible(); await user.click(screen.getByRole("button", { name: "Fix with Flect" })); diff --git a/src/components/activity-card.tsx b/src/components/activity-card.tsx index 19c27da..79393d8 100644 --- a/src/components/activity-card.tsx +++ b/src/components/activity-card.tsx @@ -1,4 +1,18 @@ +import { + CheckIcon, + ChevronDownIcon, + CircleIcon, + ClockIcon, + TerminalIcon, + WrenchIcon, + XIcon, +} from "lucide-react"; import type { ToolActivity } from "../../shared/control"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "./ui/collapsible"; const label = (toolName: string) => toolName === "bash" ? "Bash" : toolName === "flect" ? "Flect" : toolName; @@ -12,6 +26,28 @@ const phaseLabel = (phase: ToolActivity["phase"]) => ? "Failed" : "Queued"; +const actionLabel = (activity: ToolActivity) => { + if (activity.toolName !== "bash") return label(activity.toolName); + return activity.phase === "running" + ? "Running command" + : activity.phase === "succeeded" + ? "Ran command" + : activity.phase === "failed" + ? "Command failed" + : "Command queued"; +}; + +const PhaseIcon = ({ phase }: { readonly phase: ToolActivity["phase"] }) => + phase === "running" ? ( + + ) : phase === "succeeded" ? ( + + ) : phase === "failed" ? ( + + ) : ( + + ); + export function ActivityCard({ activity, onFixInShape, @@ -28,25 +64,27 @@ export function ActivityCard({ return (

-
- {/* biome-ignore lint/a11y/useSemanticElements: summary is the native disclosure control; the explicit role keeps it exposed consistently across WebKit and JSDOM. */} - + - + + {detail && ( -
+ {activity.command !== undefined && (
Command @@ -74,6 +112,13 @@ export function ActivityCard({
)}
+ {phaseLabel(activity.phase)} + {activity.durationMs !== undefined && ( + + )} + {activity.resultSummary !== undefined && ( + {activity.resultSummary} + )} {activity.exitCode !== undefined && ( {`Exit ${activity.exitCode}`} )} @@ -84,9 +129,9 @@ export function ActivityCard({ )}
-
+ )} -
+ {activity.phase === "failed" && onFixInShape !== undefined && ( - )} +
); } @@ -601,6 +464,7 @@ export function AgentRail({ useDisabled = false, canvasSelection, selectedNodeId, + starter = false, document, workspace, shaping, @@ -610,6 +474,8 @@ export function AgentRail({ onOpenShareSource, onOpenShareFile, onManageSharedSources, + onOpenSettings, + settingsInDock = false, onRestoreSafeMode, onDecideProductCapability, onRevokeProductCapability, @@ -625,7 +491,7 @@ export function AgentRail({ workspace.app, workspace.previewApp, workspace.shaper, - ] as const; + ]; const preferredController = preview ? workspace.previewApp : useDisabled @@ -656,6 +522,8 @@ export function AgentRail({ isAgentSessionActive(workspace.previewApp.status) || isAgentSessionActive(workspace.shaper.status) || shaping.status === "shaping"; + const showStarterPrompts = starter && messages.length === 0; + const settingsStatus = settingsSummary(diagnostics); const cancel = async () => { const active = conversationControllers.filter((entry) => isAgentSessionActive(entry.status), @@ -682,9 +550,8 @@ export function AgentRail({ : preview && candidateRevisionId !== undefined ? (text: string) => workspace.previewApp.submit(text, document, candidateRevisionId) - : useDisabled - ? shaping.request - : workspace.app.submit; + : (workspace.submitConversation ?? + (useDisabled ? shaping.request : workspace.app.submit)); const externalExtensionsEnabled = workspace.externalExtensions.app && workspace.externalExtensions.shaper; const toggleExternalExtensions = async () => { @@ -976,6 +843,7 @@ export function AgentRail({ aria-label="Flect agent" className="agent-rail" data-mode={mode} + data-status={controller.status} tabIndex={-1} >
@@ -984,6 +852,22 @@ export function AgentRail({ {mode === "safe" ? "Protected shell" : "Live canvas"}
+ {!settingsInDock && + diagnostics !== undefined && + onOpenSettings !== undefined && ( + + )}
- void shaping.fixFailure(activity)} - /> + {messages.length === 0 && activities.length === 0 ? ( + + ) : ( + }> + void shaping.fixFailure(activity)} + /> + + )}
{build !== undefined && build.phase !== "succeeded" && ( @@ -1023,21 +913,25 @@ export function AgentRail({ {mode === "safe" && (
- Custom interface state is bypassed. -

Restore the last-known-good revision to return.

+ Your interface is protected. +

+ Flect temporarily hid custom changes. Restore the last working + interface when you are ready. +

{workspace.continuity?.recovery === undefined - ? `Session continuity generation ${workspace.continuity?.generation ?? 0}, revision ${workspace.continuity?.revisionSequence ?? 0}.` - : `Session continuity needs recovery: ${workspace.continuity.recovery}.`} + ? "Your saved conversation and drafts are available." + : "Saved conversation data needs repair before it can be restored."}
{workspace.continuity?.recovery !== undefined && ( )}
@@ -1324,30 +1218,39 @@ export function AgentRail({ )} {controller.status === "setup-required" && ( -
-
- Connect an agent -

- Choose a Pi-owned provider below. You can write your first - message now; Flect keeps it private until sign-in succeeds. -

-
- } - > - - -
+
+ + + + Connect an agent + + + Sign in once, then tell Flect what you want to make. Your + draft stays private until the connection succeeds. + + + + } + > + + + + +
)} {controller.status === "unavailable" && ( @@ -1384,16 +1287,21 @@ export function AgentRail({
)} - {diagnostics !== undefined && ( - - )} + {settingsInDock && + diagnostics !== undefined && + onOpenSettings !== undefined && + controller.status !== "setup-required" && ( + + )} ; + +export const Conversation = ({ className, ...props }: ConversationProps) => ( + +); + +export type ConversationContentProps = ComponentProps< + typeof StickToBottom.Content +>; + +export const ConversationContent = ({ + className, + ...props +}: ConversationContentProps) => ( + +); + +export type ConversationEmptyStateProps = ComponentProps<"div"> & { + title?: string; + description?: string; + icon?: React.ReactNode; +}; + +export const ConversationEmptyState = ({ + className, + title = "No messages yet", + description = "Start a conversation to see messages here", + icon, + children, + ...props +}: ConversationEmptyStateProps) => ( +
+ {children ?? ( + <> + {icon &&
{icon}
} +
+

{title}

+ {description && ( +

{description}

+ )} +
+ + )} +
+); + +export type ConversationScrollButtonProps = ComponentProps; + +export const ConversationScrollButton = ({ + className, + ...props +}: ConversationScrollButtonProps) => { + const { isAtBottom, scrollToBottom } = useStickToBottomContext(); + + const handleScrollToBottom = useCallback(() => { + scrollToBottom(); + }, [scrollToBottom]); + + return ( + !isAtBottom && ( + + ) + ); +}; diff --git a/src/components/ai-elements/message.tsx b/src/components/ai-elements/message.tsx new file mode 100644 index 0000000..a0e26c0 --- /dev/null +++ b/src/components/ai-elements/message.tsx @@ -0,0 +1,39 @@ +"use client"; + +import type { HTMLAttributes } from "react"; +import { cn } from "@/lib/class-names"; + +export type MessageProps = HTMLAttributes & { + from: "user" | "assistant" | "system"; +}; + +export const Message = ({ className, from, ...props }: MessageProps) => ( +
+); + +export type MessageContentProps = HTMLAttributes; + +export const MessageContent = ({ + children, + className, + ...props +}: MessageContentProps) => ( +
+ {children} +
+); diff --git a/src/components/ai-elements/prompt-input.tsx b/src/components/ai-elements/prompt-input.tsx new file mode 100644 index 0000000..3253d69 --- /dev/null +++ b/src/components/ai-elements/prompt-input.tsx @@ -0,0 +1,203 @@ +"use client"; + +import { CornerDownLeftIcon, SquareIcon, XIcon } from "lucide-react"; +import type { + ComponentProps, + FormEvent, + FormEventHandler, + HTMLAttributes, + KeyboardEventHandler, +} from "react"; +import { useCallback, useState } from "react"; +import { + InputGroup, + InputGroupAddon, + InputGroupButton, + InputGroupTextarea, +} from "@/components/ui/input-group"; +import { Spinner } from "@/components/ui/spinner"; +import { cn } from "@/lib/class-names"; + +export interface PromptInputMessage { + text: string; + files: readonly never[]; +} + +export type PromptInputProps = Omit< + HTMLAttributes, + "onSubmit" +> & { + onSubmit: ( + message: PromptInputMessage, + event: FormEvent, + ) => void; +}; + +export const PromptInput = ({ + className, + onSubmit, + children, + ...props +}: PromptInputProps) => { + const handleSubmit: FormEventHandler = useCallback( + (event) => { + event.preventDefault(); + const formData = new FormData(event.currentTarget); + const message = formData.get("message"); + onSubmit( + { + files: [], + text: typeof message === "string" ? message : "", + }, + event, + ); + }, + [onSubmit], + ); + + return ( +
+ {children} +
+ ); +}; + +export type PromptInputBodyProps = HTMLAttributes; + +export const PromptInputBody = ({ + className, + ...props +}: PromptInputBodyProps) => ( +
+); + +export type PromptInputTextareaProps = ComponentProps< + typeof InputGroupTextarea +>; + +export const PromptInputTextarea = ({ + onKeyDown, + className, + placeholder = "What would you like to know?", + ...props +}: PromptInputTextareaProps) => { + const [isComposing, setIsComposing] = useState(false); + + const handleKeyDown: KeyboardEventHandler = useCallback( + (event) => { + onKeyDown?.(event); + if ( + event.defaultPrevented || + event.key !== "Enter" || + event.shiftKey || + isComposing || + event.nativeEvent.isComposing + ) { + return; + } + event.preventDefault(); + const submitButton = + event.currentTarget.form?.querySelector( + 'button[type="submit"]', + ); + if (submitButton?.disabled !== true) { + event.currentTarget.form?.requestSubmit(); + } + }, + [isComposing, onKeyDown], + ); + + return ( + setIsComposing(false)} + onCompositionStart={() => setIsComposing(true)} + onKeyDown={handleKeyDown} + placeholder={placeholder} + {...props} + /> + ); +}; + +export type PromptInputFooterProps = Omit< + ComponentProps, + "align" +>; + +export const PromptInputFooter = ({ + className, + ...props +}: PromptInputFooterProps) => ( + +); + +export type PromptInputToolsProps = HTMLAttributes; + +export const PromptInputTools = ({ + className, + ...props +}: PromptInputToolsProps) => ( +
+); + +export type PromptInputStatus = "ready" | "submitted" | "streaming" | "error"; + +export type PromptInputSubmitProps = ComponentProps & { + status?: PromptInputStatus; + onStop?: () => void; +}; + +export const PromptInputSubmit = ({ + className, + variant = "default", + size = "icon-sm", + status, + onStop, + onClick, + children, + ...props +}: PromptInputSubmitProps) => { + const isGenerating = status === "submitted" || status === "streaming"; + const handleClick = useCallback( + (event: React.MouseEvent) => { + if (isGenerating && onStop) { + event.preventDefault(); + onStop(); + return; + } + onClick?.(event); + }, + [isGenerating, onClick, onStop], + ); + + let icon = ; + if (status === "submitted") icon = ; + if (status === "streaming") icon = ; + if (status === "error") icon = ; + + return ( + + {children ?? icon} + + ); +}; diff --git a/src/components/ai-elements/reasoning.tsx b/src/components/ai-elements/reasoning.tsx new file mode 100644 index 0000000..9cbdac2 --- /dev/null +++ b/src/components/ai-elements/reasoning.tsx @@ -0,0 +1,191 @@ +"use client"; + +import { useControllableState } from "@radix-ui/react-use-controllable-state"; +import { BrainIcon, ChevronDownIcon } from "lucide-react"; +import type { ComponentProps, ReactNode } from "react"; +import { + createContext, + memo, + useCallback, + useContext, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { Collapsible, CollapsibleTrigger } from "@/components/ui/collapsible"; +import { cn } from "@/lib/class-names"; + +interface ReasoningContextValue { + isStreaming: boolean; + isOpen: boolean; + setIsOpen: (open: boolean) => void; + duration: number | undefined; +} + +const ReasoningContext = createContext(null); + +export const useReasoning = () => { + const context = useContext(ReasoningContext); + if (!context) { + throw new Error("Reasoning components must be used within Reasoning"); + } + return context; +}; + +export type ReasoningProps = ComponentProps & { + isStreaming?: boolean; + open?: boolean; + defaultOpen?: boolean; + onOpenChange?: (open: boolean) => void; + duration?: number; +}; + +const AUTO_CLOSE_DELAY = 1000; +const MS_IN_S = 1000; + +export const Reasoning = memo( + ({ + className, + isStreaming = false, + open, + defaultOpen, + onOpenChange, + duration: durationProp, + children, + ...props + }: ReasoningProps) => { + const resolvedDefaultOpen = defaultOpen ?? isStreaming; + // Track if defaultOpen was explicitly set to false (to prevent auto-open) + const isExplicitlyClosed = defaultOpen === false; + + const [isOpen, setIsOpen] = useControllableState({ + defaultProp: resolvedDefaultOpen, + onChange: onOpenChange, + prop: open, + }); + const [duration, setDuration] = useControllableState({ + defaultProp: undefined, + prop: durationProp, + }); + + const hasEverStreamedRef = useRef(isStreaming); + const [hasAutoClosed, setHasAutoClosed] = useState(false); + const startTimeRef = useRef(null); + + // Track when streaming starts and compute duration + useEffect(() => { + if (isStreaming) { + hasEverStreamedRef.current = true; + if (startTimeRef.current === null) { + startTimeRef.current = Date.now(); + } + } else if (startTimeRef.current !== null) { + setDuration(Math.ceil((Date.now() - startTimeRef.current) / MS_IN_S)); + startTimeRef.current = null; + } + }, [isStreaming, setDuration]); + + // Auto-open when streaming starts (unless explicitly closed) + useEffect(() => { + if (isStreaming && !isOpen && !isExplicitlyClosed) { + setIsOpen(true); + } + }, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]); + + // Auto-close when streaming ends (once only, and only if it ever streamed) + useEffect(() => { + if ( + hasEverStreamedRef.current && + !isStreaming && + isOpen && + !hasAutoClosed + ) { + const timer = setTimeout(() => { + setIsOpen(false); + setHasAutoClosed(true); + }, AUTO_CLOSE_DELAY); + + return () => clearTimeout(timer); + } + }, [isStreaming, isOpen, setIsOpen, hasAutoClosed]); + + const handleOpenChange = useCallback( + (newOpen: boolean) => { + setIsOpen(newOpen); + }, + [setIsOpen], + ); + + const contextValue = useMemo( + () => ({ duration, isOpen, isStreaming, setIsOpen }), + [duration, isOpen, isStreaming, setIsOpen], + ); + + return ( + + + {children} + + + ); + }, +); + +export type ReasoningTriggerProps = ComponentProps< + typeof CollapsibleTrigger +> & { + getThinkingMessage?: (isStreaming: boolean, duration?: number) => ReactNode; +}; + +const defaultGetThinkingMessage = (isStreaming: boolean, duration?: number) => { + if (isStreaming || duration === 0) { + return Thinking...; + } + if (duration === undefined) { + return

Thought for a few seconds

; + } + return

Thought for {duration} seconds

; +}; + +export const ReasoningTrigger = memo( + ({ + className, + children, + getThinkingMessage = defaultGetThinkingMessage, + ...props + }: ReasoningTriggerProps) => { + const { isStreaming, isOpen, duration } = useReasoning(); + + return ( + + {children ?? ( + <> + + {getThinkingMessage(isStreaming, duration)} + + + )} + + ); + }, +); + +Reasoning.displayName = "Reasoning"; +ReasoningTrigger.displayName = "ReasoningTrigger"; diff --git a/src/components/ai-elements/tool.tsx b/src/components/ai-elements/tool.tsx new file mode 100644 index 0000000..138e906 --- /dev/null +++ b/src/components/ai-elements/tool.tsx @@ -0,0 +1,115 @@ +"use client"; + +import { + CheckCircleIcon, + ChevronDownIcon, + CircleIcon, + ClockIcon, + WrenchIcon, + XCircleIcon, +} from "lucide-react"; +import type { ComponentProps, ReactNode } from "react"; +import { Badge } from "@/components/ui/badge"; +import { + Collapsible, + CollapsibleContent, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; +import { cn } from "@/lib/class-names"; + +export type ToolState = + | "approval-requested" + | "approval-responded" + | "input-available" + | "input-streaming" + | "output-available" + | "output-denied" + | "output-error"; + +export type ToolPart = { state: ToolState }; +export type ToolProps = ComponentProps; + +export const Tool = ({ className, ...props }: ToolProps) => ( + +); + +const statusLabels: Record = { + "approval-requested": "Awaiting Approval", + "approval-responded": "Responded", + "input-available": "Running", + "input-streaming": "Pending", + "output-available": "Completed", + "output-denied": "Denied", + "output-error": "Error", +}; + +const statusIcons: Record = { + "approval-requested": , + "approval-responded": , + "input-available": , + "input-streaming": , + "output-available": , + "output-denied": , + "output-error": , +}; + +export const getStatusBadge = (status: ToolState) => ( + + {statusIcons[status]} + {statusLabels[status]} + +); + +export type ToolHeaderProps = ComponentProps & { + title: string; + state: ToolState; + description?: ReactNode; + meta?: ReactNode; +}; + +export const ToolHeader = ({ + className, + title, + state, + description, + meta, + ...props +}: ToolHeaderProps) => ( + +
+ + {title} + {getStatusBadge(state)} + {description && ( + + {description} + + )} +
+
+ {meta} + +
+
+); + +export type ToolContentProps = ComponentProps; + +export const ToolContent = ({ className, ...props }: ToolContentProps) => ( + +); diff --git a/src/components/canvas-edit-palette.test.tsx b/src/components/canvas-edit-palette.test.tsx new file mode 100644 index 0000000..c20b333 --- /dev/null +++ b/src/components/canvas-edit-palette.test.tsx @@ -0,0 +1,64 @@ +// @vitest-environment jsdom + +import "@testing-library/jest-dom/vitest"; +import { cleanup, render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { CanvasSelectionRect } from "../../shared/canvas-selection"; +import { + CanvasEditPalette, + placeCanvasEditPalette, +} from "./canvas-edit-palette"; + +afterEach(cleanup); + +describe("CanvasEditPalette", () => { + it("places editing controls below a target when the viewport has room", () => { + expect( + placeCanvasEditPalette( + CanvasSelectionRect.make({ x: 300, y: 80, width: 200, height: 60 }), + { width: 800, height: 600 }, + ), + ).toEqual({ left: 190, top: 148, placement: "below" }); + }); + + it("moves above and clamps within the viewport near an edge", () => { + expect( + placeCanvasEditPalette( + CanvasSelectionRect.make({ x: 760, y: 560, width: 32, height: 24 }), + { width: 800, height: 600 }, + ), + ).toEqual({ left: 368, top: 510, placement: "above" }); + }); + + it("exposes compact semantic actions and one clear action", async () => { + const onAction = vi.fn(); + const onClear = vi.fn(); + const user = userEvent.setup(); + render( + , + ); + + await user.click(screen.getByRole("button", { name: "Move later" })); + await user.click( + screen.getByRole("button", { name: "Clear canvas selection" }), + ); + + expect(onAction).toHaveBeenCalledWith("move-later"); + expect(onClear).toHaveBeenCalledTimes(1); + expect( + screen.getByRole("toolbar", { name: "Edit Project heading" }), + ).toHaveAttribute("data-placement", "below"); + }); +}); diff --git a/src/components/canvas-edit-palette.tsx b/src/components/canvas-edit-palette.tsx new file mode 100644 index 0000000..5e84edc --- /dev/null +++ b/src/components/canvas-edit-palette.tsx @@ -0,0 +1,130 @@ +import type { CSSProperties } from "react"; +import type { CanvasSelectionRect } from "../../shared/canvas-selection"; + +export type CanvasEditAction = + | "move-earlier" + | "move-later" + | "smaller" + | "larger"; + +interface CanvasViewport { + readonly width: number; + readonly height: number; +} + +interface CanvasPalettePosition { + readonly left: number; + readonly top: number; + readonly placement: "above" | "below"; +} + +const paletteWidth = 420; +const paletteHeight = 42; +const paletteGap = 8; +const viewportInset = 12; + +const clamp = (value: number, minimum: number, maximum: number) => + Math.max(minimum, Math.min(value, maximum)); + +export const placeCanvasEditPalette = ( + rect: CanvasSelectionRect, + viewport: CanvasViewport, +): CanvasPalettePosition => { + const maximumLeft = Math.max( + viewportInset, + viewport.width - paletteWidth - viewportInset, + ); + const left = clamp( + rect.x + rect.width / 2 - paletteWidth / 2, + viewportInset, + maximumLeft, + ); + const below = rect.y + rect.height + paletteGap; + const fitsBelow = below + paletteHeight + viewportInset <= viewport.height; + if (fitsBelow) { + return { left, top: below, placement: "below" }; + } + return { + left, + top: clamp( + rect.y - paletteHeight - paletteGap, + viewportInset, + Math.max(viewportInset, viewport.height - paletteHeight - viewportInset), + ), + placement: "above", + }; +}; + +export interface CanvasEditPaletteProps { + readonly busy?: boolean; + readonly coordinateSpace?: "absolute" | "fixed"; + readonly label: string; + readonly onAction: (action: CanvasEditAction) => void; + readonly onClear: () => void; + readonly rect: CanvasSelectionRect; + readonly viewport?: CanvasViewport; +} + +export function CanvasEditPalette({ + busy = false, + coordinateSpace = "fixed", + label, + onAction, + onClear, + rect, + viewport = { + width: globalThis.innerWidth, + height: globalThis.innerHeight, + }, +}: CanvasEditPaletteProps) { + const position = placeCanvasEditPalette(rect, viewport); + const style: CSSProperties = { + left: position.left, + position: coordinateSpace, + top: position.top, + }; + return ( +
+ + {label} + + + + + + +
+ ); +} + +export default CanvasEditPalette; diff --git a/src/components/capsule-frame.test.tsx b/src/components/capsule-frame.test.tsx index 5d36b5e..bfa5b55 100644 --- a/src/components/capsule-frame.test.tsx +++ b/src/components/capsule-frame.test.tsx @@ -211,6 +211,8 @@ describe("CapsuleFrame", () => { vi.stubGlobal("MessageChannel", FakeMessageChannel); const onSelectionChange = vi.fn(); const onDirectManipulation = vi.fn(); + const onSelectionAction = vi.fn(); + const onClearSelection = vi.fn(); const selection = CanvasSelection.make({ version: 1, semanticId: "delivery-card", @@ -236,7 +238,9 @@ describe("CapsuleFrame", () => { const rendered = render( , @@ -265,22 +269,30 @@ describe("CapsuleFrame", () => { rendered.rerender( , ); - expect(screen.getByText("Late delivery").parentElement).toHaveClass( - "canvas-selection-outline", - ); const outline = screen.getByRole("group", { name: "Selected element: Late delivery. Drag to move.", }); + expect(outline).toHaveClass("canvas-selection-outline"); fireEvent.pointerDown(outline, { pointerId: 7, clientX: 20, clientY: 20 }); fireEvent.pointerMove(outline, { pointerId: 7, clientX: 44, clientY: 31 }); fireEvent.pointerUp(outline, { pointerId: 7, clientX: 44, clientY: 31 }); expect(onDirectManipulation).toHaveBeenCalledWith("move", 24, 11); + fireEvent.click(screen.getByRole("button", { name: "Move later" })); + fireEvent.click( + screen.getByRole("button", { + name: "Clear canvas selection", + }), + ); + expect(onSelectionAction).toHaveBeenCalledWith("move-later"); + expect(onClearSelection).toHaveBeenCalledTimes(1); expect(FakeMessageChannel.created).toBe(createdBeforeSelection); expect(channel?.port1.posted).toContainEqual({ version: 1, diff --git a/src/components/capsule-frame.tsx b/src/components/capsule-frame.tsx index ea803a7..b0bfb2e 100644 --- a/src/components/capsule-frame.tsx +++ b/src/components/capsule-frame.tsx @@ -16,6 +16,10 @@ import { decodeCapsuleHostMessage, decodeCapsuleMessage, } from "../../shared/capsule-protocol"; +import { + type CanvasEditAction, + CanvasEditPalette, +} from "./canvas-edit-palette"; const CSP = [ "default-src 'none'", @@ -250,6 +254,9 @@ export interface CapsuleFrameProps { readonly title?: string; readonly selectionMode?: boolean; readonly selection?: CanvasSelection; + readonly selectionBusy?: boolean; + readonly onSelectionAction?: (action: CanvasEditAction) => void; + readonly onClearSelection?: () => void; readonly onSelectionChange?: (selection: CanvasSelection | undefined) => void; readonly onDirectManipulation?: ( kind: "move" | "resize", @@ -267,6 +274,9 @@ export function CapsuleFrame({ title = "Flect app", selectionMode = false, selection, + selectionBusy = false, + onSelectionAction, + onClearSelection, onSelectionChange, onDirectManipulation, onIntent, @@ -688,6 +698,22 @@ export function CapsuleFrame({ /> )} + {selection !== undefined && + onSelectionAction !== undefined && + onClearSelection !== undefined && ( + + )}
); } diff --git a/src/components/composer.test.tsx b/src/components/composer.test.tsx index fded864..015e419 100644 --- a/src/components/composer.test.tsx +++ b/src/components/composer.test.tsx @@ -105,25 +105,70 @@ describe("Composer", () => { ); }); - it("grows with the draft and scrolls only after the height bound", () => { + it("fills a starter idea without sending it", async () => { + const user = userEvent.setup(); + const onSubmit = vi.fn(() => Promise.resolve()); + const onDraftChange = vi.fn(() => Promise.resolve()); + render( + , + ); + + await user.click( + screen.getByRole("button", { + name: "Try A calm project planner for this week", + }), + ); + + expect(screen.getByRole("textbox", { name: "Message Flect" })).toHaveValue( + "A calm project planner for this week", + ); + expect(onDraftChange).toHaveBeenLastCalledWith( + "acceptedUse", + "A calm project planner for this week", + ); + expect(onSubmit).not.toHaveBeenCalled(); + }); + + it("does not replace an in-progress draft with a stale persistence update", async () => { + const user = userEvent.setup(); + const initial = props({ + drafts: { + acceptedUse: "", + candidateUse: "", + shape: "", + }, + }); + const { rerender } = render(); + const input = screen.getByRole("textbox", { name: "Message Flect" }); + + await user.type(input, "Current draft"); + rerender( + , + ); + + expect(input).toHaveValue("Current draft"); + }); + + it("uses the AI Elements field-sizing composer with a bounded height", () => { render(); const input = screen.getByRole("textbox", { name: "Message Flect" }); - Object.defineProperty(input, "scrollHeight", { - configurable: true, - value: 96, - }); fireEvent.change(input, { target: { value: "Two\nlines" } }); - expect(input).toHaveStyle({ height: "96px", overflowY: "hidden" }); - - Object.defineProperty(input, "scrollHeight", { - configurable: true, - value: 240, - }); - fireEvent.change(input, { - target: { value: "One\nTwo\nThree\nFour\nFive\nSix\nSeven" }, - }); - expect(input).toHaveStyle({ height: "168px", overflowY: "auto" }); + expect(input).toHaveClass("field-sizing-content", "max-h-48"); }); it("exposes implemented protected actions without placeholder controls", async () => { diff --git a/src/components/composer.tsx b/src/components/composer.tsx index 58d0139..4e0e0fa 100644 --- a/src/components/composer.tsx +++ b/src/components/composer.tsx @@ -1,4 +1,4 @@ -import { useEffect, useId, useLayoutEffect, useRef, useState } from "react"; +import { useEffect, useId, useRef, useState } from "react"; import type { AuthLoginEvent, AuthLoginReference, @@ -14,14 +14,18 @@ import { type AgentSessionStatus, isAgentSessionActive, } from "../hooks/use-agent-session"; +import { + PromptInput, + PromptInputBody, + PromptInputFooter, + PromptInputSubmit, + PromptInputTextarea, + PromptInputTools, +} from "./ai-elements/prompt-input"; import { ComposerActionsMenu } from "./composer-actions-menu"; -import { ArrowUpIcon, StopIcon } from "./icons"; import { ModelMenu } from "./model-menu"; import type { ConversationTarget, ShellMode } from "./role-switcher"; -const MAX_COMPOSER_HEIGHT = 168; -const MIN_COMPOSER_HEIGHT = 48; - export interface ComposerProps { readonly mode: ShellMode; /** @deprecated Flect presents one conversation and ignores role targeting. */ @@ -33,6 +37,8 @@ export interface ComposerProps { /** @deprecated Routing is automatic. */ readonly useDisabled?: boolean; readonly placeholder: string; + /** Outcome-oriented examples for a blank Flect workspace. */ + readonly starterPrompts?: ReadonlyArray; readonly disabled?: boolean; readonly disabledReason?: string; readonly drafts?: ContinuityDrafts; @@ -89,6 +95,7 @@ export interface ComposerProps { export function Composer({ mode, placeholder, + starterPrompts = [], disabled = false, disabledReason, drafts: persistedDrafts, @@ -128,15 +135,15 @@ export function Composer({ externalExtensionsEnabled, onToggleExternalExtensions, }: ComposerProps) { - const [drafts, setDrafts] = useState>({}); + const draftKey = "accepted-use"; + const continuityKey: keyof ContinuityDrafts = "acceptedUse"; + const [drafts, setDrafts] = useState>(() => ({ + [draftKey]: persistedDrafts?.acceptedUse ?? "", + })); const [submitting, setSubmitting] = useState(false); - const composingRef = useRef(false); const submittingRef = useRef(false); - const initialFocusAttemptedRef = useRef(false); - const textareaRef = useRef(null); + const hasLocalDraftRef = useRef(false); const helpId = useId(); - const draftKey = "accepted-use"; - const continuityKey: keyof ContinuityDrafts = "acceptedUse"; const prompt = mode === "safe" ? "" : (drafts[draftKey] ?? ""); const isActive = isAgentSessionActive(status); const protectedActionsLocked = submitting || isActive; @@ -178,48 +185,13 @@ export function Composer({ : "Press Enter to send. Press Shift Enter for a new line."); useEffect(() => { - if (persistedDrafts === undefined) { - return; - } + if (persistedDrafts === undefined || hasLocalDraftRef.current) return; setDrafts((current) => ({ ...current, - "accepted-use": persistedDrafts.acceptedUse, + [draftKey]: persistedDrafts.acceptedUse, })); }, [persistedDrafts]); - useEffect(() => { - const textarea = textareaRef.current; - if ( - initialFocusAttemptedRef.current || - textarea === null || - inputUnavailable || - globalThis.matchMedia?.("(pointer: coarse)").matches === true - ) { - return; - } - initialFocusAttemptedRef.current = true; - const active = textarea.ownerDocument.activeElement; - if (active === null || active === textarea.ownerDocument.body) { - textarea.focus({ preventScroll: true }); - } - }, [inputUnavailable]); - - useLayoutEffect(() => { - const textarea = textareaRef.current; - if (textarea === null) { - return; - } - - textarea.style.height = "0px"; - const measuredHeight = Math.max(textarea.scrollHeight, MIN_COMPOSER_HEIGHT); - textarea.style.height = `${Math.min( - measuredHeight, - MAX_COMPOSER_HEIGHT, - )}px`; - textarea.style.overflowY = - textarea.scrollHeight > MAX_COMPOSER_HEIGHT ? "auto" : "hidden"; - }); - const submit = async () => { const nextPrompt = prompt.trim(); if ( @@ -243,53 +215,60 @@ export function Composer({ } }; + const chooseStarterPrompt = (starterPrompt: string) => { + hasLocalDraftRef.current = true; + setDrafts((current) => ({ ...current, [draftKey]: starterPrompt })); + void onDraftChange?.(continuityKey, starterPrompt); + }; + return ( -
{ - event.preventDefault(); + onSubmit={() => { void submit(); }} > - - + +
+ + + +

- Ready when you are. Press ⌘K or Ctrl+K from anywhere. + Describe the outcome, not the implementation. You can refine it + after the first result.

diff --git a/src/shell/flect-command.test.ts b/src/shell/flect-command.test.ts index e6bcc63..110e237 100644 --- a/src/shell/flect-command.test.ts +++ b/src/shell/flect-command.test.ts @@ -527,37 +527,74 @@ describe("reserved browser flect command", () => { }), ); - it.effect("validates and proposes a workspace interface only as Shaper", () => - Effect.gen(function* () { - yield* respondToReads; - const shell = yield* SandboxedShell; - const validated = yield* shell.execute( - "shaper", - "flect interface validate ./interface.json", - { agentContext: context }, - ); - const proposed = yield* shell.execute( - "shaper", - "flect interface propose /workspace/interface.json", - { agentContext: { ...context, requestId: "tool-propose" } }, - ); - const escaped = yield* shell.execute( - "shaper", - "flect interface validate ../outside.json", - { agentContext: { ...context, requestId: "tool-escape" } }, - ); - assert.strictEqual(validated.exitCode, 0); - assert.include(validated.stdout, "status: valid"); - assert.strictEqual(proposed.exitCode, 0); - assert.include(proposed.stdout, "status: proposed"); - assert.strictEqual(escaped.exitCode, 1); - assert.include(escaped.stdout, "code: unauthorized"); - }).pipe( - Effect.provide( - makeLayer("shaper", { - "/workspace/interface.json": JSON.stringify(defaultInterfaceDocument), - }), + it.effect( + "describes, validates, and proposes an interface only as Shaper", + () => + Effect.gen(function* () { + yield* respondToReads; + const shell = yield* SandboxedShell; + const schema = yield* shell.execute( + "shaper", + "flect interface schema", + { agentContext: { ...context, requestId: "tool-schema" } }, + ); + const candidate = JSON.stringify({ + version: 2, + name: "Visible canvas", + root: { + id: "root", + type: "stack", + direction: "column", + gap: "md", + children: [ + { + id: "headline", + type: "text", + text: "Visible canvas", + style: "headline", + }, + ], + }, + }); + const written = yield* shell.execute( + "shaper", + `printf '%s' '${candidate}' > /workspace/interface.json`, + { agentContext: { ...context, requestId: "tool-write" } }, + ); + const validated = yield* shell.execute( + "shaper", + "flect interface validate ./interface.json", + { agentContext: context }, + ); + const proposed = yield* shell.execute( + "shaper", + "flect interface propose /workspace/interface.json", + { agentContext: { ...context, requestId: "tool-propose" } }, + ); + const escaped = yield* shell.execute( + "shaper", + "flect interface validate ../outside.json", + { agentContext: { ...context, requestId: "tool-escape" } }, + ); + assert.strictEqual(schema.exitCode, 0); + assert.include(schema.stdout, "direction"); + assert.include(schema.stdout, "children"); + assert.include(schema.stdout, "headline"); + assert.strictEqual(written.exitCode, 0); + assert.strictEqual(validated.exitCode, 0); + assert.include(validated.stdout, "status: valid"); + assert.strictEqual(proposed.exitCode, 0); + assert.include(proposed.stdout, "status: proposed"); + assert.strictEqual(escaped.exitCode, 1); + assert.include(escaped.stdout, "code: unauthorized"); + }).pipe( + Effect.provide( + makeLayer("shaper", { + "/workspace/interface.json": JSON.stringify( + defaultInterfaceDocument, + ), + }), + ), ), - ), ); }); diff --git a/src/shell/sandboxed-shell.test.ts b/src/shell/sandboxed-shell.test.ts index 3b889c5..6d1750b 100644 --- a/src/shell/sandboxed-shell.test.ts +++ b/src/shell/sandboxed-shell.test.ts @@ -3,6 +3,7 @@ import { Deferred, Effect, Fiber, Layer, Ref } from "effect"; import { BunCommandResult } from "../../shared/bun-command"; import { type BunOperationCall, makeBunCommandTestLayer } from "./bun-command"; import { + makeLiveRoleSandboxedShellLayer, makeRoleSandboxedShellLayer, makeRoleSandboxedShellService, makeSandboxedShellLayer, @@ -18,6 +19,24 @@ const operationResult = (operation: string) => }); describe("SandboxedShell", () => { + it.effect("runs a basic command through the live role workspace", () => + Effect.gen(function* () { + const shellLayer = makeLiveRoleSandboxedShellLayer({ + app: { files: {} }, + previewApp: { files: {} }, + shaper: { files: {} }, + }); + const result = yield* Effect.gen(function* () { + const shell = yield* SandboxedShell; + return yield* shell.execute("shaper", "printf ready"); + }).pipe(Effect.provide(shellLayer)); + + assert.strictEqual(result.exitCode, 0); + assert.strictEqual(result.stdout, "ready"); + assert.strictEqual(result.stderr, ""); + }), + ); + it.effect( "keeps accepted App, candidate App, and Shaper filesystems isolated", () => diff --git a/src/shell/sandboxed-shell.ts b/src/shell/sandboxed-shell.ts index c426afa..fad6f78 100644 --- a/src/shell/sandboxed-shell.ts +++ b/src/shell/sandboxed-shell.ts @@ -1,5 +1,5 @@ import type { Fetcher } from "@riftydev/npm-client"; -import { MemoryVfs, OpfsVfs } from "@riftydev/vfs"; +import { MemoryVfs } from "@riftydev/vfs"; import { Effect, Layer, @@ -535,16 +535,10 @@ export const makeLiveRoleSandboxedShellLayer = (options: { Layer.effect( SandboxedShell, Effect.gen(function* () { - const vfs = yield* Effect.promise(async () => { - if (OpfsVfs.isSupported()) { - try { - const opfs = new OpfsVfs(); - await opfs.init(); - return opfs; - } catch {} - } - return new MemoryVfs(); - }); + // Role workspaces are deliberately disposable. They must not share the + // canonical browser persistence surface used by accepted interface and + // repository state. + const vfs = new MemoryVfs(); const workspaceId = options.workspaceId ?? "default"; const makeFs = ( workspace: SandboxedShellWorkspace, diff --git a/src/styles.css b/src/styles.css index cb4a280..8293823 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,35 +1,85 @@ +@import "tailwindcss/theme.css" layer(theme); +@import "tailwindcss/utilities.css" layer(utilities) source(none); +@source "./components/ai-elements"; +@source "./components/ui"; +@source "./components/provider-auth-panel.tsx"; + +@theme inline { + --font-sans: ui-sans-serif, system-ui, sans-serif; + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted-surface); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --radius-sm: calc(var(--radius) * 0.6); + --radius-md: calc(var(--radius) * 0.8); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) * 1.4); + --radius-2xl: calc(var(--radius) * 1.8); +} + :root { - color-scheme: dark; - font-family: - -apple-system, BlinkMacSystemFont, "SF Pro Text", "Inter", sans-serif; + color-scheme: light; + font-family: ui-sans-serif, system-ui, sans-serif; font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; - --void: oklch(0.095 0 0); - --canvas: oklch(0.125 0.004 340); - --surface: oklch(0.165 0.006 340); - --surface-raised: oklch(0.205 0.008 340); - --ink: oklch(0.955 0.006 340); - --muted: oklch(0.72 0.012 340); - --quiet: oklch(0.61 0.012 340); - --line: oklch(0.3 0.01 340); - --flect-rose: oklch(0.63 0.18 340); - --flect-rose-hover: oklch(0.69 0.17 340); - --ready: oklch(0.78 0.12 158); - --danger: oklch(0.66 0.17 27); - --accent-soft: color-mix(in oklch, var(--flect-rose) 14%, transparent); - --accent-softer: color-mix(in oklch, var(--flect-rose) 7%, transparent); - --accent-border: color-mix(in oklch, var(--flect-rose) 28%, transparent); - --accent-line: color-mix(in oklch, var(--flect-rose) 66%, transparent); + --background: oklch(1 0 0); + --foreground: oklch(0.145 0 0); + --card: oklch(1 0 0); + --card-foreground: oklch(0.145 0 0); + --popover: oklch(1 0 0); + --popover-foreground: oklch(0.145 0 0); + --primary: oklch(0.205 0 0); + --primary-foreground: oklch(0.985 0 0); + --secondary: oklch(0.97 0 0); + --secondary-foreground: oklch(0.205 0 0); + --muted-surface: oklch(0.97 0 0); + --muted-foreground: oklch(0.45 0 0); + --accent: oklch(0.97 0 0); + --accent-foreground: oklch(0.205 0 0); + --destructive: oklch(0.577 0.245 27.325); + --border: oklch(0.922 0 0); + --input: oklch(0.922 0 0); + --ring: oklch(0.708 0 0); + --radius: 0.625rem; + + --void: var(--background); + --canvas: var(--background); + --surface: var(--card); + --surface-raised: var(--secondary); + --ink: var(--foreground); + --muted: var(--muted-foreground); + --quiet: var(--muted-foreground); + --line: var(--border); + --ready: var(--foreground); + --danger: var(--destructive); + --accent-soft: color-mix(in oklch, var(--primary) 14%, transparent); + --accent-softer: color-mix(in oklch, var(--primary) 7%, transparent); + --accent-border: color-mix(in oklch, var(--primary) 28%, transparent); + --accent-line: color-mix(in oklch, var(--primary) 66%, transparent); --ready-halo: color-mix(in oklch, var(--ready) 10%, transparent); - --shadow-soft: oklch(0.02 0 0 / 0.24); - --shadow-float: oklch(0 0 0 / 0.28); - --shadow-strong: oklch(0.02 0 0 / 0.32); - --surface-shine: oklch(1 0 0 / 0.04); - --sheet-backdrop: oklch(0.02 0 0 / 0.52); - --placeholder: oklch(0.74 0.01 340); - --focus-ring: 0 0 0 2px var(--void), 0 0 0 4px var(--flect-rose); + --shadow-soft: oklch(0 0 0 / 0.08); + --shadow-float: oklch(0 0 0 / 0.12); + --shadow-strong: oklch(0 0 0 / 0.16); + --surface-shine: oklch(0 0 0 / 0.03); + --sheet-backdrop: oklch(0 0 0 / 0.4); + --placeholder: var(--muted-foreground); + --focus-ring: 0 0 0 2px var(--void), 0 0 0 4px var(--primary); --state-motion: 180ms cubic-bezier(0.22, 1, 0.36, 1); --font-mono: "SFMono-Regular", "SF Mono", Menlo, Consolas, monospace; --flect-rail-width: 400px; @@ -40,23 +90,32 @@ --z-modal: 60; } -@media (prefers-color-scheme: light) { +@media (prefers-color-scheme: dark) { :root { - color-scheme: light; - --void: oklch(0.985 0.003 340); - --canvas: oklch(0.965 0.005 340); - --surface: oklch(0.995 0.002 340); - --surface-raised: oklch(0.925 0.009 340); - --ink: oklch(0.205 0.012 340); - --muted: oklch(0.43 0.014 340); - --quiet: oklch(0.47 0.014 340); - --line: oklch(0.79 0.012 340); - --flect-rose: oklch(0.47 0.18 340); - --flect-rose-hover: oklch(0.41 0.17 340); - --ready: oklch(0.39 0.11 158); - --danger: oklch(0.45 0.17 27); - --surface-shine: oklch(0 0 0 / 0.06); - --placeholder: var(--muted); + color-scheme: dark; + --background: oklch(0.145 0 0); + --foreground: oklch(0.985 0 0); + --card: oklch(0.205 0 0); + --card-foreground: oklch(0.985 0 0); + --popover: oklch(0.205 0 0); + --popover-foreground: oklch(0.985 0 0); + --primary: oklch(0.922 0 0); + --primary-foreground: oklch(0.205 0 0); + --secondary: oklch(0.269 0 0); + --secondary-foreground: oklch(0.985 0 0); + --muted-surface: oklch(0.269 0 0); + --muted-foreground: oklch(0.708 0 0); + --accent: oklch(0.269 0 0); + --accent-foreground: oklch(0.985 0 0); + --destructive: oklch(0.704 0.191 22.216); + --border: oklch(1 0 0 / 10%); + --input: oklch(1 0 0 / 15%); + --ring: oklch(0.556 0 0); + --shadow-soft: oklch(0 0 0 / 0.24); + --shadow-float: oklch(0 0 0 / 0.28); + --shadow-strong: oklch(0 0 0 / 0.32); + --surface-shine: oklch(1 0 0 / 0.04); + --sheet-backdrop: oklch(0 0 0 / 0.52); } } @@ -90,11 +149,33 @@ textarea { font: inherit; } -button { +button:not([data-slot="button"]) { color: inherit; -webkit-tap-highlight-color: transparent; } +[data-slot="button"] { + -webkit-tap-highlight-color: transparent; +} + +[data-slot="input-group"] { + opacity: 1; +} + +[data-slot="input-group-control"] { + border: 0; +} + +[data-slot="input-group-control"]::placeholder { + opacity: 1; +} + +[data-slot="input-group-control"]:focus-visible { + border: 0; + outline: none; + box-shadow: none; +} + button:focus-visible, a:focus-visible, input:focus-visible, @@ -129,7 +210,7 @@ textarea:focus-visible, } .role-shell--split:not(.role-shell--collapsed) { - grid-template-columns: minmax(0, 1fr) var(--flect-rail-width); + grid-template-columns: minmax(0, 1fr); } .topbar { @@ -141,7 +222,7 @@ textarea:focus-visible, width: 100%; height: 64px; align-items: center; - justify-content: space-between; + justify-content: flex-end; padding: 0 24px; pointer-events: none; } @@ -150,12 +231,32 @@ textarea:focus-visible, pointer-events: auto; } -.wordmark { - color: var(--ink); - font-size: 15px; - font-weight: 650; - letter-spacing: -0.025em; - text-decoration: none; +.window-drag-region { + position: fixed; + z-index: calc(var(--z-topbar) - 1); + top: 0; + right: 0; + left: 0; + height: 64px; + display: flex; + align-items: center; + justify-content: center; + cursor: grab; + user-select: none; + -webkit-app-region: drag; + -webkit-user-select: none; +} + +.window-drag-region::after { + width: 68px; + height: 5px; + border-radius: 999px; + background: color-mix(in oklch, var(--ink) 22%, transparent); + content: ""; +} + +.window-drag-region:active { + cursor: grabbing; } .topbar__status { @@ -205,6 +306,23 @@ textarea:focus-visible, background: var(--void); } +.workspace-canvas--settings { + overflow: auto; +} + +.role-shell--split:not(.role-shell--collapsed) .workspace-canvas--starter { + padding-right: calc(var(--flect-rail-width) + 64px); +} + +.workspace-canvas--settings::before { + position: fixed; + z-index: var(--z-backdrop); + inset: 0; + background: color-mix(in oklch, var(--void) 28%, transparent); + content: ""; + pointer-events: none; +} + .role-shell--preview .workspace-canvas { background: var(--canvas); } @@ -255,7 +373,7 @@ textarea:focus-visible, } .share-review__state { - color: var(--flect-rose-hover); + color: var(--primary); font-weight: 560; } @@ -281,7 +399,7 @@ textarea:focus-visible, } .share-review__accepted-state { - border-left: 2px solid var(--flect-rose); + border-left: 2px solid var(--primary); padding-left: 10px; color: var(--ink); } @@ -626,7 +744,7 @@ textarea:focus-visible, } .share-library__header p { - color: var(--flect-rose-hover); + color: var(--primary); font-size: 11px; font-weight: 620; letter-spacing: 0.04em; @@ -827,6 +945,52 @@ textarea:focus-visible, text-wrap: balance; } +.blank-invitation p { + max-width: 30rem; + margin: 12px auto 0; + color: var(--muted); + font-size: 15px; + line-height: 1.5; +} + +.composer__starter-prompts { + display: flex; + flex-wrap: wrap; + gap: 7px; + min-width: 0; + margin: 0; + border: 0; + padding: 0 10px 10px; +} + +.composer__starter-prompt { + min-height: 34px; + border: 1px solid var(--line); + border-radius: 999px; + padding: 6px 10px; + color: var(--muted); + background: var(--surface); + cursor: pointer; + font-size: 12px; + line-height: 1.35; + text-align: left; + transition: + color var(--state-motion), + background var(--state-motion), + border-color var(--state-motion); +} + +.composer__starter-prompt:hover { + border-color: var(--accent-border); + color: var(--ink); + background: var(--surface-raised); +} + +.composer__starter-prompt:focus-visible { + outline: none; + box-shadow: var(--focus-ring); +} + .shell-loading-status { color: var(--muted); font-size: 13px; @@ -945,12 +1109,15 @@ textarea:focus-visible, } .agent-rail-container { - position: relative; - z-index: 35; - min-width: 0; - height: 100dvh; + position: fixed; + z-index: var(--z-sheet); + top: max(16px, env(safe-area-inset-top)); + right: max(16px, env(safe-area-inset-right)); + bottom: max(16px, env(safe-area-inset-bottom)); + width: var(--flect-rail-width); + min-width: min(340px, calc(100vw - 32px)); + height: auto; container-type: inline-size; - grid-column: 2; } .role-shell--centered .agent-rail-container { @@ -963,23 +1130,65 @@ textarea:focus-visible, transform: translate(-50%, 22px); } +.role-shell--centered + .agent-rail-container:not(:has(.agent-rail[data-status="setup-required"])) { + top: auto; + bottom: max(18px, env(safe-area-inset-bottom)); + max-height: calc(100dvh - 80px); + overflow: visible; + transform: translateX(-50%); +} + +.role-shell--centered + .agent-rail-container:has(.agent-rail[data-status="setup-required"]) { + top: clamp(210px, 30dvh, 360px); + bottom: max(18px, env(safe-area-inset-bottom)); + height: auto; + max-height: none; + overflow: hidden; + transform: translateX(-50%); +} + +.role-shell:has(.agent-rail[data-status="setup-required"]) .workspace-canvas { + align-items: flex-start; +} + +.role-shell:has(.agent-rail[data-status="setup-required"]) .blank-invitation { + padding-top: clamp(82px, 14dvh, 164px); + padding-bottom: 0; +} + .role-shell--collapsed .agent-rail-container { visibility: hidden; pointer-events: none; } .agent-rail { + position: relative; + z-index: 1; display: flex; width: 100%; height: 100%; min-height: 0; flex-direction: column; - background: var(--canvas); + overflow: hidden; + border: 0; + border-radius: 16px; + background: var(--surface); + box-shadow: 0 18px 42px var(--shadow-strong); } .role-shell--centered .agent-rail { height: auto; + border: 0; + border-radius: 0; background: transparent; + box-shadow: none; +} + +.role-shell--centered .agent-rail[data-status="setup-required"] { + height: 100%; + min-height: 0; } .agent-rail__header { @@ -1015,6 +1224,37 @@ textarea:focus-visible, gap: 6px; } +.agent-rail__settings { + display: inline-flex; + min-height: 32px; + flex-direction: column; + align-items: flex-start; + justify-content: center; + border: 0; + border-radius: 8px; + padding: 0 9px; + background: transparent; + color: var(--muted); + cursor: pointer; + font-size: 11px; + font-weight: 560; +} + +.agent-rail__settings small { + color: var(--quiet); + font-size: 9px; + font-weight: 500; +} + +.agent-rail__settings:hover { + background: var(--surface-raised); + color: var(--ink); +} + +.agent-rail__settings--dock { + display: none; +} + .runtime-state { display: inline-flex; min-height: 28px; @@ -1022,7 +1262,7 @@ textarea:focus-visible, gap: 7px; border-radius: 999px; padding: 0 9px; - color: var(--muted); + color: var(--foreground); font-size: 11px; font-weight: 520; } @@ -1071,69 +1311,224 @@ textarea:focus-visible, touch-action: none; } -.agent-rail-resizer::after { - position: absolute; - top: 0; - bottom: 0; - left: 3px; - width: 1px; - background: var(--line); - content: ""; - transition: background var(--state-motion); -} - -.agent-rail-resizer:hover::after, -.agent-rail-resizer:focus-visible::after { - background: var(--flect-rose); -} - .conversation { display: flex; min-height: 0; flex: 1 1 auto; flex-direction: column; - gap: 18px; + overflow: hidden; +} + +.conversation-shell { + width: 100%; + min-height: 0; + flex: 1 1 auto; +} + +.conversation__scroll { overflow-anchor: none; overflow-y: auto; - padding: 24px 20px; + padding: 22px 18px 32px; overscroll-behavior: contain; - scrollbar-gutter: stable; } -.jump-to-latest { - position: sticky; - bottom: 4px; - align-self: center; - min-height: 30px; - border: 1px solid var(--line); - border-radius: 999px; - padding: 0 12px; - background: color-mix(in oklch, var(--surface-raised) 92%, transparent); - box-shadow: 0 8px 24px var(--shadow-float); - color: var(--ink); +.conversation__content { + gap: 20px; +} + +.message { + line-height: 1.55; +} + +.message--user { + max-width: 88%; +} + +.message--user > div { + border: 1px solid color-mix(in oklch, var(--line) 72%, transparent); + border-radius: 14px 14px 4px 14px; + padding: 9px 12px; + background: color-mix(in oklch, var(--surface-raised) 72%, transparent); + box-shadow: 0 1px 0 color-mix(in oklch, var(--ink) 4%, transparent); +} + +.message--assistant { + max-width: 100%; +} + +.message--assistant > div { + width: 100%; +} + +.work-log { + display: grid; + min-width: 0; + gap: 2px; + border: 0; + color: var(--muted); +} + +.historical-turn { + display: grid; + min-width: 0; + gap: 8px; +} + +.historical-turn__summary { + display: grid; + width: 100%; + min-width: 0; + min-height: 32px; + align-items: center; + border: 0; + border-radius: 7px; + gap: 8px; + grid-template-columns: auto minmax(0, 1fr) auto; + padding: 4px; + background: transparent; + color: var(--muted); cursor: pointer; font-size: 0.75rem; - font-weight: 570; - backdrop-filter: blur(16px); + text-align: start; +} + +.historical-turn__summary:hover, +.historical-turn__summary:focus-visible { + background: color-mix(in oklch, var(--surface-raised) 42%, transparent); +} + +.historical-turn__summary > span { + color: var(--muted-strong); +} + +.historical-turn__summary > strong { + overflow: hidden; + color: var(--muted); + font-weight: 450; + text-overflow: ellipsis; + white-space: nowrap; +} + +.historical-turn__summary > svg { + width: 13px; + height: 13px; + transition: transform 140ms ease; +} + +.historical-turn__summary[aria-expanded="true"] > svg { + transform: rotate(180deg); +} + +.historical-turn__context { + display: grid; + min-width: 0; + gap: 8px; + padding-inline-start: 8px; + border-inline-start: 1px solid var(--line); +} + +.historical-turn__context[hidden] { + display: none; +} + +.historical-turn__context .message--user { + max-width: 100%; +} + +.work-log__summary { + display: grid; + width: 100%; + min-width: 0; + min-height: 28px; + align-items: center; + border: 0; + border-radius: 6px; + gap: 7px; + grid-template-columns: auto auto minmax(0, 1fr) auto; + padding: 3px 4px; + background: transparent; + color: inherit; + cursor: pointer; + font-size: 0.6875rem; + text-align: start; +} + +.work-log__summary:hover, +.work-log__summary:focus-visible { + background: color-mix(in oklch, var(--surface-raised) 42%, transparent); +} + +.work-log__summary strong { + color: var(--ink); + font-weight: 560; + white-space: nowrap; +} + +.work-log__summary > span:nth-child(3) { + overflow: hidden; + color: var(--quiet); + text-overflow: ellipsis; + white-space: nowrap; +} + +.work-log__summary .lucide { + width: 12px; + height: 12px; + transition: transform var(--state-motion); +} + +.work-log__summary[aria-expanded="true"] .lucide { + transform: rotate(180deg); +} + +.work-log__mark { + width: 5px; + height: 5px; + border-radius: 50%; + background: var(--ready); +} + +.work-log--active .work-log__mark { + animation: activity-pulse 1.4s ease-in-out infinite; + background: var(--primary); +} + +.work-log--failed .work-log__mark { + background: var(--danger); +} + +.work-log__entries { + display: grid; + min-width: 0; + gap: 1px; + margin-left: 4px; +} + +.work-log__entries[hidden] { + display: none; } .activity-card { position: relative; - border: 1px solid color-mix(in oklch, var(--line) 78%, transparent); - border-radius: 12px; - background: color-mix(in oklch, var(--surface) 76%, transparent); + border: 0; + border-radius: 7px; + background: transparent; } .activity-card__disclosure { + margin-bottom: 0; + border: 0; border-radius: inherit; + background: transparent; } .activity-card__fix { - width: 100%; - min-height: 36px; + width: calc(100% - 28px); + min-height: 30px; border: 0; - border-top: 1px solid var(--line); - padding: 0 10px; + border-radius: 6px; + margin: 0 0 4px 28px; + padding: 0 7px; background: transparent; color: var(--ink); cursor: pointer; @@ -1150,13 +1545,30 @@ textarea:focus-visible, .activity-card__summary { display: grid; - min-height: 42px; + width: 100%; + min-width: 0; + min-height: 30px; align-items: center; - padding: 8px 10px; + border: 0; + border-radius: 6px; + padding: 4px; + background: transparent; + color: inherit; cursor: pointer; - gap: 8px; - grid-template-columns: auto minmax(0, 1fr) auto auto; + gap: 5px; + grid-template-columns: 20px auto minmax(0, 1fr) 16px auto 16px; list-style: none; + text-align: start; +} + +.activity-card__summary:hover, +.activity-card__summary:focus-visible { + background: color-mix(in oklch, var(--surface-raised) 52%, transparent); +} + +.activity-card__summary .lucide { + width: 12px; + height: 12px; } .activity-card__summary::-webkit-details-marker, @@ -1165,45 +1577,68 @@ textarea:focus-visible, } .activity-card__summary strong { - overflow: hidden; font-size: 0.75rem; - font-weight: 590; - text-overflow: ellipsis; + font-weight: 520; white-space: nowrap; } -.activity-card__summary > span:not(.activity-card__dot), -.activity-card__summary time, -.activity-card__summary small { +.activity-card__summary > code { + min-width: 0; + overflow: hidden; color: var(--muted); font-size: 0.6875rem; + font-weight: 430; + text-overflow: ellipsis; + white-space: nowrap; } -.activity-card__dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--quiet); +.activity-card__tool, +.activity-card__phase { + display: inline-grid; + width: 16px; + height: 16px; + place-items: center; + color: var(--quiet); +} + +.activity-card__summary time { + color: var(--quiet); + font-size: 0.625rem; + font-variant-numeric: tabular-nums; + white-space: nowrap; } -.activity-card--running .activity-card__dot { +.activity-card--running .activity-card__phase { animation: activity-pulse 1.4s ease-in-out infinite; - background: var(--flect-rose); + color: var(--ink); } -.activity-card--succeeded .activity-card__dot { - background: var(--ready); +.activity-card--failed .activity-card__phase { + color: var(--danger); } -.activity-card--failed .activity-card__dot { - background: var(--danger); +.activity-card__chevron { + color: var(--quiet); + transition: transform var(--state-motion); +} + +.activity-card__summary[data-state="open"] .activity-card__chevron { + transform: rotate(180deg); } .activity-card__details { display: grid; + min-width: 0; gap: 10px; - border-top: 1px solid var(--line); - padding: 10px; + border: 0; + border-left: 1px solid color-mix(in oklch, var(--line) 56%, transparent); + margin: 2px 0 6px 14px; + padding: 5px 4px 5px 14px; + background: transparent; +} + +.activity-card__details[data-state="closed"] { + display: none; } .activity-card__details section { @@ -1252,13 +1687,15 @@ textarea:focus-visible, display: flex; min-width: 0; align-items: center; - justify-content: space-between; + flex-wrap: wrap; gap: 8px; color: var(--quiet); font-size: 0.625rem; } .activity-card__details footer code { + min-width: 0; + flex: 1 1 120px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -1288,34 +1725,6 @@ textarea:focus-visible, line-height: 1.5; } -.message { - max-width: min(92%, 70ch); - font-size: 1rem; - font-weight: 430; - letter-spacing: -0.01em; - line-height: 1.55; - overflow-wrap: anywhere; -} - -.message--user { - align-self: flex-end; - border-radius: 12px 12px 3px 12px; - padding: 9px 12px; - background: var(--surface-raised); -} - -.message--assistant { - width: 100%; - max-width: min(100%, 70ch); - align-self: flex-start; -} - -.message--activity { - align-self: flex-start; - color: var(--muted); - font-size: 0.6875rem; -} - .message-content { --markdown-block-rhythm: 0.65rem; min-width: 0; @@ -1416,7 +1825,7 @@ textarea:focus-visible, height: 0.875rem; flex: 0 0 auto; margin: 0; - accent-color: var(--flect-rose); + accent-color: var(--primary); opacity: 1; } @@ -1443,13 +1852,9 @@ textarea:focus-visible, } .message-content a { - color: var(--flect-rose-hover); + color: var(--primary); text-decoration: underline; - text-decoration-color: color-mix( - in oklch, - var(--flect-rose-hover) 50%, - transparent - ); + text-decoration-color: color-mix(in oklch, var(--primary) 50%, transparent); text-decoration-thickness: 1px; text-underline-offset: 0.15em; overflow-wrap: anywhere; @@ -1462,7 +1867,7 @@ textarea:focus-visible, .message-content a:focus-visible, .markdown-action:focus-visible, .markdown-details > summary:focus-visible { - outline: 2px solid var(--flect-rose); + outline: 2px solid var(--primary); outline-offset: 2px; } @@ -1753,6 +2158,25 @@ textarea:focus-visible, padding: 12px; } +.agent-rail__dock:has(.capsule-review) { + max-height: 70dvh; + overflow-y: auto; +} + +.composer { + border-color: color-mix(in oklch, var(--line) 84%, transparent); + border-radius: var(--radius); + background: var(--card); + box-shadow: + 0 1px 0 color-mix(in oklch, var(--ink) 4%, transparent), + 0 8px 24px color-mix(in oklch, var(--shadow-soft) 72%, transparent); +} + +.composer textarea { + min-height: 44px; + padding: 10px 12px 4px; +} + .capsule-notice { color: var(--text-secondary); font-size: 0.75rem; @@ -1780,7 +2204,7 @@ textarea:focus-visible, .canvas-selection-outline { position: absolute; z-index: 4; - border: 2px solid var(--flect-rose); + border: 2px solid var(--primary); border-radius: 4px; min-width: 0; margin: 0; @@ -1804,7 +2228,7 @@ textarea:focus-visible, overflow: hidden; border-radius: 5px 5px 5px 0; padding: 4px 7px; - background: var(--flect-rose); + background: var(--primary); color: var(--void); font-size: 11px; font-weight: 650; @@ -1821,38 +2245,89 @@ textarea:focus-visible, border: 2px solid var(--void); border-radius: 50%; padding: 0; - background: var(--flect-rose); + background: var(--primary); cursor: nwse-resize; touch-action: none; } -.canvas-edit-toolbar { +.canvas-edit-trigger { position: fixed; z-index: calc(var(--z-topbar) - 1); - top: 72px; - left: 50%; + bottom: 18px; + left: 18px; + display: inline-flex; + width: 44px; + height: 44px; + align-items: center; + justify-content: center; + border: 1px solid var(--line); + border-radius: 50%; + padding: 0; + background: color-mix(in oklch, var(--surface) 94%, transparent); + box-shadow: 0 8px 18px var(--shadow-soft); + color: var(--text-secondary); + cursor: pointer; + backdrop-filter: blur(16px); +} + +.canvas-edit-trigger:hover:not(:disabled), +.canvas-edit-trigger[aria-pressed="true"] { + border-color: color-mix(in oklch, var(--primary) 55%, var(--line)); + background: var(--surface-raised); + color: var(--ink); +} + +.canvas-edit-trigger:disabled { + cursor: default; + opacity: 0.5; +} + +.canvas-edit-trigger__glyph { + width: 16px; + height: 18px; + background: currentcolor; + clip-path: polygon( + 10% 0, + 92% 68%, + 58% 70%, + 76% 100%, + 62% 100%, + 44% 72%, + 10% 98% + ); +} + +.canvas-edit-palette { + z-index: calc(var(--z-topbar) - 1); display: flex; - max-width: min(760px, calc(100vw - 32px)); - min-height: 38px; + width: 420px; + max-width: calc(100vw - 24px); + min-height: 42px; align-items: center; - gap: 6px; + gap: 2px; overflow: auto hidden; - border: 1px solid var(--line); + border: 1px solid color-mix(in oklch, var(--line) 88%, transparent); border-radius: 10px; padding: 4px; - background: color-mix(in oklch, var(--surface) 94%, transparent); - box-shadow: 0 8px 18px var(--shadow-soft); + background: color-mix(in oklch, var(--surface) 96%, transparent); + box-shadow: 0 10px 28px var(--shadow-float); color: var(--ink); - transform: translateX(-50%); - backdrop-filter: blur(16px); + backdrop-filter: blur(18px); } -.role-shell--split:not(.role-shell--collapsed) .canvas-edit-toolbar { - left: calc((100vw - var(--flect-rail-width)) / 2); - max-width: min(760px, calc(100vw - var(--flect-rail-width) - 32px)); +.canvas-edit-palette__target { + min-width: 0; + flex: 1 1 auto; + overflow: hidden; + padding: 0 7px; + color: var(--ink); + font-size: 11px; + font-weight: 620; + text-overflow: ellipsis; + white-space: nowrap; } -.canvas-edit-toolbar button { +.canvas-edit-palette button { min-height: 30px; flex: 0 0 auto; border: 0; @@ -1866,44 +2341,28 @@ textarea:focus-visible, font-weight: 590; } -.canvas-edit-toolbar button:hover:not(:disabled), -.canvas-edit-toolbar button[aria-pressed="true"] { +.canvas-edit-palette button:hover:not(:disabled) { background: var(--accent-soft); color: var(--ink); } -.canvas-edit-toolbar button:disabled { +.canvas-edit-palette button:disabled { cursor: default; opacity: 0.5; } -.canvas-edit-toolbar button.canvas-edit-toolbar__select { - color: var(--ink); -} - -.canvas-edit-toolbar__selection { - max-width: 180px; - overflow: hidden; - padding: 0 4px; - color: var(--ink); - font-size: 11px; - font-weight: 620; - text-overflow: ellipsis; - white-space: nowrap; -} - -.canvas-edit-toolbar__actions { - display: flex; - align-items: center; - gap: 2px; -} - .interface-canvas[data-selection-mode="true"] [data-node-id] { cursor: crosshair; } +.interface-canvas[data-selection-mode="true"] + [data-node-id]:hover:not(:has([data-node-id]:hover)) { + outline: 2px dashed color-mix(in oklch, var(--primary) 75%, transparent); + outline-offset: 3px; +} + .interface-canvas [data-selected="true"] { - outline: 2px solid var(--flect-rose); + outline: 2px solid var(--primary); outline-offset: 3px; } @@ -1920,6 +2379,65 @@ textarea:focus-visible, background: color-mix(in oklch, var(--surface) 62%, transparent); } +.diagnostics-panel--workspace { + position: fixed; + z-index: calc(var(--z-sheet) + 1); + top: max(16px, env(safe-area-inset-top)); + bottom: max(16px, env(safe-area-inset-bottom)); + left: max(16px, env(safe-area-inset-left)); + display: flex; + width: min(720px, calc(100vw - var(--flect-rail-width) - 48px)); + height: auto; + min-height: 0; + flex-direction: column; + overflow: hidden; + border: 1px solid var(--line); + border-radius: 16px; + background: var(--surface); + box-shadow: 0 18px 42px var(--shadow-strong); +} + +.diagnostics-panel__workspace-header { + display: flex; + min-height: 96px; + flex: 0 0 auto; + align-items: center; + justify-content: space-between; + gap: 24px; + border-bottom: 1px solid var(--line); + padding: 20px clamp(24px, 5vw, 64px); +} + +.diagnostics-panel__workspace-header h1 { + margin: 0; + font-size: 20px; + font-weight: 620; + letter-spacing: -0.02em; +} + +.diagnostics-panel__workspace-header p { + margin: 4px 0 0; + color: var(--muted); + font-size: 13px; +} + +.diagnostics-panel__close { + min-height: 36px; + flex: 0 0 auto; + border: 1px solid var(--line); + border-radius: 8px; + padding: 0 12px; + background: var(--surface); + color: var(--ink); + cursor: pointer; + font-size: 12px; + font-weight: 590; +} + +.diagnostics-panel__close:hover { + background: var(--surface-raised); +} + .build-progress { display: flex; min-height: 32px; @@ -2195,7 +2713,8 @@ textarea:focus-visible, } .diagnostics-panel__operations li > span[data-phase="failed"] { - color: var(--danger); + background: color-mix(in oklch, var(--danger) 18%, var(--surface-raised)); + color: var(--ink); } .diagnostics-panel__operations li strong { @@ -2219,65 +2738,49 @@ textarea:focus-visible, white-space: nowrap; } -.role-shell--centered .agent-rail__dock { - padding: 0; -} - -.composer { - position: relative; - width: 100%; - border-radius: 16px; - background: var(--surface); - box-shadow: 0 1px 0 var(--surface-shine); - transition: - background var(--state-motion), - box-shadow var(--state-motion); -} - -.composer::after { - position: absolute; - inset: 0; - border-radius: inherit; - box-shadow: inset 0 0 0 1px transparent; - content: ""; - pointer-events: none; - transition: box-shadow var(--state-motion); +.diagnostics-panel--workspace .diagnostics-panel__body { + width: min(100%, 920px); + max-height: none; + flex: 1 1 auto; + align-content: start; + align-self: center; + gap: 16px; + border-top: 0; + padding: 32px clamp(24px, 5vw, 64px) 48px; } -.composer:focus-within { - background: color-mix(in oklch, var(--surface) 78%, var(--surface-raised)); - box-shadow: 0 6px 8px var(--shadow-soft); +.diagnostics-panel--workspace .diagnostics-panel__control, +.diagnostics-panel--workspace .diagnostics-panel__setup-heading, +.diagnostics-panel--workspace .diagnostics-panel__integrations li { + min-height: 44px; } -.composer:focus-within::after, -.composer--active::after { - box-shadow: inset 0 0 0 1px var(--accent-line); +.diagnostics-panel--workspace .diagnostics-panel__control button, +.diagnostics-panel--workspace .diagnostics-panel__update button, +.diagnostics-panel--workspace .diagnostics-panel__uninstall button, +.diagnostics-panel--workspace .diagnostics-panel__setup button { + min-height: 36px; + padding: 0 12px; + font-size: 12px; } -.composer textarea { - display: block; - width: 100%; - min-height: 48px; - max-height: 168px; - resize: none; - border: 0; - outline: none; - padding: 15px 16px 4px; - background: transparent; - color: var(--ink); - font-size: 15px; - letter-spacing: -0.01em; - line-height: 1.45; +.role-shell--centered .agent-rail__dock { + padding: 0; } -.composer textarea::placeholder { - color: var(--placeholder); - opacity: 1; +.role-shell--centered + .agent-rail[data-status="setup-required"] + .agent-rail__dock { + min-height: 0; + height: 100%; + align-content: end; + overflow-y: auto; + padding: 2px; + scrollbar-gutter: stable; } -.composer textarea:disabled { - cursor: not-allowed; - color: var(--muted); +.agent-rail[data-status="setup-required"] .diagnostics-panel { + display: none; } .composer__rail { @@ -2343,7 +2846,7 @@ textarea:focus-visible, .composer-control:disabled { cursor: not-allowed; - opacity: 0.55; + opacity: 1; } .composer-menu, @@ -2382,11 +2885,21 @@ textarea:focus-visible, } .composer-popover--models { - right: 0; + position: fixed; + top: auto; + right: max(24px, env(safe-area-inset-right)); + bottom: max(150px, calc(env(safe-area-inset-bottom) + 134px)); + left: auto; display: flex; width: min(360px, calc(100vw - 32px)); max-height: min(480px, calc(100dvh - 120px)); + margin: 0; padding: 0; + color: var(--ink); +} + +.composer-popover--models::backdrop { + background: color-mix(in oklch, var(--sheet-backdrop) 42%, transparent); } .composer-popover__context { @@ -2490,7 +3003,7 @@ textarea:focus-visible, } .model-menu__source { - color: var(--muted); + color: var(--foreground); white-space: nowrap; } @@ -2634,7 +3147,7 @@ textarea:focus-visible, .model-menu__check { flex: 0 0 auto; - color: var(--flect-rose-hover); + color: var(--primary); font-weight: 700; } @@ -2654,7 +3167,7 @@ textarea:focus-visible, .model-menu__favorite:hover, .model-menu__favorite[aria-pressed="true"] { - color: var(--flect-rose-hover); + color: var(--primary); } .model-menu__empty { @@ -2697,9 +3210,7 @@ textarea:focus-visible, gap: 4px; } -.model-menu__reasoning button, -.provider-auth button, -.provider-auth a { +.model-menu__reasoning button { min-height: 28px; border: 1px solid var(--line); border-radius: 7px; @@ -2714,11 +3225,7 @@ textarea:focus-visible, .model-menu__reasoning button:hover, .model-menu__reasoning button:focus-visible, -.model-menu__reasoning button[aria-checked="true"], -.provider-auth button:hover:not(:disabled), -.provider-auth button:focus-visible, -.provider-auth a:hover, -.provider-auth a:focus-visible { +.model-menu__reasoning button[aria-checked="true"] { border-color: var(--accent-line); background: var(--accent-soft); color: var(--ink); @@ -2726,24 +3233,23 @@ textarea:focus-visible, .provider-auth { display: grid; - max-height: 220px; - gap: 9px; + min-height: 0; + max-height: 230px; + gap: 10px; overflow-y: auto; - border-top: 1px solid var(--line); - padding: 11px 12px 12px; + padding: 2px; overscroll-behavior: contain; + scrollbar-gutter: stable; } -.provider-auth > header, -.provider-auth__provider { +.provider-auth > header { display: flex; align-items: center; justify-content: space-between; gap: 10px; } -.provider-auth > header > div, -.provider-auth__provider > span { +.provider-auth > header > div { display: grid; min-width: 0; gap: 2px; @@ -2760,13 +3266,6 @@ textarea:focus-visible, justify-self: start; } -.provider-auth__provider { - min-height: 42px; - border-radius: 9px; - padding: 6px 7px; - background: color-mix(in oklch, var(--surface-raised) 68%, transparent); -} - .provider-auth__actions { display: flex; flex: 0 0 auto; @@ -2817,11 +3316,6 @@ textarea:focus-visible, letter-spacing: 0.08em; } -.provider-auth button:disabled { - cursor: not-allowed; - opacity: 0.45; -} - .role-switcher { display: inline-flex; min-width: 0; @@ -2874,6 +3368,7 @@ textarea:focus-visible, border-radius: 8px; padding: 0 8px; background: var(--accent-soft); + color: var(--foreground); font-size: 11px; font-weight: 580; } @@ -2893,7 +3388,7 @@ textarea:focus-visible, } .submit-button:not(:disabled):hover { - background: var(--flect-rose-hover); + background: var(--primary); color: var(--ink); transform: translateY(-1px); } @@ -2923,14 +3418,12 @@ textarea:focus-visible, align-items: center; } -.runtime-alert--setup { - grid-template-columns: minmax(0, 1fr); +.provider-setup { + min-height: 0; } -.runtime-alert--setup .provider-auth { - max-height: min(34dvh, 260px); - border-top: 1px solid var(--line); - padding: 10px 0 0; +.provider-setup .provider-auth { + max-height: min(30dvh, 250px); } .runtime-alert strong, @@ -2983,7 +3476,7 @@ textarea:focus-visible, } .revision-banner__copy > span { - color: var(--flect-rose-hover); + color: var(--primary); font-size: 11px; font-weight: 590; } @@ -3200,7 +3693,7 @@ textarea:focus-visible, width: 15px; height: 15px; margin: 0; - accent-color: var(--flect-rose); + accent-color: var(--primary); } .extension-review__authority input:disabled + span { @@ -3279,7 +3772,7 @@ textarea:focus-visible, } .extension-review__fork input:focus-visible { - border-color: var(--flect-rose); + border-color: var(--primary); } .decision-button--danger { @@ -3405,7 +3898,7 @@ textarea:focus-visible, } .reference-product-diagnostic > header .eyebrow { - color: var(--flect-rose-hover); + color: var(--primary); font-size: 10px; font-weight: 650; letter-spacing: 0.12em; @@ -3440,7 +3933,7 @@ textarea:focus-visible, } .reference-product-diagnostic__actions button:focus-visible { - outline: 2px solid var(--flect-rose); + outline: 2px solid var(--primary); outline-offset: 2px; } @@ -3488,7 +3981,7 @@ textarea:focus-visible, .product-adoption-diagnostic__eyebrow { margin: 0; - color: var(--flect-rose-hover); + color: var(--primary); font-size: 10px; font-weight: 680; letter-spacing: 0.13em; @@ -3564,7 +4057,7 @@ textarea:focus-visible, .product-adoption-card__state.is-blocked { border-color: color-mix(in oklch, var(--danger) 45%, var(--line)); - color: var(--danger); + color: var(--foreground); } .product-adoption-card__facts { @@ -3645,7 +4138,7 @@ textarea:focus-visible, } .product-adoption-card__ownership strong { - color: var(--flect-rose-hover); + color: var(--primary); font-weight: 650; } @@ -3683,7 +4176,7 @@ textarea:focus-visible, } .product-adoption-card__diagnostics li[data-severity="warning"] > span { - color: var(--flect-rose-hover); + color: var(--primary); } .product-adoption-card__diagnostics strong { @@ -3715,6 +4208,16 @@ textarea:focus-visible, } @media (max-width: 760px) { + .diagnostics-panel--workspace { + top: 0; + right: 0; + bottom: 0; + left: 0; + width: 100%; + border: 0; + border-radius: 0; + } + .capsule-review .reference-product-diagnostic__results { grid-template-columns: 1fr; } @@ -3815,14 +4318,18 @@ textarea:focus-visible, gap: 7px; } -.decision-button--primary { - background: var(--ink); - color: var(--void); +button.decision-button--primary { + background: var(--primary); + color: var(--primary-foreground); } -.decision-button--primary:hover:not(:disabled) { - background: var(--flect-rose-hover); - color: var(--void); +button.decision-button--primary:hover:not(:disabled) { + background: color-mix( + in oklch, + var(--primary) 92%, + var(--primary-foreground) + ); + color: var(--primary-foreground); } .decision-button:disabled { @@ -3870,6 +4377,14 @@ textarea:focus-visible, } @media (max-width: 980px) { + .role-shell--settings .agent-rail-container { + display: none; + } + + .role-shell--settings .workspace-canvas { + padding: 88px 32px 48px; + } + .role-shell--split:not(.role-shell--collapsed) { grid-template-columns: minmax(0, 1fr); } @@ -3879,9 +4394,11 @@ textarea:focus-visible, padding-left: 32px; } - .role-shell--split:not(.role-shell--collapsed) .canvas-edit-toolbar { - left: 50%; - max-width: calc(100vw - 32px); + .role-shell--split:not(.role-shell--collapsed) .workspace-canvas--starter { + padding-right: min( + calc(var(--flect-rail-width) + 32px), + calc(100vw - 56px) + ); } .role-shell--split .agent-rail-container { @@ -3891,6 +4408,7 @@ textarea:focus-visible, right: 0; width: min(var(--flect-rail-width), calc(100vw - 24px)); height: 100dvh; + border-radius: 0; box-shadow: -8px 0 8px var(--shadow-float); } @@ -3907,6 +4425,23 @@ textarea:focus-visible, } @media (max-width: 760px) { + .diagnostics-panel__workspace-header { + min-height: 84px; + padding: 16px 18px; + } + + .diagnostics-panel--workspace .diagnostics-panel__body { + padding: 24px 18px 36px; + } + + .diagnostics-panel--workspace .diagnostics-panel__control, + .diagnostics-panel--workspace .diagnostics-panel__setup-heading, + .diagnostics-panel--workspace .diagnostics-panel__integrations li { + align-items: flex-start; + flex-direction: column; + padding-block: 8px; + } + .topbar { height: 56px; padding: 0 16px; @@ -3916,9 +4451,9 @@ textarea:focus-visible, padding: 76px 18px 28px; } - .canvas-edit-toolbar { - top: 60px; - max-width: calc(100vw - 20px); + .canvas-edit-trigger { + bottom: 12px; + left: 12px; } .blank-invitation { @@ -3950,7 +4485,7 @@ textarea:focus-visible, padding-left: max(10px, env(safe-area-inset-left)); } - .conversation { + .conversation__scroll { padding-right: 16px; padding-left: 16px; } @@ -3990,7 +4525,7 @@ textarea:focus-visible, .agent-reopen, .activity-card__summary, .activity-card__fix, - .canvas-edit-toolbar button, + .canvas-edit-palette button, .diagnostics-panel__control button, .diagnostics-panel__update button, .diagnostics-panel__uninstall button, @@ -4032,17 +4567,50 @@ textarea:focus-visible, } } +@media (max-height: 640px) { + .role-shell:has(.agent-rail[data-status="setup-required"]) .blank-invitation { + padding-top: 64px; + } + + .role-shell--centered + .agent-rail-container:has(.agent-rail[data-status="setup-required"]) { + top: 72px; + bottom: max(10px, env(safe-area-inset-bottom)); + } + + .provider-setup .provider-auth { + max-height: min(34dvh, 190px); + } +} + .role-shell--split:not(.role-shell--collapsed) .topbar { padding-right: calc(var(--flect-rail-width) + 24px); } +.role-shell--settings .topbar { + padding-right: 24px; +} + +.role-shell--settings .agent-rail-container { + visibility: hidden; + pointer-events: none; +} + @media (max-width: 760px) { .role-shell--split:not(.role-shell--collapsed) .topbar { padding-right: calc(var(--flect-rail-width) + 16px); } + + .role-shell--settings .topbar { + padding-right: 16px; + } } @media (max-width: 480px) { + .canvas-edit-palette__target { + display: none; + } + .composer-popover__item { align-items: flex-start; flex-direction: column; @@ -4059,22 +4627,35 @@ textarea:focus-visible, display: none; } +.role-shell--centered .agent-rail__settings--dock { + display: inline-flex; + width: fit-content; + align-items: center; +} + @media (prefers-reduced-motion: reduce) { :root { --state-motion: 0.01ms linear; } .thinking span, - .activity-card--running .activity-card__dot { + .activity-card--running .activity-card__phase, + .work-log--active .work-log__mark { animation: none; } } @media (pointer: coarse) { - .canvas-edit-toolbar button { + .canvas-edit-trigger, + .canvas-edit-palette button { min-height: 44px; } + .canvas-edit-trigger { + width: 44px; + height: 44px; + } + .canvas-selection-resize { right: -22px; bottom: -22px; @@ -4093,19 +4674,24 @@ textarea:focus-visible, --muted: CanvasText; --quiet: CanvasText; --line: GrayText; - --flect-rose: LinkText; - --flect-rose-hover: LinkText; --ready: CanvasText; --danger: CanvasText; --focus-ring: 0 0 0 3px Highlight; } - .activity-card__dot, + .work-log__mark, .runtime-state__dot { border: 1px solid CanvasText; } - .canvas-edit-toolbar, + button.decision-button--primary { + border: 1px solid HighlightText; + background: Highlight; + color: HighlightText; + } + + .canvas-edit-trigger, + .canvas-edit-palette, .canvas-selection-outline, .interface-canvas [data-selected="true"] { border-color: Highlight; diff --git a/tests/e2e/accessibility.spec.ts b/tests/e2e/accessibility.spec.ts index 16a8e9a..3ab2136 100644 --- a/tests/e2e/accessibility.spec.ts +++ b/tests/e2e/accessibility.spec.ts @@ -27,6 +27,47 @@ const expectAccessible = async (page: Page, state: string) => { ).toEqual([]); }; +const decisionButtonContrast = async (page: Page) => + page.locator(".decision-button:not(:disabled)").evaluateAll((buttons) => { + const canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = 1; + const context = canvas.getContext("2d", { willReadFrequently: true }); + if (context === null) { + throw new Error("Canvas context is unavailable"); + } + const toRgb = (color: string) => { + context.clearRect(0, 0, 1, 1); + context.fillStyle = color; + context.fillRect(0, 0, 1, 1); + return [...context.getImageData(0, 0, 1, 1).data].slice(0, 3); + }; + const luminance = (color: ReadonlyArray) => { + const channel = (value: number) => { + const normalized = value / 255; + return normalized <= 0.04045 + ? normalized / 12.92 + : ((normalized + 0.055) / 1.055) ** 2.4; + }; + return ( + 0.2126 * channel(color[0] ?? 0) + + 0.7152 * channel(color[1] ?? 0) + + 0.0722 * channel(color[2] ?? 0) + ); + }; + return buttons.map((button) => { + const style = getComputedStyle(button); + const foreground = luminance(toRgb(style.color)); + const background = luminance(toRgb(style.backgroundColor)); + return { + label: button.textContent?.trim() ?? "Unnamed decision", + ratio: + (Math.max(foreground, background) + 0.05) / + (Math.min(foreground, background) + 0.05), + }; + }); + }); + const shapeCandidate = async (page: Page) => { await expect(page.locator("html")).toHaveAttribute( "data-flect-state", @@ -48,6 +89,56 @@ test.beforeEach(async ({ page }) => { ).toBeEnabled(); }); +test("keeps first-run provider setup contained and immediately actionable", async ({ + page, +}, testInfo) => { + await page.route("**/api/models", (route) => { + void route.fulfill({ + body: JSON.stringify({ models: [], version: 1 }), + contentType: "application/json", + status: 200, + }); + }); + await page.setViewportSize({ width: 760, height: 560 }); + await page.reload(); + + const setup = page.getByRole("region", { name: "Connect an agent" }); + await expect(setup).toBeVisible(); + await expect(page.getByRole("button", { name: "Connect" })).toBeVisible(); + await expect( + page.getByRole("textbox", { name: "Message Flect" }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toBeHidden(); + + const geometry = await page.evaluate(() => { + const setup = document.querySelector(".provider-setup"); + const composer = document.querySelector(".composer"); + if (setup === null || composer === null) { + throw new Error("First-run surfaces are missing"); + } + const setupBox = setup.getBoundingClientRect(); + const composerBox = composer.getBoundingClientRect(); + return { + composerBottom: composerBox.bottom, + composerLeft: composerBox.left, + composerRight: composerBox.right, + documentWidth: document.documentElement.scrollWidth, + setupTop: setupBox.top, + viewportHeight: window.innerHeight, + viewportWidth: window.innerWidth, + }; + }); + expect(geometry.documentWidth).toBe(geometry.viewportWidth); + expect(geometry.setupTop).toBeGreaterThanOrEqual(64); + expect(geometry.composerLeft).toBeGreaterThanOrEqual(0); + expect(geometry.composerRight).toBeLessThanOrEqual(geometry.viewportWidth); + expect(geometry.composerBottom).toBeLessThanOrEqual(geometry.viewportHeight); + await expectAccessible(page, "contained first-run provider setup"); + await page.screenshot({ path: testInfo.outputPath("first-run-setup.png") }); +}); + test("gates blank, candidate, accepted, Diagnostics, model, and safe states", async ({ page, }) => { @@ -60,21 +151,21 @@ test("gates blank, candidate, accepted, Diagnostics, model, and safe states", as await expectAccessible(page, "extension and recovery actions menu"); await page.keyboard.press("Escape"); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Open settings" }).click(); await expect(page.getByText("Workspace storage")).toBeVisible(); await expect( page.getByText( "Source history and compiled interfaces are durable in this browser.", ), ).toBeVisible(); - await expectAccessible(page, "Diagnostics disclosure"); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await expectAccessible(page, "Settings workspace"); + await page.getByRole("button", { name: "Close settings" }).click(); await page.getByRole("button", { name: "Model: Auto via Pi" }).click(); await expectAccessible(page, "model chooser dialog"); await page.keyboard.press("Escape"); - await page.getByRole("button", { name: "Safe mode" }).click(); + await page.getByRole("button", { name: "Open recovery mode" }).click(); await expectAccessible(page, "protected recovery"); }); @@ -88,20 +179,78 @@ test.describe("adaptive appearances", () => { await shapeCandidate(page); await expectAccessible(page, `${colorScheme} live canvas workbench`); - const geometry = await page.evaluate(() => ({ - colorScheme: getComputedStyle(document.documentElement).colorScheme, - documentWidth: document.documentElement.scrollWidth, - viewportWidth: window.innerWidth, - })); + await page.getByRole("button", { name: "Select element" }).click(); + const heading = page.getByRole("heading", { + name: "Focused project overview", + }); + await heading.hover(); + await expect(heading).toHaveCSS("outline-style", "dashed"); + await heading.click(); + const editPalette = page.getByRole("toolbar", { + name: "Edit Focused project overview", + }); + await expect(editPalette).toBeVisible(); + + const geometry = await editPalette.evaluate((palette) => { + const rect = palette.getBoundingClientRect(); + return { + bottom: rect.bottom, + colorScheme: getComputedStyle(document.documentElement).colorScheme, + documentWidth: document.documentElement.scrollWidth, + left: rect.left, + right: rect.right, + top: rect.top, + viewportHeight: window.innerHeight, + viewportWidth: window.innerWidth, + }; + }); expect(geometry.colorScheme).toContain(colorScheme); expect(geometry.documentWidth).toBe(geometry.viewportWidth); + expect(geometry.left).toBeGreaterThanOrEqual(0); + expect(geometry.top).toBeGreaterThanOrEqual(0); + expect(geometry.right).toBeLessThanOrEqual(geometry.viewportWidth); + expect(geometry.bottom).toBeLessThanOrEqual(geometry.viewportHeight); + await expectAccessible(page, `${colorScheme} contextual edit overlay`); await page.screenshot({ - path: testInfo.outputPath(`${colorScheme}-candidate.png`), + path: testInfo.outputPath(`${colorScheme}-selection-overlay.png`), }); }); } }); +test.describe("recovery action visibility", () => { + for (const colorScheme of ["dark", "light"] as const) { + test(`${colorScheme} recovery controls keep their text legible in every state`, async ({ + page, + }) => { + await page.emulateMedia({ colorScheme }); + await page.goto("/?safe=1"); + const restore = page.getByRole("button", { + name: "Restore working interface", + }); + await expect(restore).toBeVisible(); + await expectAccessible(page, `${colorScheme} protected recovery`); + + for (const button of await decisionButtonContrast(page)) { + expect( + button.ratio, + `${colorScheme} ${button.label} must meet WCAG AA text contrast`, + ).toBeGreaterThanOrEqual(4.5); + } + + await restore.hover(); + const hoveredRestore = (await decisionButtonContrast(page)).find( + (button) => button.label === "Restore working interface", + ); + expect(hoveredRestore).toBeDefined(); + expect( + hoveredRestore?.ratio, + `${colorScheme} Restore working interface must remain legible on hover`, + ).toBeGreaterThanOrEqual(4.5); + }); + } +}); + test("reflows at the 200 percent page-zoom viewport equivalent", async ({ page, }) => { diff --git a/tests/e2e/embedded-axi.spec.ts b/tests/e2e/embedded-axi.spec.ts index bc8f445..3378b7a 100644 --- a/tests/e2e/embedded-axi.spec.ts +++ b/tests/e2e/embedded-axi.spec.ts @@ -5,6 +5,7 @@ import { join } from "node:path"; import { promisify } from "node:util"; import { expect, type Page, test } from "@playwright/test"; import { resetBrowserWorkspace } from "./reset-browser-workspace"; +import { revealActivity } from "./reveal-activity"; const browserFailures = new WeakMap>(); const completedPromptPages = new WeakSet(); @@ -90,17 +91,27 @@ test("Flect validates and applies local edits while protected authority stays in await expect(workspaceComposer(page)).toBeVisible(); await expect(page.locator(".role-switcher")).toHaveCount(0); - const activities = page.getByRole("button", { name: "Bash details" }); + const activities = page.locator('button[aria-label="Bash details"]'); await expect(activities).toHaveCount(2); + await revealActivity(bashForCommand(page, "flect interface schema")); await expect(activities.first()).toContainText("Completed"); - await expect(activities.first()).toContainText("40ms"); + await expect(activities.first()).toContainText("40 ms"); await expect(activities.last()).toContainText("Failed"); - await expect(activities.last()).toContainText("2ms"); + await expect(activities.last()).toContainText("2 ms"); await activities.first().click(); await activities.last().click(); + await expect( + page.locator(".activity-card__details code").first(), + ).toContainText("flect interface schema"); await expect( page.locator(".activity-card__details code").first(), ).toContainText("flect interface validate /workspace/interface.json"); + await expect( + page.locator(".activity-card__details pre").first(), + ).toContainText("treeDepth"); + await expect( + page.locator(".activity-card__details pre").first(), + ).toContainText("direction"); await expect( page.locator(".activity-card__details pre").first(), ).toContainText("status: proposed"); @@ -118,6 +129,7 @@ test("Flect inspects its accepted live-canvas ref through reserved embedded Git" await composer.press("Enter"); const activity = bashForCommand(page, "alias git=false"); + await revealActivity(activity); await expect(activity).toContainText("Completed"); await activity.getByRole("button", { name: "Bash details" }).click(); const output = activity.locator(".activity-card__details pre"); @@ -134,6 +146,7 @@ test("Flect checkpoints staged source through embedded Wasm Git", async ({ await composer.press("Enter"); const activity = bashForCommand(page, "git commit -m 'Shape source'"); + await revealActivity(activity); await expect(activity).toContainText("Completed"); await activity.getByRole("button", { name: "Bash details" }).click(); const output = activity.locator(".activity-card__details pre"); @@ -187,6 +200,7 @@ test("Flect lists and invokes a visible product action through embedded flect", ).toBeVisible(); const activity = bashForCommand(page, "flect action list"); + await revealActivity(activity); await expect(activity).toContainText("Completed"); await activity.getByRole("button", { name: "Bash details" }).click(); await expect( @@ -210,6 +224,7 @@ test("Flect authority and reserved-command identity fail closed", async ({ await composer.fill("Verify App Agent authority"); await composer.press("Enter"); let activity = bashForCommand(page, "flect shape 'App must not shape'"); + await revealActivity(activity); await expect(activity).toContainText("Completed"); await activity.getByRole("button", { name: "Bash details" }).click(); await expect(activity.locator(".activity-card__details pre")).toContainText( @@ -220,6 +235,7 @@ test("Flect authority and reserved-command identity fail closed", async ({ await composer.fill("Verify embedded shell composition"); await composer.press("Enter"); activity = bashForCommand(page, "FLECT_ROLE=shaper"); + await revealActivity(activity); await expect(activity).toContainText("Completed"); await activity.getByRole("button", { name: "Bash details" }).click(); const output = activity.locator(".activity-card__details pre"); @@ -228,28 +244,34 @@ test("Flect authority and reserved-command identity fail closed", async ({ completedPromptPages.add(page); }); -test("role workspace source persists through OPFS across a page restart", async ({ +test("role workspace source is discarded across a page restart", async ({ page, }) => { await acceptAndRun(page); let composer = workspaceComposer(page); await composer.fill("Write persistent workspace marker"); + const activityButtons = page.locator('button[aria-label="Bash details"]'); + let previousActivityCount = await activityButtons.count(); await composer.press("Enter"); - await expect( - page.getByRole("button", { name: "Bash details" }).last(), - ).toContainText("Completed"); + await expect(activityButtons).toHaveCount(previousActivityCount + 1); + let activity = activityButtons.last(); + await revealActivity(activity.locator("xpath=ancestor::article")); + await expect(activity).toContainText("Completed"); await page.reload(); await expect(page.locator(".role-shell")).toBeVisible(); composer = workspaceComposer(page); await composer.fill("Read persistent workspace marker"); + previousActivityCount = await activityButtons.count(); await composer.press("Enter"); - const activity = page.getByRole("button", { name: "Bash details" }).last(); - await expect(activity).toContainText("Completed"); + await expect(activityButtons).toHaveCount(previousActivityCount + 1); + activity = activityButtons.last(); + await revealActivity(activity.locator("xpath=ancestor::article")); + await expect(activity).toContainText("Failed"); await activity.click(); await expect( page.locator(".activity-card__details pre").last(), - ).toContainText("opfs-role-workspace"); + ).not.toContainText("opfs-role-workspace"); completedPromptPages.add(page); }); @@ -268,14 +290,15 @@ test("streamed embedded CLI activity does not steal manual scroll position", asy const conversation = page.getByRole("log", { name: "Flect conversation", }); + const conversationScroll = conversation.locator(".conversation__scroll"); await expect .poll(() => - conversation.evaluate( + conversationScroll.evaluate( (element) => element.scrollHeight > element.clientHeight, ), ) .toBe(true); - await conversation.evaluate((element) => { + await conversationScroll.evaluate((element) => { element.scrollTop = 0; element.dispatchEvent(new Event("scroll")); }); @@ -286,7 +309,7 @@ test("streamed embedded CLI activity does not steal manual scroll position", asy page.getByRole("button", { name: /Jump to latest/ }), ).toBeVisible(); expect( - await conversation.evaluate((element) => element.scrollTop), + await conversationScroll.evaluate((element) => element.scrollTop), ).toBeLessThan(50); completedPromptPages.add(page); }); diff --git a/tests/e2e/flect.spec.ts b/tests/e2e/flect.spec.ts index e56f4d5..c1cfa3b 100644 --- a/tests/e2e/flect.spec.ts +++ b/tests/e2e/flect.spec.ts @@ -295,7 +295,7 @@ test("shapes a blank workspace in one continuous live canvas", async ({ page, }) => { await expect( - page.getByRole("heading", { name: "What do you want to make?" }), + page.getByRole("heading", { name: "What do you need?" }), ).toBeVisible(); await shapeFirstInterface(page); @@ -310,6 +310,162 @@ test("shapes a blank workspace in one continuous live canvas", async ({ await expect(page.locator(".composer")).toHaveCount(1); }); +test("keeps completed agent work quiet behind the final answer", async ({ + page, +}) => { + await shapeFirstInterface(page); + + const work = page.getByRole("region", { name: "2 tool calls" }); + await expect(work).toContainText("Worked for 42 ms"); + await expect(work).toContainText("2 steps"); + await expect( + work.getByRole("button", { name: "Show 2 completed steps" }), + ).toHaveAttribute("aria-expanded", "false"); + await expect(work.locator(".work-log__entries")).toBeHidden(); + await expect( + page.getByText("Change complete: Focused project overview"), + ).toBeVisible(); + + await work.getByRole("button", { name: "Show 2 completed steps" }).click(); + const commandRows = work.locator(".activity-card__summary"); + await expect(commandRows).toHaveCount(2); + await expect(commandRows.first()).toBeVisible(); + const expandedLayout = await work.evaluate((region) => { + const bounds = region.getBoundingClientRect(); + const rows = [ + ...region.querySelectorAll(".activity-card__summary"), + ]; + return rows.map((row) => { + const rowBounds = row.getBoundingClientRect(); + const style = getComputedStyle(row); + return { + borderWidth: style.borderTopWidth, + contained: rowBounds.right <= bounds.right + 0.5, + scrollContained: row.scrollWidth <= row.clientWidth, + }; + }); + }); + expect(expandedLayout).toEqual([ + { borderWidth: "0px", contained: true, scrollContained: true }, + { borderWidth: "0px", contained: true, scrollContained: true }, + ]); + + await commandRows.first().click(); + const commandDetails = work.locator(".activity-card__details").first(); + await expect(commandDetails).toBeVisible(); + const detailsLayout = await commandDetails.evaluate((details) => { + const style = getComputedStyle(details); + return { + borderBottomWidth: style.borderBottomWidth, + borderLeftWidth: style.borderLeftWidth, + borderRightWidth: style.borderRightWidth, + borderTopWidth: style.borderTopWidth, + contained: details.scrollWidth <= details.clientWidth, + }; + }); + expect(detailsLayout).toEqual({ + borderBottomWidth: "0px", + borderLeftWidth: "1px", + borderRightWidth: "0px", + borderTopWidth: "0px", + contained: true, + }); + + const railLayout = await page.locator(".agent-rail").evaluate((rail) => { + const railStyle = getComputedStyle(rail); + const workLog = rail.querySelector(".work-log"); + const workStyle = workLog === null ? undefined : getComputedStyle(workLog); + return { + borderLeftWidth: railStyle.borderLeftWidth, + railContained: rail.scrollWidth <= rail.clientWidth, + workBorderWidth: workStyle?.borderTopWidth, + }; + }); + expect(railLayout).toEqual({ + borderLeftWidth: "0px", + railContained: true, + workBorderWidth: "0px", + }); +}); + +test("gives the static home screen one clear starting action", async ({ + page, +}) => { + const staticView = new URL(page.url()); + staticView.searchParams.set("view", "1"); + await page.goto(staticView.href); + + await expect( + page.getByRole("heading", { name: "Describe the app you want to make." }), + ).toBeVisible(); + await expect( + page.getByRole("textbox", { name: "Message Flect" }), + ).toHaveAttribute( + "placeholder", + "For example: a calm project planner for this week", + ); + await expect( + page.getByRole("button", { name: "Create with Flect" }), + ).toBeVisible(); + await page + .getByRole("button", { name: "A calm project planner for this week" }) + .click(); + await expect( + page.getByRole("textbox", { name: "Message Flect" }), + ).toHaveValue("A calm project planner for this week"); + await expect( + page.getByRole("heading", { name: "Describe the app you want to make." }), + ).toBeVisible(); + await expect( + page.getByRole("button", { name: "Start building" }), + ).toHaveCount(0); + await expect( + page.getByRole("button", { name: "Select element" }), + ).toHaveCount(0); + + const dragHandle = await page + .locator(".activation-shell__bar") + .evaluate((element) => { + const style = getComputedStyle(element); + const indicator = getComputedStyle(element, "::after"); + return { + cursor: style.cursor, + height: Number.parseFloat(style.height), + indicatorWidth: Number.parseFloat(indicator.width), + }; + }); + expect(dragHandle.cursor).toBe("grab"); + expect(dragHandle.height).toBeGreaterThanOrEqual(56); + expect(dragHandle.indicatorWidth).toBe(68); + + completedShapePages.add(page); + await page.getByRole("button", { name: "Create with Flect" }).click(); + await expect(page.locator("#flect-static-shell")).toBeHidden(); + await expect(page.locator(".role-shell")).toHaveClass(/role-shell--split/); + await expect( + page.getByRole("heading", { name: "Focused project overview" }), + ).toBeVisible(); +}); + +test("keeps a visible, spacious drag handle above the workspace", async ({ + page, +}) => { + const dragHandle = await page + .locator(".window-drag-region") + .evaluate((element) => { + const style = getComputedStyle(element); + const indicator = getComputedStyle(element, "::after"); + return { + cursor: style.cursor, + height: Number.parseFloat(style.height), + indicatorWidth: Number.parseFloat(indicator.width), + }; + }); + expect(dragHandle.cursor).toBe("grab"); + expect(dragHandle.height).toBeGreaterThanOrEqual(64); + expect(dragHandle.indicatorWidth).toBe(68); +}); + test("selects and directly edits the running canvas through the same agent", async ({ page, }) => { @@ -1027,11 +1183,9 @@ test("previews and accepts compiled UI only inside the isolated capsule frame", if (exported === null) throw new Error("Compiled capsule was not exported."); expect(await readFile(exported)).toEqual(Buffer.from(archive)); - await page.getByRole("button", { name: "Safe mode" }).click(); + await page.getByRole("button", { name: "Open recovery mode" }).click(); await expect(page.locator('iframe[title="Compiled fixture"]')).toHaveCount(0); - await expect( - page.getByText("Custom interface state is bypassed."), - ).toBeVisible(); + await expect(page.getByText("Your interface is protected.")).toBeVisible(); }); test("restores a compiled candidate for review without replacing accepted state", async ({ @@ -1107,6 +1261,14 @@ test("keeps one draft and one conversation while Flect routes product and edit w .click(); await composer.fill("Fail candidate extension"); await composer.press("Enter"); + await expect(page.locator("form.composer")).toHaveAttribute( + "aria-busy", + "false", + ); + const failedWork = page.getByRole("region", { name: "1 tool call" }).last(); + await failedWork + .getByRole("button", { name: "Show 1 completed step" }) + .click(); const failedActivity = page.getByRole("button", { name: "Trusted Pi extension details", }); @@ -1123,10 +1285,14 @@ test("keeps one draft and one conversation while Flect routes product and edit w await expect(fix).toBeVisible(); await fix.click(); await page.getByRole("button", { name: "Actions" }).click(); - await expect( - page.getByRole("menuitem", { name: "Disable trusted Pi extensions" }), - ).toBeVisible(); - await page.keyboard.press("Escape"); + const disableExtensions = page.getByRole("menuitem", { + name: "Disable trusted Pi extensions", + }); + await expect(disableExtensions).toBeVisible(); + await disableExtensions.press("Escape"); + await expect(page.getByRole("dialog", { name: "Flect actions" })).toHaveCount( + 0, + ); await expect(page.getByText("Fail candidate extension")).toBeVisible(); await expect( page.getByRole("button", { name: "Fix with Flect" }).last(), @@ -1151,19 +1317,44 @@ test("routes product questions and typed edit requests without exposing agent mo await shapeFirstInterface(page); const appInput = page.getByRole("textbox", { name: "Message Flect" }); await appInput.fill("Which interface is active?"); + completedPromptPages.add(page); await appInput.press("Enter"); await expect(page.getByText("The product action completed.")).toBeVisible(); await expect( page.getByRole("region", { name: "Import decision" }), ).toHaveCount(0); - await appInput.fill("Explicitly change the interface"); + const activeRevision = await page + .locator(".role-shell") + .getAttribute("data-active-revision"); + await appInput.fill( + "Build a premium Northstar AI meeting-notes page: nav, hero, dashboard, CTAs, logos, 3 features.", + ); await appInput.press("Enter"); await expect( page.getByRole("region", { name: "Import decision" }), ).toHaveCount(0); + await expect( + page.getByRole("heading", { + name: "Meetings, remembered. Work, unblocked.", + }), + ).toBeVisible(); + await expect(page.getByRole("button", { name: "Start free" })).toBeVisible(); + await expect( + page.getByText("Live capture · Instant summaries · Action tracking", { + exact: true, + }), + ).toBeVisible(); + await expect(page.locator(".role-shell")).not.toHaveAttribute( + "data-active-revision", + activeRevision ?? "", + ); await expect(appInput).toBeEnabled(); - await expect(page.getByText("Explicitly change the interface")).toBeVisible(); + await expect( + page.getByText( + "Build a premium Northstar AI meeting-notes page: nav, hero, dashboard, CTAs, logos, 3 features.", + ), + ).toBeVisible(); }); test("keeps essential composer qualifiers at AA contrast", async ({ page }) => { @@ -1184,13 +1375,45 @@ test("keeps one chronological conversation across internal routing and reload", await appInput.fill("Open the latest project"); await appInput.press("Enter"); await expect(page.getByText("The product action completed.")).toBeVisible(); - await expect( - page.getByRole("button", { name: "Bash details" }).first(), - ).toContainText("Completed"); + const latestWork = page.getByRole("region", { name: "1 tool call" }).last(); + await expect(latestWork).toContainText("Worked for 10 ms"); + await latestWork + .getByRole("button", { name: "Show 1 completed step" }) + .click(); + const bashDetails = latestWork.getByRole("button", { + name: "Bash details", + }); + await expect(bashDetails).toContainText("Completed"); + await expect(latestWork.locator(".activity-card__details")).toBeHidden(); + await bashDetails.click(); + await expect(latestWork.locator(".activity-card__details")).toBeVisible(); completedPromptPages.add(page); await expect( page.getByText("Change complete: Focused project overview"), ).toBeVisible(); + const earlierTurn = page.getByRole("region", { + name: "Earlier turn: Create a focused project overview", + }); + await expect(earlierTurn).toBeVisible(); + await expect( + earlierTurn.getByRole("button", { + name: "Show earlier request: Create a focused project overview", + }), + ).toHaveAttribute("aria-expanded", "false"); + await expect( + earlierTurn.locator(".historical-turn__context .message--user"), + ).toBeHidden(); + await expect( + earlierTurn.getByText("Change complete: Focused project overview"), + ).toBeVisible(); + await earlierTurn + .getByRole("button", { + name: "Show earlier request: Create a focused project overview", + }) + .click(); + await expect( + earlierTurn.locator(".historical-turn__context .message--user"), + ).toBeVisible(); const conversation = page.getByRole("log", { name: "Flect conversation" }); await expect(conversation).toContainText("Create a focused project overview"); await expect(conversation).toContainText("Open the latest project"); @@ -1241,6 +1464,13 @@ test("normalizes an interrupted Shaper turn without restoring partial output", a await input.fill("Create a candidate that will be cancelled"); completedShapePages.add(page); await input.press("Enter"); + const conversation = page.getByRole("log", { name: "Flect conversation" }); + await expect(conversation).toContainText( + "Create a candidate that will be cancelled", + ); + await expect( + page.getByRole("status", { name: "Workbench status" }), + ).toContainText("Flect is responding"); await expect(page.getByRole("button", { name: "Stop Flect" })).toBeVisible(); await page.reload(); @@ -1288,8 +1518,12 @@ test("rejects a stale draft writer across two real same-origin tabs", async ({ await page.evaluate(() => localStorage.getItem("flect.role-continuity.v1")), ).not.toContain("Stale draft from the second tab"); - await second.getByRole("button", { name: "Safe mode" }).click(); - await expect(second.getByText(/stale-write/)).toBeVisible(); + await second.getByRole("button", { name: "Open recovery mode" }).click(); + await expect( + second.getByText( + "Saved conversation data needs repair before it can be restored.", + ), + ).toBeVisible(); await second.close(); }); @@ -1321,8 +1555,12 @@ test("preserves the prior continuity record when browser quota rejects a write", const input = page.getByRole("textbox", { name: "Message Flect" }); await expect(input).toHaveValue("Last durable draft"); await input.fill("This write exceeds quota"); - await page.getByRole("button", { name: "Safe mode" }).click(); - await expect(page.getByText(/storage-unavailable/)).toBeVisible(); + await page.getByRole("button", { name: "Open recovery mode" }).click(); + await expect( + page.getByText( + "Saved conversation data needs repair before it can be restored.", + ), + ).toBeVisible(); expect( await page.evaluate(() => localStorage.getItem("flect.role-continuity.v1")), ).toBe(durable); @@ -1442,14 +1680,15 @@ test("keeps a reader's position until they choose to jump to new activity", asyn const conversation = page.getByRole("log", { name: "Flect conversation", }); + const conversationScroll = conversation.locator(".conversation__scroll"); await expect .poll(() => - conversation.evaluate( + conversationScroll.evaluate( (element) => element.scrollHeight > element.clientHeight, ), ) .toBe(true); - await conversation.evaluate((element) => { + await conversationScroll.evaluate((element) => { element.scrollTop = 0; element.dispatchEvent(new Event("scroll")); }); @@ -1460,13 +1699,13 @@ test("keeps a reader's position until they choose to jump to new activity", asyn page.getByRole("button", { name: /Jump to latest/ }), ).toBeVisible(); expect( - await conversation.evaluate((element) => element.scrollTop), + await conversationScroll.evaluate((element) => element.scrollTop), ).toBeLessThan(50); await page.getByRole("button", { name: /Jump to latest/ }).click(); await expect .poll(() => - conversation.evaluate( + conversationScroll.evaluate( (element) => element.scrollHeight - element.clientHeight - element.scrollTop, ), @@ -1626,8 +1865,13 @@ test("uses right and full-height sheets at compact breakpoints", async ({ ), ).toBe(false); + await page + .getByRole("region", { name: "2 tool calls" }) + .getByRole("button", { name: "Show 2 completed steps" }) + .click(); + for (const name of [ - "Safe mode", + "Open recovery mode", "Select element", "Collapse agent", "Fix with Flect", @@ -1644,6 +1888,37 @@ test("uses right and full-height sheets at compact breakpoints", async ({ } }); +test("keeps Settings in a foreground overlay above the running canvas", async ({ + page, +}) => { + await shapeFirstInterface(page); + + await page.getByRole("button", { name: "Open settings" }).click(); + await expect(page.getByRole("heading", { name: "Settings" })).toBeVisible(); + + const settings = page.locator(".diagnostics-panel--workspace"); + const rail = page.locator(".agent-rail-container"); + const settingsBox = await settings.boundingBox(); + const railBox = await rail.boundingBox(); + expect(settingsBox).not.toBeNull(); + expect(railBox).not.toBeNull(); + expect(settingsBox?.x ?? 0).toBeGreaterThan(0); + expect(settingsBox?.width ?? 0).toBeLessThan(railBox?.x ?? 0); + await expect( + page.getByRole("heading", { name: "Focused project overview" }), + ).toBeVisible(); + + await page.getByRole("button", { name: "Close settings" }).click(); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toBeFocused(); + + await page.setViewportSize({ width: 720, height: 780 }); + await page.getByRole("button", { name: "Open settings" }).click(); + await expect(settings).toHaveCSS("width", "720px"); + await expect(rail).toBeHidden(); +}); + test("keeps safe mode and promptless products inside the protected shell", async ({ page, }) => { @@ -1724,11 +1999,9 @@ test("keeps safe mode and promptless products inside the protected shell", async await page.goto("/?safe=1"); await expect( - page.locator(".topbar").getByText("Safe mode", { exact: true }), - ).toBeVisible(); - await expect( - page.getByText("Custom interface state is bypassed."), + page.locator(".topbar").getByText("Recovery mode", { exact: true }), ).toBeVisible(); + await expect(page.getByText("Your interface is protected.")).toBeVisible(); await expect( page.getByRole("textbox", { name: "Message Flect" }), ).toBeDisabled(); @@ -1736,31 +2009,27 @@ test("keeps safe mode and promptless products inside the protected shell", async page.getByRole("textbox", { name: "Message Flect" }), ).toHaveValue(""); await expect( - page.getByRole("button", { name: "Restore interface" }), + page.getByRole("button", { name: "Restore working interface" }), ).toBeVisible(); const downloadEvent = page.waitForEvent("download"); - await page.getByRole("button", { name: "Export session continuity" }).click(); + await page.getByRole("button", { name: "Download recovery backup" }).click(); const download = await downloadEvent; expect(download.suggestedFilename()).toBe("flect-role-continuity.json"); await page - .getByRole("button", { name: "Discard session continuity" }) + .getByRole("button", { name: "Discard saved conversation" }) .click(); await expect .poll(() => page.evaluate(() => localStorage.getItem("flect.role-continuity.v1")), ) .toBeNull(); - await page.getByRole("button", { name: "Restore interface" }).click(); - await expect( - page.getByText("Custom interface state is bypassed."), - ).toHaveCount(0); + await page.getByRole("button", { name: "Restore working interface" }).click(); + await expect(page.getByText("Your interface is protected.")).toHaveCount(0); await expect .poll(() => new URL(page.url()).searchParams.has("safe")) .toBe(false); await page.reload(); - await expect( - page.getByText("Custom interface state is bypassed."), - ).toHaveCount(0); + await expect(page.getByText("Your interface is protected.")).toHaveCount(0); }); test("supports keyboard shaping and reduced motion", async ({ page }) => { @@ -1788,11 +2057,12 @@ test("supports keyboard shaping and reduced motion", async ({ page }) => { test("lets an outside agent drive the same reactive workspace through flect", async ({ page, }) => { - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Open settings" }).click(); await page.getByRole("button", { name: "Enable local control" }).click(); await expect( page.getByRole("button", { name: "Disable local control" }), ).toBeVisible(); + await page.getByRole("button", { name: "Close settings" }).click(); await expect .poll(async () => { @@ -1812,9 +2082,6 @@ test("lets an outside agent drive the same reactive workspace through flect", as await expect( page.getByRole("heading", { name: "Focused project overview" }), ).toBeVisible(); - await expect( - page.getByRole("button", { name: "Bash details" }).first(), - ).toContainText("Completed"); const repository = (await runFlect("repository", "status")) as { readonly acceptedCommit?: string; @@ -1828,9 +2095,6 @@ test("lets an outside agent drive the same reactive workspace through flect", as await runFlect("prompt", "Open the latest project"); completedPromptPages.add(page); await expect(page.getByText("The product action completed.")).toBeVisible(); - await expect( - page.getByRole("button", { name: "Bash details" }).first(), - ).toContainText("Completed"); const logs = (await runFlect("logs")) as { readonly operations?: ReadonlyArray<{ @@ -1859,7 +2123,9 @@ test("lets an outside agent drive the same reactive workspace through flect", as expect(enteredSafeMode.acceptedCommit).toBe(beforeSafeMode.acceptedCommit); await runFlect("safe", "restore"); await expect(page.locator(".topbar .safe-mode")).toHaveCount(0); - await expect(page.getByRole("button", { name: "Safe mode" })).toBeVisible(); + await expect( + page.getByRole("button", { name: "Open recovery mode" }), + ).toBeVisible(); await expect .poll(async () => { const restored = (await runFlect("repository", "status")) as { @@ -1869,12 +2135,13 @@ test("lets an outside agent drive the same reactive workspace through flect", as }) .not.toBe(enteredSafeMode.acceptedCommit); await runFlect("control", "disable"); + await page.getByRole("button", { name: "Open settings" }).click(); await expect( page.getByRole("button", { name: "Enable local control" }), ).toBeVisible(); await page.reload(); await expect(page.locator(".topbar .safe-mode")).toHaveCount(0); await expect( - page.getByRole("heading", { name: "What do you want to make?" }), + page.getByRole("heading", { name: "What do you need?" }), ).toBeVisible(); }); diff --git a/tests/e2e/native-update.spec.ts b/tests/e2e/native-update.spec.ts index bbd54b0..a20629f 100644 --- a/tests/e2e/native-update.spec.ts +++ b/tests/e2e/native-update.spec.ts @@ -29,7 +29,7 @@ test.afterEach(async ({ page }) => { }); const openUpdate = async (page: Page) => { - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Open settings" }).click(); await expect( page.getByRole("region", { name: "Flect update" }), ).toBeVisible(); diff --git a/tests/e2e/performance.spec.ts b/tests/e2e/performance.spec.ts index 0f64c8a..7a7fbe3 100644 --- a/tests/e2e/performance.spec.ts +++ b/tests/e2e/performance.spec.ts @@ -4,6 +4,12 @@ import { resetBrowserWorkspace } from "./reset-browser-workspace"; const budget = FlectPerformanceBudgets.browser; +// Shared macOS runners occasionally stall the whole browser process long +// enough for several independent budgets to fail together. Re-measure a noisy +// CI sample on a fresh page; local runs stay fail-fast and the budgets remain +// unchanged. +test.describe.configure({ retries: process.env.CI === "true" ? 2 : 0 }); + const networkProfiles = [ { cpuRate: 4, @@ -141,6 +147,112 @@ const shape = async (page: Page, instruction: string, enforceBudget = true) => { }; }; +const measureVisibleShapeResponse = async (page: Page) => { + const instruction = "Create a focused project overview"; + const input = page.getByRole("textbox", { name: "Message Flect" }); + await input.fill(instruction); + return input.evaluate( + (element, expectedInstruction) => + new Promise<{ + readonly canvasChangeMs: number; + readonly firstActivityMs: number; + readonly sendAcknowledgeMs: number; + }>((resolve, reject) => { + if (!(element instanceof HTMLTextAreaElement)) { + reject(new Error("Flect composer is not a textarea.")); + return; + } + const form = element.closest("form"); + const send = form?.querySelector('button[aria-label="Send to Flect"]'); + const shell = document.querySelector(".role-shell"); + if ( + !(form instanceof HTMLFormElement) || + !(send instanceof HTMLButtonElement) || + !(shell instanceof HTMLElement) + ) { + reject(new Error("Flect visible send controls are unavailable.")); + return; + } + const revisionBefore = shell.dataset.activeRevision; + const startedAt = performance.now(); + let sendAcknowledgeMs: number | undefined; + let firstActivityMs: number | undefined; + let canvasChangeMs: number | undefined; + const visible = (candidate: Element | null) => + candidate instanceof HTMLElement && + candidate.getClientRects().length > 0 && + getComputedStyle(candidate).visibility !== "hidden"; + const sample = () => { + const elapsedMs = performance.now() - startedAt; + const conversation = document.querySelector( + '[role="log"][aria-label="Flect conversation"]', + ); + const workbench = document.querySelector( + '[role="status"][aria-label="Workbench status"]', + ); + const stop = document.querySelector( + 'button[aria-label="Stop Flect"]', + ); + if ( + sendAcknowledgeMs === undefined && + conversation?.textContent?.includes(expectedInstruction) === true && + workbench?.textContent?.includes("Flect is responding") === true && + visible(stop) + ) { + sendAcknowledgeMs = elapsedMs; + } + const activity = document.querySelector( + ".work-log, article.activity-card", + ); + if (firstActivityMs === undefined && visible(activity)) { + firstActivityMs = elapsedMs; + } + const heading = [...document.querySelectorAll("h1, h2, h3")].find( + (candidate) => + candidate.textContent?.trim() === "Focused project overview", + ); + if ( + canvasChangeMs === undefined && + visible(heading ?? null) && + shell.dataset.activeRevision !== revisionBefore + ) { + canvasChangeMs = elapsedMs; + } + if ( + sendAcknowledgeMs !== undefined && + firstActivityMs !== undefined && + canvasChangeMs !== undefined + ) { + observer.disconnect(); + clearTimeout(timeout); + resolve({ + canvasChangeMs, + firstActivityMs, + sendAcknowledgeMs, + }); + } + }; + const observer = new MutationObserver(sample); + const timeout = setTimeout(() => { + observer.disconnect(); + reject( + new Error( + "Flect did not visibly acknowledge, show activity, and change the canvas.", + ), + ); + }, 10_000); + observer.observe(document.documentElement, { + attributes: true, + childList: true, + subtree: true, + }); + send.click(); + sample(); + }), + instruction, + ); +}; + test.beforeEach(async ({ page }) => { await resetBrowserWorkspace(page, { viewOnly: true }); await expect( @@ -277,6 +389,42 @@ test("enforces the static Astro shell and cold/warm interaction budgets", async }); }); +test("visibly responds to Send before completing the canvas change", async ({ + page, +}) => { + await activate(page); + const metrics = await measureVisibleShapeResponse(page); + + expect( + metrics.sendAcknowledgeMs, + "visible send acknowledgement milliseconds", + ).toBeLessThan(budget.sendVisualAcknowledgeMs); + expect( + metrics.firstActivityMs, + "first visible agent activity milliseconds", + ).toBeLessThan(budget.firstVisibleActivityMs); + expect( + metrics.canvasChangeMs, + "deterministic visible canvas change milliseconds", + ).toBeLessThan(budget.deterministicCanvasChangeMs); + // React may commit acknowledgement and activity in the same render. The + // contract is that acknowledgement is already visible by completion, not + // that separate commits must be observable on every machine. + expect(metrics.sendAcknowledgeMs).toBeLessThanOrEqual(metrics.canvasChangeMs); + expect(metrics.firstActivityMs).toBeLessThanOrEqual(metrics.canvasChangeMs); + await expect( + page.getByRole("heading", { name: "Focused project overview" }), + ).toBeVisible(); + await expect( + page.getByRole("status", { name: "Workbench status" }), + ).toContainText("Flect is ready"); + report({ + canvasChangeMs: Math.round(metrics.canvasChangeMs), + firstVisibleActivityMs: Math.round(metrics.firstActivityMs), + sendVisualAcknowledgeMs: Math.round(metrics.sendAcknowledgeMs), + }); +}); + test("gates the static Astro shell on Fast and Slow 4G with 4x CPU", async ({ page, }) => { @@ -327,6 +475,8 @@ test("gates the static Astro shell on Fast and Slow 4G with 4x CPU", async ({ readonly reportPrefix: string; }> = []; let warmFast4gActivationMs = Number.POSITIVE_INFINITY; + let warmFast4gActivationMinMs = Number.POSITIVE_INFINITY; + let warmFast4gActivationMaxMs = Number.POSITIVE_INFINITY; try { await session.send("Network.enable"); @@ -391,8 +541,20 @@ test("gates the static Astro shell on Fast and Slow 4G with 4x CPU", async ({ }); await page.goto(viewUrl("fast4g-warmup")); await activate(page); - await page.goto(viewUrl("fast4g-warm")); - warmFast4gActivationMs = await activate(page); + const warmSamples: Array = []; + for (let sample = 0; sample < 3; sample += 1) { + await page.goto(viewUrl(`fast4g-warm-${sample + 1}`)); + warmSamples.push(await activate(page)); + } + const orderedWarmSamples = warmSamples.toSorted( + (left, right) => left - right, + ); + warmFast4gActivationMs = + orderedWarmSamples[1] ?? Number.POSITIVE_INFINITY; + warmFast4gActivationMinMs = + orderedWarmSamples[0] ?? Number.POSITIVE_INFINITY; + warmFast4gActivationMaxMs = + orderedWarmSamples[2] ?? Number.POSITIVE_INFINITY; } } } finally { @@ -409,6 +571,8 @@ test("gates the static Astro shell on Fast and Slow 4G with 4x CPU", async ({ const reported: Record = { warmFast4gActivationMs: Math.round(warmFast4gActivationMs), + warmFast4gActivationMaxMs: Math.round(warmFast4gActivationMaxMs), + warmFast4gActivationMinMs: Math.round(warmFast4gActivationMinMs), }; for (const result of results) { const profile = networkProfiles.find( diff --git a/tests/e2e/portable-extensions.spec.ts b/tests/e2e/portable-extensions.spec.ts index ae2b3a4..5a9b2d8 100644 --- a/tests/e2e/portable-extensions.spec.ts +++ b/tests/e2e/portable-extensions.spec.ts @@ -2,6 +2,7 @@ import AxeBuilder from "@axe-core/playwright"; import { expect, type Page, test } from "@playwright/test"; import { portableExtensionCapsule } from "../fixtures/portable-extensions/capsules"; import { resetBrowserWorkspace } from "./reset-browser-workspace"; +import { revealActivity } from "./reveal-activity"; const browserFailures = new WeakMap>(); @@ -117,8 +118,9 @@ test("reviews, tests, activates, discovers, disables, and removes role-scoped pa const candidatePromptFinished = promptFinished(page); await previewComposer.press("Enter"); const candidateActivity = page - .getByRole("button", { name: "Bash details" }) + .locator('button[aria-label="Bash details"]') .last(); + await revealActivity(candidateActivity.locator("xpath=ancestor::article")); await expect(candidateActivity).toContainText("Completed", { timeout: 30_000, }); @@ -141,7 +143,8 @@ test("reviews, tests, activates, discovers, disables, and removes role-scoped pa await composer.fill("Inspect portable extensions"); const acceptedPromptFinished = promptFinished(page); await composer.press("Enter"); - const activity = page.getByRole("button", { name: "Bash details" }).last(); + const activity = page.locator('button[aria-label="Bash details"]').last(); + await revealActivity(activity.locator("xpath=ancestor::article")); await expect(activity).toContainText("Completed", { timeout: 30_000 }); await activity.click(); const output = page.locator(".activity-card__details pre").last(); diff --git a/tests/e2e/product-capability.spec.ts b/tests/e2e/product-capability.spec.ts index cff3c40..cf61472 100644 --- a/tests/e2e/product-capability.spec.ts +++ b/tests/e2e/product-capability.spec.ts @@ -134,12 +134,12 @@ test.beforeEach(async ({ page }) => { await expect( page.getByRole("textbox", { name: "Message Flect" }), ).toBeEnabled(); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Open settings" }).click(); await page.getByRole("button", { name: "Enable local control" }).click(); await expect( page.getByRole("button", { name: "Disable local control" }), ).toBeVisible(); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Close settings" }).click(); }); test.afterEach(async ({ page }) => { @@ -242,12 +242,12 @@ test("drives digest-bound permission lifecycle through protected UI, controller, ).toBeVisible(); await page.reload(); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Open settings" }).click(); await page.getByRole("button", { name: "Enable local control" }).click(); await expect( page.getByRole("button", { name: "Disable local control" }), ).toBeVisible(); - await page.getByRole("button", { name: "Diagnostics" }).click(); + await page.getByRole("button", { name: "Close settings" }).click(); await page.getByText("Product capabilities").click(); await expect( page.getByText("Required · Granted · Always allow"), diff --git a/tests/e2e/reveal-activity.ts b/tests/e2e/reveal-activity.ts new file mode 100644 index 0000000..5b65d59 --- /dev/null +++ b/tests/e2e/reveal-activity.ts @@ -0,0 +1,10 @@ +import { expect, type Locator } from "@playwright/test"; + +export const revealActivity = async (activity: Locator) => { + if (await activity.isVisible()) return; + await activity + .locator("xpath=ancestor::section[contains(@class, 'work-log')]") + .locator(".work-log__summary") + .click(); + await expect(activity).toBeVisible(); +}; diff --git a/tests/e2e/sharing.spec.ts b/tests/e2e/sharing.spec.ts index 28375ca..2e39859 100644 --- a/tests/e2e/sharing.spec.ts +++ b/tests/e2e/sharing.spec.ts @@ -312,7 +312,15 @@ const expectAccessible = async (page: Page, include: string) => { .include(include) .withTags(["wcag2a", "wcag2aa", "wcag21a", "wcag21aa", "wcag22aa"]) .analyze(); - expect(result.violations.map((violation) => violation.id)).toEqual([]); + expect( + result.violations.map((violation) => ({ + id: violation.id, + nodes: violation.nodes.map((node) => ({ + summary: node.failureSummary, + target: node.target, + })), + })), + ).toEqual([]); }; test.beforeEach(async ({ page }) => { @@ -449,9 +457,9 @@ test("retains, previews, exports, removes, and explicitly deletes a real Git sha .getByRole("dialog", { name: "Shared sources" }) .getByText("No shared sources yet"), ).toBeVisible(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("prepares and activates an exact fast-forward update from real Git history", async ({ @@ -504,9 +512,9 @@ test("prepares and activates an exact fast-forward update from real Git history" fixtures.compatibleUpdate.commit, ); await library.getByRole("button", { name: "Close shared sources" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("routes fork personalization through one composer and activates a real two-parent merge", async ({ @@ -530,15 +538,10 @@ test("routes fork personalization through one composer and activates a real two- const composer = page.getByRole("textbox", { name: "Message Flect" }); await composer.fill(`Personalize shared fork ${fixtures.initial.commit}`); await composer.press("Enter"); - await expect( - page - .getByRole("button", { name: "Bash details" }) - .filter({ hasText: "Completed" }) - .last(), - ).toBeVisible({ timeout: 30_000 }); await expect(page.locator("form.composer")).toHaveAttribute( "aria-busy", "false", + { timeout: 30_000 }, ); completedPromptPages.add(page); await expect( @@ -551,7 +554,9 @@ test("routes fork personalization through one composer and activates a real two- buffer: Buffer.from(fixtures.compatibleUpdate.archive), }); review = page.getByRole("region", { name: "Weather workspace" }); - await expect(review.getByText(/1\.1\.0 · update/)).toBeVisible(); + await expect(review.getByText(/1\.1\.0 · update/)).toBeVisible({ + timeout: 30_000, + }); await review.getByRole("button", { name: "Prepare update" }).click(); await expect(review.getByText(/1\.1\.0 · fork/)).toBeVisible({ timeout: 30_000, @@ -579,9 +584,9 @@ test("routes fork personalization through one composer and activates a real two- expect(exported.upstream).toContain("refreshed: true"); expect(exported.decoded.manifest.signatures).toEqual([]); await library.getByRole("button", { name: "Close shared sources" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("resolves a real Git conflict with Flect and activates only the explicit resolution", async ({ @@ -607,15 +612,10 @@ test("resolves a real Git conflict with Flect and activates only the explicit re `Personalize shared conflict fork ${fixtures.initial.commit}`, ); await composer.press("Enter"); - await expect( - page - .getByRole("button", { name: "Bash details" }) - .filter({ hasText: "Completed" }) - .last(), - ).toBeVisible({ timeout: 30_000 }); await expect(page.locator("form.composer")).toHaveAttribute( "aria-busy", "false", + { timeout: 30_000 }, ); completedPromptPages.add(page); await expect( @@ -684,9 +684,9 @@ test("resolves a real Git conflict with Flect and activates only the explicit re expect(exported.weather).toContain("warning: true"); expect(exported.decoded.manifest.signatures).toEqual([]); await library.getByRole("button", { name: "Close shared sources" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("reviews a credential-free HTTPS share through the same inactive boundary", async ({ @@ -725,9 +725,9 @@ test("reviews a credential-free HTTPS share through the same inactive boundary", review.getByText("Inactive until you activate it"), ).toBeVisible(); await review.getByRole("button", { name: "Discard shared source" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("clones and reviews an exact public Git descriptor through wasm-git", async ({ @@ -799,9 +799,9 @@ test("clones and reviews an exact public Git descriptor through wasm-git", async await page.unroute(pattern); await rm(root, { force: true, recursive: true }); } - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("opens a host-composed private adapter without exposing its credential closure", async ({ @@ -855,9 +855,9 @@ test("opens a host-composed private adapter without exposing its credential clos ), ).toBe(false); await review.getByRole("button", { name: "Discard shared source" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); test("sharing review and source library remain contained at 320px and 200 percent text", async ({ @@ -946,7 +946,7 @@ test("inspects every artifact kind inertly and contains a malicious local archiv ).toBeEnabled(); await review.getByRole("button", { name: "Discard shared source" }).click(); await expect( - page.getByRole("heading", { name: "What do you want to make?" }), + page.getByRole("heading", { name: "What do you need?" }), ).toBeVisible(); await page.getByRole("button", { name: "Actions" }).click(); @@ -965,7 +965,7 @@ test("inspects every artifact kind inertly and contains a malicious local archiv /The shared file could not be reviewed safely/, ); await expect( - page.getByRole("heading", { name: "What do you want to make?" }), + page.getByRole("heading", { name: "What do you need?" }), ).toBeVisible(); await expect(page.getByText("private archive detail")).toHaveCount(0); await expect(page.locator("body")).not.toContainText( @@ -982,7 +982,7 @@ test("inspects every artifact kind inertly and contains a malicious local archiv ).toBeVisible(); await expect(failure).not.toBeVisible(); await page.getByRole("button", { name: "Discard shared source" }).click(); - await expect(page.getByRole("button", { name: "Diagnostics" })).toContainText( - "Local control off", - ); + await expect( + page.getByRole("button", { name: "Open settings" }), + ).toContainText("Local control off"); }); diff --git a/tests/vitest.setup.ts b/tests/vitest.setup.ts new file mode 100644 index 0000000..e74bd68 --- /dev/null +++ b/tests/vitest.setup.ts @@ -0,0 +1,9 @@ +if (globalThis.ResizeObserver === undefined) { + globalThis.ResizeObserver = class ResizeObserverStub { + disconnect() {} + + observe() {} + + unobserve() {} + }; +} diff --git a/tsconfig.json b/tsconfig.json index e12bd42..92586b3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,11 @@ { + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"], + "@shared/*": ["./shared/*"] + } + }, "files": [], "references": [ { "path": "./tsconfig.app.json" }, diff --git a/vite.config.ts b/vite.config.ts index aede65c..b2f1e80 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,4 +1,5 @@ import { fileURLToPath, URL } from "node:url"; +import tailwindcss from "@tailwindcss/vite"; import react from "@vitejs/plugin-react"; import { defineConfig, type UserConfig } from "vite"; @@ -68,7 +69,18 @@ export const browserExecutionHeaders = { export const flectViteConfig = { envPrefix: ["PUBLIC_", "VITE_"], - plugins: [react(), browserBundleAnalysis, immutablePreviewAssets], + optimizeDeps: { + // The Git worker is loaded only after the workspace island hydrates. Warm + // its browser entry before Astro serves the native shell so Vite does not + // invalidate the module graph while Tauri is opening the workspace. + include: ["wasm-git/lg2_opfs_async.js"], + }, + plugins: [ + react(), + tailwindcss(), + browserBundleAnalysis, + immutablePreviewAssets, + ], worker: { format: "es", }, diff --git a/vitest.config.ts b/vitest.config.ts index 99116d1..5025163 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -19,6 +19,7 @@ export default defineConfig({ }, test: { environment: "node", + setupFiles: ["./tests/vitest.setup.ts"], include: [ "cli/**/*.test.ts", "examples/**/*.test.ts",