refactor: Cleanup

This commit is contained in:
Aleksander Grygier 2026-02-03 15:57:46 +01:00
parent 7ca66f5fa4
commit 67e04c92db
14 changed files with 352 additions and 212 deletions

View File

@ -798,9 +798,9 @@
"license": "MIT"
},
"node_modules/@hono/node-server": {
"version": "1.19.7",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.7.tgz",
"integrity": "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==",
"version": "1.19.9",
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.9.tgz",
"integrity": "sha512-vHL6w3ecZsky+8P5MD+eFfaGTyCeOHUIFYMGpQGbrBTSmNNoxv0if69rEZ5giu36weC5saFuznL411gRX7bJDw==",
"license": "MIT",
"engines": {
"node": ">=18.14.1"
@ -881,6 +881,7 @@
"integrity": "sha512-oJrXtQiAXLvT9clCf1K4kxp3eKsQhIaZqxEyowkBcsvZDdZkbWrVmnGknxs5flTD0VGsxrxKgBCZty1EzoiMzA==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"dependencies": {
"@swc/helpers": "^0.5.0"
}
@ -973,12 +974,12 @@
}
},
"node_modules/@modelcontextprotocol/sdk": {
"version": "1.25.1",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.1.tgz",
"integrity": "sha512-yO28oVFFC7EBoiKdAn+VqRm+plcfv4v0xp6osG/VsCB0NlPZWi87ajbCZZ8f/RvOFLEu7//rSRmuZZ7lMoe3gQ==",
"version": "1.25.3",
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.25.3.tgz",
"integrity": "sha512-vsAMBMERybvYgKbg/l4L1rhS7VXV1c0CtyJg72vwxONVX0l4ZfKVAnZEWTQixJGTzKnELjQ59e4NbdFDALRiAQ==",
"license": "MIT",
"dependencies": {
"@hono/node-server": "^1.19.7",
"@hono/node-server": "^1.19.9",
"ajv": "^8.17.1",
"ajv-formats": "^3.0.1",
"content-type": "^1.0.5",
@ -2106,6 +2107,7 @@
"integrity": "sha512-rO+YQhHucy47Vh67z318pALmd6x+K1Kj30Fb4a6oOEw4xn4zCo9KTmkMWs24c4oduEXD/eJu3badlRmsVXzyfA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"ts-dedent": "^2.0.0",
"type-fest": "~2.19"
@ -2184,24 +2186,25 @@
}
},
"node_modules/@sveltejs/kit": {
"version": "2.49.2",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.49.2.tgz",
"integrity": "sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ==",
"version": "2.50.2",
"resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.50.2.tgz",
"integrity": "sha512-875hTUkEbz+MyJIxWbQjfMaekqdmEKUUfR7JyKcpfMRZqcGyrO9Gd+iS1D/Dx8LpE5FEtutWGOtlAh4ReSAiOA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@standard-schema/spec": "^1.0.0",
"@sveltejs/acorn-typescript": "^1.0.5",
"@types/cookie": "^0.6.0",
"acorn": "^8.14.1",
"cookie": "^0.6.0",
"devalue": "^5.3.2",
"devalue": "^5.6.2",
"esm-env": "^1.2.2",
"kleur": "^4.1.5",
"magic-string": "^0.30.5",
"mrmime": "^2.0.0",
"sade": "^1.8.1",
"set-cookie-parser": "^2.6.0",
"set-cookie-parser": "^3.0.0",
"sirv": "^3.0.0"
},
"bin": {
@ -2214,11 +2217,15 @@
"@opentelemetry/api": "^1.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0",
"svelte": "^4.0.0 || ^5.0.0-next.0",
"typescript": "^5.3.3",
"vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0"
},
"peerDependenciesMeta": {
"@opentelemetry/api": {
"optional": true
},
"typescript": {
"optional": true
}
}
},
@ -2228,6 +2235,7 @@
"integrity": "sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@sveltejs/vite-plugin-svelte-inspector": "^5.0.0",
"debug": "^4.4.1",
@ -2643,6 +2651,7 @@
"integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
@ -2810,6 +2819,7 @@
"integrity": "sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@ -2877,6 +2887,7 @@
"integrity": "sha512-kVIaQE9vrN9RLCQMQ3iyRlVJpTiDUY6woHGb30JDkfJErqrQEmtdWH3gV0PBAfGZgQXoqzXOO0T3K6ioApbbAA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "8.37.0",
"@typescript-eslint/types": "8.37.0",
@ -3101,6 +3112,7 @@
"integrity": "sha512-tJxiPrWmzH8a+w9nLKlQMzAKX/7VjFs50MWgcAj7p9XQ7AQ9/35fByFYptgPELyLw+0aixTnC4pUWV+APcZ/kw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/user-event": "^14.6.1",
@ -3204,6 +3216,7 @@
"integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@vitest/utils": "3.2.4",
"pathe": "^2.0.3",
@ -3274,6 +3287,7 @@
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"license": "MIT",
"peer": true,
"bin": {
"acorn": "bin/acorn"
},
@ -3604,6 +3618,22 @@
"node": ">=8"
}
},
"node_modules/bundle-name": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"run-applescript": "^7.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@ -3955,8 +3985,7 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/debug": {
"version": "4.4.3",
@ -4037,6 +4066,49 @@
"node": ">=0.10.0"
}
},
"node_modules/default-browser": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz",
"integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==",
"dev": true,
"license": "MIT",
"dependencies": {
"bundle-name": "^4.1.0",
"default-browser-id": "^5.0.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/default-browser-id": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz",
"integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-lazy-prop": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
"integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
@ -4066,9 +4138,9 @@
}
},
"node_modules/devalue": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.3.2.tgz",
"integrity": "sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==",
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.2.tgz",
"integrity": "sha512-nPRkjWzzDQlsejL1WVifk5rvcFi/y1onBRxjaFMjZeR9mFpqu2gmAZ9xUB9/IEanEP/vBtGeGganC/GO1fmufg==",
"dev": true,
"license": "MIT"
},
@ -4210,6 +4282,7 @@
"dev": true,
"hasInstallScript": true,
"license": "MIT",
"peer": true,
"bin": {
"esbuild": "bin/esbuild"
},
@ -4270,6 +4343,7 @@
"integrity": "sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1",
@ -5275,9 +5349,9 @@
}
},
"node_modules/hono": {
"version": "4.11.1",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.1.tgz",
"integrity": "sha512-KsFcH0xxHes0J4zaQgWbYwmz3UPOOskdqZmItstUG93+Wk1ePBLkLGwbP9zlmh1BFUiL8Qp+Xfu9P7feJWpGNg==",
"version": "4.11.7",
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.7.tgz",
"integrity": "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw==",
"license": "MIT",
"peer": true,
"engines": {
@ -5458,6 +5532,22 @@
"node": ">= 0.10"
}
},
"node_modules/is-docker": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
"integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
"dev": true,
"license": "MIT",
"bin": {
"is-docker": "cli.js"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@ -5481,6 +5571,25 @@
"node": ">=0.10.0"
}
},
"node_modules/is-inside-container": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
"integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-docker": "^3.0.0"
},
"bin": {
"is-inside-container": "cli.js"
},
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
@ -5509,6 +5618,22 @@
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/is-wsl": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
"integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-inside-container": "^1.0.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
@ -5924,9 +6049,9 @@
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"dev": true,
"license": "MIT"
},
@ -7102,9 +7227,9 @@
}
},
"node_modules/minizlib": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -7114,22 +7239,6 @@
"node": ">= 18"
}
},
"node_modules/mkdirp": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
"dev": true,
"license": "MIT",
"bin": {
"mkdirp": "dist/cjs/src/bin.js"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mode-watcher": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/mode-watcher/-/mode-watcher-1.1.0.tgz",
@ -7254,6 +7363,25 @@
"wrappy": "1"
}
},
"node_modules/open": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz",
"integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",
"dev": true,
"license": "MIT",
"dependencies": {
"default-browser": "^5.2.1",
"define-lazy-prop": "^3.0.0",
"is-inside-container": "^1.0.0",
"wsl-utils": "^0.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/opener": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
@ -7502,6 +7630,7 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@ -7635,6 +7764,7 @@
"integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
"dev": true,
"license": "MIT",
"peer": true,
"bin": {
"prettier": "bin/prettier.cjs"
},
@ -7651,6 +7781,7 @@
"integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
"dev": true,
"license": "MIT",
"peer": true,
"peerDependencies": {
"prettier": "^3.0.0",
"svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
@ -7846,9 +7977,9 @@
}
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"version": "6.14.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
"integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
@ -7927,6 +8058,7 @@
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
@ -7937,6 +8069,7 @@
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
@ -8222,6 +8355,7 @@
"integrity": "sha512-4iya7Jb76fVpQyLoiVpzUrsjQ12r3dM7fIVz+4NwoYvZOShknRmiv+iu9CClZml5ZLGb0XMcYLutK6w9tgxHDw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/estree": "1.0.8"
},
@ -8272,6 +8406,19 @@
"node": ">= 18"
}
},
"node_modules/run-applescript": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz",
"integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@ -8343,6 +8490,7 @@
"integrity": "sha512-elOcIZRTM76dvxNAjqYrucTSI0teAF/L2Lv0s6f6b7FOwcwIuA357bIE871580AjHJuSvLIRUosgV+lIWx6Rgg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"chokidar": "^4.0.0",
"immutable": "^5.0.2",
@ -8380,9 +8528,9 @@
"license": "MIT"
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
"integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
"dev": true,
"license": "ISC",
"bin": {
@ -8438,9 +8586,9 @@
}
},
"node_modules/set-cookie-parser": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz",
"integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.0.1.tgz",
"integrity": "sha512-n7Z7dXZhJbwuAHhNzkTti6Aw9QDDjZtm3JTpTGATIdNzdQz5GuFs22w90BcvF4INfnrL5xrX3oGsuqO5Dx3A1Q==",
"dev": true,
"license": "MIT"
},
@ -8626,22 +8774,24 @@
"license": "MIT"
},
"node_modules/storybook": {
"version": "10.0.7",
"resolved": "https://registry.npmjs.org/storybook/-/storybook-10.0.7.tgz",
"integrity": "sha512-7smAu0o+kdm378Q2uIddk32pn0UdIbrtTVU+rXRVtTVTCrK/P2cCui2y4JH+Bl3NgEq1bbBQpCAF/HKrDjk2Qw==",
"version": "10.2.4",
"resolved": "https://registry.npmjs.org/storybook/-/storybook-10.2.4.tgz",
"integrity": "sha512-LwF0VZsT4qkgx66Ad/q0QgZZrU2a5WftaADDEcJ3bGq3O2fHvwWPlSZjM1HiXD4vqP9U5JiMqQkV1gkyH0XJkw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@storybook/global": "^5.0.0",
"@storybook/icons": "^1.6.0",
"@storybook/icons": "^2.0.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/user-event": "^14.6.1",
"@vitest/expect": "3.2.4",
"@vitest/mocker": "3.2.4",
"@vitest/spy": "3.2.4",
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0",
"esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0 || ^0.26.0 || ^0.27.0",
"open": "^10.2.0",
"recast": "^0.23.5",
"semver": "^7.6.2",
"semver": "^7.7.3",
"use-sync-external-store": "^1.5.0",
"ws": "^8.18.0"
},
"bin": {
@ -8660,6 +8810,17 @@
}
}
},
"node_modules/storybook/node_modules/@storybook/icons": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-2.0.1.tgz",
"integrity": "sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"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"
}
},
"node_modules/stringify-entities": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
@ -8776,6 +8937,7 @@
"resolved": "https://registry.npmjs.org/svelte/-/svelte-5.36.12.tgz",
"integrity": "sha512-c3mWT+b0yBLl3gPGSHiy4pdSQCsPNTjLC0tVoOhrGJ6PPfCzD/RQpAmAfJtQZ304CAae2ph+L3C4aqds3R3seQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@ampproject/remapping": "^2.3.0",
"@jridgewell/sourcemap-codec": "^1.5.0",
@ -9019,6 +9181,7 @@
"integrity": "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"type": "github",
"url": "https://github.com/sponsors/dcastil"
@ -9049,7 +9212,8 @@
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz",
"integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==",
"dev": true,
"license": "MIT"
"license": "MIT",
"peer": true
},
"node_modules/tapable": {
"version": "2.2.2",
@ -9062,17 +9226,16 @@
}
},
"node_modules/tar": {
"version": "7.4.3",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
"version": "7.5.7",
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
"dev": true,
"license": "ISC",
"license": "BlueOak-1.0.0",
"dependencies": {
"@isaacs/fs-minipass": "^4.0.0",
"chownr": "^3.0.0",
"minipass": "^7.1.2",
"minizlib": "^3.0.1",
"mkdirp": "^3.0.1",
"minizlib": "^3.1.0",
"yallist": "^5.0.0"
},
"engines": {
@ -9285,6 +9448,7 @@
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -9548,6 +9712,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/use-sync-external-store": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
"integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
@ -9668,6 +9842,7 @@
"integrity": "sha512-BxAKBWmIbrDgrokdGZH1IgkIk/5mMHDreLDmCJ0qpyJaAteP8NvMhkwr/ZCQNqNH97bw/dANTE9PDzqwJghfMQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@ -9828,6 +10003,7 @@
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@types/chai": "^5.2.2",
"@vitest/expect": "3.2.4",
@ -10014,6 +10190,22 @@
}
}
},
"node_modules/wsl-utils": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
"integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==",
"dev": true,
"license": "MIT",
"dependencies": {
"is-wsl": "^3.1.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yallist": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz",
@ -10048,6 +10240,7 @@
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/colinhacks"
}

