Thomas G. Lopes commited on
Commit
52c6f5c
·
unverified ·
1 Parent(s): 78dcd5a

MCPs (#91)

Browse files
.env.example CHANGED
@@ -1,3 +1,4 @@
 
1
  HYPERBOLIC_API_KEY=
2
  COHERE_API_KEY=
3
  TOGETHER_API_KEY=
@@ -9,4 +10,3 @@ FAL_API_KEY=
9
  HF_TOKEN=
10
 
11
  MODELS_FILE=
12
-
 
1
+ PUBLIC_ENABLE_MCP=
2
  HYPERBOLIC_API_KEY=
3
  COHERE_API_KEY=
4
  TOGETHER_API_KEY=
 
10
  HF_TOKEN=
11
 
12
  MODELS_FILE=
 
eslint.config.mts CHANGED
@@ -66,6 +66,7 @@ export default ts.config(
66
  "object-shorthand": ["error", "always"],
67
  "svelte/no-at-html-tags": "off",
68
  "svelte/require-each-key": "off",
 
69
  "local/enforce-ext": [
70
  "error",
71
  {
@@ -92,6 +93,7 @@ export default ts.config(
92
  "**/package-lock.json",
93
  "**/yarn.lock",
94
  "context_length.json",
 
95
  ],
96
  },
97
  {
 
66
  "object-shorthand": ["error", "always"],
67
  "svelte/no-at-html-tags": "off",
68
  "svelte/require-each-key": "off",
69
+ "svelte/no-navigation-without-resolve": "off",
70
  "local/enforce-ext": [
71
  "error",
72
  {
 
93
  "**/package-lock.json",
94
  "**/yarn.lock",
95
  "context_length.json",
96
+ ".claude/**/*",
97
  ],
98
  },
99
  {
package.json CHANGED
@@ -12,8 +12,9 @@
12
  "lint": "prettier . --check . && eslint src/",
13
  "format": "prettier . --write .",
14
  "clean": "rm -rf ./node_modules/ && rm -rf ./.svelte-kit/ && ni && echo 'Project cleaned!'",
 
15
  "test:unit": "vitest --browser.headless",
16
- "test": "npm run test:unit",
17
  "test:e2e": "playwright test"
18
  },
19
  "devDependencies": {
@@ -30,10 +31,10 @@
30
  "@playwright/test": "^1.49.1",
31
  "@ryoppippi/unplugin-typia": "^1.0.0",
32
  "@samchon/openapi": "^3.0.0",
33
- "@sveltejs/adapter-auto": "^3.2.2",
34
- "@sveltejs/adapter-node": "^5.2.0",
35
- "@sveltejs/kit": "^2.5.27",
36
- "@sveltejs/vite-plugin-svelte": "^4.0.0",
37
  "@tailwindcss/container-queries": "^0.1.1",
38
  "@tailwindcss/postcss": "^4.0.9",
39
  "@testing-library/jest-dom": "^6.6.3",
@@ -59,8 +60,8 @@
59
  "prettier-plugin-tailwindcss": "^0.6.11",
60
  "runed": "^0.25.0",
61
  "shiki": "^3.4.0",
62
- "svelte": "^5.36.16",
63
- "svelte-check": "^4.0.0",
64
  "tailwind-merge": "^3.0.2",
65
  "tailwindcss": "^4.0.9",
66
  "ts-patch": "^3.3.0",
@@ -74,11 +75,13 @@
74
  },
75
  "type": "module",
76
  "dependencies": {
 
77
  "@tailwindcss/typography": "^0.5.16",
78
  "dequal": "^2.0.3",
79
- "eslint-plugin-svelte": "^3.11.0",
80
  "marked": "^16.1.2",
81
  "remult": "^3.0.2",
 
82
  "typia": "^8.0.0"
83
  },
84
  "pnpm": {
 
12
  "lint": "prettier . --check . && eslint src/",
13
  "format": "prettier . --write .",
14
  "clean": "rm -rf ./node_modules/ && rm -rf ./.svelte-kit/ && ni && echo 'Project cleaned!'",
15
+ "update-ctx-length": "jiti scripts/update-ctx-length.ts",
16
  "test:unit": "vitest --browser.headless",
17
+ "test": "npm run test:unit -- --run",
18
  "test:e2e": "playwright test"
19
  },
20
  "devDependencies": {
 
31
  "@playwright/test": "^1.49.1",
32
  "@ryoppippi/unplugin-typia": "^1.0.0",
33
  "@samchon/openapi": "^3.0.0",
34
+ "@sveltejs/adapter-auto": "^3.3.1",
35
+ "@sveltejs/adapter-node": "^5.3.1",
36
+ "@sveltejs/kit": "^2.37.1",
37
+ "@sveltejs/vite-plugin-svelte": "^4.0.4",
38
  "@tailwindcss/container-queries": "^0.1.1",
39
  "@tailwindcss/postcss": "^4.0.9",
40
  "@testing-library/jest-dom": "^6.6.3",
 
60
  "prettier-plugin-tailwindcss": "^0.6.11",
61
  "runed": "^0.25.0",
62
  "shiki": "^3.4.0",
63
+ "svelte": "^5.38.7",
64
+ "svelte-check": "^4.3.1",
65
  "tailwind-merge": "^3.0.2",
66
  "tailwindcss": "^4.0.9",
67
  "ts-patch": "^3.3.0",
 
75
  },
76
  "type": "module",
77
  "dependencies": {
78
+ "@modelcontextprotocol/sdk": "^1.13.3",
79
  "@tailwindcss/typography": "^0.5.16",
80
  "dequal": "^2.0.3",
81
+ "eslint-plugin-svelte": "^3.12.2",
82
  "marked": "^16.1.2",
83
  "remult": "^3.0.2",
84
+ "tailwindcss-spring": "^1.0.1",
85
  "typia": "^8.0.0"
86
  },
87
  "pnpm": {
pnpm-lock.yaml CHANGED
@@ -8,6 +8,9 @@ importers:
8
 
9
  .:
10
  dependencies:
 
 
 
11
  '@tailwindcss/typography':
12
  specifier: ^0.5.16
13
  version: 0.5.16(tailwindcss@4.0.9)
@@ -15,14 +18,17 @@ importers:
15
  specifier: ^2.0.3
16
  version: 2.0.3
17
  eslint-plugin-svelte:
18
- specifier: ^3.11.0
19
- version: 3.11.0(eslint@9.22.0(jiti@2.4.2))(svelte@5.36.16)
20
  marked:
21
  specifier: ^16.1.2
22
  version: 16.1.2
23
  remult:
24
  specifier: ^3.0.2
25
  version: 3.0.2
 
 
 
26
  typia:
27
  specifier: ^8.0.0
28
  version: 8.0.0(@samchon/openapi@3.0.0)(typescript@5.8.2)
@@ -67,17 +73,17 @@ importers:
67
  specifier: ^3.0.0
68
  version: 3.0.0
69
  '@sveltejs/adapter-auto':
70
- specifier: ^3.2.2
71
- version: 3.3.1(@sveltejs/kit@2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
72
  '@sveltejs/adapter-node':
73
- specifier: ^5.2.0
74
- version: 5.2.12(@sveltejs/kit@2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
75
  '@sveltejs/kit':
76
- specifier: ^2.5.27
77
- version: 2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
78
  '@sveltejs/vite-plugin-svelte':
79
- specifier: ^4.0.0
80
- version: 4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
81
  '@tailwindcss/container-queries':
82
  specifier: ^0.1.1
83
  version: 0.1.1(tailwindcss@4.0.9)
@@ -89,7 +95,7 @@ importers:
89
  version: 6.6.3
90
  '@testing-library/svelte':
91
  specifier: ^5.2.4
92
- version: 5.2.8(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)
93
  '@types/node':
94
  specifier: ^22.14.1
95
  version: 22.14.1
@@ -128,10 +134,10 @@ importers:
128
  version: 26.1.0
129
  melt:
130
  specifier: ^0.36.0
131
- version: 0.36.0(@floating-ui/dom@1.6.13)(svelte@5.36.16)
132
  openai:
133
  specifier: ^4.90.0
134
- version: 4.90.0(ws@8.18.2)
135
  playwright:
136
  specifier: ^1.52.0
137
  version: 1.52.0
@@ -143,22 +149,22 @@ importers:
143
  version: 3.5.3
144
  prettier-plugin-svelte:
145
  specifier: ^3.4.0
146
- version: 3.4.0(prettier@3.5.3)(svelte@5.36.16)
147
  prettier-plugin-tailwindcss:
148
  specifier: ^0.6.11
149
- version: 0.6.11(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.36.16))(prettier@3.5.3)
150
  runed:
151
  specifier: ^0.25.0
152
- version: 0.25.0(svelte@5.36.16)
153
  shiki:
154
  specifier: ^3.4.0
155
  version: 3.4.0
156
  svelte:
157
- specifier: ^5.36.16
158
- version: 5.36.16
159
  svelte-check:
160
- specifier: ^4.0.0
161
- version: 4.1.5(picomatch@4.0.2)(svelte@5.36.16)(typescript@5.8.2)
162
  tailwind-merge:
163
  specifier: ^3.0.2
164
  version: 3.0.2
@@ -179,7 +185,7 @@ importers:
179
  version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
180
  unplugin-icons:
181
  specifier: ^22.1.0
182
- version: 22.1.0(svelte@5.36.16)
183
  vite:
184
  specifier: ^5.4.4
185
  version: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
@@ -188,7 +194,7 @@ importers:
188
  version: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
189
  vitest-browser-svelte:
190
  specifier: ^0.1.0
191
- version: 0.1.0(@vitest/browser@3.1.4)(svelte@5.36.16)(vitest@3.1.4)
192
 
193
  packages:
194
 
@@ -199,10 +205,6 @@ packages:
199
  resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
200
  engines: {node: '>=10'}
201
 
202
- '@ampproject/remapping@2.3.0':
203
- resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==}
204
- engines: {node: '>=6.0.0'}
205
-
206
  '@antfu/install-pkg@1.0.0':
207
  resolution: {integrity: sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==}
208
 
@@ -774,24 +776,32 @@ packages:
774
  resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
775
  engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
776
 
777
- '@jridgewell/gen-mapping@0.3.8':
778
- resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==}
779
- engines: {node: '>=6.0.0'}
 
 
780
 
781
  '@jridgewell/resolve-uri@3.1.2':
782
  resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
783
  engines: {node: '>=6.0.0'}
784
 
785
- '@jridgewell/set-array@1.2.1':
786
- resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==}
787
- engines: {node: '>=6.0.0'}
788
-
789
  '@jridgewell/sourcemap-codec@1.5.0':
790
  resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
791
 
 
 
 
792
  '@jridgewell/trace-mapping@0.3.25':
793
  resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
794
 
 
 
 
 
 
 
 
795
  '@noble/hashes@1.8.0':
796
  resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
797
  engines: {node: ^14.21.3 || >=16}
@@ -1014,6 +1024,9 @@ packages:
1014
  '@sinclair/typebox@0.27.8':
1015
  resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
1016
 
 
 
 
1017
  '@sveltejs/acorn-typescript@1.0.5':
1018
  resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==}
1019
  peerDependencies:
@@ -1024,19 +1037,23 @@ packages:
1024
  peerDependencies:
1025
  '@sveltejs/kit': ^2.0.0
1026
 
1027
- '@sveltejs/adapter-node@5.2.12':
1028
- resolution: {integrity: sha512-0bp4Yb3jKIEcZWVcJC/L1xXp9zzJS4hDwfb4VITAkfT4OVdkspSHsx7YhqJDbb2hgLl6R9Vs7VQR+fqIVOxPUQ==}
1029
  peerDependencies:
1030
  '@sveltejs/kit': ^2.4.0
1031
 
1032
- '@sveltejs/kit@2.18.0':
1033
- resolution: {integrity: sha512-4DGCGiwNzgnPJySlMe/Qi6rKMK3ntphJaV95BTW+aggaTIAVZ5x3Bp+LURVLMxAEAtWAI5U449NafVxTS+kXbQ==}
1034
  engines: {node: '>=18.13'}
1035
  hasBin: true
1036
  peerDependencies:
1037
- '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0
 
1038
  svelte: ^4.0.0 || ^5.0.0-next.0
1039
- vite: ^5.0.3 || ^6.0.0
 
 
 
1040
 
1041
  '@sveltejs/vite-plugin-svelte-inspector@3.0.1':
1042
  resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==}
@@ -1297,6 +1314,10 @@ packages:
1297
  resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
1298
  engines: {node: '>=6.5'}
1299
 
 
 
 
 
1300
  acorn-jsx@5.3.2:
1301
  resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
1302
  peerDependencies:
@@ -1307,6 +1328,11 @@ packages:
1307
  engines: {node: '>=0.4.0'}
1308
  hasBin: true
1309
 
 
 
 
 
 
1310
  agent-base@7.1.3:
1311
  resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
1312
  engines: {node: '>= 14'}
@@ -1371,6 +1397,10 @@ packages:
1371
  bl@4.1.0:
1372
  resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
1373
 
 
 
 
 
1374
  boolean@3.2.0:
1375
  resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
1376
  deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
@@ -1388,6 +1418,10 @@ packages:
1388
  buffer@5.7.1:
1389
  resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
1390
 
 
 
 
 
1391
  cac@6.7.14:
1392
  resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
1393
  engines: {node: '>=8'}
@@ -1396,6 +1430,10 @@ packages:
1396
  resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
1397
  engines: {node: '>= 0.4'}
1398
 
 
 
 
 
1399
  callsites@3.1.0:
1400
  resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
1401
  engines: {node: '>=6'}
@@ -1504,13 +1542,33 @@ packages:
1504
  resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
1505
  engines: {node: ^14.18.0 || >=16.10.0}
1506
 
 
 
 
 
 
 
 
 
 
 
 
 
1507
  cookie@0.6.0:
1508
  resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
1509
  engines: {node: '>= 0.6'}
1510
 
 
 
 
 
1511
  core-util-is@1.0.3:
1512
  resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
1513
 
 
 
 
 
1514
  cross-spawn@7.0.6:
1515
  resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
1516
  engines: {node: '>= 8'}
@@ -1572,6 +1630,10 @@ packages:
1572
  resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
1573
  engines: {node: '>=0.4.0'}
1574
 
 
 
 
 
1575
  dequal@2.0.3:
1576
  resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
1577
  engines: {node: '>=6'}
@@ -1588,8 +1650,8 @@ packages:
1588
  detect-node@2.1.0:
1589
  resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
1590
 
1591
- devalue@5.1.1:
1592
- resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==}
1593
 
1594
  devlop@1.1.0:
1595
  resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
@@ -1619,9 +1681,16 @@ packages:
1619
  resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
1620
  engines: {node: '>= 0.4'}
1621
 
 
 
 
1622
  emoji-regex@8.0.0:
1623
  resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
1624
 
 
 
 
 
1625
  enhanced-resolve@5.18.1:
1626
  resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
1627
  engines: {node: '>=10.13.0'}
@@ -1662,6 +1731,9 @@ packages:
1662
  engines: {node: '>=18'}
1663
  hasBin: true
1664
 
 
 
 
1665
  escape-string-regexp@1.0.5:
1666
  resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
1667
  engines: {node: '>=0.8.0'}
@@ -1690,8 +1762,8 @@ packages:
1690
  eslint-config-prettier:
1691
  optional: true
1692
 
1693
- eslint-plugin-svelte@3.11.0:
1694
- resolution: {integrity: sha512-KliWlkieHyEa65aQIkRwUFfHzT5Cn4u3BQQsu3KlkJOs7c1u7ryn84EWaOjEzilbKgttT4OfBURA8Uc4JBSQIw==}
1695
  engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1696
  peerDependencies:
1697
  eslint: ^8.57.1 || ^9.0.0
@@ -1759,14 +1831,36 @@ packages:
1759
  resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
1760
  engines: {node: '>=0.10.0'}
1761
 
 
 
 
 
1762
  event-target-shim@5.0.1:
1763
  resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
1764
  engines: {node: '>=6'}
1765
 
 
 
 
 
 
 
 
 
1766
  expect-type@1.2.1:
1767
  resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
1768
  engines: {node: '>=12.0.0'}
1769
 
 
 
 
 
 
 
 
 
 
 
1770
  exsolve@1.0.4:
1771
  resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==}
1772
 
@@ -1825,6 +1919,10 @@ packages:
1825
  resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
1826
  engines: {node: '>=8'}
1827
 
 
 
 
 
1828
  find-cache-dir@5.0.0:
1829
  resolution: {integrity: sha512-OuWNfjfP05JcpAP3JPgAKUhWefjMRfI5iAoSsvE24ANYWJaepAtlSgWECSVEuRgSXpyNEc9DJwG/TZpgcOqyig==}
1830
  engines: {node: '>=16'}
@@ -1858,6 +1956,14 @@ packages:
1858
  resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
1859
  engines: {node: '>= 12.20'}
1860
 
 
 
 
 
 
 
 
 
1861
  fsevents@2.3.2:
1862
  resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
1863
  engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1964,6 +2070,10 @@ packages:
1964
  html-void-elements@3.0.0:
1965
  resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
1966
 
 
 
 
 
1967
  http-proxy-agent@7.0.2:
1968
  resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
1969
  engines: {node: '>= 14'}
@@ -1983,6 +2093,10 @@ packages:
1983
  resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
1984
  engines: {node: '>=0.10.0'}
1985
 
 
 
 
 
1986
  ieee754@1.2.1:
1987
  resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
1988
 
@@ -2016,6 +2130,10 @@ packages:
2016
  resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==}
2017
  engines: {node: '>=12.0.0'}
2018
 
 
 
 
 
2019
  is-arrayish@0.3.2:
2020
  resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
2021
 
@@ -2049,6 +2167,9 @@ packages:
2049
  is-potential-custom-element-name@1.0.1:
2050
  resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
2051
 
 
 
 
2052
  is-reference@1.2.1:
2053
  resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
2054
 
@@ -2266,12 +2387,20 @@ packages:
2266
  mdast-util-to-hast@13.2.0:
2267
  resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
2268
 
 
 
 
 
2269
  melt@0.36.0:
2270
  resolution: {integrity: sha512-lJdUuPvsCZs7zpcL2iSvxerHxv3QuM91FoTbdsliOQ2+J3fR4ADqUN878J4kkQSzzHlWqyedQmEBDP6U3iEWgA==}
2271
  peerDependencies:
2272
  '@floating-ui/dom': ^1.6.0
2273
  svelte: ^5.30.1
2274
 
 
 
 
 
2275
  merge2@1.4.1:
2276
  resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
2277
  engines: {node: '>= 8'}
@@ -2299,10 +2428,18 @@ packages:
2299
  resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
2300
  engines: {node: '>= 0.6'}
2301
 
 
 
 
 
2302
  mime-types@2.1.35:
2303
  resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
2304
  engines: {node: '>= 0.6'}
2305
 
 
 
 
 
2306
  mimic-fn@2.1.0:
2307
  resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
2308
  engines: {node: '>=6'}
@@ -2364,6 +2501,10 @@ packages:
2364
  natural-compare@1.4.0:
2365
  resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
2366
 
 
 
 
 
2367
  node-domexception@1.0.0:
2368
  resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
2369
  engines: {node: '>=10.5.0'}
@@ -2380,10 +2521,25 @@ packages:
2380
  nwsapi@2.2.20:
2381
  resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
2382
 
 
 
 
 
 
 
 
 
2383
  object-keys@1.1.1:
2384
  resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
2385
  engines: {node: '>= 0.4'}
2386
 
 
 
 
 
 
 
 
2387
  onetime@5.1.2:
2388
  resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
2389
  engines: {node: '>=6'}
@@ -2457,6 +2613,10 @@ packages:
2457
  parse5@7.3.0:
2458
  resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
2459
 
 
 
 
 
2460
  path-exists@4.0.0:
2461
  resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
2462
  engines: {node: '>=8'}
@@ -2472,6 +2632,9 @@ packages:
2472
  path-parse@1.0.7:
2473
  resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
2474
 
 
 
 
2475
  pathe@1.1.2:
2476
  resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
2477
 
@@ -2493,6 +2656,10 @@ packages:
2493
  resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
2494
  engines: {node: '>=12'}
2495
 
 
 
 
 
2496
  pkg-dir@7.0.0:
2497
  resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
2498
  engines: {node: '>=14.16'}
@@ -2641,10 +2808,18 @@ packages:
2641
  resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==}
2642
  engines: {node: '>=12.0.0'}
2643
 
 
 
 
 
2644
  punycode@2.3.1:
2645
  resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
2646
  engines: {node: '>=6'}
2647
 
 
 
 
 
2648
  quansync@0.2.8:
2649
  resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==}
2650
 
@@ -2655,6 +2830,14 @@ packages:
2655
  resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==}
2656
  engines: {node: '>=4'}
2657
 
 
 
 
 
 
 
 
 
2658
  react-is@17.0.2:
2659
  resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
2660
 
@@ -2722,6 +2905,10 @@ packages:
2722
  engines: {node: '>=18.0.0', npm: '>=8.0.0'}
2723
  hasBin: true
2724
 
 
 
 
 
2725
  rrweb-cssom@0.8.0:
2726
  resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
2727
 
@@ -2772,13 +2959,24 @@ packages:
2772
  engines: {node: '>=10'}
2773
  hasBin: true
2774
 
 
 
 
 
2775
  serialize-error@7.0.1:
2776
  resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
2777
  engines: {node: '>=10'}
2778
 
 
 
 
 
2779
  set-cookie-parser@2.7.1:
2780
  resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
2781
 
 
 
 
2782
  sharp@0.34.2:
2783
  resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==}
2784
  engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
@@ -2794,6 +2992,22 @@ packages:
2794
  shiki@3.4.0:
2795
  resolution: {integrity: sha512-Ni80XHcqhOEXv5mmDAvf5p6PAJqbUc/RzFeaOqk+zP5DLvTPS3j0ckvA+MI87qoxTQ5RGJDVTbdl/ENLSyyAnQ==}
2796
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2797
  siginfo@2.0.0:
2798
  resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
2799
 
@@ -2820,6 +3034,14 @@ packages:
2820
  stackback@0.0.2:
2821
  resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
2822
 
 
 
 
 
 
 
 
 
2823
  std-env@3.9.0:
2824
  resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
2825
 
@@ -2853,8 +3075,8 @@ packages:
2853
  resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
2854
  engines: {node: '>= 0.4'}
2855
 
2856
- svelte-check@4.1.5:
2857
- resolution: {integrity: sha512-Gb0T2IqBNe1tLB9EB1Qh+LOe+JB8wt2/rNBDGvkxQVvk8vNeAoG+vZgFB/3P5+zC7RWlyBlzm9dVjZFph/maIg==}
2858
  engines: {node: '>= 18.0.0'}
