victor HF Staff commited on
Commit
cbdd432
·
1 Parent(s): cb00da9

New /models layout

Browse files

Replaces CarbonTools and related Carbon icons with Lucide equivalents throughout the UI, updating imports and usage in Svelte components. Updates Hugging Face organization avatar URLs to the new /api/avatars/{org} endpoint in both frontend and backend code. Adds new models to dev and prod YAML configs, and improves the models page layout and filtering. Also updates dependencies to include @iconify-json/lucide and the latest @sinclair/typebox.

chart/env/dev.yaml CHANGED
@@ -77,6 +77,23 @@ envVars:
77
  PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
78
  MODELS: >
79
  [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  { "id": "deepseek-ai/DeepSeek-V3.2-Exp", "description": "Experimental V3.2 release focused on faster, lower-cost inference with strong general reasoning and tool use." },
81
  { "id": "zai-org/GLM-4.6", "description": "Next-gen GLM with very long context and solid multilingual reasoning; good for agents and tools." },
82
  { "id": "Kwaipilot/KAT-Dev", "description": "Developer-oriented assistant tuned for coding, debugging, and lightweight agent workflows." },
 
77
  PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
78
  MODELS: >
79
  [
80
+ { "id": "MiniMaxAI/MiniMax-M2", "description": "Compact MoE model tuned for fast coding, agentic workflows, and long-context chat." },
81
+ { "id": "PrimeIntellect/INTELLECT-3-FP8", "description": "FP8 INTELLECT-3 variant for cheaper frontier-level math, code, and general reasoning." },
82
+ { "id": "Qwen/Qwen3-VL-30B-A3B-Instruct", "description": "Flagship Qwen3 vision-language model for high-accuracy image, text, and video reasoning." },
83
+ { "id": "Qwen/Qwen3-VL-30B-A3B-Thinking", "description": "Thinking-mode Qwen3-VL that emits detailed multimodal reasoning traces for difficult problems." },
84
+ { "id": "Qwen/Qwen3-VL-8B-Instruct", "description": "Smaller Qwen3 vision-language assistant for everyday multimodal chat, captioning, and analysis." },
85
+ { "id": "aisingapore/Qwen-SEA-LION-v4-32B-IT", "description": "SEA-LION v4 Qwen optimized for Southeast Asian languages and regional enterprise workloads." },
86
+ { "id": "allenai/Olmo-3-32B-Think", "description": "Fully open 32B thinking model excelling at stepwise math, coding, and research reasoning." },
87
+ { "id": "allenai/Olmo-3-7B-Instruct", "description": "Lightweight Olmo assistant for instruction following, Q&A, and everyday open-source workflows." },
88
+ { "id": "allenai/Olmo-3-7B-Think", "description": "7B Olmo reasoning model delivering transparent multi-step thinking on modest hardware." },
89
+ { "id": "deepcogito/cogito-671b-v2.1", "description": "Frontier-scale 671B MoE focused on deep reasoning, math proofs, and complex coding." },
90
+ { "id": "deepcogito/cogito-671b-v2.1-FP8", "description": "FP8 Cogito v2.1 making 671B-scale reasoning more affordable to serve and experiment with." },
91
+ { "id": "deepseek-ai/DeepSeek-V3.2", "description": "Latest DeepSeek agent model combining strong reasoning, tool-use, and efficient long-context inference." },
92
+ { "id": "moonshotai/Kimi-K2-Thinking", "description": "Reasoning-focused Kimi K2 variant for deep chain-of-thought and large agentic tool flows." },
93
+ { "id": "nvidia/NVIDIA-Nemotron-Nano-12B-v2", "description": "NVIDIA Nano 12B general assistant for coding, chat, and agents with efficient deployment." },
94
+ { "id": "openai/gpt-oss-safeguard-20b", "description": "Safety-focused gpt-oss variant for content classification, policy enforcement, and LLM output filtering." },
95
+ { "id": "zai-org/GLM-4.5", "description": "Flagship GLM agent model unifying advanced reasoning, coding, and tool-using capabilities." },
96
+ { "id": "zai-org/GLM-4.5V-FP8", "description": "FP8 vision-language GLM-4.5V for efficient multilingual visual QA, understanding, and hybrid reasoning." },
97
  { "id": "deepseek-ai/DeepSeek-V3.2-Exp", "description": "Experimental V3.2 release focused on faster, lower-cost inference with strong general reasoning and tool use." },
98
  { "id": "zai-org/GLM-4.6", "description": "Next-gen GLM with very long context and solid multilingual reasoning; good for agents and tools." },
99
  { "id": "Kwaipilot/KAT-Dev", "description": "Developer-oriented assistant tuned for coding, debugging, and lightweight agent workflows." },
chart/env/prod.yaml CHANGED
@@ -87,6 +87,23 @@ envVars:
87
  PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
88
  MODELS: >
89
  [
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  { "id": "deepseek-ai/DeepSeek-V3.2-Exp", "description": "Experimental V3.2 release focused on faster, lower-cost inference with strong general reasoning and tool use." },
91
  { "id": "zai-org/GLM-4.6", "description": "Next-gen GLM with very long context and solid multilingual reasoning; good for agents and tools." },
92
  { "id": "Kwaipilot/KAT-Dev", "description": "Developer-oriented assistant tuned for coding, debugging, and lightweight agent workflows." },
 
87
  PUBLIC_LLM_ROUTER_ALIAS_ID: "omni"
88
  MODELS: >
89
  [
90
+ { "id": "MiniMaxAI/MiniMax-M2", "description": "Compact MoE model tuned for fast coding, agentic workflows, and long-context chat." },
91
+ { "id": "PrimeIntellect/INTELLECT-3-FP8", "description": "FP8 INTELLECT-3 variant for cheaper frontier-level math, code, and general reasoning." },
92
+ { "id": "Qwen/Qwen3-VL-30B-A3B-Instruct", "description": "Flagship Qwen3 vision-language model for high-accuracy image, text, and video reasoning." },
93
+ { "id": "Qwen/Qwen3-VL-30B-A3B-Thinking", "description": "Thinking-mode Qwen3-VL that emits detailed multimodal reasoning traces for difficult problems." },
94
+ { "id": "Qwen/Qwen3-VL-8B-Instruct", "description": "Smaller Qwen3 vision-language assistant for everyday multimodal chat, captioning, and analysis." },
95
+ { "id": "aisingapore/Qwen-SEA-LION-v4-32B-IT", "description": "SEA-LION v4 Qwen optimized for Southeast Asian languages and regional enterprise workloads." },
96
+ { "id": "allenai/Olmo-3-32B-Think", "description": "Fully open 32B thinking model excelling at stepwise math, coding, and research reasoning." },
97
+ { "id": "allenai/Olmo-3-7B-Instruct", "description": "Lightweight Olmo assistant for instruction following, Q&A, and everyday open-source workflows." },
98
+ { "id": "allenai/Olmo-3-7B-Think", "description": "7B Olmo reasoning model delivering transparent multi-step thinking on modest hardware." },
99
+ { "id": "deepcogito/cogito-671b-v2.1", "description": "Frontier-scale 671B MoE focused on deep reasoning, math proofs, and complex coding." },
100
+ { "id": "deepcogito/cogito-671b-v2.1-FP8", "description": "FP8 Cogito v2.1 making 671B-scale reasoning more affordable to serve and experiment with." },
101
+ { "id": "deepseek-ai/DeepSeek-V3.2", "description": "Latest DeepSeek agent model combining strong reasoning, tool-use, and efficient long-context inference." },
102
+ { "id": "moonshotai/Kimi-K2-Thinking", "description": "Reasoning-focused Kimi K2 variant for deep chain-of-thought and large agentic tool flows." },
103
+ { "id": "nvidia/NVIDIA-Nemotron-Nano-12B-v2", "description": "NVIDIA Nano 12B general assistant for coding, chat, and agents with efficient deployment." },
104
+ { "id": "openai/gpt-oss-safeguard-20b", "description": "Safety-focused gpt-oss variant for content classification, policy enforcement, and LLM output filtering." },
105
+ { "id": "zai-org/GLM-4.5", "description": "Flagship GLM agent model unifying advanced reasoning, coding, and tool-using capabilities." },
106
+ { "id": "zai-org/GLM-4.5V-FP8", "description": "FP8 vision-language GLM-4.5V for efficient multilingual visual QA, understanding, and hybrid reasoning." },
107
  { "id": "deepseek-ai/DeepSeek-V3.2-Exp", "description": "Experimental V3.2 release focused on faster, lower-cost inference with strong general reasoning and tool use." },
108
  { "id": "zai-org/GLM-4.6", "description": "Next-gen GLM with very long context and solid multilingual reasoning; good for agents and tools." },
109
  { "id": "Kwaipilot/KAT-Dev", "description": "Developer-oriented assistant tuned for coding, debugging, and lightweight agent workflows." },
package-lock.json CHANGED
@@ -15,6 +15,7 @@
15
  "@iconify-json/bi": "^1.1.21",
16
  "@modelcontextprotocol/sdk": "^1.21.1",
17
  "@resvg/resvg-js": "^2.6.2",
 
18
  "autoprefixer": "^10.4.14",
19
  "aws4": "^1.13.2",
20
  "bits-ui": "^2.14.2",
@@ -55,6 +56,7 @@
55
  "@faker-js/faker": "^8.4.1",
56
  "@iconify-json/carbon": "^1.1.16",
57
  "@iconify-json/eos-icons": "^1.1.6",
 
58
  "@sveltejs/adapter-node": "^5.2.12",
59
  "@sveltejs/kit": "^2.21.1",
60
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
@@ -678,6 +680,7 @@
678
  "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.927.0.tgz",
679
  "integrity": "sha512-CasoHKKE/K+6YcVqjE+v5dVyKqKBtfzZyvGi669HvJ1f4EPHbVRPPLIb0eAYd/aEmwHsB/nn9VnyN9Wq5OppUQ==",
680
  "license": "Apache-2.0",
 
681
  "dependencies": {
682
  "@aws-sdk/client-cognito-identity": "3.927.0",
683
  "@aws-sdk/core": "3.927.0",
@@ -954,7 +957,6 @@
954
  "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
955
  "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
956
  "license": "MIT",
957
- "peer": true,
958
  "dependencies": {
959
  "@babel/helper-validator-identifier": "^7.27.1",
960
  "js-tokens": "^4.0.0",
@@ -969,7 +971,6 @@
969
  "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
970
  "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
971
  "license": "MIT",
972
- "peer": true,
973
  "engines": {
974
  "node": ">=6.9.0"
975
  }
@@ -1071,6 +1072,7 @@
1071
  }
1072
  ],
1073
  "license": "MIT",
 
1074
  "engines": {
1075
  "node": ">=18"
1076
  },
@@ -1094,6 +1096,7 @@
1094
  }
1095
  ],
1096
  "license": "MIT",
 
1097
  "engines": {
1098
  "node": ">=18"
1099
  }
@@ -1796,6 +1799,16 @@
1796
  "@iconify/types": "*"
1797
  }
1798
  },
 
 
 
 
 
 
 
 
 
 
