From dd6b09ebe4f44c2b3193083f9eb7d0b60a1837ee Mon Sep 17 00:00:00 2001 From: ScriptSmith Date: Wed, 1 Jul 2026 23:45:10 +1000 Subject: [PATCH 1/2] Consolidate top bar --- src/config/ui.rs | 4 + ui/pnpm-lock.yaml | 357 +++++++++++----------- ui/src/components/Header/Header.tsx | 125 +++++++- ui/src/components/PageGuard/PageGuard.tsx | 4 + ui/src/config/defaults.ts | 2 + ui/src/config/types.ts | 2 + ui/src/pages/SkillsPage.tsx | 155 ++++++++++ ui/src/pages/TemplatesPage.tsx | 115 +++++++ ui/src/routes/AppRoutes.tsx | 26 ++ 9 files changed, 602 insertions(+), 188 deletions(-) create mode 100644 ui/src/pages/SkillsPage.tsx create mode 100644 ui/src/pages/TemplatesPage.tsx diff --git a/src/config/ui.rs b/src/config/ui.rs index 49198ed2..182c4e8a 100644 --- a/src/config/ui.rs +++ b/src/config/ui.rs @@ -634,6 +634,10 @@ pub struct PagesConfig { #[serde(default)] pub providers: PageConfig, #[serde(default)] + pub templates: PageConfig, + #[serde(default)] + pub skills: PageConfig, + #[serde(default)] pub usage: PageConfig, #[serde(default)] pub admin: AdminPagesConfig, diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index 068575f2..57af87cb 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -4,33 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -overrides: - glob>minimatch: '>=10.2.3' - filelist>minimatch: '>=10.2.3' - '@typescript-eslint/typescript-estree>minimatch': '>=10.2.3' - eslint>minimatch: ~3.1.4 - '@eslint/config-array>minimatch': ~3.1.4 - '@eslint/eslintrc>minimatch': ~3.1.4 - eslint-plugin-jsx-a11y>minimatch: ~3.1.4 - '@rollup/plugin-terser>serialize-javascript': '>=7.0.3' - qs: '>=6.14.2' - workbox-build>ajv: '>=8.18.0' - '@modelcontextprotocol/sdk>ajv': '>=8.18.0' - hono: '>=4.12.25' - '@modelcontextprotocol/sdk>@hono/node-server': '>=1.19.10' - '@modelcontextprotocol/sdk>express-rate-limit': '>=8.2.2' - flatted: '>=3.4.2' - picomatch: '>=4.0.4' - '@rollup/pluginutils>picomatch': '>=2.3.2 <4.0.0 || >=4.0.4' - lodash: '>=4.18.1' - lodash-es: '>=4.18.1' - defu: '>=6.1.7' - vite: '>=7.3.5 <8' - ws: '>=8.21.0' - fast-uri: '>=3.1.2' - '@babel/plugin-transform-modules-systemjs': '>=7.29.4' - esbuild: '>=0.28.1' - importers: .: @@ -164,7 +137,7 @@ importers: version: 10.2.11(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) '@storybook/addon-docs': specifier: ^10.2.11 - version: 10.2.11(@types/react@19.2.14)(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) + version: 10.2.11(@types/react@19.2.14)(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) '@storybook/addon-vitest': specifier: ^10.2.11 version: 10.2.11(@vitest/browser-playwright@4.1.8)(@vitest/browser@4.1.8)(@vitest/runner@4.1.8)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vitest@4.1.8) @@ -173,7 +146,7 @@ importers: version: 10.2.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) '@storybook/react-vite': specifier: ^10.2.11 - version: 10.2.11(esbuild@0.28.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) + version: 10.2.11(esbuild@0.27.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) '@tailwindcss/vite': specifier: ^4.2.1 version: 4.2.1(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) @@ -250,7 +223,7 @@ importers: specifier: ^8.56.1 version: 8.56.1(eslint@9.39.3(jiti@2.6.1))(typescript@5.9.3) vite: - specifier: '>=7.3.5 <8' + specifier: ^7.3.1 version: 7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0) vite-plugin-pwa: specifier: ^1.2.0 @@ -899,158 +872,158 @@ packages: '@duckdb/duckdb-wasm@1.33.1-dev13.0': resolution: {integrity: sha512-d6TuZRKnOMZPvoZqeCTLXUbpr8QcZwujrQ2cJRr4tk0hBdMO8AF8h6J39MX7BRtbQS9X6ZDihjAcfHJhiKIhug==} - '@esbuild/aix-ppc64@0.28.1': - resolution: {integrity: sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==} + '@esbuild/aix-ppc64@0.27.7': + resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} engines: {node: '>=18'} cpu: [ppc64] os: [aix] - '@esbuild/android-arm64@0.28.1': - resolution: {integrity: sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==} + '@esbuild/android-arm64@0.27.7': + resolution: {integrity: sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==} engines: {node: '>=18'} cpu: [arm64] os: [android] - '@esbuild/android-arm@0.28.1': - resolution: {integrity: sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==} + '@esbuild/android-arm@0.27.7': + resolution: {integrity: sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==} engines: {node: '>=18'} cpu: [arm] os: [android] - '@esbuild/android-x64@0.28.1': - resolution: {integrity: sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==} + '@esbuild/android-x64@0.27.7': + resolution: {integrity: sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==} engines: {node: '>=18'} cpu: [x64] os: [android] - '@esbuild/darwin-arm64@0.28.1': - resolution: {integrity: sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==} + '@esbuild/darwin-arm64@0.27.7': + resolution: {integrity: sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] - '@esbuild/darwin-x64@0.28.1': - resolution: {integrity: sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==} + '@esbuild/darwin-x64@0.27.7': + resolution: {integrity: sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==} engines: {node: '>=18'} cpu: [x64] os: [darwin] - '@esbuild/freebsd-arm64@0.28.1': - resolution: {integrity: sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==} + '@esbuild/freebsd-arm64@0.27.7': + resolution: {integrity: sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-x64@0.28.1': - resolution: {integrity: sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==} + '@esbuild/freebsd-x64@0.27.7': + resolution: {integrity: sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] - '@esbuild/linux-arm64@0.28.1': - resolution: {integrity: sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==} + '@esbuild/linux-arm64@0.27.7': + resolution: {integrity: sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==} engines: {node: '>=18'} cpu: [arm64] os: [linux] - '@esbuild/linux-arm@0.28.1': - resolution: {integrity: sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==} + '@esbuild/linux-arm@0.27.7': + resolution: {integrity: sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==} engines: {node: '>=18'} cpu: [arm] os: [linux] - '@esbuild/linux-ia32@0.28.1': - resolution: {integrity: sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==} + '@esbuild/linux-ia32@0.27.7': + resolution: {integrity: sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==} engines: {node: '>=18'} cpu: [ia32] os: [linux] - '@esbuild/linux-loong64@0.28.1': - resolution: {integrity: sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==} + '@esbuild/linux-loong64@0.27.7': + resolution: {integrity: sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==} engines: {node: '>=18'} cpu: [loong64] os: [linux] - '@esbuild/linux-mips64el@0.28.1': - resolution: {integrity: sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==} + '@esbuild/linux-mips64el@0.27.7': + resolution: {integrity: sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] - '@esbuild/linux-ppc64@0.28.1': - resolution: {integrity: sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==} + '@esbuild/linux-ppc64@0.27.7': + resolution: {integrity: sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] - '@esbuild/linux-riscv64@0.28.1': - resolution: {integrity: sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==} + '@esbuild/linux-riscv64@0.27.7': + resolution: {integrity: sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] - '@esbuild/linux-s390x@0.28.1': - resolution: {integrity: sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==} + '@esbuild/linux-s390x@0.27.7': + resolution: {integrity: sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==} engines: {node: '>=18'} cpu: [s390x] os: [linux] - '@esbuild/linux-x64@0.28.1': - resolution: {integrity: sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==} + '@esbuild/linux-x64@0.27.7': + resolution: {integrity: sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==} engines: {node: '>=18'} cpu: [x64] os: [linux] - '@esbuild/netbsd-arm64@0.28.1': - resolution: {integrity: sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==} + '@esbuild/netbsd-arm64@0.27.7': + resolution: {integrity: sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] - '@esbuild/netbsd-x64@0.28.1': - resolution: {integrity: sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==} + '@esbuild/netbsd-x64@0.27.7': + resolution: {integrity: sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] - '@esbuild/openbsd-arm64@0.28.1': - resolution: {integrity: sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==} + '@esbuild/openbsd-arm64@0.27.7': + resolution: {integrity: sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] - '@esbuild/openbsd-x64@0.28.1': - resolution: {integrity: sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==} + '@esbuild/openbsd-x64@0.27.7': + resolution: {integrity: sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] - '@esbuild/openharmony-arm64@0.28.1': - resolution: {integrity: sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==} + '@esbuild/openharmony-arm64@0.27.7': + resolution: {integrity: sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==} engines: {node: '>=18'} cpu: [arm64] os: [openharmony] - '@esbuild/sunos-x64@0.28.1': - resolution: {integrity: sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==} + '@esbuild/sunos-x64@0.27.7': + resolution: {integrity: sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] - '@esbuild/win32-arm64@0.28.1': - resolution: {integrity: sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==} + '@esbuild/win32-arm64@0.27.7': + resolution: {integrity: sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==} engines: {node: '>=18'} cpu: [arm64] os: [win32] - '@esbuild/win32-ia32@0.28.1': - resolution: {integrity: sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==} + '@esbuild/win32-ia32@0.27.7': + resolution: {integrity: sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==} engines: {node: '>=18'} cpu: [ia32] os: [win32] - '@esbuild/win32-x64@0.28.1': - resolution: {integrity: sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==} + '@esbuild/win32-x64@0.27.7': + resolution: {integrity: sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==} engines: {node: '>=18'} cpu: [x64] os: [win32] @@ -1129,7 +1102,7 @@ packages: resolution: {integrity: sha512-dr8/3zEaB+p0D2n/IUrlPF1HZm586qgJNXK1a9fhg/PzdtkK7Ksd5l312tJX2yBuALqDYBlG20QEbayqPyxn+g==} engines: {node: '>=18.14.1'} peerDependencies: - hono: '>=4.12.25' + hono: ^4 '@hookform/resolvers@5.2.2': resolution: {integrity: sha512-A/IxlMLShx3KjV/HeTcTfaMxdwy690+L/ZADoeaTltLx+CVuzkeVIPuybK3jrRfw7YZnmdKsVVHAlEPIAEUNlA==} @@ -1207,7 +1180,7 @@ packages: resolution: {integrity: sha512-6PyZBYKnnVNqOSB0YFly+62R7dmov8segT27A+RVTBVd4iAE6kbW9QBJGlyR2yG4D4ohzhZSTIu7BK1UTtmFFA==} peerDependencies: typescript: '>= 4.3.x' - vite: '>=7.3.5 <8' + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 peerDependenciesMeta: typescript: optional: true @@ -1884,15 +1857,15 @@ packages: resolution: {integrity: sha512-am7/kfMUSSwQt+9Cwzwe9cUUk9vFGJktr6Lgh3LDuLs35mHzpIpV+DgLqGlGsvWioriha9tNC57q1QwRop2KHA==} peerDependencies: storybook: ^10.2.11 - vite: '>=7.3.5 <8' + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 '@storybook/csf-plugin@10.2.11': resolution: {integrity: sha512-sHPc5SaTpee+WsTI7N8DUFYo/DJj3BxZNuzmRkPXN3vf/aHOPdGKLZiglIRQvXBucKF2JDSpbYHoz9+702O/cQ==} peerDependencies: - esbuild: '>=0.28.1' + esbuild: '*' rollup: '*' storybook: ^10.2.11 - vite: '>=7.3.5 <8' + vite: '*' webpack: '*' peerDependenciesMeta: esbuild: @@ -1926,7 +1899,7 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 storybook: ^10.2.11 - vite: '>=7.3.5 <8' + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 '@storybook/react@10.2.11': resolution: {integrity: sha512-JGfmA8AE5/hZFkHsXJ2tT+Q4hoTOZZUSfKKG9u/Dn0lh/lSAYm1gpH+5ZFFGScZZ1p+ByFVxJnSRUBn/taaZgw==} @@ -2052,7 +2025,7 @@ packages: '@tailwindcss/vite@4.2.1': resolution: {integrity: sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w==} peerDependencies: - vite: '>=7.3.5 <8' + vite: ^5.2.0 || ^6 || ^7 '@tanstack/query-core@5.90.20': resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} @@ -2363,6 +2336,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@upsetjs/venn.js@2.0.0': resolution: {integrity: sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw==} @@ -2371,7 +2345,7 @@ packages: resolution: {integrity: sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: - vite: '>=7.3.5 <8' + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 '@vitest/browser-playwright@4.1.8': resolution: {integrity: sha512-SR7FqgegaexEg73xvf3ArtygXegagMdXnL0EZMpxrWvvhQxvicD/E8p0ib0J91riPRtQUViyh67Xjw3NqvyhVg==} @@ -2403,7 +2377,7 @@ packages: resolution: {integrity: sha512-LEiN/xe4OSIbKe9HQIp5OC24agGD9J5CnmMgsLohVVoOPWL9a2sBoR6VBx43jQZb7Kr1l4RCuyCJzcAa0+dojw==} peerDependencies: msw: ^2.4.9 - vite: '>=7.3.5 <8' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: msw: optional: true @@ -2624,6 +2598,9 @@ packages: brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + brace-expansion@2.1.1: + resolution: {integrity: sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==} + brace-expansion@5.0.3: resolution: {integrity: sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==} engines: {node: 18 || 20 || >=22} @@ -3218,8 +3195,8 @@ packages: es-toolkit@1.44.0: resolution: {integrity: sha512-6penXeZalaV88MM3cGkFZZfOoLGWshWWfdy0tWw/RlVVyhvMaWSBTOvXNeiW3e5FwdS5ePW0LGEu17zT139ktg==} - esbuild@0.28.1: - resolution: {integrity: sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==} + esbuild@0.27.7: + resolution: {integrity: sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==} engines: {node: '>=18'} hasBin: true @@ -3395,7 +3372,7 @@ packages: resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} engines: {node: '>=12.0.0'} peerDependencies: - picomatch: '>=4.0.4' + picomatch: ^3 || ^4 peerDependenciesMeta: picomatch: optional: true @@ -4074,6 +4051,9 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash-es@4.17.23: + resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} + lodash-es@4.18.1: resolution: {integrity: sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==} @@ -4313,6 +4293,10 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimatch@5.1.9: + resolution: {integrity: sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==} + engines: {node: '>=10'} + minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} @@ -4503,6 +4487,10 @@ packages: picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + picomatch@2.3.2: + resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} + engines: {node: '>=8.6'} + picomatch@4.0.4: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} @@ -4599,6 +4587,9 @@ packages: quickjs-emscripten-core@0.31.0: resolution: {integrity: sha512-oQz8p0SiKDBc1TC7ZBK2fr0GoSHZKA0jZIeXxsnCyCs4y32FStzCW4d1h6E1sE0uHDMbGITbk2zhNaytaoJwXQ==} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -4869,6 +4860,9 @@ packages: resolution: {integrity: sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==} engines: {node: '>=0.4'} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -4904,9 +4898,8 @@ packages: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} - serialize-javascript@7.0.5: - resolution: {integrity: sha512-F4LcB0UqUl1zErq+1nYEEzSHJnIwb3AF2XWB94b+afhrekOUijwooAYqFyRbjYkm2PAKBabx6oYv/xDxNi8IBw==} - engines: {node: '>=20.0.0'} + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} serve-static@2.2.1: resolution: {integrity: sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==} @@ -5535,7 +5528,7 @@ packages: engines: {node: '>=16.0.0'} peerDependencies: '@vite-pwa/assets-generator': ^1.0.0 - vite: '>=7.3.5 <8' + vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 workbox-build: ^7.4.0 workbox-window: ^7.4.0 peerDependenciesMeta: @@ -5598,7 +5591,7 @@ packages: '@vitest/ui': 4.1.8 happy-dom: '*' jsdom: '*' - vite: '>=7.3.5 <8' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 peerDependenciesMeta: '@edge-runtime/vm': optional: true @@ -6621,12 +6614,12 @@ snapshots: dependencies: '@chevrotain/gast': 11.1.2 '@chevrotain/types': 11.1.2 - lodash-es: 4.18.1 + lodash-es: 4.17.23 '@chevrotain/gast@11.1.2': dependencies: '@chevrotain/types': 11.1.2 - lodash-es: 4.18.1 + lodash-es: 4.17.23 '@chevrotain/regexp-to-ast@11.1.2': {} @@ -6663,82 +6656,82 @@ snapshots: dependencies: apache-arrow: 17.0.0 - '@esbuild/aix-ppc64@0.28.1': + '@esbuild/aix-ppc64@0.27.7': optional: true - '@esbuild/android-arm64@0.28.1': + '@esbuild/android-arm64@0.27.7': optional: true - '@esbuild/android-arm@0.28.1': + '@esbuild/android-arm@0.27.7': optional: true - '@esbuild/android-x64@0.28.1': + '@esbuild/android-x64@0.27.7': optional: true - '@esbuild/darwin-arm64@0.28.1': + '@esbuild/darwin-arm64@0.27.7': optional: true - '@esbuild/darwin-x64@0.28.1': + '@esbuild/darwin-x64@0.27.7': optional: true - '@esbuild/freebsd-arm64@0.28.1': + '@esbuild/freebsd-arm64@0.27.7': optional: true - '@esbuild/freebsd-x64@0.28.1': + '@esbuild/freebsd-x64@0.27.7': optional: true - '@esbuild/linux-arm64@0.28.1': + '@esbuild/linux-arm64@0.27.7': optional: true - '@esbuild/linux-arm@0.28.1': + '@esbuild/linux-arm@0.27.7': optional: true - '@esbuild/linux-ia32@0.28.1': + '@esbuild/linux-ia32@0.27.7': optional: true - '@esbuild/linux-loong64@0.28.1': + '@esbuild/linux-loong64@0.27.7': optional: true - '@esbuild/linux-mips64el@0.28.1': + '@esbuild/linux-mips64el@0.27.7': optional: true - '@esbuild/linux-ppc64@0.28.1': + '@esbuild/linux-ppc64@0.27.7': optional: true - '@esbuild/linux-riscv64@0.28.1': + '@esbuild/linux-riscv64@0.27.7': optional: true - '@esbuild/linux-s390x@0.28.1': + '@esbuild/linux-s390x@0.27.7': optional: true - '@esbuild/linux-x64@0.28.1': + '@esbuild/linux-x64@0.27.7': optional: true - '@esbuild/netbsd-arm64@0.28.1': + '@esbuild/netbsd-arm64@0.27.7': optional: true - '@esbuild/netbsd-x64@0.28.1': + '@esbuild/netbsd-x64@0.27.7': optional: true - '@esbuild/openbsd-arm64@0.28.1': + '@esbuild/openbsd-arm64@0.27.7': optional: true - '@esbuild/openbsd-x64@0.28.1': + '@esbuild/openbsd-x64@0.27.7': optional: true - '@esbuild/openharmony-arm64@0.28.1': + '@esbuild/openharmony-arm64@0.27.7': optional: true - '@esbuild/sunos-x64@0.28.1': + '@esbuild/sunos-x64@0.27.7': optional: true - '@esbuild/win32-arm64@0.28.1': + '@esbuild/win32-arm64@0.27.7': optional: true - '@esbuild/win32-ia32@0.28.1': + '@esbuild/win32-ia32@0.27.7': optional: true - '@esbuild/win32-x64@0.28.1': + '@esbuild/win32-x64@0.27.7': optional: true '@eslint-community/eslint-utils@4.9.1(eslint@9.39.3(jiti@2.6.1))': @@ -6929,7 +6922,7 @@ snapshots: '@mcp-ui/client@6.1.0(@preact/signals-core@1.13.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': dependencies: - '@modelcontextprotocol/ext-apps': 0.3.1(@modelcontextprotocol/sdk@1.27.0(zod@4.3.6))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76) + '@modelcontextprotocol/ext-apps': 0.3.1(@modelcontextprotocol/sdk@1.27.0(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76) '@modelcontextprotocol/sdk': 1.27.0(zod@3.25.76) '@quilted/threads': 3.3.1(@preact/signals-core@1.13.0) '@r2wc/react-to-web-component': 2.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -6954,7 +6947,7 @@ snapshots: dependencies: langium: 4.2.1 - '@modelcontextprotocol/ext-apps@0.3.1(@modelcontextprotocol/sdk@1.27.0(zod@4.3.6))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76)': + '@modelcontextprotocol/ext-apps@0.3.1(@modelcontextprotocol/sdk@1.27.0(zod@3.25.76))(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(zod@3.25.76)': dependencies: '@modelcontextprotocol/sdk': 1.27.0(zod@3.25.76) zod: 3.25.76 @@ -7326,7 +7319,7 @@ snapshots: '@rollup/plugin-terser@0.4.4(rollup@2.80.0)': dependencies: - serialize-javascript: 7.0.5 + serialize-javascript: 6.0.2 smob: 1.6.2 terser: 5.48.0 optionalDependencies: @@ -7336,7 +7329,7 @@ snapshots: dependencies: '@types/estree': 0.0.39 estree-walker: 1.0.1 - picomatch: 4.0.4 + picomatch: 2.3.2 rollup: 2.80.0 '@rollup/pluginutils@5.3.0(rollup@2.80.0)': @@ -7473,10 +7466,10 @@ snapshots: axe-core: 4.11.1 storybook: 10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@storybook/addon-docs@10.2.11(@types/react@19.2.14)(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': + '@storybook/addon-docs@10.2.11(@types/react@19.2.14)(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.14)(react@19.2.4) - '@storybook/csf-plugin': 10.2.11(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) + '@storybook/csf-plugin': 10.2.11(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) '@storybook/icons': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) '@storybook/react-dom-shim': 10.2.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)) react: 19.2.4 @@ -7504,9 +7497,9 @@ snapshots: - react - react-dom - '@storybook/builder-vite@10.2.11(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': + '@storybook/builder-vite@10.2.11(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': dependencies: - '@storybook/csf-plugin': 10.2.11(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) + '@storybook/csf-plugin': 10.2.11(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) storybook: 10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) ts-dedent: 2.2.0 vite: 7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0) @@ -7515,12 +7508,12 @@ snapshots: - rollup - webpack - '@storybook/csf-plugin@10.2.11(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': + '@storybook/csf-plugin@10.2.11(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': dependencies: storybook: 10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) unplugin: 2.3.11 optionalDependencies: - esbuild: 0.28.1 + esbuild: 0.27.7 rollup: 2.80.0 vite: 7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0) @@ -7537,11 +7530,11 @@ snapshots: react-dom: 19.2.4(react@19.2.4) storybook: 10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) - '@storybook/react-vite@10.2.11(esbuild@0.28.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': + '@storybook/react-vite@10.2.11(esbuild@0.27.7)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3)(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0))': dependencies: '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.4(typescript@5.9.3)(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) '@rollup/pluginutils': 5.3.0(rollup@2.80.0) - '@storybook/builder-vite': 10.2.11(esbuild@0.28.1)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) + '@storybook/builder-vite': 10.2.11(esbuild@0.27.7)(rollup@2.80.0)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0)) '@storybook/react': 10.2.11(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(storybook@10.2.11(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) empathic: 2.0.0 magic-string: 0.30.21 @@ -7878,7 +7871,7 @@ snapshots: '@types/estree-jsx@1.0.5': dependencies: - '@types/estree': 1.0.8 + '@types/estree': 1.0.9 '@types/estree@0.0.39': {} @@ -8373,6 +8366,10 @@ snapshots: balanced-match: 1.0.2 concat-map: 0.0.1 + brace-expansion@2.1.1: + dependencies: + balanced-match: 1.0.2 + brace-expansion@5.0.3: dependencies: balanced-match: 4.0.4 @@ -8495,7 +8492,7 @@ snapshots: '@chevrotain/regexp-to-ast': 11.1.2 '@chevrotain/types': 11.1.2 '@chevrotain/utils': 11.1.2 - lodash-es: 4.18.1 + lodash-es: 4.17.23 chokidar@4.0.3: dependencies: @@ -9071,34 +9068,34 @@ snapshots: es-toolkit@1.44.0: {} - esbuild@0.28.1: + esbuild@0.27.7: 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 + '@esbuild/aix-ppc64': 0.27.7 + '@esbuild/android-arm': 0.27.7 + '@esbuild/android-arm64': 0.27.7 + '@esbuild/android-x64': 0.27.7 + '@esbuild/darwin-arm64': 0.27.7 + '@esbuild/darwin-x64': 0.27.7 + '@esbuild/freebsd-arm64': 0.27.7 + '@esbuild/freebsd-x64': 0.27.7 + '@esbuild/linux-arm': 0.27.7 + '@esbuild/linux-arm64': 0.27.7 + '@esbuild/linux-ia32': 0.27.7 + '@esbuild/linux-loong64': 0.27.7 + '@esbuild/linux-mips64el': 0.27.7 + '@esbuild/linux-ppc64': 0.27.7 + '@esbuild/linux-riscv64': 0.27.7 + '@esbuild/linux-s390x': 0.27.7 + '@esbuild/linux-x64': 0.27.7 + '@esbuild/netbsd-arm64': 0.27.7 + '@esbuild/netbsd-x64': 0.27.7 + '@esbuild/openbsd-arm64': 0.27.7 + '@esbuild/openbsd-x64': 0.27.7 + '@esbuild/openharmony-arm64': 0.27.7 + '@esbuild/sunos-x64': 0.27.7 + '@esbuild/win32-arm64': 0.27.7 + '@esbuild/win32-ia32': 0.27.7 + '@esbuild/win32-x64': 0.27.7 escalade@3.2.0: {} @@ -9313,7 +9310,7 @@ snapshots: filelist@1.0.6: dependencies: - minimatch: 10.2.5 + minimatch: 5.1.9 finalhandler@2.1.1: dependencies: @@ -9998,6 +9995,8 @@ snapshots: dependencies: p-locate: 5.0.0 + lodash-es@4.17.23: {} + lodash-es@4.18.1: {} lodash.camelcase@4.3.0: {} @@ -10466,6 +10465,10 @@ snapshots: dependencies: brace-expansion: 1.1.12 + minimatch@5.1.9: + dependencies: + brace-expansion: 2.1.1 + minimist@1.2.8: {} minipass@7.1.3: {} @@ -10670,6 +10673,8 @@ snapshots: picocolors@1.1.1: {} + picomatch@2.3.2: {} + picomatch@4.0.4: {} pkce-challenge@5.0.1: {} @@ -10758,6 +10763,10 @@ snapshots: dependencies: '@jitl/quickjs-ffi-types': 0.31.0 + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + range-parser@1.2.1: {} raw-body@3.0.2: @@ -11137,6 +11146,8 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 + safe-buffer@5.2.1: {} + safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -11178,7 +11189,9 @@ snapshots: transitivePeerDependencies: - supports-color - serialize-javascript@7.0.5: {} + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 serve-static@2.2.1: dependencies: @@ -11310,7 +11323,7 @@ snapshots: '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) '@vitest/expect': 3.2.4 '@vitest/spy': 3.2.4 - esbuild: 0.28.1 + esbuild: 0.27.7 open: 10.2.0 recast: 0.23.11 semver: 7.7.4 @@ -12057,7 +12070,7 @@ snapshots: vite@7.3.5(@types/node@24.10.13)(jiti@2.6.1)(lightningcss@1.31.1)(terser@5.48.0): dependencies: - esbuild: 0.28.1 + esbuild: 0.27.7 fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 postcss: 8.5.6 diff --git a/ui/src/components/Header/Header.tsx b/ui/src/components/Header/Header.tsx index e7b4f0a8..c9f36af6 100644 --- a/ui/src/components/Header/Header.tsx +++ b/ui/src/components/Header/Header.tsx @@ -1,8 +1,10 @@ -import { Link, NavLink, useLocation } from "react-router-dom"; +import { Link, NavLink, useLocation, useNavigate } from "react-router-dom"; import { BarChart3, BookOpen, Box, + Brain, + ClipboardPenLine, FolderOpen, Key, Menu, @@ -10,10 +12,17 @@ import { Palette, Server, Shield, + ToolCase, WandSparkles, UsersRound, } from "lucide-react"; import { Button } from "@/components/Button/Button"; +import { + Dropdown, + DropdownContent, + DropdownItem, + DropdownTrigger, +} from "@/components/Dropdown/Dropdown"; import { HadrianIcon } from "@/components/HadrianIcon/HadrianIcon"; import { ThemeToggle } from "@/components/ThemeToggle/ThemeToggle"; import { UserMenu } from "@/components/UserMenu/UserMenu"; @@ -32,18 +41,45 @@ export interface NavItem { pageKey?: string; } -export const navItems: NavItem[] = [ +/** A set of nav items collapsed under a single top-bar dropdown (e.g. "Resources"). */ +export interface NavGroup { + label: string; + icon: React.ComponentType<{ className?: string }>; + items: NavItem[]; +} + +export type NavEntry = NavItem | NavGroup; + +function isNavGroup(entry: NavEntry): entry is NavGroup { + return "items" in entry; +} + +/** Ordered top-bar navigation. Individual links plus grouped dropdowns. */ +export const navEntries: NavEntry[] = [ { to: "/chat", icon: MessageSquare, label: "Chat", pageKey: "chat" }, { to: "/studio", icon: Palette, label: "Studio", pageKey: "studio" }, { to: "/projects", icon: FolderOpen, label: "Projects", pageKey: "projects" }, { to: "/teams", icon: UsersRound, label: "Teams", pageKey: "teams" }, - { to: "/knowledge-bases", icon: BookOpen, label: "Knowledge", pageKey: "knowledge_bases" }, - { to: "/containers", icon: Box, label: "Containers", pageKey: "containers" }, - { to: "/api-keys", icon: Key, label: "API Keys", pageKey: "api_keys" }, - { to: "/providers", icon: Server, label: "Providers", pageKey: "providers" }, { to: "/usage", icon: BarChart3, label: "Usage", pageKey: "usage" }, + { + label: "Resources", + icon: ToolCase, + items: [ + { to: "/api-keys", icon: Key, label: "API Keys", pageKey: "api_keys" }, + { to: "/containers", icon: Box, label: "Containers", pageKey: "containers" }, + { to: "/knowledge-bases", icon: BookOpen, label: "Knowledge", pageKey: "knowledge_bases" }, + { to: "/providers", icon: Server, label: "Providers", pageKey: "providers" }, + { to: "/skills", icon: Brain, label: "Skills", pageKey: "skills" }, + { to: "/templates", icon: ClipboardPenLine, label: "Templates", pageKey: "templates" }, + ], + }, ]; +/** Flattened list of every destination, consumed by the mobile menu in UserMenu. */ +export const navItems: NavItem[] = navEntries.flatMap((entry) => + isNavGroup(entry) ? entry.items : [entry] +); + export const adminNavItem: NavItem = { to: "/admin", icon: Shield, @@ -70,15 +106,25 @@ export function Header({ onMenuClick, showMenuButton = false, className }: Heade ? config.branding.logo_dark_url : config?.branding.logo_url; - // Filter nav items by page visibility - const visibleNavItems = navItems.filter((item) => { + const isItemVisible = (item: NavItem) => { if (!item.pageKey) return true; return getPageConfig(config.pages, item.pageKey).status !== "disabled"; - }); + }; + + // Filter nav entries by page visibility; drop groups left with no visible items. + const visibleNavEntries = navEntries.reduce((acc, entry) => { + if (isNavGroup(entry)) { + const items = entry.items.filter(isItemVisible); + if (items.length > 0) acc.push({ ...entry, items }); + } else if (isItemVisible(entry)) { + acc.push(entry); + } + return acc; + }, []); // Only show admin nav if admin is enabled AND user has admin access const showAdmin = config?.admin.enabled && hasAdminAccess(user); - const allNavItems = showAdmin ? [...visibleNavItems, adminNavItem] : visibleNavItems; + const allNavEntries = showAdmin ? [...visibleNavEntries, adminNavItem] : visibleNavEntries; const isActive = (item: NavItem) => { if (item.matchPrefix) { @@ -126,13 +172,16 @@ export function Header({ onMenuClick, showMenuButton = false, className }: Heade role="navigation" aria-label="Main navigation" > - {allNavItems.map((item) => { - const Icon = item.icon; - const active = isActive(item); + {allNavEntries.map((entry) => { + if (isNavGroup(entry)) { + return ; + } + const Icon = entry.icon; + const active = isActive(entry); return ( ); })} @@ -166,3 +215,47 @@ export function Header({ onMenuClick, showMenuButton = false, className }: Heade ); } + +/** Top-bar dropdown that collapses a group of nav items (e.g. "Resources"). */ +function NavGroupMenu({ + group, + isActive, +}: { + group: NavGroup; + isActive: (item: NavItem) => boolean; +}) { + const navigate = useNavigate(); + const Icon = group.icon; + const groupActive = group.items.some(isActive); + + return ( + + + + + {group.items.map((item) => { + const ItemIcon = item.icon; + return ( + navigate(item.to)} + className={cn(isActive(item) && "bg-accent text-accent-foreground")} + > + + {item.label} + + ); + })} + + + ); +} diff --git a/ui/src/components/PageGuard/PageGuard.tsx b/ui/src/components/PageGuard/PageGuard.tsx index 1922c370..2dec7214 100644 --- a/ui/src/components/PageGuard/PageGuard.tsx +++ b/ui/src/components/PageGuard/PageGuard.tsx @@ -14,6 +14,8 @@ const mainPageOrder: MainPageKey[] = [ "containers", "api_keys", "providers", + "templates", + "skills", "usage", ]; @@ -26,6 +28,8 @@ const mainPageRoutes: Record = { containers: "/containers", api_keys: "/api-keys", providers: "/providers", + templates: "/templates", + skills: "/skills", usage: "/usage", }; diff --git a/ui/src/config/defaults.ts b/ui/src/config/defaults.ts index e4bc2c3c..5d2cdd34 100644 --- a/ui/src/config/defaults.ts +++ b/ui/src/config/defaults.ts @@ -11,6 +11,8 @@ export const defaultPagesConfig: PagesConfig = { containers: enabledPage, api_keys: enabledPage, providers: enabledPage, + templates: enabledPage, + skills: enabledPage, usage: enabledPage, admin: { dashboard: enabledPage, diff --git a/ui/src/config/types.ts b/ui/src/config/types.ts index 8391f47a..7e72da27 100644 --- a/ui/src/config/types.ts +++ b/ui/src/config/types.ts @@ -14,6 +14,8 @@ export interface PagesConfig { containers: PageConfig; api_keys: PageConfig; providers: PageConfig; + templates: PageConfig; + skills: PageConfig; usage: PageConfig; admin: AdminPagesConfig; } diff --git a/ui/src/pages/SkillsPage.tsx b/ui/src/pages/SkillsPage.tsx new file mode 100644 index 00000000..fea4ff91 --- /dev/null +++ b/ui/src/pages/SkillsPage.tsx @@ -0,0 +1,155 @@ +import { useState } from "react"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { type ColumnDef } from "@tanstack/react-table"; +import { ChevronDown, Download, Folder, Plus } from "lucide-react"; + +import { skillDeleteMutation } from "@/api/generated/@tanstack/react-query.gen"; +import type { SkillResource } from "@/api/generated/types.gen"; +import { useAuth } from "@/auth"; +import { Button } from "@/components/Button/Button"; +import { Card, CardContent } from "@/components/Card/Card"; +import { DataTable } from "@/components/DataTable/DataTable"; +import { + Dropdown, + DropdownContent, + DropdownItem, + DropdownTrigger, +} from "@/components/Dropdown/Dropdown"; +import { SkillFormModal } from "@/components/Admin"; +import { SkillImportModal } from "@/components/SkillImportModal/SkillImportModal"; +import { useToast } from "@/components/Toast/Toast"; +import { useConfirm } from "@/components/ConfirmDialog/ConfirmDialog"; +import { useUserSkills } from "@/hooks/useUserSkills"; +import { createSkillColumns } from "@/pages/admin/skillColumns"; +import { formatApiError } from "@/utils/formatApiError"; + +export default function SkillsPage() { + const { user } = useAuth(); + const { toast } = useToast(); + const confirm = useConfirm(); + const queryClient = useQueryClient(); + const { skills, isLoading } = useUserSkills(); + const [isFormOpen, setIsFormOpen] = useState(false); + const [editingSkill, setEditingSkill] = useState(null); + const [importOpen, setImportOpen] = useState(false); + const [importTab, setImportTab] = useState<"github" | "filesystem">("github"); + + const deleteSkillMutation = useMutation({ + ...skillDeleteMutation(), + onSuccess: () => { + queryClient.invalidateQueries({ queryKey: [{ _id: "skillList" }] }); + toast({ title: "Skill deleted", type: "success" }); + }, + onError: (error) => { + toast({ + title: "Failed to delete skill", + description: formatApiError(error), + type: "error", + }); + }, + }); + + const handleEdit = (skill: SkillResource) => { + setEditingSkill(skill); + setIsFormOpen(true); + }; + + const handleDelete = async (skill: SkillResource) => { + const confirmed = await confirm({ + title: "Delete Skill", + message: `Are you sure you want to delete "${skill.name}"? This action cannot be undone.`, + confirmLabel: "Delete", + variant: "destructive", + }); + if (confirmed) { + deleteSkillMutation.mutate({ path: { skill_id: skill.id } }); + } + }; + + const openImport = (tab: "github" | "filesystem") => { + setImportTab(tab); + setImportOpen(true); + }; + + const columns = createSkillColumns(handleEdit, handleDelete); + + return ( +
+
+
+

Skills

+

+ Reusable, file-based skills the model can invoke across chats and projects +

+
+ + + + + + { + setEditingSkill(null); + setIsFormOpen(true); + }} + > + + Create new + + openImport("github")}> + + Import from GitHub + + openImport("filesystem")}> + + Import from folder + + + +
+ + + + []} + data={skills} + isLoading={isLoading} + emptyMessage="No skills yet. Create one or import from GitHub or a folder." + searchColumn="name" + searchPlaceholder="Search skills..." + /> + + + + {user?.id && ( + <> + { + setIsFormOpen(false); + setEditingSkill(null); + }} + editingSkill={editingSkill} + ownerOverride={{ type: "user", user_id: user.id }} + onSaved={() => { + toast({ + title: editingSkill ? "Skill updated" : "Skill created", + type: "success", + }); + }} + /> + setImportOpen(false)} + ownerOverride={{ type: "user", user_id: user.id }} + initialTab={importTab} + /> + + )} +
+ ); +} diff --git a/ui/src/pages/TemplatesPage.tsx b/ui/src/pages/TemplatesPage.tsx new file mode 100644 index 00000000..f32d5be2 --- /dev/null +++ b/ui/src/pages/TemplatesPage.tsx @@ -0,0 +1,115 @@ +import { useState } from "react"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { type ColumnDef } from "@tanstack/react-table"; +import { Plus } from "lucide-react"; + +import { templateDeleteMutation } from "@/api/generated/@tanstack/react-query.gen"; +import type { Template } from "@/api/generated/types.gen"; +import { Button } from "@/components/Button/Button"; +import { Card, CardContent } from "@/components/Card/Card"; +import { DataTable } from "@/components/DataTable/DataTable"; +import { PromptFormModal } from "@/components/PromptFormModal/PromptFormModal"; +import { useToast } from "@/components/Toast/Toast"; +import { useConfirm } from "@/components/ConfirmDialog/ConfirmDialog"; +import { useUserTemplates } from "@/hooks/useUserPrompts"; +import { createTemplateColumns } from "@/pages/admin/promptColumns"; +import { formatApiError } from "@/utils/formatApiError"; + +export default function TemplatesPage() { + const { toast } = useToast(); + const confirm = useConfirm(); + const queryClient = useQueryClient(); + const { templates, isLoading } = useUserTemplates(); + const [isModalOpen, setIsModalOpen] = useState(false); + const [editingTemplate, setEditingTemplate] = useState