2859
  hasBin: true
2860
  peerDependencies:
@@ -2870,8 +3092,8 @@ packages:
2870
  svelte:
2871
  optional: true
2872
 
2873
- svelte@5.36.16:
2874
- resolution: {integrity: sha512-C7HnyISfvZEofs7T4p7+bmjrbQlhd6lZfgV2tLYg6Eb3nUFM/Zu9dGlSg+GWbUBU/WPw6zDPOFNZAx9qXsoCkg==}
2875
  engines: {node: '>=18'}
2876
 
2877
  symbol-tree@3.2.4:
@@ -2884,6 +3106,11 @@ packages:
2884
  tailwind-merge@3.0.2:
2885
  resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==}
2886
 
 
 
 
 
 
2887
  tailwindcss@4.0.9:
2888
  resolution: {integrity: sha512-12laZu+fv1ONDRoNR9ipTOpUD7RN9essRVkX36sjxuRUInpN7hIiHN4lBd/SIFjbISvnXzp8h/hXzmU8SQQYhw==}
2889
 
@@ -2935,6 +3162,10 @@ packages:
2935
  resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
2936
  engines: {node: '>=8.0'}
2937
 
 
 
 
 
2938
  totalist@3.0.1:
2939
  resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
2940
  engines: {node: '>=6'}
@@ -2982,6 +3213,10 @@ packages:
2982
  resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==}
2983
  engines: {node: '>=16'}
2984
 
 
 
 
 
2985
  typescript-eslint@8.26.1:
2986
  resolution: {integrity: sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg==}
2987
  engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3037,6 +3272,10 @@ packages:
3037
  unist-util-visit@5.0.0:
3038
  resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
3039
 
 
 
 
 
3040
  unplugin-icons@22.1.0:
3041
  resolution: {integrity: sha512-ect2ZNtk1Zgwb0NVHd0C1IDW/MV+Jk/xaq4t8o6rYdVS3+L660ZdD5kTSQZvsgdwCvquRw+/wYn75hsweRjoIA==}
3042
  peerDependencies:
@@ -3078,6 +3317,10 @@ packages:
3078
  resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
3079
  hasBin: true
3080
 
 
 
 
 
3081
  vfile-message@4.0.2:
3082
  resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
3083
 
@@ -3263,6 +3506,9 @@ packages:
3263
  resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
3264
  engines: {node: '>=8'}
3265
 
 
 
 
3266
  ws@8.18.2:
3267
  resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
3268
  engines: {node: '>=10.0.0'}
@@ -3306,6 +3552,14 @@ packages:
3306
  zimmerframe@1.1.2:
3307
  resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
3308
 
 
 
 
 
 
 
 
 
3309
  zwitch@2.0.4:
3310
  resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
3311
 
@@ -3315,11 +3569,6 @@ snapshots:
3315
 
3316
  '@alloc/quick-lru@5.2.0': {}
3317
 
3318
- '@ampproject/remapping@2.3.0':
3319
- dependencies:
3320
- '@jridgewell/gen-mapping': 0.3.8
3321
- '@jridgewell/trace-mapping': 0.3.25
3322
-
3323
  '@antfu/install-pkg@1.0.0':
3324
  dependencies:
3325
  package-manager-detector: 0.2.11
@@ -3723,23 +3972,49 @@ snapshots:
3723
  dependencies:
3724
  '@sinclair/typebox': 0.27.8
3725
 
3726
- '@jridgewell/gen-mapping@0.3.8':
3727
  dependencies:
3728
- '@jridgewell/set-array': 1.2.1
3729
  '@jridgewell/sourcemap-codec': 1.5.0
3730
- '@jridgewell/trace-mapping': 0.3.25
3731
 
3732
- '@jridgewell/resolve-uri@3.1.2': {}
 
 
 
3733
 
3734
- '@jridgewell/set-array@1.2.1': {}
3735
 
3736
  '@jridgewell/sourcemap-codec@1.5.0': {}
3737
 
 
 
3738
  '@jridgewell/trace-mapping@0.3.25':
3739
  dependencies:
3740
  '@jridgewell/resolve-uri': 3.1.2
3741
  '@jridgewell/sourcemap-codec': 1.5.0
3742
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3743
  '@noble/hashes@1.8.0': {}
3744
 
3745
  '@nodelib/fs.scandir@2.1.5':
@@ -3949,57 +4224,65 @@ snapshots:
3949
 
3950
  '@sinclair/typebox@0.27.8': {}
3951
 
 
 
3952
  '@sveltejs/acorn-typescript@1.0.5(acorn@8.14.0)':
3953
  dependencies:
3954
  acorn: 8.14.0
3955
 
3956
- '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
3957
  dependencies:
3958
- '@sveltejs/kit': 2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
 
 
 
 
3959
  import-meta-resolve: 4.1.0
3960
 
3961
- '@sveltejs/adapter-node@5.2.12(@sveltejs/kit@2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
3962
  dependencies:
3963
  '@rollup/plugin-commonjs': 28.0.2(rollup@4.34.9)
3964
  '@rollup/plugin-json': 6.1.0(rollup@4.34.9)
3965
  '@rollup/plugin-node-resolve': 16.0.0(rollup@4.34.9)
3966
- '@sveltejs/kit': 2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
3967
  rollup: 4.34.9
3968
 
3969
- '@sveltejs/kit@2.18.0(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
3970
  dependencies:
3971
- '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
 
 
3972
  '@types/cookie': 0.6.0
 
3973
  cookie: 0.6.0
3974
- devalue: 5.1.1
3975
  esm-env: 1.2.2
3976
- import-meta-resolve: 4.1.0
3977
  kleur: 4.1.5
3978
  magic-string: 0.30.17
3979
  mrmime: 2.0.1
3980
  sade: 1.8.1
3981
  set-cookie-parser: 2.7.1
3982
  sirv: 3.0.1
3983
- svelte: 5.36.16
3984
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
3985
 
3986
- '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
3987
  dependencies:
3988
- '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
3989
  debug: 4.4.0
3990
- svelte: 5.36.16
3991
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
3992
  transitivePeerDependencies:
3993
  - supports-color
3994
 
3995
- '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
3996
  dependencies:
3997
- '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
3998
  debug: 4.4.0
3999
  deepmerge: 4.3.1
4000
  kleur: 4.1.5
4001
  magic-string: 0.30.17
4002
- svelte: 5.36.16
4003
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4004
  vitefu: 1.0.6(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4005
  transitivePeerDependencies:
@@ -4100,10 +4383,10 @@ snapshots:
4100
  lodash: 4.17.21
4101
  redent: 3.0.0
4102
 
4103
- '@testing-library/svelte@5.2.8(svelte@5.36.16)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)':
4104
  dependencies:
4105
  '@testing-library/dom': 10.4.0
4106
- svelte: 5.36.16
4107
  optionalDependencies:
4108
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4109
  vitest: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
@@ -4287,12 +4570,19 @@ snapshots:
4287
  dependencies:
4288
  event-target-shim: 5.0.1
4289
 
 
 
 
 
 
4290
  acorn-jsx@5.3.2(acorn@8.14.0):
4291
  dependencies:
4292
  acorn: 8.14.0
4293
 
4294
  acorn@8.14.0: {}
4295
 
 
 
4296
  agent-base@7.1.3: {}
4297
 
4298
  agentkeepalive@4.6.0:
@@ -4346,6 +4636,20 @@ snapshots:
4346
  inherits: 2.0.4
4347
  readable-stream: 3.6.2
4348
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4349
  boolean@3.2.0: {}
4350
 
4351
  brace-expansion@1.1.11:
@@ -4366,6 +4670,8 @@ snapshots:
4366
  base64-js: 1.5.1
4367
  ieee754: 1.2.1
4368
 
 
 
4369
  cac@6.7.14: {}
4370
 
4371
  call-bind-apply-helpers@1.0.2:
@@ -4373,6 +4679,11 @@ snapshots:
4373
  es-errors: 1.3.0
4374
  function-bind: 1.1.2
4375
 
 
 
 
 
 
4376
  callsites@3.1.0: {}
4377
 
4378
  ccount@2.0.1: {}
@@ -4465,10 +4776,25 @@ snapshots:
4465
 
4466
  consola@3.4.0: {}
4467
 
 
 
 
 
 
 
 
 
4468
  cookie@0.6.0: {}
4469
 
 
 
4470
  core-util-is@1.0.3: {}
4471
 
 
 
 
 
 
4472
  cross-spawn@7.0.6:
4473
  dependencies:
4474
  path-key: 3.1.1
@@ -4521,6 +4847,8 @@ snapshots:
4521
 
4522
  delayed-stream@1.0.0: {}
4523
 
 
 
4524
  dequal@2.0.3: {}
4525
 
4526
  detect-libc@1.0.3: {}
@@ -4529,7 +4857,7 @@ snapshots:
4529
 
4530
  detect-node@2.1.0: {}
4531
 
4532
- devalue@5.1.1: {}
4533
 
4534
  devlop@1.1.0:
4535
  dependencies:
@@ -4553,8 +4881,12 @@ snapshots:
4553
  es-errors: 1.3.0
4554
  gopd: 1.2.0
4555
 
 
 
4556
  emoji-regex@8.0.0: {}
4557
 
 
 
4558
  enhanced-resolve@5.18.1:
4559
  dependencies:
4560
  graceful-fs: 4.2.11
@@ -4635,6 +4967,8 @@ snapshots:
4635
  '@esbuild/win32-ia32': 0.25.1
4636
  '@esbuild/win32-x64': 0.25.1
4637
 
 
 
4638
  escape-string-regexp@1.0.5: {}
4639
 
4640
  escape-string-regexp@4.0.0: {}
@@ -4652,7 +4986,7 @@ snapshots:
4652
  optionalDependencies:
4653
  eslint-config-prettier: 10.1.1(eslint@9.22.0(jiti@2.4.2))
4654
 
4655
- eslint-plugin-svelte@3.11.0(eslint@9.22.0(jiti@2.4.2))(svelte@5.36.16):
4656
  dependencies:
4657
  '@eslint-community/eslint-utils': 4.7.0(eslint@9.22.0(jiti@2.4.2))
4658
  '@jridgewell/sourcemap-codec': 1.5.0
@@ -4664,9 +4998,9 @@ snapshots:
4664
  postcss-load-config: 3.1.4(postcss@8.5.3)
4665
  postcss-safe-parser: 7.0.1(postcss@8.5.3)
4666
  semver: 7.7.2
4667
- svelte-eslint-parser: 1.3.0(svelte@5.36.16)
4668
  optionalDependencies:
4669
- svelte: 5.36.16
4670
  transitivePeerDependencies:
4671
  - ts-node
4672
 
@@ -4753,10 +5087,54 @@ snapshots:
4753
 
4754
  esutils@2.0.3: {}
4755
 
 
 
4756
  event-target-shim@5.0.1: {}
4757
 
 
 
 
 
 
 
4758
  expect-type@1.2.1: {}
4759
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4760
  exsolve@1.0.4: {}
4761
 
4762
  external-editor@3.1.0:
@@ -4807,6 +5185,17 @@ snapshots:
4807
  dependencies:
4808
  to-regex-range: 5.0.1
4809
 
 
 
 
 
 
 
 
 
 
 
 
4810
  find-cache-dir@5.0.0:
4811
  dependencies:
4812
  common-path-prefix: 3.0.0
@@ -4845,6 +5234,10 @@ snapshots:
4845
  node-domexception: 1.0.0
4846
  web-streams-polyfill: 4.0.0-beta.3
4847
 
 
 
 
 
4848
  fsevents@2.3.2:
4849
  optional: true
4850
 
@@ -4957,6 +5350,14 @@ snapshots:
4957
 
4958
  html-void-elements@3.0.0: {}
4959
 
 
 
 
 
 
 
 
 
4960
  http-proxy-agent@7.0.2:
4961
  dependencies:
4962
  agent-base: 7.1.3
@@ -4983,6 +5384,10 @@ snapshots:
4983
  dependencies:
4984
  safer-buffer: 2.1.2
4985
 
 
 
 
 
4986
  ieee754@1.2.1: {}
4987
 
4988
  ignore@5.3.2: {}
@@ -5020,6 +5425,8 @@ snapshots:
5020
  through: 2.3.8
5021
  wrap-ansi: 6.2.0
5022
 
 
 
5023
  is-arrayish@0.3.2: {}
5024
 
5025
  is-core-module@2.16.1:
@@ -5042,6 +5449,8 @@ snapshots:
5042
 
5043
  is-potential-custom-element-name@1.0.1: {}
5044
 
 
 
5045
  is-reference@1.2.1:
5046
  dependencies:
5047
  '@types/estree': 1.0.6
@@ -5225,7 +5634,7 @@ snapshots:
5225
 
5226
  magic-string@0.30.17:
5227
  dependencies:
5228
- '@jridgewell/sourcemap-codec': 1.5.0
5229
 
5230
  marked@16.1.2: {}
5231
 
@@ -5247,14 +5656,18 @@ snapshots:
5247
  unist-util-visit: 5.0.0
5248
  vfile: 6.0.3
5249
 
5250
- melt@0.36.0(@floating-ui/dom@1.6.13)(svelte@5.36.16):
 
 
5251
  dependencies:
5252
  '@floating-ui/dom': 1.6.13
5253
  dequal: 2.0.3
5254
  jest-axe: 9.0.0
5255
  nanoid: 5.1.5
5256
- runed: 0.23.4(svelte@5.36.16)
5257
- svelte: 5.36.16
 
 
5258
 
5259
  merge2@1.4.1: {}
5260
 
@@ -5282,10 +5695,16 @@ snapshots:
5282
 
5283
  mime-db@1.52.0: {}
5284
 
 
 
5285
  mime-types@2.1.35:
5286
  dependencies:
5287
  mime-db: 1.52.0
5288
 
 
 
 
 
5289
  mimic-fn@2.1.0: {}
5290
 
5291
  min-indent@1.0.1: {}
@@ -5329,6 +5748,8 @@ snapshots:
5329
 
5330
  natural-compare@1.4.0: {}
5331
 
 
 
5332
  node-domexception@1.0.0: {}
5333
 
5334
  node-fetch@2.7.0:
@@ -5337,8 +5758,20 @@ snapshots:
5337
 
5338
  nwsapi@2.2.20: {}
5339
 
 
 
 
 
5340
  object-keys@1.1.1: {}
5341
 
 
 
 
 
 
 
 
 
5342
  onetime@5.1.2:
5343
  dependencies:
5344
  mimic-fn: 2.1.0
@@ -5370,7 +5803,7 @@ snapshots:
5370
  platform: 1.3.6
5371
  protobufjs: 7.4.0
5372
 
5373
- openai@4.90.0(ws@8.18.2):
5374
  dependencies:
5375
  '@types/node': 18.19.84
5376
  '@types/node-fetch': 2.6.12
@@ -5381,6 +5814,7 @@ snapshots:
5381
  node-fetch: 2.7.0
5382
  optionalDependencies:
5383
  ws: 8.18.2
 
5384
  transitivePeerDependencies:
5385
  - encoding
5386
 
@@ -5435,6 +5869,8 @@ snapshots:
5435
  dependencies:
5436
  entities: 6.0.0
5437
 
 
 
5438
  path-exists@4.0.0: {}
5439
 
5440
  path-exists@5.0.0: {}
@@ -5443,6 +5879,8 @@ snapshots:
5443
 
5444
  path-parse@1.0.7: {}
5445
 
 
 
5446
  pathe@1.1.2: {}
5447
 
5448
  pathe@2.0.3: {}
@@ -5455,6 +5893,8 @@ snapshots:
5455
 
5456
  picomatch@4.0.2: {}
5457
 
 
 
5458
  pkg-dir@7.0.0:
5459
  dependencies:
5460
  find-up: 6.3.0
@@ -5518,16 +5958,16 @@ snapshots:
5518
  dependencies:
5519
  fast-diff: 1.3.0
5520
 
5521
- prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.36.16):
5522
  dependencies:
5523
  prettier: 3.5.3
5524
- svelte: 5.36.16
5525
 
5526
- prettier-plugin-tailwindcss@0.6.11(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.36.16))(prettier@3.5.3):
5527
  dependencies:
5528
  prettier: 3.5.3
5529
  optionalDependencies:
5530
- prettier-plugin-svelte: 3.4.0(prettier@3.5.3)(svelte@5.36.16)
5531
 
5532
  prettier@3.5.3: {}
5533
 
@@ -5560,8 +6000,17 @@ snapshots:
5560
  '@types/node': 22.14.1
5561
  long: 5.3.1
5562
 
 
 
 
 
 
5563
  punycode@2.3.1: {}
5564
 
 
 
 
 
5565
  quansync@0.2.8: {}
5566
 
5567
  queue-microtask@1.2.3: {}
@@ -5571,6 +6020,15 @@ snapshots:
5571
  drange: 1.1.1
5572
  ret: 0.2.2
5573
 
 
 
 
 
 
 
 
 
 
5574
  react-is@17.0.2: {}
5575
 
5576
  react-is@18.3.1: {}
@@ -5660,6 +6118,16 @@ snapshots:
5660
  '@rollup/rollup-win32-x64-msvc': 4.34.9
5661
  fsevents: 2.3.3
5662
 
 
 
 
 
 
 
 
 
 
 
5663
  rrweb-cssom@0.8.0: {}
5664
 
5665
  run-async@2.4.1: {}
@@ -5668,15 +6136,15 @@ snapshots:
5668
  dependencies:
5669
  queue-microtask: 1.2.3
5670
 
5671
- runed@0.23.4(svelte@5.36.16):
5672
  dependencies:
5673
  esm-env: 1.2.2
5674
- svelte: 5.36.16
5675
 
5676
- runed@0.25.0(svelte@5.36.16):
5677
  dependencies:
5678
  esm-env: 1.2.2
5679
- svelte: 5.36.16
5680
 
5681
  rxjs@7.8.2:
5682
  dependencies:
@@ -5700,12 +6168,39 @@ snapshots:
5700
 
5701
  semver@7.7.2: {}
5702
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5703
  serialize-error@7.0.1:
5704
  dependencies:
5705
  type-fest: 0.13.1
5706
 
 
 
 
 
 
 
 
 
 
5707
  set-cookie-parser@2.7.1: {}
5708
 
 
 
5709
  sharp@0.34.2:
5710
  dependencies:
5711
  color: 4.2.3
@@ -5751,6 +6246,34 @@ snapshots:
5751
  '@shikijs/vscode-textmate': 10.0.2
5752
  '@types/hast': 3.0.4
5753
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5754
  siginfo@2.0.0: {}
5755
 
5756
  signal-exit@3.0.7: {}
@@ -5773,6 +6296,10 @@ snapshots:
5773
 
5774
  stackback@0.0.2: {}
5775
 
 
 
 
 
5776
  std-env@3.9.0: {}
5777
 
5778
  string-width@4.2.3:
@@ -5806,19 +6333,19 @@ snapshots:
5806
 
5807
  supports-preserve-symlinks-flag@1.0.0: {}
5808
 
5809
- svelte-check@4.1.5(picomatch@4.0.2)(svelte@5.36.16)(typescript@5.8.2):
5810
  dependencies:
5811
  '@jridgewell/trace-mapping': 0.3.25
5812
  chokidar: 4.0.3
5813
  fdir: 6.4.3(picomatch@4.0.2)
5814
  picocolors: 1.1.1
5815
  sade: 1.8.1
5816
- svelte: 5.36.16
5817
  typescript: 5.8.2
5818
  transitivePeerDependencies:
5819
  - picomatch
5820
 
5821
- svelte-eslint-parser@1.3.0(svelte@5.36.16):
5822
  dependencies:
5823
  eslint-scope: 8.3.0
5824
  eslint-visitor-keys: 4.2.0
@@ -5827,11 +6354,11 @@ snapshots:
5827
  postcss-scss: 4.0.9(postcss@8.5.3)
5828
  postcss-selector-parser: 7.1.0
5829
  optionalDependencies:
5830
- svelte: 5.36.16
5831
 
5832
- svelte@5.36.16:
5833
  dependencies:
5834
- '@ampproject/remapping': 2.3.0
5835
  '@jridgewell/sourcemap-codec': 1.5.0
5836
  '@sveltejs/acorn-typescript': 1.0.5(acorn@8.14.0)
5837
  '@types/estree': 1.0.6
@@ -5855,6 +6382,10 @@ snapshots:
5855
 
5856
  tailwind-merge@3.0.2: {}
5857
 
 
 
 
 
5858
  tailwindcss@4.0.9: {}
5859
 
5860
  tapable@2.2.1: {}
@@ -5899,6 +6430,8 @@ snapshots:
5899
  dependencies:
5900
  is-number: 7.0.0
5901
 
 
 
5902
  totalist@3.0.1: {}
5903
 
5904
  tough-cookie@5.1.2:
@@ -5938,6 +6471,12 @@ snapshots:
5938
 
5939
  type-fest@4.37.0: {}
5940
 
 
 
 
 
 
 
5941
  typescript-eslint@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2):
5942
  dependencies:
5943
  '@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
@@ -6001,7 +6540,9 @@ snapshots:
6001
  unist-util-is: 6.0.0
6002
  unist-util-visit-parents: 6.0.1
6003
 
6004
- unplugin-icons@22.1.0(svelte@5.36.16):
 
 
6005
  dependencies:
6006
  '@antfu/install-pkg': 1.0.0
6007
  '@iconify/utils': 2.3.0
@@ -6009,7 +6550,7 @@ snapshots:
6009
  local-pkg: 1.1.1
6010
  unplugin: 2.2.0
6011
  optionalDependencies:
6012
- svelte: 5.36.16
6013
  transitivePeerDependencies:
6014
  - supports-color
6015
 
@@ -6031,6 +6572,8 @@ snapshots:
6031
 
6032
  uuid@8.3.2: {}
6033
 
 
 
6034
  vfile-message@4.0.2:
6035
  dependencies:
6036
  '@types/unist': 3.0.3
@@ -6085,10 +6628,10 @@ snapshots:
6085
  optionalDependencies:
6086
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
6087
 
6088
- vitest-browser-svelte@0.1.0(@vitest/browser@3.1.4)(svelte@5.36.16)(vitest@3.1.4):
6089
  dependencies:
6090
  '@vitest/browser': 3.1.4(playwright@1.52.0)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)
6091
- svelte: 5.36.16
6092
  vitest: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
6093
 
6094
  vitest@3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1):
@@ -6182,6 +6725,8 @@ snapshots:
6182
  string-width: 4.2.3
6183
  strip-ansi: 6.0.1