1799
  "node_modules/@iconify/types": {
1800
  "version": "2.0.0",
1801
  "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
@@ -3214,11 +3227,11 @@
3214
  "license": "MIT"
3215
  },
3216
  "node_modules/@sinclair/typebox": {
3217
- "version": "0.34.33",
3218
- "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.33.tgz",
3219
- "integrity": "sha512-5HAV9exOMcXRUxo+9iYB5n09XxzCXnfy4VTNW4xnDv+FgjzAGY989C28BIdljKqmF+ZltUwujE3aossvcVtq6g==",
3220
  "license": "MIT",
3221
- "optional": true
3222
  },
3223
  "node_modules/@smithy/abort-controller": {
3224
  "version": "4.2.4",
@@ -3831,6 +3844,7 @@
3831
  "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==",
3832
  "devOptional": true,
3833
  "license": "MIT",
 
3834
  "dependencies": {
3835
  "@sveltejs/acorn-typescript": "^1.0.5",
3836
  "@types/cookie": "^0.6.0",
@@ -3863,6 +3877,7 @@
3863
  "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==",
3864
  "devOptional": true,
3865
  "license": "MIT",
 
3866
  "dependencies": {
3867
  "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
3868
  "debug": "^4.4.1",
@@ -3902,7 +3917,6 @@
3902
  "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
3903
  "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
3904
  "license": "Apache-2.0",
3905
- "peer": true,
3906
  "dependencies": {
3907
  "tslib": "^2.8.0"
3908
  }
@@ -3948,7 +3962,6 @@
3948
  "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
3949
  "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
3950
  "license": "MIT",
3951
- "peer": true,
3952
  "engines": {
3953
  "node": ">=12",
3954
  "npm": ">=6"
@@ -3994,8 +4007,7 @@
3994
  "version": "5.0.4",
3995
  "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
3996
  "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
3997
- "license": "MIT",
3998
- "peer": true
3999
  },
4000
  "node_modules/@types/chai": {
4001
  "version": "5.2.2",
@@ -4224,6 +4236,7 @@
4224
  "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
4225
  "dev": true,
4226
  "license": "BSD-2-Clause",
 
4227
  "dependencies": {
4228
  "@typescript-eslint/scope-manager": "6.21.0",
4229
  "@typescript-eslint/types": "6.21.0",
@@ -4622,6 +4635,7 @@
4622
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
4623
  "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
4624
  "license": "MIT",
 
4625
  "bin": {
4626
  "acorn": "bin/acorn"
4627
  },
@@ -4805,7 +4819,6 @@
4805
  "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
4806
  "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
4807
  "license": "Apache-2.0",
4808
- "peer": true,
4809
  "dependencies": {
4810
  "dequal": "^2.0.3"
4811
  }
@@ -5071,6 +5084,7 @@
5071
  }
5072
  ],
5073
  "license": "MIT",
 
5074
  "dependencies": {
5075
  "caniuse-lite": "^1.0.30001718",
5076
  "electron-to-chromium": "^1.5.160",
@@ -5740,8 +5754,7 @@
5740
  "version": "0.5.16",
5741
  "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
5742
  "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
5743
- "license": "MIT",
5744
- "peer": true
5745
  },
5746
  "node_modules/domexception": {
5747
  "version": "4.0.0",
@@ -5815,6 +5828,7 @@
5815
  "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.3.4.tgz",
5816
  "integrity": "sha512-kAfM3Zwovy3z255IZgTKVxBw91HbgKhYl3TqrGRdZqqr+Fd+4eKOfvxgaKij22+MZLczPzIHtscAmvfpI3+q/A==",
5817
  "license": "MIT",
 
5818
  "dependencies": {
5819
  "cookie": "^1.0.2",
5820
  "exact-mirror": "0.1.2",
@@ -6015,6 +6029,7 @@
6015
  "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
6016
  "dev": true,
6017
  "license": "MIT",
 
6018
  "dependencies": {
6019
  "@eslint-community/eslint-utils": "^4.2.0",
6020
  "@eslint-community/regexpp": "^4.6.1",
@@ -6652,6 +6667,7 @@
6652
  "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz",
6653
  "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==",
6654
  "license": "MIT",
 
6655
  "dependencies": {
6656
  "@tokenizer/inflate": "^0.2.7",
6657
  "strtok3": "^10.2.2",
@@ -7773,8 +7789,7 @@
7773
  "version": "4.0.0",
7774
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
7775
  "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
7776
- "license": "MIT",
7777
- "peer": true
7778
  },
7779
  "node_modules/js-yaml": {
7780
  "version": "4.1.0",
@@ -9546,6 +9561,7 @@
9546
  "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
9547
  "devOptional": true,
9548
  "license": "Apache-2.0",
 
9549
  "dependencies": {
9550
  "playwright-core": "1.55.1"
9551
  },
@@ -9591,6 +9607,7 @@
9591
  }
9592
  ],
9593
  "license": "MIT",
 
9594
  "dependencies": {
9595
  "nanoid": "^3.3.11",
9596
  "picocolors": "^1.1.1",
@@ -9822,6 +9839,7 @@
9822
  "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
9823
  "dev": true,
9824
  "license": "MIT",
 
9825
  "bin": {
9826
  "prettier": "bin/prettier.cjs"
9827
  },
@@ -9838,6 +9856,7 @@
9838
  "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
9839
  "dev": true,
9840
  "license": "MIT",
 
9841
  "peerDependencies": {
9842
  "prettier": "^3.0.0",
9843
  "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
@@ -9927,7 +9946,6 @@
9927
  "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
9928
  "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
9929
  "license": "MIT",
9930
- "peer": true,
9931
  "dependencies": {
9932
  "ansi-regex": "^5.0.1",
9933
  "ansi-styles": "^5.0.0",
@@ -9942,7 +9960,6 @@
9942
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
9943
  "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
9944
  "license": "MIT",
9945
- "peer": true,
9946
  "engines": {
9947
  "node": ">=10"
9948
  },
@@ -10151,8 +10168,7 @@
10151
  "version": "17.0.2",
10152
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
10153
  "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
10154
- "license": "MIT",
10155
- "peer": true
10156
  },
10157
  "node_modules/read-cache": {
10158
  "version": "1.0.0",
@@ -10316,6 +10332,7 @@
10316
  "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz",
10317
  "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==",
10318
  "license": "MIT",
 
10319
  "dependencies": {
10320
  "@types/estree": "1.0.7"
10321
  },
@@ -11234,6 +11251,7 @@
11234
  "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.14.tgz",
11235
  "integrity": "sha512-kRlbhIlMTijbFmVDQFDeKXPLlX1/ovXwV0I162wRqQhRcygaqDIcu1d/Ese3H2uI+yt3uT8E7ndgDthQv5v5BA==",
11236
  "license": "MIT",
 
11237
  "dependencies": {
11238
  "@ampproject/remapping": "^2.3.0",
11239
  "@jridgewell/sourcemap-codec": "^1.5.0",
@@ -11373,6 +11391,7 @@
11373
  "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
11374
  "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
11375
  "license": "MIT",
 
11376
  "dependencies": {
11377
  "@alloc/quick-lru": "^5.2.0",
11378
  "arg": "^5.0.2",
@@ -11830,6 +11849,7 @@
11830
  "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
11831
  "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
11832
  "license": "Apache-2.0",
 
11833
  "bin": {
11834
  "tsc": "bin/tsc",
11835
  "tsserver": "bin/tsserver"
@@ -12065,6 +12085,7 @@
12065
  "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
12066
  "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
12067
  "license": "MIT",
 
12068
  "dependencies": {
12069
  "esbuild": "^0.25.0",
12070
  "fdir": "^6.4.4",
@@ -12200,6 +12221,7 @@
12200
  "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz",
12201
  "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==",
12202
  "license": "MIT",
 
12203
  "dependencies": {
12204
  "@types/chai": "^5.2.2",
12205
  "@vitest/expect": "3.2.2",
@@ -12522,6 +12544,7 @@
12522
  "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
12523
  "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
12524
  "license": "MIT",
 
12525
  "engines": {
12526
  "node": ">=10.0.0"
12527
  },
@@ -12644,6 +12667,7 @@
12644
  "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.55.tgz",
12645
  "integrity": "sha512-219huNnkSLQnLsQ3uaRjXsxMrVm5C9W3OOpEVt2k5tvMKuA8nBSu38e0B//a+he9Iq2dvmk2VyYVlHqiHa4YBA==",
12646
  "license": "MIT",
 
12647
  "funding": {
12648
  "url": "https://github.com/sponsors/colinhacks"
12649
  }
 
15
  "@iconify-json/bi": "^1.1.21",
16
  "@modelcontextprotocol/sdk": "^1.21.1",
17
  "@resvg/resvg-js": "^2.6.2",
18
+ "@sinclair/typebox": "^0.34.41",
19
  "autoprefixer": "^10.4.14",
20
  "aws4": "^1.13.2",
21
  "bits-ui": "^2.14.2",
 
56
  "@faker-js/faker": "^8.4.1",
57
  "@iconify-json/carbon": "^1.1.16",
58
  "@iconify-json/eos-icons": "^1.1.6",
59
+ "@iconify-json/lucide": "^1.2.77",
60
  "@sveltejs/adapter-node": "^5.2.12",
61
  "@sveltejs/kit": "^2.21.1",
62
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
 
680
  "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.927.0.tgz",
681
  "integrity": "sha512-CasoHKKE/K+6YcVqjE+v5dVyKqKBtfzZyvGi669HvJ1f4EPHbVRPPLIb0eAYd/aEmwHsB/nn9VnyN9Wq5OppUQ==",
682
  "license": "Apache-2.0",
683
+ "peer": true,
684
  "dependencies": {
685
  "@aws-sdk/client-cognito-identity": "3.927.0",
686
  "@aws-sdk/core": "3.927.0",
 
957
  "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
958
  "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
959
  "license": "MIT",
 
960
  "dependencies": {
961
  "@babel/helper-validator-identifier": "^7.27.1",
962
  "js-tokens": "^4.0.0",
 
971
  "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
972
  "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
973
  "license": "MIT",
 
974
  "engines": {
975
  "node": ">=6.9.0"
976
  }
 
1072
  }
1073
  ],
1074
  "license": "MIT",
1075
+ "peer": true,
1076
  "engines": {
1077
  "node": ">=18"
1078
  },
 
1096
  }
1097
  ],
1098
  "license": "MIT",
1099
+ "peer": true,
1100
  "engines": {
1101
  "node": ">=18"
1102
  }
 
1799
  "@iconify/types": "*"
1800
  }
1801
  },
1802
+ "node_modules/@iconify-json/lucide": {
1803
+ "version": "1.2.77",
1804
+ "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.2.77.tgz",
1805
+ "integrity": "sha512-FF3Z+np6Ksb0MaoQymhCHZ4xs5Oo8992Fw7By7bCgVCbBCClYV3wxpF8KzsI1FlxHD4ZXR42NVmXuqdW8YQGgA==",
1806
+ "dev": true,
1807
+ "license": "ISC",
1808
+ "dependencies": {
1809
+ "@iconify/types": "*"
1810
+ }
1811
+ },
1812
  "node_modules/@iconify/types": {
1813
  "version": "2.0.0",
1814
  "resolved": "https://registry.npmjs.org/@iconify/types/-/types-2.0.0.tgz",
 
3227
  "license": "MIT"
3228
  },
3229
  "node_modules/@sinclair/typebox": {
3230
+ "version": "0.34.41",
3231
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.41.tgz",
3232
+ "integrity": "sha512-6gS8pZzSXdyRHTIqoqSVknxolr1kzfy4/CeDnrzsVz8TTIWUbOBr6gnzOmTYJ3eXQNh4IYHIGi5aIL7sOZ2G/g==",
3233
  "license": "MIT",
3234
+ "peer": true
3235
  },
3236
  "node_modules/@smithy/abort-controller": {
3237
  "version": "4.2.4",
 
3844
  "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==",
3845
  "devOptional": true,
3846
  "license": "MIT",
3847
+ "peer": true,
3848
  "dependencies": {
3849
  "@sveltejs/acorn-typescript": "^1.0.5",
3850
  "@types/cookie": "^0.6.0",
 
3877
  "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==",
3878
  "devOptional": true,
3879
  "license": "MIT",
3880
+ "peer": true,
3881
  "dependencies": {
3882
  "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1",
3883
  "debug": "^4.4.1",
 
3917
  "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz",
3918
  "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==",
3919
  "license": "Apache-2.0",
 
3920
  "dependencies": {
3921
  "tslib": "^2.8.0"
3922
  }
 
3962
  "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.6.1.tgz",
3963
  "integrity": "sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==",
3964
  "license": "MIT",
 
3965
  "engines": {
3966
  "node": ">=12",
3967
  "npm": ">=6"
 
4007
  "version": "5.0.4",
4008
  "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
4009
  "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
4010
+ "license": "MIT"
 
4011
  },
4012
  "node_modules/@types/chai": {
4013
  "version": "5.2.2",
 
4236
  "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==",
4237
  "dev": true,
4238
  "license": "BSD-2-Clause",
4239
+ "peer": true,
4240
  "dependencies": {
4241
  "@typescript-eslint/scope-manager": "6.21.0",
4242
  "@typescript-eslint/types": "6.21.0",
 
4635
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz",
4636
  "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==",
4637
  "license": "MIT",
4638
+ "peer": true,
4639
  "bin": {
4640
  "acorn": "bin/acorn"
4641
  },
 
4819
  "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
4820
  "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
4821
  "license": "Apache-2.0",
 
4822
  "dependencies": {
4823
  "dequal": "^2.0.3"
4824
  }
 
5084
  }
5085
  ],
5086
  "license": "MIT",
5087
+ "peer": true,
5088
  "dependencies": {
5089
  "caniuse-lite": "^1.0.30001718",
5090
  "electron-to-chromium": "^1.5.160",
 
5754
  "version": "0.5.16",
5755
  "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
5756
  "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
5757
+ "license": "MIT"
 
5758
  },
5759
  "node_modules/domexception": {
5760
  "version": "4.0.0",
 
5828
  "resolved": "https://registry.npmjs.org/elysia/-/elysia-1.3.4.tgz",
5829
  "integrity": "sha512-kAfM3Zwovy3z255IZgTKVxBw91HbgKhYl3TqrGRdZqqr+Fd+4eKOfvxgaKij22+MZLczPzIHtscAmvfpI3+q/A==",
5830
  "license": "MIT",
5831
+ "peer": true,
5832
  "dependencies": {
5833
  "cookie": "^1.0.2",
5834
  "exact-mirror": "0.1.2",
 
6029
  "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
6030
  "dev": true,
6031
  "license": "MIT",
6032
+ "peer": true,
6033
  "dependencies": {
6034
  "@eslint-community/eslint-utils": "^4.2.0",
6035
  "@eslint-community/regexpp": "^4.6.1",
 
6667
  "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.0.0.tgz",
6668
  "integrity": "sha512-ek5xNX2YBYlXhiUXui3D/BXa3LdqPmoLJ7rqEx2bKJ7EAUEfmXgW0Das7Dc6Nr9MvqaOnIqiPV0mZk/r/UpNAg==",
6669
  "license": "MIT",
6670
+ "peer": true,
6671
  "dependencies": {
6672
  "@tokenizer/inflate": "^0.2.7",
6673
  "strtok3": "^10.2.2",
 
7789
  "version": "4.0.0",
7790
  "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
7791
  "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
7792
+ "license": "MIT"
 
7793
  },
7794
  "node_modules/js-yaml": {
7795
  "version": "4.1.0",
 
9561
  "integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
9562
  "devOptional": true,
9563
  "license": "Apache-2.0",
9564
+ "peer": true,
9565
  "dependencies": {
9566
  "playwright-core": "1.55.1"
9567
  },
 
9607
  }
9608
  ],
9609
  "license": "MIT",
9610
+ "peer": true,
9611
  "dependencies": {
9612
  "nanoid": "^3.3.11",
9613
  "picocolors": "^1.1.1",
 
9839
  "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
9840
  "dev": true,
9841
  "license": "MIT",
9842
+ "peer": true,
9843
  "bin": {
9844
  "prettier": "bin/prettier.cjs"
9845
  },
 
9856
  "integrity": "sha512-pn1ra/0mPObzqoIQn/vUTR3ZZI6UuZ0sHqMK5x2jMLGrs53h0sXhkVuDcrlssHwIMk7FYrMjHBPoUSyyEEDlBQ==",
9857
  "dev": true,
9858
  "license": "MIT",
9859
+ "peer": true,
9860
  "peerDependencies": {
9861
  "prettier": "^3.0.0",
9862
  "svelte": "^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0"
 
9946
  "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
9947
  "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
9948
  "license": "MIT",
 
9949
  "dependencies": {
9950
  "ansi-regex": "^5.0.1",
9951
  "ansi-styles": "^5.0.0",
 
9960
  "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
9961
  "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
9962
  "license": "MIT",
 
9963
  "engines": {
9964
  "node": ">=10"
9965
  },
 
10168
  "version": "17.0.2",
10169
  "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
10170
  "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
10171
+ "license": "MIT"
 
10172
  },
10173
  "node_modules/read-cache": {
10174
  "version": "1.0.0",
 
10332
  "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.1.tgz",
10333
  "integrity": "sha512-cPmwD3FnFv8rKMBc1MxWCwVQFxwf1JEmSX3iQXrRVVG15zerAIXRjMFVWnd5Q5QvgKF7Aj+5ykXFhUl+QGnyOw==",
10334
  "license": "MIT",
10335
+ "peer": true,
10336
  "dependencies": {
10337
  "@types/estree": "1.0.7"
10338
  },
 
11251
  "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.14.tgz",
11252
  "integrity": "sha512-kRlbhIlMTijbFmVDQFDeKXPLlX1/ovXwV0I162wRqQhRcygaqDIcu1d/Ese3H2uI+yt3uT8E7ndgDthQv5v5BA==",
11253
  "license": "MIT",
11254
+ "peer": true,
11255
  "dependencies": {
11256
  "@ampproject/remapping": "^2.3.0",
11257
  "@jridgewell/sourcemap-codec": "^1.5.0",
 
11391
  "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
11392
  "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
11393
  "license": "MIT",
11394
+ "peer": true,
11395
  "dependencies": {
11396
  "@alloc/quick-lru": "^5.2.0",
11397
  "arg": "^5.0.2",
 
11849
  "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
11850
  "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
11851
  "license": "Apache-2.0",
11852
+ "peer": true,
11853
  "bin": {
11854
  "tsc": "bin/tsc",
11855
  "tsserver": "bin/tsserver"
 
12085
  "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz",
12086
  "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==",
12087
  "license": "MIT",
12088
+ "peer": true,
12089
  "dependencies": {
12090
  "esbuild": "^0.25.0",
12091
  "fdir": "^6.4.4",
 
12221
  "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.2.tgz",
12222
  "integrity": "sha512-fyNn/Rp016Bt5qvY0OQvIUCwW2vnaEBLxP42PmKbNIoasSYjML+8xyeADOPvBe+Xfl/ubIw4og7Lt9jflRsCNw==",
12223
  "license": "MIT",
12224
+ "peer": true,
12225
  "dependencies": {
12226
  "@types/chai": "^5.2.2",
12227
  "@vitest/expect": "3.2.2",
 
12544
  "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.2.tgz",
12545
  "integrity": "sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==",
12546
  "license": "MIT",
12547
+ "peer": true,
12548
  "engines": {
12549
  "node": ">=10.0.0"
12550
  },
 
12667
  "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.55.tgz",
12668
  "integrity": "sha512-219huNnkSLQnLsQ3uaRjXsxMrVm5C9W3OOpEVt2k5tvMKuA8nBSu38e0B//a+he9Iq2dvmk2VyYVlHqiHa4YBA==",
12669
  "license": "MIT",
12670
+ "peer": true,
12671
  "funding": {
12672
  "url": "https://github.com/sponsors/colinhacks"
12673
  }
package.json CHANGED
@@ -22,6 +22,7 @@
22
  "@faker-js/faker": "^8.4.1",
23
  "@iconify-json/carbon": "^1.1.16",
24
  "@iconify-json/eos-icons": "^1.1.6",
 
25
  "@sveltejs/adapter-node": "^5.2.12",
26
  "@sveltejs/kit": "^2.21.1",
27
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
@@ -70,9 +71,10 @@
70
  "@elysiajs/swagger": "^1.3.0",
71
  "@huggingface/hub": "^2.2.0",
72
  "@huggingface/inference": "^4.11.3",
73
- "@modelcontextprotocol/sdk": "^1.21.1",
74
  "@iconify-json/bi": "^1.1.21",
 
75
  "@resvg/resvg-js": "^2.6.2",
 
76
  "autoprefixer": "^10.4.14",
77
  "aws4": "^1.13.2",
78
  "bits-ui": "^2.14.2",
 
22
  "@faker-js/faker": "^8.4.1",
23
  "@iconify-json/carbon": "^1.1.16",
24
  "@iconify-json/eos-icons": "^1.1.6",
25
+ "@iconify-json/lucide": "^1.2.77",
26
  "@sveltejs/adapter-node": "^5.2.12",
27
  "@sveltejs/kit": "^2.21.1",
28
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
 
71
  "@elysiajs/swagger": "^1.3.0",
72
  "@huggingface/hub": "^2.2.0",
73
  "@huggingface/inference": "^4.11.3",
 
74
  "@iconify-json/bi": "^1.1.21",
75
+ "@modelcontextprotocol/sdk": "^1.21.1",
76
  "@resvg/resvg-js": "^2.6.2",
77
+ "@sinclair/typebox": "^0.34.41",
78
  "autoprefixer": "^10.4.14",
79
  "aws4": "^1.13.2",
80
  "bits-ui": "^2.14.2",
src/lib/components/chat/ChatMessage.svelte CHANGED
@@ -300,7 +300,7 @@
300
  class="flex items-center gap-1 truncate rounded bg-gray-100 px-1 font-mono hover:text-gray-500 dark:bg-gray-800 dark:hover:text-gray-300 max-sm:hidden sm:py-px"
301
  >
302
  <img
303
- src="https://huggingface.co/api/organizations/{hubOrg}/avatar"
304
  alt="{message.routerMetadata.provider} logo"
305
  class="size-2.5 flex-none rounded-sm"
306
  onerror={(e) => ((e.currentTarget as HTMLImageElement).style.display = "none")}
 
300
  class="flex items-center gap-1 truncate rounded bg-gray-100 px-1 font-mono hover:text-gray-500 dark:bg-gray-800 dark:hover:text-gray-300 max-sm:hidden sm:py-px"
301
  >
302
  <img
303
+ src="https://huggingface.co/api/avatars/{hubOrg}"
304
  alt="{message.routerMetadata.provider} logo"
305
  class="size-2.5 flex-none rounded-sm"
306
  onerror={(e) => ((e.currentTarget as HTMLImageElement).style.display = "none")}
src/lib/components/chat/ChatWindow.svelte CHANGED
@@ -29,7 +29,7 @@
29
  import type { RouterFollowUp, RouterExample } from "$lib/constants/routerExamples";
30
  import { allBaseServersEnabled, mcpServersLoaded } from "$lib/stores/mcpServers";
31
  import { shareModal } from "$lib/stores/shareModal";
32
- import CarbonTools from "~icons/carbon/tools";
33
 
34
  import { fly } from "svelte/transition";
35
  import { cubicInOut } from "svelte/easing";
@@ -600,7 +600,7 @@
600
  {#if models.find((m) => m.id === currentModel.id)}
601
  {#if loading && streamingToolCallName}
602
  <span class="inline-flex items-center gap-1 whitespace-nowrap text-xs">
603
- <CarbonTools class="text-[11px]" />
604
  Calling tool
605
  <span class="loading-dots font-medium">
606
  {availableTools.find((t) => t.name === streamingToolCallName)?.displayName ??
 
29
  import type { RouterFollowUp, RouterExample } from "$lib/constants/routerExamples";
30
  import { allBaseServersEnabled, mcpServersLoaded } from "$lib/stores/mcpServers";
31
  import { shareModal } from "$lib/stores/shareModal";
32
+ import LucideHammer from "~icons/lucide/hammer";
33
 
34
  import { fly } from "svelte/transition";
35
  import { cubicInOut } from "svelte/easing";
 
600
  {#if models.find((m) => m.id === currentModel.id)}
601
  {#if loading && streamingToolCallName}
602
  <span class="inline-flex items-center gap-1 whitespace-nowrap text-xs">
603
+ <LucideHammer class="size-3" />
604
  Calling tool
605
  <span class="loading-dots font-medium">
606
  {availableTools.find((t) => t.name === streamingToolCallName)?.displayName ??
src/lib/components/chat/ToolUpdate.svelte CHANGED
@@ -5,7 +5,7 @@
5
  isMessageToolErrorUpdate,
6
  isMessageToolResultUpdate,
7
  } from "$lib/utils/messageUpdates";
8
- import CarbonTools from "~icons/carbon/tools";
9
  import { ToolResultStatus, type ToolFront } from "$lib/types/Tool";
10
  import { page } from "$app/state";
11
  import { onDestroy } from "svelte";
@@ -165,7 +165,7 @@
165
  id="shape"
166
  />
167
  </svg>
168
- <CarbonTools class="text-xs text-purple-700 dark:text-purple-500" />
169
  </div>
170
 
171
  <span class="relative">
 
5
  isMessageToolErrorUpdate,
6
  isMessageToolResultUpdate,
7
  } from "$lib/utils/messageUpdates";
8
+ import LucideHammer from "~icons/lucide/hammer";
9
  import { ToolResultStatus, type ToolFront } from "$lib/types/Tool";
10
  import { page } from "$app/state";
11
  import { onDestroy } from "svelte";
 
165
  id="shape"
166
  />
167
  </svg>
168
+ <LucideHammer class="size-3.5 text-purple-700 dark:text-purple-500" />
169
  </div>
170
 
171
  <span class="relative">
src/lib/components/mcp/MCPServerManager.svelte CHANGED
@@ -14,7 +14,7 @@
14
  import type { KeyValuePair } from "$lib/types/Tool";
15
  import IconAddLarge from "~icons/carbon/add-large";
16
  import IconRefresh from "~icons/carbon/renew";
17
- import IconTools from "~icons/carbon/tools";
18
  import IconMCP from "$lib/components/icons/IconMCP.svelte";
19
 
20
  const publicConfig = usePublicConfig();
@@ -143,7 +143,7 @@
143
  <div
144
  class="flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 p-8 dark:border-gray-700"
145
  >
146
- <IconTools class="mb-3 size-12 text-gray-400" />
147
  <p class="mb-1 text-sm font-medium text-gray-900 dark:text-gray-100">
148
  No custom servers yet
149
  </p>
 
14
  import type { KeyValuePair } from "$lib/types/Tool";
15
  import IconAddLarge from "~icons/carbon/add-large";
16
  import IconRefresh from "~icons/carbon/renew";
17
+ import LucideHammer from "~icons/lucide/hammer";
18
  import IconMCP from "$lib/components/icons/IconMCP.svelte";
19
 
20
  const publicConfig = usePublicConfig();
 
143
  <div
144
  class="flex flex-col items-center justify-center rounded-lg border-2 border-dashed border-gray-300 p-8 dark:border-gray-700"
145
  >
146
+ <LucideHammer class="mb-3 size-12 text-gray-400" />
147
  <p class="mb-1 text-sm font-medium text-gray-900 dark:text-gray-100">
148
  No custom servers yet
149
  </p>
src/lib/components/mcp/ServerCard.svelte CHANGED
@@ -6,7 +6,7 @@
6
  import IconPending from "~icons/carbon/pending-filled";
7
  import IconRefresh from "~icons/carbon/renew";
8
  import IconTrash from "~icons/carbon/trash-can";
9
- import IconTools from "~icons/carbon/tools";
10
  import IconSettings from "~icons/carbon/settings";
11
  import Switch from "$lib/components/Switch.svelte";
12
  import { getMcpServerFaviconUrl } from "$lib/utils/favicon";
@@ -127,7 +127,7 @@
127
 
128
  {#if server.tools && server.tools.length > 0}
129
  <span class="inline-flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400">
130
- <IconTools class="size-3" />
131
  {server.tools.length}
132
  {server.tools.length === 1 ? "tool" : "tools"}
133
  </span>
 
6
  import IconPending from "~icons/carbon/pending-filled";
7
  import IconRefresh from "~icons/carbon/renew";
8
  import IconTrash from "~icons/carbon/trash-can";
9
+ import LucideHammer from "~icons/lucide/hammer";
10
  import IconSettings from "~icons/carbon/settings";
11
  import Switch from "$lib/components/Switch.svelte";
12
  import { getMcpServerFaviconUrl } from "$lib/utils/favicon";
 
127
 
128
  {#if server.tools && server.tools.length > 0}
129
  <span class="inline-flex items-center gap-1 text-xs text-gray-600 dark:text-gray-400">
130
+ <LucideHammer class="size-3" />
131
  {server.tools.length}
132
  {server.tools.length === 1 ? "tool" : "tools"}
133
  </span>
src/lib/server/models.ts CHANGED
@@ -336,7 +336,7 @@ const buildModels = async (): Promise<ProcessedModel[]> => {
336
  let logoUrl: string | undefined = undefined;
337
  if (isHFRouter && m.id.includes("/")) {
338
  const org = m.id.split("/")[0];
339
- logoUrl = `https://huggingface.co/api/organizations/${encodeURIComponent(org)}/avatar?redirect=true`;
340
  }
341
 
342
  const inputModalities = (m.architecture?.input_modalities ?? []).map((modality) =>
 
336
  let logoUrl: string | undefined = undefined;
337
  if (isHFRouter && m.id.includes("/")) {
338
  const org = m.id.split("/")[0];
339
+ logoUrl = `https://huggingface.co/api/avatars/${encodeURIComponent(org)}`;
340
  }
341
 
342
  const inputModalities = (m.architecture?.input_modalities ?? []).map((modality) =>
src/routes/models/+page.svelte CHANGED
@@ -6,9 +6,9 @@
6
  import { page } from "$app/state";
7
 
8
  import CarbonHelpFilled from "~icons/carbon/help-filled";
9
- import CarbonView from "~icons/carbon/view";
10
- import CarbonTools from "~icons/carbon/tools";
11
- import CarbonSettings from "~icons/carbon/settings";
12
  import { useSettingsStore } from "$lib/stores/settings";
13
  import { goto } from "$app/navigation";
14
  interface Props {
@@ -25,6 +25,16 @@
25
  let modelFilter = $state("");
26
  const normalize = (s: string) => s.toLowerCase().replace(/[^a-z0-9]+/g, " ");
27
  let queryTokens = $derived(normalize(modelFilter).trim().split(/\s+/).filter(Boolean));
 
 
 
 
 
 
 
 
 
 
28
  </script>
29
 
30
  <svelte:head>
@@ -71,119 +81,108 @@
71
  placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-300
72
  dark:border-gray-700 dark:bg-gray-900 dark:focus:ring-gray-700"
73
  />
74
- <div class="mt-6 grid grid-cols-1 gap-3 sm:gap-5 xl:grid-cols-2">
75
- {#each data.models
76
- .filter((el) => !el.unlisted)
77
- .filter((el) => {
78
- const haystack = normalize(`${el.id} ${el.name ?? ""} ${el.displayName ?? ""}`);
79
- return queryTokens.every((q) => haystack.includes(q));
80
- }) as model, index (model.id)}
81
- <a
82
- href="{base}/models/{model.id}"
83
- aria-label="Model card"
84
- class="relative flex flex-col gap-2 overflow-hidden rounded-xl border bg-gray-50/50 px-6 py-5 shadow hover:bg-gray-50 hover:shadow-inner dark:border-gray-800/70 dark:bg-gray-950/20 dark:hover:bg-gray-950/40"
85
- class:omni-gradient={model.isRouter}
86
- class:active-model={model.id === $settings.activeModel}
87
- >
88
- <div class="flex items-center justify-between gap-1">
89
- {#if model.logoUrl}
90
- <img
91
- class="aspect-square size-6 rounded border bg-white dark:border-gray-700"
92
- src={model.logoUrl}
93
- alt=""
94
- />
95
- {:else}
96
- <div
97
- class="size-6 rounded border border-transparent bg-gray-300 dark:bg-gray-800"
98
- aria-hidden="true"
99
- ></div>
100
- {/if}
101
- <div class="flex items-center gap-1">
102
- {#if $settings.toolsOverrides?.[model.id] ?? (model as { supportsTools?: boolean }).supportsTools}
103
- <span
104
- title="This model supports tool calling (functions)."
105
- class="background ml-auto flex size-[21px] items-center justify-center rounded-lg bg-purple-500/10 text-purple-600 dark:text-purple-500"
106
- aria-label="Model supports tools"
107
- role="img"
108
- >
109
- <CarbonTools class="text-xxs" />
110
- </span>
111
  {/if}
112
- {#if $settings.multimodalOverrides?.[model.id] ?? model.multimodal}
113
- <span
114
- title="This model is multimodal and supports image inputs natively."
115
- class="flex size-[21px] items-center justify-center rounded-lg bg-blue-500/10 text-blue-600 dark:text-blue-500"
116
- aria-label="Model is multimodal"
117
- role="img"
 
 
 
118
  >
119
- <CarbonView class="text-xxs" />
120
- </span>
121
- {/if}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
122
  <button
123
  type="button"
124
  title="Model settings"
125
  aria-label="Model settings for {model.displayName}"
126
- class="flex size-[21px] items-center justify-center rounded-md border border-gray-300 text-xs text-gray-600 hover:bg-gray-100 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700"
127
  onclick={(e) => {
128
  e.preventDefault();
129
  e.stopPropagation();
130
  goto(`${base}/settings/${model.id}`);
131
  }}
132
  >
133
- <CarbonSettings class="text-xs" />
134
  </button>
135
- {#if model.id === $settings.activeModel}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  <span
137
- class="rounded-full bg-black px-2 py-0.5 text-xs text-white dark:bg-white dark:text-black"
138
  >
139
  Active
140
  </span>
141
- {:else if index === 0 && model.id === "omni"}
142
- <span
143
- class="rounded-full border border-gray-300 px-2 py-0.5 text-xs text-gray-500 dark:border-gray-500 dark:text-gray-400"
144
- >
145
- Default
146
- </span>
147
  {/if}
148
  </div>
149
- </div>
150
- <span class="flex items-center gap-2 font-semibold">
151
- {model.displayName}
152
- </span>
153
- <span class="line-clamp-4 whitespace-pre-wrap text-sm text-gray-500 dark:text-gray-400">
154
- {model.isRouter
155
- ? "Routes your messages to the best model for your request."
156
- : model.description || "-"}
157
- </span>
158
- </a>
159
- {/each}
160
  </div>
161
  </div>
162
  </div>
163
-
164
- <style>
165
- /* Subtle highlight for the router (Omni) tile */
166
- .omni-gradient {
167
- /* layered gradients to keep readable on both themes */
168
- background-image:
169
- radial-gradient(900px 300px at -10% -20%, rgba(59, 130, 246, 0.16), transparent 60%),
170
- radial-gradient(700px 240px at 110% 120%, rgba(16, 185, 129, 0.16), transparent 60%),
171
- linear-gradient(135deg, rgba(236, 72, 153, 0.1), rgba(59, 130, 246, 0.08));
172
- box-shadow:
173
- inset 0 1px 0 rgba(255, 255, 255, 0.06),
174
- 0 6px 18px rgba(59, 130, 246, 0.12),
175
- 0 2px 8px rgba(236, 72, 153, 0.1);
176
- }
177
-
178
- :global(.dark) .omni-gradient {
179
- background-image:
180
- radial-gradient(900px 300px at -10% -20%, rgba(59, 130, 246, 0.12), transparent 60%),
181
- radial-gradient(700px 240px at 110% 120%, rgba(16, 185, 129, 0.12), transparent 60%),
182
- linear-gradient(135deg, rgba(236, 72, 153, 0.08), rgba(59, 130, 246, 0.06));
183
- box-shadow:
184
- inset 0 1px 0 rgba(255, 255, 255, 0.04),
185
- 0 10px 28px rgba(0, 0, 0, 0.25);
186
- }
187
-
188
- /* Active border handled via Tailwind utilities (see .active-model in src/styles/main.css) */
189
- </style>
 
6
  import { page } from "$app/state";
7
 
8
  import CarbonHelpFilled from "~icons/carbon/help-filled";
9
+ import LucideHammer from "~icons/lucide/hammer";
10
+ import LucideImage from "~icons/lucide/image";
11
+ import LucideSettings from "~icons/lucide/settings";
12
  import { useSettingsStore } from "$lib/stores/settings";
13
  import { goto } from "$app/navigation";
14
  interface Props {
 
25
  let modelFilter = $state("");
26
  const normalize = (s: string) => s.toLowerCase().replace(/[^a-z0-9]+/g, " ");
27
  let queryTokens = $derived(normalize(modelFilter).trim().split(/\s+/).filter(Boolean));
28
+
29
+ // Filtered models list
30
+ let filteredModels = $derived(
31
+ data.models
32
+ .filter((el) => !el.unlisted)
33
+ .filter((el) => {
34
+ const haystack = normalize(`${el.id} ${el.name ?? ""} ${el.displayName ?? ""}`);
35
+ return queryTokens.every((q) => haystack.includes(q));
36
+ })
37
+ );
38
  </script>
39
 
40
  <svelte:head>
 
81
  placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-300
82
  dark:border-gray-700 dark:bg-gray-900 dark:focus:ring-gray-700"
83
  />
84
+
85
+ <div class="mt-6 min-h-[50vh]">
86
+ <div
87
+ class="overflow-hidden rounded-2xl border border-gray-200/60 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900"
88
+ >
89
+ {#each filteredModels as model, index (model.id)}
90
+ {@const isActive = model.id === $settings.activeModel}
91
+ {@const isLast = index === filteredModels.length - 1}
92
+ <a
93
+ href="{base}/models/{model.id}"
94
+ aria-label="Model card for {model.displayName}"
95
+ class="group flex cursor-pointer items-center gap-4 p-4
96
+ {isActive
97
+ ? 'bg-gray-50 dark:bg-gray-800'
98
+ : 'bg-white hover:bg-gray-50 dark:bg-gray-900 dark:hover:bg-gray-800'}
99
+ {isLast ? '' : 'border-b border-gray-100 dark:border-gray-800'}"
100
+ >
101
+ <!-- Avatar -->
102
+ <div class="flex-shrink-0">
103
+ {#if model.logoUrl}
104
+ <img
105
+ alt={model.displayName}
106
+ class="h-10 w-10 rounded-lg border border-gray-100 bg-gray-50 object-cover dark:border-gray-700 dark:bg-gray-100"
107
+ src={model.logoUrl}
108
+ />
109
+ {:else}
110
+ <div
111
+ class="h-10 w-10 rounded-lg border border-gray-100 bg-gray-200 dark:border-gray-700 dark:bg-gray-700"
112
+ aria-hidden="true"
113
+ ></div>
 
 
 
 
 
 
 
114
  {/if}
115
+ </div>
116
+
117
+ <!-- Content -->
118
+ <div class="min-w-0 flex-1">
119
+ <div class="flex items-center gap-2">
120
+ <h3
121
+ class="truncate font-medium text-gray-900 dark:text-gray-200"
122
+ class:font-bold={isActive}
123
+ class:dark:text-white={isActive}
124
  >
125
+ {model.displayName}
126
+ </h3>
127
+ {#if index === 0 && model.isRouter && !isActive}
128
+ <span
129
+ class="rounded border border-gray-200 px-1.5 py-0.5 text-[10px] font-semibold uppercase text-gray-500 dark:border-gray-700 dark:text-gray-400"
130
+ >
131
+ Default
132
+ </span>
133
+ {/if}
134
+ </div>
135
+ <p class="truncate pr-4 text-[13px] text-gray-500 dark:text-gray-400">
136
+ {model.isRouter
137
+ ? "Routes your messages to the best model for your request."
138
+ : model.description || "-"}
139
+ </p>
140
+ </div>
141
+
142
+ <!-- Icons and badges -->
143
+ <div class="flex flex-shrink-0 items-center gap-1.5">
144
  <button
145
  type="button"
146
  title="Model settings"
147
  aria-label="Model settings for {model.displayName}"
148
+ class="rounded-md border border-gray-200 p-1.5 text-gray-500 hover:bg-gray-100 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700"
149
  onclick={(e) => {
150
  e.preventDefault();
151
  e.stopPropagation();
152
  goto(`${base}/settings/${model.id}`);
153
  }}
154
  >
155
+ <LucideSettings class="h-3.5 w-3.5" />
156
  </button>
157
+ <div class="flex items-center gap-1.5">
158
+ {#if $settings.toolsOverrides?.[model.id] ?? (model as { supportsTools?: boolean }).supportsTools}
159
+ <div
160
+ title="This model supports tool calling (functions)."
161
+ class="rounded-md bg-purple-50 p-1.5 text-purple-600 dark:bg-purple-900/20 dark:text-purple-400"
162
+ >
163
+ <LucideHammer class="h-3.5 w-3.5" />
164
+ </div>
165
+ {/if}
166
+ {#if $settings.multimodalOverrides?.[model.id] ?? model.multimodal}
167
+ <div
168
+ title="This model is multimodal and supports image inputs natively."
169
+ class="rounded-md bg-blue-50 p-1.5 text-blue-600 dark:bg-blue-900/20 dark:text-blue-400"
170
+ >
171
+ <LucideImage class="h-3.5 w-3.5" />
172
+ </div>
173
+ {/if}
174
+ </div>
175
+ {#if isActive}
176
  <span
177
+ class="rounded-full bg-black px-2.5 py-1 text-xs font-bold text-white shadow-md dark:bg-white dark:text-black"
178
  >
179
  Active
180
  </span>
 
 
 
 
 
 
181
  {/if}
182
  </div>
183
+ </a>
184
+ {/each}
185
+ </div>
 
 
 
 
 
 
 
 
186
  </div>
187
  </div>
188
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
src/routes/settings/(nav)/+layout.svelte CHANGED
@@ -8,8 +8,8 @@
8
  import CarbonClose from "~icons/carbon/close";
9
  import CarbonTextLongParagraph from "~icons/carbon/text-long-paragraph";
10
  import CarbonChevronLeft from "~icons/carbon/chevron-left";
11
- import CarbonView from "~icons/carbon/view";
12
- import CarbonTools from "~icons/carbon/tools";
13
  import IconGear from "~icons/bi/gear-fill";
14
 
15
  import type { LayoutData } from "../$types";
@@ -181,7 +181,7 @@
181
  aria-label="Model supports tools"
182
  role="img"
183
  >
184
- <CarbonTools class="text-xxs" />
185
  </span>
186
  {/if}
187
 
@@ -192,7 +192,7 @@
192
  aria-label="Model is multimodal"
193
  role="img"
194
  >
195
- <CarbonView class="text-xxs" />
196
  </span>
197
  {/if}
198
 
 
8
  import CarbonClose from "~icons/carbon/close";
9
  import CarbonTextLongParagraph from "~icons/carbon/text-long-paragraph";
10
  import CarbonChevronLeft from "~icons/carbon/chevron-left";
11
+ import LucideImage from "~icons/lucide/image";
12
+ import LucideHammer from "~icons/lucide/hammer";
13
  import IconGear from "~icons/bi/gear-fill";
14
 
15
  import type { LayoutData } from "../$types";
 
181
  aria-label="Model supports tools"
182
  role="img"
183
  >
184
+ <LucideHammer class="size-3" />
185
  </span>
186
  {/if}
187
 
 
192
  aria-label="Model is multimodal"
193
  role="img"
194
  >
195
+ <LucideImage class="size-3" />
196
  </span>
197
  {/if}
198
 
src/routes/settings/(nav)/[...model]/+page.svelte CHANGED
@@ -192,7 +192,7 @@
192
  classNames="inline-flex items-center rounded-full border border-gray-200 px-2.5 py-1 text-sm hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700/60"
193
  >
194
  <div class="flex items-center gap-1.5">
195
- <CarbonCopy class="shrink-0 text-xs" />Copy new chat link
196
  </div>
197
  </CopyToClipBoardBtn>
198
  {/if}
@@ -305,7 +305,7 @@
305
  >
306
  {#if hubOrg}
307
  <img
308
- src="https://huggingface.co/api/organizations/{hubOrg}/avatar"
309
  alt="{prov.provider} logo"
310
  class="size-2.5 flex-none rounded-sm"
311
  onerror={(e) => ((e.currentTarget as HTMLImageElement).style.display = "none")}
 
192
  classNames="inline-flex items-center rounded-full border border-gray-200 px-2.5 py-1 text-sm hover:bg-gray-50 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-700/60"
193
  >
194
  <div class="flex items-center gap-1.5">
195
+ <CarbonCopy class="shrink-0 text-xs" />Copy direct link
196
  </div>
197
  </CopyToClipBoardBtn>
198
  {/if}
 
305
  >
306
  {#if hubOrg}
307
  <img
308
+ src="https://huggingface.co/api/avatars/{hubOrg}"
309
  alt="{prov.provider} logo"
310
  class="size-2.5 flex-none rounded-sm"
311
  onerror={(e) => ((e.currentTarget as HTMLImageElement).style.display = "none")}