From 33b19ba98bdda1ce44de470470faac135a47889e Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 22:28:48 +0100
Subject: [PATCH 01/10] better model naming
---
routstr/upstreams/ollama.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/routstr/upstreams/ollama.py b/routstr/upstreams/ollama.py
index e999e221..5414434e 100644
--- a/routstr/upstreams/ollama.py
+++ b/routstr/upstreams/ollama.py
@@ -121,7 +121,7 @@ class OllamaUpstreamProvider(UpstreamProvider):
models_list.append(
Model(
id=model_name,
- name=model_name,
+ name=model_name.replace(':', ' '),
created=0,
description=description,
context_length=context_length,
From b8a1d699246d1554fe452887bdd8cff3653ef846 Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 22:45:07 +0100
Subject: [PATCH 02/10] fmt
---
routstr/upstreams/ollama.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/routstr/upstreams/ollama.py b/routstr/upstreams/ollama.py
index 5414434e..117b95a7 100644
--- a/routstr/upstreams/ollama.py
+++ b/routstr/upstreams/ollama.py
@@ -121,7 +121,7 @@ class OllamaUpstreamProvider(UpstreamProvider):
models_list.append(
Model(
id=model_name,
- name=model_name.replace(':', ' '),
+ name=model_name.replace(":", " "),
created=0,
description=description,
context_length=context_length,
From 1e90b223cf7f29bbc358739117ddd4f82eee9b56 Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 22:45:18 +0100
Subject: [PATCH 03/10] fix model filter
---
routstr/proxy.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/routstr/proxy.py b/routstr/proxy.py
index 7c63de49..8eece67b 100644
--- a/routstr/proxy.py
+++ b/routstr/proxy.py
@@ -83,9 +83,7 @@ async def refresh_model_maps() -> None:
# Gather database overrides and disabled models
async with create_session() as session:
- result = await session.exec(
- select(ModelRow).where(col(ModelRow.enabled).is_(True))
- )
+ result = await session.exec(select(ModelRow).where(ModelRow.enabled == True))
override_rows = result.all()
provider_result = await session.exec(select(UpstreamProviderRow))
@@ -103,7 +101,7 @@ async def refresh_model_maps() -> None:
}
disabled_result = await session.exec(
- select(ModelRow.id).where(col(ModelRow.enabled).is_(False))
+ select(ModelRow.id).where(ModelRow.enabled == False)
)
disabled_model_ids = {row for row in disabled_result.all()}
From ded82cd729ba9c01ee214f343dec8953bab89095 Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 23:16:08 +0100
Subject: [PATCH 04/10] fix model endpoint & filter query
---
routstr/proxy.py | 5 +++--
scripts/build-ui.sh | 1 +
ui/components/ModelSelector.tsx | 12 ++++--------
3 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/routstr/proxy.py b/routstr/proxy.py
index 8eece67b..914d20bd 100644
--- a/routstr/proxy.py
+++ b/routstr/proxy.py
@@ -3,7 +3,7 @@ from typing import Any
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import Response, StreamingResponse
-from sqlmodel import col, select
+from sqlmodel import select
from .algorithm import create_model_mappings
from .auth import pay_for_request, revert_pay_for_request, validate_bearer_key
@@ -101,9 +101,10 @@ async def refresh_model_maps() -> None:
}
disabled_result = await session.exec(
- select(ModelRow.id).where(ModelRow.enabled == False)
+ select(ModelRow.id).where(~ModelRow.enabled)
)
disabled_model_ids = {row for row in disabled_result.all()}
+ print(disabled_model_ids)
_model_instances, _provider_map, _unique_models = create_model_mappings(
upstreams=_upstreams,
diff --git a/scripts/build-ui.sh b/scripts/build-ui.sh
index 557c26db..7a235f01 100755
--- a/scripts/build-ui.sh
+++ b/scripts/build-ui.sh
@@ -49,6 +49,7 @@ else
npm run build
fi
+rm -rf ../ui_out
mkdir -p ../ui_out
mv out/* ../ui_out
diff --git a/ui/components/ModelSelector.tsx b/ui/components/ModelSelector.tsx
index 5b03e350..1a9a2814 100644
--- a/ui/components/ModelSelector.tsx
+++ b/ui/components/ModelSelector.tsx
@@ -387,14 +387,10 @@ export function ModelSelector({
providerIdNum,
model.id
);
- await AdminService.updateProviderModel(
- providerIdNum,
- model.full_name,
- {
- ...existingModel,
- enabled: true,
- }
- );
+ await AdminService.updateProviderModel(providerIdNum, model.id, {
+ ...existingModel,
+ enabled: true,
+ });
totalEnabled++;
} catch (error) {
console.error(`Failed to enable model ${model.full_name}:`, error);
From 88fbefbd183257e52b58a33f393b4d058b7672b8 Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 23:28:09 +0100
Subject: [PATCH 05/10] fmt
---
routstr/payment/models.py | 2 --
routstr/proxy.py | 5 ++---
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/routstr/payment/models.py b/routstr/payment/models.py
index 61955035..c240b856 100644
--- a/routstr/payment/models.py
+++ b/routstr/payment/models.py
@@ -577,7 +577,6 @@ async def _cleanup_enabled_models_once() -> None:
for db_model in db_models:
# Find corresponding upstream model
- print(db_model.id)
upstream_model = None
for upstream in upstreams:
upstream_model = upstream.get_cached_model_by_id(db_model.id)
@@ -628,7 +627,6 @@ def _pricing_matches(
for key in keys_to_compare:
db_val = float(db_pricing.get(key, 0.0)) * 1000000
upstream_val = float(upstream_pricing.get(key, 0.0)) * 1000000
- print(db_val - upstream_val)
if abs(db_val - upstream_val) > tolerance:
return False
diff --git a/routstr/proxy.py b/routstr/proxy.py
index 914d20bd..7da56b42 100644
--- a/routstr/proxy.py
+++ b/routstr/proxy.py
@@ -3,7 +3,7 @@ from typing import Any
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import Response, StreamingResponse
-from sqlmodel import select
+from sqlmodel import select
from .algorithm import create_model_mappings
from .auth import pay_for_request, revert_pay_for_request, validate_bearer_key
@@ -83,7 +83,7 @@ async def refresh_model_maps() -> None:
# Gather database overrides and disabled models
async with create_session() as session:
- result = await session.exec(select(ModelRow).where(ModelRow.enabled == True))
+ result = await session.exec(select(ModelRow).where(ModelRow.enabled))
override_rows = result.all()
provider_result = await session.exec(select(UpstreamProviderRow))
@@ -104,7 +104,6 @@ async def refresh_model_maps() -> None:
select(ModelRow.id).where(~ModelRow.enabled)
)
disabled_model_ids = {row for row in disabled_result.all()}
- print(disabled_model_ids)
_model_instances, _provider_map, _unique_models = create_model_mappings(
upstreams=_upstreams,
From f5c9cde85282a679bd8af41a8bf3b175078a00c1 Mon Sep 17 00:00:00 2001
From: 9qeklajc <9qeklajc>
Date: Tue, 4 Nov 2025 23:46:38 +0100
Subject: [PATCH 06/10] clean up
---
ui/app/layout.tsx | 2 +-
ui/app/model/page.tsx | 6 +-
ui/app/providers/page.tsx | 96 ++++++++++++++---------
ui/components/ModelSelector.tsx | 18 +++--
ui/components/detailed-wallet-balance.tsx | 8 +-
ui/components/temporary-balances.tsx | 13 ++-
ui/lib/currency.ts | 1 -
ui/lib/exchange-rate.ts | 1 -
ui/lib/types/units.ts | 1 -
9 files changed, 85 insertions(+), 61 deletions(-)
diff --git a/ui/app/layout.tsx b/ui/app/layout.tsx
index 1eff9d1c..6c087695 100644
--- a/ui/app/layout.tsx
+++ b/ui/app/layout.tsx
@@ -34,7 +34,7 @@ export default function RootLayout({
return (
{children}
diff --git a/ui/app/model/page.tsx b/ui/app/model/page.tsx
index cc13cb7a..6382b53f 100644
--- a/ui/app/model/page.tsx
+++ b/ui/app/model/page.tsx
@@ -156,7 +156,10 @@ export default function ModelsPage() {
models={models}
onFilteredModelsChange={setFilteredModels}
/>
-
+
@@ -199,6 +202,7 @@ export default function ModelsPage() {
filterProvider={provider}
groupData={groupData}
showProviderActions={true}
+ showDeleteAllButton={false}
/>
diff --git a/ui/app/providers/page.tsx b/ui/app/providers/page.tsx
index 49411bb0..53ca72c4 100644
--- a/ui/app/providers/page.tsx
+++ b/ui/app/providers/page.tsx
@@ -277,7 +277,11 @@ export default function ProvidersPage() {
}
placeholder='https://api.example.com/v1'
disabled={hasFixedBaseUrl(formData.provider_type)}
- className={hasFixedBaseUrl(formData.provider_type) ? 'cursor-not-allowed opacity-60' : ''}
+ className={
+ hasFixedBaseUrl(formData.provider_type)
+ ? 'cursor-not-allowed opacity-60'
+ : ''
+ }
/>
@@ -453,7 +457,8 @@ export default function ProvidersPage() {
{providerModels.db_models.length === 0 ? (
- No models configured. Add custom models to use this provider.
+ No models configured. Add custom models to
+ use this provider.
) : (
@@ -495,7 +500,10 @@ export default function ProvidersPage() {
) : (
// Has provided models - show tabs
-
+
Provided Models
- Provided
+
+ Provided
+
{providerModels.db_models.length > 0 && (
- Custom models override or extend the provider's catalog.
+ Custom models override or extend the
+ provider's catalog.
)}
{providerModels.db_models.length === 0 ? (
@@ -543,39 +554,42 @@ export default function ProvidersPage() {
) : (
- {providerModels.db_models.map((model) => (
-
-
-
-
- {model.id}
-
-
- {model.enabled
- ? 'Enabled'
- : 'Disabled'}
-
+ {providerModels.db_models.map(
+ (model) => (
+
+
+
+
+ {model.id}
+
+
+ {model.enabled
+ ? 'Enabled'
+ : 'Disabled'}
+
+
+
+ {model.description ||
+ model.name}
+
-
- {model.description || model.name}
+
+ {model.context_length?.toLocaleString()}{' '}
+ tokens
-
- {model.context_length?.toLocaleString()}{' '}
- tokens
-
-
- ))}
+ )
+ )}
)}
@@ -583,9 +597,11 @@ export default function ProvidersPage() {
value='provided'
className='mt-4 space-y-2'
>
- {providerModels.remote_models.length > 0 && (
+ {providerModels.remote_models.length >
+ 0 && (
- Models automatically discovered from the provider's catalog.
+ Models automatically discovered from the
+ provider's catalog.
)}
@@ -670,7 +686,11 @@ export default function ProvidersPage() {
}
placeholder='https://api.example.com/v1'
disabled={hasFixedBaseUrl(formData.provider_type)}
- className={hasFixedBaseUrl(formData.provider_type) ? 'cursor-not-allowed opacity-60' : ''}
+ className={
+ hasFixedBaseUrl(formData.provider_type)
+ ? 'cursor-not-allowed opacity-60'
+ : ''
+ }
/>
diff --git a/ui/components/ModelSelector.tsx b/ui/components/ModelSelector.tsx
index 1a9a2814..7f7e24a9 100644
--- a/ui/components/ModelSelector.tsx
+++ b/ui/components/ModelSelector.tsx
@@ -65,12 +65,14 @@ interface ModelSelectorProps {
groupData?: ModelGroup;
showProviderActions?: boolean;
filteredModels?: Model[];
+ showDeleteAllButton?: boolean;
}
export function ModelSelector({
filterProvider,
groupData,
filteredModels: propFilteredModels,
+ showDeleteAllButton = false,
}: ModelSelectorProps) {
const [selectedModelId, setSelectedModelId] = useState
('');
const [, setHoveredModelId] = useState(null);
@@ -824,13 +826,15 @@ export function ModelSelector({
Deselect All
-
+ {showDeleteAllButton && (
+
+ )}
{/* Model Management Actions