6184
 
 
 
6185
  ws@8.18.2: {}
6186
 
6187
  xml-name-validator@5.0.0: {}
@@ -6201,4 +6746,10 @@ snapshots:
6201
 
6202
  zimmerframe@1.1.2: {}
6203
 
 
 
 
 
 
 
6204
  zwitch@2.0.4: {}
 
8
 
9
  .:
10
  dependencies:
11
+ '@modelcontextprotocol/sdk':
12
+ specifier: ^1.13.3
13
+ version: 1.17.5
14
  '@tailwindcss/typography':
15
  specifier: ^0.5.16
16
  version: 0.5.16(tailwindcss@4.0.9)
 
18
  specifier: ^2.0.3
19
  version: 2.0.3
20
  eslint-plugin-svelte:
21
+ specifier: ^3.12.2
22
+ version: 3.12.2(eslint@9.22.0(jiti@2.4.2))(svelte@5.38.7)
23
  marked:
24
  specifier: ^16.1.2
25
  version: 16.1.2
26
  remult:
27
  specifier: ^3.0.2
28
  version: 3.0.2
29
+ tailwindcss-spring:
30
+ specifier: ^1.0.1
31
+ version: 1.0.1(tailwindcss@4.0.9)
32
  typia:
33
  specifier: ^8.0.0
34
  version: 8.0.0(@samchon/openapi@3.0.0)(typescript@5.8.2)
 
73
  specifier: ^3.0.0
74
  version: 3.0.0
75
  '@sveltejs/adapter-auto':
76
+ specifier: ^3.3.1
77
+ version: 3.3.1(@sveltejs/kit@2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
78
  '@sveltejs/adapter-node':
79
+ specifier: ^5.3.1
80
+ version: 5.3.1(@sveltejs/kit@2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))
81
  '@sveltejs/kit':
82
+ specifier: ^2.37.1
83
+ version: 2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
84
  '@sveltejs/vite-plugin-svelte':
85
+ specifier: ^4.0.4
86
+ version: 4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
87
  '@tailwindcss/container-queries':
88
  specifier: ^0.1.1
89
  version: 0.1.1(tailwindcss@4.0.9)
 
95
  version: 6.6.3
96
  '@testing-library/svelte':
97
  specifier: ^5.2.4
98
+ version: 5.2.8(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)
99
  '@types/node':
100
  specifier: ^22.14.1
101
  version: 22.14.1
 
134
  version: 26.1.0
135
  melt:
136
  specifier: ^0.36.0
137
+ version: 0.36.0(@floating-ui/dom@1.6.13)(svelte@5.38.7)
138
  openai:
139
  specifier: ^4.90.0
140
+ version: 4.90.0(ws@8.18.2)(zod@3.25.76)
141
  playwright:
142
  specifier: ^1.52.0
143
  version: 1.52.0
 
149
  version: 3.5.3
150
  prettier-plugin-svelte:
151
  specifier: ^3.4.0
152
+ version: 3.4.0(prettier@3.5.3)(svelte@5.38.7)
153
  prettier-plugin-tailwindcss:
154
  specifier: ^0.6.11
155
+ version: 0.6.11(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.38.7))(prettier@3.5.3)
156
  runed:
157
  specifier: ^0.25.0
158
+ version: 0.25.0(svelte@5.38.7)
159
  shiki:
160
  specifier: ^3.4.0
161
  version: 3.4.0
162
  svelte:
163
+ specifier: ^5.38.7
164
+ version: 5.38.7
165
  svelte-check:
166
+ specifier: ^4.3.1
167
+ version: 4.3.1(picomatch@4.0.2)(svelte@5.38.7)(typescript@5.8.2)
168
  tailwind-merge:
169
  specifier: ^3.0.2
170
  version: 3.0.2
 
185
  version: 8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
186
  unplugin-icons:
187
  specifier: ^22.1.0
188
+ version: 22.1.0(svelte@5.38.7)
189
  vite:
190
  specifier: ^5.4.4
191
  version: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
 
194
  version: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
195
  vitest-browser-svelte:
196
  specifier: ^0.1.0
197
+ version: 0.1.0(@vitest/browser@3.1.4)(svelte@5.38.7)(vitest@3.1.4)
198
 
199
  packages:
200
 
 
205
  resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==}
206
  engines: {node: '>=10'}
207
 
 
 
 
 
208
  '@antfu/install-pkg@1.0.0':
209
  resolution: {integrity: sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw==}
210
 
 
776
  resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==}
777
  engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
778
 
779
+ '@jridgewell/gen-mapping@0.3.13':
780
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
781
+
782
+ '@jridgewell/remapping@2.3.5':
783
+ resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==}
784
 
785
  '@jridgewell/resolve-uri@3.1.2':
786
  resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
787
  engines: {node: '>=6.0.0'}
788
 
 
 
 
 
789
  '@jridgewell/sourcemap-codec@1.5.0':
790
  resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==}
791
 
792
+ '@jridgewell/sourcemap-codec@1.5.5':
793
+ resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
794
+
795
  '@jridgewell/trace-mapping@0.3.25':
796
  resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==}
797
 
798
+ '@jridgewell/trace-mapping@0.3.30':
799
+ resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
800
+
801
+ '@modelcontextprotocol/sdk@1.17.5':
802
+ resolution: {integrity: sha512-QakrKIGniGuRVfWBdMsDea/dx1PNE739QJ7gCM41s9q+qaCYTHCdsIBXQVVXry3mfWAiaM9kT22Hyz53Uw8mfg==}
803
+ engines: {node: '>=18'}
804
+
805
  '@noble/hashes@1.8.0':
806
  resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==}
807
  engines: {node: ^14.21.3 || >=16}
 
1024
  '@sinclair/typebox@0.27.8':
1025
  resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
1026
 
1027
+ '@standard-schema/spec@1.0.0':
1028
+ resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
1029
+
1030
  '@sveltejs/acorn-typescript@1.0.5':
1031
  resolution: {integrity: sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==}
1032
  peerDependencies:
 
1037
  peerDependencies:
1038
  '@sveltejs/kit': ^2.0.0
1039
 
1040
+ '@sveltejs/adapter-node@5.3.1':
1041
+ resolution: {integrity: sha512-PSoGfa9atkmuixe7jvuS2tsUohVZF20So87ASzfMRGTTNqEd8s48KAodlv3CzHwq9XO/BM8KsQLpqqsr/6dmuA==}
1042
  peerDependencies:
1043
  '@sveltejs/kit': ^2.4.0
1044
 
1045
+ '@sveltejs/kit@2.37.1':
1046
+ resolution: {integrity: sha512-4T9rF2Roe7RGvHfcn6+n92Yc2NF88k7ljFz9+wE0jWxyencqRpadr2/CvlcQbbTXf1ozmFxgMO6af+qm+1mPFw==}
1047
  engines: {node: '>=18.13'}
1048
  hasBin: true
1049
  peerDependencies:
1050
+ '@opentelemetry/api': ^1.0.0
1051
+ '@sveltejs/vite-plugin-svelte': ^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0
1052
  svelte: ^4.0.0 || ^5.0.0-next.0
1053
+ vite: ^5.0.3 || ^6.0.0 || ^7.0.0-beta.0
1054
+ peerDependenciesMeta:
1055
+ '@opentelemetry/api':
1056
+ optional: true
1057
 
1058
  '@sveltejs/vite-plugin-svelte-inspector@3.0.1':
1059
  resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==}
 
1314
  resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==}
1315
  engines: {node: '>=6.5'}
1316
 
1317
+ accepts@2.0.0:
1318
+ resolution: {integrity: sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==}
1319
+ engines: {node: '>= 0.6'}
1320
+
1321
  acorn-jsx@5.3.2:
1322
  resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
1323
  peerDependencies:
 
1328
  engines: {node: '>=0.4.0'}
1329
  hasBin: true
1330
 
1331
+ acorn@8.15.0:
1332
+ resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==}
1333
+ engines: {node: '>=0.4.0'}
1334
+ hasBin: true
1335
+
1336
  agent-base@7.1.3:
1337
  resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==}
1338
  engines: {node: '>= 14'}
 
1397
  bl@4.1.0:
1398
  resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
1399
 
1400
+ body-parser@2.2.0:
1401
+ resolution: {integrity: sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==}
1402
+ engines: {node: '>=18'}
1403
+
1404
  boolean@3.2.0:
1405
  resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
1406
  deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
 
1418
  buffer@5.7.1:
1419
  resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
1420
 
1421
+ bytes@3.1.2:
1422
+ resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==}
1423
+ engines: {node: '>= 0.8'}
1424
+
1425
  cac@6.7.14:
1426
  resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==}
1427
  engines: {node: '>=8'}
 
1430
  resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==}
1431
  engines: {node: '>= 0.4'}
1432
 
1433
+ call-bound@1.0.4:
1434
+ resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
1435
+ engines: {node: '>= 0.4'}
1436
+
1437
  callsites@3.1.0:
1438
  resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
1439
  engines: {node: '>=6'}
 
1542
  resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==}
1543
  engines: {node: ^14.18.0 || >=16.10.0}
1544
 
1545
+ content-disposition@1.0.0:
1546
+ resolution: {integrity: sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==}
1547
+ engines: {node: '>= 0.6'}
1548
+
1549
+ content-type@1.0.5:
1550
+ resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==}
1551
+ engines: {node: '>= 0.6'}
1552
+
1553
+ cookie-signature@1.2.2:
1554
+ resolution: {integrity: sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==}
1555
+ engines: {node: '>=6.6.0'}
1556
+
1557
  cookie@0.6.0:
1558
  resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
1559
  engines: {node: '>= 0.6'}
1560
 
1561
+ cookie@0.7.2:
1562
+ resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==}
1563
+ engines: {node: '>= 0.6'}
1564
+
1565
  core-util-is@1.0.3:
1566
  resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==}
1567
 
1568
+ cors@2.8.5:
1569
+ resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==}
1570
+ engines: {node: '>= 0.10'}
1571
+
1572
  cross-spawn@7.0.6:
1573
  resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
1574
  engines: {node: '>= 8'}
 
1630
  resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
1631
  engines: {node: '>=0.4.0'}
1632
 
1633
+ depd@2.0.0:
1634
+ resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==}
1635
+ engines: {node: '>= 0.8'}
1636
+
1637
  dequal@2.0.3:
1638
  resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
1639
  engines: {node: '>=6'}
 
1650
  detect-node@2.1.0:
1651
  resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
1652
 
1653
+ devalue@5.3.2:
1654
+ resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==}
1655
 
1656
  devlop@1.1.0:
1657
  resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==}
 
1681
  resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==}
1682
  engines: {node: '>= 0.4'}
1683
 
1684
+ ee-first@1.1.1:
1685
+ resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==}
1686
+
1687
  emoji-regex@8.0.0:
1688
  resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
1689
 
1690
+ encodeurl@2.0.0:
1691
+ resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==}
1692
+ engines: {node: '>= 0.8'}
1693
+
1694
  enhanced-resolve@5.18.1:
1695
  resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
1696
  engines: {node: '>=10.13.0'}
 
1731
  engines: {node: '>=18'}
1732
  hasBin: true
1733
 
1734
+ escape-html@1.0.3:
1735
+ resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
1736
+
1737
  escape-string-regexp@1.0.5:
1738
  resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
1739
  engines: {node: '>=0.8.0'}
 
1762
  eslint-config-prettier:
1763
  optional: true
1764
 
1765
+ eslint-plugin-svelte@3.12.2:
1766
+ resolution: {integrity: sha512-NDYltSWcDybvnXD5P3NtrLAfdrgr2lklZsXpyIoSlQfg2d80p/E853XXccu+uVn+w4+Q/iHy4oRw00GJH9I/Cg==}
1767
  engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
1768
  peerDependencies:
1769
  eslint: ^8.57.1 || ^9.0.0
 
1831
  resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
1832
  engines: {node: '>=0.10.0'}
1833
 
1834
+ etag@1.8.1:
1835
+ resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==}
1836
+ engines: {node: '>= 0.6'}
1837
+
1838
  event-target-shim@5.0.1:
1839
  resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==}
1840
  engines: {node: '>=6'}
1841
 
1842
+ eventsource-parser@3.0.6:
1843
+ resolution: {integrity: sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==}
1844
+ engines: {node: '>=18.0.0'}
1845
+
1846
+ eventsource@3.0.7:
1847
+ resolution: {integrity: sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==}
1848
+ engines: {node: '>=18.0.0'}
1849
+
1850
  expect-type@1.2.1:
1851
  resolution: {integrity: sha512-/kP8CAwxzLVEeFrMm4kMmy4CCDlpipyA7MYLVrdJIkV0fYF0UaigQHRsxHiuY/GEea+bh4KSv3TIlgr+2UL6bw==}
1852
  engines: {node: '>=12.0.0'}
1853
 
1854
+ express-rate-limit@7.5.1:
1855
+ resolution: {integrity: sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==}
1856
+ engines: {node: '>= 16'}
1857
+ peerDependencies:
1858
+ express: '>= 4.11'
1859
+
1860
+ express@5.1.0:
1861
+ resolution: {integrity: sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==}
1862
+ engines: {node: '>= 18'}
1863
+
1864
  exsolve@1.0.4:
1865
  resolution: {integrity: sha512-xsZH6PXaER4XoV+NiT7JHp1bJodJVT+cxeSH1G0f0tlT0lJqYuHUP3bUx2HtfTDvOagMINYp8rsqusxud3RXhw==}
1866
 
 
1919
  resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
1920
  engines: {node: '>=8'}
1921
 
1922
+ finalhandler@2.1.0:
1923
+ resolution: {integrity: sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==}
1924
+ engines: {node: '>= 0.8'}
1925
+
1926
  find-cache-dir@5.0.0:
1927
  resolution: {integrity: sha512-OuWNfjfP05JcpAP3JPgAKUhWefjMRfI5iAoSsvE24ANYWJaepAtlSgWECSVEuRgSXpyNEc9DJwG/TZpgcOqyig==}
1928
  engines: {node: '>=16'}
 
1956
  resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==}
1957
  engines: {node: '>= 12.20'}
1958
 
1959
+ forwarded@0.2.0:
1960
+ resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
1961
+ engines: {node: '>= 0.6'}
1962
+
1963
+ fresh@2.0.0:
1964
+ resolution: {integrity: sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==}
1965
+ engines: {node: '>= 0.8'}
1966
+
1967
  fsevents@2.3.2:
1968
  resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==}
1969
  engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
 
2070
  html-void-elements@3.0.0:
2071
  resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==}
2072
 
2073
+ http-errors@2.0.0:
2074
+ resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
2075
+ engines: {node: '>= 0.8'}
2076
+
2077
  http-proxy-agent@7.0.2:
2078
  resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==}
2079
  engines: {node: '>= 14'}
 
2093
  resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
2094
  engines: {node: '>=0.10.0'}
2095
 
2096
+ iconv-lite@0.7.0:
2097
+ resolution: {integrity: sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==}
2098
+ engines: {node: '>=0.10.0'}
2099
+
2100
  ieee754@1.2.1:
2101
  resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
2102
 
 
2130
  resolution: {integrity: sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==}
2131
  engines: {node: '>=12.0.0'}
2132
 
2133
+ ipaddr.js@1.9.1:
2134
+ resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==}
2135
+ engines: {node: '>= 0.10'}
2136
+
2137
  is-arrayish@0.3.2:
2138
  resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
2139
 
 
2167
  is-potential-custom-element-name@1.0.1:
2168
  resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
2169
 
2170
+ is-promise@4.0.0:
2171
+ resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==}
2172
+
2173
  is-reference@1.2.1:
2174
  resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==}
2175
 
 
2387
  mdast-util-to-hast@13.2.0:
2388
  resolution: {integrity: sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==}
2389
 
2390
+ media-typer@1.1.0:
2391
+ resolution: {integrity: sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==}
2392
+ engines: {node: '>= 0.8'}
2393
+
2394
  melt@0.36.0:
2395
  resolution: {integrity: sha512-lJdUuPvsCZs7zpcL2iSvxerHxv3QuM91FoTbdsliOQ2+J3fR4ADqUN878J4kkQSzzHlWqyedQmEBDP6U3iEWgA==}
2396
  peerDependencies:
2397
  '@floating-ui/dom': ^1.6.0
2398
  svelte: ^5.30.1
2399
 
2400
+ merge-descriptors@2.0.0:
2401
+ resolution: {integrity: sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==}
2402
+ engines: {node: '>=18'}
2403
+
2404
  merge2@1.4.1:
2405
  resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
2406
  engines: {node: '>= 8'}
 
2428
  resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
2429
  engines: {node: '>= 0.6'}
2430
 
2431
+ mime-db@1.54.0:
2432
+ resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
2433
+ engines: {node: '>= 0.6'}
2434
+
2435
  mime-types@2.1.35:
2436
  resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
2437
  engines: {node: '>= 0.6'}
2438
 
2439
+ mime-types@3.0.1:
2440
+ resolution: {integrity: sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==}
2441
+ engines: {node: '>= 0.6'}
2442
+
2443
  mimic-fn@2.1.0:
2444
  resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
2445
  engines: {node: '>=6'}
 
2501
  natural-compare@1.4.0:
2502
  resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
2503
 
2504
+ negotiator@1.0.0:
2505
+ resolution: {integrity: sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==}
2506
+ engines: {node: '>= 0.6'}
2507
+
2508
  node-domexception@1.0.0:
2509
  resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
2510
  engines: {node: '>=10.5.0'}
 
2521
  nwsapi@2.2.20:
2522
  resolution: {integrity: sha512-/ieB+mDe4MrrKMT8z+mQL8klXydZWGR5Dowt4RAGKbJ3kIGEx3X4ljUo+6V73IXtUPWgfOlU5B9MlGxFO5T+cA==}
2523
 
2524
+ object-assign@4.1.1:
2525
+ resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==}
2526
+ engines: {node: '>=0.10.0'}
2527
+
2528
+ object-inspect@1.13.4:
2529
+ resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==}
2530
+ engines: {node: '>= 0.4'}
2531
+
2532
  object-keys@1.1.1:
2533
  resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
2534
  engines: {node: '>= 0.4'}
2535
 
2536
+ on-finished@2.4.1:
2537
+ resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==}
2538
+ engines: {node: '>= 0.8'}
2539
+
2540
+ once@1.4.0:
2541
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
2542
+
2543
  onetime@5.1.2:
2544
  resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
2545
  engines: {node: '>=6'}
 
2613
  parse5@7.3.0:
2614
  resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==}
2615
 
2616
+ parseurl@1.3.3:
2617
+ resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
2618
+ engines: {node: '>= 0.8'}
2619
+
2620
  path-exists@4.0.0:
2621
  resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
2622
  engines: {node: '>=8'}
 
2632
  path-parse@1.0.7:
2633
  resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
2634
 
2635
+ path-to-regexp@8.3.0:
2636
+ resolution: {integrity: sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==}
2637
+
2638
  pathe@1.1.2:
2639
  resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
2640
 
 
2656
  resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==}
2657
  engines: {node: '>=12'}
2658
 
2659
+ pkce-challenge@5.0.0:
2660
+ resolution: {integrity: sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==}
2661
+ engines: {node: '>=16.20.0'}
2662
+
2663
  pkg-dir@7.0.0:
2664
  resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==}
2665
  engines: {node: '>=14.16'}
 
2808
  resolution: {integrity: sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw==}
2809
  engines: {node: '>=12.0.0'}
2810
 
2811
+ proxy-addr@2.0.7:
2812
+ resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==}
2813
+ engines: {node: '>= 0.10'}
2814
+
2815
  punycode@2.3.1:
2816
  resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
2817
  engines: {node: '>=6'}
2818
 
2819
+ qs@6.14.0:
2820
+ resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==}
2821
+ engines: {node: '>=0.6'}
2822
+
2823
  quansync@0.2.8:
2824
  resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==}
2825
 
 
2830
  resolution: {integrity: sha512-U+5l2KrcMNOUPYvazA3h5ekF80FHTUG+87SEAmHZmolh1M+i/WyTCxVzmi+tidIa1tM4BSe8g2Y/D3loWDjj+w==}
2831
  engines: {node: '>=4'}
2832
 
2833
+ range-parser@1.2.1:
2834
+ resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==}
2835
+ engines: {node: '>= 0.6'}
2836
+
2837
+ raw-body@3.0.1:
2838
+ resolution: {integrity: sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==}
2839
+ engines: {node: '>= 0.10'}
2840
+
2841
  react-is@17.0.2:
2842
  resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==}
2843
 
 
2905
  engines: {node: '>=18.0.0', npm: '>=8.0.0'}
2906
  hasBin: true
2907
 
2908
+ router@2.2.0:
2909
+ resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==}
2910
+ engines: {node: '>= 18'}
2911
+
2912
  rrweb-cssom@0.8.0:
2913
  resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==}
2914
 
 
2959
  engines: {node: '>=10'}
2960
  hasBin: true
2961
 
2962
+ send@1.2.0:
2963
+ resolution: {integrity: sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==}
2964
+ engines: {node: '>= 18'}
2965
+
2966
  serialize-error@7.0.1:
2967
  resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
2968
  engines: {node: '>=10'}
2969
 
2970
+ serve-static@2.2.0:
2971
+ resolution: {integrity: sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==}
2972
+ engines: {node: '>= 18'}
2973
+
2974
  set-cookie-parser@2.7.1:
2975
  resolution: {integrity: sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==}
2976
 
2977
+ setprototypeof@1.2.0:
2978
+ resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==}
2979
+
2980
  sharp@0.34.2:
2981
  resolution: {integrity: sha512-lszvBmB9QURERtyKT2bNmsgxXK0ShJrL/fvqlonCo7e6xBF8nT8xU6pW+PMIbLsz0RxQk3rgH9kd8UmvOzlMJg==}
2982
  engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0}
 
2992
  shiki@3.4.0:
2993
  resolution: {integrity: sha512-Ni80XHcqhOEXv5mmDAvf5p6PAJqbUc/RzFeaOqk+zP5DLvTPS3j0ckvA+MI87qoxTQ5RGJDVTbdl/ENLSyyAnQ==}
2994
 
2995
+ side-channel-list@1.0.0:
2996
+ resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==}
2997
+ engines: {node: '>= 0.4'}
2998
+
2999
+ side-channel-map@1.0.1:
3000
+ resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==}
3001
+ engines: {node: '>= 0.4'}
3002
+
3003
+ side-channel-weakmap@1.0.2:
3004
+ resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==}
3005
+ engines: {node: '>= 0.4'}
3006
+
3007
+ side-channel@1.1.0:
3008
+ resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
3009
+ engines: {node: '>= 0.4'}
3010
+
3011
  siginfo@2.0.0:
