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.
Files changed (827) hide show
  1. app/__init__.py +10 -0
  2. app/admin_cli.py +494 -0
  3. app/cli.py +339 -0
  4. app/codex_sessions_retag.py +487 -0
  5. app/core/__init__.py +0 -0
  6. app/core/audit/__init__.py +0 -0
  7. app/core/audit/service.py +216 -0
  8. app/core/audit/types.py +94 -0
  9. app/core/auth/__init__.py +236 -0
  10. app/core/auth/api_key_cache.py +65 -0
  11. app/core/auth/dashboard_access.py +429 -0
  12. app/core/auth/dashboard_mode.py +171 -0
  13. app/core/auth/dashboard_session_ttl.py +74 -0
  14. app/core/auth/dashboard_users_cache.py +120 -0
  15. app/core/auth/dependencies.py +710 -0
  16. app/core/auth/external_identity.py +78 -0
  17. app/core/auth/guardian.py +374 -0
  18. app/core/auth/models.py +49 -0
  19. app/core/auth/providers/__init__.py +129 -0
  20. app/core/auth/providers/oidc.py +838 -0
  21. app/core/auth/providers/registry.py +118 -0
  22. app/core/auth/refresh.py +394 -0
  23. app/core/auth/step_up.py +117 -0
  24. app/core/auth/totp.py +81 -0
  25. app/core/balancer/__init__.py +71 -0
  26. app/core/balancer/logic.py +1612 -0
  27. app/core/balancer/rendezvous_hash.py +21 -0
  28. app/core/balancer/types.py +21 -0
  29. app/core/bootstrap.py +172 -0
  30. app/core/cache/invalidation.py +426 -0
  31. app/core/clients/__init__.py +0 -0
  32. app/core/clients/codex.py +996 -0
  33. app/core/clients/codex_version.py +187 -0
  34. app/core/clients/codex_version_snapshot.py +2 -0
  35. app/core/clients/files.py +534 -0
  36. app/core/clients/headers.py +29 -0
  37. app/core/clients/http.py +511 -0
  38. app/core/clients/model_fetcher.py +276 -0
  39. app/core/clients/native_egress.py +1304 -0
  40. app/core/clients/oauth.py +477 -0
  41. app/core/clients/proxy.py +6089 -0
  42. app/core/clients/proxy_websocket.py +1411 -0
  43. app/core/clients/rate_limit_reset_credits.py +412 -0
  44. app/core/clients/stream_errors.py +12 -0
  45. app/core/clients/thread_cache_identity.py +347 -0
  46. app/core/clients/usage.py +467 -0
  47. app/core/clock.py +170 -0
  48. app/core/config/__init__.py +0 -0
  49. app/core/config/background_jobs.py +73 -0
  50. app/core/config/context_window_overrides.py +166 -0
  51. app/core/config/dashboard_overrides.py +145 -0
  52. app/core/config/inheritable.py +47 -0
  53. app/core/config/key_fingerprint.py +115 -0
  54. app/core/config/settings.py +872 -0
  55. app/core/config/settings_cache.py +100 -0
  56. app/core/config/spool_retention.py +217 -0
  57. app/core/config/tiers.py +174 -0
  58. app/core/conversation_archive.py +568 -0
  59. app/core/crypto.py +37 -0
  60. app/core/draining.py +11 -0
  61. app/core/errors.py +365 -0
  62. app/core/exceptions.py +155 -0
  63. app/core/handlers/__init__.py +3 -0
  64. app/core/handlers/exceptions.py +478 -0
  65. app/core/http_protocol.py +176 -0
  66. app/core/http_protocol_httptools.py +204 -0
  67. app/core/ingress_limits.py +17 -0
  68. app/core/metadata_store.py +18 -0
  69. app/core/metrics/__init__.py +0 -0
  70. app/core/metrics/middleware.py +74 -0
  71. app/core/metrics/prometheus.py +604 -0
  72. app/core/middleware/__init__.py +25 -0
  73. app/core/middleware/api_firewall.py +111 -0
  74. app/core/middleware/app_version.py +37 -0
  75. app/core/middleware/dashboard_auth_proxy.py +55 -0
  76. app/core/middleware/dashboard_csrf.py +177 -0
  77. app/core/middleware/dashboard_gzip.py +41 -0
  78. app/core/middleware/dashboard_overrides.py +59 -0
  79. app/core/middleware/firewall_cache.py +91 -0
  80. app/core/middleware/inflight.py +126 -0
  81. app/core/middleware/multipart_content_encoding.py +129 -0
  82. app/core/middleware/path_rewrite.py +148 -0
  83. app/core/middleware/request_body_limit.py +196 -0
  84. app/core/middleware/request_decompression.py +209 -0
  85. app/core/middleware/request_id.py +72 -0
  86. app/core/middleware/required_capability_http.py +116 -0
  87. app/core/middleware/trusted_proxy_headers.py +36 -0
  88. app/core/multipart.py +237 -0
  89. app/core/multipart_fields.py +91 -0
  90. app/core/openai/__init__.py +0 -0
  91. app/core/openai/chat_requests.py +493 -0
  92. app/core/openai/chat_responses.py +931 -0
  93. app/core/openai/contracts.py +46 -0
  94. app/core/openai/exceptions.py +24 -0
  95. app/core/openai/host_models.py +14 -0
  96. app/core/openai/images.py +413 -0
  97. app/core/openai/message_coercion.py +376 -0
  98. app/core/openai/model_refresh_scheduler.py +423 -0
  99. app/core/openai/model_registry.py +997 -0
  100. app/core/openai/model_registry_store.py +548 -0
  101. app/core/openai/models.py +172 -0
  102. app/core/openai/parsing.py +97 -0
  103. app/core/openai/requests.py +1980 -0
  104. app/core/openai/strict_schema.py +199 -0
  105. app/core/openai/tool_call_safety.py +99 -0
  106. app/core/openai/v1_requests.py +187 -0
  107. app/core/plan_types.py +90 -0
  108. app/core/prestop.py +202 -0
  109. app/core/rate_limiter/__init__.py +0 -0
  110. app/core/rate_limiter/db_rate_limiter.py +215 -0
  111. app/core/request_locality.py +473 -0
  112. app/core/resilience/__init__.py +0 -0
  113. app/core/resilience/backpressure.py +57 -0
  114. app/core/resilience/bulkhead.py +202 -0
  115. app/core/resilience/circuit_breaker.py +150 -0
  116. app/core/resilience/degradation.py +55 -0
  117. app/core/resilience/loop_lag_monitor.py +60 -0
  118. app/core/resilience/memory_monitor.py +137 -0
  119. app/core/resilience/network_recovery.py +256 -0
  120. app/core/resilience/overload.py +98 -0
  121. app/core/resilience/toggles.py +114 -0
  122. app/core/retention/__init__.py +0 -0
  123. app/core/retention/job.py +240 -0
  124. app/core/retention/scheduler.py +69 -0
  125. app/core/runtime_logging.py +601 -0
  126. app/core/scheduling/__init__.py +0 -0
  127. app/core/scheduling/leader_election.py +993 -0
  128. app/core/scheduling/leader_election_handle.py +25 -0
  129. app/core/server.py +140 -0
  130. app/core/shutdown.py +326 -0
  131. app/core/socket_peer.py +22 -0
  132. app/core/startup.py +41 -0
  133. app/core/timeout_invariants.py +347 -0
  134. app/core/tracing/__init__.py +0 -0
  135. app/core/tracing/otel.py +207 -0
  136. app/core/types.py +6 -0
  137. app/core/upstream_proxy/__init__.py +13 -0
  138. app/core/upstream_proxy/cache.py +130 -0
  139. app/core/upstream_proxy/resolver.py +189 -0
  140. app/core/upstream_proxy/types.py +104 -0
  141. app/core/usage/__init__.py +407 -0
  142. app/core/usage/depletion.py +109 -0
  143. app/core/usage/live_hub.py +41 -0
  144. app/core/usage/live_snapshots.py +174 -0
  145. app/core/usage/logs.py +212 -0
  146. app/core/usage/metadata_scheduler.py +118 -0
  147. app/core/usage/models.py +54 -0
  148. app/core/usage/pricing.py +576 -0
  149. app/core/usage/pricing_catalog.py +241 -0
  150. app/core/usage/pricing_snapshot.json +821 -0
  151. app/core/usage/quota.py +133 -0
  152. app/core/usage/refresh_policy.py +21 -0
  153. app/core/usage/refresh_scheduler.py +713 -0
  154. app/core/usage/reset_credits_refresh_scheduler.py +435 -0
  155. app/core/usage/types.py +168 -0
  156. app/core/utils/__init__.py +0 -0
  157. app/core/utils/json_guards.py +18 -0
  158. app/core/utils/locks.py +33 -0
  159. app/core/utils/masking.py +20 -0
  160. app/core/utils/proxy_env.py +104 -0
  161. app/core/utils/request_id.py +65 -0
  162. app/core/utils/retry.py +77 -0
  163. app/core/utils/shared_future.py +172 -0
  164. app/core/utils/sse.py +286 -0
  165. app/core/utils/time.py +24 -0
  166. app/db/__init__.py +0 -0
  167. app/db/account_identity_lock.py +56 -0
  168. app/db/alembic/__init__.py +1 -0
  169. app/db/alembic/env.py +70 -0
  170. app/db/alembic/revision_ids.py +43 -0
  171. app/db/alembic/versions/20260213_000000_base_schema.py +248 -0
  172. app/db/alembic/versions/20260213_000100_normalize_account_plan_types.py +45 -0
  173. app/db/alembic/versions/20260213_000200_add_request_logs_reasoning_effort.py +45 -0
  174. app/db/alembic/versions/20260213_000300_add_accounts_reset_at.py +45 -0
  175. app/db/alembic/versions/20260213_000400_add_accounts_chatgpt_account_id.py +45 -0
  176. app/db/alembic/versions/20260213_000500_add_dashboard_settings.py +70 -0
  177. app/db/alembic/versions/20260213_000600_add_dashboard_settings_totp.py +64 -0
  178. app/db/alembic/versions/20260213_000700_add_dashboard_settings_password.py +59 -0
  179. app/db/alembic/versions/20260213_000800_add_api_keys.py +87 -0
  180. app/db/alembic/versions/20260214_000000_add_api_key_limits.py +143 -0
  181. app/db/alembic/versions/20260215_000000_add_idx_logs_requested_at.py +38 -0
  182. app/db/alembic/versions/20260218_000000_add_api_key_usage_reservations.py +117 -0
  183. app/db/alembic/versions/20260218_000100_add_import_without_overwrite_and_drop_accounts_email_unique.py +198 -0
  184. app/db/alembic/versions/20260225_000000_add_dashboard_settings_routing_strategy.py +53 -0
  185. app/db/alembic/versions/20260228_020000_align_api_key_limit_enum_types.py +104 -0
  186. app/db/alembic/versions/20260228_030000_add_api_firewall_allowlist.py +42 -0
  187. app/db/alembic/versions/20260306_000000_add_request_logs_service_tier.py +45 -0
  188. app/db/alembic/versions/20260307_000000_add_api_key_enforcement_fields.py +56 -0
  189. app/db/alembic/versions/20260308_000000_add_sqlite_performance_indexes.py +41 -0
  190. app/db/alembic/versions/20260309_000000_add_additional_usage_history.py +71 -0
  191. app/db/alembic/versions/20260309_000000_request_logs_nullable_account_id.py +28 -0
  192. app/db/alembic/versions/20260310_000000_add_request_logs_transport.py +45 -0
  193. app/db/alembic/versions/20260310_000000_fix_postgresql_enum_value_casing.py +79 -0
  194. app/db/alembic/versions/20260310_120000_add_sticky_session_kinds_and_affinity_ttl.py +110 -0
  195. app/db/alembic/versions/20260312_000000_add_additional_usage_quota_key.py +193 -0
  196. app/db/alembic/versions/20260312_000000_split_sticky_sessions_primary_key_by_kind.py +96 -0
  197. app/db/alembic/versions/20260312_010000_merge_additional_usage_and_sticky_session_heads.py +25 -0
  198. app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_feature_heads.py +25 -0
  199. app/db/alembic/versions/20260312_020000_merge_request_logs_transport_and_sticky_heads.py +25 -0
  200. app/db/alembic/versions/20260312_120000_add_dashboard_upstream_stream_transport.py +62 -0
  201. app/db/alembic/versions/20260313_024500_merge_request_log_transport_heads.py +27 -0
  202. app/db/alembic/versions/20260319_100937_increase_prompt_cache_ttl_to_1800s.py +73 -0
  203. app/db/alembic/versions/20260319_111500_merge_prompt_cache_ttl_and_upstream_transport_heads.py +25 -0
  204. app/db/alembic/versions/20260319_183000_normalize_sqlite_account_status_casing.py +48 -0
  205. app/db/alembic/versions/20260320_000000_add_request_log_requested_actual_tiers.py +51 -0
  206. app/db/alembic/versions/20260321_190000_tighten_dashboard_db_indexes.py +64 -0
  207. app/db/alembic/versions/20260321_210000_merge_request_log_tiers_and_dashboard_index_heads.py +25 -0
  208. app/db/alembic/versions/20260325_000000_add_request_log_cost.py +193 -0
  209. app/db/alembic/versions/20260328_000000_add_rate_limit_attempts.py +48 -0
  210. app/db/alembic/versions/20260328_120000_add_request_log_ttft.py +37 -0
  211. app/db/alembic/versions/20260328_130000_add_audit_logs_table.py +45 -0
  212. app/db/alembic/versions/20260328_140000_add_scheduler_leader_table.py +39 -0
  213. app/db/alembic/versions/20260330_000000_add_cache_locality_settings.py +69 -0
  214. app/db/alembic/versions/20260330_010000_merge_scheduler_leader_and_cache_locality_heads.py +25 -0
  215. app/db/alembic/versions/20260330_020000_add_bridge_ring_members.py +46 -0
  216. app/db/alembic/versions/20260401_000000_add_api_key_enforced_service_tier.py +52 -0
  217. app/db/alembic/versions/20260401_000000_add_cache_invalidation.py +41 -0
  218. app/db/alembic/versions/20260401_020000_merge_cache_invalidation_and_api_key_service_tier_heads.py +22 -0
  219. app/db/alembic/versions/20260402_000000_switch_dashboard_routing_default_to_capacity_weighted.py +66 -0
  220. app/db/alembic/versions/20260403_000000_add_credit_api_key_limit_values.py +44 -0
  221. app/db/alembic/versions/20260406_000000_add_api_key_account_assignments.py +57 -0
  222. app/db/alembic/versions/20260406_010000_add_api_key_assignment_scope_flag.py +75 -0
  223. app/db/alembic/versions/20260407_000000_add_bridge_gateway_safe_mode.py +51 -0
  224. app/db/alembic/versions/20260407_010000_merge_api_key_assignment_and_bridge_gateway_heads.py +25 -0
  225. app/db/alembic/versions/20260408_000000_switch_import_without_overwrite_default_to_true.py +73 -0
  226. app/db/alembic/versions/20260408_010000_merge_import_without_overwrite_and_assignment_heads.py +25 -0
  227. app/db/alembic/versions/20260409_000000_add_http_bridge_sessions.py +130 -0
  228. app/db/alembic/versions/20260409_000000_switch_sticky_threads_and_prefer_earlier_reset_defaults_to_true.py +89 -0
  229. app/db/alembic/versions/20260409_010000_add_dashboard_settings_bootstrap_token.py +57 -0
  230. app/db/alembic/versions/20260409_010000_merge_http_bridge_and_import_without_overwrite_heads.py +25 -0
  231. app/db/alembic/versions/20260409_020000_fix_http_bridge_last_seen_index.py +46 -0
  232. app/db/alembic/versions/20260410_000000_backfill_pristine_dashboard_settings_defaults.py +77 -0
  233. app/db/alembic/versions/20260410_030000_restore_import_without_overwrite_default_true.py +73 -0
  234. app/db/alembic/versions/20260410_040000_merge_dashboard_defaults_and_import_default_heads.py +25 -0
  235. app/db/alembic/versions/20260413_000000_add_accounts_blocked_at.py +44 -0
  236. app/db/alembic/versions/20260415_160000_add_automations_tables.py +189 -0
  237. app/db/alembic/versions/20260415_160000_add_request_logs_response_lookup_index.py +67 -0
  238. app/db/alembic/versions/20260417_000000_add_request_log_plan_type.py +44 -0
  239. app/db/alembic/versions/20260418_190000_add_automation_runs_cycle_key.py +87 -0
  240. app/db/alembic/versions/20260419_000000_add_automation_run_cycle_metadata.py +56 -0
  241. app/db/alembic/versions/20260419_020000_add_automation_run_cycles_snapshot_tables.py +342 -0
  242. app/db/alembic/versions/20260421_000000_add_dashboard_session_ttl_setting.py +51 -0
  243. app/db/alembic/versions/20260421_120000_merge_request_log_lookup_and_plan_type_heads.py +25 -0
  244. app/db/alembic/versions/20260421_130000_merge_automation_and_request_log_heads.py +25 -0
  245. app/db/alembic/versions/20260422_103000_normalize_legacy_automation_run_cycle_keys.py +648 -0
  246. app/db/alembic/versions/20260423_120000_add_api_key_limit_reset_at_index.py +43 -0
  247. app/db/alembic/versions/20260424_000000_merge_dashboard_session_ttl_and_request_log_heads.py +25 -0
  248. app/db/alembic/versions/20260426_000000_add_dashboard_relative_availability_settings.py +68 -0
  249. app/db/alembic/versions/20260427_130000_add_warmup_model_and_request_kind.py +75 -0
  250. app/db/alembic/versions/20260506_000000_add_account_routing_policy.py +37 -0
  251. app/db/alembic/versions/20260509_000000_add_api_key_traffic_class.py +37 -0
  252. app/db/alembic/versions/20260509_010000_add_additional_quota_routing_policies.py +37 -0
  253. app/db/alembic/versions/20260513_000000_add_accounts_alias.py +44 -0
  254. app/db/alembic/versions/20260513_000000_add_api_key_apply_to_codex_model.py +59 -0
  255. app/db/alembic/versions/20260514_000000_add_request_logs_api_key_time_index.py +43 -0
  256. app/db/alembic/versions/20260515_000000_add_prefer_earlier_reset_window.py +47 -0
  257. app/db/alembic/versions/20260515_000000_soft_delete_request_logs_on_account_delete.py +83 -0
  258. app/db/alembic/versions/20260515_020000_add_split_sticky_budget_thresholds.py +62 -0
  259. app/db/alembic/versions/20260516_000000_add_sqlite_hot_path_indexes.py +75 -0
  260. app/db/alembic/versions/20260517_000000_merge_sqlite_hot_path_and_request_log_delete_heads.py +24 -0
  261. app/db/alembic/versions/20260518_000000_add_http_bridge_durable_input_prefix.py +44 -0
  262. app/db/alembic/versions/20260518_010000_merge_http_bridge_and_sqlite_recovery_heads.py +25 -0
  263. app/db/alembic/versions/20260518_120000_add_dashboard_guest_access.py +57 -0
  264. app/db/alembic/versions/20260520_000000_merge_api_key_and_http_bridge_heads.py +26 -0
  265. app/db/alembic/versions/20260520_010000_add_request_logs_api_key_account_index.py +45 -0
  266. app/db/alembic/versions/20260520_010000_merge_automation_and_api_key_heads.py +26 -0
  267. app/db/alembic/versions/20260520_030000_add_quota_planner.py +194 -0
  268. app/db/alembic/versions/20260520_040000_merge_quota_planner_and_request_log_index_heads.py +24 -0
  269. app/db/alembic/versions/20260521_000000_add_account_security_work_authorized.py +46 -0
  270. app/db/alembic/versions/20260521_000000_merge_dashboard_guest_and_api_key_heads.py +26 -0
  271. app/db/alembic/versions/20260521_000000_merge_prefer_reset_window_head.py +26 -0
  272. app/db/alembic/versions/20260521_000000_merge_warmup_and_request_log_index_heads.py +25 -0
  273. app/db/alembic/versions/20260522_000000_add_limit_warmup_trigger.py +195 -0
  274. app/db/alembic/versions/20260524_000000_merge_accounts_alias_and_reset_window_heads.py +24 -0
  275. app/db/alembic/versions/20260525_000000_add_usage_raw_window_latest_index.py +31 -0
  276. app/db/alembic/versions/20260526_000000_add_request_log_failure_metadata.py +100 -0
  277. app/db/alembic/versions/20260531_000000_add_account_workspace_identity.py +39 -0
  278. app/db/alembic/versions/20260531_000000_add_single_account_routing.py +42 -0
  279. app/db/alembic/versions/20260601_000000_merge_relative_availability_and_usage_raw_heads.py +24 -0
  280. app/db/alembic/versions/20260601_010000_add_api_key_usage_sections.py +58 -0
  281. app/db/alembic/versions/20260601_010000_add_routing_policy_persistence.py +67 -0
  282. app/db/alembic/versions/20260601_010000_merge_security_work_and_relative_availability_heads.py +25 -0
  283. app/db/alembic/versions/20260601_010000_merge_split_sticky_and_relative_usage_heads.py +25 -0
  284. app/db/alembic/versions/20260601_010000_merge_warmup_and_relative_availability_heads.py +25 -0
  285. app/db/alembic/versions/20260601_020000_merge_additional_quota_routing_and_relative_availability_heads.py +25 -0
  286. app/db/alembic/versions/20260601_020000_merge_quota_planner_and_relative_availability_heads.py +25 -0
  287. app/db/alembic/versions/20260601_020000_merge_reset_window_and_relative_availability_heads.py +25 -0
  288. app/db/alembic/versions/20260601_020000_merge_routing_policy_and_split_threshold_heads.py +24 -0
  289. app/db/alembic/versions/20260601_020000_merge_warmup_and_request_log_failure_heads.py +25 -0
  290. app/db/alembic/versions/20260601_030000_merge_single_account_and_routing_quota_heads.py +29 -0
  291. app/db/alembic/versions/20260601_040000_merge_security_work_and_routing_consolidation_heads.py +25 -0
  292. app/db/alembic/versions/20260601_050000_merge_quota_planner_and_routing_consolidation_heads.py +25 -0
  293. app/db/alembic/versions/20260602_050000_add_upstream_proxy_routing.py +164 -0
  294. app/db/alembic/versions/20260602_060000_merge_account_workspace_and_failure_heads.py +25 -0
  295. app/db/alembic/versions/20260602_070000_add_request_log_useragent_fields.py +86 -0
  296. app/db/alembic/versions/20260602_070000_merge_quota_planner_and_account_workspace_heads.py +25 -0
  297. app/db/alembic/versions/20260602_080000_merge_upstream_proxy_and_quota_planner_heads.py +25 -0
  298. app/db/alembic/versions/20260602_080000_merge_useragent_and_upstream_proxy_heads.py +24 -0
  299. app/db/alembic/versions/20260603_000000_add_weekly_pace_working_days.py +52 -0
  300. app/db/alembic/versions/20260603_000000_free_account_monthly_window.py +60 -0
  301. app/db/alembic/versions/20260604_000000_add_reauth_required_account_status.py +159 -0
  302. app/db/alembic/versions/20260604_010000_merge_automations_and_reauth_status_heads.py +25 -0
  303. app/db/alembic/versions/20260604_010000_merge_dashboard_guest_and_reauth_status_heads.py +25 -0
  304. app/db/alembic/versions/20260604_010000_merge_useragent_and_reauth_heads.py +24 -0
  305. app/db/alembic/versions/20260607_000000_merge_weekly_monthly_useragent_heads.py +28 -0
  306. app/db/alembic/versions/20260608_000000_add_hide_upstream_quota_from_api_keys.py +50 -0
  307. app/db/alembic/versions/20260611_000000_add_request_log_archive_request_id.py +47 -0
  308. app/db/alembic/versions/20260611_000000_merge_automations_and_weekly_monthly_useragent_heads.py +26 -0
  309. app/db/alembic/versions/20260611_000000_merge_dashboard_guest_and_weekly_useragent_heads.py +26 -0
  310. app/db/alembic/versions/20260611_010000_add_request_log_client_ip.py +57 -0
  311. app/db/alembic/versions/20260611_020000_merge_request_log_archive_and_client_ip_heads.py +26 -0
  312. app/db/alembic/versions/20260611_030000_merge_dashboard_guest_and_request_log_client_ip_heads.py +26 -0
  313. app/db/alembic/versions/20260613_000000_add_accounts_codex_installation_id.py +57 -0
  314. app/db/alembic/versions/20260613_010000_merge_installation_id_and_dashboard_weekly_heads.py +26 -0
  315. app/db/alembic/versions/20260615_000000_merge_automations_and_dashboard_guest_heads.py +26 -0
  316. app/db/alembic/versions/20260623_000000_add_limit_warmup_exhausted_threshold.py +51 -0
  317. app/db/alembic/versions/20260626_000000_add_http_downstream_transport_policy.py +46 -0
  318. app/db/alembic/versions/20260626_010000_add_request_logs_upstream_transport.py +31 -0
  319. app/db/alembic/versions/20260629_000000_add_dashboard_query_hot_path_indexes.py +53 -0
  320. app/db/alembic/versions/20260630_000000_add_limit_warmup_staggered_idle.py +47 -0
  321. app/db/alembic/versions/20260630_000000_merge_request_log_client_ip_and_dashboard_hot_path_heads.py +26 -0
  322. app/db/alembic/versions/20260630_010000_merge_warmup_and_request_log_dashboard_heads.py +26 -0
  323. app/db/alembic/versions/20260630_020000_merge_automations_and_main_heads.py +26 -0
  324. app/db/alembic/versions/20260630_020000_merge_warmup_threshold_and_main_heads.py +26 -0
  325. app/db/alembic/versions/20260630_030000_add_automation_run_model_snapshot.py +59 -0
  326. app/db/alembic/versions/20260630_040000_merge_automation_snapshot_and_warmup_threshold_heads.py +26 -0
  327. app/db/alembic/versions/20260630_050000_add_automation_run_prompt_snapshot.py +52 -0
  328. app/db/alembic/versions/20260701_000000_add_weekly_pace_smoothing_minutes.py +51 -0
  329. app/db/alembic/versions/20260702_000000_add_model_sources.py +176 -0
  330. app/db/alembic/versions/20260705_000000_add_model_source_audio_transcriptions.py +50 -0
  331. app/db/alembic/versions/20260705_000000_harden_dashboard_session_ttl.py +62 -0
  332. app/db/alembic/versions/20260706_000000_add_model_source_audio_per_minute.py +43 -0
  333. app/db/alembic/versions/20260707_000000_merge_model_sources_and_session_ttl.py +24 -0
  334. app/db/alembic/versions/20260707_010000_merge_automations_and_model_sources_heads.py +24 -0
  335. app/db/alembic/versions/20260707_020000_add_automation_job_account_scope.py +125 -0
  336. app/db/alembic/versions/20260709_000000_add_ttft_phase_observability.py +66 -0
  337. app/db/alembic/versions/20260711_000000_add_dashboard_prohibit_fast_mode.py +42 -0
  338. app/db/alembic/versions/20260711_010000_add_account_chatgpt_user_id.py +40 -0
  339. app/db/alembic/versions/20260711_020000_add_dashboard_account_concurrency_caps.py +71 -0
  340. app/db/alembic/versions/20260711_030000_add_limit_warmup_idle_threshold.py +51 -0
  341. app/db/alembic/versions/20260712_010000_add_account_usage_rollups.py +56 -0
  342. app/db/alembic/versions/20260712_020000_add_api_key_usage_rollups.py +53 -0
  343. app/db/alembic/versions/20260713_020000_add_model_registry_snapshot.py +42 -0
  344. app/db/alembic/versions/20260713_040000_add_account_refresh_claims.py +42 -0
  345. app/db/alembic/versions/20260713_040000_add_replica_guardrails.py +64 -0
  346. app/db/alembic/versions/20260713_070000_add_reset_credit_redeem_tables.py +58 -0
  347. app/db/alembic/versions/20260714_000000_add_oauth_flow_states.py +63 -0
  348. app/db/alembic/versions/20260715_000000_add_request_log_queue_latency.py +44 -0
  349. app/db/alembic/versions/20260716_000000_add_oauth_device_flow_slots.py +41 -0
  350. app/db/alembic/versions/20260716_010000_add_dashboard_retention_settings.py +48 -0
  351. app/db/alembic/versions/20260716_010000_add_reset_credit_display_settings.py +73 -0
  352. app/db/alembic/versions/20260717_000000_add_http_bridge_retry_circuits.py +47 -0
  353. app/db/alembic/versions/20260717_000000_merge_retention_and_reset_credit_display_heads.py +26 -0
  354. app/db/alembic/versions/20260717_000000_optimize_dashboard_hot_path_indexes.py +162 -0
  355. app/db/alembic/versions/20260717_000001_merge_retry_circuits_and_dashboard_indexes.py +22 -0
  356. app/db/alembic/versions/20260720_000000_add_request_log_conversation_id.py +57 -0
  357. app/db/alembic/versions/20260722_000000_backfill_request_log_useragent_families.py +40 -0
  358. app/db/alembic/versions/20260724_000000_add_request_usage_time_rollups.py +176 -0
  359. app/db/alembic/versions/20260724_000000_merge_request_log_schema_heads.py +33 -0
  360. app/db/alembic/versions/20260725_000000_add_http_bridge_pending_tool_calls.py +43 -0
  361. app/db/alembic/versions/20260726_000000_add_account_plan_downgrade_observations.py +44 -0
  362. app/db/alembic/versions/20260726_000000_repair_request_usage_rollups_after_merge.py +37 -0
  363. app/db/alembic/versions/20260727_000000_add_sticky_session_continuity_abandoned_at.py +45 -0
  364. app/db/alembic/versions/20260728_000000_merge_pending_tool_calls_and_rollup_repair_heads.py +31 -0
  365. app/db/alembic/versions/20260730_000000_add_api_key_fair_share_threshold.py +44 -0
  366. app/db/alembic/versions/20260730_000000_add_http_bridge_recovery_attempts.py +60 -0
  367. app/db/alembic/versions/20260731_000000_add_capability_lineage_markers.py +38 -0
  368. app/db/alembic/versions/20260803_000000_merge_http_bridge_recovery_and_capability_lineage_heads.py +30 -0
  369. app/db/alembic/versions/20260804_000000_add_http_bridge_operations.py +63 -0
  370. app/db/alembic/versions/20260804_000001_add_global_http_bridge_operation_fingerprint.py +53 -0
  371. app/db/alembic/versions/20260804_230000_add_request_log_connection_request_kind.py +43 -0
  372. app/db/alembic/versions/20260805_000000_add_http_bridge_operation_spool.py +75 -0
  373. app/db/alembic/versions/20260805_000001_finalize_http_bridge_operation_spool.py +65 -0
  374. app/db/alembic/versions/20260806_000000_add_additional_usage_alias_probe_indexes.py +84 -0
  375. app/db/alembic/versions/20260806_000000_add_anonymous_telemetry.py +49 -0
  376. app/db/alembic/versions/20260806_010000_add_conversation_presence_rollup.py +72 -0
  377. app/db/alembic/versions/20260806_020000_add_usage_history_bulk_covering_indexes.py +99 -0
  378. app/db/alembic/versions/20260806_030000_add_api_key_allowed_reasoning_efforts.py +65 -0
  379. app/db/alembic/versions/20260806_120000_add_http_bridge_owner_process_epoch.py +57 -0
  380. app/db/alembic/versions/20260807_000000_merge_http_bridge_operation_spool_and_latest_main.py +24 -0
  381. app/db/alembic/versions/20260808_000000_tune_usage_history_autovacuum.py +54 -0
  382. app/db/alembic/versions/20260810_000000_add_http_bridge_recovery_dispatch_count.py +44 -0
  383. app/db/alembic/versions/20260811_000000_add_hourly_rollup_cancelled_count.py +92 -0
  384. app/db/alembic/versions/20260812_000000_merge_recovery_dispatch_and_hourly_cancelled_heads.py +25 -0
  385. app/db/alembic/versions/20260812_120000_add_sticky_abandonment_scope.py +43 -0
  386. app/db/alembic/versions/20260813_000000_add_file_account_pins.py +40 -0
  387. app/db/alembic/versions/20260816_000000_add_account_pending_deletion.py +81 -0
  388. app/db/alembic/versions/20260816_000000_add_model_source_embeddings.py +50 -0
  389. app/db/alembic/versions/20260821_000000_add_retry_circuit_admission_generation.py +49 -0
  390. app/db/alembic/versions/20260826_000000_add_http_bridge_event_chunks.py +107 -0
  391. app/db/alembic/versions/20260828_000000_add_accounts_chatgpt_identity_index.py +55 -0
  392. app/db/alembic/versions/20260830_000000_add_quota_warmup_claim_expiry.py +83 -0
  393. app/db/alembic/versions/20260908_000000_add_guest_session_generation.py +37 -0
  394. app/db/alembic/versions/20260908_000000_add_subscription_overflow.py +140 -0
  395. app/db/alembic/versions/20260908_000000_replace_upstream_stream_transport_default_sentinel.py +50 -0
  396. app/db/alembic/versions/20260908_020000_merge_overflow_transport_heads.py +27 -0
  397. app/db/alembic/versions/20260909_000000_add_dashboard_roles.py +72 -0
  398. app/db/alembic/versions/20260909_010000_add_dashboard_users.py +183 -0
  399. app/db/alembic/versions/20260909_020000_reproject_compat_admin_credentials.py +105 -0
  400. app/db/alembic/versions/20260909_030000_add_audit_actor_columns.py +103 -0
  401. app/db/alembic/versions/20260909_030000_dashboard_resilience_toggle_settings.py +63 -0
  402. app/db/alembic/versions/20260909_040000_add_dashboard_user_invites.py +54 -0
  403. app/db/alembic/versions/20260909_040000_dashboard_timeout_settings.py +68 -0
  404. app/db/alembic/versions/20260909_050000_dashboard_routing_overload_settings.py +65 -0
  405. app/db/alembic/versions/20260909_060000_add_report_rollup.py +74 -0
  406. app/db/alembic/versions/20260909_070000_automation_run_claim_budget.py +50 -0
  407. app/db/alembic/versions/20260909_080000_dashboard_stream_bridge_budgets.py +62 -0
  408. app/db/alembic/versions/20260909_090000_dashboard_background_job_toggles.py +63 -0
  409. app/db/alembic/versions/20260909_100000_dashboard_codex_prewarm.py +49 -0
  410. app/db/alembic/versions/20260909_110000_model_context_window_overrides.py +45 -0
  411. app/db/alembic/versions/20260909_120000_dashboard_conversation_archive.py +48 -0
  412. app/db/alembic/versions/20260909_130000_add_request_logs_live_facet_indexes.py +96 -0
  413. app/db/alembic/versions/20260910_000000_add_totp_required_for_admin_role.py +44 -0
  414. app/db/alembic/versions/20260910_000000_request_logs_missing_cost_index.py +52 -0
  415. app/db/alembic/versions/20260910_010000_add_dashboard_auth_providers.py +134 -0
  416. app/db/alembic/versions/20260910_010000_dashboard_spool_retention.py +52 -0
  417. app/db/alembic/versions/20260910_020000_add_dashboard_role_mappings.py +74 -0
  418. app/db/alembic/versions/20260910_143000_request_log_affinity.py +28 -0
  419. app/db/alembic/versions/20260910_180000_merge_affinity_guest_heads.py +17 -0
  420. app/db/alembic/versions/20260910_200000_merge_affinity_identity_heads.py +17 -0
  421. app/db/alembic/versions/20260910_220000_merge_affinity_invite_heads.py +17 -0
  422. app/db/alembic/versions/20260911_000000_model_source_pins_kind_expires_index.py +43 -0
  423. app/db/alembic/versions/20260911_010000_merge_pin_index_and_affinity_heads.py +17 -0
  424. app/db/alembic/versions/20260911_020000_add_http_bridge_terminal_append_phase.py +54 -0
  425. app/db/alembic/versions/20260911_030000_add_local_login_policy.py +48 -0
  426. app/db/alembic/versions/20260911_040000_add_thread_cache_identity_mode.py +48 -0
  427. app/db/alembic/versions/20260911_060000_add_bridge_session_continuity_abandonment.py +40 -0
  428. app/db/alembic/versions/20260912_000000_merge_thread_cache_and_bridge_retirement_heads.py +22 -0
  429. app/db/alembic/versions/20260912_010000_drop_legacy_dashboard_credentials.py +140 -0
  430. app/db/alembic/versions/20260913_000000_add_oidc_provider_flow.py +134 -0
  431. app/db/alembic/versions/20260914_000000_add_scim_tokens.py +78 -0
  432. app/db/alembic/versions/20260914_000000_drop_subscription_overflow_schema.py +132 -0
  433. app/db/alembic/versions/20260918_000000_merge_scim_and_overflow_heads.py +17 -0
  434. app/db/alembic/versions/__init__.py +1 -0
  435. app/db/backup.py +64 -0
  436. app/db/migrate.py +1249 -0
  437. app/db/migration_lock.py +160 -0
  438. app/db/migration_url.py +18 -0
  439. app/db/models.py +3100 -0
  440. app/db/recover.py +244 -0
  441. app/db/session.py +1295 -0
  442. app/db/snapshot.py +46 -0
  443. app/db/sqlite_lock_retry.py +190 -0
  444. app/db/sqlite_utils.py +549 -0
  445. app/dependencies.py +462 -0
  446. app/main.py +1240 -0
  447. app/modules/__init__.py +0 -0
  448. app/modules/accounts/__init__.py +0 -0
  449. app/modules/accounts/api.py +426 -0
  450. app/modules/accounts/auth_manager.py +1439 -0
  451. app/modules/accounts/background_repository.py +160 -0
  452. app/modules/accounts/deletion.py +540 -0
  453. app/modules/accounts/mappers.py +654 -0
  454. app/modules/accounts/refresh_claims.py +352 -0
  455. app/modules/accounts/repository.py +1679 -0
  456. app/modules/accounts/schemas.py +308 -0
  457. app/modules/accounts/service.py +809 -0
  458. app/modules/accounts/usage_rollup.py +486 -0
  459. app/modules/accounts/usage_rollup_scheduler.py +75 -0
  460. app/modules/accounts/usage_time_rollup.py +1037 -0
  461. app/modules/accounts/usage_time_rollup_read.py +522 -0
  462. app/modules/api_keys/__init__.py +1 -0
  463. app/modules/api_keys/api.py +344 -0
  464. app/modules/api_keys/last_used_coalescer.py +216 -0
  465. app/modules/api_keys/limit_windows.py +41 -0
  466. app/modules/api_keys/repository.py +1200 -0
  467. app/modules/api_keys/reset_scheduler.py +85 -0
  468. app/modules/api_keys/schemas.py +135 -0
  469. app/modules/api_keys/service.py +2123 -0
  470. app/modules/audit/__init__.py +0 -0
  471. app/modules/audit/api.py +88 -0
  472. app/modules/audit/repository.py +74 -0
  473. app/modules/audit/schemas.py +33 -0
  474. app/modules/audit/service.py +71 -0
  475. app/modules/auth_providers/__init__.py +0 -0
  476. app/modules/auth_providers/api.py +127 -0
  477. app/modules/auth_providers/config.py +343 -0
  478. app/modules/auth_providers/repository.py +101 -0
  479. app/modules/auth_providers/schemas.py +88 -0
  480. app/modules/auth_providers/seed.py +105 -0
  481. app/modules/auth_providers/service.py +289 -0
  482. app/modules/automations/__init__.py +1 -0
  483. app/modules/automations/api.py +369 -0
  484. app/modules/automations/repository.py +1896 -0
  485. app/modules/automations/scheduler.py +107 -0
  486. app/modules/automations/schemas.py +158 -0
  487. app/modules/automations/service.py +2548 -0
  488. app/modules/cache_isolation_probe/__init__.py +0 -0
  489. app/modules/cache_isolation_probe/api.py +188 -0
  490. app/modules/cache_isolation_probe/prefix.py +144 -0
  491. app/modules/cache_isolation_probe/schemas.py +94 -0
  492. app/modules/cache_isolation_probe/sender.py +229 -0
  493. app/modules/cache_isolation_probe/service.py +525 -0
  494. app/modules/conversation_archive/__init__.py +1 -0
  495. app/modules/conversation_archive/api.py +101 -0
  496. app/modules/conversation_archive/schemas.py +28 -0
  497. app/modules/conversation_archive/service.py +165 -0
  498. app/modules/dashboard/__init__.py +1 -0
  499. app/modules/dashboard/api.py +106 -0
  500. app/modules/dashboard/builders.py +107 -0
  501. app/modules/dashboard/repository.py +304 -0
  502. app/modules/dashboard/schemas.py +148 -0
  503. app/modules/dashboard/service.py +534 -0
  504. app/modules/dashboard/timeframes.py +19 -0
  505. app/modules/dashboard/weekly_pace.py +617 -0
  506. app/modules/dashboard_auth/__init__.py +1 -0
  507. app/modules/dashboard_auth/api.py +1344 -0
  508. app/modules/dashboard_auth/oidc_api.py +753 -0
  509. app/modules/dashboard_auth/oidc_flows.py +330 -0
  510. app/modules/dashboard_auth/repository.py +452 -0
  511. app/modules/dashboard_auth/schemas.py +232 -0
  512. app/modules/dashboard_auth/service.py +1384 -0
  513. app/modules/dashboard_roles/__init__.py +0 -0
  514. app/modules/dashboard_roles/api.py +64 -0
  515. app/modules/dashboard_roles/repository.py +54 -0
  516. app/modules/dashboard_roles/schemas.py +29 -0
  517. app/modules/dashboard_roles/seed.py +80 -0
  518. app/modules/dashboard_roles/service.py +142 -0
  519. app/modules/dashboard_users/__init__.py +0 -0
  520. app/modules/dashboard_users/api.py +278 -0
  521. app/modules/dashboard_users/break_glass.py +169 -0
  522. app/modules/dashboard_users/credentials.py +18 -0
  523. app/modules/dashboard_users/identity_resolver.py +665 -0
  524. app/modules/dashboard_users/repository.py +725 -0
  525. app/modules/dashboard_users/schemas.py +117 -0
  526. app/modules/dashboard_users/service.py +1054 -0
  527. app/modules/firewall/__init__.py +1 -0
  528. app/modules/firewall/api.py +78 -0
  529. app/modules/firewall/repository.py +51 -0
  530. app/modules/firewall/schemas.py +28 -0
  531. app/modules/firewall/service.py +93 -0
  532. app/modules/fleet/__init__.py +1 -0
  533. app/modules/fleet/api.py +177 -0
  534. app/modules/fleet/mappers.py +56 -0
  535. app/modules/fleet/observability.py +372 -0
  536. app/modules/fleet/schemas.py +119 -0
  537. app/modules/health/__init__.py +0 -0
  538. app/modules/health/api.py +246 -0
  539. app/modules/health/schemas.py +27 -0
  540. app/modules/limit_warmup/__init__.py +1 -0
  541. app/modules/limit_warmup/repository.py +159 -0
  542. app/modules/limit_warmup/service.py +1001 -0
  543. app/modules/model_sources/__init__.py +1 -0
  544. app/modules/model_sources/api.py +99 -0
  545. app/modules/model_sources/catalog.py +307 -0
  546. app/modules/model_sources/forwarding.py +1435 -0
  547. app/modules/model_sources/projection.py +55 -0
  548. app/modules/model_sources/repository.py +201 -0
  549. app/modules/model_sources/schemas.py +79 -0
  550. app/modules/model_sources/selection.py +166 -0
  551. app/modules/model_sources/service.py +236 -0
  552. app/modules/oauth/__init__.py +0 -0
  553. app/modules/oauth/api.py +101 -0
  554. app/modules/oauth/repository.py +238 -0
  555. app/modules/oauth/schemas.py +49 -0
  556. app/modules/oauth/service.py +1196 -0
  557. app/modules/oauth/templates/oauth_success.html +122 -0
  558. app/modules/proxy/__init__.py +0 -0
  559. app/modules/proxy/_load_balancer/__init__.py +1 -0
  560. app/modules/proxy/_load_balancer/error_rate.py +116 -0
  561. app/modules/proxy/_load_balancer/latency_cohort.py +154 -0
  562. app/modules/proxy/_load_balancer/model_eligibility.py +250 -0
  563. app/modules/proxy/_load_balancer/opportunistic_admission.py +350 -0
  564. app/modules/proxy/_load_balancer/overload_backoff.py +394 -0
  565. app/modules/proxy/_load_balancer/sticky_selection.py +2417 -0
  566. app/modules/proxy/_load_balancer/throughput_cohort.py +233 -0
  567. app/modules/proxy/_load_balancer/ttft_cohort.py +214 -0
  568. app/modules/proxy/_load_balancer/tunables.py +97 -0
  569. app/modules/proxy/_load_balancer/types.py +96 -0
  570. app/modules/proxy/_load_balancer/unbound_selection.py +534 -0
  571. app/modules/proxy/_service/__init__.py +6 -0
  572. app/modules/proxy/_service/api_key_usage.py +745 -0
  573. app/modules/proxy/_service/clock_budget.py +38 -0
  574. app/modules/proxy/_service/codex_control.py +611 -0
  575. app/modules/proxy/_service/compact.py +2211 -0
  576. app/modules/proxy/_service/file_ops.py +749 -0
  577. app/modules/proxy/_service/http_bridge/__init__.py +3 -0
  578. app/modules/proxy/_service/http_bridge/accepted_replay.py +331 -0
  579. app/modules/proxy/_service/http_bridge/account_sessions.py +57 -0
  580. app/modules/proxy/_service/http_bridge/activity.py +178 -0
  581. app/modules/proxy/_service/http_bridge/helpers.py +3959 -0
  582. app/modules/proxy/_service/http_bridge/mixin.py +2435 -0
  583. app/modules/proxy/_service/http_bridge/owner_forwarding.py +609 -0
  584. app/modules/proxy/_service/http_bridge/protocol.py +167 -0
  585. app/modules/proxy/_service/http_bridge/proxy_failover.py +58 -0
  586. app/modules/proxy/_service/http_bridge/quarantine.py +443 -0
  587. app/modules/proxy/_service/http_bridge/request_submit.py +4582 -0
  588. app/modules/proxy/_service/http_bridge/retry_circuit.py +2442 -0
  589. app/modules/proxy/_service/http_bridge/service_stubs.py +492 -0
  590. app/modules/proxy/_service/http_bridge/session_registry.py +778 -0
  591. app/modules/proxy/_service/http_bridge/streaming.py +5328 -0
  592. app/modules/proxy/_service/http_bridge/upstream_events.py +4538 -0
  593. app/modules/proxy/_service/observability.py +410 -0
  594. app/modules/proxy/_service/rate_limit.py +361 -0
  595. app/modules/proxy/_service/realtime_live.py +655 -0
  596. app/modules/proxy/_service/refresh.py +154 -0
  597. app/modules/proxy/_service/request_log.py +585 -0
  598. app/modules/proxy/_service/response_create.py +930 -0
  599. app/modules/proxy/_service/streaming/__init__.py +3 -0
  600. app/modules/proxy/_service/streaming/helpers.py +1317 -0
  601. app/modules/proxy/_service/streaming/mixin.py +1100 -0
  602. app/modules/proxy/_service/streaming/protocol.py +32 -0
  603. app/modules/proxy/_service/streaming/retry.py +3762 -0
  604. app/modules/proxy/_service/support.py +2122 -0
  605. app/modules/proxy/_service/transcribe.py +434 -0
  606. app/modules/proxy/_service/warmup.py +483 -0
  607. app/modules/proxy/_service/websocket/__init__.py +3 -0
  608. app/modules/proxy/_service/websocket/helpers.py +2360 -0
  609. app/modules/proxy/_service/websocket/mixin.py +7285 -0
  610. app/modules/proxy/_service/websocket/protocol.py +74 -0
  611. app/modules/proxy/account_cache.py +229 -0
  612. app/modules/proxy/account_eligibility.py +87 -0
  613. app/modules/proxy/additional_model_limits.py +40 -0
  614. app/modules/proxy/affinity.py +830 -0
  615. app/modules/proxy/affinity_observation.py +101 -0
  616. app/modules/proxy/api.py +10254 -0
  617. app/modules/proxy/api_key_usage.py +113 -0
  618. app/modules/proxy/cap_partitioning.py +280 -0
  619. app/modules/proxy/capability_lineage.py +65 -0
  620. app/modules/proxy/capability_lineage_repository.py +82 -0
  621. app/modules/proxy/capability_routing.py +253 -0
  622. app/modules/proxy/continuity.py +112 -0
  623. app/modules/proxy/downstream_delivery.py +277 -0
  624. app/modules/proxy/durable_bridge_coordinator.py +1217 -0
  625. app/modules/proxy/durable_bridge_repository.py +4516 -0
  626. app/modules/proxy/durable_bridge_runtime.py +9 -0
  627. app/modules/proxy/durable_bridge_transcript_codec.py +122 -0
  628. app/modules/proxy/fair_share.py +131 -0
  629. app/modules/proxy/file_pin_repository.py +210 -0
  630. app/modules/proxy/helpers.py +439 -0
  631. app/modules/proxy/http_bridge_event_batcher.py +613 -0
  632. app/modules/proxy/http_bridge_forwarding.py +797 -0
  633. app/modules/proxy/http_continuation.py +76 -0
  634. app/modules/proxy/images_observability.py +62 -0
  635. app/modules/proxy/images_service.py +1054 -0
  636. app/modules/proxy/load_balancer.py +3016 -0
  637. app/modules/proxy/rate_limit_cache.py +46 -0
  638. app/modules/proxy/replay_safety.py +1063 -0
  639. app/modules/proxy/repo_bundle.py +31 -0
  640. app/modules/proxy/request_policy.py +1054 -0
  641. app/modules/proxy/ring_membership.py +251 -0
  642. app/modules/proxy/schemas.py +345 -0
  643. app/modules/proxy/selection_errors.py +41 -0
  644. app/modules/proxy/service.py +2600 -0
  645. app/modules/proxy/source_admission.py +125 -0
  646. app/modules/proxy/source_dispatch.py +999 -0
  647. app/modules/proxy/sticky_repository.py +831 -0
  648. app/modules/proxy/thread_anchors.py +491 -0
  649. app/modules/proxy/tool_call_dedupe.py +802 -0
  650. app/modules/proxy/types.py +54 -0
  651. app/modules/proxy/work_admission.py +121 -0
  652. app/modules/quota_planner/__init__.py +1 -0
  653. app/modules/quota_planner/api.py +276 -0
  654. app/modules/quota_planner/logic.py +743 -0
  655. app/modules/quota_planner/repository.py +722 -0
  656. app/modules/quota_planner/scheduler.py +212 -0
  657. app/modules/quota_planner/schemas.py +102 -0
  658. app/modules/quota_planner/warmup.py +693 -0
  659. app/modules/rate_limit_reset_credits/__init__.py +0 -0
  660. app/modules/rate_limit_reset_credits/api.py +601 -0
  661. app/modules/rate_limit_reset_credits/redeem_coordination.py +274 -0
  662. app/modules/rate_limit_reset_credits/store.py +114 -0
  663. app/modules/reports/__init__.py +1 -0
  664. app/modules/reports/api.py +134 -0
  665. app/modules/reports/cache.py +74 -0
  666. app/modules/reports/filters.py +27 -0
  667. app/modules/reports/repository.py +525 -0
  668. app/modules/reports/rollup.py +150 -0
  669. app/modules/reports/rollup_read.py +148 -0
  670. app/modules/reports/schemas.py +123 -0
  671. app/modules/reports/service.py +287 -0
  672. app/modules/reports/thread_identity.py +256 -0
  673. app/modules/request_logs/__init__.py +0 -0
  674. app/modules/request_logs/api.py +224 -0
  675. app/modules/request_logs/cost_backfill.py +154 -0
  676. app/modules/request_logs/mappers.py +97 -0
  677. app/modules/request_logs/repository.py +1765 -0
  678. app/modules/request_logs/schemas.py +145 -0
  679. app/modules/request_logs/service.py +348 -0
  680. app/modules/role_mappings/__init__.py +0 -0
  681. app/modules/role_mappings/api.py +206 -0
  682. app/modules/role_mappings/matching.py +55 -0
  683. app/modules/role_mappings/repository.py +106 -0
  684. app/modules/role_mappings/schemas.py +67 -0
  685. app/modules/role_mappings/service.py +334 -0
  686. app/modules/runtime/__init__.py +1 -0
  687. app/modules/runtime/api.py +18 -0
  688. app/modules/runtime/schemas.py +14 -0
  689. app/modules/runtime/service.py +218 -0
  690. app/modules/scim/__init__.py +1 -0
  691. app/modules/scim/api.py +194 -0
  692. app/modules/scim/dependencies.py +112 -0
  693. app/modules/scim/errors.py +77 -0
  694. app/modules/scim/management_api.py +156 -0
  695. app/modules/scim/repository.py +212 -0
  696. app/modules/scim/schemas.py +145 -0
  697. app/modules/scim/service.py +786 -0
  698. app/modules/scim/tokens.py +43 -0
  699. app/modules/settings/__init__.py +1 -0
  700. app/modules/settings/api.py +1677 -0
  701. app/modules/settings/repository.py +606 -0
  702. app/modules/settings/schemas.py +496 -0
  703. app/modules/settings/service.py +769 -0
  704. app/modules/shared/__init__.py +0 -0
  705. app/modules/shared/schemas.py +22 -0
  706. app/modules/sticky_sessions/__init__.py +1 -0
  707. app/modules/sticky_sessions/api.py +118 -0
  708. app/modules/sticky_sessions/cleanup_scheduler.py +487 -0
  709. app/modules/sticky_sessions/schemas.py +78 -0
  710. app/modules/sticky_sessions/service.py +196 -0
  711. app/modules/telemetry/__init__.py +5 -0
  712. app/modules/telemetry/api.py +115 -0
  713. app/modules/telemetry/clients.py +62 -0
  714. app/modules/telemetry/consent.py +115 -0
  715. app/modules/telemetry/scheduler.py +85 -0
  716. app/modules/telemetry/schemas.py +163 -0
  717. app/modules/telemetry/sender.py +221 -0
  718. app/modules/telemetry/snapshot.py +490 -0
  719. app/modules/usage/__init__.py +0 -0
  720. app/modules/usage/additional_quota_keys.py +379 -0
  721. app/modules/usage/api.py +45 -0
  722. app/modules/usage/background_repository.py +147 -0
  723. app/modules/usage/builders.py +559 -0
  724. app/modules/usage/depletion_service.py +277 -0
  725. app/modules/usage/live_ingest.py +356 -0
  726. app/modules/usage/mappers.py +29 -0
  727. app/modules/usage/plan_downgrade_observations.py +488 -0
  728. app/modules/usage/repository.py +1890 -0
  729. app/modules/usage/schemas.py +68 -0
  730. app/modules/usage/service.py +102 -0
  731. app/modules/usage/updater.py +1488 -0
  732. app/static/assets/Trans-Cj-J9mVA.js +1 -0
  733. app/static/assets/access-page-DHzZiXZi.js +1 -0
  734. app/static/assets/account-cost-donut-DGhfA4U8.js +1 -0
  735. app/static/assets/account-identifiers-CxbdLshZ.js +1 -0
  736. app/static/assets/account-status-DIsU5sUS.js +1 -0
  737. app/static/assets/account-trend-chart-BptlfwwQ.js +1 -0
  738. app/static/assets/accounts-page-Bbai8ift.js +3 -0
  739. app/static/assets/api-Dwa7XxPe.js +1 -0
  740. app/static/assets/api-client-dugX1Pti.js +55 -0
  741. app/static/assets/api-key-create-dialog-DnRm0oYN.js +1 -0
  742. app/static/assets/api-key-created-dialog-B6jkDG9f.js +1 -0
  743. app/static/assets/api-key-edit-dialog-Ck3Bnc3V.js +1 -0
  744. app/static/assets/api-trend-chart-BchCw7Hj.js +1 -0
  745. app/static/assets/apis-page-BvXz9c6i.js +2 -0
  746. app/static/assets/arrow-up-Dqh_KzJo.js +1 -0
  747. app/static/assets/arrow-up-down-LBRgVDGY.js +1 -0
  748. app/static/assets/automations-page-DQgNAJOR.js +3 -0
  749. app/static/assets/badge-DqMb9es0.js +1 -0
  750. app/static/assets/blur-email-HEvKagG2.js +1 -0
  751. app/static/assets/button-BjVmmiGW.js +1 -0
  752. app/static/assets/checkbox-apsl9vzk.js +1 -0
  753. app/static/assets/chevron-left-1d_pHVa5.js +1 -0
  754. app/static/assets/circle-alert-BS0xd_o1.js +1 -0
  755. app/static/assets/clsx-DB0hHKMi.js +1 -0
  756. app/static/assets/colors-BBy8GEtr.js +1 -0
  757. app/static/assets/copy-button-D7nAvOKR.js +1 -0
  758. app/static/assets/cost-per-day-chart-YdqlkZVM.js +1 -0
  759. app/static/assets/createLucideIcon-DBLzLNh2.js +1 -0
  760. app/static/assets/dashboard-page-CSdhBy0f.js +2 -0
  761. app/static/assets/distribution-metric-format-yZTy1ZEu.js +1 -0
  762. app/static/assets/donut-chart-Bxc69cra.js +1 -0
  763. app/static/assets/download-kQteIcsB.js +1 -0
  764. app/static/assets/ellipsis-B_5OgIre.js +1 -0
  765. app/static/assets/empty-state-JcA7tc8m.js +1 -0
  766. app/static/assets/es2015-bMH8YKZT.js +41 -0
  767. app/static/assets/es6-B264ni6W.js +69 -0
  768. app/static/assets/external-link-UVAOgMQ0.js +1 -0
  769. app/static/assets/i18n-BWqZ9Ua2.js +1 -0
  770. app/static/assets/inbox-B_RM2s1J.js +1 -0
  771. app/static/assets/index-DIpd264Z.js +23 -0
  772. app/static/assets/index-DMeLKRJx.css +2 -0
  773. app/static/assets/inherit-badge-QhTYVaU6.js +1 -0
  774. app/static/assets/invite-dialog-0CYh0GiQ.js +1 -0
  775. app/static/assets/iso-Bpe5Ihbb.js +1 -0
  776. app/static/assets/label-CGaLmLNf.js +1 -0
  777. app/static/assets/lazy-recharts-Pv8p9ArM.js +2 -0
  778. app/static/assets/loading-overlay-CzKQfHLI.js +1 -0
  779. app/static/assets/mini-quota-bar-cGT_t8Ae.js +1 -0
  780. app/static/assets/model-distribution-donut-BKjAfT48.js +1 -0
  781. app/static/assets/model-source-multi-select-D2d06Vc7.js +1 -0
  782. app/static/assets/multi-select-filter-KIA5qU6Z.js +1 -0
  783. app/static/assets/oauth-dialog-XeaGGDjS.js +1 -0
  784. app/static/assets/pagination-controls-D1Ypd0RU.js +1 -0
  785. app/static/assets/payload-CIYnGZz9.js +1 -0
  786. app/static/assets/queue-wait-chart-VoV7Yg9L.js +1 -0
  787. app/static/assets/report-chart-card-BXDliwcc.js +1 -0
  788. app/static/assets/reports-page-CGCJeMHG.js +3 -0
  789. app/static/assets/reset-credit-confirm-dialog-QOifTnVB.js +1 -0
  790. app/static/assets/rolldown-runtime-hePW80VL.js +1 -0
  791. app/static/assets/search-HfhqwERt.js +1 -0
  792. app/static/assets/select-Cl33bz-g.js +1 -0
  793. app/static/assets/settings-page-mZj01HYl.js +2 -0
  794. app/static/assets/shim-CZwyM4Q7.js +1 -0
  795. app/static/assets/skeleton-C_EUc4Rp.js +1 -0
  796. app/static/assets/sparkline-chart-DdNNsddM.js +1 -0
  797. app/static/assets/status-badge-CHHA5X6c.js +1 -0
  798. app/static/assets/switch-CzxgokcM.js +1 -0
  799. app/static/assets/table-DXaNSQ0G.js +1 -0
  800. app/static/assets/time-to-first-token-chart--68L0u_v.js +1 -0
  801. app/static/assets/tokens-per-day-chart-Cs82BFuE.js +1 -0
  802. app/static/assets/tokens-per-second-chart-AD2dfOn6.js +1 -0
  803. app/static/assets/totp-settings-CRHtxQ7j.js +1 -0
  804. app/static/assets/trash-D3KyWr1h.js +1 -0
  805. app/static/assets/use-account-quota-display-BPmrTBTC.js +1 -0
  806. app/static/assets/use-accounts-PWlVGw3z.js +1 -0
  807. app/static/assets/use-auth-CuDlW3iC.js +1 -0
  808. app/static/assets/use-chart-colors-DIu6tClI.js +1 -0
  809. app/static/assets/use-model-sources-Bul24JBu.js +1 -0
  810. app/static/assets/use-models-DUCPUuZg.js +1 -0
  811. app/static/assets/use-reduced-motion-hAm5r6_d.js +1 -0
  812. app/static/assets/useTranslation--56nHhlH.js +1 -0
  813. app/static/assets/useragent-distribution-donut-Dup6sf_n.js +1 -0
  814. app/static/assets/users-uIC3TIlE.js +1 -0
  815. app/static/assets/vendor-query-_bHZuxEx.js +1 -0
  816. app/static/assets/vendor-react-BVL0YZPW.js +9 -0
  817. app/static/favicon.svg +10 -0
  818. app/static/fonts/GeistSans-Variable.woff2 +0 -0
  819. app/static/fonts/jetbrains-mono-latin-ext.woff2 +0 -0
  820. app/static/fonts/jetbrains-mono-latin.woff2 +0 -0
  821. app/static/index.html +29 -0
  822. codexlb_up-1.25.0b10.dist-info/METADATA +124 -0
  823. codexlb_up-1.25.0b10.dist-info/RECORD +827 -0
  824. codexlb_up-1.25.0b10.dist-info/WHEEL +4 -0
  825. codexlb_up-1.25.0b10.dist-info/entry_points.txt +3 -0
  826. codexlb_up-1.25.0b10.dist-info/licenses/LICENSE +21 -0
  827. 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