From 0da08fb94593ecf7910b6bf23f6e7d6bf8200ab8 Mon Sep 17 00:00:00 2001 From: Shroominic Date: Mon, 20 Oct 2025 12:45:02 +0800 Subject: [PATCH] refactor pricing, provider fees, realtime model map updates --- .../a1a1a1a1a1a1_composite_pk_for_models.py | 64 +++ ...b9c0d1e2_add_fees_to_upstream_providers.py | 27 + routstr/core/admin.py | 498 +++++++++++++----- routstr/core/db.py | 16 +- routstr/core/main.py | 12 +- routstr/payment/cost_caculation.py | 7 +- routstr/payment/helpers.py | 14 +- routstr/payment/models.py | 304 +++++------ routstr/payment/price.py | 95 ++-- routstr/proxy.py | 66 ++- routstr/upstream.py | 175 ++++-- 11 files changed, 854 insertions(+), 424 deletions(-) create mode 100644 migrations/versions/a1a1a1a1a1a1_composite_pk_for_models.py create mode 100644 migrations/versions/f7a8b9c0d1e2_add_fees_to_upstream_providers.py diff --git a/migrations/versions/a1a1a1a1a1a1_composite_pk_for_models.py b/migrations/versions/a1a1a1a1a1a1_composite_pk_for_models.py new file mode 100644 index 00000000..0cbafc26 --- /dev/null +++ b/migrations/versions/a1a1a1a1a1a1_composite_pk_for_models.py @@ -0,0 +1,64 @@ +"""change models to composite primary key (id, upstream_provider_id) + +Revision ID: a1a1a1a1a1a1 +Revises: f7a8b9c0d1e2 +Create Date: 2025-10-20 00:00:00.000000 +""" + +from __future__ import annotations + +import sqlalchemy as sa +from alembic import op + +revision = "a1a1a1a1a1a1" +down_revision = "f7a8b9c0d1e2" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + conn = op.get_bind() + inspector = sa.inspect(conn) + + if "models" in inspector.get_table_names(): + op.drop_table("models") + + op.create_table( + "models", + sa.Column("id", sa.String(), nullable=False), + sa.Column("upstream_provider_id", sa.Integer(), nullable=False), + sa.Column("name", sa.String(), nullable=False), + sa.Column("created", sa.Integer(), nullable=False), + sa.Column("description", sa.Text(), nullable=False), + sa.Column("context_length", sa.Integer(), nullable=False), + sa.Column("architecture", sa.Text(), nullable=False), + sa.Column("pricing", sa.Text(), nullable=False), + sa.Column("sats_pricing", sa.Text(), nullable=True), + sa.Column("per_request_limits", sa.Text(), nullable=True), + sa.Column("top_provider", sa.Text(), nullable=True), + sa.Column("enabled", sa.Boolean(), nullable=False, server_default="1"), + sa.PrimaryKeyConstraint("id", "upstream_provider_id"), + sa.ForeignKeyConstraint( + ["upstream_provider_id"], ["upstream_providers.id"], ondelete="CASCADE" + ), + ) + + +def downgrade() -> None: + op.drop_table("models") + op.create_table( + "models", + sa.Column("id", sa.String(), primary_key=True, nullable=False), + sa.Column("name", sa.String(), nullable=False), + sa.Column("created", sa.Integer(), nullable=False), + sa.Column("description", sa.Text(), nullable=False), + sa.Column("context_length", sa.Integer(), nullable=False), + sa.Column("architecture", sa.Text(), nullable=False), + sa.Column("pricing", sa.Text(), nullable=False), + sa.Column("sats_pricing", sa.Text(), nullable=True), + sa.Column("per_request_limits", sa.Text(), nullable=True), + sa.Column("top_provider", sa.Text(), nullable=True), + sa.Column("enabled", sa.Boolean(), nullable=False, server_default="1"), + sa.Column("upstream_provider_id", sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(["upstream_provider_id"], ["upstream_providers.id"]), + ) diff --git a/migrations/versions/f7a8b9c0d1e2_add_fees_to_upstream_providers.py b/migrations/versions/f7a8b9c0d1e2_add_fees_to_upstream_providers.py new file mode 100644 index 00000000..2c921094 --- /dev/null +++ b/migrations/versions/f7a8b9c0d1e2_add_fees_to_upstream_providers.py @@ -0,0 +1,27 @@ +"""add provider_fee to upstream_providers + +Revision ID: f7a8b9c0d1e2 +Revises: e1f2a3b4c5d6 +Create Date: 2025-10-13 00:00:00.000000 +""" + +from __future__ import annotations + +import sqlalchemy as sa +from alembic import op + +revision = "f7a8b9c0d1e2" +down_revision = "e1f2a3b4c5d6" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.add_column( + "upstream_providers", + sa.Column("provider_fee", sa.Float(), nullable=False, server_default="1.01"), + ) + + +def downgrade() -> None: + op.drop_column("upstream_providers", "provider_fee") diff --git a/routstr/core/admin.py b/routstr/core/admin.py index bb54ffe7..288b1c8e 100644 --- a/routstr/core/admin.py +++ b/routstr/core/admin.py @@ -1389,30 +1389,30 @@ UPSTREAM_PROVIDERS_JS: str = """ """ @@ -1936,7 +2083,6 @@ def upstream_providers_page() -> str: - @@ -1944,7 +2090,7 @@ def upstream_providers_page() -> str: - +
ID Type Base URL Status
Loading…
Loading…
@@ -1958,7 +2104,15 @@ def upstream_providers_page() -> str:
Loading models…
@@ -2003,7 +2159,7 @@ def upstream_providers_page() -> str: - + @@ -2017,6 +2173,10 @@ def upstream_providers_page() -> str: + + + Leave empty to use default (OpenRouter: 1.06, Others: 1.01) +