3012
  resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
3013
 
 
3034
  stackback@0.0.2:
3035
  resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
3036
 
3037
+ statuses@2.0.1:
3038
+ resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
3039
+ engines: {node: '>= 0.8'}
3040
+
3041
+ statuses@2.0.2:
3042
+ resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==}
3043
+ engines: {node: '>= 0.8'}
3044
+
3045
  std-env@3.9.0:
3046
  resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==}
3047
 
 
3075
  resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
3076
  engines: {node: '>= 0.4'}
3077
 
3078
+ svelte-check@4.3.1:
3079
+ resolution: {integrity: sha512-lkh8gff5gpHLjxIV+IaApMxQhTGnir2pNUAqcNgeKkvK5bT/30Ey/nzBxNLDlkztCH4dP7PixkMt9SWEKFPBWg==}
3080
  engines: {node: '>= 18.0.0'}
3081
  hasBin: true
3082
  peerDependencies:
 
3092
  svelte:
3093
  optional: true
3094
 
3095
+ svelte@5.38.7:
3096
+ resolution: {integrity: sha512-1ld9TPZSdUS3EtYGQzisU2nhwXoIzNQcZ71IOU9fEmltaUofQnVfW5CQuhgM/zFsZ43arZXS1BRKi0MYgUV91w==}
3097
  engines: {node: '>=18'}
3098
 
3099
  symbol-tree@3.2.4:
 
3106
  tailwind-merge@3.0.2:
3107
  resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==}
3108
 
3109
+ tailwindcss-spring@1.0.1:
3110
+ resolution: {integrity: sha512-v8ibKyVCgbFcHzP9EFSbsvR0vH7Vk2Skl9JnJ9HUrnA16NhjvI4SlV9Y4SkinL+4bNrm1XpftZwX1DAD1mNZFA==}
3111
+ peerDependencies:
3112
+ tailwindcss: '>=3.0.0 || insiders'
3113
+
3114
  tailwindcss@4.0.9:
3115
  resolution: {integrity: sha512-12laZu+fv1ONDRoNR9ipTOpUD7RN9essRVkX36sjxuRUInpN7hIiHN4lBd/SIFjbISvnXzp8h/hXzmU8SQQYhw==}
3116
 
 
3162
  resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
3163
  engines: {node: '>=8.0'}
3164
 
3165
+ toidentifier@1.0.1:
3166
+ resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==}
3167
+ engines: {node: '>=0.6'}
3168
+
3169
  totalist@3.0.1:
3170
  resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
3171
  engines: {node: '>=6'}
 
3213
  resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==}
3214
  engines: {node: '>=16'}
3215
 
3216
+ type-is@2.0.1:
3217
+ resolution: {integrity: sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==}
3218
+ engines: {node: '>= 0.6'}
3219
+
3220
  typescript-eslint@8.26.1:
3221
  resolution: {integrity: sha512-t/oIs9mYyrwZGRpDv3g+3K6nZ5uhKEMt2oNmAPwaY4/ye0+EH4nXIPYNtkYFS6QHm+1DFg34DbglYBz5P9Xysg==}
3222
  engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
3272
  unist-util-visit@5.0.0:
3273
  resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==}
3274
 
3275
+ unpipe@1.0.0:
3276
+ resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
3277
+ engines: {node: '>= 0.8'}
3278
+
3279
  unplugin-icons@22.1.0:
3280
  resolution: {integrity: sha512-ect2ZNtk1Zgwb0NVHd0C1IDW/MV+Jk/xaq4t8o6rYdVS3+L660ZdD5kTSQZvsgdwCvquRw+/wYn75hsweRjoIA==}
3281
  peerDependencies:
 
3317
  resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==}
3318
  hasBin: true
3319
 
3320
+ vary@1.1.2:
3321
+ resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
3322
+ engines: {node: '>= 0.8'}
3323
+
3324
  vfile-message@4.0.2:
3325
  resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==}
3326
 
 
3506
  resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
3507
  engines: {node: '>=8'}
3508
 
3509
+ wrappy@1.0.2:
3510
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
3511
+
3512
  ws@8.18.2:
3513
  resolution: {integrity: sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==}
3514
  engines: {node: '>=10.0.0'}
 
3552
  zimmerframe@1.1.2:
3553
  resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==}
3554
 
3555
+ zod-to-json-schema@3.24.6:
3556
+ resolution: {integrity: sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==}
3557
+ peerDependencies:
3558
+ zod: ^3.24.1
3559
+
3560
+ zod@3.25.76:
3561
+ resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==}
3562
+
3563
  zwitch@2.0.4:
3564
  resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
3565
 
 
3569
 
3570
  '@alloc/quick-lru@5.2.0': {}
3571
 
 
 
 
 
 
3572
  '@antfu/install-pkg@1.0.0':
3573
  dependencies:
3574
  package-manager-detector: 0.2.11
 
3972
  dependencies:
3973
  '@sinclair/typebox': 0.27.8
3974
 
3975
+ '@jridgewell/gen-mapping@0.3.13':
3976
  dependencies:
 
3977
  '@jridgewell/sourcemap-codec': 1.5.0
3978
+ '@jridgewell/trace-mapping': 0.3.30
3979
 
3980
+ '@jridgewell/remapping@2.3.5':
3981
+ dependencies:
3982
+ '@jridgewell/gen-mapping': 0.3.13
3983
+ '@jridgewell/trace-mapping': 0.3.30
3984
 
3985
+ '@jridgewell/resolve-uri@3.1.2': {}
3986
 
3987
  '@jridgewell/sourcemap-codec@1.5.0': {}
3988
 
3989
+ '@jridgewell/sourcemap-codec@1.5.5': {}
3990
+
3991
  '@jridgewell/trace-mapping@0.3.25':
3992
  dependencies:
3993
  '@jridgewell/resolve-uri': 3.1.2
3994
  '@jridgewell/sourcemap-codec': 1.5.0
3995
 
3996
+ '@jridgewell/trace-mapping@0.3.30':
3997
+ dependencies:
3998
+ '@jridgewell/resolve-uri': 3.1.2
3999
+ '@jridgewell/sourcemap-codec': 1.5.0
4000
+
4001
+ '@modelcontextprotocol/sdk@1.17.5':
4002
+ dependencies:
4003
+ ajv: 6.12.6
4004
+ content-type: 1.0.5
4005
+ cors: 2.8.5
4006
+ cross-spawn: 7.0.6
4007
+ eventsource: 3.0.7
4008
+ eventsource-parser: 3.0.6
4009
+ express: 5.1.0
4010
+ express-rate-limit: 7.5.1(express@5.1.0)
4011
+ pkce-challenge: 5.0.0
4012
+ raw-body: 3.0.1
4013
+ zod: 3.25.76
4014
+ zod-to-json-schema: 3.24.6(zod@3.25.76)
4015
+ transitivePeerDependencies:
4016
+ - supports-color
4017
+
4018
  '@noble/hashes@1.8.0': {}
4019
 
4020
  '@nodelib/fs.scandir@2.1.5':
 
4224
 
4225
  '@sinclair/typebox@0.27.8': {}
4226
 
4227
+ '@standard-schema/spec@1.0.0': {}
4228
+
4229
  '@sveltejs/acorn-typescript@1.0.5(acorn@8.14.0)':
4230
  dependencies:
4231
  acorn: 8.14.0
4232
 
4233
+ '@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)':
4234
  dependencies:
4235
+ acorn: 8.15.0
4236
+
4237
+ '@sveltejs/adapter-auto@3.3.1(@sveltejs/kit@2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
4238
+ dependencies:
4239
+ '@sveltejs/kit': 2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4240
  import-meta-resolve: 4.1.0
4241
 
4242
+ '@sveltejs/adapter-node@5.3.1(@sveltejs/kit@2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))':
4243
  dependencies:
4244
  '@rollup/plugin-commonjs': 28.0.2(rollup@4.34.9)
4245
  '@rollup/plugin-json': 6.1.0(rollup@4.34.9)
4246
  '@rollup/plugin-node-resolve': 16.0.0(rollup@4.34.9)
4247
+ '@sveltejs/kit': 2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4248
  rollup: 4.34.9
4249
 
4250
+ '@sveltejs/kit@2.37.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
4251
  dependencies:
4252
+ '@standard-schema/spec': 1.0.0
4253
+ '@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
4254
+ '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4255
  '@types/cookie': 0.6.0
4256
+ acorn: 8.15.0
4257
  cookie: 0.6.0
4258
+ devalue: 5.3.2
4259
  esm-env: 1.2.2
 
4260
  kleur: 4.1.5
4261
  magic-string: 0.30.17
4262
  mrmime: 2.0.1
4263
  sade: 1.8.1
4264
  set-cookie-parser: 2.7.1
4265
  sirv: 3.0.1
4266
+ svelte: 5.38.7
4267
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4268
 
4269
+ '@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
4270
  dependencies:
4271
+ '@sveltejs/vite-plugin-svelte': 4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4272
  debug: 4.4.0
4273
+ svelte: 5.38.7
4274
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4275
  transitivePeerDependencies:
4276
  - supports-color
4277
 
4278
+ '@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))':
4279
  dependencies:
4280
+ '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.4(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)))(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4281
  debug: 4.4.0
4282
  deepmerge: 4.3.1
4283
  kleur: 4.1.5
4284
  magic-string: 0.30.17
4285
+ svelte: 5.38.7
4286
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4287
  vitefu: 1.0.6(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))
4288
  transitivePeerDependencies:
 
4383
  lodash: 4.17.21
4384
  redent: 3.0.0
4385
 
4386
+ '@testing-library/svelte@5.2.8(svelte@5.38.7)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)':
4387
  dependencies:
4388
  '@testing-library/dom': 10.4.0
4389
+ svelte: 5.38.7
4390
  optionalDependencies:
4391
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
4392
  vitest: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
 
4570
  dependencies:
4571
  event-target-shim: 5.0.1
4572
 
4573
+ accepts@2.0.0:
4574
+ dependencies:
4575
+ mime-types: 3.0.1
4576
+ negotiator: 1.0.0
4577
+
4578
  acorn-jsx@5.3.2(acorn@8.14.0):
4579
  dependencies:
4580
  acorn: 8.14.0
4581
 
4582
  acorn@8.14.0: {}
4583
 
4584
+ acorn@8.15.0: {}
4585
+
4586
  agent-base@7.1.3: {}
4587
 
4588
  agentkeepalive@4.6.0:
 
4636
  inherits: 2.0.4
4637
  readable-stream: 3.6.2
4638
 
4639
+ body-parser@2.2.0:
4640
+ dependencies:
4641
+ bytes: 3.1.2
4642
+ content-type: 1.0.5
4643
+ debug: 4.4.0
4644
+ http-errors: 2.0.0
4645
+ iconv-lite: 0.6.3
4646
+ on-finished: 2.4.1
4647
+ qs: 6.14.0
4648
+ raw-body: 3.0.1
4649
+ type-is: 2.0.1
4650
+ transitivePeerDependencies:
4651
+ - supports-color
4652
+
4653
  boolean@3.2.0: {}
4654
 
4655
  brace-expansion@1.1.11:
 
4670
  base64-js: 1.5.1
4671
  ieee754: 1.2.1
4672
 
4673
+ bytes@3.1.2: {}
4674
+
4675
  cac@6.7.14: {}
4676
 
4677
  call-bind-apply-helpers@1.0.2:
 
4679
  es-errors: 1.3.0
4680
  function-bind: 1.1.2
4681
 
4682
+ call-bound@1.0.4:
4683
+ dependencies:
4684
+ call-bind-apply-helpers: 1.0.2
4685
+ get-intrinsic: 1.3.0
4686
+
4687
  callsites@3.1.0: {}
4688
 
4689
  ccount@2.0.1: {}
 
4776
 
4777
  consola@3.4.0: {}
4778
 
4779
+ content-disposition@1.0.0:
4780
+ dependencies:
4781
+ safe-buffer: 5.2.1
4782
+
4783
+ content-type@1.0.5: {}
4784
+
4785
+ cookie-signature@1.2.2: {}
4786
+
4787
  cookie@0.6.0: {}
4788
 
4789
+ cookie@0.7.2: {}
4790
+
4791
  core-util-is@1.0.3: {}
4792
 
4793
+ cors@2.8.5:
4794
+ dependencies:
4795
+ object-assign: 4.1.1
4796
+ vary: 1.1.2
4797
+
4798
  cross-spawn@7.0.6:
4799
  dependencies:
4800
  path-key: 3.1.1
 
4847
 
4848
  delayed-stream@1.0.0: {}
4849
 
4850
+ depd@2.0.0: {}
4851
+
4852
  dequal@2.0.3: {}
4853
 
4854
  detect-libc@1.0.3: {}
 
4857
 
4858
  detect-node@2.1.0: {}
4859
 
4860
+ devalue@5.3.2: {}
4861
 
4862
  devlop@1.1.0:
4863
  dependencies:
 
4881
  es-errors: 1.3.0
4882
  gopd: 1.2.0
4883
 
4884
+ ee-first@1.1.1: {}
4885
+
4886
  emoji-regex@8.0.0: {}
4887
 
4888
+ encodeurl@2.0.0: {}
4889
+
4890
  enhanced-resolve@5.18.1:
4891
  dependencies:
4892
  graceful-fs: 4.2.11
 
4967
  '@esbuild/win32-ia32': 0.25.1
4968
  '@esbuild/win32-x64': 0.25.1
4969
 
4970
+ escape-html@1.0.3: {}
4971
+
4972
  escape-string-regexp@1.0.5: {}
4973
 
4974
  escape-string-regexp@4.0.0: {}
 
4986
  optionalDependencies:
4987
  eslint-config-prettier: 10.1.1(eslint@9.22.0(jiti@2.4.2))
4988
 
4989
+ eslint-plugin-svelte@3.12.2(eslint@9.22.0(jiti@2.4.2))(svelte@5.38.7):
4990
  dependencies:
4991
  '@eslint-community/eslint-utils': 4.7.0(eslint@9.22.0(jiti@2.4.2))
4992
  '@jridgewell/sourcemap-codec': 1.5.0
 
4998
  postcss-load-config: 3.1.4(postcss@8.5.3)
4999
  postcss-safe-parser: 7.0.1(postcss@8.5.3)
5000
  semver: 7.7.2
5001
+ svelte-eslint-parser: 1.3.0(svelte@5.38.7)
5002
  optionalDependencies:
5003
+ svelte: 5.38.7
5004
  transitivePeerDependencies:
5005
  - ts-node
5006
 
 
5087
 
5088
  esutils@2.0.3: {}
5089
 
5090
+ etag@1.8.1: {}
5091
+
5092
  event-target-shim@5.0.1: {}
5093
 
5094
+ eventsource-parser@3.0.6: {}
5095
+
5096
+ eventsource@3.0.7:
5097
+ dependencies:
5098
+ eventsource-parser: 3.0.6
5099
+
5100
  expect-type@1.2.1: {}
5101
 
5102
+ express-rate-limit@7.5.1(express@5.1.0):
5103
+ dependencies:
5104
+ express: 5.1.0
5105
+
5106
+ express@5.1.0:
5107
+ dependencies:
5108
+ accepts: 2.0.0
5109
+ body-parser: 2.2.0
5110
+ content-disposition: 1.0.0
5111
+ content-type: 1.0.5
5112
+ cookie: 0.7.2
5113
+ cookie-signature: 1.2.2
5114
+ debug: 4.4.0
5115
+ encodeurl: 2.0.0
5116
+ escape-html: 1.0.3
5117
+ etag: 1.8.1
5118
+ finalhandler: 2.1.0
5119
+ fresh: 2.0.0
5120
+ http-errors: 2.0.0
5121
+ merge-descriptors: 2.0.0
5122
+ mime-types: 3.0.1
5123
+ on-finished: 2.4.1
5124
+ once: 1.4.0
5125
+ parseurl: 1.3.3
5126
+ proxy-addr: 2.0.7
5127
+ qs: 6.14.0
5128
+ range-parser: 1.2.1
5129
+ router: 2.2.0
5130
+ send: 1.2.0
5131
+ serve-static: 2.2.0
5132
+ statuses: 2.0.2
5133
+ type-is: 2.0.1
5134
+ vary: 1.1.2
5135
+ transitivePeerDependencies:
5136
+ - supports-color
5137
+
5138
  exsolve@1.0.4: {}
5139
 
5140
  external-editor@3.1.0:
 
5185
  dependencies:
5186
  to-regex-range: 5.0.1
5187
 
5188
+ finalhandler@2.1.0:
5189
+ dependencies:
5190
+ debug: 4.4.0
5191
+ encodeurl: 2.0.0
5192
+ escape-html: 1.0.3
5193
+ on-finished: 2.4.1
5194
+ parseurl: 1.3.3
5195
+ statuses: 2.0.2
5196
+ transitivePeerDependencies:
5197
+ - supports-color
5198
+
5199
  find-cache-dir@5.0.0:
5200
  dependencies:
5201
  common-path-prefix: 3.0.0
 
5234
  node-domexception: 1.0.0
5235
  web-streams-polyfill: 4.0.0-beta.3
5236
 
5237
+ forwarded@0.2.0: {}
5238
+
5239
+ fresh@2.0.0: {}
5240
+
5241
  fsevents@2.3.2:
5242
  optional: true
5243
 
 
5350
 
5351
  html-void-elements@3.0.0: {}
5352
 
5353
+ http-errors@2.0.0:
5354
+ dependencies:
5355
+ depd: 2.0.0
5356
+ inherits: 2.0.4
5357
+ setprototypeof: 1.2.0
5358
+ statuses: 2.0.1
5359
+ toidentifier: 1.0.1
5360
+
5361
  http-proxy-agent@7.0.2:
5362
  dependencies:
5363
  agent-base: 7.1.3
 
5384
  dependencies:
5385
  safer-buffer: 2.1.2
5386
 
5387
+ iconv-lite@0.7.0:
5388
+ dependencies:
5389
+ safer-buffer: 2.1.2
5390
+
5391
  ieee754@1.2.1: {}
5392
 
5393
  ignore@5.3.2: {}
 
5425
  through: 2.3.8
5426
  wrap-ansi: 6.2.0
5427
 
5428
+ ipaddr.js@1.9.1: {}
5429
+
5430
  is-arrayish@0.3.2: {}
5431
 
5432
  is-core-module@2.16.1:
 
5449
 
5450
  is-potential-custom-element-name@1.0.1: {}
5451
 
5452
+ is-promise@4.0.0: {}
5453
+
5454
  is-reference@1.2.1:
5455
  dependencies:
5456
  '@types/estree': 1.0.6
 
5634
 
5635
  magic-string@0.30.17:
5636
  dependencies:
5637
+ '@jridgewell/sourcemap-codec': 1.5.5
5638
 
5639
  marked@16.1.2: {}
5640
 
 
5656
  unist-util-visit: 5.0.0
5657
  vfile: 6.0.3
5658
 
5659
+ media-typer@1.1.0: {}
5660
+
5661
+ melt@0.36.0(@floating-ui/dom@1.6.13)(svelte@5.38.7):
5662
  dependencies:
5663
  '@floating-ui/dom': 1.6.13
5664
  dequal: 2.0.3
5665
  jest-axe: 9.0.0
5666
  nanoid: 5.1.5
5667
+ runed: 0.23.4(svelte@5.38.7)
5668
+ svelte: 5.38.7
5669
+
5670
+ merge-descriptors@2.0.0: {}
5671
 
5672
  merge2@1.4.1: {}
5673
 
 
5695
 
5696
  mime-db@1.52.0: {}
5697
 
5698
+ mime-db@1.54.0: {}
5699
+
5700
  mime-types@2.1.35:
5701
  dependencies:
5702
  mime-db: 1.52.0
5703
 
5704
+ mime-types@3.0.1:
5705
+ dependencies:
5706
+ mime-db: 1.54.0
5707
+
5708
  mimic-fn@2.1.0: {}
5709
 
5710
  min-indent@1.0.1: {}
 
5748
 
5749
  natural-compare@1.4.0: {}
5750
 
5751
+ negotiator@1.0.0: {}
5752
+
5753
  node-domexception@1.0.0: {}
5754
 
5755
  node-fetch@2.7.0:
 
5758
 
5759
  nwsapi@2.2.20: {}
5760
 
5761
+ object-assign@4.1.1: {}
5762
+
5763
+ object-inspect@1.13.4: {}
5764
+
5765
  object-keys@1.1.1: {}
5766
 
5767
+ on-finished@2.4.1:
5768
+ dependencies:
5769
+ ee-first: 1.1.1
5770
+
5771
+ once@1.4.0:
5772
+ dependencies:
5773
+ wrappy: 1.0.2
5774
+
5775
  onetime@5.1.2:
5776
  dependencies:
5777
  mimic-fn: 2.1.0
 
5803
  platform: 1.3.6
5804
  protobufjs: 7.4.0
5805
 
5806
+ openai@4.90.0(ws@8.18.2)(zod@3.25.76):
5807
  dependencies:
5808
  '@types/node': 18.19.84
5809
  '@types/node-fetch': 2.6.12
 
5814
  node-fetch: 2.7.0
5815
  optionalDependencies:
5816
  ws: 8.18.2
5817
+ zod: 3.25.76
5818
  transitivePeerDependencies:
5819
  - encoding
5820
 
 
5869
  dependencies:
5870
  entities: 6.0.0
5871
 
5872
+ parseurl@1.3.3: {}
5873
+
5874
  path-exists@4.0.0: {}
5875
 
5876
  path-exists@5.0.0: {}
 
5879
 
5880
  path-parse@1.0.7: {}
5881
 
5882
+ path-to-regexp@8.3.0: {}
5883
+
5884
  pathe@1.1.2: {}
5885
 
5886
  pathe@2.0.3: {}
 
5893
 
5894
  picomatch@4.0.2: {}
5895
 
5896
+ pkce-challenge@5.0.0: {}
5897
+
5898
  pkg-dir@7.0.0:
5899
  dependencies:
5900
  find-up: 6.3.0
 
5958
  dependencies:
5959
  fast-diff: 1.3.0
5960
 
5961
+ prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.38.7):
5962
  dependencies:
5963
  prettier: 3.5.3
5964
+ svelte: 5.38.7
5965
 
5966
+ prettier-plugin-tailwindcss@0.6.11(prettier-plugin-svelte@3.4.0(prettier@3.5.3)(svelte@5.38.7))(prettier@3.5.3):
5967
  dependencies:
5968
  prettier: 3.5.3
5969
  optionalDependencies:
5970
+ prettier-plugin-svelte: 3.4.0(prettier@3.5.3)(svelte@5.38.7)
5971
 
5972
  prettier@3.5.3: {}
