codexLB-up 1.25.0b10__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- app/__init__.py +10 -0
- app/admin_cli.py +494 -0
- app/cli.py +339 -0
- app/codex_sessions_retag.py +487 -0
- app/core/__init__.py +0 -0
- app/core/audit/__init__.py +0 -0
- app/core/audit/service.py +216 -0
- app/core/audit/types.py +94 -0
- app/core/auth/__init__.py +236 -0
- app/core/auth/api_key_cache.py +65 -0
- app/core/auth/dashboard_access.py +429 -0
- app/core/auth/dashboard_mode.py +171 -0
- app/core/auth/dashboard_session_ttl.py +74 -0
- app/core/auth/dashboard_users_cache.py +120 -0
- app/core/auth/dependencies.py +710 -0
- app/core/auth/external_identity.py +78 -0
- app/core/auth/guardian.py +374 -0
- app/core/auth/models.py +49 -0
- app/core/auth/providers/__init__.py +129 -0
- app/core/auth/providers/oidc.py +838 -0
- app/core/auth/providers/registry.py +118 -0
- app/core/auth/refresh.py +394 -0
- app/core/auth/step_up.py +117 -0
- app/core/auth/totp.py +81 -0
- app/core/balancer/__init__.py +71 -0
- app/core/balancer/logic.py +1612 -0
- app/core/balancer/rendezvous_hash.py +21 -0
- app/core/balancer/types.py +21 -0
- app/core/bootstrap.py +172 -0
- app/core/cache/invalidation.py +426 -0
- app/core/clients/__init__.py +0 -0
- app/core/clients/codex.py +996 -0
- app/core/clients/codex_version.py +187 -0
- app/core/clients/codex_version_snapshot.py +2 -0
- app/core/clients/files.py +534 -0
- app/core/clients/headers.py +29 -0
- app/core/clients/http.py +511 -0
- app/core/clients/model_fetcher.py +276 -0
- app/core/clients/native_egress.py +1304 -0
- app/core/clients/oauth.py +477 -0
- app/core/clients/proxy.py +6089 -0
- app/core/clients/proxy_websocket.py +1411 -0
- app/core/clients/rate_limit_reset_credits.py +412 -0
- app/core/clients/stream_errors.py +12 -0
- app/core/clients/thread_cache_identity.py +347 -0
- app/core/clients/usage.py +467 -0
- app/core/clock.py +170 -0
- app/core/config/__init__.py +0 -0
- app/core/config/background_jobs.py +73 -0
- app/core/config/context_window_overrides.py +166 -0
- app/core/config/dashboard_overrides.py +145 -0
- app/core/config/inheritable.py +47 -0
- app/core/config/key_fingerprint.py +115 -0
- app/core/config/settings.py +872 -0
- app/core/config/settings_cache.py +100 -0
- app/core/config/spool_retention.py +217 -0
- app/core/config/tiers.py +174 -0
- app/core/conversation_archive.py +568 -0
- app/core/crypto.py +37 -0
- app/core/draining.py +11 -0
- app/core/errors.py +365 -0
- app/core/exceptions.py +155 -0
- app/core/handlers/__init__.py +3 -0
- app/core/handlers/exceptions.py +478 -0
- app/core/http_protocol.py +176 -0
- app/core/http_protocol_httptools.py +204 -0
- app/core/ingress_limits.py +17 -0
- app/core/metadata_store.py +18 -0
- app/core/metrics/__init__.py +0 -0
- app/core/metrics/middleware.py +74 -0
- app/core/metrics/prometheus.py +604 -0
- app/core/middleware/__init__.py +25 -0
- app/core/middleware/api_firewall.py +111 -0
- app/core/middleware/app_version.py +37 -0
- app/core/middleware/dashboard_auth_proxy.py +55 -0
- app/core/middleware/dashboard_csrf.py +177 -0
- app/core/middleware/dashboard_gzip.py +41 -0
- app/core/middleware/dashboard_overrides.py +59 -0
- app/core/middleware/firewall_cache.py +91 -0
- app/core/middleware/inflight.py +126 -0
- app/core/middleware/multipart_content_encoding.py +129 -0
- app/core/middleware/path_rewrite.py +148 -0
- app/core/middleware/request_body_limit.py +196 -0
- app/core/middleware/request_decompression.py +209 -0
- app/core/middleware/request_id.py +72 -0
- app/core/middleware/required_capability_http.py +116 -0
- app/core/middleware/trusted_proxy_headers.py +36 -0
- app/core/multipart.py +237 -0
- app/core/multipart_fields.py +91 -0
- app/core/openai/__init__.py +0 -0
- app/core/openai/chat_requests.py +493 -0
- app/core/openai/chat_responses.py +931 -0
- app/core/openai/contracts.py +46 -0
- app/core/openai/exceptions.py +24 -0
- app/core/openai/host_models.py +14 -0
- app/core/openai/images.py +413 -0
- app/core/openai/message_coercion.py +376 -0
- app/core/openai/model_refresh_scheduler.py +423 -0
- app/core/openai/model_registry.py +997 -0
- app/core/openai/model_registry_store.py +548 -0
- app/core/openai/models.py +172 -0
- app/core/openai/parsing.py +97 -0
- app/core/openai/requests.py +1980 -0
- app/core/openai/strict_schema.py +199 -0
- app/core/openai/tool_call_safety.py +99 -0
- app/core/openai/v1_requests.py +187 -0
- app/core/plan_types.py +90 -0
- app/core/prestop.py +202 -0
- app/core/rate_limiter/__init__.py +0 -0
- app/core/rate_limiter/db_rate_limiter.py +215 -0
- app/core/request_locality.py +473 -0
- app/core/resilience/__init__.py +0 -0
- app/core/resilience/backpressure.py +57 -0
- app/core/resilience/bulkhead.py +202 -0
- app/core/resilience/circuit_breaker.py +150 -0
- app/core/resilience/degradation.py +55 -0
- app/core/resilience/loop_lag_monitor.py +60 -0
- app/core/resilience/memory_monitor.py +137 -0
- app/core/resilience/network_recovery.py +256 -0
- app/core/resilience/overload.py +98 -0
- app/core/resilience/toggles.py +114 -0
- app/core/retention/__init__.py +0 -0
- app/core/retention/job.py +240 -0
- app/core/retention/scheduler.py +69 -0
- app/core/runtime_logging.py +601 -0
- app/core/scheduling/__init__.py +0 -0
- app/core/scheduling/leader_election.py +993 -0
- app/core/scheduling/leader_election_handle.py +25 -0
- app/core/server.py +140 -0
- app/core/shutdown.py +326 -0
- app/core/socket_peer.py +22 -0
- app/core/startup.py +41 -0
- app/core/timeout_invariants.py +347 -0
- app/core/tracing/__init__.py +0 -0
- app/core/tracing/otel.py +207 -0
- app/core/types.py +6 -0
- app/core/upstream_proxy/__init__.py +13 -0
- app/core/upstream_proxy/cache.py +130 -0
- app/core/upstream_proxy/resolver.py +189 -0
- app/core/upstream_proxy/types.py +104 -0
- app/core/usage/__init__.py +407 -0
- app/core/usage/depletion.py +109 -0
- app/core/usage/live_hub.py +41 -0
- app/core/usage/live_snapshots.py +174 -0
- app/core/usage/logs.py +212 -0
- app/core/usage/metadata_scheduler.py +118 -0
- app/core/usage/models.py +54 -0
- app/core/usage/pricing.py +576 -0
- app/core/usage/pricing_catalog.py +241 -0
- app/core/usage/pricing_snapshot.json +821 -0
- app/core/usage/quota.py +133 -0
- app/core/usage/refresh_policy.py +21 -0
- app/core/usage/refresh_scheduler.py +713 -0
- app/core/usage/reset_credits_refresh_scheduler.py +435 -0
- app/core/usage/types.py +168 -0
- app/core/utils/__init__.py +0 -0
- app/core/utils/json_guards.py +18 -0
- app/core/utils/locks.py +33 -0
- app/core/utils/masking.py +20 -0
- app/core/utils/proxy_env.py +104 -0
- app/core/utils/request_id.py +65 -0
- app/core/utils/retry.py +77 -0
- app/core/utils/shared_future.py +172 -0
- app/core/utils/sse.py +286 -0
- app/core/utils/time.py +24 -0
- app/db/__init__.py +0 -0
- app/db/account_identity_lock.py +56 -0
- app/db/alembic/__init__.py +1 -0
- app/db/alembic/env.py +70 -0
- app/db/alembic/revision_ids.py +43 -0
- app/db/alembic/versions/20260213_000000_base_schema.py +248 -0
- app/db/alembic/versions/20260213_000100_normalize_account_plan_types.py +45 -0
- app/db/alembic/versions/20260213_000200_add_request_logs_reasoning_effort.py +45 -0
- app/db/alembic/versions/20260213_000300_add_accounts_reset_at.py +45 -0
- app/db/alembic/versions/20260213_000400_add_accounts_chatgpt_account_id.py +45 -0
- app/db/alembic/versions/20260213_000500_add_dashboard_settings.py +70 -0
- app/db/alembic/versions/20260213_000600_add_dashboard_settings_totp.py +64 -0
- app/db/alembic/versions/20260213_000700_add_dashboard_settings_password.py +59 -0
- app/db/alembic/versions/20260213_000800_add_api_keys.py +87 -0
- app/db/alembic/versions/20260214_000000_add_api_key_limits.py +143 -0
- app/db/alembic/versions/20260215_000000_add_idx_logs_requested_at.py +38 -0
- app/db/alembic/versions/20260218_000000_add_api_key_usage_reservations.py +117 -0
- app/db/alembic/versions/20260218_000100_add_import_without_overwrite_and_drop_accounts_email_unique.py +198 -0
- app/db/alembic/versions/20260225_000000_add_dashboard_settings_routing_strategy.py +53 -0
- app/db/alembic/versions/20260228_020000_align_api_key_limit_enum_types.py +104 -0
- app/db/alembic/versions/20260228_030000_add_api_firewall_allowlist.py +42 -0
- app/db/alembic/versions/20260306_000000_add_request_logs_service_tier.py +45 -0
- app/db/alembic/versions/20260307_000000_add_api_key_enforcement_fields.py +56 -0
- app/db/alembic/versions/20260308_000000_add_sqlite_performance_indexes.py +41 -0
- app/db/alembic/versions/20260309_000000_add_additional_usage_history.py +71 -0
- app/db/alembic/versions/20260309_000000_request_logs_nullable_account_id.py +28 -0
- app/db/alembic/versions/20260310_000000_add_request_logs_transport.py +45 -0
- app/db/alembic/versions/20260310_000000_fix_postgresql_enum_value_casing.py +79 -0
- app/db/alembic/versions/20260310_120000_add_sticky_session_kinds_and_affinity_ttl.py +110 -0
- app/db/alembic/versions/20260312_000000_add_additional_usage_quota_key.py +193 -0
- app/db/alembic/versions/20260312_000000_split_sticky_sessions_primary_key_by_kind.py +96 -0
- app/db/alembic/versions/20260312_010000_merge_additional_usage_and_sticky_session_heads.py +25 -0
- app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_feature_heads.py +25 -0
- app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_sticky_heads.py +25 -0
- app/db/alembic/versions/20260312_120000_add_dashboard_upstream_stream_transport.py +62 -0
- app/db/alembic/versions/20260313_024500_merge_request_log_transport_heads.py +27 -0
- app/db/alembic/versions/20260319_100937_increase_prompt_cache_ttl_to_1800s.py +73 -0
- app/db/alembic/versions/20260319_111500_merge_prompt_cache_ttl_and_upstream_transport_heads.py +25 -0
- app/db/alembic/versions/20260319_183000_normalize_sqlite_account_status_casing.py +48 -0
- app/db/alembic/versions/20260320_000000_add_request_log_requested_actual_tiers.py +51 -0
- app/db/alembic/versions/20260321_190000_tighten_dashboard_db_indexes.py +64 -0
- app/db/alembic/versions/20260321_210000_merge_request_log_tiers_and_dashboard_index_heads.py +25 -0
- app/db/alembic/versions/20260325_000000_add_request_log_cost.py +193 -0
- app/db/alembic/versions/20260328_000000_add_rate_limit_attempts.py +48 -0
- app/db/alembic/versions/20260328_120000_add_request_log_ttft.py +37 -0
- app/db/alembic/versions/20260328_130000_add_audit_logs_table.py +45 -0
- app/db/alembic/versions/20260328_140000_add_scheduler_leader_table.py +39 -0
- app/db/alembic/versions/20260330_000000_add_cache_locality_settings.py +69 -0
- app/db/alembic/versions/20260330_010000_merge_scheduler_leader_and_cache_locality_heads.py +25 -0
- app/db/alembic/versions/20260330_020000_add_bridge_ring_members.py +46 -0
- app/db/alembic/versions/20260401_000000_add_api_key_enforced_service_tier.py +52 -0
- app/db/alembic/versions/20260401_000000_add_cache_invalidation.py +41 -0
- app/db/alembic/versions/20260401_020000_merge_cache_invalidation_and_api_key_service_tier_heads.py +22 -0
- app/db/alembic/versions/20260402_000000_switch_dashboard_routing_default_to_capacity_weighted.py +66 -0
- app/db/alembic/versions/20260403_000000_add_credit_api_key_limit_values.py +44 -0
- app/db/alembic/versions/20260406_000000_add_api_key_account_assignments.py +57 -0
- app/db/alembic/versions/20260406_010000_add_api_key_assignment_scope_flag.py +75 -0
- app/db/alembic/versions/20260407_000000_add_bridge_gateway_safe_mode.py +51 -0
- app/db/alembic/versions/20260407_010000_merge_api_key_assignment_and_bridge_gateway_heads.py +25 -0
- app/db/alembic/versions/20260408_000000_switch_import_without_overwrite_default_to_true.py +73 -0
- app/db/alembic/versions/20260408_010000_merge_import_without_overwrite_and_assignment_heads.py +25 -0
- app/db/alembic/versions/20260409_000000_add_http_bridge_sessions.py +130 -0
- app/db/alembic/versions/20260409_000000_switch_sticky_threads_and_prefer_earlier_reset_defaults_to_true.py +89 -0
- app/db/alembic/versions/20260409_010000_add_dashboard_settings_bootstrap_token.py +57 -0
- app/db/alembic/versions/20260409_010000_merge_http_bridge_and_import_without_overwrite_heads.py +25 -0
- app/db/alembic/versions/20260409_020000_fix_http_bridge_last_seen_index.py +46 -0
- app/db/alembic/versions/20260410_000000_backfill_pristine_dashboard_settings_defaults.py +77 -0
- app/db/alembic/versions/20260410_030000_restore_import_without_overwrite_default_true.py +73 -0
- app/db/alembic/versions/20260410_040000_merge_dashboard_defaults_and_import_default_heads.py +25 -0
- app/db/alembic/versions/20260413_000000_add_accounts_blocked_at.py +44 -0
- app/db/alembic/versions/20260415_160000_add_automations_tables.py +189 -0
- app/db/alembic/versions/20260415_160000_add_request_logs_response_lookup_index.py +67 -0
- app/db/alembic/versions/20260417_000000_add_request_log_plan_type.py +44 -0
- app/db/alembic/versions/20260418_190000_add_automation_runs_cycle_key.py +87 -0
- app/db/alembic/versions/20260419_000000_add_automation_run_cycle_metadata.py +56 -0
- app/db/alembic/versions/20260419_020000_add_automation_run_cycles_snapshot_tables.py +342 -0
- app/db/alembic/versions/20260421_000000_add_dashboard_session_ttl_setting.py +51 -0
- app/db/alembic/versions/20260421_120000_merge_request_log_lookup_and_plan_type_heads.py +25 -0
- app/db/alembic/versions/20260421_130000_merge_automation_and_request_log_heads.py +25 -0
- app/db/alembic/versions/20260422_103000_normalize_legacy_automation_run_cycle_keys.py +648 -0
- app/db/alembic/versions/20260423_120000_add_api_key_limit_reset_at_index.py +43 -0
- app/db/alembic/versions/20260424_000000_merge_dashboard_session_ttl_and_request_log_heads.py +25 -0
- app/db/alembic/versions/20260426_000000_add_dashboard_relative_availability_settings.py +68 -0
- app/db/alembic/versions/20260427_130000_add_warmup_model_and_request_kind.py +75 -0
- app/db/alembic/versions/20260506_000000_add_account_routing_policy.py +37 -0
- app/db/alembic/versions/20260509_000000_add_api_key_traffic_class.py +37 -0
- app/db/alembic/versions/20260509_010000_add_additional_quota_routing_policies.py +37 -0
- app/db/alembic/versions/20260513_000000_add_accounts_alias.py +44 -0
- app/db/alembic/versions/20260513_000000_add_api_key_apply_to_codex_model.py +59 -0
- app/db/alembic/versions/20260514_000000_add_request_logs_api_key_time_index.py +43 -0
- app/db/alembic/versions/20260515_000000_add_prefer_earlier_reset_window.py +47 -0
- app/db/alembic/versions/20260515_000000_soft_delete_request_logs_on_account_delete.py +83 -0
- app/db/alembic/versions/20260515_020000_add_split_sticky_budget_thresholds.py +62 -0
- app/db/alembic/versions/20260516_000000_add_sqlite_hot_path_indexes.py +75 -0
- app/db/alembic/versions/20260517_000000_merge_sqlite_hot_path_and_request_log_delete_heads.py +24 -0
- app/db/alembic/versions/20260518_000000_add_http_bridge_durable_input_prefix.py +44 -0
- app/db/alembic/versions/20260518_010000_merge_http_bridge_and_sqlite_recovery_heads.py +25 -0
- app/db/alembic/versions/20260518_120000_add_dashboard_guest_access.py +57 -0
- app/db/alembic/versions/20260520_000000_merge_api_key_and_http_bridge_heads.py +26 -0
- app/db/alembic/versions/20260520_010000_add_request_logs_api_key_account_index.py +45 -0
- app/db/alembic/versions/20260520_010000_merge_automation_and_api_key_heads.py +26 -0
- app/db/alembic/versions/20260520_030000_add_quota_planner.py +194 -0
- app/db/alembic/versions/20260520_040000_merge_quota_planner_and_request_log_index_heads.py +24 -0
- app/db/alembic/versions/20260521_000000_add_account_security_work_authorized.py +46 -0
- app/db/alembic/versions/20260521_000000_merge_dashboard_guest_and_api_key_heads.py +26 -0
- app/db/alembic/versions/20260521_000000_merge_prefer_reset_window_head.py +26 -0
- app/db/alembic/versions/20260521_000000_merge_warmup_and_request_log_index_heads.py +25 -0
- app/db/alembic/versions/20260522_000000_add_limit_warmup_trigger.py +195 -0
- app/db/alembic/versions/20260524_000000_merge_accounts_alias_and_reset_window_heads.py +24 -0
- app/db/alembic/versions/20260525_000000_add_usage_raw_window_latest_index.py +31 -0
- app/db/alembic/versions/20260526_000000_add_request_log_failure_metadata.py +100 -0
- app/db/alembic/versions/20260531_000000_add_account_workspace_identity.py +39 -0
- app/db/alembic/versions/20260531_000000_add_single_account_routing.py +42 -0
- app/db/alembic/versions/20260601_000000_merge_relative_availability_and_usage_raw_heads.py +24 -0
- app/db/alembic/versions/20260601_010000_add_api_key_usage_sections.py +58 -0
- app/db/alembic/versions/20260601_010000_add_routing_policy_persistence.py +67 -0
- app/db/alembic/versions/20260601_010000_merge_security_work_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_010000_merge_split_sticky_and_relative_usage_heads.py +25 -0
- app/db/alembic/versions/20260601_010000_merge_warmup_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_additional_quota_routing_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_quota_planner_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_reset_window_and_relative_availability_heads.py +25 -0
- app/db/alembic/versions/20260601_020000_merge_routing_policy_and_split_threshold_heads.py +24 -0
- app/db/alembic/versions/20260601_020000_merge_warmup_and_request_log_failure_heads.py +25 -0
- app/db/alembic/versions/20260601_030000_merge_single_account_and_routing_quota_heads.py +29 -0
- app/db/alembic/versions/20260601_040000_merge_security_work_and_routing_consolidation_heads.py +25 -0
- app/db/alembic/versions/20260601_050000_merge_quota_planner_and_routing_consolidation_heads.py +25 -0
- app/db/alembic/versions/20260602_050000_add_upstream_proxy_routing.py +164 -0
- app/db/alembic/versions/20260602_060000_merge_account_workspace_and_failure_heads.py +25 -0
- app/db/alembic/versions/20260602_070000_add_request_log_useragent_fields.py +86 -0
- app/db/alembic/versions/20260602_070000_merge_quota_planner_and_account_workspace_heads.py +25 -0
- app/db/alembic/versions/20260602_080000_merge_upstream_proxy_and_quota_planner_heads.py +25 -0
- app/db/alembic/versions/20260602_080000_merge_useragent_and_upstream_proxy_heads.py +24 -0
- app/db/alembic/versions/20260603_000000_add_weekly_pace_working_days.py +52 -0
- app/db/alembic/versions/20260603_000000_free_account_monthly_window.py +60 -0
- app/db/alembic/versions/20260604_000000_add_reauth_required_account_status.py +159 -0
- app/db/alembic/versions/20260604_010000_merge_automations_and_reauth_status_heads.py +25 -0
- app/db/alembic/versions/20260604_010000_merge_dashboard_guest_and_reauth_status_heads.py +25 -0
- app/db/alembic/versions/20260604_010000_merge_useragent_and_reauth_heads.py +24 -0
- app/db/alembic/versions/20260607_000000_merge_weekly_monthly_useragent_heads.py +28 -0
- app/db/alembic/versions/20260608_000000_add_hide_upstream_quota_from_api_keys.py +50 -0
- app/db/alembic/versions/20260611_000000_add_request_log_archive_request_id.py +47 -0
- app/db/alembic/versions/20260611_000000_merge_automations_and_weekly_monthly_useragent_heads.py +26 -0
- app/db/alembic/versions/20260611_000000_merge_dashboard_guest_and_weekly_useragent_heads.py +26 -0
- app/db/alembic/versions/20260611_010000_add_request_log_client_ip.py +57 -0
- app/db/alembic/versions/20260611_020000_merge_request_log_archive_and_client_ip_heads.py +26 -0
- app/db/alembic/versions/20260611_030000_merge_dashboard_guest_and_request_log_client_ip_heads.py +26 -0
- app/db/alembic/versions/20260613_000000_add_accounts_codex_installation_id.py +57 -0
- app/db/alembic/versions/20260613_010000_merge_installation_id_and_dashboard_weekly_heads.py +26 -0
- app/db/alembic/versions/20260615_000000_merge_automations_and_dashboard_guest_heads.py +26 -0
- app/db/alembic/versions/20260623_000000_add_limit_warmup_exhausted_threshold.py +51 -0
- app/db/alembic/versions/20260626_000000_add_http_downstream_transport_policy.py +46 -0
- app/db/alembic/versions/20260626_010000_add_request_logs_upstream_transport.py +31 -0
- app/db/alembic/versions/20260629_000000_add_dashboard_query_hot_path_indexes.py +53 -0
- app/db/alembic/versions/20260630_000000_add_limit_warmup_staggered_idle.py +47 -0
- app/db/alembic/versions/20260630_000000_merge_request_log_client_ip_and_dashboard_hot_path_heads.py +26 -0
- app/db/alembic/versions/20260630_010000_merge_warmup_and_request_log_dashboard_heads.py +26 -0
- app/db/alembic/versions/20260630_020000_merge_automations_and_main_heads.py +26 -0
- app/db/alembic/versions/20260630_020000_merge_warmup_threshold_and_main_heads.py +26 -0
- app/db/alembic/versions/20260630_030000_add_automation_run_model_snapshot.py +59 -0
- app/db/alembic/versions/20260630_040000_merge_automation_snapshot_and_warmup_threshold_heads.py +26 -0
- app/db/alembic/versions/20260630_050000_add_automation_run_prompt_snapshot.py +52 -0
- app/db/alembic/versions/20260701_000000_add_weekly_pace_smoothing_minutes.py +51 -0
- app/db/alembic/versions/20260702_000000_add_model_sources.py +176 -0
- app/db/alembic/versions/20260705_000000_add_model_source_audio_transcriptions.py +50 -0
- app/db/alembic/versions/20260705_000000_harden_dashboard_session_ttl.py +62 -0
- app/db/alembic/versions/20260706_000000_add_model_source_audio_per_minute.py +43 -0
- app/db/alembic/versions/20260707_000000_merge_model_sources_and_session_ttl.py +24 -0
- app/db/alembic/versions/20260707_010000_merge_automations_and_model_sources_heads.py +24 -0
- app/db/alembic/versions/20260707_020000_add_automation_job_account_scope.py +125 -0
- app/db/alembic/versions/20260709_000000_add_ttft_phase_observability.py +66 -0
- app/db/alembic/versions/20260711_000000_add_dashboard_prohibit_fast_mode.py +42 -0
- app/db/alembic/versions/20260711_010000_add_account_chatgpt_user_id.py +40 -0
- app/db/alembic/versions/20260711_020000_add_dashboard_account_concurrency_caps.py +71 -0
- app/db/alembic/versions/20260711_030000_add_limit_warmup_idle_threshold.py +51 -0
- app/db/alembic/versions/20260712_010000_add_account_usage_rollups.py +56 -0
- app/db/alembic/versions/20260712_020000_add_api_key_usage_rollups.py +53 -0
- app/db/alembic/versions/20260713_020000_add_model_registry_snapshot.py +42 -0
- app/db/alembic/versions/20260713_040000_add_account_refresh_claims.py +42 -0
- app/db/alembic/versions/20260713_040000_add_replica_guardrails.py +64 -0
- app/db/alembic/versions/20260713_070000_add_reset_credit_redeem_tables.py +58 -0
- app/db/alembic/versions/20260714_000000_add_oauth_flow_states.py +63 -0
- app/db/alembic/versions/20260715_000000_add_request_log_queue_latency.py +44 -0
- app/db/alembic/versions/20260716_000000_add_oauth_device_flow_slots.py +41 -0
- app/db/alembic/versions/20260716_010000_add_dashboard_retention_settings.py +48 -0
- app/db/alembic/versions/20260716_010000_add_reset_credit_display_settings.py +73 -0
- app/db/alembic/versions/20260717_000000_add_http_bridge_retry_circuits.py +47 -0
- app/db/alembic/versions/20260717_000000_merge_retention_and_reset_credit_display_heads.py +26 -0
- app/db/alembic/versions/20260717_000000_optimize_dashboard_hot_path_indexes.py +162 -0
- app/db/alembic/versions/20260717_000001_merge_retry_circuits_and_dashboard_indexes.py +22 -0
- app/db/alembic/versions/20260720_000000_add_request_log_conversation_id.py +57 -0
- app/db/alembic/versions/20260722_000000_backfill_request_log_useragent_families.py +40 -0
- app/db/alembic/versions/20260724_000000_add_request_usage_time_rollups.py +176 -0
- app/db/alembic/versions/20260724_000000_merge_request_log_schema_heads.py +33 -0
- app/db/alembic/versions/20260725_000000_add_http_bridge_pending_tool_calls.py +43 -0
- app/db/alembic/versions/20260726_000000_add_account_plan_downgrade_observations.py +44 -0
- app/db/alembic/versions/20260726_000000_repair_request_usage_rollups_after_merge.py +37 -0
- app/db/alembic/versions/20260727_000000_add_sticky_session_continuity_abandoned_at.py +45 -0
- app/db/alembic/versions/20260728_000000_merge_pending_tool_calls_and_rollup_repair_heads.py +31 -0
- app/db/alembic/versions/20260730_000000_add_api_key_fair_share_threshold.py +44 -0
- app/db/alembic/versions/20260730_000000_add_http_bridge_recovery_attempts.py +60 -0
- app/db/alembic/versions/20260731_000000_add_capability_lineage_markers.py +38 -0
- app/db/alembic/versions/20260803_000000_merge_http_bridge_recovery_and_capability_lineage_heads.py +30 -0
- app/db/alembic/versions/20260804_000000_add_http_bridge_operations.py +63 -0
- app/db/alembic/versions/20260804_000001_add_global_http_bridge_operation_fingerprint.py +53 -0
- app/db/alembic/versions/20260804_230000_add_request_log_connection_request_kind.py +43 -0
- app/db/alembic/versions/20260805_000000_add_http_bridge_operation_spool.py +75 -0
- app/db/alembic/versions/20260805_000001_finalize_http_bridge_operation_spool.py +65 -0
- app/db/alembic/versions/20260806_000000_add_additional_usage_alias_probe_indexes.py +84 -0
- app/db/alembic/versions/20260806_000000_add_anonymous_telemetry.py +49 -0
- app/db/alembic/versions/20260806_010000_add_conversation_presence_rollup.py +72 -0
- app/db/alembic/versions/20260806_020000_add_usage_history_bulk_covering_indexes.py +99 -0
- app/db/alembic/versions/20260806_030000_add_api_key_allowed_reasoning_efforts.py +65 -0
- app/db/alembic/versions/20260806_120000_add_http_bridge_owner_process_epoch.py +57 -0
- app/db/alembic/versions/20260807_000000_merge_http_bridge_operation_spool_and_latest_main.py +24 -0
- app/db/alembic/versions/20260808_000000_tune_usage_history_autovacuum.py +54 -0
- app/db/alembic/versions/20260810_000000_add_http_bridge_recovery_dispatch_count.py +44 -0
- app/db/alembic/versions/20260811_000000_add_hourly_rollup_cancelled_count.py +92 -0
- app/db/alembic/versions/20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads.py +25 -0
- app/db/alembic/versions/20260812_120000_add_sticky_abandonment_scope.py +43 -0
- app/db/alembic/versions/20260813_000000_add_file_account_pins.py +40 -0
- app/db/alembic/versions/20260816_000000_add_account_pending_deletion.py +81 -0
- app/db/alembic/versions/20260816_000000_add_model_source_embeddings.py +50 -0
- app/db/alembic/versions/20260821_000000_add_retry_circuit_admission_generation.py +49 -0
- app/db/alembic/versions/20260826_000000_add_http_bridge_event_chunks.py +107 -0
- app/db/alembic/versions/20260828_000000_add_accounts_chatgpt_identity_index.py +55 -0
- app/db/alembic/versions/20260830_000000_add_quota_warmup_claim_expiry.py +83 -0
- app/db/alembic/versions/20260908_000000_add_guest_session_generation.py +37 -0
- app/db/alembic/versions/20260908_000000_add_subscription_overflow.py +140 -0
- app/db/alembic/versions/20260908_000000_replace_upstream_stream_transport_default_sentinel.py +50 -0
- app/db/alembic/versions/20260908_020000_merge_overflow_transport_heads.py +27 -0
- app/db/alembic/versions/20260909_000000_add_dashboard_roles.py +72 -0
- app/db/alembic/versions/20260909_010000_add_dashboard_users.py +183 -0
- app/db/alembic/versions/20260909_020000_reproject_compat_admin_credentials.py +105 -0
- app/db/alembic/versions/20260909_030000_add_audit_actor_columns.py +103 -0
- app/db/alembic/versions/20260909_030000_dashboard_resilience_toggle_settings.py +63 -0
- app/db/alembic/versions/20260909_040000_add_dashboard_user_invites.py +54 -0
- app/db/alembic/versions/20260909_040000_dashboard_timeout_settings.py +68 -0
- app/db/alembic/versions/20260909_050000_dashboard_routing_overload_settings.py +65 -0
- app/db/alembic/versions/20260909_060000_add_report_rollup.py +74 -0
- app/db/alembic/versions/20260909_070000_automation_run_claim_budget.py +50 -0
- app/db/alembic/versions/20260909_080000_dashboard_stream_bridge_budgets.py +62 -0
- app/db/alembic/versions/20260909_090000_dashboard_background_job_toggles.py +63 -0
- app/db/alembic/versions/20260909_100000_dashboard_codex_prewarm.py +49 -0
- app/db/alembic/versions/20260909_110000_model_context_window_overrides.py +45 -0
- app/db/alembic/versions/20260909_120000_dashboard_conversation_archive.py +48 -0
- app/db/alembic/versions/20260909_130000_add_request_logs_live_facet_indexes.py +96 -0
- app/db/alembic/versions/20260910_000000_add_totp_required_for_admin_role.py +44 -0
- app/db/alembic/versions/20260910_000000_request_logs_missing_cost_index.py +52 -0
- app/db/alembic/versions/20260910_010000_add_dashboard_auth_providers.py +134 -0
- app/db/alembic/versions/20260910_010000_dashboard_spool_retention.py +52 -0
- app/db/alembic/versions/20260910_020000_add_dashboard_role_mappings.py +74 -0
- app/db/alembic/versions/20260910_143000_request_log_affinity.py +28 -0
- app/db/alembic/versions/20260910_180000_merge_affinity_guest_heads.py +17 -0
- app/db/alembic/versions/20260910_200000_merge_affinity_identity_heads.py +17 -0
- app/db/alembic/versions/20260910_220000_merge_affinity_invite_heads.py +17 -0
- app/db/alembic/versions/20260911_000000_model_source_pins_kind_expires_index.py +43 -0
- app/db/alembic/versions/20260911_010000_merge_pin_index_and_affinity_heads.py +17 -0
- app/db/alembic/versions/20260911_020000_add_http_bridge_terminal_append_phase.py +54 -0
- app/db/alembic/versions/20260911_030000_add_local_login_policy.py +48 -0
- app/db/alembic/versions/20260911_040000_add_thread_cache_identity_mode.py +48 -0
- app/db/alembic/versions/20260911_060000_add_bridge_session_continuity_abandonment.py +40 -0
- app/db/alembic/versions/20260912_000000_merge_thread_cache_and_bridge_retirement_heads.py +22 -0
- app/db/alembic/versions/20260912_010000_drop_legacy_dashboard_credentials.py +140 -0
- app/db/alembic/versions/20260913_000000_add_oidc_provider_flow.py +134 -0
- app/db/alembic/versions/20260914_000000_add_scim_tokens.py +78 -0
- app/db/alembic/versions/20260914_000000_drop_subscription_overflow_schema.py +132 -0
- app/db/alembic/versions/20260918_000000_merge_scim_and_overflow_heads.py +17 -0
- app/db/alembic/versions/__init__.py +1 -0
- app/db/backup.py +64 -0
- app/db/migrate.py +1249 -0
- app/db/migration_lock.py +160 -0
- app/db/migration_url.py +18 -0
- app/db/models.py +3100 -0
- app/db/recover.py +244 -0
- app/db/session.py +1295 -0
- app/db/snapshot.py +46 -0
- app/db/sqlite_lock_retry.py +190 -0
- app/db/sqlite_utils.py +549 -0
- app/dependencies.py +462 -0
- app/main.py +1240 -0
- app/modules/__init__.py +0 -0
- app/modules/accounts/__init__.py +0 -0
- app/modules/accounts/api.py +426 -0
- app/modules/accounts/auth_manager.py +1439 -0
- app/modules/accounts/background_repository.py +160 -0
- app/modules/accounts/deletion.py +540 -0
- app/modules/accounts/mappers.py +654 -0
- app/modules/accounts/refresh_claims.py +352 -0
- app/modules/accounts/repository.py +1679 -0
- app/modules/accounts/schemas.py +308 -0
- app/modules/accounts/service.py +809 -0
- app/modules/accounts/usage_rollup.py +486 -0
- app/modules/accounts/usage_rollup_scheduler.py +75 -0
- app/modules/accounts/usage_time_rollup.py +1037 -0
- app/modules/accounts/usage_time_rollup_read.py +522 -0
- app/modules/api_keys/__init__.py +1 -0
- app/modules/api_keys/api.py +344 -0
- app/modules/api_keys/last_used_coalescer.py +216 -0
- app/modules/api_keys/limit_windows.py +41 -0
- app/modules/api_keys/repository.py +1200 -0
- app/modules/api_keys/reset_scheduler.py +85 -0
- app/modules/api_keys/schemas.py +135 -0
- app/modules/api_keys/service.py +2123 -0
- app/modules/audit/__init__.py +0 -0
- app/modules/audit/api.py +88 -0
- app/modules/audit/repository.py +74 -0
- app/modules/audit/schemas.py +33 -0
- app/modules/audit/service.py +71 -0
- app/modules/auth_providers/__init__.py +0 -0
- app/modules/auth_providers/api.py +127 -0
- app/modules/auth_providers/config.py +343 -0
- app/modules/auth_providers/repository.py +101 -0
- app/modules/auth_providers/schemas.py +88 -0
- app/modules/auth_providers/seed.py +105 -0
- app/modules/auth_providers/service.py +289 -0
- app/modules/automations/__init__.py +1 -0
- app/modules/automations/api.py +369 -0
- app/modules/automations/repository.py +1896 -0
- app/modules/automations/scheduler.py +107 -0
- app/modules/automations/schemas.py +158 -0
- app/modules/automations/service.py +2548 -0
- app/modules/cache_isolation_probe/__init__.py +0 -0
- app/modules/cache_isolation_probe/api.py +188 -0
- app/modules/cache_isolation_probe/prefix.py +144 -0
- app/modules/cache_isolation_probe/schemas.py +94 -0
- app/modules/cache_isolation_probe/sender.py +229 -0
- app/modules/cache_isolation_probe/service.py +525 -0
- app/modules/conversation_archive/__init__.py +1 -0
- app/modules/conversation_archive/api.py +101 -0
- app/modules/conversation_archive/schemas.py +28 -0
- app/modules/conversation_archive/service.py +165 -0
- app/modules/dashboard/__init__.py +1 -0
- app/modules/dashboard/api.py +106 -0
- app/modules/dashboard/builders.py +107 -0
- app/modules/dashboard/repository.py +304 -0
- app/modules/dashboard/schemas.py +148 -0
- app/modules/dashboard/service.py +534 -0
- app/modules/dashboard/timeframes.py +19 -0
- app/modules/dashboard/weekly_pace.py +617 -0
- app/modules/dashboard_auth/__init__.py +1 -0
- app/modules/dashboard_auth/api.py +1344 -0
- app/modules/dashboard_auth/oidc_api.py +753 -0
- app/modules/dashboard_auth/oidc_flows.py +330 -0
- app/modules/dashboard_auth/repository.py +452 -0
- app/modules/dashboard_auth/schemas.py +232 -0
- app/modules/dashboard_auth/service.py +1384 -0
- app/modules/dashboard_roles/__init__.py +0 -0
- app/modules/dashboard_roles/api.py +64 -0
- app/modules/dashboard_roles/repository.py +54 -0
- app/modules/dashboard_roles/schemas.py +29 -0
- app/modules/dashboard_roles/seed.py +80 -0
- app/modules/dashboard_roles/service.py +142 -0
- app/modules/dashboard_users/__init__.py +0 -0
- app/modules/dashboard_users/api.py +278 -0
- app/modules/dashboard_users/break_glass.py +169 -0
- app/modules/dashboard_users/credentials.py +18 -0
- app/modules/dashboard_users/identity_resolver.py +665 -0
- app/modules/dashboard_users/repository.py +725 -0
- app/modules/dashboard_users/schemas.py +117 -0
- app/modules/dashboard_users/service.py +1054 -0
- app/modules/firewall/__init__.py +1 -0
- app/modules/firewall/api.py +78 -0
- app/modules/firewall/repository.py +51 -0
- app/modules/firewall/schemas.py +28 -0
- app/modules/firewall/service.py +93 -0
- app/modules/fleet/__init__.py +1 -0
- app/modules/fleet/api.py +177 -0
- app/modules/fleet/mappers.py +56 -0
- app/modules/fleet/observability.py +372 -0
- app/modules/fleet/schemas.py +119 -0
- app/modules/health/__init__.py +0 -0
- app/modules/health/api.py +246 -0
- app/modules/health/schemas.py +27 -0
- app/modules/limit_warmup/__init__.py +1 -0
- app/modules/limit_warmup/repository.py +159 -0
- app/modules/limit_warmup/service.py +1001 -0
- app/modules/model_sources/__init__.py +1 -0
- app/modules/model_sources/api.py +99 -0
- app/modules/model_sources/catalog.py +307 -0
- app/modules/model_sources/forwarding.py +1435 -0
- app/modules/model_sources/projection.py +55 -0
- app/modules/model_sources/repository.py +201 -0
- app/modules/model_sources/schemas.py +79 -0
- app/modules/model_sources/selection.py +166 -0
- app/modules/model_sources/service.py +236 -0
- app/modules/oauth/__init__.py +0 -0
- app/modules/oauth/api.py +101 -0
- app/modules/oauth/repository.py +238 -0
- app/modules/oauth/schemas.py +49 -0
- app/modules/oauth/service.py +1196 -0
- app/modules/oauth/templates/oauth_success.html +122 -0
- app/modules/proxy/__init__.py +0 -0
- app/modules/proxy/_load_balancer/__init__.py +1 -0
- app/modules/proxy/_load_balancer/error_rate.py +116 -0
- app/modules/proxy/_load_balancer/latency_cohort.py +154 -0
- app/modules/proxy/_load_balancer/model_eligibility.py +250 -0
- app/modules/proxy/_load_balancer/opportunistic_admission.py +350 -0
- app/modules/proxy/_load_balancer/overload_backoff.py +394 -0
- app/modules/proxy/_load_balancer/sticky_selection.py +2417 -0
- app/modules/proxy/_load_balancer/throughput_cohort.py +233 -0
- app/modules/proxy/_load_balancer/ttft_cohort.py +214 -0
- app/modules/proxy/_load_balancer/tunables.py +97 -0
- app/modules/proxy/_load_balancer/types.py +96 -0
- app/modules/proxy/_load_balancer/unbound_selection.py +534 -0
- app/modules/proxy/_service/__init__.py +6 -0
- app/modules/proxy/_service/api_key_usage.py +745 -0
- app/modules/proxy/_service/clock_budget.py +38 -0
- app/modules/proxy/_service/codex_control.py +611 -0
- app/modules/proxy/_service/compact.py +2211 -0
- app/modules/proxy/_service/file_ops.py +749 -0
- app/modules/proxy/_service/http_bridge/__init__.py +3 -0
- app/modules/proxy/_service/http_bridge/accepted_replay.py +331 -0
- app/modules/proxy/_service/http_bridge/account_sessions.py +57 -0
- app/modules/proxy/_service/http_bridge/activity.py +178 -0
- app/modules/proxy/_service/http_bridge/helpers.py +3959 -0
- app/modules/proxy/_service/http_bridge/mixin.py +2435 -0
- app/modules/proxy/_service/http_bridge/owner_forwarding.py +609 -0
- app/modules/proxy/_service/http_bridge/protocol.py +167 -0
- app/modules/proxy/_service/http_bridge/proxy_failover.py +58 -0
- app/modules/proxy/_service/http_bridge/quarantine.py +443 -0
- app/modules/proxy/_service/http_bridge/request_submit.py +4582 -0
- app/modules/proxy/_service/http_bridge/retry_circuit.py +2442 -0
- app/modules/proxy/_service/http_bridge/service_stubs.py +492 -0
- app/modules/proxy/_service/http_bridge/session_registry.py +778 -0
- app/modules/proxy/_service/http_bridge/streaming.py +5328 -0
- app/modules/proxy/_service/http_bridge/upstream_events.py +4538 -0
- app/modules/proxy/_service/observability.py +410 -0
- app/modules/proxy/_service/rate_limit.py +361 -0
- app/modules/proxy/_service/realtime_live.py +655 -0
- app/modules/proxy/_service/refresh.py +154 -0
- app/modules/proxy/_service/request_log.py +585 -0
- app/modules/proxy/_service/response_create.py +930 -0
- app/modules/proxy/_service/streaming/__init__.py +3 -0
- app/modules/proxy/_service/streaming/helpers.py +1317 -0
- app/modules/proxy/_service/streaming/mixin.py +1100 -0
- app/modules/proxy/_service/streaming/protocol.py +32 -0
- app/modules/proxy/_service/streaming/retry.py +3762 -0
- app/modules/proxy/_service/support.py +2122 -0
- app/modules/proxy/_service/transcribe.py +434 -0
- app/modules/proxy/_service/warmup.py +483 -0
- app/modules/proxy/_service/websocket/__init__.py +3 -0
- app/modules/proxy/_service/websocket/helpers.py +2360 -0
- app/modules/proxy/_service/websocket/mixin.py +7285 -0
- app/modules/proxy/_service/websocket/protocol.py +74 -0
- app/modules/proxy/account_cache.py +229 -0
- app/modules/proxy/account_eligibility.py +87 -0
- app/modules/proxy/additional_model_limits.py +40 -0
- app/modules/proxy/affinity.py +830 -0
- app/modules/proxy/affinity_observation.py +101 -0
- app/modules/proxy/api.py +10254 -0
- app/modules/proxy/api_key_usage.py +113 -0
- app/modules/proxy/cap_partitioning.py +280 -0
- app/modules/proxy/capability_lineage.py +65 -0
- app/modules/proxy/capability_lineage_repository.py +82 -0
- app/modules/proxy/capability_routing.py +253 -0
- app/modules/proxy/continuity.py +112 -0
- app/modules/proxy/downstream_delivery.py +277 -0
- app/modules/proxy/durable_bridge_coordinator.py +1217 -0
- app/modules/proxy/durable_bridge_repository.py +4516 -0
- app/modules/proxy/durable_bridge_runtime.py +9 -0
- app/modules/proxy/durable_bridge_transcript_codec.py +122 -0
- app/modules/proxy/fair_share.py +131 -0
- app/modules/proxy/file_pin_repository.py +210 -0
- app/modules/proxy/helpers.py +439 -0
- app/modules/proxy/http_bridge_event_batcher.py +613 -0
- app/modules/proxy/http_bridge_forwarding.py +797 -0
- app/modules/proxy/http_continuation.py +76 -0
- app/modules/proxy/images_observability.py +62 -0
- app/modules/proxy/images_service.py +1054 -0
- app/modules/proxy/load_balancer.py +3016 -0
- app/modules/proxy/rate_limit_cache.py +46 -0
- app/modules/proxy/replay_safety.py +1063 -0
- app/modules/proxy/repo_bundle.py +31 -0
- app/modules/proxy/request_policy.py +1054 -0
- app/modules/proxy/ring_membership.py +251 -0
- app/modules/proxy/schemas.py +345 -0
- app/modules/proxy/selection_errors.py +41 -0
- app/modules/proxy/service.py +2600 -0
- app/modules/proxy/source_admission.py +125 -0
- app/modules/proxy/source_dispatch.py +999 -0
- app/modules/proxy/sticky_repository.py +831 -0
- app/modules/proxy/thread_anchors.py +491 -0
- app/modules/proxy/tool_call_dedupe.py +802 -0
- app/modules/proxy/types.py +54 -0
- app/modules/proxy/work_admission.py +121 -0
- app/modules/quota_planner/__init__.py +1 -0
- app/modules/quota_planner/api.py +276 -0
- app/modules/quota_planner/logic.py +743 -0
- app/modules/quota_planner/repository.py +722 -0
- app/modules/quota_planner/scheduler.py +212 -0
- app/modules/quota_planner/schemas.py +102 -0
- app/modules/quota_planner/warmup.py +693 -0
- app/modules/rate_limit_reset_credits/__init__.py +0 -0
- app/modules/rate_limit_reset_credits/api.py +601 -0
- app/modules/rate_limit_reset_credits/redeem_coordination.py +274 -0
- app/modules/rate_limit_reset_credits/store.py +114 -0
- app/modules/reports/__init__.py +1 -0
- app/modules/reports/api.py +134 -0
- app/modules/reports/cache.py +74 -0
- app/modules/reports/filters.py +27 -0
- app/modules/reports/repository.py +525 -0
- app/modules/reports/rollup.py +150 -0
- app/modules/reports/rollup_read.py +148 -0
- app/modules/reports/schemas.py +123 -0
- app/modules/reports/service.py +287 -0
- app/modules/reports/thread_identity.py +256 -0
- app/modules/request_logs/__init__.py +0 -0
- app/modules/request_logs/api.py +224 -0
- app/modules/request_logs/cost_backfill.py +154 -0
- app/modules/request_logs/mappers.py +97 -0
- app/modules/request_logs/repository.py +1765 -0
- app/modules/request_logs/schemas.py +145 -0
- app/modules/request_logs/service.py +348 -0
- app/modules/role_mappings/__init__.py +0 -0
- app/modules/role_mappings/api.py +206 -0
- app/modules/role_mappings/matching.py +55 -0
- app/modules/role_mappings/repository.py +106 -0
- app/modules/role_mappings/schemas.py +67 -0
- app/modules/role_mappings/service.py +334 -0
- app/modules/runtime/__init__.py +1 -0
- app/modules/runtime/api.py +18 -0
- app/modules/runtime/schemas.py +14 -0
- app/modules/runtime/service.py +218 -0
- app/modules/scim/__init__.py +1 -0
- app/modules/scim/api.py +194 -0
- app/modules/scim/dependencies.py +112 -0
- app/modules/scim/errors.py +77 -0
- app/modules/scim/management_api.py +156 -0
- app/modules/scim/repository.py +212 -0
- app/modules/scim/schemas.py +145 -0
- app/modules/scim/service.py +786 -0
- app/modules/scim/tokens.py +43 -0
- app/modules/settings/__init__.py +1 -0
- app/modules/settings/api.py +1677 -0
- app/modules/settings/repository.py +606 -0
- app/modules/settings/schemas.py +496 -0
- app/modules/settings/service.py +769 -0
- app/modules/shared/__init__.py +0 -0
- app/modules/shared/schemas.py +22 -0
- app/modules/sticky_sessions/__init__.py +1 -0
- app/modules/sticky_sessions/api.py +118 -0
- app/modules/sticky_sessions/cleanup_scheduler.py +487 -0
- app/modules/sticky_sessions/schemas.py +78 -0
- app/modules/sticky_sessions/service.py +196 -0
- app/modules/telemetry/__init__.py +5 -0
- app/modules/telemetry/api.py +115 -0
- app/modules/telemetry/clients.py +62 -0
- app/modules/telemetry/consent.py +115 -0
- app/modules/telemetry/scheduler.py +85 -0
- app/modules/telemetry/schemas.py +163 -0
- app/modules/telemetry/sender.py +221 -0
- app/modules/telemetry/snapshot.py +490 -0
- app/modules/usage/__init__.py +0 -0
- app/modules/usage/additional_quota_keys.py +379 -0
- app/modules/usage/api.py +45 -0
- app/modules/usage/background_repository.py +147 -0
- app/modules/usage/builders.py +559 -0
- app/modules/usage/depletion_service.py +277 -0
- app/modules/usage/live_ingest.py +356 -0
- app/modules/usage/mappers.py +29 -0
- app/modules/usage/plan_downgrade_observations.py +488 -0
- app/modules/usage/repository.py +1890 -0
- app/modules/usage/schemas.py +68 -0
- app/modules/usage/service.py +102 -0
- app/modules/usage/updater.py +1488 -0
- app/static/assets/Trans-Cj-J9mVA.js +1 -0
- app/static/assets/access-page-DHzZiXZi.js +1 -0
- app/static/assets/account-cost-donut-DGhfA4U8.js +1 -0
- app/static/assets/account-identifiers-CxbdLshZ.js +1 -0
- app/static/assets/account-status-DIsU5sUS.js +1 -0
- app/static/assets/account-trend-chart-BptlfwwQ.js +1 -0
- app/static/assets/accounts-page-Bbai8ift.js +3 -0
- app/static/assets/api-Dwa7XxPe.js +1 -0
- app/static/assets/api-client-dugX1Pti.js +55 -0
- app/static/assets/api-key-create-dialog-DnRm0oYN.js +1 -0
- app/static/assets/api-key-created-dialog-B6jkDG9f.js +1 -0
- app/static/assets/api-key-edit-dialog-Ck3Bnc3V.js +1 -0
- app/static/assets/api-trend-chart-BchCw7Hj.js +1 -0
- app/static/assets/apis-page-BvXz9c6i.js +2 -0
- app/static/assets/arrow-up-Dqh_KzJo.js +1 -0
- app/static/assets/arrow-up-down-LBRgVDGY.js +1 -0
- app/static/assets/automations-page-DQgNAJOR.js +3 -0
- app/static/assets/badge-DqMb9es0.js +1 -0
- app/static/assets/blur-email-HEvKagG2.js +1 -0
- app/static/assets/button-BjVmmiGW.js +1 -0
- app/static/assets/checkbox-apsl9vzk.js +1 -0
- app/static/assets/chevron-left-1d_pHVa5.js +1 -0
- app/static/assets/circle-alert-BS0xd_o1.js +1 -0
- app/static/assets/clsx-DB0hHKMi.js +1 -0
- app/static/assets/colors-BBy8GEtr.js +1 -0
- app/static/assets/copy-button-D7nAvOKR.js +1 -0
- app/static/assets/cost-per-day-chart-YdqlkZVM.js +1 -0
- app/static/assets/createLucideIcon-DBLzLNh2.js +1 -0
- app/static/assets/dashboard-page-CSdhBy0f.js +2 -0
- app/static/assets/distribution-metric-format-yZTy1ZEu.js +1 -0
- app/static/assets/donut-chart-Bxc69cra.js +1 -0
- app/static/assets/download-kQteIcsB.js +1 -0
- app/static/assets/ellipsis-B_5OgIre.js +1 -0
- app/static/assets/empty-state-JcA7tc8m.js +1 -0
- app/static/assets/es2015-bMH8YKZT.js +41 -0
- app/static/assets/es6-B264ni6W.js +69 -0
- app/static/assets/external-link-UVAOgMQ0.js +1 -0
- app/static/assets/i18n-BWqZ9Ua2.js +1 -0
- app/static/assets/inbox-B_RM2s1J.js +1 -0
- app/static/assets/index-DIpd264Z.js +23 -0
- app/static/assets/index-DMeLKRJx.css +2 -0
- app/static/assets/inherit-badge-QhTYVaU6.js +1 -0
- app/static/assets/invite-dialog-0CYh0GiQ.js +1 -0
- app/static/assets/iso-Bpe5Ihbb.js +1 -0
- app/static/assets/label-CGaLmLNf.js +1 -0
- app/static/assets/lazy-recharts-Pv8p9ArM.js +2 -0
- app/static/assets/loading-overlay-CzKQfHLI.js +1 -0
- app/static/assets/mini-quota-bar-cGT_t8Ae.js +1 -0
- app/static/assets/model-distribution-donut-BKjAfT48.js +1 -0
- app/static/assets/model-source-multi-select-D2d06Vc7.js +1 -0
- app/static/assets/multi-select-filter-KIA5qU6Z.js +1 -0
- app/static/assets/oauth-dialog-XeaGGDjS.js +1 -0
- app/static/assets/pagination-controls-D1Ypd0RU.js +1 -0
- app/static/assets/payload-CIYnGZz9.js +1 -0
- app/static/assets/queue-wait-chart-VoV7Yg9L.js +1 -0
- app/static/assets/report-chart-card-BXDliwcc.js +1 -0
- app/static/assets/reports-page-CGCJeMHG.js +3 -0
- app/static/assets/reset-credit-confirm-dialog-QOifTnVB.js +1 -0
- app/static/assets/rolldown-runtime-hePW80VL.js +1 -0
- app/static/assets/search-HfhqwERt.js +1 -0
- app/static/assets/select-Cl33bz-g.js +1 -0
- app/static/assets/settings-page-mZj01HYl.js +2 -0
- app/static/assets/shim-CZwyM4Q7.js +1 -0
- app/static/assets/skeleton-C_EUc4Rp.js +1 -0
- app/static/assets/sparkline-chart-DdNNsddM.js +1 -0
- app/static/assets/status-badge-CHHA5X6c.js +1 -0
- app/static/assets/switch-CzxgokcM.js +1 -0
- app/static/assets/table-DXaNSQ0G.js +1 -0
- app/static/assets/time-to-first-token-chart--68L0u_v.js +1 -0
- app/static/assets/tokens-per-day-chart-Cs82BFuE.js +1 -0
- app/static/assets/tokens-per-second-chart-AD2dfOn6.js +1 -0
- app/static/assets/totp-settings-CRHtxQ7j.js +1 -0
- app/static/assets/trash-D3KyWr1h.js +1 -0
- app/static/assets/use-account-quota-display-BPmrTBTC.js +1 -0
- app/static/assets/use-accounts-PWlVGw3z.js +1 -0
- app/static/assets/use-auth-CuDlW3iC.js +1 -0
- app/static/assets/use-chart-colors-DIu6tClI.js +1 -0
- app/static/assets/use-model-sources-Bul24JBu.js +1 -0
- app/static/assets/use-models-DUCPUuZg.js +1 -0
- app/static/assets/use-reduced-motion-hAm5r6_d.js +1 -0
- app/static/assets/useTranslation--56nHhlH.js +1 -0
- app/static/assets/useragent-distribution-donut-Dup6sf_n.js +1 -0
- app/static/assets/users-uIC3TIlE.js +1 -0
- app/static/assets/vendor-query-_bHZuxEx.js +1 -0
- app/static/assets/vendor-react-BVL0YZPW.js +9 -0
- app/static/favicon.svg +10 -0
- app/static/fonts/GeistSans-Variable.woff2 +0 -0
- app/static/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
- app/static/fonts/jetbrains-mono-latin.woff2 +0 -0
- app/static/index.html +29 -0
- codexlb_up-1.25.0b10.dist-info/METADATA +124 -0
- codexlb_up-1.25.0b10.dist-info/RECORD +827 -0
- codexlb_up-1.25.0b10.dist-info/WHEEL +4 -0
- codexlb_up-1.25.0b10.dist-info/entry_points.txt +3 -0
- codexlb_up-1.25.0b10.dist-info/licenses/LICENSE +21 -0
- config/additional_quota_registry.json +11 -0
|
@@ -0,0 +1,606 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
|
+
|
|
5
|
+
from sqlalchemy import func, select
|
|
6
|
+
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
|
7
|
+
from sqlalchemy.dialects.sqlite import insert as sqlite_insert
|
|
8
|
+
from sqlalchemy.exc import IntegrityError
|
|
9
|
+
from sqlalchemy.ext.asyncio import AsyncSession
|
|
10
|
+
from sqlalchemy.orm.attributes import flag_modified
|
|
11
|
+
from sqlalchemy.orm.exc import StaleDataError
|
|
12
|
+
|
|
13
|
+
from app.core.auth.dashboard_session_ttl import DEFAULT_DASHBOARD_SESSION_TTL_SECONDS
|
|
14
|
+
from app.core.exceptions import DashboardSettingsConflictError
|
|
15
|
+
from app.core.upstream_proxy.cache import get_upstream_route_cache
|
|
16
|
+
from app.db.models import DashboardSettings, DashboardUser, LocalLoginPolicy, ModelContextWindowOverride
|
|
17
|
+
from app.modules.dashboard_users.repository import DashboardUsersRepository
|
|
18
|
+
|
|
19
|
+
_SETTINGS_ID = 1
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SettingsRepository:
|
|
23
|
+
def __init__(self, session: AsyncSession) -> None:
|
|
24
|
+
self._session = session
|
|
25
|
+
|
|
26
|
+
async def list_active_password_users(self) -> Sequence[DashboardUser]:
|
|
27
|
+
"""Accounts the TOTP requirements bind (roles loaded for the admin-level check)."""
|
|
28
|
+
|
|
29
|
+
return await DashboardUsersRepository(self._session).list_active_local_password_users()
|
|
30
|
+
|
|
31
|
+
async def acquire_account_write_intent(self) -> None:
|
|
32
|
+
"""Serialise this settings write against the account mutations it depends on.
|
|
33
|
+
|
|
34
|
+
The tightening gate counts qualifying emergency accounts and then
|
|
35
|
+
writes the policy; without the accounts lock a concurrent TOTP reset,
|
|
36
|
+
password removal or deactivation can take the last one away in between
|
|
37
|
+
and leave a restricted policy with no way back in.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
await DashboardUsersRepository(self._session).acquire_write_intent()
|
|
41
|
+
|
|
42
|
+
async def count_qualifying_break_glass(self) -> int:
|
|
43
|
+
"""Accounts that can still open the door once local sign-in is restricted."""
|
|
44
|
+
|
|
45
|
+
return await DashboardUsersRepository(self._session).count_qualifying_break_glass()
|
|
46
|
+
|
|
47
|
+
async def list_break_glass_designations(self) -> Sequence[DashboardUser]:
|
|
48
|
+
"""Designated accounts, so a refusal can name the one an operator should enrol."""
|
|
49
|
+
|
|
50
|
+
return await DashboardUsersRepository(self._session).list_break_glass_designations()
|
|
51
|
+
|
|
52
|
+
async def get_or_create(self) -> DashboardSettings:
|
|
53
|
+
existing = await self._session.get(DashboardSettings, _SETTINGS_ID)
|
|
54
|
+
if existing is not None:
|
|
55
|
+
return existing
|
|
56
|
+
|
|
57
|
+
row = DashboardSettings(
|
|
58
|
+
id=_SETTINGS_ID,
|
|
59
|
+
sticky_threads_enabled=True,
|
|
60
|
+
upstream_stream_transport="auto",
|
|
61
|
+
prohibit_fast_mode=False,
|
|
62
|
+
# Account-capacity overrides are tri-state: NULL inherits the
|
|
63
|
+
# process environment value at read time. The first-boot seed must
|
|
64
|
+
# stay NULL — copying the env value here would freeze it as a
|
|
65
|
+
# dashboard override while the UI keeps labelling the (possibly
|
|
66
|
+
# changed) env value as the inherited baseline.
|
|
67
|
+
proxy_account_response_create_limit=None,
|
|
68
|
+
proxy_account_stream_limit=None,
|
|
69
|
+
proxy_account_stream_recovery_reserve=None,
|
|
70
|
+
proxy_api_key_fair_share_congestion_threshold_pct=None,
|
|
71
|
+
# Thread cache identity: same tri-state rule, seeded NULL.
|
|
72
|
+
# NULL inherits the environment value and then ``shared``.
|
|
73
|
+
thread_cache_identity_mode=None,
|
|
74
|
+
# C2-2 routing/overload: same tri-state rule, seeded NULL.
|
|
75
|
+
proxy_overload_isolation_seconds=None,
|
|
76
|
+
proxy_account_error_rate_weighting_enabled=None,
|
|
77
|
+
proxy_account_inflight_penalty_pct=None,
|
|
78
|
+
proxy_account_lease_token_weight=None,
|
|
79
|
+
proxy_account_lease_ttl_seconds=None,
|
|
80
|
+
upstream_proxy_routing_enabled=False,
|
|
81
|
+
upstream_proxy_default_pool_id=None,
|
|
82
|
+
prefer_earlier_reset_accounts=True,
|
|
83
|
+
prefer_earlier_reset_window="secondary",
|
|
84
|
+
show_reset_credit_badges=True,
|
|
85
|
+
auto_redeem_reset_credits_before_expiry=False,
|
|
86
|
+
show_reset_credit_expiry_badge=True,
|
|
87
|
+
routing_strategy="capacity_weighted",
|
|
88
|
+
relative_availability_power=2.0,
|
|
89
|
+
relative_availability_top_k=5,
|
|
90
|
+
single_account_id=None,
|
|
91
|
+
dashboard_session_ttl_seconds=DEFAULT_DASHBOARD_SESSION_TTL_SECONDS,
|
|
92
|
+
import_without_overwrite=True,
|
|
93
|
+
totp_required_on_login=False,
|
|
94
|
+
totp_required_for_admin_role=False,
|
|
95
|
+
local_login_policy=LocalLoginPolicy.ENABLED.value,
|
|
96
|
+
guest_access_enabled=False,
|
|
97
|
+
guest_password_hash=None,
|
|
98
|
+
bootstrap_token_encrypted=None,
|
|
99
|
+
bootstrap_token_hash=None,
|
|
100
|
+
api_key_auth_enabled=False,
|
|
101
|
+
hide_upstream_quota_from_api_keys=False,
|
|
102
|
+
sticky_reallocation_primary_budget_threshold_pct=95.0,
|
|
103
|
+
sticky_reallocation_secondary_budget_threshold_pct=100.0,
|
|
104
|
+
additional_quota_routing_policies_json="{}",
|
|
105
|
+
limit_warmup_enabled=False,
|
|
106
|
+
limit_warmup_windows="both",
|
|
107
|
+
limit_warmup_model="auto",
|
|
108
|
+
limit_warmup_prompt="Say OK.",
|
|
109
|
+
limit_warmup_cooldown_seconds=3600,
|
|
110
|
+
limit_warmup_exhausted_threshold_percent=99.0,
|
|
111
|
+
limit_warmup_idle_threshold_percent=1.0,
|
|
112
|
+
limit_warmup_min_available_percent=100.0,
|
|
113
|
+
weekly_pace_working_days="0,1,2,3,4,5,6",
|
|
114
|
+
weekly_pace_smoothing_minutes=30,
|
|
115
|
+
limit_warmup_staggered_idle_enabled=False,
|
|
116
|
+
request_log_retention_days=None,
|
|
117
|
+
usage_history_retention_days=None,
|
|
118
|
+
# C2-3 resilience toggles: NULL = inherit the env alias / default.
|
|
119
|
+
soft_drain_enabled=None,
|
|
120
|
+
deterministic_failover_enabled=None,
|
|
121
|
+
circuit_breaker_enabled=None,
|
|
122
|
+
# M3 codex prewarm: NULL = inherit the env alias / default (off).
|
|
123
|
+
http_responses_session_bridge_codex_prewarm_enabled=None,
|
|
124
|
+
# M2 background jobs: NULL = inherit the env alias / default.
|
|
125
|
+
auth_guardian_enabled=None,
|
|
126
|
+
automations_scheduler_enabled=None,
|
|
127
|
+
rate_limit_reset_credits_refresh_enabled=None,
|
|
128
|
+
# M5 conversation archive: NULL = inherit the env alias / default.
|
|
129
|
+
conversation_archive_enabled=None,
|
|
130
|
+
# R2 spool retention: NULL = inherit the env alias / default (7d).
|
|
131
|
+
http_responses_session_bridge_operation_spool_retention_seconds=None,
|
|
132
|
+
)
|
|
133
|
+
self._session.add(row)
|
|
134
|
+
try:
|
|
135
|
+
await self._session.commit()
|
|
136
|
+
except IntegrityError:
|
|
137
|
+
await self._session.rollback()
|
|
138
|
+
existing = await self._session.get(DashboardSettings, _SETTINGS_ID)
|
|
139
|
+
if existing is None:
|
|
140
|
+
raise
|
|
141
|
+
return existing
|
|
142
|
+
await self._session.refresh(row)
|
|
143
|
+
return row
|
|
144
|
+
|
|
145
|
+
async def update(
|
|
146
|
+
self,
|
|
147
|
+
*,
|
|
148
|
+
sticky_threads_enabled: bool | None = None,
|
|
149
|
+
upstream_stream_transport: str | None = None,
|
|
150
|
+
prohibit_fast_mode: bool | None = None,
|
|
151
|
+
http_downstream_transport_policy: str | None = None,
|
|
152
|
+
thread_cache_identity_mode: str | None = None,
|
|
153
|
+
clear_thread_cache_identity_mode: bool = False,
|
|
154
|
+
proxy_account_response_create_limit: int | None = None,
|
|
155
|
+
clear_proxy_account_response_create_limit: bool = False,
|
|
156
|
+
proxy_account_stream_limit: int | None = None,
|
|
157
|
+
clear_proxy_account_stream_limit: bool = False,
|
|
158
|
+
proxy_account_stream_recovery_reserve: int | None = None,
|
|
159
|
+
clear_proxy_account_stream_recovery_reserve: bool = False,
|
|
160
|
+
proxy_api_key_fair_share_congestion_threshold_pct: int | None = None,
|
|
161
|
+
clear_proxy_api_key_fair_share_congestion_threshold_pct: bool = False,
|
|
162
|
+
# C2-2 routing/overload
|
|
163
|
+
proxy_overload_isolation_seconds: int | None = None,
|
|
164
|
+
clear_proxy_overload_isolation_seconds: bool = False,
|
|
165
|
+
proxy_account_error_rate_weighting_enabled: bool | None = None,
|
|
166
|
+
clear_proxy_account_error_rate_weighting_enabled: bool = False,
|
|
167
|
+
proxy_account_inflight_penalty_pct: float | None = None,
|
|
168
|
+
clear_proxy_account_inflight_penalty_pct: bool = False,
|
|
169
|
+
proxy_account_lease_token_weight: float | None = None,
|
|
170
|
+
clear_proxy_account_lease_token_weight: bool = False,
|
|
171
|
+
proxy_account_lease_ttl_seconds: float | None = None,
|
|
172
|
+
clear_proxy_account_lease_ttl_seconds: bool = False,
|
|
173
|
+
# end C2-2 routing/overload
|
|
174
|
+
upstream_proxy_routing_enabled: bool | None = None,
|
|
175
|
+
upstream_proxy_default_pool_id: str | None = None,
|
|
176
|
+
prefer_earlier_reset_accounts: bool | None = None,
|
|
177
|
+
prefer_earlier_reset_window: str | None = None,
|
|
178
|
+
show_reset_credit_badges: bool | None = None,
|
|
179
|
+
auto_redeem_reset_credits_before_expiry: bool | None = None,
|
|
180
|
+
show_reset_credit_expiry_badge: bool | None = None,
|
|
181
|
+
routing_strategy: str | None = None,
|
|
182
|
+
relative_availability_power: float | None = None,
|
|
183
|
+
relative_availability_top_k: int | None = None,
|
|
184
|
+
single_account_id: str | None = None,
|
|
185
|
+
openai_cache_affinity_max_age_seconds: int | None = None,
|
|
186
|
+
dashboard_session_ttl_seconds: int | None = None,
|
|
187
|
+
http_responses_session_bridge_prompt_cache_idle_ttl_seconds: int | None = None,
|
|
188
|
+
http_responses_session_bridge_gateway_safe_mode: bool | None = None,
|
|
189
|
+
sticky_reallocation_budget_threshold_pct: float | None = None,
|
|
190
|
+
sticky_reallocation_primary_budget_threshold_pct: float | None = None,
|
|
191
|
+
sticky_reallocation_secondary_budget_threshold_pct: float | None = None,
|
|
192
|
+
additional_quota_routing_policies_json: str | None = None,
|
|
193
|
+
warmup_model: str | None = None,
|
|
194
|
+
import_without_overwrite: bool | None = None,
|
|
195
|
+
totp_required_on_login: bool | None = None,
|
|
196
|
+
totp_required_for_admin_role: bool | None = None,
|
|
197
|
+
local_login_policy: str | None = None,
|
|
198
|
+
api_key_auth_enabled: bool | None = None,
|
|
199
|
+
hide_upstream_quota_from_api_keys: bool | None = None,
|
|
200
|
+
limit_warmup_enabled: bool | None = None,
|
|
201
|
+
limit_warmup_windows: str | None = None,
|
|
202
|
+
limit_warmup_model: str | None = None,
|
|
203
|
+
limit_warmup_prompt: str | None = None,
|
|
204
|
+
limit_warmup_cooldown_seconds: int | None = None,
|
|
205
|
+
limit_warmup_exhausted_threshold_percent: float | None = None,
|
|
206
|
+
limit_warmup_idle_threshold_percent: float | None = None,
|
|
207
|
+
limit_warmup_min_available_percent: float | None = None,
|
|
208
|
+
weekly_pace_working_days: str | None = None,
|
|
209
|
+
weekly_pace_smoothing_minutes: int | None = None,
|
|
210
|
+
guest_access_enabled: bool | None = None,
|
|
211
|
+
limit_warmup_staggered_idle_enabled: bool | None = None,
|
|
212
|
+
request_log_retention_days: int | None = None,
|
|
213
|
+
usage_history_retention_days: int | None = None,
|
|
214
|
+
clear_request_log_retention: bool = False,
|
|
215
|
+
clear_usage_history_retention: bool = False,
|
|
216
|
+
# C2-3 resilience toggles (tri-state like the retention overrides)
|
|
217
|
+
soft_drain_enabled: bool | None = None,
|
|
218
|
+
clear_soft_drain_enabled: bool = False,
|
|
219
|
+
deterministic_failover_enabled: bool | None = None,
|
|
220
|
+
clear_deterministic_failover_enabled: bool = False,
|
|
221
|
+
circuit_breaker_enabled: bool | None = None,
|
|
222
|
+
clear_circuit_breaker_enabled: bool = False,
|
|
223
|
+
# M2 background jobs (tri-state like the resilience toggles)
|
|
224
|
+
auth_guardian_enabled: bool | None = None,
|
|
225
|
+
clear_auth_guardian_enabled: bool = False,
|
|
226
|
+
automations_scheduler_enabled: bool | None = None,
|
|
227
|
+
clear_automations_scheduler_enabled: bool = False,
|
|
228
|
+
rate_limit_reset_credits_refresh_enabled: bool | None = None,
|
|
229
|
+
clear_rate_limit_reset_credits_refresh_enabled: bool = False,
|
|
230
|
+
# M5 conversation archive (tri-state like the resilience toggles)
|
|
231
|
+
conversation_archive_enabled: bool | None = None,
|
|
232
|
+
clear_conversation_archive_enabled: bool = False,
|
|
233
|
+
# end M5 conversation archive
|
|
234
|
+
# R2 spool retention (tri-state like the C2-1 timeouts)
|
|
235
|
+
http_responses_session_bridge_operation_spool_retention_seconds: float | None = None,
|
|
236
|
+
clear_http_responses_session_bridge_operation_spool_retention_seconds: bool = False,
|
|
237
|
+
# end R2 spool retention
|
|
238
|
+
# C2-1 timeouts (tri-state: value = store, clear flag = back to NULL /
|
|
239
|
+
# inherit, neither = untouched).
|
|
240
|
+
upstream_connect_timeout_seconds: float | None = None,
|
|
241
|
+
clear_upstream_connect_timeout_seconds: bool = False,
|
|
242
|
+
proxy_request_budget_seconds: float | None = None,
|
|
243
|
+
clear_proxy_request_budget_seconds: bool = False,
|
|
244
|
+
compact_request_budget_seconds: float | None = None,
|
|
245
|
+
clear_compact_request_budget_seconds: bool = False,
|
|
246
|
+
transcription_request_budget_seconds: float | None = None,
|
|
247
|
+
clear_transcription_request_budget_seconds: bool = False,
|
|
248
|
+
stream_idle_timeout_seconds: float | None = None,
|
|
249
|
+
clear_stream_idle_timeout_seconds: bool = False,
|
|
250
|
+
proxy_downstream_websocket_idle_timeout_seconds: float | None = None,
|
|
251
|
+
clear_proxy_downstream_websocket_idle_timeout_seconds: bool = False,
|
|
252
|
+
sse_keepalive_interval_seconds: float | None = None,
|
|
253
|
+
clear_sse_keepalive_interval_seconds: bool = False,
|
|
254
|
+
# end C2-1 timeouts
|
|
255
|
+
# M3 codex prewarm (tri-state like the resilience toggles)
|
|
256
|
+
http_responses_session_bridge_codex_prewarm_enabled: bool | None = None,
|
|
257
|
+
clear_http_responses_session_bridge_codex_prewarm_enabled: bool = False,
|
|
258
|
+
# end M3 codex prewarm
|
|
259
|
+
# M1 stream/bridge budgets (same tri-state contract).
|
|
260
|
+
http_responses_stream_request_budget_seconds: float | None = None,
|
|
261
|
+
clear_http_responses_stream_request_budget_seconds: bool = False,
|
|
262
|
+
http_responses_session_bridge_request_budget_seconds: float | None = None,
|
|
263
|
+
clear_http_responses_session_bridge_request_budget_seconds: bool = False,
|
|
264
|
+
# end M1 stream/bridge budgets
|
|
265
|
+
expected_version: int | None = None,
|
|
266
|
+
) -> DashboardSettings:
|
|
267
|
+
settings = await self.get_or_create()
|
|
268
|
+
if expected_version is not None and settings.version != expected_version:
|
|
269
|
+
# Bind the CAS to the row this UPDATE targets: with
|
|
270
|
+
# DashboardSettings.version as version_id_col, commit_refresh emits
|
|
271
|
+
# `UPDATE ... WHERE version = :expected`, so a writer committing in
|
|
272
|
+
# between still surfaces as StaleDataError -> 409.
|
|
273
|
+
raise DashboardSettingsConflictError(
|
|
274
|
+
"Settings were modified since this form was loaded; reload and retry",
|
|
275
|
+
)
|
|
276
|
+
upstream_route_inputs_changed = (
|
|
277
|
+
upstream_proxy_routing_enabled is not None
|
|
278
|
+
and upstream_proxy_routing_enabled != settings.upstream_proxy_routing_enabled
|
|
279
|
+
) or (upstream_proxy_default_pool_id or None) != settings.upstream_proxy_default_pool_id
|
|
280
|
+
if sticky_threads_enabled is not None:
|
|
281
|
+
settings.sticky_threads_enabled = sticky_threads_enabled
|
|
282
|
+
if upstream_stream_transport is not None:
|
|
283
|
+
settings.upstream_stream_transport = upstream_stream_transport
|
|
284
|
+
if prohibit_fast_mode is not None:
|
|
285
|
+
settings.prohibit_fast_mode = prohibit_fast_mode
|
|
286
|
+
if http_downstream_transport_policy is not None:
|
|
287
|
+
settings.http_downstream_transport_policy = http_downstream_transport_policy
|
|
288
|
+
if clear_proxy_account_response_create_limit:
|
|
289
|
+
settings.proxy_account_response_create_limit = None
|
|
290
|
+
elif proxy_account_response_create_limit is not None:
|
|
291
|
+
settings.proxy_account_response_create_limit = proxy_account_response_create_limit
|
|
292
|
+
if clear_proxy_account_stream_limit:
|
|
293
|
+
settings.proxy_account_stream_limit = None
|
|
294
|
+
elif proxy_account_stream_limit is not None:
|
|
295
|
+
settings.proxy_account_stream_limit = proxy_account_stream_limit
|
|
296
|
+
if clear_proxy_account_stream_recovery_reserve:
|
|
297
|
+
settings.proxy_account_stream_recovery_reserve = None
|
|
298
|
+
elif proxy_account_stream_recovery_reserve is not None:
|
|
299
|
+
settings.proxy_account_stream_recovery_reserve = proxy_account_stream_recovery_reserve
|
|
300
|
+
if clear_proxy_api_key_fair_share_congestion_threshold_pct:
|
|
301
|
+
settings.proxy_api_key_fair_share_congestion_threshold_pct = None
|
|
302
|
+
elif proxy_api_key_fair_share_congestion_threshold_pct is not None:
|
|
303
|
+
settings.proxy_api_key_fair_share_congestion_threshold_pct = (
|
|
304
|
+
proxy_api_key_fair_share_congestion_threshold_pct
|
|
305
|
+
)
|
|
306
|
+
if clear_thread_cache_identity_mode:
|
|
307
|
+
settings.thread_cache_identity_mode = None
|
|
308
|
+
elif thread_cache_identity_mode is not None:
|
|
309
|
+
settings.thread_cache_identity_mode = thread_cache_identity_mode
|
|
310
|
+
# C2-2 routing/overload
|
|
311
|
+
if clear_proxy_overload_isolation_seconds:
|
|
312
|
+
settings.proxy_overload_isolation_seconds = None
|
|
313
|
+
elif proxy_overload_isolation_seconds is not None:
|
|
314
|
+
settings.proxy_overload_isolation_seconds = proxy_overload_isolation_seconds
|
|
315
|
+
if clear_proxy_account_error_rate_weighting_enabled:
|
|
316
|
+
settings.proxy_account_error_rate_weighting_enabled = None
|
|
317
|
+
elif proxy_account_error_rate_weighting_enabled is not None:
|
|
318
|
+
settings.proxy_account_error_rate_weighting_enabled = proxy_account_error_rate_weighting_enabled
|
|
319
|
+
if clear_proxy_account_inflight_penalty_pct:
|
|
320
|
+
settings.proxy_account_inflight_penalty_pct = None
|
|
321
|
+
elif proxy_account_inflight_penalty_pct is not None:
|
|
322
|
+
settings.proxy_account_inflight_penalty_pct = proxy_account_inflight_penalty_pct
|
|
323
|
+
if clear_proxy_account_lease_token_weight:
|
|
324
|
+
settings.proxy_account_lease_token_weight = None
|
|
325
|
+
elif proxy_account_lease_token_weight is not None:
|
|
326
|
+
settings.proxy_account_lease_token_weight = proxy_account_lease_token_weight
|
|
327
|
+
if clear_proxy_account_lease_ttl_seconds:
|
|
328
|
+
settings.proxy_account_lease_ttl_seconds = None
|
|
329
|
+
elif proxy_account_lease_ttl_seconds is not None:
|
|
330
|
+
settings.proxy_account_lease_ttl_seconds = proxy_account_lease_ttl_seconds
|
|
331
|
+
# end C2-2 routing/overload
|
|
332
|
+
if upstream_proxy_routing_enabled is not None:
|
|
333
|
+
settings.upstream_proxy_routing_enabled = upstream_proxy_routing_enabled
|
|
334
|
+
settings.upstream_proxy_default_pool_id = upstream_proxy_default_pool_id or None
|
|
335
|
+
if prefer_earlier_reset_accounts is not None:
|
|
336
|
+
settings.prefer_earlier_reset_accounts = prefer_earlier_reset_accounts
|
|
337
|
+
if prefer_earlier_reset_window is not None:
|
|
338
|
+
settings.prefer_earlier_reset_window = prefer_earlier_reset_window
|
|
339
|
+
if show_reset_credit_badges is not None:
|
|
340
|
+
settings.show_reset_credit_badges = show_reset_credit_badges
|
|
341
|
+
if auto_redeem_reset_credits_before_expiry is not None:
|
|
342
|
+
settings.auto_redeem_reset_credits_before_expiry = auto_redeem_reset_credits_before_expiry
|
|
343
|
+
if show_reset_credit_expiry_badge is not None:
|
|
344
|
+
settings.show_reset_credit_expiry_badge = show_reset_credit_expiry_badge
|
|
345
|
+
if routing_strategy is not None:
|
|
346
|
+
settings.routing_strategy = routing_strategy
|
|
347
|
+
if relative_availability_power is not None:
|
|
348
|
+
settings.relative_availability_power = relative_availability_power
|
|
349
|
+
if relative_availability_top_k is not None:
|
|
350
|
+
settings.relative_availability_top_k = relative_availability_top_k
|
|
351
|
+
if single_account_id is not None or routing_strategy == "single_account":
|
|
352
|
+
settings.single_account_id = single_account_id
|
|
353
|
+
if openai_cache_affinity_max_age_seconds is not None:
|
|
354
|
+
settings.openai_cache_affinity_max_age_seconds = openai_cache_affinity_max_age_seconds
|
|
355
|
+
if dashboard_session_ttl_seconds is not None:
|
|
356
|
+
settings.dashboard_session_ttl_seconds = dashboard_session_ttl_seconds
|
|
357
|
+
if http_responses_session_bridge_prompt_cache_idle_ttl_seconds is not None:
|
|
358
|
+
settings.http_responses_session_bridge_prompt_cache_idle_ttl_seconds = (
|
|
359
|
+
http_responses_session_bridge_prompt_cache_idle_ttl_seconds
|
|
360
|
+
)
|
|
361
|
+
if http_responses_session_bridge_gateway_safe_mode is not None:
|
|
362
|
+
settings.http_responses_session_bridge_gateway_safe_mode = http_responses_session_bridge_gateway_safe_mode
|
|
363
|
+
# M3 codex prewarm: clear flag resets to NULL (inherit the env alias /
|
|
364
|
+
# code default); a non-None value is dashboard-owned.
|
|
365
|
+
if clear_http_responses_session_bridge_codex_prewarm_enabled:
|
|
366
|
+
settings.http_responses_session_bridge_codex_prewarm_enabled = None
|
|
367
|
+
elif http_responses_session_bridge_codex_prewarm_enabled is not None:
|
|
368
|
+
settings.http_responses_session_bridge_codex_prewarm_enabled = (
|
|
369
|
+
http_responses_session_bridge_codex_prewarm_enabled
|
|
370
|
+
)
|
|
371
|
+
# end M3 codex prewarm
|
|
372
|
+
if sticky_reallocation_budget_threshold_pct is not None:
|
|
373
|
+
settings.sticky_reallocation_budget_threshold_pct = sticky_reallocation_budget_threshold_pct
|
|
374
|
+
if sticky_reallocation_primary_budget_threshold_pct is not None:
|
|
375
|
+
settings.sticky_reallocation_primary_budget_threshold_pct = sticky_reallocation_primary_budget_threshold_pct
|
|
376
|
+
if sticky_reallocation_secondary_budget_threshold_pct is not None:
|
|
377
|
+
settings.sticky_reallocation_secondary_budget_threshold_pct = (
|
|
378
|
+
sticky_reallocation_secondary_budget_threshold_pct
|
|
379
|
+
)
|
|
380
|
+
if additional_quota_routing_policies_json is not None:
|
|
381
|
+
settings.additional_quota_routing_policies_json = additional_quota_routing_policies_json
|
|
382
|
+
if warmup_model is not None:
|
|
383
|
+
settings.warmup_model = warmup_model
|
|
384
|
+
if import_without_overwrite is not None:
|
|
385
|
+
settings.import_without_overwrite = import_without_overwrite
|
|
386
|
+
if totp_required_on_login is not None:
|
|
387
|
+
settings.totp_required_on_login = totp_required_on_login
|
|
388
|
+
if totp_required_for_admin_role is not None:
|
|
389
|
+
settings.totp_required_for_admin_role = totp_required_for_admin_role
|
|
390
|
+
if local_login_policy is not None:
|
|
391
|
+
settings.local_login_policy = local_login_policy
|
|
392
|
+
if api_key_auth_enabled is not None:
|
|
393
|
+
settings.api_key_auth_enabled = api_key_auth_enabled
|
|
394
|
+
if hide_upstream_quota_from_api_keys is not None:
|
|
395
|
+
settings.hide_upstream_quota_from_api_keys = hide_upstream_quota_from_api_keys
|
|
396
|
+
if limit_warmup_enabled is not None:
|
|
397
|
+
settings.limit_warmup_enabled = limit_warmup_enabled
|
|
398
|
+
if limit_warmup_windows is not None:
|
|
399
|
+
settings.limit_warmup_windows = limit_warmup_windows
|
|
400
|
+
if limit_warmup_model is not None:
|
|
401
|
+
settings.limit_warmup_model = limit_warmup_model
|
|
402
|
+
if limit_warmup_prompt is not None:
|
|
403
|
+
settings.limit_warmup_prompt = limit_warmup_prompt
|
|
404
|
+
if limit_warmup_cooldown_seconds is not None:
|
|
405
|
+
settings.limit_warmup_cooldown_seconds = limit_warmup_cooldown_seconds
|
|
406
|
+
if limit_warmup_exhausted_threshold_percent is not None:
|
|
407
|
+
settings.limit_warmup_exhausted_threshold_percent = limit_warmup_exhausted_threshold_percent
|
|
408
|
+
if limit_warmup_idle_threshold_percent is not None:
|
|
409
|
+
settings.limit_warmup_idle_threshold_percent = limit_warmup_idle_threshold_percent
|
|
410
|
+
if limit_warmup_min_available_percent is not None:
|
|
411
|
+
settings.limit_warmup_min_available_percent = limit_warmup_min_available_percent
|
|
412
|
+
if weekly_pace_working_days is not None:
|
|
413
|
+
settings.weekly_pace_working_days = weekly_pace_working_days
|
|
414
|
+
if weekly_pace_smoothing_minutes is not None:
|
|
415
|
+
settings.weekly_pace_smoothing_minutes = weekly_pace_smoothing_minutes
|
|
416
|
+
if guest_access_enabled is not None:
|
|
417
|
+
if settings.guest_access_enabled and not guest_access_enabled:
|
|
418
|
+
# Disabling guest access must not leave already-issued guest
|
|
419
|
+
# cookies valid for when it is re-enabled later.
|
|
420
|
+
settings.guest_session_generation += 1
|
|
421
|
+
settings.guest_access_enabled = guest_access_enabled
|
|
422
|
+
if limit_warmup_staggered_idle_enabled is not None:
|
|
423
|
+
settings.limit_warmup_staggered_idle_enabled = limit_warmup_staggered_idle_enabled
|
|
424
|
+
# Retention overrides are tri-state: a clear flag resets the column to
|
|
425
|
+
# NULL (not configured = retention disabled); a non-None value stores an
|
|
426
|
+
# override; neither leaves the stored value untouched.
|
|
427
|
+
if clear_request_log_retention:
|
|
428
|
+
settings.request_log_retention_days = None
|
|
429
|
+
elif request_log_retention_days is not None:
|
|
430
|
+
settings.request_log_retention_days = request_log_retention_days
|
|
431
|
+
if clear_usage_history_retention:
|
|
432
|
+
settings.usage_history_retention_days = None
|
|
433
|
+
elif usage_history_retention_days is not None:
|
|
434
|
+
settings.usage_history_retention_days = usage_history_retention_days
|
|
435
|
+
# C2-3 resilience toggles: clear flag resets to NULL (inherit the env
|
|
436
|
+
# alias / code default); a non-None value is dashboard-owned.
|
|
437
|
+
if clear_soft_drain_enabled:
|
|
438
|
+
settings.soft_drain_enabled = None
|
|
439
|
+
elif soft_drain_enabled is not None:
|
|
440
|
+
settings.soft_drain_enabled = soft_drain_enabled
|
|
441
|
+
if clear_deterministic_failover_enabled:
|
|
442
|
+
settings.deterministic_failover_enabled = None
|
|
443
|
+
elif deterministic_failover_enabled is not None:
|
|
444
|
+
settings.deterministic_failover_enabled = deterministic_failover_enabled
|
|
445
|
+
if clear_circuit_breaker_enabled:
|
|
446
|
+
settings.circuit_breaker_enabled = None
|
|
447
|
+
elif circuit_breaker_enabled is not None:
|
|
448
|
+
settings.circuit_breaker_enabled = circuit_breaker_enabled
|
|
449
|
+
# M2 background jobs: clear flag resets to NULL (inherit the env alias
|
|
450
|
+
# / code default); a non-None value is dashboard-owned.
|
|
451
|
+
for column_name, value, clear in (
|
|
452
|
+
("auth_guardian_enabled", auth_guardian_enabled, clear_auth_guardian_enabled),
|
|
453
|
+
("automations_scheduler_enabled", automations_scheduler_enabled, clear_automations_scheduler_enabled),
|
|
454
|
+
(
|
|
455
|
+
"rate_limit_reset_credits_refresh_enabled",
|
|
456
|
+
rate_limit_reset_credits_refresh_enabled,
|
|
457
|
+
clear_rate_limit_reset_credits_refresh_enabled,
|
|
458
|
+
),
|
|
459
|
+
):
|
|
460
|
+
if clear:
|
|
461
|
+
setattr(settings, column_name, None)
|
|
462
|
+
elif value is not None:
|
|
463
|
+
setattr(settings, column_name, value)
|
|
464
|
+
# end M2 background jobs
|
|
465
|
+
# M5 conversation archive: clear flag resets to NULL (inherit the env
|
|
466
|
+
# alias / code default); a non-None value is dashboard-owned.
|
|
467
|
+
if clear_conversation_archive_enabled:
|
|
468
|
+
settings.conversation_archive_enabled = None
|
|
469
|
+
elif conversation_archive_enabled is not None:
|
|
470
|
+
settings.conversation_archive_enabled = conversation_archive_enabled
|
|
471
|
+
# end M5 conversation archive
|
|
472
|
+
# R2 spool retention: clear flag resets to NULL (inherit the env alias
|
|
473
|
+
# / code default); a non-None value is dashboard-owned.
|
|
474
|
+
if clear_http_responses_session_bridge_operation_spool_retention_seconds:
|
|
475
|
+
settings.http_responses_session_bridge_operation_spool_retention_seconds = None
|
|
476
|
+
elif http_responses_session_bridge_operation_spool_retention_seconds is not None:
|
|
477
|
+
settings.http_responses_session_bridge_operation_spool_retention_seconds = (
|
|
478
|
+
http_responses_session_bridge_operation_spool_retention_seconds
|
|
479
|
+
)
|
|
480
|
+
# end R2 spool retention
|
|
481
|
+
# C2-1 timeouts
|
|
482
|
+
for column_name, value, clear in (
|
|
483
|
+
(
|
|
484
|
+
"upstream_connect_timeout_seconds",
|
|
485
|
+
upstream_connect_timeout_seconds,
|
|
486
|
+
clear_upstream_connect_timeout_seconds,
|
|
487
|
+
),
|
|
488
|
+
("proxy_request_budget_seconds", proxy_request_budget_seconds, clear_proxy_request_budget_seconds),
|
|
489
|
+
("compact_request_budget_seconds", compact_request_budget_seconds, clear_compact_request_budget_seconds),
|
|
490
|
+
(
|
|
491
|
+
"transcription_request_budget_seconds",
|
|
492
|
+
transcription_request_budget_seconds,
|
|
493
|
+
clear_transcription_request_budget_seconds,
|
|
494
|
+
),
|
|
495
|
+
("stream_idle_timeout_seconds", stream_idle_timeout_seconds, clear_stream_idle_timeout_seconds),
|
|
496
|
+
(
|
|
497
|
+
"proxy_downstream_websocket_idle_timeout_seconds",
|
|
498
|
+
proxy_downstream_websocket_idle_timeout_seconds,
|
|
499
|
+
clear_proxy_downstream_websocket_idle_timeout_seconds,
|
|
500
|
+
),
|
|
501
|
+
("sse_keepalive_interval_seconds", sse_keepalive_interval_seconds, clear_sse_keepalive_interval_seconds),
|
|
502
|
+
# M1 stream/bridge budgets
|
|
503
|
+
(
|
|
504
|
+
"http_responses_stream_request_budget_seconds",
|
|
505
|
+
http_responses_stream_request_budget_seconds,
|
|
506
|
+
clear_http_responses_stream_request_budget_seconds,
|
|
507
|
+
),
|
|
508
|
+
(
|
|
509
|
+
"http_responses_session_bridge_request_budget_seconds",
|
|
510
|
+
http_responses_session_bridge_request_budget_seconds,
|
|
511
|
+
clear_http_responses_session_bridge_request_budget_seconds,
|
|
512
|
+
),
|
|
513
|
+
# end M1 stream/bridge budgets
|
|
514
|
+
):
|
|
515
|
+
if clear:
|
|
516
|
+
setattr(settings, column_name, None)
|
|
517
|
+
elif value is not None:
|
|
518
|
+
setattr(settings, column_name, value)
|
|
519
|
+
# end C2-1 timeouts
|
|
520
|
+
# Force the optimistic-version CAS to run even when the payload makes no
|
|
521
|
+
# net change. `version_id_col` only raises `StaleDataError` when the
|
|
522
|
+
# flush emits an ORM UPDATE; a full-row save that assigns values all
|
|
523
|
+
# equal to this (possibly stale) session's row would otherwise flush
|
|
524
|
+
# nothing, commit silently, and refresh over a concurrent writer's
|
|
525
|
+
# values without the required 409. Flagging a column dirty guarantees an
|
|
526
|
+
# `UPDATE ... SET version = version + 1 WHERE version = :expected`, so a
|
|
527
|
+
# stale no-op save still surfaces the conflict.
|
|
528
|
+
flag_modified(settings, "sticky_threads_enabled")
|
|
529
|
+
# The route cache must be cleared synchronously between the commit and
|
|
530
|
+
# the refresh await: the committed row is visible to concurrent
|
|
531
|
+
# requests as soon as the commit returns, and any await before the
|
|
532
|
+
# clear would let them resolve from the stale per-account route cache
|
|
533
|
+
# (e.g. cached direct egress immediately after routing was enabled).
|
|
534
|
+
await self.commit_refresh(
|
|
535
|
+
settings,
|
|
536
|
+
on_committed=get_upstream_route_cache().clear if upstream_route_inputs_changed else None,
|
|
537
|
+
)
|
|
538
|
+
return settings
|
|
539
|
+
|
|
540
|
+
async def commit_refresh(
|
|
541
|
+
self, settings: DashboardSettings, *, on_committed: Callable[[], None] | None = None
|
|
542
|
+
) -> None:
|
|
543
|
+
try:
|
|
544
|
+
await self._session.commit()
|
|
545
|
+
except StaleDataError as exc:
|
|
546
|
+
# The optimistic version check (DashboardSettings.version) matched
|
|
547
|
+
# zero rows: another writer (replica or request) committed first.
|
|
548
|
+
await self._session.rollback()
|
|
549
|
+
raise DashboardSettingsConflictError() from exc
|
|
550
|
+
if on_committed is not None:
|
|
551
|
+
# Runs synchronously between the commit and the refresh await so
|
|
552
|
+
# concurrent requests cannot observe the committed row alongside
|
|
553
|
+
# stale state the hook is meant to reset.
|
|
554
|
+
on_committed()
|
|
555
|
+
await self._session.refresh(settings)
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
# M4 model catalogue: dashboard rows of the per-model context window overrides.
|
|
559
|
+
_UPSERT_INSERT_FNS = {"postgresql": pg_insert, "sqlite": sqlite_insert}
|
|
560
|
+
|
|
561
|
+
|
|
562
|
+
class ModelContextWindowOverridesRepository:
|
|
563
|
+
def __init__(self, session: AsyncSession) -> None:
|
|
564
|
+
self._session = session
|
|
565
|
+
|
|
566
|
+
async def list_all(self) -> list[ModelContextWindowOverride]:
|
|
567
|
+
result = await self._session.execute(
|
|
568
|
+
select(ModelContextWindowOverride).order_by(ModelContextWindowOverride.slug.asc())
|
|
569
|
+
)
|
|
570
|
+
return list(result.scalars().all())
|
|
571
|
+
|
|
572
|
+
async def by_slug(self) -> dict[str, int]:
|
|
573
|
+
"""``slug -> context_window`` for every dashboard row."""
|
|
574
|
+
return {row.slug: row.context_window for row in await self.list_all()}
|
|
575
|
+
|
|
576
|
+
async def upsert(self, slug: str, context_window: int) -> None:
|
|
577
|
+
"""Create or replace the row for ``slug`` in one statement.
|
|
578
|
+
|
|
579
|
+
A read-then-insert would let two concurrent creates of the same new slug
|
|
580
|
+
both miss and one fail the primary key, turning a documented
|
|
581
|
+
create-or-replace into a 500. ``updated_at`` is set explicitly because
|
|
582
|
+
the ORM ``onupdate`` does not fire for a Core insert.
|
|
583
|
+
"""
|
|
584
|
+
dialect = self._session.get_bind().dialect.name
|
|
585
|
+
insert_fn = _UPSERT_INSERT_FNS.get(dialect)
|
|
586
|
+
if insert_fn is None:
|
|
587
|
+
raise RuntimeError(f"model_context_window_overrides upsert unsupported for dialect={dialect!r}")
|
|
588
|
+
statement = insert_fn(ModelContextWindowOverride).values(slug=slug, context_window=context_window)
|
|
589
|
+
await self._session.execute(
|
|
590
|
+
statement.on_conflict_do_update(
|
|
591
|
+
index_elements=[ModelContextWindowOverride.slug],
|
|
592
|
+
set_={"context_window": context_window, "updated_at": func.now()},
|
|
593
|
+
)
|
|
594
|
+
)
|
|
595
|
+
await self._session.commit()
|
|
596
|
+
|
|
597
|
+
async def delete(self, slug: str) -> bool:
|
|
598
|
+
row = await self._session.get(ModelContextWindowOverride, slug)
|
|
599
|
+
if row is None:
|
|
600
|
+
return False
|
|
601
|
+
await self._session.delete(row)
|
|
602
|
+
await self._session.commit()
|
|
603
|
+
return True
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
# end M4 model catalogue
|