From 0a00527626202b5960c1152b66e8caa903b3f580 Mon Sep 17 00:00:00 2001 From: 9qeklajc Date: Sun, 26 Jul 2026 13:23:11 +0200 Subject: [PATCH] chore: apply ruff format repo-wide CI only runs ruff check, so format drift accumulated. Committed separately so the reformat noise stays out of functional commits. --- routstr/algorithm.py | 20 ++++++++-------- routstr/balance.py | 29 +++++++++++++++++++---- routstr/core/admin.py | 26 ++++++++++----------- routstr/core/log_manager.py | 21 ++++++++--------- routstr/core/usage_analytics_store.py | 29 +++++++++++------------ routstr/nostr/analytics.py | 8 +++++-- routstr/payment/cost_calculation.py | 19 ++++----------- routstr/payment/usage.py | 4 +--- routstr/upstream/azure.py | 4 +--- routstr/upstream/ehbp.py | 32 +++++++++++++++----------- routstr/upstream/gemini.py | 4 +--- routstr/upstream/gemini_messages.py | 4 +--- routstr/upstream/groq.py | 4 +++- routstr/upstream/litellm_routing.py | 4 +--- routstr/upstream/messages_dispatch.py | 12 +++------- routstr/upstream/ollama.py | 8 +++---- routstr/upstream/rate_limit.py | 4 +++- routstr/upstream/request_correction.py | 4 +--- routstr/upstream/routstr.py | 3 +-- routstr/upstream/xai.py | 4 +++- routstr/wallet.py | 13 ++++++++--- 21 files changed, 132 insertions(+), 124 deletions(-) diff --git a/routstr/algorithm.py b/routstr/algorithm.py index fbc5388e..ef4b8574 100644 --- a/routstr/algorithm.py +++ b/routstr/algorithm.py @@ -232,7 +232,10 @@ def create_model_mappings( aliases.append(prefixed_id) # Register forwarded_model_id as a routable alias - if model_to_use.forwarded_model_id and model_to_use.forwarded_model_id not in aliases: + if ( + model_to_use.forwarded_model_id + and model_to_use.forwarded_model_id not in aliases + ): aliases.append(model_to_use.forwarded_model_id) # Try to set each alias @@ -322,7 +325,10 @@ def create_model_mappings( aliases.append(prefixed_id) # Register forwarded_model_id as a routable alias - if model_to_use.forwarded_model_id and model_to_use.forwarded_model_id not in aliases: + if ( + model_to_use.forwarded_model_id + and model_to_use.forwarded_model_id not in aliases + ): aliases.append(model_to_use.forwarded_model_id) for alias in aliases: @@ -342,16 +348,10 @@ def create_model_mappings( forwarded_model_ids, the one whose forwarded_model_id equals the requested alias wins. """ - if ( - model.forwarded_model_id - and model.forwarded_model_id.lower() == alias - ): + if model.forwarded_model_id and model.forwarded_model_id.lower() == alias: return 5 - if ( - model.id - and model.id.lower() == alias - ): + if model.id and model.id.lower() == alias: return 4 model_base = get_base_model_id(model.id) diff --git a/routstr/balance.py b/routstr/balance.py index 91b19ce5..03dc4d33 100644 --- a/routstr/balance.py +++ b/routstr/balance.py @@ -260,7 +260,11 @@ async def _lookup_key_no_create( async def _restore_balance( - session: AsyncSession, hashed_key: str, balance: int, reserved_balance: int, mint_url: str + session: AsyncSession, + hashed_key: str, + balance: int, + reserved_balance: int, + mint_url: str, ) -> None: """Restore balance after a failed refund mint attempt.""" restore_stmt = ( @@ -275,7 +279,11 @@ async def _restore_balance( await session.commit() logger.info( "refund_wallet_endpoint: balance restored after mint failure", - extra={"hashed_key": hashed_key, "restored_balance": balance, "mint_url": mint_url}, + extra={ + "hashed_key": hashed_key, + "restored_balance": balance, + "mint_url": mint_url, + }, ) @@ -460,11 +468,23 @@ async def refund_wallet_endpoint( except HTTPException: # Minting failed — restore the debited balance - await _restore_balance(session, key.hashed_key, pre_debit_balance, pre_debit_reserved, key.refund_mint_url or "") + await _restore_balance( + session, + key.hashed_key, + pre_debit_balance, + pre_debit_reserved, + key.refund_mint_url or "", + ) raise except Exception as e: # Minting failed — restore the debited balance - await _restore_balance(session, key.hashed_key, pre_debit_balance, pre_debit_reserved, key.refund_mint_url or "") + await _restore_balance( + session, + key.hashed_key, + pre_debit_balance, + pre_debit_reserved, + key.refund_mint_url or "", + ) error_msg = str(e) logger.error( "refund_wallet_endpoint: mint/send failed", @@ -685,7 +705,6 @@ async def reset_child_key_spent( return {"success": True, "message": "Child key balance reset successfully."} - @router.api_route( "/{path:path}", methods=["GET", "POST", "PUT", "DELETE"], diff --git a/routstr/core/admin.py b/routstr/core/admin.py index 66a1d288..1521510e 100644 --- a/routstr/core/admin.py +++ b/routstr/core/admin.py @@ -68,7 +68,9 @@ async def require_admin_api(request: Request) -> None: async with create_session() as session: result = await session.exec(select(CliToken).where(CliToken.token == token)) cli_token = result.first() - if cli_token and (cli_token.expires_at is None or cli_token.expires_at > now_ts): + if cli_token and ( + cli_token.expires_at is None or cli_token.expires_at > now_ts + ): cli_token.last_used_at = now_ts session.add(cli_token) await session.commit() @@ -255,16 +257,12 @@ async def update_password(request: Request, password_update: PasswordUpdate) -> secret = await get_secret(session) if not secret.admin_password_hash: - raise HTTPException( - status_code=500, detail="Admin password not configured" - ) + raise HTTPException(status_code=500, detail="Admin password not configured") if not vault.verify_password( password_update.current_password, secret.admin_password_hash ): - raise HTTPException( - status_code=401, detail="Current password is incorrect" - ) + raise HTTPException(status_code=401, detail="Current password is incorrect") # Validate new password new_password = password_update.new_password.strip() @@ -980,9 +978,7 @@ async def update_upstream_provider_by_slug( lookup = _validate_slug(payload.slug) async with create_session() as session: result = await session.exec( - select(UpstreamProviderRow).where( - UpstreamProviderRow.slug == lookup - ) + select(UpstreamProviderRow).where(UpstreamProviderRow.slug == lookup) ) provider = result.first() if not provider: @@ -1669,7 +1665,11 @@ async def get_transactions_api( ) total = count_result.one() - stmt = base.order_by(col(CashuTransaction.created_at).desc()).offset(offset).limit(limit) + stmt = ( + base.order_by(col(CashuTransaction.created_at).desc()) + .offset(offset) + .limit(limit) + ) results = await session.exec(stmt) transactions = results.all() @@ -1679,9 +1679,7 @@ async def get_transactions_api( } -@admin_router.get( - "/api/lightning-invoices", dependencies=[Depends(require_admin_api)] -) +@admin_router.get("/api/lightning-invoices", dependencies=[Depends(require_admin_api)]) async def get_lightning_invoices_api( status: str | None = None, purpose: str | None = None, diff --git a/routstr/core/log_manager.py b/routstr/core/log_manager.py index 0444dcbf..b111f68a 100644 --- a/routstr/core/log_manager.py +++ b/routstr/core/log_manager.py @@ -408,7 +408,9 @@ class LogManager: def get_error_details(self, hours: int = 24, limit: int = 100) -> dict: def compute() -> dict: try: - return self._usage_store.get_error_details(hours_back=hours, limit=limit) + return self._usage_store.get_error_details( + hours_back=hours, limit=limit + ) except Exception as e: logger.error( f"Usage analytics index failed, falling back to log scan: {e}" @@ -628,8 +630,7 @@ class LogManager: stats["total_tokens"] += input_tokens + output_tokens failed = ( - "upstream request failed" in message - or "revert payment" in message + "upstream request failed" in message or "revert payment" in message ) if failed: stats["total_requests"] += 1 @@ -787,7 +788,9 @@ class LogManager: if bucket_key: model_mix_buckets[bucket_key][model] += 1 if revenue_msats > 0: - model_mix_revenue_buckets[bucket_key][model] += revenue_msats + model_mix_revenue_buckets[bucket_key][model] += ( + revenue_msats + ) model_mix_revenue_totals[model] += revenue_msats if input_tokens > 0 or output_tokens > 0: token_total = input_tokens + output_tokens @@ -801,8 +804,7 @@ class LogManager: bucket["revenue_msats"] += revenue_msats failed = ( - "upstream request failed" in message - or "revert payment" in message + "upstream request failed" in message or "revert payment" in message ) if failed: summary_stats["total_requests"] += 1 @@ -872,9 +874,7 @@ class LogManager: models.sort(key=lambda x: float(x["net_revenue_sats"]), reverse=True) latest_errors = [ item - for _, item in sorted( - latest_errors_heap, key=lambda x: x[0], reverse=True - ) + for _, item in sorted(latest_errors_heap, key=lambda x: x[0], reverse=True) ] top_model_limit = max(1, min(model_limit, 20)) top_models_requests = [ @@ -1051,8 +1051,7 @@ class LogManager: bucket["warnings"] += 1 failed = ( - "upstream request failed" in message - or "revert payment" in message + "upstream request failed" in message or "revert payment" in message ) if failed: bucket["total_requests"] += 1 diff --git a/routstr/core/usage_analytics_store.py b/routstr/core/usage_analytics_store.py index 7ba90e24..36fa4bcb 100644 --- a/routstr/core/usage_analytics_store.py +++ b/routstr/core/usage_analytics_store.py @@ -314,9 +314,7 @@ class UsageAnalyticsStore: if column in existing_columns: return - conn.execute( - f"ALTER TABLE {table} ADD COLUMN {column} {column_definition}" - ) + conn.execute(f"ALTER TABLE {table} ADD COLUMN {column} {column_definition}") logger.info(f"Migrated analytics schema: added {table}.{column}") def _drop_index_tables_locked(self, conn: sqlite3.Connection) -> None: @@ -364,7 +362,11 @@ class UsageAnalyticsStore: self._drop_index_tables_locked(conn) self._initialize_schema_locked(conn) - files = log_files if log_files is not None else sorted(self.logs_dir.glob("app_*.log")) + files = ( + log_files + if log_files is not None + else sorted(self.logs_dir.glob("app_*.log")) + ) for log_file in files: try: self._process_log_file_locked(conn, log_file, force_full_read=True) @@ -568,8 +570,7 @@ class UsageAnalyticsStore: model_bucket["revenue_msats"] += revenue_msats failed = ( - "upstream request failed" in message - or "revert payment" in message + "upstream request failed" in message or "revert payment" in message ) if failed: bucket["total_requests"] += 1 @@ -592,9 +593,9 @@ class UsageAnalyticsStore: if isinstance(max_cost, (int, float)) and max_cost > 0: max_cost_float = float(max_cost) bucket["refunds_msats"] += max_cost_float - model_updates[(minute_key, model)][ - "refunds_msats" - ] += max_cost_float + model_updates[(minute_key, model)]["refunds_msats"] += ( + max_cost_float + ) return ( end_offset, @@ -1032,7 +1033,9 @@ class UsageAnalyticsStore: """, (cutoff_timestamp,), ).fetchone() - total_error_count = int(total_error_count_row[0]) if total_error_count_row else 0 + total_error_count = ( + int(total_error_count_row[0]) if total_error_count_row else 0 + ) return { "errors": [ @@ -1204,11 +1207,7 @@ class UsageAnalyticsStore: total_successful = int(row["total_successful"]) total_revenue_msats = float(row["total_revenue_msats"]) total_tokens = int(row["total_tokens"]) - if ( - total_successful <= 0 - and total_revenue_msats <= 0 - and total_tokens <= 0 - ): + if total_successful <= 0 and total_revenue_msats <= 0 and total_tokens <= 0: continue bucket_ts = str(row["bucket_ts"]) diff --git a/routstr/nostr/analytics.py b/routstr/nostr/analytics.py index e568b5e0..8b6da590 100644 --- a/routstr/nostr/analytics.py +++ b/routstr/nostr/analytics.py @@ -215,7 +215,9 @@ def _build_window_payload( summary = dashboard.get("summary", {}) model_usage_mix = dashboard.get("model_usage_mix", {}) - summary_payload = _build_summary_payload(summary if isinstance(summary, dict) else {}) + summary_payload = _build_summary_payload( + summary if isinstance(summary, dict) else {} + ) usage_mix_payload = model_usage_mix if isinstance(model_usage_mix, dict) else {} top_model_usage, others_usage = _aggregate_top_model_usage(usage_mix_payload) @@ -338,7 +340,9 @@ async def publish_usage_analytics() -> None: nsec = (settings.nsec or "").strip() if not nsec: if not warned_missing_nsec: - logger.info("NSEC is not configured; skipping analytics sharing to Nostr") + logger.info( + "NSEC is not configured; skipping analytics sharing to Nostr" + ) warned_missing_nsec = True await asyncio.sleep(DISABLED_POLL_SECONDS) continue diff --git a/routstr/payment/cost_calculation.py b/routstr/payment/cost_calculation.py index 37ac15d3..e7cee8ca 100644 --- a/routstr/payment/cost_calculation.py +++ b/routstr/payment/cost_calculation.py @@ -224,9 +224,7 @@ async def calculate_cost( "Token counts %s in the upstream response but cannot be " "priced; the request will appear in dashboards with the " "raw counts and a fixed max-cost charge.", - "are present" - if (input_tokens > 0 or output_tokens > 0) - else "are zero", + "are present" if (input_tokens > 0 or output_tokens > 0) else "are zero", extra={ "base_cost_msats": max_cost, "model": response_data.get("model", "unknown"), @@ -303,9 +301,7 @@ def _resolve_usd_cost(usage_data: dict, response_data: dict) -> float: # actually deducts from the balance. For non-BYOK providers (e.g. # OpenRouter) usage.cost already equals upstream_inference_cost, so we # fall through to the normal ``cost`` lookup below. - upstream_cost = _coerce_usd( - cost_details.get("upstream_inference_cost") - ) + upstream_cost = _coerce_usd(cost_details.get("upstream_inference_cost")) if upstream_cost > 0 and usage_data.get("is_byok"): byok_fee = _coerce_usd(usage_data.get("cost")) return upstream_cost + byok_fee @@ -336,8 +332,7 @@ def _get_pricing_rates( ``None`` means configured fixed pricing should be used by the caller. """ if settings.fixed_pricing and ( - settings.fixed_per_1k_input_tokens - or settings.fixed_per_1k_output_tokens + settings.fixed_per_1k_input_tokens or settings.fixed_per_1k_output_tokens ): return None @@ -393,12 +388,8 @@ def _get_pricing_rates( usd_per_sat = sats_usd_price() mspp_1k = input_usd * provider_fee * 1_000_000.0 / usd_per_sat mspc_1k = output_usd * provider_fee * 1_000_000.0 / usd_per_sat - cache_read_usd = _coerce_usd( - pricing.get("cache_read_input_token_cost") - ) - cache_write_usd = _coerce_usd( - pricing.get("cache_creation_input_token_cost") - ) + cache_read_usd = _coerce_usd(pricing.get("cache_read_input_token_cost")) + cache_write_usd = _coerce_usd(pricing.get("cache_creation_input_token_cost")) mscr_1k = ( cache_read_usd * provider_fee * 1_000_000.0 / usd_per_sat if cache_read_usd > 0 diff --git a/routstr/payment/usage.py b/routstr/payment/usage.py index 02c90055..11d5c01e 100644 --- a/routstr/payment/usage.py +++ b/routstr/payment/usage.py @@ -110,9 +110,7 @@ def normalize_usage(usage_data: object) -> NormalizedUsage | None: if not isinstance(usage_data, dict): return None - output_tokens = _first_token_count( - usage_data, "completion_tokens", "output_tokens" - ) + output_tokens = _first_token_count(usage_data, "completion_tokens", "output_tokens") cache_read, cache_write = _extract_cache_tokens(usage_data) # ``prompt_tokens`` is the inclusive grand total; ``input_tokens`` (Anthropic diff --git a/routstr/upstream/azure.py b/routstr/upstream/azure.py index a693b763..985bcfd2 100644 --- a/routstr/upstream/azure.py +++ b/routstr/upstream/azure.py @@ -94,9 +94,7 @@ class AzureUpstreamProvider(BaseUpstreamProvider): deployment_id = deployment_id.split("/")[-1] return f"openai/deployments/{deployment_id}/{clean_path}" - def get_request_base_url( - self, path: str, model_obj: "Model | None" = None - ) -> str: + def get_request_base_url(self, path: str, model_obj: "Model | None" = None) -> str: """Use endpoint root, stripping accidental /openai/v1 suffix if present.""" base_url = self.base_url.rstrip("/") marker = "/openai/v1" diff --git a/routstr/upstream/ehbp.py b/routstr/upstream/ehbp.py index 96955492..a3d1505a 100644 --- a/routstr/upstream/ehbp.py +++ b/routstr/upstream/ehbp.py @@ -191,7 +191,9 @@ def _resolve_ehbp_target_url( otherwise the header is ignored so callers cannot redirect other providers or leak upstream API keys. """ - override_header = profile.client_target_url_header if profile else _ENCLAVE_URL_HEADER + override_header = ( + profile.client_target_url_header if profile else _ENCLAVE_URL_HEADER + ) if not override_header: return target_url enclave_url = _get_header_case_insensitive(headers, override_header) @@ -295,9 +297,7 @@ def _build_cost_info( return result -def _inject_cost_response_headers( - headers: dict[str, str], cost_info: dict -) -> None: +def _inject_cost_response_headers(headers: dict[str, str], cost_info: dict) -> None: """Add per-request cost headers to an EHBP response. Since EHBP response bodies are opaque encrypted blobs, cost cannot be @@ -375,9 +375,7 @@ async def _compute_ehbp_actual_cost( resolved_upstream_model = ( actual_model_obj.forwarded_model_id or actual_model_obj.id ) - resolved_identity = _normalize_upstream_model_id( - resolved_upstream_model - ) + resolved_identity = _normalize_upstream_model_id(resolved_upstream_model) if resolved_identity != expected_identity: logger.info( "EHBP served model differs from requested, using actual " @@ -517,7 +515,9 @@ async def finalize_ehbp_actual_cost_payment( billing_key = await get_billing_key(key, session) key_hash = key.hashed_key billing_key_hash = billing_key.hashed_key - total_cost_msats = max(0, int(cost_info.get("total_msats", reserved_cost_for_model))) + total_cost_msats = max( + 0, int(cost_info.get("total_msats", reserved_cost_for_model)) + ) now = int(time.time()) safe_reserved = case( @@ -560,7 +560,9 @@ async def finalize_ehbp_actual_cost_payment( ) child_result = await session.exec(child_stmt) # type: ignore[call-overload] - if result.rowcount == 0 or (child_result is not None and child_result.rowcount == 0): + if result.rowcount == 0 or ( + child_result is not None and child_result.rowcount == 0 + ): await session.rollback() logger.error( "Failed to finalize EHBP usage-based payment", @@ -690,7 +692,9 @@ async def finalize_ehbp_max_cost_payment( else: child_result = None - if result.rowcount == 0 or (child_result is not None and child_result.rowcount == 0): + if result.rowcount == 0 or ( + child_result is not None and child_result.rowcount == 0 + ): await session.rollback() logger.error( "Failed to finalize EHBP max-cost payment", @@ -1034,7 +1038,9 @@ async def forward_ehbp_x_cashu_request( target_url = _resolve_ehbp_target_url( target.url, path, headers, provider_type, profile ) - upstream_headers = _prepare_ehbp_upstream_headers(headers, target.headers, profile) + upstream_headers = _prepare_ehbp_upstream_headers( + headers, target.headers, profile + ) request_body = await request.body() # Merge query params into the target URL @@ -1082,9 +1088,7 @@ async def forward_ehbp_x_cashu_request( usage_source = ( "header" if usage_header_name - and any( - k.lower() == usage_header_name.lower() for k, _ in resp.headers - ) + and any(k.lower() == usage_header_name.lower() for k, _ in resp.headers) else ("trailer" if usage_header else "none") ) diff --git a/routstr/upstream/gemini.py b/routstr/upstream/gemini.py index 54de41a3..d58199c2 100644 --- a/routstr/upstream/gemini.py +++ b/routstr/upstream/gemini.py @@ -94,9 +94,7 @@ class GeminiUpstreamProvider(BaseUpstreamProvider): """ return self.base_url.rstrip("/").removesuffix("/openai") + "/openai" - def get_request_base_url( - self, path: str, model_obj: "Model | None" = None - ) -> str: + def get_request_base_url(self, path: str, model_obj: "Model | None" = None) -> str: """Route every proxied request to the OpenAI-compat surface. Required because the stored ``base_url`` typically points at the diff --git a/routstr/upstream/gemini_messages.py b/routstr/upstream/gemini_messages.py index 11440b91..a7e41c9b 100644 --- a/routstr/upstream/gemini_messages.py +++ b/routstr/upstream/gemini_messages.py @@ -371,9 +371,7 @@ async def dispatch_gemini_messages( aggregates). """ if not request_body: - raise UpstreamError( - "Missing request body for /v1/messages", status_code=400 - ) + raise UpstreamError("Missing request body for /v1/messages", status_code=400) try: body: dict = json.loads(request_body) diff --git a/routstr/upstream/groq.py b/routstr/upstream/groq.py index 17103c35..a0c9475e 100644 --- a/routstr/upstream/groq.py +++ b/routstr/upstream/groq.py @@ -20,7 +20,9 @@ class GroqUpstreamProvider(BaseUpstreamProvider): ) @classmethod - def _build_from_row(cls, provider_row: "UpstreamProviderRow") -> "GroqUpstreamProvider": + def _build_from_row( + cls, provider_row: "UpstreamProviderRow" + ) -> "GroqUpstreamProvider": return cls( api_key=provider_row.api_key, provider_fee=provider_row.provider_fee, diff --git a/routstr/upstream/litellm_routing.py b/routstr/upstream/litellm_routing.py index 0b2a92a3..b7790394 100644 --- a/routstr/upstream/litellm_routing.py +++ b/routstr/upstream/litellm_routing.py @@ -91,9 +91,7 @@ OLLAMA_HOST_HINTS: tuple[str, ...] = ( ) -def detect_litellm_prefix( - base_url: str | None, default: str = DEFAULT_PREFIX -) -> str: +def detect_litellm_prefix(base_url: str | None, default: str = DEFAULT_PREFIX) -> str: """Return the litellm provider prefix (`"/"`) for `base_url`. Falls back to `default` when the host doesn't match any known provider. diff --git a/routstr/upstream/messages_dispatch.py b/routstr/upstream/messages_dispatch.py index 3d689922..efcf591b 100644 --- a/routstr/upstream/messages_dispatch.py +++ b/routstr/upstream/messages_dispatch.py @@ -108,9 +108,7 @@ def parse_sse_blocks(buffer: bytes) -> tuple[list[dict], bytes]: return events, buffer -def events_from_chunk( - chunk: object, sse_buffer: bytes -) -> tuple[list[dict], bytes]: +def events_from_chunk(chunk: object, sse_buffer: bytes) -> tuple[list[dict], bytes]: """Normalize a stream chunk into one or more event dicts. ``litellm.anthropic.messages.acreate(stream=True)`` yields raw SSE @@ -201,9 +199,7 @@ async def aggregate_anthropic_events_to_message( raw_json = partial_json.pop(idx, None) if raw_json is not None and idx < len(blocks): try: - blocks[idx]["input"] = ( - json.loads(raw_json) if raw_json else {} - ) + blocks[idx]["input"] = json.loads(raw_json) if raw_json else {} except json.JSONDecodeError: blocks[idx]["input"] = raw_json elif etype == "message_delta": @@ -445,9 +441,7 @@ async def dispatch_anthropic_messages( on bad input or upstream failure. """ if not request_body: - raise UpstreamError( - "Missing request body for /v1/messages", status_code=400 - ) + raise UpstreamError("Missing request body for /v1/messages", status_code=400) try: body: dict = json.loads(request_body) diff --git a/routstr/upstream/ollama.py b/routstr/upstream/ollama.py index 9fed0154..c4873ea0 100644 --- a/routstr/upstream/ollama.py +++ b/routstr/upstream/ollama.py @@ -66,9 +66,7 @@ class OllamaUpstreamProvider(BaseUpstreamProvider): """Strip 'ollama/' prefix for Ollama API compatibility.""" return model_id.removeprefix("ollama/") - def get_request_base_url( - self, path: str, model_obj: Model | None = None - ) -> str: + def get_request_base_url(self, path: str, model_obj: Model | None = None) -> str: """Route proxy traffic through Ollama's OpenAI-compatible /v1 endpoint.""" return f"{self.base_url.rstrip('/')}/v1" @@ -185,7 +183,9 @@ class OllamaUpstreamProvider(BaseUpstreamProvider): except Exception: self._models_cache = models_with_fees - self._models_by_id = {m.forwarded_model_id or m.id: m for m in self._models_cache} + self._models_by_id = { + m.forwarded_model_id or m.id: m for m in self._models_cache + } logger.info( f"Refreshed models cache for {self.base_url}", extra={"model_count": len(models)}, diff --git a/routstr/upstream/rate_limit.py b/routstr/upstream/rate_limit.py index dca1ba5b..ac1eff78 100644 --- a/routstr/upstream/rate_limit.py +++ b/routstr/upstream/rate_limit.py @@ -119,7 +119,9 @@ def classify_rate_limit( retry_match = _RETRY_RE.search(redacted) if retry_match is not None: value = float(retry_match.group(1)) - retry_after = value / 1000.0 if retry_match.group(2).lower() == "ms" else value + retry_after = ( + value / 1000.0 if retry_match.group(2).lower() == "ms" else value + ) limit_name_match = _LIMIT_NAME_RE.search(redacted) diff --git a/routstr/upstream/request_correction.py b/routstr/upstream/request_correction.py index c2ea5b1d..8e4379a0 100644 --- a/routstr/upstream/request_correction.py +++ b/routstr/upstream/request_correction.py @@ -84,9 +84,7 @@ def extract_error_message(response: Response) -> str: return "" -def strip_unsupported_param( - body: dict, error_message: str -) -> tuple[dict, str] | None: +def strip_unsupported_param(body: dict, error_message: str) -> tuple[dict, str] | None: """Drop a top-level param the upstream named as unsupported/deprecated. Returns ``(new_body, param)`` (a new dict, original untouched) when the diff --git a/routstr/upstream/routstr.py b/routstr/upstream/routstr.py index 0371946a..de1aa3bd 100644 --- a/routstr/upstream/routstr.py +++ b/routstr/upstream/routstr.py @@ -50,8 +50,7 @@ class RoutstrUpstreamProvider(BaseUpstreamProvider): def normalize_request_path( self, path: str, model_obj: "Model | None" = None ) -> str: - """Preserve the ``v1/`` prefix when forwarding to an upstream Routstr. - """ + """Preserve the ``v1/`` prefix when forwarding to an upstream Routstr.""" return path.lstrip("/") @classmethod diff --git a/routstr/upstream/xai.py b/routstr/upstream/xai.py index 58caaba0..12e3dd93 100644 --- a/routstr/upstream/xai.py +++ b/routstr/upstream/xai.py @@ -21,7 +21,9 @@ class XAIUpstreamProvider(BaseUpstreamProvider): ) @classmethod - def _build_from_row(cls, provider_row: "UpstreamProviderRow") -> "XAIUpstreamProvider": + def _build_from_row( + cls, provider_row: "UpstreamProviderRow" + ) -> "XAIUpstreamProvider": return cls( api_key=provider_row.api_key, provider_fee=provider_row.provider_fee, diff --git a/routstr/wallet.py b/routstr/wallet.py index dd92d913..cef6902d 100644 --- a/routstr/wallet.py +++ b/routstr/wallet.py @@ -243,7 +243,9 @@ async def send(amount: int, unit: str, mint_url: str | None = None) -> tuple[int all_mint_urls = list({k.mint_url for k in wallet.keysets.values()}) proof_summary = { - f"{k.mint_url}/{k.unit.name}": sum(p.amount for p in wallet.proofs if p.id == k.id) + f"{k.mint_url}/{k.unit.name}": sum( + p.amount for p in wallet.proofs if p.id == k.id + ) for k in wallet.keysets.values() } # Show ALL proofs in DB by keyset_id, regardless of whether the loaded wallet @@ -598,11 +600,16 @@ async def swap_to_primary_mint( # advance the counter so the next request derives fresh secrets. logger.warning( "swap_to_primary_mint: outputs already signed — recovering orphaned proofs", - extra={"mint_quote_id": mint_quote.quote, "minted_amount": minted_amount}, + extra={ + "mint_quote_id": mint_quote.quote, + "minted_amount": minted_amount, + }, ) try: for keyset_id in primary_wallet.keysets: - await primary_wallet.restore_tokens_for_keyset(keyset_id, to=1, batch=25) + await primary_wallet.restore_tokens_for_keyset( + keyset_id, to=1, batch=25 + ) await primary_wallet.load_proofs(reload=True) post_recovery_balance = primary_wallet.available_balance.amount balance_gained = post_recovery_balance - pre_mint_balance