5973
 
 
6000
  '@types/node': 22.14.1
6001
  long: 5.3.1
6002
 
6003
+ proxy-addr@2.0.7:
6004
+ dependencies:
6005
+ forwarded: 0.2.0
6006
+ ipaddr.js: 1.9.1
6007
+
6008
  punycode@2.3.1: {}
6009
 
6010
+ qs@6.14.0:
6011
+ dependencies:
6012
+ side-channel: 1.1.0
6013
+
6014
  quansync@0.2.8: {}
6015
 
6016
  queue-microtask@1.2.3: {}
 
6020
  drange: 1.1.1
6021
  ret: 0.2.2
6022
 
6023
+ range-parser@1.2.1: {}
6024
+
6025
+ raw-body@3.0.1:
6026
+ dependencies:
6027
+ bytes: 3.1.2
6028
+ http-errors: 2.0.0
6029
+ iconv-lite: 0.7.0
6030
+ unpipe: 1.0.0
6031
+
6032
  react-is@17.0.2: {}
6033
 
6034
  react-is@18.3.1: {}
 
6118
  '@rollup/rollup-win32-x64-msvc': 4.34.9
6119
  fsevents: 2.3.3
6120
 
6121
+ router@2.2.0:
6122
+ dependencies:
6123
+ debug: 4.4.0
6124
+ depd: 2.0.0
6125
+ is-promise: 4.0.0
6126
+ parseurl: 1.3.3
6127
+ path-to-regexp: 8.3.0
6128
+ transitivePeerDependencies:
6129
+ - supports-color
6130
+
6131
  rrweb-cssom@0.8.0: {}
6132
 
6133
  run-async@2.4.1: {}
 
6136
  dependencies:
6137
  queue-microtask: 1.2.3
6138
 
6139
+ runed@0.23.4(svelte@5.38.7):
6140
  dependencies:
6141
  esm-env: 1.2.2
6142
+ svelte: 5.38.7
6143
 
6144
+ runed@0.25.0(svelte@5.38.7):
6145
  dependencies:
6146
  esm-env: 1.2.2
6147
+ svelte: 5.38.7
6148
 
6149
  rxjs@7.8.2:
6150
  dependencies:
 
6168
 
6169
  semver@7.7.2: {}
6170
 
6171
+ send@1.2.0:
6172
+ dependencies:
6173
+ debug: 4.4.0
6174
+ encodeurl: 2.0.0
6175
+ escape-html: 1.0.3
6176
+ etag: 1.8.1
6177
+ fresh: 2.0.0
6178
+ http-errors: 2.0.0
6179
+ mime-types: 3.0.1
6180
+ ms: 2.1.3
6181
+ on-finished: 2.4.1
6182
+ range-parser: 1.2.1
6183
+ statuses: 2.0.2
6184
+ transitivePeerDependencies:
6185
+ - supports-color
6186
+
6187
  serialize-error@7.0.1:
6188
  dependencies:
6189
  type-fest: 0.13.1
6190
 
6191
+ serve-static@2.2.0:
6192
+ dependencies:
6193
+ encodeurl: 2.0.0
6194
+ escape-html: 1.0.3
6195
+ parseurl: 1.3.3
6196
+ send: 1.2.0
6197
+ transitivePeerDependencies:
6198
+ - supports-color
6199
+
6200
  set-cookie-parser@2.7.1: {}
6201
 
6202
+ setprototypeof@1.2.0: {}
6203
+
6204
  sharp@0.34.2:
6205
  dependencies:
6206
  color: 4.2.3
 
6246
  '@shikijs/vscode-textmate': 10.0.2
6247
  '@types/hast': 3.0.4
6248
 
6249
+ side-channel-list@1.0.0:
6250
+ dependencies:
6251
+ es-errors: 1.3.0
6252
+ object-inspect: 1.13.4
6253
+
6254
+ side-channel-map@1.0.1:
6255
+ dependencies:
6256
+ call-bound: 1.0.4
6257
+ es-errors: 1.3.0
6258
+ get-intrinsic: 1.3.0
6259
+ object-inspect: 1.13.4
6260
+
6261
+ side-channel-weakmap@1.0.2:
6262
+ dependencies:
6263
+ call-bound: 1.0.4
6264
+ es-errors: 1.3.0
6265
+ get-intrinsic: 1.3.0
6266
+ object-inspect: 1.13.4
6267
+ side-channel-map: 1.0.1
6268
+
6269
+ side-channel@1.1.0:
6270
+ dependencies:
6271
+ es-errors: 1.3.0
6272
+ object-inspect: 1.13.4
6273
+ side-channel-list: 1.0.0
6274
+ side-channel-map: 1.0.1
6275
+ side-channel-weakmap: 1.0.2
6276
+
6277
  siginfo@2.0.0: {}
6278
 
6279
  signal-exit@3.0.7: {}
 
6296
 
6297
  stackback@0.0.2: {}
6298
 
6299
+ statuses@2.0.1: {}
6300
+
6301
+ statuses@2.0.2: {}
6302
+
6303
  std-env@3.9.0: {}
6304
 
6305
  string-width@4.2.3:
 
6333
 
6334
  supports-preserve-symlinks-flag@1.0.0: {}
6335
 
6336
+ svelte-check@4.3.1(picomatch@4.0.2)(svelte@5.38.7)(typescript@5.8.2):
6337
  dependencies:
6338
  '@jridgewell/trace-mapping': 0.3.25
6339
  chokidar: 4.0.3
6340
  fdir: 6.4.3(picomatch@4.0.2)
6341
  picocolors: 1.1.1
6342
  sade: 1.8.1
6343
+ svelte: 5.38.7
6344
  typescript: 5.8.2
6345
  transitivePeerDependencies:
6346
  - picomatch
6347
 
6348
+ svelte-eslint-parser@1.3.0(svelte@5.38.7):
6349
  dependencies:
6350
  eslint-scope: 8.3.0
6351
  eslint-visitor-keys: 4.2.0
 
6354
  postcss-scss: 4.0.9(postcss@8.5.3)
6355
  postcss-selector-parser: 7.1.0
6356
  optionalDependencies:
6357
+ svelte: 5.38.7
6358
 
6359
+ svelte@5.38.7:
6360
  dependencies:
6361
+ '@jridgewell/remapping': 2.3.5
6362
  '@jridgewell/sourcemap-codec': 1.5.0
6363
  '@sveltejs/acorn-typescript': 1.0.5(acorn@8.14.0)
6364
  '@types/estree': 1.0.6
 
6382
 
6383
  tailwind-merge@3.0.2: {}
6384
 
6385
+ tailwindcss-spring@1.0.1(tailwindcss@4.0.9):
6386
+ dependencies:
6387
+ tailwindcss: 4.0.9
6388
+
6389
  tailwindcss@4.0.9: {}
6390
 
6391
  tapable@2.2.1: {}
 
6430
  dependencies:
6431
  is-number: 7.0.0
6432
 
6433
+ toidentifier@1.0.1: {}
6434
+
6435
  totalist@3.0.1: {}
6436
 
6437
  tough-cookie@5.1.2:
 
6471
 
6472
  type-fest@4.37.0: {}
6473
 
6474
+ type-is@2.0.1:
6475
+ dependencies:
6476
+ content-type: 1.0.5
6477
+ media-typer: 1.1.0
6478
+ mime-types: 3.0.1
6479
+
6480
  typescript-eslint@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2):
6481
  dependencies:
6482
  '@typescript-eslint/eslint-plugin': 8.26.1(@typescript-eslint/parser@8.26.1(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2))(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2)
 
6540
  unist-util-is: 6.0.0
6541
  unist-util-visit-parents: 6.0.1
6542
 
6543
+ unpipe@1.0.0: {}
6544
+
6545
+ unplugin-icons@22.1.0(svelte@5.38.7):
6546
  dependencies:
6547
  '@antfu/install-pkg': 1.0.0
6548
  '@iconify/utils': 2.3.0
 
6550
  local-pkg: 1.1.1
6551
  unplugin: 2.2.0
6552
  optionalDependencies:
6553
+ svelte: 5.38.7
6554
  transitivePeerDependencies:
6555
  - supports-color
6556
 
 
6572
 
6573
  uuid@8.3.2: {}
6574
 
6575
+ vary@1.1.2: {}
6576
+
6577
  vfile-message@4.0.2:
6578
  dependencies:
6579
  '@types/unist': 3.0.3
 
6628
  optionalDependencies:
6629
  vite: 5.4.14(@types/node@22.14.1)(lightningcss@1.29.1)
6630
 
6631
+ vitest-browser-svelte@0.1.0(@vitest/browser@3.1.4)(svelte@5.38.7)(vitest@3.1.4):
6632
  dependencies:
6633
  '@vitest/browser': 3.1.4(playwright@1.52.0)(vite@5.4.14(@types/node@22.14.1)(lightningcss@1.29.1))(vitest@3.1.4)
6634
+ svelte: 5.38.7
6635
  vitest: 3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1)
6636
 
6637
  vitest@3.1.4(@types/node@22.14.1)(@vitest/browser@3.1.4)(jsdom@26.1.0)(lightningcss@1.29.1):
 
6725
  string-width: 4.2.3
6726
  strip-ansi: 6.0.1
6727
 
6728
+ wrappy@1.0.2: {}
6729
+
6730
  ws@8.18.2: {}
6731
 
6732
  xml-name-validator@5.0.0: {}
 
6746
 
6747
  zimmerframe@1.1.2: {}
6748
 
6749
+ zod-to-json-schema@3.24.6(zod@3.25.76):
6750
+ dependencies:
6751
+ zod: 3.25.76
6752
+
6753
+ zod@3.25.76: {}
6754
+
6755
  zwitch@2.0.4: {}
src/app.css CHANGED
@@ -2,6 +2,7 @@
2
  @import "tailwindcss";
3
 
4
  @plugin '@tailwindcss/container-queries';
 
5
  @plugin '@tailwindcss/typography';
6
 
7
  @custom-variant dark (&:where(.dark, .dark *));
 
2
  @import "tailwindcss";
3
 
4
  @plugin '@tailwindcss/container-queries';
5
+ @plugin 'tailwindcss-spring';
6
  @plugin '@tailwindcss/typography';
7
 
8
  @custom-variant dark (&:where(.dark, .dark *));
src/lib/components/inference-playground/code-snippets.svelte CHANGED
@@ -206,6 +206,7 @@
206
  <a
207
  href={installInstructions.docs}
208
  target="_blank"
 
209
  class="relative -bottom-[1px] flex items-center gap-1 text-sm font-normal text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
210
  >
211
  <IconExternal class="text-xs" />
 
206
  <a
207
  href={installInstructions.docs}
208
  target="_blank"
209
+ rel="external"
210
  class="relative -bottom-[1px] flex items-center gap-1 text-sm font-normal text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300"
211
  >
212
  <IconExternal class="text-xs" />
src/lib/components/inference-playground/generation-config.svelte CHANGED
@@ -7,8 +7,10 @@
7
  import IconX from "~icons/carbon/close";
8
  import ExtraParamsModal, { openExtraParamsModal } from "./extra-params-modal.svelte";
9
  import { GENERATION_CONFIG_KEYS, GENERATION_CONFIG_SETTINGS } from "./generation-config-settings.js";
 
10
  import StructuredOutputModal, { openStructuredOutputModal } from "./structured-output-modal.svelte";
11
-
 
12
  interface Props {
13
  conversation: ConversationClass;
14
  classNames?: string;
@@ -43,6 +45,7 @@
43
  });
44
  }
45
 
 
46
  const extraParamsLen = $derived(Object.keys(conversation.data.extraParams ?? {}).length);
47
  </script>
48
 
@@ -124,6 +127,21 @@
124
  </label>
125
  {/if}
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  <div class="mt-2 flex items-center gap-2">
128
  <span class="text-sm font-medium text-gray-900 dark:text-gray-300">Extra parameters</span>
129
  <span
@@ -152,3 +170,6 @@
152
 
153
  <StructuredOutputModal {conversation} />
154
  <ExtraParamsModal {conversation} />
 
 
 
 
7
  import IconX from "~icons/carbon/close";
8
  import ExtraParamsModal, { openExtraParamsModal } from "./extra-params-modal.svelte";
9
  import { GENERATION_CONFIG_KEYS, GENERATION_CONFIG_SETTINGS } from "./generation-config-settings.js";
10
+ import MCPModal from "./mcp-modal.svelte";
11
  import StructuredOutputModal, { openStructuredOutputModal } from "./structured-output-modal.svelte";
12
+ import { mcpServers } from "$lib/state/mcps.svelte.js";
13
+ import { isMcpEnabled } from "$lib/constants.js";
14
  interface Props {
15
  conversation: ConversationClass;
16
  classNames?: string;
 
45
  });
46
  }
47
 
48
+ let editingMCP = $state(false);
49
  const extraParamsLen = $derived(Object.keys(conversation.data.extraParams ?? {}).length);
50
  </script>
51
 
 
127
  </label>
128
  {/if}
129
 