View File

@ -1,6 +1,6 @@
<script lang="ts">
import { Copy, Eye } from '@lucide/svelte';
import { copyCodeToClipboard } from '$lib/utils';
import { Eye } from '@lucide/svelte';
import { ActionIconCopyToClipboard } from '$lib/components/app';
import { FileTypeText } from '$lib/enums';
interface Props {
@ -14,11 +14,6 @@
const showPreview = $derived(language?.toLowerCase() === FileTypeText.HTML);
function handleCopy() {
if (disabled) return;
copyCodeToClipboard(code);
}
function handlePreview() {
if (disabled) return;
onPreview?.(code, language);
@ -26,18 +21,14 @@
</script>
<div class="code-block-actions">
<button
class="copy-code-btn"
class:opacity-50={disabled}
class:!cursor-not-allowed={disabled}
title={disabled ? 'Code incomplete' : 'Copy code'}
aria-label="Copy code"
aria-disabled={disabled}
type="button"
onclick={handleCopy}
>
<Copy size={16} />
</button>
<div class="copy-code-btn" class:opacity-50={disabled} class:!cursor-not-allowed={disabled}>
<ActionIconCopyToClipboard
text={code}
canCopy={!disabled}
ariaLabel={disabled ? 'Code incomplete' : 'Copy code'}
/>
</div>
{#if showPreview}
<button
class="preview-code-btn"

View File

@ -2,7 +2,6 @@
import { FileText, Loader2, AlertCircle, Database, Image, Code, File } from '@lucide/svelte';
import { cn } from '$lib/components/ui/utils';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { getFaviconUrl } from '$lib/utils';
import type { MCPResourceAttachment, MCPResourceInfo } from '$lib/types';
import {
IMAGE_FILE_EXTENSION_REGEX,
@ -52,19 +51,9 @@
return 'border-border/50 bg-muted/30';
}
function getServerDisplayName(serverId: string): string {
const server = mcpStore.getServerById(serverId);
return server ? mcpStore.getServerLabel(server) : serverId;
}
function getServerFavicon(serverId: string): string | null {
const server = mcpStore.getServerById(serverId);
return server ? getFaviconUrl(server.url) : null;
}
const ResourceIcon = $derived(getResourceIcon(attachment.resource));
const serverName = $derived(getServerDisplayName(attachment.resource.serverName));
const favicon = $derived(getServerFavicon(attachment.resource.serverName));
const serverName = $derived(mcpStore.getServerDisplayName(attachment.resource.serverName));
const favicon = $derived(mcpStore.getServerFavicon(attachment.resource.serverName));
</script>
<Tooltip.Root>

View File

@ -5,9 +5,9 @@
ChatFormActions,
ChatFormFileInputInvisible,
ChatFormPromptPicker,
ChatFormTextarea,
McpResourcePicker
ChatFormTextarea
} from '$lib/components/app';
import { DialogMcpResources } from '$lib/components/app/dialogs';
import { INPUT_CLASSES } from '$lib/constants/css-classes';
import { SETTING_CONFIG_DEFAULT } from '$lib/constants/settings-config';
import {
@ -542,10 +542,10 @@
</div>
</form>
<McpResourcePicker
<DialogMcpResources
bind:open={isResourcePickerOpen}
preSelectedUri={preSelectedResourceUri}
onOpenChange={(newOpen) => {
onOpenChange={(newOpen: boolean) => {
if (!newOpen) {
preSelectedResourceUri = undefined;
}

View File

@ -5,10 +5,10 @@
ChatFormActionAttachmentsDropdown,
ChatFormActionRecord,
ChatFormActionSubmit,
DialogMcpServersSettings,
McpServersSelector,
ModelsSelector
} from '$lib/components/app';
import { DialogMcpServersSettings } from '$lib/components/app/dialogs';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { FileTypeCategory } from '$lib/enums';
import { getFileTypeCategory } from '$lib/utils';

View File

@ -1,7 +1,6 @@
<script lang="ts">
import { Card } from '$lib/components/ui/card';
import type { DatabaseMessageExtraMcpPrompt, MCPServerSettingsEntry } from '$lib/types';
import { getFaviconUrl } from '$lib/utils';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { SvelteMap } from 'svelte/reactivity';
import { McpPromptVariant } from '$lib/enums';
@ -34,17 +33,6 @@
let hasArguments = $derived(prompt.arguments && Object.keys(prompt.arguments).length > 0);
let hasContent = $derived(prompt.content && prompt.content.trim().length > 0);
let serverSettingsMap = $derived.by(() => {
const servers = mcpStore.getServers();
const map = new SvelteMap<string, MCPServerSettingsEntry>();
for (const server of servers) {
map.set(server.id, server);
}
return map;
});
let contentParts = $derived.by((): ContentPart[] => {
if (!prompt.content || !hasArguments) {
return [{ text: prompt.content || '', argKey: null }];
@ -96,17 +84,8 @@
isAttachment ? 'max-height: 10rem;' : 'max-height: var(--max-message-height);'
);
function getServerFavicon(): string | null {
const server = serverSettingsMap.get(prompt.serverName);
return server ? getFaviconUrl(server.url) : null;
}
function getServerDisplayName(): string {
const server = serverSettingsMap.get(prompt.serverName);
if (!server) return prompt.serverName;
return mcpStore.getServerLabel(server);
}
const serverFavicon = $derived(mcpStore.getServerFavicon(prompt.serverName));
const serverDisplayName = $derived(mcpStore.getServerDisplayName(prompt.serverName));
</script>
<div class="flex flex-col gap-2 {className}">
@ -114,9 +93,9 @@
<div class="inline-flex flex-wrap items-center gap-1.25 text-xs text-muted-foreground">
<Tooltip.Root>
<Tooltip.Trigger>
{#if getServerFavicon()}
{#if serverFavicon}
<img
src={getServerFavicon()}
src={serverFavicon}
alt=""
class="h-3.5 w-3.5 shrink-0 rounded-sm"
onerror={(e) => {
@ -127,7 +106,7 @@
</Tooltip.Trigger>
<Tooltip.Content>
<span>{getServerDisplayName()}</span>
<span>{serverDisplayName}</span>
</Tooltip.Content>
</Tooltip.Root>
@ -136,18 +115,25 @@
{#if showArgBadges}
<div class="flex flex-wrap justify-end gap-1">
{#each argumentEntries as [key] (key)}
<!-- svelte-ignore a11y_no_static_element_interactions -->
<span
class="rounded-sm bg-purple-200/60 px-1.5 py-0.5 text-[10px] leading-none text-purple-700 transition-opacity dark:bg-purple-800/40 dark:text-purple-300 {hoveredArgKey &&
hoveredArgKey !== key
? 'opacity-30'
: ''}"
onmouseenter={() => (hoveredArgKey = key)}
onmouseleave={() => (hoveredArgKey = null)}
>
{key}
</span>
{#each argumentEntries as [key, value] (key)}
<Tooltip.Root>
<Tooltip.Trigger>
<!-- svelte-ignore a11y_no_static_element_interactions -->
<span
class="rounded-sm bg-purple-200/60 px-1.5 py-0.5 text-[10px] leading-none text-purple-700 transition-opacity dark:bg-purple-800/40 dark:text-purple-300 {hoveredArgKey &&
hoveredArgKey !== key
? 'opacity-30'
: ''}"
onmouseenter={() => (hoveredArgKey = key)}
onmouseleave={() => (hoveredArgKey = null)}
>
{key}
</span>
</Tooltip.Trigger>
<Tooltip.Content>
<span class="max-w-xs break-all">{value}</span>
</Tooltip.Content>
</Tooltip.Root>
{/each}
</div>
{/if}

View File

@ -59,7 +59,9 @@ export { default as ChatAttachmentsList } from './ChatAttachments/ChatAttachment
export { default as ChatAttachmentMcpPrompt } from './ChatAttachments/ChatAttachmentMcpPrompt.svelte';
/**
* Todo - add description
* Displays a single MCP Resource attachment with icon, name, and server info.
* Shows loading/error states and supports remove action.
* Used within ChatAttachmentMcpResources for individual resource display.
*/
export { default as ChatAttachmentMcpResource } from './ChatAttachments/ChatAttachmentMcpResource.svelte';

View File

@ -1,21 +0,0 @@
<script lang="ts">
/**
* McpResourcePicker - Wrapper component for DialogMcpResources
*
* This component re-exports DialogMcpResources for backward compatibility.
* New code should use DialogMcpResources directly from dialogs.
*/
import { DialogMcpResources } from '$lib/components/app';
import type { MCPResourceInfo } from '$lib/types';
interface Props {
open?: boolean;
onOpenChange?: (open: boolean) => void;
onAttach?: (resource: MCPResourceInfo) => void;
preSelectedUri?: string;
}
let { open = $bindable(false), onOpenChange, onAttach, preSelectedUri }: Props = $props();
</script>
<DialogMcpResources bind:open {onOpenChange} {onAttach} {preSelectedUri} />

View File

@ -1,8 +1,10 @@
<script lang="ts">
import { FileText, Loader2, AlertCircle, Download, Copy, Check } from '@lucide/svelte';
import { FileText, Loader2, AlertCircle, Download } from '@lucide/svelte';
import { Button } from '$lib/components/ui/button';
import { cn } from '$lib/components/ui/utils';
import { mcpStore } from '$lib/stores/mcp.svelte';
import { isImageMimeType } from '$lib/utils';
import { ActionIconCopyToClipboard } from '$lib/components/app';
import type { MCPResourceInfo, MCPResourceContent } from '$lib/types';
interface Props {
@ -15,7 +17,6 @@
let content = $state<MCPResourceContent[] | null>(null);
let isLoading = $state(false);
let error = $state<string | null>(null);
let copied = $state(false);
$effect(() => {
if (resource) {
@ -59,21 +60,6 @@
);
}
function isImageMimeType(mimeType?: string): boolean {
return mimeType?.startsWith('image/') ?? false;
}
async function handleCopy() {
const text = getTextContent();
if (text) {
await navigator.clipboard.writeText(text);
copied = true;
setTimeout(() => {
copied = false;
}, 2000);
}
}
function handleDownload() {
const text = getTextContent();
if (!text || !resource) return;
@ -109,21 +95,12 @@
{/if}
</div>
<div class="flex gap-1">
<Button
variant="ghost"
size="sm"
class="h-7 w-7 p-0"
onclick={handleCopy}
disabled={isLoading || !getTextContent()}
title="Copy content"
>
{#if copied}
<Check class="h-3.5 w-3.5 text-green-500" />
{:else}
<Copy class="h-3.5 w-3.5" />
{/if}
</Button>
<div class="flex items-center gap-1">
<ActionIconCopyToClipboard
text={getTextContent()}
canCopy={!isLoading && !!getTextContent()}
ariaLabel="Copy content"
/>
<Button
variant="ghost"

View File

@ -34,7 +34,10 @@
[MCPTransportType.SSE]: 'SSE'
};
const transportIcons: Record<MCPTransportType, typeof Cable> = {
const transportIcons: Record<
MCPTransportType,
typeof Cable | typeof Zap | typeof Globe | typeof Radio
> = {
[MCPTransportType.WEBSOCKET]: Zap,
[MCPTransportType.STREAMABLE_HTTP]: Globe,
[MCPTransportType.SSE]: Radio

View File

@ -246,18 +246,3 @@ export { default as McpResourceBrowser } from './McpResourceBrowser.svelte';
* - Loading and error states
*/
export { default as McpResourcePreview } from './McpResourcePreview.svelte';
/**
* **McpResourcePicker** - MCP resource selection dialog
*
* Full dialog for browsing and attaching MCP resources.
* Combines browser and preview panels.
*
* **Features:**
* - Split panel layout (browser + preview)
* - Resource selection with preview
* - Quick attach from browser
* - Attach selected resource action
* - Auto-fetch resources on open
*/
export { default as McpResourcePicker } from './McpResourcePicker.svelte';

View File

@ -279,6 +279,30 @@ class MCPStore {
return this.getServers().find((s) => s.id === serverId);
}
/**
* Get display name for an MCP server by its ID.
* Falls back to the server ID if server is not found.
*/
getServerDisplayName(serverId: string): string {
const server = this.getServerById(serverId);
return server ? this.getServerLabel(server) : serverId;
}
/**
* Get favicon URL for an MCP server by its ID.
* Returns null if server is not found.
*/
getServerFavicon(serverId: string): string | null {
const server = this.getServerById(serverId);
if (!server) return null;
try {
const url = new URL(server.url);
return `${url.origin}/favicon.ico`;
} catch {
return null;
}
}
isAnyServerLoading(): boolean {
return this.getServers().some((s) => {
const state = this.getHealthCheckState(s.id);

View File

@ -108,7 +108,8 @@ export {
detectMcpTransportFromUrl,
parseMcpServerSettings,
getMcpLogLevelIcon,
getMcpLogLevelClass
getMcpLogLevelClass,
isImageMimeType
} from './mcp';
// Header utilities

View File

@ -1,5 +1,5 @@
import type { MCPServerSettingsEntry } from '$lib/types';
import { MCPTransportType, MCPLogLevel, UrlPrefix } from '$lib/enums';
import { MCPTransportType, MCPLogLevel, UrlPrefix, MimeTypePrefix } from '$lib/enums';
import { DEFAULT_MCP_CONFIG } from '$lib/constants/mcp';
import { Info, AlertTriangle, XCircle } from '@lucide/svelte';
import type { Component } from 'svelte';
@ -97,3 +97,13 @@ export function getMcpLogLevelClass(level: MCPLogLevel): string {
return 'text-muted-foreground';
}
}
/**
* Check if a MIME type represents an image.
*
* @param mimeType - The MIME type to check
* @returns True if the MIME type starts with 'image/'
*/
export function isImageMimeType(mimeType?: string): boolean {
return mimeType?.startsWith(MimeTypePrefix.IMAGE) ?? false;
}