diff --git a/routstr/auth.py b/routstr/auth.py index a1cba59f..6202a69a 100644 --- a/routstr/auth.py +++ b/routstr/auth.py @@ -436,6 +436,40 @@ async def adjust_payment_for_tokens( "max_cost": cost.total_msats, }, ) + # Finalize by releasing reservation and charging max cost + finalize_stmt = ( + update(ApiKey) + .where(col(ApiKey.hashed_key) == key.hashed_key) + .values( + reserved_balance=col(ApiKey.reserved_balance) - deducted_max_cost, + balance=col(ApiKey.balance) - cost.total_msats, + total_spent=col(ApiKey.total_spent) + cost.total_msats, + ) + ) + result = await session.exec(finalize_stmt) # type: ignore[call-overload] + await session.commit() + if result.rowcount == 0: + logger.error( + "Failed to finalize max-cost payment - insufficient reserved balance", + extra={ + "key_hash": key.hashed_key[:8] + "...", + "deducted_max_cost": deducted_max_cost, + "current_reserved_balance": key.reserved_balance, + "total_cost": cost.total_msats, + "model": model, + }, + ) + else: + await session.refresh(key) + logger.info( + "Max cost payment finalized", + extra={ + "key_hash": key.hashed_key[:8] + "...", + "charged_amount": cost.total_msats, + "new_balance": key.balance, + "model": model, + }, + ) return cost.dict() case CostData() as cost: @@ -459,15 +493,27 @@ async def adjust_payment_for_tokens( if cost_difference == 0: logger.debug( - "No cost adjustment needed", + "Finalizing with exact reserved cost", extra={"key_hash": key.hashed_key[:8] + "...", "model": model}, ) + finalize_stmt = ( + update(ApiKey) + .where(col(ApiKey.hashed_key) == key.hashed_key) + .values( + reserved_balance=col(ApiKey.reserved_balance) + - deducted_max_cost, + balance=col(ApiKey.balance) - total_cost_msats, + total_spent=col(ApiKey.total_spent) + total_cost_msats, + ) + ) + await session.exec(finalize_stmt) # type: ignore[call-overload] await session.commit() + await session.refresh(key) return cost.dict() # this should never happen why do we handle this??? if cost_difference > 0: - # Need to charge more + # Need to charge more than reserved, finalize by releasing reservation and charging total logger.info( "Additional charge required for token usage", extra={ @@ -479,56 +525,41 @@ async def adjust_payment_for_tokens( }, ) - # this should never happen why do we handle this??? - if key.balance < cost_difference: - logger.warning( - "Insufficient balance for token-based pricing adjustment", + finalize_stmt = ( + update(ApiKey) + .where(col(ApiKey.hashed_key) == key.hashed_key) + .values( + reserved_balance=col(ApiKey.reserved_balance) + - deducted_max_cost, + balance=col(ApiKey.balance) - total_cost_msats, + total_spent=col(ApiKey.total_spent) + total_cost_msats, + ) + ) + result = await session.exec(finalize_stmt) # type: ignore[call-overload] + await session.commit() + + if result.rowcount: + cost.total_msats = total_cost_msats + await session.refresh(key) + + logger.info( + "Finalized payment with additional charge", extra={ "key_hash": key.hashed_key[:8] + "...", - "required": cost_difference, - "available": key.balance, - "shortfall": cost_difference - key.balance, + "charged_amount": total_cost_msats, + "new_balance": key.balance, "model": model, }, ) - await session.commit() else: - # this should never happen why do we handle this??? - charge_stmt = ( - update(ApiKey) - .where(col(ApiKey.hashed_key) == key.hashed_key) - .where(col(ApiKey.balance) >= cost_difference) - .values( - balance=col(ApiKey.balance) - cost_difference, - total_spent=col(ApiKey.total_spent) + cost_difference, - ) + logger.warning( + "Failed to finalize additional charge (concurrent operation)", + extra={ + "key_hash": key.hashed_key[:8] + "...", + "attempted_charge": total_cost_msats, + "model": model, + }, ) - result = await session.exec(charge_stmt) # type: ignore[call-overload] - await session.commit() - - if result.rowcount: - cost.total_msats = deducted_max_cost + cost_difference - await session.refresh(key) - - logger.info( - "Additional charge applied successfully", - extra={ - "key_hash": key.hashed_key[:8] + "...", - "charged_amount": cost_difference, - "new_balance": key.balance, - "total_cost": cost.total_msats, - "model": model, - }, - ) - else: - logger.warning( - "Failed to apply additional charge (concurrent operation)", - extra={ - "key_hash": key.hashed_key[:8] + "...", - "attempted_charge": cost_difference, - "model": model, - }, - ) else: # Refund some of the base cost refund = abs(cost_difference) diff --git a/routstr/proxy.py b/routstr/proxy.py index 5ebe7c6f..c07d6dc2 100644 --- a/routstr/proxy.py +++ b/routstr/proxy.py @@ -42,106 +42,157 @@ async def handle_streaming_chat_completion( ) async def stream_with_cost(max_cost_for_model: int) -> AsyncGenerator[bytes, None]: - # Store all chunks to analyze - stored_chunks = [] + stored_chunks: list[bytes] = [] + usage_finalized: bool = False + last_model_seen: str | None = None - async for chunk in response.aiter_bytes(): - # Store chunk for later analysis - stored_chunks.append(chunk) + async def finalize_without_usage() -> bytes | None: + nonlocal usage_finalized + if usage_finalized: + return None + async with create_session() as new_session: + fresh_key = await new_session.get(key.__class__, key.hashed_key) + if not fresh_key: + return None + try: + fallback: dict = { + "model": last_model_seen or "unknown", + "usage": None, + } + cost_data = await adjust_payment_for_tokens( + fresh_key, fallback, new_session, max_cost_for_model + ) + usage_finalized = True + logger.info( + "Finalized streaming payment without explicit usage", + extra={ + "key_hash": key.hashed_key[:8] + "...", + "cost_data": cost_data, + "balance_after_adjustment": fresh_key.balance, + }, + ) + return f"data: {json.dumps({'cost': cost_data})}\n\n".encode() + except Exception as cost_error: + logger.error( + "Error finalizing payment without usage", + extra={ + "error": str(cost_error), + "error_type": type(cost_error).__name__, + "key_hash": key.hashed_key[:8] + "...", + }, + ) + return None - # Pass through each chunk to client - yield chunk + try: + async for chunk in response.aiter_bytes(): + stored_chunks.append(chunk) + # Opportunistically capture model id + try: + for part in re.split(b"data: ", chunk): + if not part or part.strip() in (b"[DONE]", b""): + continue + try: + obj = json.loads(part) + if isinstance(obj, dict) and obj.get("model"): + last_model_seen = str(obj.get("model")) + except json.JSONDecodeError: + pass + except Exception: + pass - logger.debug( - "Streaming completed, analyzing usage data", - extra={ - "key_hash": key.hashed_key[:8] + "...", - "chunks_count": len(stored_chunks), - }, - ) + yield chunk - # Process stored chunks to find usage data - # Start from the end and work backwards - for i in range(len(stored_chunks) - 1, -1, -1): - chunk = stored_chunks[i] - if not chunk or chunk == b"": - continue + logger.debug( + "Streaming completed, analyzing usage data", + extra={ + "key_hash": key.hashed_key[:8] + "...", + "chunks_count": len(stored_chunks), + }, + ) - try: - # Split by "data: " to get individual SSE events - events = re.split(b"data: ", chunk) - for event_data in events: - if ( - not event_data - or event_data.strip() == b"[DONE]" - or event_data.strip() == b"" - ): - continue + # Process stored chunks to find usage data from the tail + for i in range(len(stored_chunks) - 1, -1, -1): + chunk = stored_chunks[i] + if not chunk: + continue + try: + events = re.split(b"data: ", chunk) + for event_data in events: + if not event_data or event_data.strip() in (b"[DONE]", b""): + continue + try: + data = json.loads(event_data) + if isinstance(data, dict) and data.get("model"): + last_model_seen = str(data.get("model")) + if isinstance(data, dict) and isinstance( + data.get("usage"), dict + ): + async with create_session() as new_session: + fresh_key = await new_session.get( + key.__class__, key.hashed_key + ) + if fresh_key: + try: + cost_data = await adjust_payment_for_tokens( + fresh_key, + data, + new_session, + max_cost_for_model, + ) + usage_finalized = True + logger.info( + "Token adjustment completed for streaming", + extra={ + "key_hash": key.hashed_key[:8] + + "...", + "cost_data": cost_data, + "balance_after_adjustment": fresh_key.balance, + }, + ) + yield f"data: {json.dumps({'cost': cost_data})}\n\n".encode() + except Exception as cost_error: + logger.error( + "Error adjusting payment for streaming tokens", + extra={ + "error": str(cost_error), + "error_type": type( + cost_error + ).__name__, + "key_hash": key.hashed_key[:8] + + "...", + }, + ) + break + except json.JSONDecodeError: + continue + except Exception as e: + logger.error( + "Error processing streaming response chunk", + extra={ + "error": str(e), + "error_type": type(e).__name__, + "key_hash": key.hashed_key[:8] + "...", + }, + ) - try: - data = json.loads(event_data) - if ( - "usage" in data - and data["usage"] is not None - and isinstance(data["usage"], dict) - ): - logger.info( - "Found usage data in streaming response", - extra={ - "key_hash": key.hashed_key[:8] + "...", - "usage_data": data["usage"], - "model": data.get("model", "unknown"), - }, - ) + # If we reach here without finding usage, finalize with max-cost + if not usage_finalized: + maybe_cost_event = await finalize_without_usage() + if maybe_cost_event is not None: + yield maybe_cost_event - # Found usage data, calculate cost - # Create a new session for this operation - async with create_session() as new_session: - # Re-fetch the key in the new session - fresh_key = await new_session.get( - key.__class__, key.hashed_key - ) - if fresh_key: - try: - cost_data = await adjust_payment_for_tokens( - fresh_key, - data, - new_session, - max_cost_for_model, - ) - logger.info( - "Token adjustment completed for streaming", - extra={ - "key_hash": key.hashed_key[:8] + "...", - "cost_data": cost_data, - "balance_after_adjustment": fresh_key.balance, - }, - ) - # Format as SSE and yield - cost_json = json.dumps({"cost": cost_data}) - yield f"data: {cost_json}\n\n".encode() - except Exception as cost_error: - logger.error( - "Error adjusting payment for streaming tokens", - extra={ - "error": str(cost_error), - "error_type": type(cost_error).__name__, - "key_hash": key.hashed_key[:8] + "...", - }, - ) - break - except json.JSONDecodeError: - continue - - except Exception as e: - logger.error( - "Error processing streaming response chunk", - extra={ - "error": str(e), - "error_type": type(e).__name__, - "key_hash": key.hashed_key[:8] + "...", - }, - ) + except Exception as stream_error: + # On stream interruption, still finalize reservation with max-cost + logger.warning( + "Streaming interrupted; finalizing without usage", + extra={ + "error": str(stream_error), + "error_type": type(stream_error).__name__, + "key_hash": key.hashed_key[:8] + "...", + }, + ) + await finalize_without_usage() + raise return StreamingResponse( stream_with_cost(max_cost_for_model), diff --git a/temp.logs b/temp.logs new file mode 100644 index 00000000..d717fcd3 --- /dev/null +++ b/temp.logs @@ -0,0 +1,124 @@ +{"asctime": "2025-09-04 14:01:45", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "bebebe5c-3db8-4117-ae39-85df53bcd058", "method": "GET", "path": "/v1/models", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "213.199.37.224", "x-forwarded-for": "213.199.37.224", "x-forwarded-proto": "https", "connection": "close", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:01:45", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "bebebe5c-3db8-4117-ae39-85df53bcd058", "method": "GET", "path": "/v1/models", "status_code": 200, "duration_ms": 172.05, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:02:45", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "a5c05bf1-f84a-4365-9998-ebc62102731d", "method": "GET", "path": "/v1/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "91.99.199.162", "x-forwarded-for": "91.99.199.162", "x-forwarded-proto": "https", "connection": "close", "accept": "*/*", "accept-encoding": "gzip, deflate, br", "user-agent": "python-httpx/0.25.2"}, "body_size": 0} +{"asctime": "2025-09-04 14:02:45", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "a5c05bf1-f84a-4365-9998-ebc62102731d", "method": "GET", "path": "/v1/info", "status_code": 200, "duration_ms": 123.72, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:06:39", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "c56d637a-38ad-46b8-8296-3a8fd07fdfe6", "method": "GET", "path": "/v1/models", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "213.199.37.224", "x-forwarded-for": "213.199.37.224", "x-forwarded-proto": "https", "connection": "close", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:06:39", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "c56d637a-38ad-46b8-8296-3a8fd07fdfe6", "method": "GET", "path": "/v1/models", "status_code": 200, "duration_ms": 138.31, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:07:46", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "fc657871-d7b5-488d-86cf-179ebe33fdb0", "method": "GET", "path": "/v1/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "91.99.199.162", "x-forwarded-for": "91.99.199.162", "x-forwarded-proto": "https", "connection": "close", "accept": "*/*", "accept-encoding": "gzip, deflate, br", "user-agent": "python-httpx/0.25.2"}, "body_size": 0} +{"asctime": "2025-09-04 14:07:46", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "fc657871-d7b5-488d-86cf-179ebe33fdb0", "method": "GET", "path": "/v1/info", "status_code": 200, "duration_ms": 314.62, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "517", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.payment.helpers", "levelname": "WARNING", "message": "Model not found in available models", "pathname": "/app/routstr/payment/helpers.py", "lineno": 111, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "requested_model": "gpt-4o-mini", "available_models": ["deepseek/deepseek-chat-v3.1", "deepseek/deepseek-v3.1-base", "openai/gpt-4o-audio-preview", "mistralai/mistral-medium-3.1", "baidu/ernie-4.5-21b-a3b", "baidu/ernie-4.5-vl-28b-a3b", "z-ai/glm-4.5v", "ai21/jamba-mini-1.7", "ai21/jamba-large-1.7", "openai/gpt-5-chat", "openai/gpt-5", "openai/gpt-5-mini", "openai/gpt-5-nano", "openai/gpt-oss-120b", "openai/gpt-oss-20b", "anthropic/claude-opus-4.1", "mistralai/codestral-2508", "qwen/qwen3-30b-a3b-instruct-2507", "z-ai/glm-4.5", "z-ai/glm-4.5-air", "qwen/qwen3-235b-a22b-thinking-2507", "z-ai/glm-4-32b", "qwen/qwen3-coder", "bytedance/ui-tars-1.5-7b", "google/gemini-2.5-flash-lite", "qwen/qwen3-235b-a22b-2507", "switchpoint/router", "moonshotai/kimi-k2", "thudm/glm-4.1v-9b-thinking", "mistralai/devstral-medium", "mistralai/devstral-small", "x-ai/grok-4", "tencent/hunyuan-a13b-instruct", "morph/morph-v3-large", "morph/morph-v3-fast", "baidu/ernie-4.5-vl-424b-a47b", "baidu/ernie-4.5-300b-a47b", "thedrummer/anubis-70b-v1.1", "inception/mercury", "mistralai/mistral-small-3.2-24b-instruct", "minimax/minimax-m1", "google/gemini-2.5-flash-lite-preview-06-17", "google/gemini-2.5-flash", "google/gemini-2.5-pro", "openai/o3-pro", "x-ai/grok-3-mini", "x-ai/grok-3", "mistralai/magistral-small-2506", "mistralai/magistral-medium-2506", "mistralai/magistral-medium-2506:thinking", "google/gemini-2.5-pro-preview", "deepseek/deepseek-r1-0528-qwen3-8b", "deepseek/deepseek-r1-0528", "anthropic/claude-opus-4", "anthropic/claude-sonnet-4", "mistralai/devstral-small-2505", "google/gemma-3n-e4b-it", "openai/codex-mini", "nousresearch/deephermes-3-mistral-24b-preview", "mistralai/mistral-medium-3", "google/gemini-2.5-pro-preview-05-06", "arcee-ai/spotlight", "arcee-ai/maestro-reasoning", "arcee-ai/virtuoso-large", "arcee-ai/coder-large", "microsoft/phi-4-reasoning-plus", "inception/mercury-coder", "opengvlab/internvl3-14b", "deepseek/deepseek-prover-v2", "meta-llama/llama-guard-4-12b", "qwen/qwen3-30b-a3b", "qwen/qwen3-8b", "qwen/qwen3-14b", "qwen/qwen3-32b", "qwen/qwen3-235b-a22b", "tngtech/deepseek-r1t-chimera", "microsoft/mai-ds-r1", "thudm/glm-z1-32b", "thudm/glm-4-32b", "openai/o4-mini-high", "openai/o3", "openai/o4-mini", "shisa-ai/shisa-v2-llama3.3-70b", "openai/gpt-4.1", "openai/gpt-4.1-mini", "openai/gpt-4.1-nano", "eleutherai/llemma_7b", "alfredpros/codellama-7b-instruct-solidity", "arliai/qwq-32b-arliai-rpr-v1", "agentica-org/deepcoder-14b-preview", "moonshotai/kimi-vl-a3b-thinking", "x-ai/grok-3-mini-beta", "x-ai/grok-3-beta", "nvidia/llama-3.3-nemotron-super-49b-v1", "nvidia/llama-3.1-nemotron-ultra-253b-v1", "meta-llama/llama-4-maverick", "meta-llama/llama-4-scout", "deepseek/deepseek-v3-base", "scb10x/llama3.1-typhoon2-70b-instruct", "qwen/qwen2.5-vl-32b-instruct", "deepseek/deepseek-chat-v3-0324", "openai/o1-pro", "mistralai/mistral-small-3.1-24b-instruct", "google/gemma-3-4b-it", "google/gemma-3-12b-it", "cohere/command-a", "openai/gpt-4o-mini-search-preview", "openai/gpt-4o-search-preview", "google/gemma-3-27b-it", "thedrummer/anubis-pro-105b-v1", "thedrummer/skyfall-36b-v2", "microsoft/phi-4-multimodal-instruct", "perplexity/sonar-reasoning-pro", "perplexity/sonar-pro", "perplexity/sonar-deep-research", "qwen/qwq-32b", "google/gemini-2.0-flash-lite-001", "anthropic/claude-3.7-sonnet", "anthropic/claude-3.7-sonnet:thinking", "perplexity/r1-1776", "mistralai/mistral-saba", "cognitivecomputations/dolphin3.0-r1-mistral-24b", "cognitivecomputations/dolphin3.0-mistral-24b", "meta-llama/llama-guard-3-8b", "openai/o3-mini-high", "deepseek/deepseek-r1-distill-llama-8b", "google/gemini-2.0-flash-001", "qwen/qwen-vl-plus", "aion-labs/aion-1.0", "aion-labs/aion-1.0-mini", "aion-labs/aion-rp-llama-3.1-8b", "qwen/qwen-vl-max", "qwen/qwen-turbo", "qwen/qwen2.5-vl-72b-instruct", "qwen/qwen-plus", "qwen/qwen-max", "openai/o3-mini", "deepseek/deepseek-r1-distill-qwen-1.5b", "mistralai/mistral-small-24b-instruct-2501", "deepseek/deepseek-r1-distill-qwen-32b", "deepseek/deepseek-r1-distill-qwen-14b", "perplexity/sonar-reasoning", "perplexity/sonar", "liquid/lfm-7b", "liquid/lfm-3b", "deepseek/deepseek-r1-distill-llama-70b", "deepseek/deepseek-r1", "minimax/minimax-01", "mistralai/codestral-2501", "microsoft/phi-4", "deepseek/deepseek-chat", "sao10k/l3.3-euryale-70b", "openai/o1", "x-ai/grok-2-vision-1212", "x-ai/grok-2-1212", "cohere/command-r7b-12-2024", "meta-llama/llama-3.3-70b-instruct", "amazon/nova-lite-v1", "amazon/nova-micro-v1", "amazon/nova-pro-v1", "qwen/qwq-32b-preview", "openai/gpt-4o-2024-11-20", "mistralai/mistral-large-2411", "mistralai/mistral-large-2407", "mistralai/pixtral-large-2411", "x-ai/grok-vision-beta", "infermatic/mn-inferor-12b", "qwen/qwen-2.5-coder-32b-instruct", "raifle/sorcererlm-8x22b", "thedrummer/unslopnemo-12b", "anthropic/claude-3.5-haiku-20241022", "anthropic/claude-3.5-haiku", "anthropic/claude-3.5-sonnet", "anthracite-org/magnum-v4-72b", "mistralai/ministral-8b", "mistralai/ministral-3b", "qwen/qwen-2.5-7b-instruct", "nvidia/llama-3.1-nemotron-70b-instruct", "inflection/inflection-3-pi", "inflection/inflection-3-productivity", "google/gemini-flash-1.5-8b", "anthracite-org/magnum-v2-72b", "thedrummer/rocinante-12b", "meta-llama/llama-3.2-90b-vision-instruct", "meta-llama/llama-3.2-11b-vision-instruct", "meta-llama/llama-3.2-3b-instruct", "meta-llama/llama-3.2-1b-instruct", "qwen/qwen-2.5-72b-instruct", "neversleep/llama-3.1-lumimaid-8b", "openai/o1-mini", "openai/o1-mini-2024-09-12", "mistralai/pixtral-12b", "cohere/command-r-plus-08-2024", "cohere/command-r-08-2024", "sao10k/l3.1-euryale-70b", "qwen/qwen-2.5-vl-7b-instruct", "microsoft/phi-3.5-mini-128k-instruct", "nousresearch/hermes-3-llama-3.1-70b", "nousresearch/hermes-3-llama-3.1-405b", "openai/chatgpt-4o-latest", "sao10k/l3-lunaris-8b", "openai/gpt-4o-2024-08-06", "meta-llama/llama-3.1-405b", "meta-llama/llama-3.1-70b-instruct", "meta-llama/llama-3.1-405b-instruct", "meta-llama/llama-3.1-8b-instruct", "mistralai/mistral-nemo", "openai/gpt-4o-mini-2024-07-18", "openai/gpt-4o-mini", "google/gemma-2-27b-it", "google/gemma-2-9b-it", "anthropic/claude-3.5-sonnet-20240620", "sao10k/l3-euryale-70b", "cognitivecomputations/dolphin-mixtral-8x22b", "qwen/qwen-2-72b-instruct", "nousresearch/hermes-2-pro-llama-3-8b", "mistralai/mistral-7b-instruct-v0.3", "mistralai/mistral-7b-instruct", "microsoft/phi-3-mini-128k-instruct", "microsoft/phi-3-medium-128k-instruct", "neversleep/llama-3-lumimaid-70b", "google/gemini-flash-1.5", "meta-llama/llama-guard-2-8b", "openai/gpt-4o-2024-05-13", "openai/gpt-4o", "openai/gpt-4o:extended", "meta-llama/llama-3-8b-instruct", "meta-llama/llama-3-70b-instruct", "mistralai/mixtral-8x22b-instruct", "microsoft/wizardlm-2-8x22b", "google/gemini-pro-1.5", "openai/gpt-4-turbo", "cohere/command-r-plus", "cohere/command-r-plus-04-2024", "sophosympatheia/midnight-rose-70b", "cohere/command-r", "cohere/command", "anthropic/claude-3-haiku", "anthropic/claude-3-opus", "cohere/command-r-03-2024", "mistralai/mistral-large", "openai/gpt-4-turbo-preview", "openai/gpt-3.5-turbo-0613", "nousresearch/nous-hermes-2-mixtral-8x7b-dpo", "mistralai/mistral-small", "mistralai/mistral-tiny", "mistralai/mixtral-8x7b-instruct", "neversleep/noromaid-20b", "alpindale/goliath-120b", "openai/gpt-4-1106-preview", "openai/gpt-3.5-turbo-instruct", "mistralai/mistral-7b-instruct-v0.1", "pygmalionai/mythalion-13b", "openai/gpt-3.5-turbo-16k", "mancer/weaver", "undi95/remm-slerp-l2-13b", "gryphe/mythomax-l2-13b", "openai/gpt-4", "openai/gpt-3.5-turbo", "openai/gpt-4-0314"], "using_default_cost": 0} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "balance": 3883554, "total_requests": 335} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3883554} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3883554, "model": "gpt-4o-mini"} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "current_balance": 3883554, "required_cost": 0, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.auth", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 358, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "charged_amount": 0, "new_balance": 3883554, "total_spent": 2116446, "total_requests": 336} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.proxy", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/proxy.py", "lineno": 561, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_after": 3883554, "model": "gpt-4o-mini"} +{"asctime": "2025-09-04 14:08:02", "name": "routstr.proxy", "levelname": "INFO", "message": "Forwarding request to upstream", "pathname": "/app/routstr/proxy.py", "lineno": 261, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "url": "https://openrouter.ai/api/v1/chat/completions", "method": "POST", "path": "chat/completions", "key_hash": "98d4c330...", "key_balance": 3883554, "has_request_body": true} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.proxy", "levelname": "INFO", "message": "Received upstream response", "pathname": "/app/routstr/proxy.py", "lineno": 303, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "status_code": 200, "path": "chat/completions", "key_hash": "98d4c330...", "content_type": "application/json"} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing non-streaming chat completion", "pathname": "/app/routstr/proxy.py", "lineno": 161, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "key_balance": 3883554, "response_status": 200} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Applied model-specific pricing", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 127, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "model": "openai/gpt-4o-mini", "input_price_msats_per_1k": 143.92719309444078, "output_price_msats_per_1k": 575.7087723777631} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 153, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "input_tokens": 118, "output_tokens": 5, "input_cost_msats": 16.983, "output_cost_msats": 2.879, "total_cost_msats": 20, "model": "openai/gpt-4o-mini"} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.auth", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/auth.py", "lineno": 447, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "model": "openai/gpt-4o-mini", "token_cost": 20, "deducted_max_cost": 0, "cost_difference": 20, "input_msats": 16, "output_msats": 2} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.auth", "levelname": "INFO", "message": "Additional charge required for token: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 471, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "additional_charge": 20, "current_balance": 3883554, "sufficient_balance": true, "model": "openai/gpt-4o-mini"} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.auth", "levelname": "INFO", "message": "Additional charge applied successfully", "pathname": "/app/routstr/auth.py", "lineno": 513, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "charged_amount": 20, "new_balance": 3883534, "total_cost": 20, "model": "openai/gpt-4o-mini"} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED] completed for non-streaming", "pathname": "/app/routstr/proxy.py", "lineno": 188, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "key_hash": "98d4c330...", "cost_data": {"base_msats": 0, "input_msats": 16, "output_msats": 2, "total_msats": 20}, "model": "openai/gpt-4o-mini", "balance_after_adjustment": 3883534} +{"asctime": "2025-09-04 14:08:03", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "9a5a8186-62b9-4f82-a78d-22c6a0ad99a5", "method": "POST", "path": "/v1/chat/completions", "status_code": 200, "duration_ms": 840.94, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "25651", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "balance": 3883534, "total_requests": 336} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3883534} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3883534, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "current_balance": 3883534, "required_cost": 1299489, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.auth", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 358, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "charged_amount": 1299489, "new_balance": 3883534, "total_spent": 2116466, "total_requests": 337} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.proxy", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/proxy.py", "lineno": 561, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_after": 3883534, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:04", "name": "routstr.proxy", "levelname": "INFO", "message": "Forwarding request to upstream", "pathname": "/app/routstr/proxy.py", "lineno": 261, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "url": "https://openrouter.ai/api/v1/chat/completions", "method": "POST", "path": "chat/completions", "key_hash": "98d4c330...", "key_balance": 3883534, "has_request_body": true} +{"asctime": "2025-09-04 14:08:06", "name": "routstr.proxy", "levelname": "INFO", "message": "Received upstream response", "pathname": "/app/routstr/proxy.py", "lineno": 303, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "status_code": 200, "path": "chat/completions", "key_hash": "98d4c330...", "content_type": "text/event-stream"} +{"asctime": "2025-09-04 14:08:06", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing streaming chat completion", "pathname": "/app/routstr/proxy.py", "lineno": 36, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "key_balance": 3883534, "response_status": 200} +{"asctime": "2025-09-04 14:08:06", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "method": "POST", "path": "/v1/chat/completions", "status_code": 200, "duration_ms": 2542.29, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.proxy", "levelname": "INFO", "message": "Found usage data in streaming response", "pathname": "/app/routstr/proxy.py", "lineno": 89, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "usage_data": {"prompt_tokens": 6864, "completion_tokens": 69, "total_tokens": 6933, "cost": 0.021627, "is_byok": false, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "cost_details": {"upstream_inference_cost": null, "upstream_inference_prompt_cost": 0.020592, "upstream_inference_completions_cost": 0.001035}, "completion_tokens_details": {"reasoning_tokens": 0, "image_tokens": 0}}, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Applied model-specific pricing", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 127, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "model": "anthropic/claude-sonnet-4", "input_price_msats_per_1k": 2878.543861888816, "output_price_msats_per_1k": 14392.71930944408} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 153, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "input_tokens": 6864, "output_tokens": 69, "input_cost_msats": 19758.325, "output_cost_msats": 993.098, "total_cost_msats": 20752, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.auth", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/auth.py", "lineno": 447, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "model": "anthropic/claude-sonnet-4", "token_cost": 20752, "deducted_max_cost": 1299489, "cost_difference": -1278737, "input_msats": 19758, "output_msats": 993} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.auth", "levelname": "INFO", "message": "Refunding excess payment", "pathname": "/app/routstr/auth.py", "lineno": 535, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "refund_amount": 1278737, "current_balance": 3883534, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.auth", "levelname": "INFO", "message": "Refund processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 575, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "refunded_amount": 1278737, "new_balance": 3862782, "final_cost": 20752, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:07", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED] completed for streaming", "pathname": "/app/routstr/proxy.py", "lineno": 113, "version": "0.1.1b", "request_id": "142c8b9a-474f-4c99-957e-2b906a2bfc8e", "key_hash": "98d4c330...", "cost_data": {"base_msats": 0, "input_msats": 19758, "output_msats": 993, "total_msats": 20752}, "balance_after_adjustment": 3862782} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "25882", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "balance": 3862782, "total_requests": 337} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3862782} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3862782, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "current_balance": 3862782, "required_cost": 1299489, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.auth", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 358, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "charged_amount": 1299489, "new_balance": 3862782, "total_spent": 2137218, "total_requests": 338} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.proxy", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/proxy.py", "lineno": 561, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_after": 3862782, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:08", "name": "routstr.proxy", "levelname": "INFO", "message": "Forwarding request to upstream", "pathname": "/app/routstr/proxy.py", "lineno": 261, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "url": "https://openrouter.ai/api/v1/chat/completions", "method": "POST", "path": "chat/completions", "key_hash": "98d4c330...", "key_balance": 3862782, "has_request_body": true} +{"asctime": "2025-09-04 14:08:10", "name": "routstr.proxy", "levelname": "INFO", "message": "Received upstream response", "pathname": "/app/routstr/proxy.py", "lineno": 303, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "status_code": 200, "path": "chat/completions", "key_hash": "98d4c330...", "content_type": "text/event-stream"} +{"asctime": "2025-09-04 14:08:10", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing streaming chat completion", "pathname": "/app/routstr/proxy.py", "lineno": 36, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "key_balance": 3862782, "response_status": 200} +{"asctime": "2025-09-04 14:08:10", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "method": "POST", "path": "/v1/chat/completions", "status_code": 200, "duration_ms": 2479.0, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.proxy", "levelname": "INFO", "message": "Found usage data in streaming response", "pathname": "/app/routstr/proxy.py", "lineno": 89, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "usage_data": {"prompt_tokens": 6913, "completion_tokens": 296, "total_tokens": 7209, "cost": 0.025179, "is_byok": false, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "cost_details": {"upstream_inference_cost": null, "upstream_inference_prompt_cost": 0.020739, "upstream_inference_completions_cost": 0.00444}, "completion_tokens_details": {"reasoning_tokens": 0, "image_tokens": 0}}, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Applied model-specific pricing", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 127, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "model": "anthropic/claude-sonnet-4", "input_price_msats_per_1k": 2878.2915672307818, "output_price_msats_per_1k": 14391.45783615391} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 153, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "input_tokens": 6913, "output_tokens": 296, "input_cost_msats": 19897.63, "output_cost_msats": 4259.872, "total_cost_msats": 24158, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.auth", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/auth.py", "lineno": 447, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "model": "anthropic/claude-sonnet-4", "token_cost": 24158, "deducted_max_cost": 1299489, "cost_difference": -1275331, "input_msats": 19897, "output_msats": 4259} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.auth", "levelname": "INFO", "message": "Refunding excess payment", "pathname": "/app/routstr/auth.py", "lineno": 535, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "refund_amount": 1275331, "current_balance": 3862782, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.auth", "levelname": "INFO", "message": "Refund processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 575, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "refunded_amount": 1275331, "new_balance": 3838624, "final_cost": 24158, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:13", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED] completed for streaming", "pathname": "/app/routstr/proxy.py", "lineno": 113, "version": "0.1.1b", "request_id": "bd9b3c40-983d-49d2-9f60-3077f061fc10", "key_hash": "98d4c330...", "cost_data": {"base_msats": 0, "input_msats": 19897, "output_msats": 4259, "total_msats": 24158}, "balance_after_adjustment": 3838624} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "26674", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "balance": 3838624, "total_requests": 338} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3838624} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3838624, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "current_balance": 3838624, "required_cost": 1299375, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.auth", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 358, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "charged_amount": 1299375, "new_balance": 3838624, "total_spent": 2161376, "total_requests": 339} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.proxy", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/proxy.py", "lineno": 561, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_after": 3838624, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:14", "name": "routstr.proxy", "levelname": "INFO", "message": "Forwarding request to upstream", "pathname": "/app/routstr/proxy.py", "lineno": 261, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "url": "https://openrouter.ai/api/v1/chat/completions", "method": "POST", "path": "chat/completions", "key_hash": "98d4c330...", "key_balance": 3838624, "has_request_body": true} +{"asctime": "2025-09-04 14:08:16", "name": "routstr.proxy", "levelname": "INFO", "message": "Received upstream response", "pathname": "/app/routstr/proxy.py", "lineno": 303, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "status_code": 200, "path": "chat/completions", "key_hash": "98d4c330...", "content_type": "text/event-stream"} +{"asctime": "2025-09-04 14:08:16", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing streaming chat completion", "pathname": "/app/routstr/proxy.py", "lineno": 36, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "key_balance": 3838624, "response_status": 200} +{"asctime": "2025-09-04 14:08:16", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "method": "POST", "path": "/v1/chat/completions", "status_code": 200, "duration_ms": 2096.41, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:17", "name": "routstr.proxy", "levelname": "INFO", "message": "Found usage data in streaming response", "pathname": "/app/routstr/proxy.py", "lineno": 89, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "usage_data": {"prompt_tokens": 7226, "completion_tokens": 142, "total_tokens": 7368, "cost": 0.023808, "is_byok": false, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "cost_details": {"upstream_inference_cost": null, "upstream_inference_prompt_cost": 0.021678, "upstream_inference_completions_cost": 0.00213}, "completion_tokens_details": {"reasoning_tokens": 0, "image_tokens": 0}}, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:17", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Applied model-specific pricing", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 127, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "model": "anthropic/claude-sonnet-4", "input_price_msats_per_1k": 2878.2915672307818, "output_price_msats_per_1k": 14391.45783615391} +{"asctime": "2025-09-04 14:08:17", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 153, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "input_tokens": 7226, "output_tokens": 142, "input_cost_msats": 20798.535, "output_cost_msats": 2043.587, "total_cost_msats": 22843, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:17", "name": "routstr.auth", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/auth.py", "lineno": 447, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "model": "anthropic/claude-sonnet-4", "token_cost": 22843, "deducted_max_cost": 1299375, "cost_difference": -1276532, "input_msats": 20798, "output_msats": 2043} +{"asctime": "2025-09-04 14:08:17", "name": "routstr.auth", "levelname": "INFO", "message": "Refunding excess payment", "pathname": "/app/routstr/auth.py", "lineno": 535, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "refund_amount": 1276532, "current_balance": 3838624, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:18", "name": "routstr.auth", "levelname": "INFO", "message": "Refund processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 575, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "refunded_amount": 1276532, "new_balance": 3815781, "final_cost": 22843, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:18", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED] completed for streaming", "pathname": "/app/routstr/proxy.py", "lineno": 113, "version": "0.1.1b", "request_id": "a6f0fc6d-ae2a-48d7-b1aa-95cb98bb19d1", "key_hash": "98d4c330...", "cost_data": {"base_msats": 0, "input_msats": 20798, "output_msats": 2043, "total_msats": 22843}, "balance_after_adjustment": 3815781} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "27130", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "balance": 3815781, "total_requests": 339} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3815781} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3815781, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "current_balance": 3815781, "required_cost": 1299375, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.auth", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 358, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "charged_amount": 1299375, "new_balance": 3815781, "total_spent": 2184219, "total_requests": 340} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.proxy", "levelname": "INFO", "message": "Payment processed successfully", "pathname": "/app/routstr/proxy.py", "lineno": 561, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_after": 3815781, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:19", "name": "routstr.proxy", "levelname": "INFO", "message": "Forwarding request to upstream", "pathname": "/app/routstr/proxy.py", "lineno": 261, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "url": "https://openrouter.ai/api/v1/chat/completions", "method": "POST", "path": "chat/completions", "key_hash": "98d4c330...", "key_balance": 3815781, "has_request_body": true} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "Received upstream response", "pathname": "/app/routstr/proxy.py", "lineno": 303, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "status_code": 200, "path": "chat/completions", "key_hash": "98d4c330...", "content_type": "text/event-stream"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing streaming chat completion", "pathname": "/app/routstr/proxy.py", "lineno": 36, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "key_balance": 3815781, "response_status": 200} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "method": "POST", "path": "/v1/chat/completions", "status_code": 200, "duration_ms": 2804.49, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "Found usage data in streaming response", "pathname": "/app/routstr/proxy.py", "lineno": 89, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "usage_data": {"prompt_tokens": 7406, "completion_tokens": 105, "total_tokens": 7511, "cost": 0.023793, "is_byok": false, "prompt_tokens_details": {"cached_tokens": 0, "audio_tokens": 0}, "cost_details": {"upstream_inference_cost": null, "upstream_inference_prompt_cost": 0.022218, "upstream_inference_completions_cost": 0.001575}, "completion_tokens_details": {"reasoning_tokens": 0, "image_tokens": 0}}, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Applied model-specific pricing", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 127, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "model": "anthropic/claude-sonnet-4", "input_price_msats_per_1k": 2878.9858767133815, "output_price_msats_per_1k": 14394.929383566907} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.payment.cost_caculation", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/payment/cost_caculation.py", "lineno": 153, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "input_tokens": 7406, "output_tokens": 105, "input_cost_msats": 21321.769, "output_cost_msats": 1511.468, "total_cost_msats": 22834, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "INFO", "message": "Calculated token-based cost", "pathname": "/app/routstr/auth.py", "lineno": 447, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "model": "anthropic/claude-sonnet-4", "token_cost": 22834, "deducted_max_cost": 1299375, "cost_difference": -1276541, "input_msats": 21321, "output_msats": 1511} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "INFO", "message": "Refunding excess payment", "pathname": "/app/routstr/auth.py", "lineno": 535, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "refund_amount": 1276541, "current_balance": 3815781, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "INFO", "message": "Refund processed successfully", "pathname": "/app/routstr/auth.py", "lineno": 575, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "refunded_amount": 1276541, "new_balance": 3792947, "final_cost": 22834, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED] completed for streaming", "pathname": "/app/routstr/proxy.py", "lineno": 113, "version": "0.1.1b", "request_id": "1d47de41-639e-45e0-9c72-9483677ac3f7", "key_hash": "98d4c330...", "cost_data": {"base_msats": 0, "input_msats": 21321, "output_msats": 1511, "total_msats": 22834}, "balance_after_adjustment": 3792947} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "method": "POST", "path": "/v1/chat/completions", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "93.113.215.62", "x-forwarded-for": "93.113.215.62", "x-forwarded-proto": "https", "connection": "close", "content-length": "27484", "content-type": "application/json", "accept": "*/*", "accept-encoding": "gzip, br, zstd, deflate"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "Received proxy request", "pathname": "/app/routstr/proxy.py", "lineno": 463, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "method": "POST", "path": "v1/chat/completions", "client_host": "172.18.0.1", "user_agent": "unknown"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "key_hash": "98d4c330...", "balance": 3792947, "total_requests": 340} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "token: [REDACTED]: [REDACTED] successfully", "pathname": "/app/routstr/proxy.py", "lineno": 675, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance": 3792947} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/proxy.py", "lineno": 549, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "path": "v1/chat/completions", "key_hash": "98d4c330...", "key_balance_before": 3792947, "model": "anthropic/claude-sonnet-4"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "INFO", "message": "Processing payment for request", "pathname": "/app/routstr/auth.py", "lineno": 279, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "key_hash": "98d4c330...", "current_balance": 3792947, "required_cost": 1299689, "sufficient_balance": true} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.auth", "levelname": "WARNING", "message": "Insufficient balance for request", "pathname": "/app/routstr/auth.py", "lineno": 290, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "key_hash": "98d4c330...", "balance": 3792947, "reserved_balance": 2508374, "required": 1299689, "shortfall": 15116} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.proxy", "levelname": "ERROR", "message": "Payment processing failed", "pathname": "/app/routstr/proxy.py", "lineno": 571, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "error": "402: {'error': {'message': 'Insufficient balance: 1299689 mSats required. 1284573 available. (reserved: 2508374)', 'type': 'insufficient_quota', 'code': 'insufficient_balance'}}", "error_type": "HTTPException", "path": "v1/chat/completions", "key_hash": "98d4c330..."} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.core.exceptions", "levelname": "WARNING", "message": "HTTP exception", "pathname": "/app/routstr/core/exceptions.py", "lineno": 17, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "status_code": 402, "detail": {"error": {"message": "Insufficient balance: 1299689 mSats required. 1284573 available. (reserved: 2508374)", "type": "insufficient_quota", "code": "insufficient_balance"}}, "path": "/v1/chat/completions"} +{"asctime": "2025-09-04 14:08:22", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "fe77405e-c0fe-498c-801a-ae6aa5a61fd0", "method": "POST", "path": "/v1/chat/completions", "status_code": 402, "duration_ms": 33.46, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "aa0f8d89-f42d-4f38-b680-325bc1eca569", "method": "OPTIONS", "path": "/v1/wallet/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "185.209.196.248", "x-forwarded-for": "185.209.196.248", "x-forwarded-proto": "https", "connection": "close", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", "accept": "*/*", "accept-language": "en-US,en;q=0.5", "accept-encoding": "gzip, deflate, br, zstd", "access-control-request-method": "GET", "access-control-request-headers": "authorization", "referer": "https://chat.routstr.com/", "origin": "https://chat.routstr.com", "dnt": "1", "sec-gpc": "1", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "cross-site", "priority": "u=4"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "aa0f8d89-f42d-4f38-b680-325bc1eca569", "method": "OPTIONS", "path": "/v1/wallet/info", "status_code": 200, "duration_ms": 2.31, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "4b1f47bd-a813-4024-a87e-f0e57b2bd247", "method": "GET", "path": "/v1/wallet/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "185.209.196.248", "x-forwarded-for": "185.209.196.248", "x-forwarded-proto": "https", "connection": "close", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", "accept": "*/*", "accept-language": "en-US,en;q=0.5", "accept-encoding": "gzip, deflate, br, zstd", "referer": "https://chat.routstr.com/", "origin": "https://chat.routstr.com", "dnt": "1", "sec-gpc": "1", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "cross-site", "priority": "u=0"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "4b1f47bd-a813-4024-a87e-f0e57b2bd247", "key_hash": "e1129de6...", "balance": 131636.79653060454, "total_requests": 32} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "4b1f47bd-a813-4024-a87e-f0e57b2bd247", "method": "GET", "path": "/v1/wallet/info", "status_code": 200, "duration_ms": 13.76, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "0ffc1a37-4558-4a28-80b2-76476ad12f36", "method": "GET", "path": "/v1/wallet/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "185.209.196.248", "x-forwarded-for": "185.209.196.248", "x-forwarded-proto": "https", "connection": "close", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", "accept": "*/*", "accept-language": "en-US,en;q=0.5", "accept-encoding": "gzip, deflate, br, zstd", "referer": "https://chat.routstr.com/", "origin": "https://chat.routstr.com", "dnt": "1", "sec-gpc": "1", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "cross-site", "priority": "u=4"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.auth", "levelname": "INFO", "message": "Existing Cashu token: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 127, "version": "0.1.1b", "request_id": "0ffc1a37-4558-4a28-80b2-76476ad12f36", "key_hash": "0553ba5f...", "balance": 46262, "total_requests": 592} +{"asctime": "2025-09-04 14:08:38", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "0ffc1a37-4558-4a28-80b2-76476ad12f36", "method": "GET", "path": "/v1/wallet/info", "status_code": 200, "duration_ms": 13.51, "client_host": "172.18.0.1"} +{"asctime": "2025-09-04 14:08:42", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Incoming request", "pathname": "/app/routstr/core/middleware.py", "lineno": 47, "version": "0.1.1b", "request_id": "43cf8a96-dcf4-4c06-b29d-68f234fc61e4", "method": "GET", "path": "/v1/wallet/info", "query_params": {}, "client_host": "172.18.0.1", "headers": {"host": "ai.redsh1ft.com", "x-real-ip": "185.209.196.248", "x-forwarded-for": "185.209.196.248", "x-forwarded-proto": "https", "connection": "close", "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", "accept": "*/*", "accept-language": "en-US,en;q=0.5", "accept-encoding": "gzip, deflate, br, zstd", "referer": "https://chat.routstr.com/", "origin": "https://chat.routstr.com", "dnt": "1", "sec-gpc": "1", "sec-fetch-dest": "empty", "sec-fetch-mode": "cors", "sec-fetch-site": "cross-site", "priority": "u=4"}, "body_size": 0} +{"asctime": "2025-09-04 14:08:42", "name": "routstr.auth", "levelname": "INFO", "message": "Existing sk- API key: [REDACTED]", "pathname": "/app/routstr/auth.py", "lineno": 72, "version": "0.1.1b", "request_id": "43cf8a96-dcf4-4c06-b29d-68f234fc61e4", "key_hash": "98d4c330...", "balance": 3792947, "total_requests": 340} +{"asctime": "2025-09-04 14:08:42", "name": "routstr.core.middleware", "levelname": "INFO", "message": "Request completed", "pathname": "/app/routstr/core/middleware.py", "lineno": 86, "version": "0.1.1b", "request_id": "43cf8a96-dcf4-4c06-b29d-68f234fc61e4", "method": "GET", "path": "/v1/wallet/info", "status_code": 200, "duration_ms": 11.4, "client_host": "172.18.0.1"}