130
+ <!-- MCP Servers -->
131
+ {#if isMcpEnabled()}
132
+ <div class="mt-2 flex cursor-pointer items-center justify-between">
133
+ <span class="text-sm font-medium text-gray-900 dark:text-gray-300">MCP Servers</span>
134
+ <div class="flex items-center gap-2">
135
+ {#if mcpServers.enabled.length > 0}
136
+ <span class="rounded-full bg-blue-100 px-2 py-1 text-xs text-blue-800 dark:bg-blue-900 dark:text-blue-200">
137
+ {mcpServers.enabled.length} enabled
138
+ </span>
139
+ {/if}
140
+ <button class="btn-mini" type="button" onclick={() => (editingMCP = true)}> configure </button>
141
+ </div>
142
+ </div>
143
+ {/if}
144
+
145
  <div class="mt-2 flex items-center gap-2">
146
  <span class="text-sm font-medium text-gray-900 dark:text-gray-300">Extra parameters</span>
147
  <span
 
170
 
171
  <StructuredOutputModal {conversation} />
172
  <ExtraParamsModal {conversation} />
173
+ {#if isMcpEnabled()}
174
+ <MCPModal bind:open={editingMCP} />
175
+ {/if}
src/lib/components/inference-playground/mcp-card.svelte ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { mcpServers, type MCPServerEntity, type MCPFormData } from "$lib/state/mcps.svelte.js";
3
+ import { projects } from "$lib/state/projects.svelte.js";
4
+ import { extractDomain } from "$lib/utils/url.js";
5
+ import IconEdit from "~icons/carbon/edit";
6
+ import IconDelete from "~icons/carbon/trash-can";
7
+ import Switch from "../switch.svelte";
8
+ import McpForm from "./mcp-form.svelte";
9
+
10
+ interface Props {
11
+ server: MCPServerEntity;
12
+ }
13
+
14
+ let { server }: Props = $props();
15
+
16
+ let editing = $state(false);
17
+
18
+ async function deleteServer() {
19
+ await mcpServers.delete(server.id);
20
+
21
+ // Remove from project's enabled MCPs if it was enabled
22
+ const currentProject = projects.current;
23
+ if (!currentProject?.enabledMCPs?.includes(server.id)) return;
24
+ await projects.update({
25
+ ...currentProject,
26
+ enabledMCPs: currentProject.enabledMCPs.filter(mcpId => mcpId !== server.id),
27
+ });
28
+ }
29
+
30
+ async function setEnabled(enabled: boolean) {
31
+ const currentProject = projects.current;
32
+ if (!currentProject) return;
33
+
34
+ const enabledMCPs = currentProject.enabledMCPs || [];
35
+ const newEnabledMCPs = enabled ? [...enabledMCPs, server.id] : enabledMCPs.filter(id => id !== server.id);
36
+
37
+ await projects.update({
38
+ ...currentProject,
39
+ enabledMCPs: newEnabledMCPs,
40
+ });
41
+ }
42
+
43
+ const isEnabled = $derived(projects.current?.enabledMCPs?.includes(server.id) || false);
44
+
45
+ async function saveServer(formData: MCPFormData) {
46
+ await mcpServers.update({
47
+ ...server,
48
+ ...formData,
49
+ });
50
+ editing = false;
51
+ }
52
+
53
+ function getFaviconUrl(url: string): string {
54
+ const domain = extractDomain(url);
55
+ return `https://www.google.com/s2/favicons?domain=https://${domain}&sz=64`;
56
+ }
57
+
58
+ function urlWithoutSubpaths(url: string): string {
59
+ const urlObj = new URL(url);
60
+ return urlObj.origin;
61
+ }
62
+ </script>
63
+
64
+ <div class="rounded-lg border border-gray-200 p-3 dark:border-gray-700">
65
+ <div class="flex justify-between">
66
+ <div>
67
+ <div class="flex items-center gap-1">
68
+ <img src={getFaviconUrl(server.url)} alt="Server Icon" class="size-4 rounded p-0.5 dark:bg-gray-500" />
69
+ <span class="font-bold">{server.name}</span>
70
+ </div>
71
+ <p class="mt-1 truncate text-sm dark:text-neutral-300">
72
+ <span class="rounded bg-blue-900 px-0.75 py-0.25 uppercase">
73
+ {server.protocol}
74
+ </span>
75
+ <span>
76
+ {urlWithoutSubpaths(server.url)}
77
+ </span>
78
+ </p>
79
+ {#if server.headers && Object.keys(server.headers).length > 0}
80
+ <p class="mt-1 text-xs dark:text-neutral-400">
81
+ Headers: {Object.keys(server.headers).length} configured
82
+ </p>
83
+ {/if}
84
+ </div>
85
+ <div class="flex flex-col items-end justify-between gap-2">
86
+ <Switch bind:value={() => isEnabled, v => setEnabled(v)} />
87
+ <div class="flex items-center gap-2">
88
+ {#if !editing}
89
+ <button class="btn-mini" onclick={() => (editing = true)}>
90
+ <IconEdit class="h-4 w-4" />
91
+ <span>Edit</span>
92
+ </button>
93
+ <button
94
+ class="btn-mini text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
95
+ onclick={() => deleteServer()}
96
+ >
97
+ <IconDelete class="h-4 w-4" />
98
+ <span>Delete</span>
99
+ </button>
100
+ {/if}
101
+ </div>
102
+ </div>
103
+ </div>
104
+
105
+ {#if editing}
106
+ <div class="mt-2 border-t border-neutral-500 pt-2 dark:border-neutral-700">
107
+ <McpForm {server} onSubmit={saveServer} onCancel={() => (editing = false)} />
108
+ </div>
109
+ {/if}
110
+ </div>
src/lib/components/inference-playground/mcp-form.svelte ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { type MCPProtocol, type MCPServerEntity, type MCPFormData } from "$lib/state/mcps.svelte.js";
3
+ import { createFieldValidation } from "$lib/utils/form.svelte";
4
+ import { entries } from "$lib/utils/object.svelte";
5
+ import { isValidURL } from "$lib/utils/url.js";
6
+ import IconAdd from "~icons/carbon/add";
7
+ import IconCheck from "~icons/carbon/checkmark";
8
+ import IconDelete from "~icons/carbon/trash-can";
9
+
10
+ interface Props {
11
+ server?: MCPServerEntity;
12
+ onSubmit: (formData: MCPFormData) => Promise<void>;
13
+ onCancel: () => void;
14
+ submitLabel?: string;
15
+ }
16
+
17
+ let { server, onSubmit, onCancel, submitLabel = "Save" }: Props = $props();
18
+
19
+ let formState = $state({
20
+ name: server?.name || "",
21
+ url: server?.url || "",
22
+ protocol: (server?.protocol || "sse") as MCPProtocol,
23
+ headers: entries(server?.headers || {}),
24
+ });
25
+
26
+ const protocolOptions: MCPProtocol[] = ["sse", "http"];
27
+
28
+ const nameField = createFieldValidation({
29
+ validate: v => {
30
+ if (!v) return "Server name is required";
31
+ if (v.trim().length === 0) return "Server name cannot be empty";
32
+ },
33
+ });
34
+
35
+ const urlField = createFieldValidation({
36
+ validate: v => {
37
+ if (!v) return "Server URL is required";
38
+ if (v.trim().length === 0) return "Server URL cannot be empty";
39
+ if (!isValidURL(v)) return "Invalid URL";
40
+ },
41
+ });
42
+
43
+ const disabled = $derived(!nameField.valid || !urlField.valid);
44
+
45
+ async function handleSubmit(e: SubmitEvent) {
46
+ e.preventDefault();
47
+ if (!nameField.valid || !urlField.valid) return;
48
+
49
+ await onSubmit({
50
+ ...formState,
51
+ headers: formState.headers.reduce((acc, [key, value]) => ({ ...acc, [key]: value }), {}),
52
+ });
53
+ }
54
+ </script>
55
+
56
+ <form class="space-y-3" onsubmit={handleSubmit}>
57
+ <label class="flex flex-col gap-2">
58
+ <p class="block text-sm font-medium text-gray-900 dark:text-white">
59
+ Server Name <span class="text-red-800 dark:text-red-300">*</span>
60
+ </p>
61
+ <input
62
+ type="text"
63
+ bind:value={formState.name}
64
+ class="input block w-full"
65
+ placeholder="My MCP Server"
66
+ {...nameField.attrs}
67
+ required
68
+ />
69
+ <p class="text-xs text-red-300">{nameField.msg}</p>
70
+ </label>
71
+
72
+ <label class="flex flex-col gap-2">
73
+ <p class="block text-sm font-medium text-gray-900 dark:text-white">
74
+ Server URL <span class="text-red-800 dark:text-red-300">*</span>
75
+ </p>
76
+ <input
77
+ type="url"
78
+ bind:value={formState.url}
79
+ class="input block w-full"
80
+ placeholder="https://mcp.example.com/sse"
81
+ {...urlField.attrs}
82
+ required
83
+ />
84
+ <p class="text-xs text-red-300">{urlField.msg}</p>
85
+ </label>
86
+
87
+ <div class="flex flex-col gap-2">
88
+ <p class="block text-sm font-medium text-gray-900 dark:text-white">Protocol</p>
89
+ <div class="flex rounded-lg bg-gray-100 p-1 dark:bg-gray-700" role="radiogroup" aria-label="Server Protocol">
90
+ {#each protocolOptions as protocol}
91
+ <label class="relative flex-1 cursor-pointer">
92
+ <input
93
+ type="radio"
94
+ name="protocol-option"
95
+ value={protocol}
96
+ bind:group={formState.protocol}
97
+ class="peer sr-only"
98
+ />
99
+ <div
100
+ class="flex items-center justify-center rounded-md px-3 py-2 text-sm font-medium text-gray-600 transition-colors duration-200 ease-in-out peer-checked:bg-white peer-checked:text-gray-900 peer-checked:shadow dark:text-gray-300 dark:peer-checked:bg-gray-800 dark:peer-checked:text-white"
101
+ >
102
+ {protocol.toUpperCase()}
103
+ </div>
104
+ <span
105
+ aria-hidden="true"
106
+ class="absolute inset-0 z-0 rounded-md transition-all duration-200 ease-in-out peer-focus:ring-2 peer-focus:ring-blue-500 peer-focus:ring-offset-2 peer-focus:ring-offset-gray-100 dark:peer-focus:ring-offset-gray-700"
107
+ ></span>
108
+ </label>
109
+ {/each}
110
+ </div>
111
+ </div>
112
+
113
+ <div class="flex flex-col gap-2">
114
+ <p class="block text-sm font-medium text-gray-900 dark:text-white">Headers</p>
115
+ {#each formState.headers || [] as _, i (i)}
116
+ <div class="flex items-center gap-2">
117
+ <input
118
+ type="text"
119
+ bind:value={formState.headers[i]![0]}
120
+ class="flex-1 rounded-md border border-gray-300 bg-gray-50 px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100"
121
+ placeholder="Header name"
122
+ />
123
+ <span class="text-gray-500">:</span>
124
+ <input
125
+ type="text"
126
+ bind:value={formState.headers[i]![1]}
127
+ class="flex-1 rounded-md border border-gray-300 bg-gray-50 px-3 py-2 text-sm dark:border-gray-600 dark:bg-gray-700 dark:text-gray-100"
128
+ placeholder="Header value"
129
+ />
130
+ <button
131
+ class="btn-sm !h-auto self-stretch text-red-600 hover:bg-red-50 dark:text-red-400 dark:hover:bg-red-900/20"
132
+ onclick={() => {
133
+ formState.headers.splice(i, 1);
134
+ }}
135
+ type="button"
136
+ >
137
+ <IconDelete class="h-4 w-4" />
138
+ </button>
139
+ </div>
140
+ {/each}
141
+ <button
142
+ class="btn-sm self-start"
143
+ type="button"
144
+ onclick={() => {
145
+ formState.headers.push(["", ""]);
146
+ formState = formState;
147
+ }}
148
+ >
149
+ <IconAdd class="size-4" />
150
+ Add Header
151
+ </button>
152
+ </div>
153
+
154
+ <div class="flex items-center gap-2">
155
+ <button class="btn-sm" {disabled}>
156
+ <IconCheck /><span>{submitLabel}</span>
157
+ </button>
158
+ <button class="btn-sm" type="button" onclick={onCancel}> Cancel </button>
159
+ </div>
160
+ </form>
src/lib/components/inference-playground/mcp-modal.svelte ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { mcpServers, type MCPFormData } from "$lib/state/mcps.svelte.js";
3
+ import IconPlus from "~icons/carbon/add";
4
+ import Dialog from "../dialog.svelte";
5
+ import McpCard from "./mcp-card.svelte";
6
+ import McpForm from "./mcp-form.svelte";
7
+
8
+ interface Props {
9
+ open: boolean;
10
+ }
11
+
12
+ let { open = $bindable(false) }: Props = $props();
13
+ let showAddForm = $state(false);
14
+
15
+ async function addServer(formData: MCPFormData) {
16
+ await mcpServers.create(formData);
17
+ showAddForm = false;
18
+ }
19
+ </script>
20
+
21
+ <Dialog
22
+ class="!w-2xl max-w-[90vw]"
23
+ title="MCP Servers"
24
+ {open}
25
+ onClose={() => {
26
+ open = false;
27
+ }}
28
+ >
29
+ <!-- Server List -->
30
+ <div class="space-y-4">
31
+ {#if mcpServers.all.length === 0}
32
+ <p class="text-sm text-gray-500">No MCP servers configured yet.</p>
33
+ {:else}
34
+ <div class="space-y-2">
35
+ {#each mcpServers.all as server (server.id)}
36
+ <McpCard {server} />
37
+ {/each}
38
+ </div>
39
+ {/if}
40
+ </div>
41
+
42
+ {#if showAddForm}
43
+ <div class="mt-4 border-t border-gray-200 pt-4 dark:border-gray-700">
44
+ <h3 class="mb-3 text-lg font-medium">Add New Server</h3>
45
+ <McpForm onSubmit={addServer} onCancel={() => (showAddForm = false)} submitLabel="Add Server" />
46
+ </div>
47
+ {:else}
48
+ <button class="btn-sm mt-2 flex w-full items-center gap-2" onclick={() => (showAddForm = true)}>
49
+ <IconPlus class="h-4 w-4" />
50
+ Add Server
51
+ </button>
52
+ {/if}
53
+ </Dialog>
src/lib/components/inference-playground/structured-output-modal.svelte CHANGED
@@ -31,6 +31,7 @@
31
  const modes = ["form", "code"] as const;
32
  const radioGroup = new RadioGroup({
33
  value: modes[0],
 
34
  });
35
 
36
  type Schema = {
 
31
  const modes = ["form", "code"] as const;
32
  const radioGroup = new RadioGroup({
33
  value: modes[0],
34
+ orientation: "horizontal",
35
  });
36
 
37
  type Schema = {
src/lib/components/switch.svelte ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <script lang="ts">
2
+ import { classes } from "$lib/utils/styles.js";
3
+ import { type ComponentProps } from "melt";
4
+ import { Toggle, type ToggleProps } from "melt/builders";
5
+ import { ElementSize } from "runed";
6
+
7
+ let {
8
+ class: className,
9
+ value = $bindable(false),
10
+ ...rest
11
+ }: ComponentProps<ToggleProps> & { class?: string } = $props();
12
+
13
+ const toggle = new Toggle({
14
+ value: () => value ?? false,
15
+ onValueChange: v => (value = v),
16
+ ...rest,
17
+ });
18
+
19
+ let trigger = $state<HTMLButtonElement>();
20
+ const triggerSize = new ElementSize(() => trigger);
21
+ let thumb = $state<HTMLSpanElement>();
22
+ const thumbSize = new ElementSize(() => thumb);
23
+ const padding = 2;
24
+
25
+ const thumbX = $derived.by(() => {
26
+ if (toggle.value) {
27
+ return triggerSize.width - thumbSize.width - padding;
28
+ }
29
+ return padding;
30
+ });
31
+
32
+ let mounted = $state(false);
33
+ $effect(() => {
34
+ setTimeout(() => {
35
+ mounted = true;
36
+ });
37
+ });
38
+ </script>
39
+
40
+ <button
41
+ bind:this={trigger}
42
+ {...toggle.trigger}
43
+ class={classes(
44
+ "relative h-5 w-10 shrink-0 rounded-full bg-neutral-500 transition-all",
45
+ { "bg-blue-500": toggle.value },
46
+ className,
47
+ )}
48
+ >
49
+ <span
50
+ bind:this={thumb}
51
+ class={classes("spring-bounce-20 spring-duration-200 absolute top-0.5 left-0 h-4 w-4 rounded-full bg-neutral-900", {
52
+ "bg-white": toggle.value,
53
+ "!duration-0": !mounted,
54
+ })}
55
+ style="transform: translateX({thumbX}px)"
56
+ ></span>
57
+ </button>
src/lib/constants.ts CHANGED
@@ -1,3 +1,5 @@
 
 
1
  export enum TEST_IDS {
2
  checkpoints_trigger,
3
  checkpoints_menu,
@@ -7,3 +9,15 @@ export enum TEST_IDS {
7
 
8
  message,
9
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { env } from "$env/dynamic/public";
2
+
3
  export enum TEST_IDS {
4
  checkpoints_trigger,
5
  checkpoints_menu,
 
9
 
10
  message,
11
  }
12
+
13
+ export function isMcpEnabled(): boolean {
14
+ const envEnabled = env.PUBLIC_ENABLE_MCP === "true";
15
+ if (envEnabled) return true;
16
+
17
+ if (typeof window === "undefined") return false;
18
+
19
+ const urlParams = new URLSearchParams(window.location.search);
20
+ const hasQueryParam = urlParams.has("mcp") || urlParams.has("enable-mcp");
21
+
22
+ return hasQueryParam;
23
+ }
src/lib/data/context_length.json ADDED
@@ -0,0 +1,269 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "replicate": {},
3
+ "sambanova": {
4
+ "DeepSeek-R1-0528": 32768,
5
+ "DeepSeek-R1-Distill-Llama-70B": 131072,
6
+ "DeepSeek-V3-0324": 32768,
7
+ "E5-Mistral-7B-Instruct": 4096,
8
+ "Llama-4-Maverick-17B-128E-Instruct": 131072,
9
+ "Meta-Llama-3.1-8B-Instruct": 16384,
10
+ "Meta-Llama-3.3-70B-Instruct": 131072,
11
+ "Qwen3-32B": 32768,
12
+ "Whisper-Large-v3": 4096
13
+ },
14
+ "nebius": {
15
+ "meta-llama/Meta-Llama-3.1-8B-Instruct-fast": 131072,
16
+ "meta-llama/Meta-Llama-3.1-8B-Instruct": 131072,
17
+ "meta-llama/Meta-Llama-3.1-70B-Instruct": 131072,
18
+ "meta-llama/Meta-Llama-3.1-405B-Instruct": 131072,
19
+ "meta-llama/Llama-Guard-3-8B": 131072,
20
+ "nvidia/Llama-3_1-Nemotron-Ultra-253B-v1": 131072,
21
+ "mistralai/Mistral-Nemo-Instruct-2407": 128000,
22
+ "google/gemma-2-2b-it": 8192,
23
+ "google/gemma-2-9b-it-fast": 8192,
24
+ "Qwen/Qwen2.5-Coder-7B-fast": 32768,
25
+ "Qwen/Qwen2.5-Coder-7B": 32768,
26
+ "Qwen/Qwen2.5-Coder-32B-Instruct-fast": 131072,
27
+ "Qwen/Qwen2.5-Coder-32B-Instruct": 131072,
28
+ "Qwen/Qwen2.5-32B-Instruct-fast": 131072,
29
+ "Qwen/Qwen2.5-32B-Instruct": 131072,
30
+ "Qwen/Qwen2.5-72B-Instruct-fast": 131072,
31
+ "Qwen/Qwen2.5-72B-Instruct": 131072,
32
+ "Qwen/Qwen2-VL-72B-Instruct": 32768,
33
+ "aaditya/Llama3-OpenBioLLM-70B": 8192,
34
+ "BAAI/bge-en-icl": 32768,
35
+ "BAAI/bge-multilingual-gemma2": 8192,
36
+ "intfloat/e5-mistral-7b-instruct": 32768,
37
+ "meta-llama/Llama-3.3-70B-Instruct": 131072,
38
+ "meta-llama/Llama-3.3-70B-Instruct-fast": 131072,
39
+ "microsoft/phi-4": 16384,
40
+ "deepseek-ai/DeepSeek-V3": 163840,
41
+ "deepseek-ai/DeepSeek-R1": 163840,
42
+ "deepseek-ai/DeepSeek-R1-0528": 131072,
43
+ "NousResearch/Hermes-3-Llama-405B": 131072,
44
+ "deepseek-ai/DeepSeek-R1-Distill-Llama-70B": 131072,
45
+ "deepseek-ai/DeepSeek-R1-fast": 163840,
46
+ "Qwen/QwQ-32B-fast": 131072,
47
+ "Qwen/QwQ-32B": 131072,
48
+ "Qwen/Qwen3-235B-A22B": 40960,
49
+ "Qwen/Qwen3-30B-A3B": 40960,
50
+ "Qwen/Qwen3-30B-A3B-fast": 40960,
51
+ "Qwen/Qwen3-32B": 40960,
52
+ "Qwen/Qwen3-32B-fast": 40960,
53
+ "Qwen/Qwen3-14B": 40960,
54
+ "Qwen/Qwen3-4B-fast": 40960,
55
+ "nvidia/Llama-3_3-Nemotron-Super-49B-v1": 131072,
56
+ "mistralai/Mistral-Small-3.1-24B-Instruct-2503": 131072,
57
+ "mistralai/Devstral-Small-2505": 128000,
58
+ "google/gemma-3-27b-it": 110000,
59
+ "google/gemma-3-27b-it-fast": 110000,
60
+ "Qwen/Qwen2.5-VL-72B-Instruct": 32000,
61
+ "Qwen/Qwen3-Embedding-8B": 40960,
62
+ "deepseek-ai/DeepSeek-V3-0324": 163840,
63
+ "deepseek-ai/DeepSeek-V3-0324-fast": 163840,
64
+ "black-forest-labs/flux-dev": 0,
65
+ "black-forest-labs/flux-schnell": 0,
66
+ "stability-ai/sdxl": 0
67
+ },
68
+ "novita": {
69
+ "deepseek/deepseek-r1-0528": 163840,
70
+ "deepseek/deepseek-v3-0324": 163840,
71
+ "baidu/ernie-4.5-vl-424b-a47b": 123000,
72
+ "baidu/ernie-4.5-300b-a47b-paddle": 123000,
73
+ "qwen/qwen3-30b-a3b-fp8": 40960,
74
+ "minimaxai/minimax-m1-80k": 128000,
75
+ "deepseek/deepseek-r1-0528-qwen3-8b": 128000,
76
+ "qwen/qwen3-32b-fp8": 40960,
77
+ "qwen/qwen2.5-vl-72b-instruct": 32768,
78
+ "qwen/qwen3-235b-a22b-fp8": 40960,
79
+ "deepseek/deepseek-v3-turbo": 64000,
80
+ "meta-llama/llama-4-maverick-17b-128e-instruct-fp8": 1048576,
81
+ "google/gemma-3-27b-it": 32000,
82
+ "deepseek/deepseek-r1-turbo": 64000,
83
+ "Sao10K/L3-8B-Stheno-v3.2": 8192,
84
+ "gryphe/mythomax-l2-13b": 4096,
85
+ "deepseek/deepseek-prover-v2-671b": 160000,
86
+ "meta-llama/llama-4-scout-17b-16e-instruct": 131072,
87
+ "deepseek/deepseek-r1-distill-llama-8b": 32000,
88
+ "meta-llama/llama-3.1-8b-instruct": 16384,
89
+ "deepseek/deepseek-r1-distill-qwen-14b": 64000,
90
+ "meta-llama/llama-3.3-70b-instruct": 131072,
91
+ "qwen/qwen-2.5-72b-instruct": 32000,
92
+ "mistralai/mistral-nemo": 60288,
93
+ "deepseek/deepseek-r1-distill-qwen-32b": 64000,
94
+ "meta-llama/llama-3-8b-instruct": 8192,
95
+ "microsoft/wizardlm-2-8x22b": 65535,
96
+ "deepseek/deepseek-r1-distill-llama-70b": 32000,
97
+ "mistralai/mistral-7b-instruct": 32768,
98
+ "meta-llama/llama-3-70b-instruct": 8192,
99
+ "nousresearch/hermes-2-pro-llama-3-8b": 8192,
100
+ "sao10k/l3-70b-euryale-v2.1": 8192,
101
+ "cognitivecomputations/dolphin-mixtral-8x22b": 16000,
102
+ "sophosympatheia/midnight-rose-70b": 4096,
103
+ "sao10k/l3-8b-lunaris": 8192,
104
+ "baidu/ernie-4.5-vl-28b-a3b": 30000,
105
+ "baidu/ernie-4.5-21B-a3b": 120000,
106
+ "baidu/ernie-4.5-0.3b": 120000,
107
+ "google/gemma-3-1b-it": 32768,
108
+ "qwen/qwen3-8b-fp8": 128000,
109
+ "qwen/qwen3-4b-fp8": 128000,
110
+ "thudm/glm-4-32b-0414": 32000,
111
+ "qwen/qwen2.5-7b-instruct": 32000,
112
+ "meta-llama/llama-3.2-1b-instruct": 131000,
113
+ "meta-llama/llama-3.2-3b-instruct": 32768,
114
+ "meta-llama/llama-3.1-8b-instruct-bf16": 8192,
115
+ "sao10k/l31-70b-euryale-v2.2": 8192
116
+ },
117
+ "fal": {
118
+ "fal/model-name": 4096
119
+ },
120
+ "cerebras": {
121
+ "cerebras/model-name": 8192
122
+ },
123
+ "hf-inference": {
124
+ "google/gemma-2-9b-it": 8192,
125
+ "meta-llama/Meta-Llama-3-8B-Instruct": 8192
126
+ },
127
+ "hyperbolic": {
128
+ "Qwen/Qwen2.5-72B-Instruct": 131072,
129
+ "Qwen/Qwen2.5-VL-72B-Instruct": 32768,
130
+ "meta-llama/Meta-Llama-3-70B-Instruct": 8192,
131
+ "deepseek-ai/DeepSeek-V3": 131072,
132
+ "deepseek-ai/DeepSeek-V3-0324": 163840,
133
+ "meta-llama/Llama-3.3-70B-Instruct": 131072,
134
+ "Qwen/Qwen2.5-Coder-32B-Instruct": 32768,
135
+ "meta-llama/Llama-3.2-3B-Instruct": 131072,
136
+ "NousResearch/Hermes-3-Llama-3.1-70B": 12288,
137
+ "meta-llama/Meta-Llama-3.1-405B-Instruct": 131000,
138
+ "meta-llama/Meta-Llama-3.1-70B-Instruct": 131072,
139
+ "meta-llama/Meta-Llama-3.1-8B-Instruct": 131072,
140
+ "mistralai/Pixtral-12B-2409": 32768,
141
+ "Qwen/Qwen2.5-VL-7B-Instruct": 32768,
142
+ "meta-llama/Meta-Llama-3.1-405B-FP8": 32768,
143
+ "deepseek-ai/DeepSeek-R1": 163840,
144
+ "Qwen/QwQ-32B": 131072
145
+ },
146
+ "cohere": {
147
+ "embed-english-light-v3.0": 512,
148
+ "embed-multilingual-v2.0": 256,
149
+ "rerank-v3.5": 4096,
150
+ "embed-v4.0": 8192,
151
+ "rerank-english-v3.0": 4096,
152
+ "command-r-08-2024": 132096,
153
+ "embed-english-light-v3.0-image": 0,
154
+ "embed-english-v3.0-image": 0,
155
+ "command-nightly": 288000,
156
+ "command-a-03-2025": 288000,
157
+ "command-r-plus-08-2024": 132096,
158
+ "c4ai-aya-vision-32b": 16384,
159
+ "command-r": 132096,
160
+ "command-r7b-12-2024": 132000,
161
+ "command-r7b-arabic-02-2025": 128000,
162
+ "command-light-nightly": 4096,
163
+ "embed-english-v3.0": 512,
164
+ "embed-multilingual-light-v3.0-image": 0,
165
+ "embed-multilingual-v3.0-image": 0,
166
+ "c4ai-aya-expanse-32b": 128000,
167
+ "command": 4096
168
+ },
169
+ "together": {
170
+ "togethercomputer/m2-bert-80M-32k-retrieval": 32768,
171
+ "cartesia/sonic": 0,
172
+ "meta-llama/Meta-Llama-3-8B-Instruct-Lite": 8192,
173
+ "intfloat/multilingual-e5-large-instruct": 514,
174
+ "Alibaba-NLP/gte-modernbert-base": 8192,
175
+ "meta-llama/Llama-4-Scout-17B-16E-Instruct": 1048576,
176
+ "meta-llama/LlamaGuard-2-8b": 8192,
177
+ "Qwen/Qwen2.5-Coder-32B-Instruct": 16384,
178
+ "cartesia/sonic-2": 0,
179
+ "Qwen/Qwen3-235B-A22B-fp8-tput": 40960,
180
+ "togethercomputer/MoA-1": 32768,
181
+ "meta-llama/Meta-Llama-3-70B-Instruct-Turbo": 8192,
182
+ "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo": 131072,
183
+ "meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo": 131072,
184
+ "meta-llama/Meta-Llama-Guard-3-8B": 8192,
185
+ "arcee_ai/arcee-spotlight": 131072,
186
+ "google/gemma-3-27b-it": 65536,
187
+ "arcee-ai/AFM-4.5B-Preview": 65536,
188
+ "deepseek-ai/DeepSeek-V3": 131072,
189
+ "lgai/exaone-3-5-32b-instruct": 32768,
190
+ "deepseek-ai/DeepSeek-R1-0528-tput": 163840,
191
+ "mistralai/Mixtral-8x7B-Instruct-v0.1": 32768,
192
+ "meta-llama/Llama-Vision-Free": 131072,
193
+ "meta-llama/Llama-3-8b-chat-hf": 8192,
194
+ "mistralai/Mistral-7B-Instruct-v0.1": 32768,
195
+ "Qwen/QwQ-32B": 131072,
196
+ "meta-llama/Llama-2-70b-hf": 4096,
197
+ "togethercomputer/MoA-1-Turbo": 32768,
198
+ "black-forest-labs/FLUX.1-kontext-max": 0,
199
+ "perplexity-ai/r1-1776": 163840,
200
+ "mistralai/Mistral-7B-Instruct-v0.2": 32768,
201
+ "deepseek-ai/DeepSeek-V3-p-dp": 131072,
202
+ "Qwen/Qwen2-72B-Instruct": 32768,
203
+ "mistralai/Mistral-7B-Instruct-v0.3": 32768,
204
+ "NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO": 32768,
205
+ "meta-llama/Llama-Guard-3-11B-Vision-Turbo": 131072,
206
+ "Qwen/Qwen2-VL-72B-Instruct": 32768,
207
+ "scb10x/scb10x-llama3-1-typhoon2-70b-instruct": 8192,
208
+ "arcee-ai/maestro-reasoning": 131072,
209
+ "meta-llama/Llama-3.2-3B-Instruct-Turbo": 131072,
210
+ "arcee-ai/virtuoso-medium-v2": 131072,
211
+ "arcee-ai/coder-large": 32768,
212
+ "meta-llama/Llama-Guard-4-12B": 1048576,
213
+ "deepseek-ai/DeepSeek-R1-Distill-Qwen-14B": 131072,
214
+ "arcee-ai/virtuoso-large": 131072,
215
+ "deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B": 131072,
216
+ "deepseek-ai/DeepSeek-R1-Distill-Llama-70B": 131072,
217
+ "nvidia/Llama-3.1-Nemotron-70B-Instruct-HF": 32768,
218
+ "deepseek-ai/DeepSeek-R1-Distill-Llama-70B-free": 8192,
219
+ "meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8": 1048576,
220
+ "togethercomputer/Refuel-Llm-V2-Small": 8192,
221
+ "togethercomputer/Refuel-Llm-V2": 16384,
222
+ "Qwen/Qwen2.5-VL-72B-Instruct": 32768,
223
+ "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo": 130815,
224
+ "scb10x/scb10x-typhoon-2-1-gemma3-12b": 131072,
225
+ "arcee-ai/caller": 32768,
226
+ "lgai/exaone-deep-32b": 32768,
227
+ "black-forest-labs/FLUX.1-kontext-pro": 0,
228
+ "google/gemma-3n-E4B-it": 32768,
229
+ "deepseek-ai/DeepSeek-R1": 163840,
230
+ "Qwen/Qwen2.5-72B-Instruct-Turbo": 131072,
231
+ "meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo": 131072,
232
+ "arcee-ai/arcee-blitz": 32768,
233
+ "meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo": 131072,
234
+ "meta-llama/Llama-3-70b-chat-hf": 8192,
235
+ "google/gemma-2-27b-it": 8192,
236
+ "meta-llama/Llama-3.3-70B-Instruct-Turbo-Free": 131072,
237
+ "Qwen/Qwen2.5-7B-Instruct-Turbo": 32768,
238
+ "mistralai/Mistral-Small-24B-Instruct-2501": 32768,
239
+ "Salesforce/Llama-Rank-V1": 8192,
240
+ "meta-llama/Llama-3.3-70B-Instruct-Turbo": 131072,
241
+ "marin-community/marin-8b-instruct": 4096,
242
+ "Qwen/Qwen3-32B-FP8": 0
243
+ },
244
+ "fireworks-ai": {
245
+ "accounts/perplexity/models/r1-1776": 163840,
246
+ "accounts/fireworks/models/deepseek-r1-0528": 163840,
247
+ "accounts/fireworks/models/qwen3-30b-a3b": 40000,
248
+ "accounts/fireworks/models/llama-guard-3-8b": 131072,
249
+ "accounts/fireworks/models/llama4-scout-instruct-basic": 10485760,
250
+ "accounts/fireworks/models/llama4-maverick-instruct-basic": 1048576,
251
+ "accounts/fireworks/models/llama-v3p1-8b-instruct": 131072,
252
+ "accounts/fireworks/models/firesearch-ocr-v6": 8192,
253
+ "accounts/fireworks/models/llama-v3p1-405b-instruct": 131072,
254
+ "accounts/fireworks/models/qwen2-vl-72b-instruct": 32768,
255
+ "accounts/fireworks/models/mixtral-8x22b-instruct": 65536,
256
+ "accounts/fireworks/models/qwen2p5-72b-instruct": 32768,
257
+ "accounts/fireworks/models/deepseek-r1-basic": 163840,
258
+ "accounts/fireworks/models/llama-v3p1-70b-instruct": 131072,
259
+ "accounts/fireworks/models/qwen3-235b-a22b": 128000,
260
+ "accounts/fireworks/models/llama-v3p3-70b-instruct": 131072,
261
+ "accounts/fireworks/models/deepseek-r1": 163840,
262
+ "accounts/sentientfoundation/models/dobby-unhinged-llama-3-3-70b-new": 131072,
263
+ "accounts/sentientfoundation-serverless/models/dobby-mini-unhinged-plus-llama-3-1-8b": 131072,
264
+ "accounts/fireworks/models/deepseek-v3": 131072,
265
+ "accounts/fireworks/models/deepseek-v3-0324": 163840,
266
+ "accounts/fireworks/models/qwq-32b": 131072,
267
+ "accounts/fireworks/models/qwen2p5-vl-32b-instruct": 128000
268
+ }
269
+ }
src/lib/state/mcps.svelte.ts ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { idb } from "$lib/remult.js";
2
+ import { dequal } from "dequal";
3
+ import { Entity, Fields, repo, type MembersOnly } from "remult";
4
+ import { projects } from "./projects.svelte";
5
+
6
+ export type MCPProtocol = "sse" | "http";
7
+
8
+ export interface MCPServer {
9
+ id: string;
10
+ name: string;
11
+ url: string;
12
+ protocol: MCPProtocol;
13
+ headers?: Record<string, string>;
14
+ }
15
+
16
+ @Entity("mcp_server")
17
+ export class MCPServerEntity {
18
+ @Fields.cuid()
19
+ id!: string;
20
+
21
+ @Fields.string()
22
+ name!: string;
23
+
24
+ @Fields.string()
25
+ url!: string;
26
+
27
+ @Fields.string()
28
+ protocol: MCPProtocol = "sse";
29
+
30
+ @Fields.json()
31
+ headers?: Record<string, string>;
32
+ }
33
+
34
+ export type MCPServerEntityMembers = MembersOnly<MCPServerEntity>;
35
+
36
+ export type MCPFormData = {
37
+ name: string;
38
+ url: string;
39
+ protocol: MCPProtocol;
40
+ headers: Record<string, string>;
41
+ };
42
+
43
+ const mcpServersRepo = repo(MCPServerEntity, idb);
44
+
45
+ class MCPServers {
46
+ #servers: Record<MCPServerEntity["id"], MCPServerEntity> = $state({});
47
+
48
+ constructor() {
49
+ mcpServersRepo.find().then(res => {
50
+ res.forEach(server => {
51
+ if (dequal(this.#servers[server.id], server)) return;
52
+ this.#servers[server.id] = server;
53
+ });
54
+ });
55
+ }
56
+
57
+ async create(args: Omit<MCPServerEntity, "id">): Promise<string> {
58
+ const server = await mcpServersRepo.save({ ...args });
59
+ this.#servers[server.id] = server;
60
+ return server.id;
61
+ }
62
+
63
+ get all() {
64
+ return Object.values(this.#servers);
65
+ }
66
+
67
+ get enabled() {
68
+ const currentProject = projects.current;
69
+ if (!currentProject) return [];
70
+ return this.all.filter(server => currentProject.enabledMCPs?.includes(server.id));
71
+ }
72
+
73
+ async update(data: MCPServerEntity) {
74
+ if (!data.id) return;
75
+ await mcpServersRepo.upsert({ where: { id: data.id }, set: data });
76
+ this.#servers[data.id] = { ...data };
77
+ }
78
+
79
+ async delete(id: string) {
80
+ if (!id) return;
81
+ await mcpServersRepo.delete(id);
82
+ delete this.#servers[id];
83
+ }
84
+ }
85
+
86
+ export const mcpServers = new MCPServers();
src/lib/state/projects.svelte.ts CHANGED
@@ -16,6 +16,9 @@ export class ProjectEntity {
16
  @Fields.string()
17
  systemMessage?: string;
18
 
 
 
 
19
  @Fields.string()
20
  branchedFromId?: string | null;
21
 
 
16
  @Fields.string()
17
  systemMessage?: string;
18
 
19
+ @Fields.json()
20
+ enabledMCPs?: string[];
21
+
22
  @Fields.string()
23
  branchedFromId?: string | null;
24
 
src/lib/utils/business.svelte.ts CHANGED
@@ -6,11 +6,12 @@
6
  *
7
  **/
8
 
 
9
  import { pricing } from "$lib/state/pricing.svelte.js";
10
- import { InferenceClient, snippets } from "@huggingface/inference";
11
  import { ConversationClass, type ConversationEntityMembers } from "$lib/state/conversations.svelte";
12
  import { token } from "$lib/state/token.svelte";
13
- import { billing } from "$lib/state/billing.svelte";
14
  import {
15
  isCustomModel,
16
  isHFModel,
@@ -25,11 +26,12 @@ import { omit } from "$lib/utils/object.svelte.js";
25
  import type { ChatCompletionInputMessage, InferenceSnippet } from "@huggingface/tasks";
26
  import { type ChatCompletionOutputMessage } from "@huggingface/tasks";
27
  import { AutoTokenizer, PreTrainedTokenizer } from "@huggingface/transformers";
28
- import OpenAI from "openai";
29
  import { images } from "$lib/state/images.svelte.js";
30
  import { projects } from "$lib/state/projects.svelte.js";
 
31
  import { modifySnippet } from "$lib/utils/snippets.js";
32
  import { models } from "$lib/state/models.svelte";
 
33
 
34
  type ChatCompletionInputMessageChunk =
35
  NonNullable<ChatCompletionInputMessage["content"]> extends string | (infer U)[] ? U : never;
@@ -56,20 +58,6 @@ async function parseMessage(message: ConversationMessage): Promise<ChatCompletio
56
  };
57
  }
58
 
59
- type HFCompletionMetadata = {
60
- type: "huggingface";
61
- client: InferenceClient;
62
- args: Parameters<InferenceClient["chatCompletion"]>[0];
63
- };
64
-
65
- type OpenAICompletionMetadata = {
66
- type: "openai";
67
- client: OpenAI;
68
- args: OpenAI.ChatCompletionCreateParams;
69
- };
70
-
71
- type CompletionMetadata = HFCompletionMetadata | OpenAICompletionMetadata;
72
-
73
  export function maxAllowedTokens(conversation: ConversationClass) {
74
  const model = conversation.model;
75
  const { provider } = conversation.data;
@@ -78,11 +66,29 @@ export function maxAllowedTokens(conversation: ConversationClass) {
78
  return customMaxTokens[conversation.model.id] ?? 100000;
79
  }
80
 
81
- // Try to get context length from router data
82
  const ctxLength = pricing.getContextLength(model.id, provider);
 
 
 
 
 
 
 
 
 
 
 
 
 
83
 
84
- if (!ctxLength) return customMaxTokens[conversation.model.id] ?? 100000;
85
- return ctxLength;
 
 
 
 
 
86
  }
87
 
88
  function getResponseFormatObj(conversation: ConversationClass | Conversation) {
@@ -112,10 +118,11 @@ function getResponseFormatObj(conversation: ConversationClass | Conversation) {
112
  }
113
  }
114
 
115
- async function getCompletionMetadata(
116
  conversation: ConversationClass | Conversation,
117
- signal?: AbortSignal,
118
- ): Promise<CompletionMetadata> {
 
119
  const data = conversation instanceof ConversationClass ? conversation.data : conversation;
120
  const model = conversation.model;
121
  const systemMessage = projects.current?.systemMessage;
@@ -126,98 +133,38 @@ async function getCompletionMetadata(
126
  ];
127
  const parsed = await Promise.all(messages.map(parseMessage));
128
 
129
- const extraParams = data.extraParams
130
- ? Object.fromEntries(
131
- Object.entries(data.extraParams).map(([key, value]) => {
132
- try {
133
- return [key, JSON.parse(value as string)];
134
- } catch {
135
- return [key, value];
136
- }
137
- }),
138
- )
139
- : {};
140
-
141
- const baseArgs = {
142
- ...data.config,
143
- ...extraParams,
144
  messages: parsed,
145
- model: model.id,
146
- response_format: getResponseFormatObj(conversation),
147
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
148
- } as any;
149
-
150
- // Handle OpenAI-compatible models
151
- if (isCustomModel(model)) {
152
- const openai = new OpenAI({
153
- apiKey: model.accessToken,
154
- baseURL: model.endpointUrl,
155
- dangerouslyAllowBrowser: true,
156
- fetch: (...args: Parameters<typeof fetch>) => {
157
- return fetch(args[0], { ...args[1], signal });
158
- },
159
- });
160
-
161
- const args = {
162
- ...baseArgs,
163
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
- } as any;
165
-
166
- return {
167
- type: "openai",
168
- client: openai,
169
- args,
170
- };
171
- }
172
- const args = {
173
- ...baseArgs,
174
  provider: data.provider,
175
- // max_tokens: maxAllowedTokens(conversation) - currTokens,
176
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
177
- } as any;
178
-
179
- // Handle HuggingFace models
180
- const clientOptions: ConstructorParameters<typeof InferenceClient>[1] = {};
181
- if (billing.organization) {
182
- clientOptions.billTo = billing.organization;
183
- }
184
-
185
- return {
186
- type: "huggingface",
187
- client: new InferenceClient(token.value, clientOptions),
188
- args,
189
  };
190
- }
191
 
192
- export async function handleStreamingResponse(
193
- conversation: ConversationClass | Conversation,
194
- onChunk: (content: string) => void,
195
- abortController: AbortController,
196
- ): Promise<void> {
197
- const metadata = await getCompletionMetadata(conversation, abortController.signal);
198
-
199
- if (metadata.type === "openai") {
200
- const stream = await metadata.client.chat.completions.create({
201
- ...metadata.args,
202
- stream: true,
203
- } as OpenAI.ChatCompletionCreateParamsStreaming);
204
-
205
- let out = "";
206
- for await (const chunk of stream) {
207
- if (chunk.choices[0]?.delta?.content) {
208
- out += chunk.choices[0].delta.content;
209
- onChunk(out);
210
- }
211
- }
212
- return;
213
- }
214
 
215
- // HuggingFace streaming
216
  let out = "";
217
- for await (const chunk of metadata.client.chatCompletionStream(metadata.args, { signal: abortController.signal })) {
218
- if (chunk.choices && chunk.choices.length > 0 && chunk.choices[0]?.delta?.content) {
219
- out += chunk.choices[0].delta.content;
220
  onChunk(out);
 
 
221
  }
222
  }
223
  }
@@ -225,34 +172,46 @@ export async function handleStreamingResponse(
225
  export async function handleNonStreamingResponse(
226
  conversation: ConversationClass | Conversation,
227
  ): Promise<{ message: ChatCompletionOutputMessage; completion_tokens: number }> {
228
- const metadata = await getCompletionMetadata(conversation);
229
-
230
- if (metadata.type === "openai") {
231
- const response = await metadata.client.chat.completions.create({
232
- ...metadata.args,
233
- stream: false,
234
- } as OpenAI.ChatCompletionCreateParamsNonStreaming);
235
-
236
- if (response.choices && response.choices.length > 0 && response.choices[0]?.message) {
237
- return {
238
- message: {
239
- role: "assistant",
240
- content: response.choices[0].message.content || "",
241
- },
242
- completion_tokens: response.usage?.completion_tokens || 0,
243
- };
244
- }
245
- throw new Error("No response from the model");
246
- }
247
 
248
- // HuggingFace non-streaming
249
- const response = await metadata.client.chatCompletion(metadata.args);
250
- if (response.choices && response.choices.length > 0) {
251
- const { message } = response.choices[0]!;
252
- const { completion_tokens } = response.usage;
253
- return { message, completion_tokens };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
254
  }
255
- throw new Error("No response from the model");
 
256
  }
257
 
258
  export function isSystemPromptSupported(model: Model | CustomModel) {
 
6
  *
7
  **/
8
 
9
+ import ctxLengthData from "$lib/data/context_length.json";
10
  import { pricing } from "$lib/state/pricing.svelte.js";
11
+ import { snippets } from "@huggingface/inference";
12
  import { ConversationClass, type ConversationEntityMembers } from "$lib/state/conversations.svelte";
13
  import { token } from "$lib/state/token.svelte";
14
+ import { isMcpEnabled } from "$lib/constants.js";
15
  import {
16
  isCustomModel,
17
  isHFModel,
 
26
  import type { ChatCompletionInputMessage, InferenceSnippet } from "@huggingface/tasks";
27
  import { type ChatCompletionOutputMessage } from "@huggingface/tasks";
28
  import { AutoTokenizer, PreTrainedTokenizer } from "@huggingface/transformers";
 
29
  import { images } from "$lib/state/images.svelte.js";
30
  import { projects } from "$lib/state/projects.svelte.js";
31
+ import { mcpServers } from "$lib/state/mcps.svelte.js";
32
  import { modifySnippet } from "$lib/utils/snippets.js";
33
  import { models } from "$lib/state/models.svelte";
34
+ import { StreamReader } from "$lib/utils/stream.js";
35
 
36
  type ChatCompletionInputMessageChunk =
37
  NonNullable<ChatCompletionInputMessage["content"]> extends string | (infer U)[] ? U : never;
 
58
  };
59
  }
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  export function maxAllowedTokens(conversation: ConversationClass) {
62
  const model = conversation.model;
63
  const { provider } = conversation.data;
 
66
  return customMaxTokens[conversation.model.id] ?? 100000;
67
  }
68
 
69
+ // Try to get context length from pricing/router data first
70
  const ctxLength = pricing.getContextLength(model.id, provider);
71
+ if (ctxLength) return ctxLength;
72
+
73
+ // Fall back to local context length data if available
74
+ const providerData = ctxLengthData[provider as keyof typeof ctxLengthData] as Record<string, number> | undefined;
75
+ const localCtxLength = providerData?.[model.id];
76
+ if (localCtxLength) return localCtxLength;
77
+
78
+ // Final fallback to custom max tokens
79
+ return customMaxTokens[conversation.model.id] ?? 100000;
80
+ }
81
+
82
+ function getEnabledMCPs() {
83
+ if (!isMcpEnabled()) return [];
84
 
85
+ return mcpServers.enabled.map(server => ({
86
+ id: server.id,
87
+ name: server.name,
88
+ url: server.url,
89
+ protocol: server.protocol,
90
+ headers: server.headers,
91
+ }));
92
  }
93
 
94
  function getResponseFormatObj(conversation: ConversationClass | Conversation) {
 
118
  }
119
  }
120
 
121
+ export async function handleStreamingResponse(
122
  conversation: ConversationClass | Conversation,
123
+ onChunk: (content: string) => void,
124
+ abortController: AbortController,
125
+ ): Promise<void> {
126
  const data = conversation instanceof ConversationClass ? conversation.data : conversation;
127
  const model = conversation.model;
128
  const systemMessage = projects.current?.systemMessage;
 
133
  ];
134
  const parsed = await Promise.all(messages.map(parseMessage));
135
 
136
+ const requestBody = {
137
+ model: {
138
+ id: model.id,
139
+ isCustom: isCustomModel(model),
140
+ accessToken: isCustomModel(model) ? model.accessToken : undefined,
141
+ endpointUrl: isCustomModel(model) ? model.endpointUrl : undefined,
142
+ },
 
 
 
 
 
 
 
 
143
  messages: parsed,
144
+ config: data.config,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  provider: data.provider,
146
+ streaming: true,
147
+ response_format: getResponseFormatObj(conversation),
148
+ accessToken: token.value,
149
+ enabledMCPs: getEnabledMCPs(),
 
 
 
 
 
 
 
 
 
 
150
  };
 
151
 
152
+ const reader = await StreamReader.fromFetch("/api/generate", {
153
+ method: "POST",
154
+ headers: {
155
+ "Content-Type": "application/json",
156
+ },
157
+ body: JSON.stringify(requestBody),
158
+ signal: abortController.signal,
159
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
 
 
161
  let out = "";
162
+ for await (const chunk of reader.read()) {
163
+ if (chunk.type === "chunk" && chunk.content) {
164
+ out += chunk.content;
165
  onChunk(out);
166
+ } else if (chunk.type === "error") {
167
+ throw new Error(chunk.error || "Stream error");
168
  }
169
  }
170
  }
 
172
  export async function handleNonStreamingResponse(
173
  conversation: ConversationClass | Conversation,
174
  ): Promise<{ message: ChatCompletionOutputMessage; completion_tokens: number }> {
175
+ const data = conversation instanceof ConversationClass ? conversation.data : conversation;
176
+ const model = conversation.model;
177
+ const systemMessage = projects.current?.systemMessage;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
 
179
+ const messages: ConversationMessage[] = [
180
+ ...(isSystemPromptSupported(model) && systemMessage?.length ? [{ role: "system", content: systemMessage }] : []),
181
+ ...(data.messages || []),
182
+ ];
183
+ const parsed = await Promise.all(messages.map(parseMessage));
184
+
185
+ const requestBody = {
186
+ model: {
187
+ id: model.id,
188
+ isCustom: isCustomModel(model),
189
+ accessToken: isCustomModel(model) ? model.accessToken : undefined,
190
+ endpointUrl: isCustomModel(model) ? model.endpointUrl : undefined,
191
+ },
192
+ messages: parsed,
193
+ config: data.config,
194
+ provider: data.provider,
195
+ streaming: false,
196
+ response_format: getResponseFormatObj(conversation),
197
+ accessToken: token.value,
198
+ enabledMCPs: getEnabledMCPs(),
199
+ };
200
+
201
+ const response = await fetch("/api/generate", {
202
+ method: "POST",
203
+ headers: {
204
+ "Content-Type": "application/json",
205
+ },
206
+ body: JSON.stringify(requestBody),
207
+ });
208
+
209
+ if (!response.ok) {
210
+ const error = await response.json();
211
+ throw new Error(error.error || "Failed to generate response");
212
  }
213
+
214
+ return await response.json();
215
  }
216
 
217
  export function isSystemPromptSupported(model: Model | CustomModel) {
src/lib/utils/stream.ts ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export interface StreamChunk {
2
+ type: "chunk" | "done" | "error";
3
+ content?: string;
4
+ error?: string;
5
+ }
6
+
7
+ export class StreamReader {
8
+ private decoder = new TextDecoder();
9
+ private buffer = "";
10
+
11
+ constructor(private response: Response) {
12
+ if (!response.body) {
13
+ throw new Error("Response has no body");
14
+ }
15
+ }
16
+
17
+ async *read(): AsyncGenerator<StreamChunk, void, unknown> {
18
+ const reader = this.response.body!.getReader();
19
+
20
+ try {
21
+ while (true) {
22
+ const { done, value } = await reader.read();
23
+ if (done) break;
24
+
25
+ this.buffer += this.decoder.decode(value, { stream: true });
26
+ const lines = this.buffer.split("\n");
27
+ this.buffer = lines.pop() || "";
28
+
29
+ for (const line of lines) {
30
+ if (line.startsWith("data: ")) {
31
+ const data = line.slice(6).trim();
32
+ if (!data) continue;
33
+
34
+ try {
35
+ const parsed = JSON.parse(data) as StreamChunk;
36
+ yield parsed;
37
+ if (parsed.type === "done") return;
38
+ } catch {
39
+ // Ignore malformed JSON
40
+ }
41
+ }
42
+ }
43
+ }
44
+ } finally {
45
+ reader.releaseLock();
46
+ }
47
+ }
48
+
49
+ static async fromFetch(url: string, options?: RequestInit): Promise<StreamReader> {
50
+ const response = await fetch(url, options);
51
+ if (!response.ok) {
52
+ const error = await response.json();
53
+ throw new Error(error.error || "Request failed");
54
+ }
55
+ return new StreamReader(response);
56
+ }
57
+ }
58
+
59
+ export class StreamWriter {
60
+ private encoder = new TextEncoder();
61
+ private controller?: ReadableStreamDefaultController<Uint8Array>;
62
+ public readonly stream: ReadableStream<Uint8Array>;
63
+
64
+ constructor() {
65
+ this.stream = new ReadableStream({
66
+ start: controller => {
67
+ this.controller = controller;
68
+ },
69
+ });
70
+ }
71
+
72
+ write(chunk: StreamChunk): void {
73
+ if (!this.controller) {
74
+ return;
75
+ }
76
+
77
+ try {
78
+ const data = JSON.stringify(chunk);
79
+ this.controller.enqueue(this.encoder.encode(`data: ${data}\n\n`));
80
+ } catch {
81
+ // Controller might be closed
82
+ }
83
+ }
84
+
85
+ writeChunk(content: string): void {
86
+ this.write({ type: "chunk", content });
87
+ }
88
+
89
+ writeError(error: string): void {
90
+ this.write({ type: "error", error });
91
+ }
92
+
93
+ end(): void {
94
+ if (!this.controller) return;
95
+ try {
96
+ this.write({ type: "done" });
97
+ this.controller.close();
98
+ } catch {
99
+ // Controller might already be closed
100
+ }
101
+ this.controller = undefined;
102
+ }
103
+
104
+ error(error: Error): void {
105
+ if (!this.controller) return;
106
+ try {
107
+ this.writeError(error.message);
108
+ this.controller.close();
109
+ } catch {
110
+ // Controller might already be closed
111
+ }
112
+ this.controller = undefined;
113
+ }
114
+
115
+ createResponse(): Response {
116
+ return new Response(this.stream, {
117
+ headers: {
118
+ "Content-Type": "text/event-stream",
119
+ "Cache-Control": "no-cache",
120
+ "Connection": "keep-alive",
121
+ },
122
+ });
123
+ }
124
+ }
125
+
126
+ export async function streamFromAsyncIterable<T>(
127
+ iterable: AsyncIterable<T>,
128
+ transform: (item: T) => StreamChunk,
129
+ ): Promise<ReadableStream<Uint8Array>> {
130
+ const writer = new StreamWriter();
131
+
132
+ (async () => {
133
+ try {
134
+ for await (const item of iterable) {
135
+ writer.write(transform(item));
136
+ }
137
+ writer.end();
138
+ } catch (error) {
139
+ writer.error(error instanceof Error ? error : new Error(String(error)));
140
+ }
141
+ })();
142
+
143
+ return writer.stream;
144
+ }
src/lib/utils/styles.ts ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import { type ClassValue, clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function classes(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
src/lib/utils/url.spec.ts ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { describe, expect, it } from "vitest";
2
+ import { extractDomain } from "./url.js";
3
+
4
+ describe("extractDomain", () => {
5
+ it("should handle regular domains", () => {
6
+ expect(extractDomain("https://example.com")).toBe("example.com");
7
+ });
8
+
9
+ it("should handle single subdomains", () => {
10
+ expect(extractDomain("https://sub.example.com")).toBe("example.com");
11
+ });
12
+
13
+ it("should handle multiple subdomains", () => {
14
+ expect(extractDomain("https://sub1.sub2.example.com")).toBe("example.com");
15
+ expect(extractDomain("https://deep.sub.domain.co.uk")).toBe("domain.co.uk");
16
+ expect(extractDomain("https://a.b.c.d.e.f.g.example.net")).toBe("example.net");
17
+ });
18
+
19
+ it("should handle special TLDs like co.uk", () => {
20
+ expect(extractDomain("https://domain.co.uk")).toBe("domain.co.uk");
21
+ expect(extractDomain("https://sub.domain.co.uk")).toBe("domain.co.uk");
22
+ expect(extractDomain("https://another.domain.com.au")).toBe("domain.com.au");
23
+ });
24
+
25
+ it("should handle localhost", () => {
26
+ expect(extractDomain("http://localhost:3000")).toBe("localhost");
27
+ expect(extractDomain("http://localhost")).toBe("localhost");
28
+ });
29
+
30
+ it("should handle non-HTTP/HTTPS protocols", () => {
31
+ expect(extractDomain("ftp://files.example.com")).toBe("example.com");
32
+ expect(extractDomain("ws://websocket.example.com")).toBe("example.com");
33
+ });
34
+
35
+ it("should handle non-string values", () => {
36
+ expect(extractDomain(12345)).toBeNull();
37
+ expect(extractDomain({})).toBeNull();
38
+ expect(extractDomain(["https://example.com"])).toBeNull();
39
+ expect(extractDomain(true)).toBeNull();
40
+ });
41
+
42
+ it("should handle URL instances", () => {
43
+ expect(extractDomain(new URL("https://test.example.com"))).toBe("example.com");
44
+ expect(extractDomain(new URL("https://deeply.nested.subdomain.example.org"))).toBe("example.org");
45
+ });
46
+
47
+ it("should handle invalid URLs gracefully", () => {
48
+ expect(extractDomain("not-a-url")).toBeNull();
49
+ expect(extractDomain("htt:invalid-url")).toBeNull();
50
+ expect(extractDomain("example")).toBeNull();
51
+ expect(extractDomain("http://")).toBeNull();
52
+ });
53
+
54
+ it("should handle tricky but valid URLs", () => {
55
+ expect(extractDomain("https://example.com#hash")).toBe("example.com");
56
+ expect(extractDomain("https://example.com/path")).toBe("example.com");
57
+ expect(extractDomain("https://example.com/path?query=string")).toBe("example.com");
58
+ });
59
+ });
src/lib/utils/url.ts CHANGED
@@ -6,3 +6,43 @@ export function isValidURL(url: string): boolean {
6
  return false;
7
  }
8
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  return false;
7
  }
8
  }
9
+
10
+ export const extractDomain = (value: unknown) => {
11
+ const url = toURL(value);
12
+
13
+ if (!url) {
14
+ return null;
15
+ }
16
+
17
+ const hostnameParts = url.hostname.split(".");
18
+
19
+ // Determine typical hostnames like "domain.com" or "domain.org"
20
+ if (hostnameParts.length <= 2) {
21
+ return url.hostname;
22
+ }
23
+
24
+ // Determine two-part TLD if second last part of the hostname matches one of the prefixes
25
+ const prefixes = ["com", "co", "org", "net", "gov", "edu"];
26
+ const potentialTwoPartTLD = `${hostnameParts[hostnameParts.length - 2]}.${hostnameParts[hostnameParts.length - 1]}`;
27
+
28
+ return prefixes.includes(hostnameParts[hostnameParts.length - 2]!)
29
+ ? `${hostnameParts[hostnameParts.length - 3]}.${potentialTwoPartTLD}`
30
+ : hostnameParts.slice(-2).join("."); // Fallback to last two parts of hostname
31
+ };
32
+
33
+ const toURL = (value: unknown) => {
34
+ if (value instanceof URL) {
35
+ return value;
36
+ }
37
+
38
+ if (typeof value !== "string" || !value) {
39
+ return null;
40
+ }
41
+
42
+ try {
43
+ const url = new URL(value);
44
+ return url.hostname ? url : null;
45
+ } catch {
46
+ return null;
47
+ }
48
+ };
src/routes/api/generate/+server.ts ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { last } from "$lib/utils/array.js";
2
+ import { StreamWriter } from "$lib/utils/stream.js";
3
+ import { json } from "@sveltejs/kit";
4
+ import type { ChatCompletionMessage } from "openai/resources/index.mjs";
5
+ import type { RequestHandler } from "./$types.js";
6
+ import { createAdapter, type GenerationArgs } from "./adapter.js";
7
+ import { connectToMCPServers, executeMcpTool, type MCPServerConnection } from "./mcp.js";
8
+ import type { FinishReason, GenerateRequest } from "./types.js";
9
+ import { debugLog } from "./utils.js";
10
+
11
+ type AssistantResponse = { message: ChatCompletionMessage; finish_reason: FinishReason };
12
+
13
+ type GenerateLoopArgs = {
14
+ args: GenerationArgs;
15
+ getAssistantResponse: (args: GenerationArgs) => Promise<AssistantResponse>;
16
+ connections: MCPServerConnection[];
17
+ };
18
+
19
+ async function generateLoop({ args, getAssistantResponse, connections }: GenerateLoopArgs) {
20
+ let finish_reason: FinishReason | null = null;
21
+ const abortReasons: FinishReason[] = ["stop", "content_filter", "length"];
22
+
23
+ while (!abortReasons.includes(finish_reason)) {
24
+ debugLog("finish reason", finish_reason);
25
+ switch (finish_reason) {
26
+ case null: {
27
+ const res = await getAssistantResponse(args);
28
+ args.messages.push(res.message);
29
+ finish_reason = res.finish_reason;
30
+ break;
31
+ }
32
+ case "tool_calls": {
33
+ const toolCalls = last(args.messages)?.tool_calls;
34
+ if (!toolCalls) {
35
+ debugLog("No tool calls found");
36
+ finish_reason = null;
37
+ break;
38
+ }
39
+
40
+ debugLog("Executing tool calls");
41
+ debugLog(JSON.stringify(toolCalls, null, 2));
42
+
43
+ await Promise.allSettled(
44
+ toolCalls.map(async toolCall => {
45
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
46
+ const response = await executeMcpTool(connections, toolCall as any);
47
+ debugLog("Tool call response", response);
48
+ args.messages.push(response);
49
+ }),
50
+ );
51
+
52
+ finish_reason = null;
53
+
54
+ break;
55
+ }
56
+ default: {
57
+ finish_reason = "stop";
58
+ break;
59
+ }
60
+ }
61
+ }
62
+ }
63
+
64
+ export const POST: RequestHandler = async ({ request }) => {
65
+ try {
66
+ const body: GenerateRequest = await request.json();
67
+ const { model, messages, config, provider, streaming, response_format, enabledMCPs } = body;
68
+
69
+ if (enabledMCPs?.length === 0) {
70
+ debugLog(`MCP: Enabled MCP servers: ${enabledMCPs?.join(", ")}`);
71
+ }
72
+
73
+ // Connect to enabled MCP servers
74
+ const connections = await connectToMCPServers(enabledMCPs || []);
75
+ const tools = connections.flatMap(conn => conn.tools);
76
+
77
+ debugLog(`MCP: Connected to ${connections.length} servers with ${tools.length} tools available`);
78
+
79
+ const adapter = createAdapter(body);
80
+
81
+ const args = {
82
+ model: model.id,
83
+ messages,
84
+ provider,
85
+ ...config,
86
+ tools,
87
+ response_format,
88
+ stream: streaming,
89
+ };
90
+
91
+ if (streaming) {
92
+ const writer = new StreamWriter();
93
+
94
+ generateLoop({
95
+ args,
96
+ connections,
97
+ getAssistantResponse: async args => {
98
+ debugLog("Generating streaming response");
99
+ const res: AssistantResponse = {
100
+ message: {
101
+ role: "assistant",
102
+ content: "",
103
+ // refusal: null,
104
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
105
+ } as any,
106
+ finish_reason: null,
107
+ };
108
+
109
+ try {
110
+ const adapterStream = await adapter.stream(args);
111
+ for await (const chunk of adapterStream) {
112
+ const choice = chunk.choices[0];
113
+ if (!choice) continue;
114
+
115
+ if (choice.delta.content) {
116
+ res.message.content += choice.delta.content;
117
+ writer.writeChunk(choice.delta.content || "");
118
+ }
119
+ if (choice.delta.tool_calls) {
120
+ res.message.tool_calls = res.message.tool_calls ?? [];
121
+
122
+ for (const toolCall of choice.delta.tool_calls) {
123
+ res.message.tool_calls[toolCall.index] = res.message.tool_calls[toolCall.index] ?? {
124
+ id: toolCall.id ?? "",
125
+ type: "function",
126
+ function: {
127
+ name: "",
128
+ arguments: "",
129
+ },
130
+ };
131
+
132
+ if (toolCall.function?.name) {
133
+ res.message.tool_calls[toolCall.index]!.function.name += toolCall.function.name;
134
+ }
135
+ if (toolCall.function?.arguments) {
136
+ res.message.tool_calls[toolCall.index]!.function.arguments += toolCall.function.arguments;
137
+ }
138
+ }
139
+ }
140
+ if (choice.finish_reason) {
141
+ res.finish_reason = choice.finish_reason;
142
+ }
143
+ }
144
+ } catch (error) {
145
+ console.error("stream error", error);
146
+ writer.error(error instanceof Error ? error : new Error(String(error)));
147
+ res.finish_reason = "stop";
148
+ return res;
149
+ }
150
+
151
+ debugLog("Generated message");
152
+ debugLog(JSON.stringify(res.message, null, 2));
153
+ return res;
154
+ },
155
+ })
156
+ .then(() => writer.end())
157
+ .catch(error => {
158
+ console.error("Generation loop error:", error);
159
+ writer.error(error instanceof Error ? error : new Error(String(error)));
160
+ });
161
+
162
+ debugLog("Creating response...");
163
+
164
+ return writer.createResponse();
165
+ }
166
+
167
+ const message: ChatCompletionMessage = {
168
+ role: "assistant",
169
+ content: "",
170
+ // refusal: null,
171
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
172
+ } as any;
173
+
174
+ await generateLoop({
175
+ args,
176
+ connections,
177
+ getAssistantResponse: async args => {
178
+ debugLog("Generating non-streaming response");
179
+ const response = await adapter.generate(args);
180
+ debugLog("Generated the response");
181
+ debugLog(JSON.stringify(response, null, 2));
182
+
183
+ if (response.choices && response.choices.length > 0) {
184
+ message.content += response.choices[0]!.message.content ?? "";
185
+ // const { completion_tokens } = response.usage || { completion_tokens: 0 };
186
+
187
+ return {
188
+ message: response.choices[0]!.message,
189
+ finish_reason: response.choices[0]!.finish_reason,
190
+ };
191
+ }
192
+ throw new Error("No response from the model");
193
+ },
194
+ });
195
+
196
+ return json({ message /* ,completion_tokens */ });
197
+ } catch (error) {
198
+ debugLog(JSON.stringify(error, null, 2));
199
+ console.error("Generation error:", error);
200
+ return json({ error: error instanceof Error ? error.message : "Unknown error occurred" }, { status: 500 });
201
+ }
202
+ };
src/routes/api/generate/adapter.ts ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* eslint-disable @typescript-eslint/no-explicit-any -- Sorry */
2
+ import { omit } from "$lib/utils/object.svelte.js";
3
+ import { InferenceClient } from "@huggingface/inference";
4
+ import type { ChatCompletionInputMessage } from "@huggingface/tasks";
5
+ import OpenAI from "openai";
6
+ import type { Stream } from "openai/streaming.mjs";
7
+ import type { GenerateRequest, OpenAIFunctionSchema } from "./types.js";
8
+ import type { ChatCompletionMessage } from "openai/resources/index.mjs";
9
+
10
+ export type GenerationArgs = {
11
+ model: string;
12
+ messages: Array<ChatCompletionInputMessage | ChatCompletionMessage>;
13
+ provider?: string;
14
+ config?: Record<string, unknown>;
15
+ tools?: OpenAIFunctionSchema[];
16
+ response_format?: unknown;
17
+ };
18
+
19
+ export interface Adapter {
20
+ stream: (args: GenerationArgs) => Promise<Stream<OpenAI.Chat.Completions.ChatCompletionChunk>>;
21
+ generate: (args: GenerationArgs) => Promise<OpenAI.Chat.Completions.ChatCompletion>;
22
+ }
23
+
24
+ function createCustomAdapter({ model }: GenerateRequest): Adapter {
25
+ // Handle OpenAI-compatible custom models
26
+ const openai = new OpenAI({
27
+ apiKey: model.accessToken,
28
+ baseURL: model.endpointUrl,
29
+ });
30
+
31
+ return {
32
+ stream: async (args: GenerationArgs) => {
33
+ return await openai.chat.completions.create({
34
+ ...omit(args, "provider"),
35
+ stream: true,
36
+ } as OpenAI.ChatCompletionCreateParamsStreaming);
37
+ },
38
+ generate: (args: GenerationArgs) => {
39
+ return openai.chat.completions.create({
40
+ ...omit(args, "provider"),
41
+ stream: false,
42
+ } as OpenAI.ChatCompletionCreateParamsNonStreaming);
43
+ },
44
+ };
45
+ }
46
+
47
+ function createHFAdapter({ accessToken }: GenerateRequest): Adapter {
48
+ const client = new InferenceClient(accessToken);
49
+ return {
50
+ stream: (args: GenerationArgs) => {
51
+ return client.chatCompletionStream({
52
+ ...args,
53
+ provider: args.provider as any,
54
+ response_format: args.response_format as any,
55
+ tools: args.tools as any,
56
+ } as any) as any;
57
+ },
58
+ generate: (args: GenerationArgs) => {
59
+ return client.chatCompletion(args as any) as any;
60
+ },
61
+ };
62
+ }
63
+
64
+ export function createAdapter(body: GenerateRequest): Adapter {
65
+ const { model } = body;
66
+
67
+ if (model.isCustom) {
68
+ return createCustomAdapter(body);
69
+ }
70
+ return createHFAdapter(body);
71
+ }
src/routes/api/generate/mcp.ts ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
+ import type { MCPServerConfig, McpToolSchema, OpenAIFunctionSchema } from "./types.js";
3
+ import { debugError, debugLog } from "./utils.js";
4
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
5
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
6
+
7
+ export const mcpToolToOpenAIFunction = (tool: McpToolSchema): OpenAIFunctionSchema => {
8
+ return {
9
+ type: "function",
10
+ function: {
11
+ name: tool.name,
12
+ description: tool.name,
13
+ parameters: tool.inputSchema,
14
+ strict: true,
15
+ },
16
+ };
17
+ };
18
+
19
+ export type MCPServerConnection = { client: Client; tools: OpenAIFunctionSchema[] };
20
+
21
+ export const connectToMCPServers = async (servers: MCPServerConfig[]): Promise<MCPServerConnection[]> => {
22
+ const connections: MCPServerConnection[] = [];
23
+
24
+ await Promise.allSettled(
25
+ servers.map(async server => {
26
+ try {
27
+ const conn: MCPServerConnection = {
28
+ client: new Client({
29
+ name: "playground-client" + crypto.randomUUID(),
30
+ version: "0.0.1",
31
+ }),
32
+ tools: [],
33
+ };
34
+
35
+ debugLog(`Connecting to MCP server: ${server.name} (${server.url})`);
36
+
37
+ let transport;
38
+ const url = new URL(server.url);
39
+ if (server.protocol === "sse") {
40
+ transport = new SSEClientTransport(url);
41
+ } else {
42
+ transport = new StreamableHTTPClientTransport(url);
43
+ }
44
+
45
+ await conn.client.connect(transport);
46
+
47
+ const { tools: mcpTools } = await conn.client.listTools();
48
+ const serverTools = mcpTools.map(mcpToolToOpenAIFunction);
49
+ conn.tools.push(...serverTools);
50
+ debugLog(`Connected to ${server.name} with ${mcpTools.length} tools`);
51
+ connections.push(conn);
52
+ } catch (error) {
53
+ debugError(`Failed to connect to MCP server ${server.name}:`, error);
54
+ }
55
+ }),
56
+ );
57
+
58
+ return connections;
59
+ };
60
+
61
+ export const executeMcpTool = async (
62
+ connections: MCPServerConnection[],
63
+ toolCall: { id: string; function: { name: string; arguments: string } },
64
+ ) => {
65
+ try {
66
+ debugLog(`Executing tool: ${toolCall.function.name}`);
67
+ debugLog(`Tool arguments:`, JSON.parse(toolCall.function.arguments));
68
+
69
+ // Try to find the tool in any of the connected clients
70
+ let result = null;
71
+ for (const conn of connections) {
72
+ try {
73
+ const toolExists = conn.tools.some(tool => tool.function?.name === toolCall.function.name);
74
+ if (!toolExists) continue;
75
+ debugLog(`Found tool ${toolCall.function.name}`);
76
+ result = await conn.client.callTool({
77
+ name: toolCall.function.name,
78
+ arguments: JSON.parse(toolCall.function.arguments),
79
+ });
80
+ } catch (clientError) {
81
+ debugError(`Failed to execute tool on client:`, clientError);
82
+ continue;
83
+ }
84
+ }
85
+
86
+ if (!result) {
87
+ throw new Error(`Tool ${toolCall.function.name} not found in any connected MCP server`);
88
+ }
89
+
90
+ // mcpLog(`Tool result:`, result.content);
91
+
92
+ return {
93
+ tool_call_id: toolCall.id,
94
+ role: "tool" as const,
95
+ content: JSON.stringify(result.content),
96
+ };
97
+ } catch (error) {
98
+ debugError(`Tool execution failed:`, error);
99
+
100
+ return {
101
+ tool_call_id: toolCall.id,
102
+ role: "tool" as const,
103
+ content: JSON.stringify({ error: error instanceof Error ? error.message : "Tool execution failed" }),
104
+ };
105
+ }
106
+ };
src/routes/api/generate/types.ts ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { ChatCompletionInputMessage } from "@huggingface/tasks";
2
+ import type { ChatCompletionChunk } from "openai/resources/index.mjs";
3
+
4
+ export interface MCPServerConfig {
5
+ id: string;
6
+ name: string;
7
+ url: string;
8
+ protocol: "sse" | "http";
9
+ headers?: Record<string, string>;
10
+ }
11
+
12
+ export interface GenerateRequest {
13
+ model: {
14
+ id: string;
15
+ isCustom?: boolean;
16
+ accessToken?: string;
17
+ endpointUrl?: string;
18
+ };
19
+ messages: ChatCompletionInputMessage[];
20
+ config: Record<string, unknown>;
21
+ provider?: string;
22
+ streaming?: boolean;
23
+ response_format?: unknown;
24
+ accessToken: string;
25
+ enabledMCPs?: MCPServerConfig[];
26
+ }
27
+
28
+ export interface OpenAIFunctionSchema {
29
+ type?: string;
30
+ function?: {
31
+ name?: string;
32
+ description?: string;
33
+ parameters?: {
34
+ type?: string;
35
+ required?: string[];
36
+ additionalProperties?: boolean;
37
+ [key: string]: unknown;
38
+ };
39
+ strict?: boolean;
40
+ };
41
+ }
42
+
43
+ export type McpToolSchema = {
44
+ name: string;
45
+ inputSchema: {
46
+ type: string;
47
+ required?: string[];
48
+ additionalProperties?: boolean;
49
+ [key: string]: unknown;
50
+ };
51
+ };
52
+
53
+ export type FinishReason = ChatCompletionChunk.Choice["finish_reason"];
src/routes/api/generate/utils.ts ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const DEBUG_LOG = true;
2
+
3
+ export const debugLog = (...args: unknown[]) => {
4
+ if (!DEBUG_LOG) return;
5
+ console.log("[LOG DEBUG]", ...args);
6
+ };
7
+
8
+ export const debugError = (...args: unknown[]) => {
9
+ if (!DEBUG_LOG) return;
10
+ console.error("[LOG DEBUG]", ...args);
11
+ };