Procházet zdrojové kódy

Merge pull request #942 from ding113/dev

release v0.6.5
Ding před 3 týdny
rodič
revize
c293f70568
100 změnil soubory, kde provedl 10456 přidání a 597 odebrání
  1. 1 0
      drizzle/0083_aromatic_wolverine.sql
  2. 1 0
      drizzle/0084_needy_jackpot.sql
  3. 4002 0
      drizzle/meta/0083_snapshot.json
  4. 4002 0
      drizzle/meta/0084_snapshot.json
  5. 14 0
      drizzle/meta/_journal.json
  6. 6 3
      messages/en/dashboard.json
  7. 1 0
      messages/en/errors.json
  8. 13 1
      messages/en/quota.json
  9. 4 1
      messages/en/settings/providers/form/sections.json
  10. 6 3
      messages/ja/dashboard.json
  11. 1 0
      messages/ja/errors.json
  12. 13 1
      messages/ja/quota.json
  13. 4 1
      messages/ja/settings/providers/form/sections.json
  14. 6 3
      messages/ru/dashboard.json
  15. 1 0
      messages/ru/errors.json
  16. 13 1
      messages/ru/quota.json
  17. 4 1
      messages/ru/settings/providers/form/sections.json
  18. 6 3
      messages/zh-CN/dashboard.json
  19. 1 0
      messages/zh-CN/errors.json
  20. 13 1
      messages/zh-CN/quota.json
  21. 4 1
      messages/zh-CN/settings/providers/form/sections.json
  22. 6 3
      messages/zh-TW/dashboard.json
  23. 1 0
      messages/zh-TW/errors.json
  24. 14 2
      messages/zh-TW/quota.json
  25. 4 1
      messages/zh-TW/settings/providers/form/sections.json
  26. 13 6
      src/actions/admin-user-insights.ts
  27. 2 2
      src/actions/key-quota.ts
  28. 109 9
      src/actions/keys.ts
  29. 42 19
      src/actions/my-usage.ts
  30. 57 7
      src/actions/provider-endpoints.ts
  31. 31 0
      src/actions/providers.ts
  32. 2 1
      src/actions/usage-logs.ts
  33. 3 0
      src/actions/users.ts
  34. 1 0
      src/app/[locale]/dashboard/_components/user/edit-key-dialog.tsx
  35. 110 2
      src/app/[locale]/dashboard/_components/user/forms/edit-key-form.tsx
  36. 3 0
      src/app/[locale]/dashboard/_components/user/forms/user-form.tsx
  37. 3 0
      src/app/[locale]/dashboard/_components/user/hooks/use-user-translations.ts
  38. 4 0
      src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx
  39. 1 1
      src/app/[locale]/dashboard/leaderboard/user/[userId]/_components/user-insights-view.tsx
  40. 12 10
      src/app/[locale]/dashboard/leaderboard/user/[userId]/_components/user-overview-cards.tsx
  41. 2 4
      src/app/[locale]/dashboard/logs/_components/provider-chain-popover.test.tsx
  42. 117 109
      src/app/[locale]/dashboard/logs/_components/usage-logs-view-virtualized.tsx
  43. 6 6
      src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx
  44. 11 4
      src/app/[locale]/dashboard/quotas/users/page.tsx
  45. 1 1
      src/app/[locale]/settings/providers/_components/batch-edit/build-patch-draft.ts
  46. 4 4
      src/app/[locale]/settings/providers/_components/forms/provider-form.legacy.tsx
  47. 34 92
      src/app/[locale]/settings/providers/_components/forms/provider-form/index.tsx
  48. 8 3
      src/app/[locale]/settings/providers/_components/forms/provider-form/sections/routing-section.tsx
  49. 16 0
      src/app/[locale]/settings/providers/_components/invalidate-provider-queries.ts
  50. 21 3
      src/app/[locale]/settings/providers/_components/provider-endpoints-table.tsx
  51. 10 5
      src/app/[locale]/settings/providers/_components/provider-list.tsx
  52. 168 51
      src/app/[locale]/settings/providers/_components/provider-rich-list-item.tsx
  53. 35 0
      src/app/api/actions/[...route]/route.ts
  54. 43 11
      src/app/v1/_lib/proxy/client-detector.ts
  55. 4 9
      src/app/v1/_lib/proxy/client-guard.ts
  56. 470 0
      src/app/v1/_lib/proxy/endpoint-family-catalog.ts
  57. 3 0
      src/app/v1/_lib/proxy/endpoint-paths.ts
  58. 1 1
      src/app/v1/_lib/proxy/errors.ts
  59. 45 47
      src/app/v1/_lib/proxy/format-mapper.ts
  60. 94 83
      src/app/v1/_lib/proxy/forwarder.ts
  61. 4 3
      src/app/v1/_lib/proxy/provider-selector.ts
  62. 8 5
      src/app/v1/_lib/proxy/rate-limit-guard.ts
  63. 34 1
      src/app/v1/_lib/proxy/response-handler.ts
  64. 24 1
      src/app/v1/_lib/proxy/session-guard.ts
  65. 1 0
      src/app/v1/_lib/url.ts
  66. 3 0
      src/components/form/client-restrictions-editor.test.tsx
  67. 7 7
      src/components/ui/alert-dialog.tsx
  68. 1 1
      src/components/ui/alert.tsx
  69. 1 1
      src/components/ui/avatar.tsx
  70. 1 1
      src/components/ui/card.tsx
  71. 2 2
      src/components/ui/chart.tsx
  72. 1 1
      src/components/ui/collapsible.tsx
  73. 3 3
      src/components/ui/command.tsx
  74. 5 5
      src/components/ui/drawer.tsx
  75. 5 5
      src/components/ui/dropdown-menu.tsx
  76. 1 1
      src/components/ui/popover.tsx
  77. 3 3
      src/components/ui/sheet.tsx
  78. 1 1
      src/components/ui/table.tsx
  79. 1 1
      src/components/ui/tabs.tsx
  80. 5 2
      src/components/ui/tag-input.tsx
  81. 1 1
      src/components/ui/tooltip.tsx
  82. 2 1
      src/drizzle/schema.ts
  83. 165 0
      src/lib/claude-code/metadata-user-id.test.ts
  84. 157 0
      src/lib/claude-code/metadata-user-id.ts
  85. 28 1
      src/lib/client-restrictions/client-presets.test.ts
  86. 10 1
      src/lib/client-restrictions/client-presets.ts
  87. 14 3
      src/lib/gemini/provider-overrides.ts
  88. 2 0
      src/lib/provider-endpoint-error-codes.ts
  89. 1 0
      src/lib/provider-patch-contract.ts
  90. 9 0
      src/lib/rate-limit/cost-reset-utils.ts
  91. 6 6
      src/lib/rate-limit/service.ts
  92. 90 0
      src/lib/redis/cost-cache-cleanup.ts
  93. 1 1
      src/lib/redis/leaderboard-cache.ts
  94. 2 0
      src/lib/security/api-key-auth-cache.ts
  95. 94 16
      src/lib/session-manager.ts
  96. 2 2
      src/lib/validation/schemas.ts
  97. 1 0
      src/repository/_shared/transformers.ts
  98. 55 4
      src/repository/_shared/usage-log-filters.ts
  99. 53 1
      src/repository/admin-user-insights.ts
  100. 25 0
      src/repository/key.ts

+ 1 - 0
drizzle/0083_aromatic_wolverine.sql

@@ -0,0 +1 @@
+ALTER TABLE "keys" ADD COLUMN "cost_reset_at" timestamp with time zone;

+ 1 - 0
drizzle/0084_needy_jackpot.sql

@@ -0,0 +1 @@
+ALTER TABLE "providers" ALTER COLUMN "group_tag" SET DATA TYPE varchar(255);

+ 4002 - 0
drizzle/meta/0083_snapshot.json

@@ -0,0 +1,4002 @@
+{
+  "id": "9efca82f-66e5-4173-a499-db9d00a02956",
+  "prevId": "27de33af-ef32-46fe-8271-f3e88081c11d",
+  "version": "7",
+  "dialect": "postgresql",
+  "tables": {
+    "public.error_rules": {
+      "name": "error_rules",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "pattern": {
+          "name": "pattern",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'regex'"
+        },
+        "category": {
+          "name": "category",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "override_response": {
+          "name": "override_response",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "override_status_code": {
+          "name": "override_status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "is_default": {
+          "name": "is_default",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_error_rules_enabled": {
+          "name": "idx_error_rules_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "unique_pattern": {
+          "name": "unique_pattern",
+          "columns": [
+            {
+              "expression": "pattern",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_category": {
+          "name": "idx_category",
+          "columns": [
+            {
+              "expression": "category",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_match_type": {
+          "name": "idx_match_type",
+          "columns": [
+            {
+              "expression": "match_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.keys": {
+      "name": "keys",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "expires_at": {
+          "name": "expires_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "can_login_web_ui": {
+          "name": "can_login_web_ui",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_daily_usd": {
+          "name": "limit_daily_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_reset_at": {
+          "name": "cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "provider_group": {
+          "name": "provider_group",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'default'"
+        },
+        "cache_ttl_preference": {
+          "name": "cache_ttl_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_keys_user_id": {
+          "name": "idx_keys_user_id",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_key": {
+          "name": "idx_keys_key",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_created_at": {
+          "name": "idx_keys_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_deleted_at": {
+          "name": "idx_keys_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.message_request": {
+      "name": "message_request",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "provider_id": {
+          "name": "provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "model": {
+          "name": "model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "duration_ms": {
+          "name": "duration_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_usd": {
+          "name": "cost_usd",
+          "type": "numeric(21, 15)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0'"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "session_id": {
+          "name": "session_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "request_sequence": {
+          "name": "request_sequence",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 1
+        },
+        "provider_chain": {
+          "name": "provider_chain",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "api_type": {
+          "name": "api_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "endpoint": {
+          "name": "endpoint",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "original_model": {
+          "name": "original_model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "input_tokens": {
+          "name": "input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "output_tokens": {
+          "name": "output_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "ttfb_ms": {
+          "name": "ttfb_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_input_tokens": {
+          "name": "cache_creation_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_read_input_tokens": {
+          "name": "cache_read_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_5m_input_tokens": {
+          "name": "cache_creation_5m_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_1h_input_tokens": {
+          "name": "cache_creation_1h_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_applied": {
+          "name": "cache_ttl_applied",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "context_1m_applied": {
+          "name": "context_1m_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "swap_cache_ttl_applied": {
+          "name": "swap_cache_ttl_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "special_settings": {
+          "name": "special_settings",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_message": {
+          "name": "error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_stack": {
+          "name": "error_stack",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_cause": {
+          "name": "error_cause",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "blocked_by": {
+          "name": "blocked_by",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "blocked_reason": {
+          "name": "blocked_reason",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "user_agent": {
+          "name": "user_agent",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "messages_count": {
+          "name": "messages_count",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_message_request_user_date_cost": {
+          "name": "idx_message_request_user_date_cost",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_created_at_cost_stats": {
+          "name": "idx_message_request_user_created_at_cost_stats",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_query": {
+          "name": "idx_message_request_user_query",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_provider_created_at_active": {
+          "name": "idx_message_request_provider_created_at_active",
+          "columns": [
+            {
+              "expression": "provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_id": {
+          "name": "idx_message_request_session_id",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_id_prefix": {
+          "name": "idx_message_request_session_id_prefix",
+          "columns": [
+            {
+              "expression": "\"session_id\" varchar_pattern_ops",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_seq": {
+          "name": "idx_message_request_session_seq",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "request_sequence",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_endpoint": {
+          "name": "idx_message_request_endpoint",
+          "columns": [
+            {
+              "expression": "endpoint",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_blocked_by": {
+          "name": "idx_message_request_blocked_by",
+          "columns": [
+            {
+              "expression": "blocked_by",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_provider_id": {
+          "name": "idx_message_request_provider_id",
+          "columns": [
+            {
+              "expression": "provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_id": {
+          "name": "idx_message_request_user_id",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key": {
+          "name": "idx_message_request_key",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_created_at_id": {
+          "name": "idx_message_request_key_created_at_id",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_model_active": {
+          "name": "idx_message_request_key_model_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"model\" IS NOT NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_endpoint_active": {
+          "name": "idx_message_request_key_endpoint_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "endpoint",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"endpoint\" IS NOT NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_created_at_id_active": {
+          "name": "idx_message_request_created_at_id_active",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_model_active": {
+          "name": "idx_message_request_model_active",
+          "columns": [
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"model\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_status_code_active": {
+          "name": "idx_message_request_status_code_active",
+          "columns": [
+            {
+              "expression": "status_code",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"status_code\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_created_at": {
+          "name": "idx_message_request_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_deleted_at": {
+          "name": "idx_message_request_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_last_active": {
+          "name": "idx_message_request_key_last_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_cost_active": {
+          "name": "idx_message_request_key_cost_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_user_info": {
+          "name": "idx_message_request_session_user_info",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.model_prices": {
+      "name": "model_prices",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "model_name": {
+          "name": "model_name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "price_data": {
+          "name": "price_data",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "source": {
+          "name": "source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'litellm'"
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_model_prices_latest": {
+          "name": "idx_model_prices_latest",
+          "columns": [
+            {
+              "expression": "model_name",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_model_name": {
+          "name": "idx_model_prices_model_name",
+          "columns": [
+            {
+              "expression": "model_name",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_created_at": {
+          "name": "idx_model_prices_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_source": {
+          "name": "idx_model_prices_source",
+          "columns": [
+            {
+              "expression": "source",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.notification_settings": {
+      "name": "notification_settings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "enabled": {
+          "name": "enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "use_legacy_mode": {
+          "name": "use_legacy_mode",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "circuit_breaker_enabled": {
+          "name": "circuit_breaker_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "circuit_breaker_webhook": {
+          "name": "circuit_breaker_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_leaderboard_enabled": {
+          "name": "daily_leaderboard_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "daily_leaderboard_webhook": {
+          "name": "daily_leaderboard_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_leaderboard_time": {
+          "name": "daily_leaderboard_time",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'09:00'"
+        },
+        "daily_leaderboard_top_n": {
+          "name": "daily_leaderboard_top_n",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "cost_alert_enabled": {
+          "name": "cost_alert_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "cost_alert_webhook": {
+          "name": "cost_alert_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_alert_threshold": {
+          "name": "cost_alert_threshold",
+          "type": "numeric(5, 2)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.80'"
+        },
+        "cost_alert_check_interval": {
+          "name": "cost_alert_check_interval",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 60
+        },
+        "cache_hit_rate_alert_enabled": {
+          "name": "cache_hit_rate_alert_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "cache_hit_rate_alert_webhook": {
+          "name": "cache_hit_rate_alert_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_hit_rate_alert_window_mode": {
+          "name": "cache_hit_rate_alert_window_mode",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'auto'"
+        },
+        "cache_hit_rate_alert_check_interval": {
+          "name": "cache_hit_rate_alert_check_interval",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "cache_hit_rate_alert_historical_lookback_days": {
+          "name": "cache_hit_rate_alert_historical_lookback_days",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 7
+        },
+        "cache_hit_rate_alert_min_eligible_requests": {
+          "name": "cache_hit_rate_alert_min_eligible_requests",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 20
+        },
+        "cache_hit_rate_alert_min_eligible_tokens": {
+          "name": "cache_hit_rate_alert_min_eligible_tokens",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "cache_hit_rate_alert_abs_min": {
+          "name": "cache_hit_rate_alert_abs_min",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "cache_hit_rate_alert_drop_rel": {
+          "name": "cache_hit_rate_alert_drop_rel",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.3'"
+        },
+        "cache_hit_rate_alert_drop_abs": {
+          "name": "cache_hit_rate_alert_drop_abs",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.1'"
+        },
+        "cache_hit_rate_alert_cooldown_minutes": {
+          "name": "cache_hit_rate_alert_cooldown_minutes",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 30
+        },
+        "cache_hit_rate_alert_top_n": {
+          "name": "cache_hit_rate_alert_top_n",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.notification_target_bindings": {
+      "name": "notification_target_bindings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "notification_type": {
+          "name": "notification_type",
+          "type": "notification_type",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "target_id": {
+          "name": "target_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "schedule_cron": {
+          "name": "schedule_cron",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "schedule_timezone": {
+          "name": "schedule_timezone",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "template_override": {
+          "name": "template_override",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "unique_notification_target_binding": {
+          "name": "unique_notification_target_binding",
+          "columns": [
+            {
+              "expression": "notification_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "target_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_notification_bindings_type": {
+          "name": "idx_notification_bindings_type",
+          "columns": [
+            {
+              "expression": "notification_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_notification_bindings_target": {
+          "name": "idx_notification_bindings_target",
+          "columns": [
+            {
+              "expression": "target_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "notification_target_bindings_target_id_webhook_targets_id_fk": {
+          "name": "notification_target_bindings_target_id_webhook_targets_id_fk",
+          "tableFrom": "notification_target_bindings",
+          "tableTo": "webhook_targets",
+          "columnsFrom": [
+            "target_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_endpoint_probe_logs": {
+      "name": "provider_endpoint_probe_logs",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "endpoint_id": {
+          "name": "endpoint_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "source": {
+          "name": "source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'scheduled'"
+        },
+        "ok": {
+          "name": "ok",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "latency_ms": {
+          "name": "latency_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_type": {
+          "name": "error_type",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_message": {
+          "name": "error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_provider_endpoint_probe_logs_endpoint_created_at": {
+          "name": "idx_provider_endpoint_probe_logs_endpoint_created_at",
+          "columns": [
+            {
+              "expression": "endpoint_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoint_probe_logs_created_at": {
+          "name": "idx_provider_endpoint_probe_logs_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "provider_endpoint_probe_logs_endpoint_id_provider_endpoints_id_fk": {
+          "name": "provider_endpoint_probe_logs_endpoint_id_provider_endpoints_id_fk",
+          "tableFrom": "provider_endpoint_probe_logs",
+          "tableTo": "provider_endpoints",
+          "columnsFrom": [
+            "endpoint_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_endpoints": {
+      "name": "provider_endpoints",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "vendor_id": {
+          "name": "vendor_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'claude'"
+        },
+        "url": {
+          "name": "url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "label": {
+          "name": "label",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "sort_order": {
+          "name": "sort_order",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "last_probed_at": {
+          "name": "last_probed_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_ok": {
+          "name": "last_probe_ok",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_status_code": {
+          "name": "last_probe_status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_latency_ms": {
+          "name": "last_probe_latency_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_error_type": {
+          "name": "last_probe_error_type",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_error_message": {
+          "name": "last_probe_error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "uniq_provider_endpoints_vendor_type_url": {
+          "name": "uniq_provider_endpoints_vendor_type_url",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "url",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_vendor_type": {
+          "name": "idx_provider_endpoints_vendor_type",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_enabled": {
+          "name": "idx_provider_endpoints_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_pick_enabled": {
+          "name": "idx_provider_endpoints_pick_enabled",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "sort_order",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_created_at": {
+          "name": "idx_provider_endpoints_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_deleted_at": {
+          "name": "idx_provider_endpoints_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "provider_endpoints_vendor_id_provider_vendors_id_fk": {
+          "name": "provider_endpoints_vendor_id_provider_vendors_id_fk",
+          "tableFrom": "provider_endpoints",
+          "tableTo": "provider_vendors",
+          "columnsFrom": [
+            "vendor_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_vendors": {
+      "name": "provider_vendors",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "website_domain": {
+          "name": "website_domain",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "display_name": {
+          "name": "display_name",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "website_url": {
+          "name": "website_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "favicon_url": {
+          "name": "favicon_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "uniq_provider_vendors_website_domain": {
+          "name": "uniq_provider_vendors_website_domain",
+          "columns": [
+            {
+              "expression": "website_domain",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_vendors_created_at": {
+          "name": "idx_provider_vendors_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.providers": {
+      "name": "providers",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "url": {
+          "name": "url",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_vendor_id": {
+          "name": "provider_vendor_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "weight": {
+          "name": "weight",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 1
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "group_priorities": {
+          "name": "group_priorities",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'1.0'"
+        },
+        "group_tag": {
+          "name": "group_tag",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'claude'"
+        },
+        "preserve_client_ip": {
+          "name": "preserve_client_ip",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "model_redirects": {
+          "name": "model_redirects",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "allowed_models": {
+          "name": "allowed_models",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "allowed_clients": {
+          "name": "allowed_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "blocked_clients": {
+          "name": "blocked_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "active_time_start": {
+          "name": "active_time_start",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "active_time_end": {
+          "name": "active_time_end",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_instructions_strategy": {
+          "name": "codex_instructions_strategy",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'auto'"
+        },
+        "mcp_passthrough_type": {
+          "name": "mcp_passthrough_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'none'"
+        },
+        "mcp_passthrough_url": {
+          "name": "mcp_passthrough_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_daily_usd": {
+          "name": "limit_daily_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "total_cost_reset_at": {
+          "name": "total_cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "max_retry_attempts": {
+          "name": "max_retry_attempts",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "circuit_breaker_failure_threshold": {
+          "name": "circuit_breaker_failure_threshold",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "circuit_breaker_open_duration": {
+          "name": "circuit_breaker_open_duration",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 1800000
+        },
+        "circuit_breaker_half_open_success_threshold": {
+          "name": "circuit_breaker_half_open_success_threshold",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 2
+        },
+        "proxy_url": {
+          "name": "proxy_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_fallback_to_direct": {
+          "name": "proxy_fallback_to_direct",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "first_byte_timeout_streaming_ms": {
+          "name": "first_byte_timeout_streaming_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "streaming_idle_timeout_ms": {
+          "name": "streaming_idle_timeout_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "request_timeout_non_streaming_ms": {
+          "name": "request_timeout_non_streaming_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "website_url": {
+          "name": "website_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "favicon_url": {
+          "name": "favicon_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_preference": {
+          "name": "cache_ttl_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "swap_cache_ttl_billing": {
+          "name": "swap_cache_ttl_billing",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "context_1m_preference": {
+          "name": "context_1m_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_reasoning_effort_preference": {
+          "name": "codex_reasoning_effort_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_reasoning_summary_preference": {
+          "name": "codex_reasoning_summary_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_text_verbosity_preference": {
+          "name": "codex_text_verbosity_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_parallel_tool_calls_preference": {
+          "name": "codex_parallel_tool_calls_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_service_tier_preference": {
+          "name": "codex_service_tier_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_max_tokens_preference": {
+          "name": "anthropic_max_tokens_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_thinking_budget_preference": {
+          "name": "anthropic_thinking_budget_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_adaptive_thinking": {
+          "name": "anthropic_adaptive_thinking",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "gemini_google_search_preference": {
+          "name": "gemini_google_search_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "tpm": {
+          "name": "tpm",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "rpm": {
+          "name": "rpm",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "rpd": {
+          "name": "rpd",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "cc": {
+          "name": "cc",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_providers_enabled_priority": {
+          "name": "idx_providers_enabled_priority",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "weight",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_group": {
+          "name": "idx_providers_group",
+          "columns": [
+            {
+              "expression": "group_tag",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_vendor_type_url_active": {
+          "name": "idx_providers_vendor_type_url_active",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "url",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_created_at": {
+          "name": "idx_providers_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_deleted_at": {
+          "name": "idx_providers_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_vendor_type": {
+          "name": "idx_providers_vendor_type",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_enabled_vendor_type": {
+          "name": "idx_providers_enabled_vendor_type",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL AND \"providers\".\"is_enabled\" = true AND \"providers\".\"provider_vendor_id\" IS NOT NULL AND \"providers\".\"provider_vendor_id\" > 0",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "providers_provider_vendor_id_provider_vendors_id_fk": {
+          "name": "providers_provider_vendor_id_provider_vendors_id_fk",
+          "tableFrom": "providers",
+          "tableTo": "provider_vendors",
+          "columnsFrom": [
+            "provider_vendor_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "restrict",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.request_filters": {
+      "name": "request_filters",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "scope": {
+          "name": "scope",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "action": {
+          "name": "action",
+          "type": "varchar(30)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "target": {
+          "name": "target",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "replacement": {
+          "name": "replacement",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "binding_type": {
+          "name": "binding_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'global'"
+        },
+        "provider_ids": {
+          "name": "provider_ids",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "group_tags": {
+          "name": "group_tags",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "rule_mode": {
+          "name": "rule_mode",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'simple'"
+        },
+        "execution_phase": {
+          "name": "execution_phase",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'guard'"
+        },
+        "operations": {
+          "name": "operations",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_request_filters_enabled": {
+          "name": "idx_request_filters_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_scope": {
+          "name": "idx_request_filters_scope",
+          "columns": [
+            {
+              "expression": "scope",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_action": {
+          "name": "idx_request_filters_action",
+          "columns": [
+            {
+              "expression": "action",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_binding": {
+          "name": "idx_request_filters_binding",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "binding_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_phase": {
+          "name": "idx_request_filters_phase",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "execution_phase",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.sensitive_words": {
+      "name": "sensitive_words",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "word": {
+          "name": "word",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'contains'"
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_sensitive_words_enabled": {
+          "name": "idx_sensitive_words_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "match_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_sensitive_words_created_at": {
+          "name": "idx_sensitive_words_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.system_settings": {
+      "name": "system_settings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "site_title": {
+          "name": "site_title",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'Claude Code Hub'"
+        },
+        "allow_global_usage_view": {
+          "name": "allow_global_usage_view",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "currency_display": {
+          "name": "currency_display",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'USD'"
+        },
+        "billing_model_source": {
+          "name": "billing_model_source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'original'"
+        },
+        "timezone": {
+          "name": "timezone",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "enable_auto_cleanup": {
+          "name": "enable_auto_cleanup",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "cleanup_retention_days": {
+          "name": "cleanup_retention_days",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 30
+        },
+        "cleanup_schedule": {
+          "name": "cleanup_schedule",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0 2 * * *'"
+        },
+        "cleanup_batch_size": {
+          "name": "cleanup_batch_size",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10000
+        },
+        "enable_client_version_check": {
+          "name": "enable_client_version_check",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "verbose_provider_error": {
+          "name": "verbose_provider_error",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "enable_http2": {
+          "name": "enable_http2",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "intercept_anthropic_warmup_requests": {
+          "name": "intercept_anthropic_warmup_requests",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "enable_thinking_signature_rectifier": {
+          "name": "enable_thinking_signature_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_thinking_budget_rectifier": {
+          "name": "enable_thinking_budget_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_billing_header_rectifier": {
+          "name": "enable_billing_header_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_response_input_rectifier": {
+          "name": "enable_response_input_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_codex_session_id_completion": {
+          "name": "enable_codex_session_id_completion",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_claude_metadata_user_id_injection": {
+          "name": "enable_claude_metadata_user_id_injection",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_response_fixer": {
+          "name": "enable_response_fixer",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "response_fixer_config": {
+          "name": "response_fixer_config",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'{\"fixTruncatedJson\":true,\"fixSseFormat\":true,\"fixEncoding\":true,\"maxJsonDepth\":200,\"maxFixSize\":1048576}'::jsonb"
+        },
+        "quota_db_refresh_interval_seconds": {
+          "name": "quota_db_refresh_interval_seconds",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10
+        },
+        "quota_lease_percent_5h": {
+          "name": "quota_lease_percent_5h",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_daily": {
+          "name": "quota_lease_percent_daily",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_weekly": {
+          "name": "quota_lease_percent_weekly",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_monthly": {
+          "name": "quota_lease_percent_monthly",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_cap_usd": {
+          "name": "quota_lease_cap_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.usage_ledger": {
+      "name": "usage_ledger",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "request_id": {
+          "name": "request_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_id": {
+          "name": "provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "final_provider_id": {
+          "name": "final_provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "model": {
+          "name": "model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "original_model": {
+          "name": "original_model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "endpoint": {
+          "name": "endpoint",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "api_type": {
+          "name": "api_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "session_id": {
+          "name": "session_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_success": {
+          "name": "is_success",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "blocked_by": {
+          "name": "blocked_by",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_usd": {
+          "name": "cost_usd",
+          "type": "numeric(21, 15)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0'"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "input_tokens": {
+          "name": "input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "output_tokens": {
+          "name": "output_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_input_tokens": {
+          "name": "cache_creation_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_read_input_tokens": {
+          "name": "cache_read_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_5m_input_tokens": {
+          "name": "cache_creation_5m_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_1h_input_tokens": {
+          "name": "cache_creation_1h_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_applied": {
+          "name": "cache_ttl_applied",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "context_1m_applied": {
+          "name": "context_1m_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "swap_cache_ttl_applied": {
+          "name": "swap_cache_ttl_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "duration_ms": {
+          "name": "duration_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "ttfb_ms": {
+          "name": "ttfb_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {
+        "idx_usage_ledger_request_id": {
+          "name": "idx_usage_ledger_request_id",
+          "columns": [
+            {
+              "expression": "request_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_user_created_at": {
+          "name": "idx_usage_ledger_user_created_at",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_created_at": {
+          "name": "idx_usage_ledger_key_created_at",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_provider_created_at": {
+          "name": "idx_usage_ledger_provider_created_at",
+          "columns": [
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_created_at_minute": {
+          "name": "idx_usage_ledger_created_at_minute",
+          "columns": [
+            {
+              "expression": "date_trunc('minute', \"created_at\" AT TIME ZONE 'UTC')",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_created_at_desc_id": {
+          "name": "idx_usage_ledger_created_at_desc_id",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_session_id": {
+          "name": "idx_usage_ledger_session_id",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"session_id\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_model": {
+          "name": "idx_usage_ledger_model",
+          "columns": [
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"model\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_cost": {
+          "name": "idx_usage_ledger_key_cost",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_user_cost_cover": {
+          "name": "idx_usage_ledger_user_cost_cover",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_provider_cost_cover": {
+          "name": "idx_usage_ledger_provider_cost_cover",
+          "columns": [
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_created_at_desc_cover": {
+          "name": "idx_usage_ledger_key_created_at_desc_cover",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "\"created_at\" DESC NULLS LAST",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.users": {
+      "name": "users",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "role": {
+          "name": "role",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'user'"
+        },
+        "rpm_limit": {
+          "name": "rpm_limit",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_limit_usd": {
+          "name": "daily_limit_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "provider_group": {
+          "name": "provider_group",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'default'"
+        },
+        "tags": {
+          "name": "tags",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_reset_at": {
+          "name": "cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "expires_at": {
+          "name": "expires_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "allowed_clients": {
+          "name": "allowed_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "allowed_models": {
+          "name": "allowed_models",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "blocked_clients": {
+          "name": "blocked_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_users_active_role_sort": {
+          "name": "idx_users_active_role_sort",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "role",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_enabled_expires_at": {
+          "name": "idx_users_enabled_expires_at",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "expires_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_tags_gin": {
+          "name": "idx_users_tags_gin",
+          "columns": [
+            {
+              "expression": "tags",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "gin",
+          "with": {}
+        },
+        "idx_users_created_at": {
+          "name": "idx_users_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_deleted_at": {
+          "name": "idx_users_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.webhook_targets": {
+      "name": "webhook_targets",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "webhook_provider_type",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "webhook_url": {
+          "name": "webhook_url",
+          "type": "varchar(1024)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "telegram_bot_token": {
+          "name": "telegram_bot_token",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "telegram_chat_id": {
+          "name": "telegram_chat_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "dingtalk_secret": {
+          "name": "dingtalk_secret",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "custom_template": {
+          "name": "custom_template",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "custom_headers": {
+          "name": "custom_headers",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_url": {
+          "name": "proxy_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_fallback_to_direct": {
+          "name": "proxy_fallback_to_direct",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "last_test_at": {
+          "name": "last_test_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_test_result": {
+          "name": "last_test_result",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    }
+  },
+  "enums": {
+    "public.daily_reset_mode": {
+      "name": "daily_reset_mode",
+      "schema": "public",
+      "values": [
+        "fixed",
+        "rolling"
+      ]
+    },
+    "public.notification_type": {
+      "name": "notification_type",
+      "schema": "public",
+      "values": [
+        "circuit_breaker",
+        "daily_leaderboard",
+        "cost_alert",
+        "cache_hit_rate_alert"
+      ]
+    },
+    "public.webhook_provider_type": {
+      "name": "webhook_provider_type",
+      "schema": "public",
+      "values": [
+        "wechat",
+        "feishu",
+        "dingtalk",
+        "telegram",
+        "custom"
+      ]
+    }
+  },
+  "schemas": {},
+  "sequences": {},
+  "roles": {},
+  "policies": {},
+  "views": {},
+  "_meta": {
+    "columns": {},
+    "schemas": {},
+    "tables": {}
+  }
+}

+ 4002 - 0
drizzle/meta/0084_snapshot.json

@@ -0,0 +1,4002 @@
+{
+  "id": "1d1ba01c-7adc-467e-bc9c-90abab9e5b92",
+  "prevId": "9efca82f-66e5-4173-a499-db9d00a02956",
+  "version": "7",
+  "dialect": "postgresql",
+  "tables": {
+    "public.error_rules": {
+      "name": "error_rules",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "pattern": {
+          "name": "pattern",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'regex'"
+        },
+        "category": {
+          "name": "category",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "override_response": {
+          "name": "override_response",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "override_status_code": {
+          "name": "override_status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "is_default": {
+          "name": "is_default",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_error_rules_enabled": {
+          "name": "idx_error_rules_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "unique_pattern": {
+          "name": "unique_pattern",
+          "columns": [
+            {
+              "expression": "pattern",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_category": {
+          "name": "idx_category",
+          "columns": [
+            {
+              "expression": "category",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_match_type": {
+          "name": "idx_match_type",
+          "columns": [
+            {
+              "expression": "match_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.keys": {
+      "name": "keys",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": true
+        },
+        "expires_at": {
+          "name": "expires_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "can_login_web_ui": {
+          "name": "can_login_web_ui",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_daily_usd": {
+          "name": "limit_daily_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_reset_at": {
+          "name": "cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "provider_group": {
+          "name": "provider_group",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'default'"
+        },
+        "cache_ttl_preference": {
+          "name": "cache_ttl_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_keys_user_id": {
+          "name": "idx_keys_user_id",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_key": {
+          "name": "idx_keys_key",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_created_at": {
+          "name": "idx_keys_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_keys_deleted_at": {
+          "name": "idx_keys_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.message_request": {
+      "name": "message_request",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "provider_id": {
+          "name": "provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "model": {
+          "name": "model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "duration_ms": {
+          "name": "duration_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_usd": {
+          "name": "cost_usd",
+          "type": "numeric(21, 15)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0'"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "session_id": {
+          "name": "session_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "request_sequence": {
+          "name": "request_sequence",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 1
+        },
+        "provider_chain": {
+          "name": "provider_chain",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "api_type": {
+          "name": "api_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "endpoint": {
+          "name": "endpoint",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "original_model": {
+          "name": "original_model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "input_tokens": {
+          "name": "input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "output_tokens": {
+          "name": "output_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "ttfb_ms": {
+          "name": "ttfb_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_input_tokens": {
+          "name": "cache_creation_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_read_input_tokens": {
+          "name": "cache_read_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_5m_input_tokens": {
+          "name": "cache_creation_5m_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_1h_input_tokens": {
+          "name": "cache_creation_1h_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_applied": {
+          "name": "cache_ttl_applied",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "context_1m_applied": {
+          "name": "context_1m_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "swap_cache_ttl_applied": {
+          "name": "swap_cache_ttl_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "special_settings": {
+          "name": "special_settings",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_message": {
+          "name": "error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_stack": {
+          "name": "error_stack",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_cause": {
+          "name": "error_cause",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "blocked_by": {
+          "name": "blocked_by",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "blocked_reason": {
+          "name": "blocked_reason",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "user_agent": {
+          "name": "user_agent",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "messages_count": {
+          "name": "messages_count",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_message_request_user_date_cost": {
+          "name": "idx_message_request_user_date_cost",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_created_at_cost_stats": {
+          "name": "idx_message_request_user_created_at_cost_stats",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_query": {
+          "name": "idx_message_request_user_query",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_provider_created_at_active": {
+          "name": "idx_message_request_provider_created_at_active",
+          "columns": [
+            {
+              "expression": "provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_id": {
+          "name": "idx_message_request_session_id",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_id_prefix": {
+          "name": "idx_message_request_session_id_prefix",
+          "columns": [
+            {
+              "expression": "\"session_id\" varchar_pattern_ops",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_seq": {
+          "name": "idx_message_request_session_seq",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "request_sequence",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_endpoint": {
+          "name": "idx_message_request_endpoint",
+          "columns": [
+            {
+              "expression": "endpoint",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_blocked_by": {
+          "name": "idx_message_request_blocked_by",
+          "columns": [
+            {
+              "expression": "blocked_by",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_provider_id": {
+          "name": "idx_message_request_provider_id",
+          "columns": [
+            {
+              "expression": "provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_user_id": {
+          "name": "idx_message_request_user_id",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key": {
+          "name": "idx_message_request_key",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_created_at_id": {
+          "name": "idx_message_request_key_created_at_id",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_model_active": {
+          "name": "idx_message_request_key_model_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"model\" IS NOT NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_endpoint_active": {
+          "name": "idx_message_request_key_endpoint_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "endpoint",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"endpoint\" IS NOT NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_created_at_id_active": {
+          "name": "idx_message_request_created_at_id_active",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_model_active": {
+          "name": "idx_message_request_model_active",
+          "columns": [
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"model\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_status_code_active": {
+          "name": "idx_message_request_status_code_active",
+          "columns": [
+            {
+              "expression": "status_code",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND \"message_request\".\"status_code\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_created_at": {
+          "name": "idx_message_request_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_deleted_at": {
+          "name": "idx_message_request_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_last_active": {
+          "name": "idx_message_request_key_last_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_key_cost_active": {
+          "name": "idx_message_request_key_cost_active",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL AND (\"message_request\".\"blocked_by\" IS NULL OR \"message_request\".\"blocked_by\" <> 'warmup')",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_message_request_session_user_info": {
+          "name": "idx_message_request_session_user_info",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"message_request\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.model_prices": {
+      "name": "model_prices",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "model_name": {
+          "name": "model_name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "price_data": {
+          "name": "price_data",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "source": {
+          "name": "source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'litellm'"
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_model_prices_latest": {
+          "name": "idx_model_prices_latest",
+          "columns": [
+            {
+              "expression": "model_name",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_model_name": {
+          "name": "idx_model_prices_model_name",
+          "columns": [
+            {
+              "expression": "model_name",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_created_at": {
+          "name": "idx_model_prices_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_model_prices_source": {
+          "name": "idx_model_prices_source",
+          "columns": [
+            {
+              "expression": "source",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.notification_settings": {
+      "name": "notification_settings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "enabled": {
+          "name": "enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "use_legacy_mode": {
+          "name": "use_legacy_mode",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "circuit_breaker_enabled": {
+          "name": "circuit_breaker_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "circuit_breaker_webhook": {
+          "name": "circuit_breaker_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_leaderboard_enabled": {
+          "name": "daily_leaderboard_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "daily_leaderboard_webhook": {
+          "name": "daily_leaderboard_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_leaderboard_time": {
+          "name": "daily_leaderboard_time",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'09:00'"
+        },
+        "daily_leaderboard_top_n": {
+          "name": "daily_leaderboard_top_n",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "cost_alert_enabled": {
+          "name": "cost_alert_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "cost_alert_webhook": {
+          "name": "cost_alert_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_alert_threshold": {
+          "name": "cost_alert_threshold",
+          "type": "numeric(5, 2)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.80'"
+        },
+        "cost_alert_check_interval": {
+          "name": "cost_alert_check_interval",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 60
+        },
+        "cache_hit_rate_alert_enabled": {
+          "name": "cache_hit_rate_alert_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "cache_hit_rate_alert_webhook": {
+          "name": "cache_hit_rate_alert_webhook",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_hit_rate_alert_window_mode": {
+          "name": "cache_hit_rate_alert_window_mode",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'auto'"
+        },
+        "cache_hit_rate_alert_check_interval": {
+          "name": "cache_hit_rate_alert_check_interval",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "cache_hit_rate_alert_historical_lookback_days": {
+          "name": "cache_hit_rate_alert_historical_lookback_days",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 7
+        },
+        "cache_hit_rate_alert_min_eligible_requests": {
+          "name": "cache_hit_rate_alert_min_eligible_requests",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 20
+        },
+        "cache_hit_rate_alert_min_eligible_tokens": {
+          "name": "cache_hit_rate_alert_min_eligible_tokens",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "cache_hit_rate_alert_abs_min": {
+          "name": "cache_hit_rate_alert_abs_min",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "cache_hit_rate_alert_drop_rel": {
+          "name": "cache_hit_rate_alert_drop_rel",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.3'"
+        },
+        "cache_hit_rate_alert_drop_abs": {
+          "name": "cache_hit_rate_alert_drop_abs",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.1'"
+        },
+        "cache_hit_rate_alert_cooldown_minutes": {
+          "name": "cache_hit_rate_alert_cooldown_minutes",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 30
+        },
+        "cache_hit_rate_alert_top_n": {
+          "name": "cache_hit_rate_alert_top_n",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.notification_target_bindings": {
+      "name": "notification_target_bindings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "notification_type": {
+          "name": "notification_type",
+          "type": "notification_type",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "target_id": {
+          "name": "target_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "schedule_cron": {
+          "name": "schedule_cron",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "schedule_timezone": {
+          "name": "schedule_timezone",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "template_override": {
+          "name": "template_override",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "unique_notification_target_binding": {
+          "name": "unique_notification_target_binding",
+          "columns": [
+            {
+              "expression": "notification_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "target_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_notification_bindings_type": {
+          "name": "idx_notification_bindings_type",
+          "columns": [
+            {
+              "expression": "notification_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_notification_bindings_target": {
+          "name": "idx_notification_bindings_target",
+          "columns": [
+            {
+              "expression": "target_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "notification_target_bindings_target_id_webhook_targets_id_fk": {
+          "name": "notification_target_bindings_target_id_webhook_targets_id_fk",
+          "tableFrom": "notification_target_bindings",
+          "tableTo": "webhook_targets",
+          "columnsFrom": [
+            "target_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_endpoint_probe_logs": {
+      "name": "provider_endpoint_probe_logs",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "endpoint_id": {
+          "name": "endpoint_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "source": {
+          "name": "source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'scheduled'"
+        },
+        "ok": {
+          "name": "ok",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "latency_ms": {
+          "name": "latency_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_type": {
+          "name": "error_type",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "error_message": {
+          "name": "error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_provider_endpoint_probe_logs_endpoint_created_at": {
+          "name": "idx_provider_endpoint_probe_logs_endpoint_created_at",
+          "columns": [
+            {
+              "expression": "endpoint_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoint_probe_logs_created_at": {
+          "name": "idx_provider_endpoint_probe_logs_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "provider_endpoint_probe_logs_endpoint_id_provider_endpoints_id_fk": {
+          "name": "provider_endpoint_probe_logs_endpoint_id_provider_endpoints_id_fk",
+          "tableFrom": "provider_endpoint_probe_logs",
+          "tableTo": "provider_endpoints",
+          "columnsFrom": [
+            "endpoint_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_endpoints": {
+      "name": "provider_endpoints",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "vendor_id": {
+          "name": "vendor_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'claude'"
+        },
+        "url": {
+          "name": "url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "label": {
+          "name": "label",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "sort_order": {
+          "name": "sort_order",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "last_probed_at": {
+          "name": "last_probed_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_ok": {
+          "name": "last_probe_ok",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_status_code": {
+          "name": "last_probe_status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_latency_ms": {
+          "name": "last_probe_latency_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_error_type": {
+          "name": "last_probe_error_type",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_probe_error_message": {
+          "name": "last_probe_error_message",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "uniq_provider_endpoints_vendor_type_url": {
+          "name": "uniq_provider_endpoints_vendor_type_url",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "url",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_vendor_type": {
+          "name": "idx_provider_endpoints_vendor_type",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_enabled": {
+          "name": "idx_provider_endpoints_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_pick_enabled": {
+          "name": "idx_provider_endpoints_pick_enabled",
+          "columns": [
+            {
+              "expression": "vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "sort_order",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"provider_endpoints\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_created_at": {
+          "name": "idx_provider_endpoints_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_endpoints_deleted_at": {
+          "name": "idx_provider_endpoints_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "provider_endpoints_vendor_id_provider_vendors_id_fk": {
+          "name": "provider_endpoints_vendor_id_provider_vendors_id_fk",
+          "tableFrom": "provider_endpoints",
+          "tableTo": "provider_vendors",
+          "columnsFrom": [
+            "vendor_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "cascade",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.provider_vendors": {
+      "name": "provider_vendors",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "website_domain": {
+          "name": "website_domain",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "display_name": {
+          "name": "display_name",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "website_url": {
+          "name": "website_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "favicon_url": {
+          "name": "favicon_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "uniq_provider_vendors_website_domain": {
+          "name": "uniq_provider_vendors_website_domain",
+          "columns": [
+            {
+              "expression": "website_domain",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_provider_vendors_created_at": {
+          "name": "idx_provider_vendors_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.providers": {
+      "name": "providers",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "url": {
+          "name": "url",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_vendor_id": {
+          "name": "provider_vendor_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "weight": {
+          "name": "weight",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 1
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "group_priorities": {
+          "name": "group_priorities",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'1.0'"
+        },
+        "group_tag": {
+          "name": "group_tag",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'claude'"
+        },
+        "preserve_client_ip": {
+          "name": "preserve_client_ip",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "model_redirects": {
+          "name": "model_redirects",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "allowed_models": {
+          "name": "allowed_models",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "allowed_clients": {
+          "name": "allowed_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "blocked_clients": {
+          "name": "blocked_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "active_time_start": {
+          "name": "active_time_start",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "active_time_end": {
+          "name": "active_time_end",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_instructions_strategy": {
+          "name": "codex_instructions_strategy",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'auto'"
+        },
+        "mcp_passthrough_type": {
+          "name": "mcp_passthrough_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'none'"
+        },
+        "mcp_passthrough_url": {
+          "name": "mcp_passthrough_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_daily_usd": {
+          "name": "limit_daily_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "total_cost_reset_at": {
+          "name": "total_cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "max_retry_attempts": {
+          "name": "max_retry_attempts",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "circuit_breaker_failure_threshold": {
+          "name": "circuit_breaker_failure_threshold",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 5
+        },
+        "circuit_breaker_open_duration": {
+          "name": "circuit_breaker_open_duration",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 1800000
+        },
+        "circuit_breaker_half_open_success_threshold": {
+          "name": "circuit_breaker_half_open_success_threshold",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 2
+        },
+        "proxy_url": {
+          "name": "proxy_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_fallback_to_direct": {
+          "name": "proxy_fallback_to_direct",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "first_byte_timeout_streaming_ms": {
+          "name": "first_byte_timeout_streaming_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "streaming_idle_timeout_ms": {
+          "name": "streaming_idle_timeout_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "request_timeout_non_streaming_ms": {
+          "name": "request_timeout_non_streaming_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "website_url": {
+          "name": "website_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "favicon_url": {
+          "name": "favicon_url",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_preference": {
+          "name": "cache_ttl_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "swap_cache_ttl_billing": {
+          "name": "swap_cache_ttl_billing",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "context_1m_preference": {
+          "name": "context_1m_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_reasoning_effort_preference": {
+          "name": "codex_reasoning_effort_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_reasoning_summary_preference": {
+          "name": "codex_reasoning_summary_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_text_verbosity_preference": {
+          "name": "codex_text_verbosity_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_parallel_tool_calls_preference": {
+          "name": "codex_parallel_tool_calls_preference",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "codex_service_tier_preference": {
+          "name": "codex_service_tier_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_max_tokens_preference": {
+          "name": "anthropic_max_tokens_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_thinking_budget_preference": {
+          "name": "anthropic_thinking_budget_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "anthropic_adaptive_thinking": {
+          "name": "anthropic_adaptive_thinking",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'null'::jsonb"
+        },
+        "gemini_google_search_preference": {
+          "name": "gemini_google_search_preference",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "tpm": {
+          "name": "tpm",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "rpm": {
+          "name": "rpm",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "rpd": {
+          "name": "rpd",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "cc": {
+          "name": "cc",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 0
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_providers_enabled_priority": {
+          "name": "idx_providers_enabled_priority",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "weight",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_group": {
+          "name": "idx_providers_group",
+          "columns": [
+            {
+              "expression": "group_tag",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_vendor_type_url_active": {
+          "name": "idx_providers_vendor_type_url_active",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "url",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_created_at": {
+          "name": "idx_providers_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_deleted_at": {
+          "name": "idx_providers_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_vendor_type": {
+          "name": "idx_providers_vendor_type",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_providers_enabled_vendor_type": {
+          "name": "idx_providers_enabled_vendor_type",
+          "columns": [
+            {
+              "expression": "provider_vendor_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "provider_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"providers\".\"deleted_at\" IS NULL AND \"providers\".\"is_enabled\" = true AND \"providers\".\"provider_vendor_id\" IS NOT NULL AND \"providers\".\"provider_vendor_id\" > 0",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {
+        "providers_provider_vendor_id_provider_vendors_id_fk": {
+          "name": "providers_provider_vendor_id_provider_vendors_id_fk",
+          "tableFrom": "providers",
+          "tableTo": "provider_vendors",
+          "columnsFrom": [
+            "provider_vendor_id"
+          ],
+          "columnsTo": [
+            "id"
+          ],
+          "onDelete": "restrict",
+          "onUpdate": "no action"
+        }
+      },
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.request_filters": {
+      "name": "request_filters",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "scope": {
+          "name": "scope",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "action": {
+          "name": "action",
+          "type": "varchar(30)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "target": {
+          "name": "target",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "replacement": {
+          "name": "replacement",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "priority": {
+          "name": "priority",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true,
+          "default": 0
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "binding_type": {
+          "name": "binding_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'global'"
+        },
+        "provider_ids": {
+          "name": "provider_ids",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "group_tags": {
+          "name": "group_tags",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "rule_mode": {
+          "name": "rule_mode",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'simple'"
+        },
+        "execution_phase": {
+          "name": "execution_phase",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'guard'"
+        },
+        "operations": {
+          "name": "operations",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_request_filters_enabled": {
+          "name": "idx_request_filters_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "priority",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_scope": {
+          "name": "idx_request_filters_scope",
+          "columns": [
+            {
+              "expression": "scope",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_action": {
+          "name": "idx_request_filters_action",
+          "columns": [
+            {
+              "expression": "action",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_binding": {
+          "name": "idx_request_filters_binding",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "binding_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_request_filters_phase": {
+          "name": "idx_request_filters_phase",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "execution_phase",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.sensitive_words": {
+      "name": "sensitive_words",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "word": {
+          "name": "word",
+          "type": "varchar(255)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "match_type": {
+          "name": "match_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'contains'"
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {
+        "idx_sensitive_words_enabled": {
+          "name": "idx_sensitive_words_enabled",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "match_type",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_sensitive_words_created_at": {
+          "name": "idx_sensitive_words_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.system_settings": {
+      "name": "system_settings",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "site_title": {
+          "name": "site_title",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'Claude Code Hub'"
+        },
+        "allow_global_usage_view": {
+          "name": "allow_global_usage_view",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "currency_display": {
+          "name": "currency_display",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'USD'"
+        },
+        "billing_model_source": {
+          "name": "billing_model_source",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'original'"
+        },
+        "timezone": {
+          "name": "timezone",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "enable_auto_cleanup": {
+          "name": "enable_auto_cleanup",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "cleanup_retention_days": {
+          "name": "cleanup_retention_days",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 30
+        },
+        "cleanup_schedule": {
+          "name": "cleanup_schedule",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0 2 * * *'"
+        },
+        "cleanup_batch_size": {
+          "name": "cleanup_batch_size",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10000
+        },
+        "enable_client_version_check": {
+          "name": "enable_client_version_check",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "verbose_provider_error": {
+          "name": "verbose_provider_error",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "enable_http2": {
+          "name": "enable_http2",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "intercept_anthropic_warmup_requests": {
+          "name": "intercept_anthropic_warmup_requests",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "enable_thinking_signature_rectifier": {
+          "name": "enable_thinking_signature_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_thinking_budget_rectifier": {
+          "name": "enable_thinking_budget_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_billing_header_rectifier": {
+          "name": "enable_billing_header_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_response_input_rectifier": {
+          "name": "enable_response_input_rectifier",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_codex_session_id_completion": {
+          "name": "enable_codex_session_id_completion",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_claude_metadata_user_id_injection": {
+          "name": "enable_claude_metadata_user_id_injection",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "enable_response_fixer": {
+          "name": "enable_response_fixer",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "response_fixer_config": {
+          "name": "response_fixer_config",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'{\"fixTruncatedJson\":true,\"fixSseFormat\":true,\"fixEncoding\":true,\"maxJsonDepth\":200,\"maxFixSize\":1048576}'::jsonb"
+        },
+        "quota_db_refresh_interval_seconds": {
+          "name": "quota_db_refresh_interval_seconds",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 10
+        },
+        "quota_lease_percent_5h": {
+          "name": "quota_lease_percent_5h",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_daily": {
+          "name": "quota_lease_percent_daily",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_weekly": {
+          "name": "quota_lease_percent_weekly",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_percent_monthly": {
+          "name": "quota_lease_percent_monthly",
+          "type": "numeric(5, 4)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0.05'"
+        },
+        "quota_lease_cap_usd": {
+          "name": "quota_lease_cap_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.usage_ledger": {
+      "name": "usage_ledger",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "request_id": {
+          "name": "request_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "user_id": {
+          "name": "user_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "key": {
+          "name": "key",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_id": {
+          "name": "provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "final_provider_id": {
+          "name": "final_provider_id",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "model": {
+          "name": "model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "original_model": {
+          "name": "original_model",
+          "type": "varchar(128)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "endpoint": {
+          "name": "endpoint",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "api_type": {
+          "name": "api_type",
+          "type": "varchar(20)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "session_id": {
+          "name": "session_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "status_code": {
+          "name": "status_code",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "is_success": {
+          "name": "is_success",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": false
+        },
+        "blocked_by": {
+          "name": "blocked_by",
+          "type": "varchar(50)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_usd": {
+          "name": "cost_usd",
+          "type": "numeric(21, 15)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'0'"
+        },
+        "cost_multiplier": {
+          "name": "cost_multiplier",
+          "type": "numeric(10, 4)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "input_tokens": {
+          "name": "input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "output_tokens": {
+          "name": "output_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_input_tokens": {
+          "name": "cache_creation_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_read_input_tokens": {
+          "name": "cache_read_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_5m_input_tokens": {
+          "name": "cache_creation_5m_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_creation_1h_input_tokens": {
+          "name": "cache_creation_1h_input_tokens",
+          "type": "bigint",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cache_ttl_applied": {
+          "name": "cache_ttl_applied",
+          "type": "varchar(10)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "context_1m_applied": {
+          "name": "context_1m_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "swap_cache_ttl_applied": {
+          "name": "swap_cache_ttl_applied",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "duration_ms": {
+          "name": "duration_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "ttfb_ms": {
+          "name": "ttfb_ms",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": true
+        }
+      },
+      "indexes": {
+        "idx_usage_ledger_request_id": {
+          "name": "idx_usage_ledger_request_id",
+          "columns": [
+            {
+              "expression": "request_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": true,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_user_created_at": {
+          "name": "idx_usage_ledger_user_created_at",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_created_at": {
+          "name": "idx_usage_ledger_key_created_at",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_provider_created_at": {
+          "name": "idx_usage_ledger_provider_created_at",
+          "columns": [
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_created_at_minute": {
+          "name": "idx_usage_ledger_created_at_minute",
+          "columns": [
+            {
+              "expression": "date_trunc('minute', \"created_at\" AT TIME ZONE 'UTC')",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_created_at_desc_id": {
+          "name": "idx_usage_ledger_created_at_desc_id",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": false,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_session_id": {
+          "name": "idx_usage_ledger_session_id",
+          "columns": [
+            {
+              "expression": "session_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"session_id\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_model": {
+          "name": "idx_usage_ledger_model",
+          "columns": [
+            {
+              "expression": "model",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"model\" IS NOT NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_cost": {
+          "name": "idx_usage_ledger_key_cost",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_user_cost_cover": {
+          "name": "idx_usage_ledger_user_cost_cover",
+          "columns": [
+            {
+              "expression": "user_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_provider_cost_cover": {
+          "name": "idx_usage_ledger_provider_cost_cover",
+          "columns": [
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "cost_usd",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_usage_ledger_key_created_at_desc_cover": {
+          "name": "idx_usage_ledger_key_created_at_desc_cover",
+          "columns": [
+            {
+              "expression": "key",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "\"created_at\" DESC NULLS LAST",
+              "asc": true,
+              "isExpression": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "final_provider_id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"usage_ledger\".\"blocked_by\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.users": {
+      "name": "users",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "description": {
+          "name": "description",
+          "type": "text",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "role": {
+          "name": "role",
+          "type": "varchar",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'user'"
+        },
+        "rpm_limit": {
+          "name": "rpm_limit",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_limit_usd": {
+          "name": "daily_limit_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "provider_group": {
+          "name": "provider_group",
+          "type": "varchar(200)",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'default'"
+        },
+        "tags": {
+          "name": "tags",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "limit_5h_usd": {
+          "name": "limit_5h_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_weekly_usd": {
+          "name": "limit_weekly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_monthly_usd": {
+          "name": "limit_monthly_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_total_usd": {
+          "name": "limit_total_usd",
+          "type": "numeric(10, 2)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "cost_reset_at": {
+          "name": "cost_reset_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "limit_concurrent_sessions": {
+          "name": "limit_concurrent_sessions",
+          "type": "integer",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "daily_reset_mode": {
+          "name": "daily_reset_mode",
+          "type": "daily_reset_mode",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'fixed'"
+        },
+        "daily_reset_time": {
+          "name": "daily_reset_time",
+          "type": "varchar(5)",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'00:00'"
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "expires_at": {
+          "name": "expires_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "allowed_clients": {
+          "name": "allowed_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "allowed_models": {
+          "name": "allowed_models",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "'[]'::jsonb"
+        },
+        "blocked_clients": {
+          "name": "blocked_clients",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": true,
+          "default": "'[]'::jsonb"
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "deleted_at": {
+          "name": "deleted_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        }
+      },
+      "indexes": {
+        "idx_users_active_role_sort": {
+          "name": "idx_users_active_role_sort",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "role",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "id",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_enabled_expires_at": {
+          "name": "idx_users_enabled_expires_at",
+          "columns": [
+            {
+              "expression": "is_enabled",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            },
+            {
+              "expression": "expires_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_tags_gin": {
+          "name": "idx_users_tags_gin",
+          "columns": [
+            {
+              "expression": "tags",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "where": "\"users\".\"deleted_at\" IS NULL",
+          "concurrently": false,
+          "method": "gin",
+          "with": {}
+        },
+        "idx_users_created_at": {
+          "name": "idx_users_created_at",
+          "columns": [
+            {
+              "expression": "created_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        },
+        "idx_users_deleted_at": {
+          "name": "idx_users_deleted_at",
+          "columns": [
+            {
+              "expression": "deleted_at",
+              "isExpression": false,
+              "asc": true,
+              "nulls": "last"
+            }
+          ],
+          "isUnique": false,
+          "concurrently": false,
+          "method": "btree",
+          "with": {}
+        }
+      },
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    },
+    "public.webhook_targets": {
+      "name": "webhook_targets",
+      "schema": "",
+      "columns": {
+        "id": {
+          "name": "id",
+          "type": "serial",
+          "primaryKey": true,
+          "notNull": true
+        },
+        "name": {
+          "name": "name",
+          "type": "varchar(100)",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "provider_type": {
+          "name": "provider_type",
+          "type": "webhook_provider_type",
+          "typeSchema": "public",
+          "primaryKey": false,
+          "notNull": true
+        },
+        "webhook_url": {
+          "name": "webhook_url",
+          "type": "varchar(1024)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "telegram_bot_token": {
+          "name": "telegram_bot_token",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "telegram_chat_id": {
+          "name": "telegram_chat_id",
+          "type": "varchar(64)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "dingtalk_secret": {
+          "name": "dingtalk_secret",
+          "type": "varchar(256)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "custom_template": {
+          "name": "custom_template",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "custom_headers": {
+          "name": "custom_headers",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_url": {
+          "name": "proxy_url",
+          "type": "varchar(512)",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "proxy_fallback_to_direct": {
+          "name": "proxy_fallback_to_direct",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": false
+        },
+        "is_enabled": {
+          "name": "is_enabled",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": true,
+          "default": true
+        },
+        "last_test_at": {
+          "name": "last_test_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "last_test_result": {
+          "name": "last_test_result",
+          "type": "jsonb",
+          "primaryKey": false,
+          "notNull": false
+        },
+        "created_at": {
+          "name": "created_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        },
+        "updated_at": {
+          "name": "updated_at",
+          "type": "timestamp with time zone",
+          "primaryKey": false,
+          "notNull": false,
+          "default": "now()"
+        }
+      },
+      "indexes": {},
+      "foreignKeys": {},
+      "compositePrimaryKeys": {},
+      "uniqueConstraints": {},
+      "policies": {},
+      "checkConstraints": {},
+      "isRLSEnabled": false
+    }
+  },
+  "enums": {
+    "public.daily_reset_mode": {
+      "name": "daily_reset_mode",
+      "schema": "public",
+      "values": [
+        "fixed",
+        "rolling"
+      ]
+    },
+    "public.notification_type": {
+      "name": "notification_type",
+      "schema": "public",
+      "values": [
+        "circuit_breaker",
+        "daily_leaderboard",
+        "cost_alert",
+        "cache_hit_rate_alert"
+      ]
+    },
+    "public.webhook_provider_type": {
+      "name": "webhook_provider_type",
+      "schema": "public",
+      "values": [
+        "wechat",
+        "feishu",
+        "dingtalk",
+        "telegram",
+        "custom"
+      ]
+    }
+  },
+  "schemas": {},
+  "sequences": {},
+  "roles": {},
+  "policies": {},
+  "views": {},
+  "_meta": {
+    "columns": {},
+    "schemas": {},
+    "tables": {}
+  }
+}

+ 14 - 0
drizzle/meta/_journal.json

@@ -582,6 +582,20 @@
       "when": 1773423984994,
       "tag": "0082_hot_vision",
       "breakpoints": true
+    },
+    {
+      "idx": 83,
+      "version": "7",
+      "when": 1773768000000,
+      "tag": "0083_aromatic_wolverine",
+      "breakpoints": true
+    },
+    {
+      "idx": 84,
+      "version": "7",
+      "when": 1773809022650,
+      "tag": "0084_needy_jackpot",
+      "breakpoints": true
     }
   ]
 }

+ 6 - 3
messages/en/dashboard.json

@@ -493,8 +493,8 @@
       "overview": "Overview",
       "keyTrend": "Key Usage Trend",
       "modelBreakdown": "Model Breakdown",
-      "todayRequests": "Today Requests",
-      "todayCost": "Today Cost",
+      "requests": "Requests",
+      "cost": "Cost",
       "avgResponseTime": "Avg Response Time",
       "errorRate": "Error Rate",
       "timeRange": {
@@ -1961,7 +1961,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "{count} selected"
     },

+ 1 - 0
messages/en/errors.json

@@ -49,6 +49,7 @@
   "RESOURCE_BUSY": "Resource is currently in use",
   "INVALID_STATE": "Operation not allowed in current state",
   "CONFLICT": "Operation conflict",
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS": "This endpoint is still referenced by {count} enabled providers: {providers}",
 
   "RATE_LIMIT_RPM_EXCEEDED": "Rate limit exceeded: {current} requests per minute (limit: {limit}). Resets at {resetTime}",
   "RATE_LIMIT_5H_EXCEEDED": "5-hour cost limit exceeded: ${current} USD (limit: ${limit} USD). Resets at {resetTime}",

+ 13 - 1
messages/en/quota.json

@@ -348,7 +348,19 @@
       "success": "Key updated successfully",
       "error": "Failed to update key",
       "retryError": "Save failed, please try again later",
-      "keyInfoMissing": "Key information does not exist"
+      "keyInfoMissing": "Key information does not exist",
+      "resetLimits": {
+        "title": "Reset Quota",
+        "description": "Reset all limit counters for this key. Usage logs will be preserved.",
+        "button": "Reset Quota",
+        "confirmTitle": "Reset Quota?",
+        "confirmDescription": "This will reset all accumulated usage counters (5h, daily, weekly, monthly, total) to zero. Usage logs and statistics will be kept.",
+        "confirm": "Yes, reset quota",
+        "loading": "Resetting...",
+        "error": "Failed to reset quota",
+        "success": "Quota has been reset successfully",
+        "lastResetAt": "Last reset: {date}"
+      }
     }
   }
 }

+ 4 - 1
messages/en/settings/providers/form/sections.json

@@ -335,7 +335,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "{count} selected"
     },

+ 6 - 3
messages/ja/dashboard.json

@@ -493,8 +493,8 @@
       "overview": "概要",
       "keyTrend": "Key 使用トレンド",
       "modelBreakdown": "モデル内訳",
-      "todayRequests": "本日リクエスト",
-      "todayCost": "本日コスト",
+      "requests": "リクエスト数",
+      "cost": "コスト",
       "avgResponseTime": "平均応答時間",
       "errorRate": "エラー率",
       "timeRange": {
@@ -1897,7 +1897,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "{count} 件選択"
     },

+ 1 - 0
messages/ja/errors.json

@@ -58,6 +58,7 @@
   "RESOURCE_BUSY": "リソースは現在使用中です",
   "INVALID_STATE": "現在の状態では操作が許可されていません",
   "CONFLICT": "操作の競合",
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS": "このエンドポイントは {count} 件の有効なプロバイダーから参照されています: {providers}",
 
   "USER_NOT_FOUND": "ユーザーが見つかりません",
   "USER_CANNOT_MODIFY_SENSITIVE_FIELDS": "一般ユーザーはクォータ制限とプロバイダーグループを変更できません",

+ 13 - 1
messages/ja/quota.json

@@ -325,7 +325,19 @@
       "success": "キーが正常に更新されました",
       "error": "キーの更新に失敗しました",
       "retryError": "保存に失敗しました。後でもう一度お試しください",
-      "keyInfoMissing": "キー情報が存在しません"
+      "keyInfoMissing": "キー情報が存在しません",
+      "resetLimits": {
+        "title": "クォータのリセット",
+        "description": "このキーのすべての制限カウンターをリセットします。使用ログは保持されます。",
+        "button": "クォータをリセット",
+        "confirmTitle": "クォータをリセットしますか?",
+        "confirmDescription": "これにより、すべての累積使用量カウンター(5時間、日次、週次、月次、合計)がゼロにリセットされます。使用ログと統計は保持されます。",
+        "confirm": "はい、リセットします",
+        "loading": "リセット中...",
+        "error": "クォータのリセットに失敗しました",
+        "success": "クォータが正常にリセットされました",
+        "lastResetAt": "前回のリセット: {date}"
+      }
     }
   }
 }

+ 4 - 1
messages/ja/settings/providers/form/sections.json

@@ -336,7 +336,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "{count} 件選択"
     },

+ 6 - 3
messages/ru/dashboard.json

@@ -493,8 +493,8 @@
       "overview": "Обзор",
       "keyTrend": "Тренд использования ключей",
       "modelBreakdown": "Разбивка по моделям",
-      "todayRequests": "Запросы за сегодня",
-      "todayCost": "Стоимость за сегодня",
+      "requests": "Запросы",
+      "cost": "Стоимость",
       "avgResponseTime": "Среднее время ответа",
       "errorRate": "Частота ошибок",
       "timeRange": {
@@ -1945,7 +1945,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "Выбрано: {count}"
     },

+ 1 - 0
messages/ru/errors.json

@@ -58,6 +58,7 @@
   "RESOURCE_BUSY": "Ресурс в настоящее время используется",
   "INVALID_STATE": "Операция не разрешена в текущем состоянии",
   "CONFLICT": "Конфликт операции",
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS": "Этот endpoint все еще используется {count} активными провайдерами: {providers}",
 
   "USER_NOT_FOUND": "Пользователь не найден",
   "USER_CANNOT_MODIFY_SENSITIVE_FIELDS": "Обычные пользователи не могут изменять лимиты квоты и группы провайдеров",

+ 13 - 1
messages/ru/quota.json

@@ -348,7 +348,19 @@
       "success": "Ключ успешно обновлен",
       "error": "Не удалось обновить ключ",
       "retryError": "Не удалось сохранить, попробуйте позже",
-      "keyInfoMissing": "Информация о ключе отсутствует"
+      "keyInfoMissing": "Информация о ключе отсутствует",
+      "resetLimits": {
+        "title": "Сбросить квоту",
+        "description": "Сбросить все счетчики лимитов для этого ключа. Журналы использования будут сохранены.",
+        "button": "Сбросить квоту",
+        "confirmTitle": "Сбросить квоту?",
+        "confirmDescription": "Это сбросит все накопленные счетчики использования (за 5ч, день, неделю, месяц, всего) до нуля. Журналы использования и статистика будут сохранены.",
+        "confirm": "Да, сбросить квоту",
+        "loading": "Сброс...",
+        "error": "Не удалось сбросить квоту",
+        "success": "Квота успешно сброшена",
+        "lastResetAt": "Последний сброс: {date}"
+      }
     }
   }
 }

+ 4 - 1
messages/ru/settings/providers/form/sections.json

@@ -336,7 +336,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "Выбрано: {count}"
     },

+ 6 - 3
messages/zh-CN/dashboard.json

@@ -493,8 +493,8 @@
       "overview": "概览",
       "keyTrend": "Key 使用趋势",
       "modelBreakdown": "模型明细",
-      "todayRequests": "今日请求",
-      "todayCost": "今日费用",
+      "requests": "请求数",
+      "cost": "费用",
       "avgResponseTime": "平均响应时间",
       "errorRate": "错误率",
       "timeRange": {
@@ -1920,7 +1920,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "已选 {count} 项"
     },

+ 1 - 0
messages/zh-CN/errors.json

@@ -58,6 +58,7 @@
   "RESOURCE_BUSY": "资源正在使用中",
   "INVALID_STATE": "当前状态不允许此操作",
   "CONFLICT": "操作冲突",
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS": "该端点仍被 {count} 个启用中的供应商引用:{providers}",
 
   "USER_NOT_FOUND": "用户不存在",
   "USER_CANNOT_MODIFY_SENSITIVE_FIELDS": "普通用户不能修改账户限额和供应商分组",

+ 13 - 1
messages/zh-CN/quota.json

@@ -348,7 +348,19 @@
       "success": "密钥更新成功",
       "error": "密钥更新失败",
       "retryError": "保存失败,请稍后重试",
-      "keyInfoMissing": "密钥信息不存在"
+      "keyInfoMissing": "密钥信息不存在",
+      "resetLimits": {
+        "title": "重置限额",
+        "description": "重置该密钥的所有限额累计消费计数器。请求日志和统计数据将被保留。",
+        "button": "重置限额",
+        "confirmTitle": "确认重置限额?",
+        "confirmDescription": "这将把所有累计消费计数器(5小时、每日、每周、每月、总计)归零。请求日志和使用统计将被保留。",
+        "confirm": "是的,重置限额",
+        "loading": "正在重置...",
+        "error": "重置限额失败",
+        "success": "所有限额已重置",
+        "lastResetAt": "上次重置: {date}"
+      }
     }
   }
 }

+ 4 - 1
messages/zh-CN/settings/providers/form/sections.json

@@ -81,7 +81,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "已选 {count} 项"
     },

+ 6 - 3
messages/zh-TW/dashboard.json

@@ -493,8 +493,8 @@
       "overview": "概覽",
       "keyTrend": "Key 使用趨勢",
       "modelBreakdown": "模型明細",
-      "todayRequests": "今日請求",
-      "todayCost": "今日費用",
+      "requests": "請求數",
+      "cost": "費用",
       "avgResponseTime": "平均回應時間",
       "errorRate": "錯誤率",
       "timeRange": {
@@ -1905,7 +1905,10 @@
         "sdk-ts": "SDK(TypeScript)",
         "sdk-py": "SDK(Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "已選 {count} 項"
     },

+ 1 - 0
messages/zh-TW/errors.json

@@ -58,6 +58,7 @@
   "RESOURCE_BUSY": "資源正在使用中",
   "INVALID_STATE": "當前狀態不允許此操作",
   "CONFLICT": "操作衝突",
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS": "此端點仍被 {count} 個啟用中的供應商引用:{providers}",
 
   "USER_NOT_FOUND": "使用者不存在",
   "USER_CANNOT_MODIFY_SENSITIVE_FIELDS": "普通使用者不能修改帳戶額度和供應商分組",

+ 14 - 2
messages/zh-TW/quota.json

@@ -19,7 +19,7 @@
       "description": "统计过去5小时内的消费,每小时滚动更新"
     },
     "weekly": {
-      "label": "每重置",
+      "label": "每重置",
       "description": "自然周制(周一00:00重置),整周统计"
     },
     "monthly": {
@@ -323,7 +323,19 @@
       "success": "金鑰更新成功",
       "error": "金鑰更新失敗",
       "retryError": "儲存失敗,請稍後重試",
-      "keyInfoMissing": "金鑰資訊不存在"
+      "keyInfoMissing": "金鑰資訊不存在",
+      "resetLimits": {
+        "title": "重置限額",
+        "description": "重置該金鑰的所有限額累計消費計數器。請求日誌和統計數據將被保留。",
+        "button": "重置限額",
+        "confirmTitle": "確認重置限額?",
+        "confirmDescription": "這將把所有累計消費計數器(5小時、每日、每週、每月、總計)歸零。請求日誌和使用統計將被保留。",
+        "confirm": "是的,重置限額",
+        "loading": "正在重置...",
+        "error": "重置限額失敗",
+        "success": "所有限額已重置",
+        "lastResetAt": "上次重置: {date}"
+      }
     }
   }
 }

+ 4 - 1
messages/zh-TW/settings/providers/form/sections.json

@@ -336,7 +336,10 @@
         "sdk-ts": "SDK (TypeScript)",
         "sdk-py": "SDK (Python)",
         "cli-sdk": "CLI SDK",
-        "gh-action": "GitHub Action"
+        "gh-action": "GitHub Action",
+        "codex-cli-core": "CLI / TUI",
+        "desktop": "Desktop",
+        "exec": "Exec"
       },
       "nSelected": "已選 {count} 項"
     },

+ 13 - 6
src/actions/admin-user-insights.ts

@@ -1,15 +1,15 @@
 "use server";
 
 import { getSession } from "@/lib/auth";
-import { getOverviewWithCache } from "@/lib/redis/overview-cache";
 import { getStatisticsWithCache } from "@/lib/redis/statistics-cache";
 import {
   type AdminUserModelBreakdownItem,
   type AdminUserProviderBreakdownItem,
   getUserModelBreakdown,
+  getUserOverviewMetrics,
   getUserProviderBreakdown,
+  type UserInsightsOverviewMetrics,
 } from "@/repository/admin-user-insights";
-import type { OverviewMetricsWithComparison } from "@/repository/overview";
 import { getSystemSettings } from "@/repository/system-config";
 import { findUserById } from "@/repository/user";
 import type { DatabaseKeyStatRow } from "@/types/statistics";
@@ -26,12 +26,16 @@ function isValidTimeRange(value: string): value is ValidTimeRange {
 }
 
 /**
- * Get overview metrics for a specific user (admin only).
+ * Get overview metrics for a specific user and date range (admin only).
  */
-export async function getUserInsightsOverview(targetUserId: number): Promise<
+export async function getUserInsightsOverview(
+  targetUserId: number,
+  startDate?: string,
+  endDate?: string
+): Promise<
   ActionResult<{
     user: User;
-    overview: OverviewMetricsWithComparison;
+    overview: UserInsightsOverviewMetrics;
     currencyCode: string;
   }>
 > {
@@ -40,13 +44,16 @@ export async function getUserInsightsOverview(targetUserId: number): Promise<
     return { ok: false, error: "Unauthorized" };
   }
 
+  const dateError = validateDateRange(startDate, endDate);
+  if (dateError) return dateError;
+
   const user = await findUserById(targetUserId);
   if (!user) {
     return { ok: false, error: "User not found" };
   }
 
   const [overview, settings] = await Promise.all([
-    getOverviewWithCache(targetUserId),
+    getUserOverviewMetrics(targetUserId, startDate, endDate),
     getSystemSettings(),
   ]);
 

+ 2 - 2
src/actions/key-quota.ts

@@ -7,6 +7,7 @@ import { keys as keysTable, users as usersTable } from "@/drizzle/schema";
 import { getSession } from "@/lib/auth";
 import { logger } from "@/lib/logger";
 import { resolveKeyConcurrentSessionLimit } from "@/lib/rate-limit/concurrent-session-limit";
+import { resolveKeyCostResetAt } from "@/lib/rate-limit/cost-reset-utils";
 import type { DailyResetMode } from "@/lib/rate-limit/time-utils";
 import { SessionTracker } from "@/lib/session-tracker";
 import type { CurrencyCode } from "@/lib/utils";
@@ -111,8 +112,7 @@ export async function getKeyQuotaUsage(keyId: number): Promise<ActionResult<KeyQ
     const rangeWeekly = await getTimeRangeForPeriod("weekly");
     const rangeMonthly = await getTimeRangeForPeriod("monthly");
 
-    // Clip time range starts by user's costResetAt (for limits-only reset)
-    const costResetAt = result.userCostResetAt ?? null;
+    const costResetAt = resolveKeyCostResetAt(keyRow.costResetAt ?? null, result.userCostResetAt);
     const clipStart = (start: Date): Date =>
       costResetAt instanceof Date && costResetAt > start ? costResetAt : start;
 

+ 109 - 9
src/actions/keys.ts

@@ -10,6 +10,7 @@ import { getSession } from "@/lib/auth";
 import { PROVIDER_GROUP } from "@/lib/constants/provider.constants";
 import { logger } from "@/lib/logger";
 import { resolveKeyConcurrentSessionLimit } from "@/lib/rate-limit/concurrent-session-limit";
+import { resolveKeyCostResetAt } from "@/lib/rate-limit/cost-reset-utils";
 import { parseDateInputAsTimezone } from "@/lib/utils/date-input";
 import { ERROR_CODES } from "@/lib/utils/error-messages";
 import { normalizeProviderGroup, parseProviderGroups } from "@/lib/utils/provider-group";
@@ -25,6 +26,7 @@ import {
   findKeyById,
   findKeyList,
   findKeysWithStatistics,
+  resetKeyCostResetAt,
   updateKey,
 } from "@/repository/key";
 import type { Key } from "@/types/key";
@@ -545,7 +547,11 @@ export async function editKey(
       limit_total_usd: validatedData.limitTotalUsd,
       limit_concurrent_sessions: validatedData.limitConcurrentSessions,
       // providerGroup 为 admin-only 字段:非管理员不允许更新该字段
-      ...(isAdmin ? { provider_group: normalizeProviderGroup(validatedData.providerGroup) } : {}),
+      ...(isAdmin
+        ? {
+            provider_group: normalizeProviderGroup(validatedData.providerGroup),
+          }
+        : {}),
       cache_ttl_preference: validatedData.cacheTtlPreference,
     });
 
@@ -734,8 +740,7 @@ export async function getKeyLimitUsage(keyId: number): Promise<
       result.userLimitConcurrentSessions ?? null
     );
 
-    // Clip time range start by costResetAt (for limits-only reset)
-    const costResetAt = result.userCostResetAt ?? null;
+    const costResetAt = resolveKeyCostResetAt(key.costResetAt ?? null, result.userCostResetAt);
     const clipStart = (start: Date): Date =>
       costResetAt instanceof Date && costResetAt > start ? costResetAt : start;
 
@@ -815,6 +820,77 @@ export async function getKeyLimitUsage(keyId: number): Promise<
   }
 }
 
+export async function resetKeyLimitsOnly(keyId: number): Promise<ActionResult> {
+  try {
+    const tError = await getTranslations("errors");
+
+    const session = await getSession();
+    if (!session || session.user.role !== "admin") {
+      return {
+        ok: false,
+        error: tError("PERMISSION_DENIED"),
+        errorCode: ERROR_CODES.PERMISSION_DENIED,
+      };
+    }
+
+    const key = await findKeyById(keyId);
+    if (!key) {
+      return {
+        ok: false,
+        error: tError("KEY_NOT_FOUND"),
+        errorCode: ERROR_CODES.NOT_FOUND,
+      };
+    }
+
+    const updated = await resetKeyCostResetAt(keyId, new Date());
+    if (!updated) {
+      return {
+        ok: false,
+        error: tError("KEY_NOT_FOUND"),
+        errorCode: ERROR_CODES.NOT_FOUND,
+      };
+    }
+
+    try {
+      const { clearSingleKeyCostCache } = await import("@/lib/redis/cost-cache-cleanup");
+      const cacheResult = await clearSingleKeyCostCache({
+        keyId,
+        keyHash: key.key,
+      });
+      if (cacheResult) {
+        logger.info("Reset key limits only - Redis cost cache cleared", {
+          keyId,
+          userId: key.userId,
+          ...cacheResult,
+        });
+      }
+    } catch (error) {
+      logger.error("Failed to clear Redis cache during key limits reset", {
+        keyId,
+        userId: key.userId,
+        error: error instanceof Error ? error.message : String(error),
+      });
+    }
+
+    logger.info("Reset key limits only (costResetAt set)", {
+      keyId,
+      userId: key.userId,
+    });
+    revalidatePath("/dashboard/users");
+    revalidatePath("/dashboard");
+
+    return { ok: true };
+  } catch (error) {
+    logger.error("Failed to reset key limits:", error);
+    const tError = await getTranslations("errors");
+    return {
+      ok: false,
+      error: tError("OPERATION_FAILED"),
+      errorCode: ERROR_CODES.OPERATION_FAILED,
+    };
+  }
+}
+
 /**
  * 切换密钥启用/禁用状态
  */
@@ -824,12 +900,20 @@ export async function toggleKeyEnabled(keyId: number, enabled: boolean): Promise
 
     const session = await getSession();
     if (!session) {
-      return { ok: false, error: tError("UNAUTHORIZED"), errorCode: ERROR_CODES.UNAUTHORIZED };
+      return {
+        ok: false,
+        error: tError("UNAUTHORIZED"),
+        errorCode: ERROR_CODES.UNAUTHORIZED,
+      };
     }
 
     const key = await findKeyById(keyId);
     if (!key) {
-      return { ok: false, error: tError("KEY_NOT_FOUND"), errorCode: ERROR_CODES.NOT_FOUND };
+      return {
+        ok: false,
+        error: tError("KEY_NOT_FOUND"),
+        errorCode: ERROR_CODES.NOT_FOUND,
+      };
     }
 
     // 权限检查:用户只能管理自己的Key,管理员可以管理所有Key
@@ -895,7 +979,11 @@ export async function batchUpdateKeys(
     const MAX_BATCH_SIZE = 500;
     const requestedIds = Array.from(new Set(params.keyIds)).filter((id) => Number.isInteger(id));
     if (requestedIds.length === 0) {
-      return { ok: false, error: tError("REQUIRED_FIELD"), errorCode: ERROR_CODES.REQUIRED_FIELD };
+      return {
+        ok: false,
+        error: tError("REQUIRED_FIELD"),
+        errorCode: ERROR_CODES.REQUIRED_FIELD,
+      };
     }
     if (requestedIds.length > MAX_BATCH_SIZE) {
       return {
@@ -908,7 +996,11 @@ export async function batchUpdateKeys(
     const updates = params.updates ?? {};
     const hasAnyUpdate = Object.values(updates).some((v) => v !== undefined);
     if (!hasAnyUpdate) {
-      return { ok: false, error: tError("EMPTY_UPDATE"), errorCode: ERROR_CODES.EMPTY_UPDATE };
+      return {
+        ok: false,
+        error: tError("EMPTY_UPDATE"),
+        errorCode: ERROR_CODES.EMPTY_UPDATE,
+      };
     }
 
     const normalizedProviderGroup =
@@ -1087,12 +1179,20 @@ export async function renewKeyExpiresAt(
 
     const session = await getSession();
     if (!session) {
-      return { ok: false, error: tError("UNAUTHORIZED"), errorCode: ERROR_CODES.UNAUTHORIZED };
+      return {
+        ok: false,
+        error: tError("UNAUTHORIZED"),
+        errorCode: ERROR_CODES.UNAUTHORIZED,
+      };
     }
 
     const key = await findKeyById(keyId);
     if (!key) {
-      return { ok: false, error: tError("KEY_NOT_FOUND"), errorCode: ERROR_CODES.NOT_FOUND };
+      return {
+        ok: false,
+        error: tError("KEY_NOT_FOUND"),
+        errorCode: ERROR_CODES.NOT_FOUND,
+      };
     }
 
     // 权限检查:用户只能续期自己的Key,管理员可以续期所有Key

+ 42 - 19
src/actions/my-usage.ts

@@ -7,6 +7,7 @@ import { messageRequest, usageLedger } from "@/drizzle/schema";
 import { getSession } from "@/lib/auth";
 import { logger } from "@/lib/logger";
 import { resolveKeyConcurrentSessionLimit } from "@/lib/rate-limit/concurrent-session-limit";
+import { resolveKeyCostResetAt } from "@/lib/rate-limit/cost-reset-utils";
 import type { DailyResetMode } from "@/lib/rate-limit/time-utils";
 import { SessionTracker } from "@/lib/session-tracker";
 import type { CurrencyCode } from "@/lib/utils";
@@ -244,25 +245,47 @@ export async function getMyQuota(): Promise<ActionResult<MyUsageQuota>> {
     const rangeMonthly = await getTimeRangeForPeriod("monthly");
 
     // Clip time range starts by costResetAt (for limits-only reset)
-    const costResetAt = user.costResetAt ?? null;
-    const clipStart = (start: Date): Date =>
-      costResetAt instanceof Date && costResetAt > start ? costResetAt : start;
-
-    const clippedRange5h = { startTime: clipStart(range5h.startTime), endTime: range5h.endTime };
-    const clippedRangeWeekly = {
-      startTime: clipStart(rangeWeekly.startTime),
+    // Key uses MAX(key.costResetAt, user.costResetAt); User uses only user.costResetAt
+    const userCostResetAt = user.costResetAt ?? null;
+    const keyCostResetAtResolved = resolveKeyCostResetAt(key.costResetAt ?? null, userCostResetAt);
+    const keyClipStart = (start: Date): Date =>
+      keyCostResetAtResolved instanceof Date && keyCostResetAtResolved > start
+        ? keyCostResetAtResolved
+        : start;
+    const userClipStart = (start: Date): Date =>
+      userCostResetAt instanceof Date && userCostResetAt > start ? userCostResetAt : start;
+
+    const keyClippedRange5h = {
+      startTime: keyClipStart(range5h.startTime),
+      endTime: range5h.endTime,
+    };
+    const keyClippedRangeWeekly = {
+      startTime: keyClipStart(rangeWeekly.startTime),
       endTime: rangeWeekly.endTime,
     };
-    const clippedRangeMonthly = {
-      startTime: clipStart(rangeMonthly.startTime),
+    const keyClippedRangeMonthly = {
+      startTime: keyClipStart(rangeMonthly.startTime),
       endTime: rangeMonthly.endTime,
     };
     const clippedKeyDaily = {
-      startTime: clipStart(keyDailyTimeRange.startTime),
+      startTime: keyClipStart(keyDailyTimeRange.startTime),
       endTime: keyDailyTimeRange.endTime,
     };
+
+    const userClippedRange5h = {
+      startTime: userClipStart(range5h.startTime),
+      endTime: range5h.endTime,
+    };
+    const userClippedRangeWeekly = {
+      startTime: userClipStart(rangeWeekly.startTime),
+      endTime: rangeWeekly.endTime,
+    };
+    const userClippedRangeMonthly = {
+      startTime: userClipStart(rangeMonthly.startTime),
+      endTime: rangeMonthly.endTime,
+    };
     const clippedUserDaily = {
-      startTime: clipStart(userDailyTimeRange.startTime),
+      startTime: userClipStart(userDailyTimeRange.startTime),
       endTime: userDailyTimeRange.endTime,
     };
 
@@ -276,26 +299,26 @@ export async function getMyQuota(): Promise<ActionResult<MyUsageQuota>> {
       sumKeyQuotaCostsById(
         key.id,
         {
-          range5h: clippedRange5h,
+          range5h: keyClippedRange5h,
           rangeDaily: clippedKeyDaily,
-          rangeWeekly: clippedRangeWeekly,
-          rangeMonthly: clippedRangeMonthly,
+          rangeWeekly: keyClippedRangeWeekly,
+          rangeMonthly: keyClippedRangeMonthly,
         },
         ALL_TIME_MAX_AGE_DAYS,
-        costResetAt
+        keyCostResetAtResolved
       ),
       SessionTracker.getKeySessionCount(key.id),
       // User 配额:直接查 DB
       sumUserQuotaCosts(
         user.id,
         {
-          range5h: clippedRange5h,
+          range5h: userClippedRange5h,
           rangeDaily: clippedUserDaily,
-          rangeWeekly: clippedRangeWeekly,
-          rangeMonthly: clippedRangeMonthly,
+          rangeWeekly: userClippedRangeWeekly,
+          rangeMonthly: userClippedRangeMonthly,
         },
         ALL_TIME_MAX_AGE_DAYS,
-        costResetAt
+        userCostResetAt
       ),
       getUserConcurrentSessions(user.id),
     ]);

+ 57 - 7
src/actions/provider-endpoints.ts

@@ -9,8 +9,12 @@ import {
   resetEndpointCircuit as resetEndpointCircuitState,
 } from "@/lib/endpoint-circuit-breaker";
 import { logger } from "@/lib/logger";
-import { PROVIDER_ENDPOINT_CONFLICT_CODE } from "@/lib/provider-endpoint-error-codes";
+import {
+  ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS_CODE,
+  PROVIDER_ENDPOINT_CONFLICT_CODE,
+} from "@/lib/provider-endpoint-error-codes";
 import { probeProviderEndpointAndRecordByEndpoint } from "@/lib/provider-endpoints/probe";
+import { SessionManager } from "@/lib/session-manager";
 import { ERROR_CODES } from "@/lib/utils/error-messages";
 import { extractZodErrorCode, formatZodError } from "@/lib/utils/zod-i18n";
 import {
@@ -35,8 +39,9 @@ import {
 } from "@/repository";
 import {
   findDashboardProviderEndpointsByVendorAndType,
+  findEnabledProviderIdsByVendorAndType,
+  findEnabledProviderReferencesForVendorTypeUrl,
   findEnabledProviderVendorTypePairs,
-  hasEnabledProviderReferenceForVendorTypeUrl,
 } from "@/repository/provider-endpoints";
 import {
   findProviderEndpointProbeLogsBatch,
@@ -219,6 +224,25 @@ function isForeignKeyViolationError(error: unknown): boolean {
   );
 }
 
+function formatProviderReferenceSummary(
+  references: Array<{ id: number; name: string }>,
+  maxDisplayCount: number = 3
+): string {
+  const uniqueNames = Array.from(
+    new Set(references.map((reference) => reference.name.trim()).filter(Boolean))
+  );
+  if (uniqueNames.length === 0) {
+    return "";
+  }
+
+  if (uniqueNames.length <= maxDisplayCount) {
+    return uniqueNames.join(", ");
+  }
+
+  const displayed = uniqueNames.slice(0, maxDisplayCount).join(", ");
+  return `${displayed} +${uniqueNames.length - maxDisplayCount}`;
+}
+
 export async function getProviderVendors(): Promise<ProviderVendor[]> {
   try {
     const session = await getAdminSession();
@@ -496,6 +520,21 @@ export async function editProviderEndpoint(
       }
     }
 
+    const shouldTerminateStickySessions =
+      parsed.data.url !== undefined ||
+      parsed.data.sortOrder !== undefined ||
+      parsed.data.isEnabled !== undefined;
+    if (shouldTerminateStickySessions) {
+      const affectedProviderIds = await findEnabledProviderIdsByVendorAndType(
+        endpoint.vendorId,
+        endpoint.providerType
+      );
+      await SessionManager.terminateStickySessionsForProviders(
+        affectedProviderIds,
+        "editProviderEndpoint"
+      );
+    }
+
     try {
       await publishProviderCacheInvalidation();
     } catch (error) {
@@ -551,18 +590,20 @@ export async function removeProviderEndpoint(input: unknown): Promise<ActionResu
       };
     }
 
-    // 若该端点仍被启用 provider 引用,则不允许删除:否则会导致运行时 endpoint pool 变空/回填复活,
-    // 产生“删了但还在/仍被探测”的困惑(#781)。
-    const referencedByEnabledProvider = await hasEnabledProviderReferenceForVendorTypeUrl({
+    const references = await findEnabledProviderReferencesForVendorTypeUrl({
       vendorId: endpoint.vendorId,
       providerType: endpoint.providerType,
       url: endpoint.url,
     });
-    if (referencedByEnabledProvider) {
+    if (references.length > 0) {
       return {
         ok: false,
         error: "该端点仍被启用的供应商引用,请先修改或禁用相关供应商的 URL 后再删除",
-        errorCode: ERROR_CODES.CONFLICT,
+        errorCode: ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS_CODE,
+        errorParams: {
+          count: references.length,
+          providers: formatProviderReferenceSummary(references),
+        },
       };
     }
 
@@ -585,6 +626,15 @@ export async function removeProviderEndpoint(input: unknown): Promise<ActionResu
       });
     }
 
+    const affectedProviderIds = await findEnabledProviderIdsByVendorAndType(
+      endpoint.vendorId,
+      endpoint.providerType
+    );
+    await SessionManager.terminateStickySessionsForProviders(
+      affectedProviderIds,
+      "removeProviderEndpoint"
+    );
+
     // Auto cleanup: if the vendor has no active providers/endpoints, delete it as well.
     try {
       await tryDeleteProviderVendorIfEmpty(endpoint.vendorId);

+ 31 - 0
src/actions/providers.ts

@@ -43,6 +43,7 @@ import {
   saveProviderCircuitConfig,
 } from "@/lib/redis/circuit-breaker-config";
 import { RedisKVStore } from "@/lib/redis/redis-kv-store";
+import { SessionManager } from "@/lib/session-manager";
 import { maskKey } from "@/lib/utils/validation";
 import { extractZodErrorCode, formatZodError } from "@/lib/utils/zod-i18n";
 import { validateProviderUrlForConnectivity } from "@/lib/validation/provider-url";
@@ -183,6 +184,28 @@ async function broadcastProviderCacheInvalidation(context: {
   }
 }
 
+const STICKY_SESSION_INVALIDATING_PROVIDER_KEYS = new Set<string>([
+  "url",
+  "websiteUrl",
+  "providerType",
+  "groupTag",
+  "isEnabled",
+  "allowedModels",
+  "allowedClients",
+  "blockedClients",
+  "modelRedirects",
+  "activeTimeStart",
+  "activeTimeEnd",
+]);
+
+function shouldInvalidateStickySessionsOnProviderEdit(
+  changedProviderFields: Record<string, unknown>
+): boolean {
+  return Object.keys(changedProviderFields).some((key) =>
+    STICKY_SESSION_INVALIDATING_PROVIDER_KEYS.has(key)
+  );
+}
+
 // 获取服务商数据
 export async function getProviders(): Promise<ProviderDisplay[]> {
   try {
@@ -776,6 +799,10 @@ export async function editProvider(
       return { ok: false, error: "供应商不存在" };
     }
 
+    if (shouldInvalidateStickySessionsOnProviderEdit(preimageFields)) {
+      await SessionManager.terminateStickySessionsForProviders([providerId], "editProvider");
+    }
+
     // 同步熔断器配置到 Redis(如果配置有变化)
     const hasCircuitConfigChange =
       validated.circuit_breaker_failure_threshold !== undefined ||
@@ -848,6 +875,8 @@ export async function removeProvider(
     const provider = await findProviderById(providerId);
     await deleteProvider(providerId);
 
+    await SessionManager.terminateStickySessionsForProviders([providerId], "removeProvider");
+
     const undoToken = createProviderPatchUndoToken();
     const operationId = createProviderPatchOperationId();
 
@@ -1280,6 +1309,8 @@ const SINGLE_EDIT_PREIMAGE_FIELD_TO_PROVIDER_KEY: Record<string, keyof Provider>
   active_time_end: "activeTimeEnd",
   model_redirects: "modelRedirects",
   allowed_models: "allowedModels",
+  allowed_clients: "allowedClients",
+  blocked_clients: "blockedClients",
   limit_5h_usd: "limit5hUsd",
   limit_daily_usd: "limitDailyUsd",
   daily_reset_mode: "dailyResetMode",

+ 2 - 1
src/actions/usage-logs.ts

@@ -8,6 +8,7 @@ import {
 } from "@/lib/constants/usage-logs.constants";
 import { logger } from "@/lib/logger";
 import { readLiveChainBatch } from "@/lib/redis/live-chain-store";
+import { getRetryCount } from "@/lib/utils/provider-chain-formatter";
 import { isProviderFinalized } from "@/lib/utils/provider-display";
 import {
   findUsageLogSessionIdSuggestions,
@@ -121,7 +122,7 @@ function generateCsv(logs: UsageLogRow[]): string {
   ];
 
   const rows = logs.map((log) => {
-    const retryCount = log.providerChain ? Math.max(0, log.providerChain.length - 1) : 0;
+    const retryCount = log.providerChain ? getRetryCount(log.providerChain) : 0;
     return [
       log.createdAt ? new Date(log.createdAt).toISOString() : "",
       escapeCsvField(log.userName),

+ 3 - 0
src/actions/users.ts

@@ -323,6 +323,7 @@ export async function getUsers(): Promise<UserDisplay[]> {
               limitMonthlyUsd: key.limitMonthlyUsd,
               limitTotalUsd: key.limitTotalUsd,
               limitConcurrentSessions: key.limitConcurrentSessions || 0,
+              costResetAt: key.costResetAt?.toISOString() ?? null,
               providerGroup: key.providerGroup,
             };
           }),
@@ -592,6 +593,7 @@ export async function getUsersBatch(
               limitMonthlyUsd: key.limitMonthlyUsd,
               limitTotalUsd: key.limitTotalUsd,
               limitConcurrentSessions: key.limitConcurrentSessions || 0,
+              costResetAt: key.costResetAt?.toISOString() ?? null,
               providerGroup: key.providerGroup,
             };
           }),
@@ -740,6 +742,7 @@ export async function getUsersBatchCore(
           limitMonthlyUsd: key.limitMonthlyUsd,
           limitTotalUsd: key.limitTotalUsd,
           limitConcurrentSessions: key.limitConcurrentSessions || 0,
+          costResetAt: key.costResetAt?.toISOString() ?? null,
           providerGroup: key.providerGroup,
         })),
       };

+ 1 - 0
src/app/[locale]/dashboard/_components/user/edit-key-dialog.tsx

@@ -29,6 +29,7 @@ export interface EditKeyDialogProps {
     limitMonthlyUsd?: number | null;
     limitTotalUsd?: number | null;
     limitConcurrentSessions?: number;
+    costResetAt?: string | null;
   };
   user?: KeyDialogUserContext;
   isAdmin?: boolean;

+ 110 - 2
src/app/[locale]/dashboard/_components/user/forms/edit-key-form.tsx

@@ -1,14 +1,27 @@
 "use client";
 import { useQueryClient } from "@tanstack/react-query";
+import { Loader2, RotateCcw } from "lucide-react";
 import { useRouter } from "next/navigation";
-import { useTranslations } from "next-intl";
+import { useLocale, useTranslations } from "next-intl";
 import { useCallback, useEffect, useState, useTransition } from "react";
 import { toast } from "sonner";
-import { editKey } from "@/actions/keys";
+import { editKey, resetKeyLimitsOnly } from "@/actions/keys";
 import { getAvailableProviderGroups } from "@/actions/providers";
 import { DatePickerField } from "@/components/form/date-picker-field";
 import { NumberField, TagInputField, TextField } from "@/components/form/form-field";
 import { DialogFormLayout, FormGrid } from "@/components/form/form-layout";
+import {
+  AlertDialog,
+  AlertDialogAction,
+  AlertDialogCancel,
+  AlertDialogContent,
+  AlertDialogDescription,
+  AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogTitle,
+  AlertDialogTrigger,
+} from "@/components/ui/alert-dialog";
+import { Button } from "@/components/ui/button";
 import { Label } from "@/components/ui/label";
 import {
   Select,
@@ -40,6 +53,7 @@ interface EditKeyFormProps {
     limitMonthlyUsd?: number | null;
     limitTotalUsd?: number | null;
     limitConcurrentSessions?: number;
+    costResetAt?: string | null;
   };
   user?: KeyDialogUserContext;
   isAdmin?: boolean;
@@ -49,6 +63,9 @@ interface EditKeyFormProps {
 export function EditKeyForm({ keyData, user, isAdmin = false, onSuccess }: EditKeyFormProps) {
   const [isPending, startTransition] = useTransition();
   const [providerGroupSuggestions, setProviderGroupSuggestions] = useState<string[]>([]);
+  const [isResettingLimits, setIsResettingLimits] = useState(false);
+  const [resetLimitsDialogOpen, setResetLimitsDialogOpen] = useState(false);
+  const locale = useLocale();
   const router = useRouter();
   const queryClient = useQueryClient();
   const t = useTranslations("quota.keys.editKeyForm");
@@ -71,6 +88,27 @@ export function EditKeyForm({ keyData, user, isAdmin = false, onSuccess }: EditK
       });
   }, [isAdmin]);
 
+  const handleResetLimitsOnly = async () => {
+    if (!keyData?.id) return;
+    setIsResettingLimits(true);
+    try {
+      const res = await resetKeyLimitsOnly(keyData.id);
+      if (!res.ok) {
+        toast.error(res.error || t("resetLimits.error"));
+        return;
+      }
+      toast.success(t("resetLimits.success"));
+      setResetLimitsDialogOpen(false);
+      router.refresh();
+      queryClient.invalidateQueries();
+    } catch (error) {
+      console.error("[EditKeyForm] reset limits only failed", error);
+      toast.error(t("resetLimits.error"));
+    } finally {
+      setIsResettingLimits(false);
+    }
+  };
+
   const formatExpiresAt = (expiresAt: string) => {
     if (!expiresAt) return "";
     try {
@@ -386,6 +424,76 @@ export function EditKeyForm({ keyData, user, isAdmin = false, onSuccess }: EditK
           {...form.getFieldProps("limitConcurrentSessions")}
         />
       </FormGrid>
+
+      {/* Reset Quota Section - Admin only, less destructive (amber) */}
+      {isAdmin && (
+        <section className="rounded-lg border border-muted p-4 space-y-3 mt-6">
+          <h3 className="text-sm font-medium">{t("resetLimits.title")}</h3>
+          <div className="rounded-md border border-amber-500/30 bg-amber-500/5 p-3">
+            <div className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between">
+              <div className="space-y-1">
+                <h4 className="text-sm font-medium text-amber-700 dark:text-amber-400">
+                  {t("resetLimits.title")}
+                </h4>
+                <p className="text-xs text-muted-foreground">{t("resetLimits.description")}</p>
+                {keyData?.costResetAt && (
+                  <p className="text-xs text-amber-600/80 dark:text-amber-400/80">
+                    {t("resetLimits.lastResetAt", {
+                      date: new Intl.DateTimeFormat(locale as string, {
+                        dateStyle: "medium",
+                        timeStyle: "short",
+                      }).format(new Date(keyData.costResetAt)),
+                    })}
+                  </p>
+                )}
+              </div>
+
+              <AlertDialog open={resetLimitsDialogOpen} onOpenChange={setResetLimitsDialogOpen}>
+                <AlertDialogTrigger asChild>
+                  <Button
+                    type="button"
+                    variant="outline"
+                    className="border-amber-500/50 text-amber-700 hover:bg-amber-500/10 dark:text-amber-400 dark:hover:bg-amber-500/10"
+                  >
+                    <RotateCcw className="h-4 w-4 mr-2" />
+                    {t("resetLimits.button")}
+                  </Button>
+                </AlertDialogTrigger>
+                <AlertDialogContent>
+                  <AlertDialogHeader>
+                    <AlertDialogTitle>{t("resetLimits.confirmTitle")}</AlertDialogTitle>
+                    <AlertDialogDescription>
+                      {t("resetLimits.confirmDescription")}
+                    </AlertDialogDescription>
+                  </AlertDialogHeader>
+                  <AlertDialogFooter>
+                    <AlertDialogCancel disabled={isResettingLimits}>
+                      {tCommon("cancel")}
+                    </AlertDialogCancel>
+                    <AlertDialogAction
+                      onClick={(e) => {
+                        e.preventDefault();
+                        handleResetLimitsOnly();
+                      }}
+                      disabled={isResettingLimits}
+                      className="bg-amber-600 text-white hover:bg-amber-700"
+                    >
+                      {isResettingLimits ? (
+                        <>
+                          <Loader2 className="h-4 w-4 mr-2 animate-spin" />
+                          {t("resetLimits.loading")}
+                        </>
+                      ) : (
+                        t("resetLimits.confirm")
+                      )}
+                    </AlertDialogAction>
+                  </AlertDialogFooter>
+                </AlertDialogContent>
+              </AlertDialog>
+            </div>
+          </div>
+        </section>
+      )}
     </DialogFormLayout>
   );
 }

+ 3 - 0
src/app/[locale]/dashboard/_components/user/forms/user-form.tsx

@@ -408,6 +408,9 @@ export function UserForm({ user, onSuccess, currentUser }: UserFormProps) {
                 "sdk-py": tUserEdit("subClients.sdk-py"),
                 "cli-sdk": tUserEdit("subClients.cli-sdk"),
                 "gh-action": tUserEdit("subClients.gh-action"),
+                "codex-cli-core": tUserEdit("subClients.codex-cli-core"),
+                desktop: tUserEdit("subClients.desktop"),
+                exec: tUserEdit("subClients.exec"),
               },
               nSelected: tUserEdit("nSelected", { count: "{count}" }),
             }}

+ 3 - 0
src/app/[locale]/dashboard/_components/user/hooks/use-user-translations.ts

@@ -213,6 +213,9 @@ export function useUserTranslations(
         "sdk-py": t("userEditSection.subClients.sdk-py"),
         "cli-sdk": t("userEditSection.subClients.cli-sdk"),
         "gh-action": t("userEditSection.subClients.gh-action"),
+        "codex-cli-core": t("userEditSection.subClients.codex-cli-core"),
+        desktop: t("userEditSection.subClients.desktop"),
+        exec: t("userEditSection.subClients.exec"),
       },
       nSelected: t("userEditSection.nSelected", { count: "{count}" }),
       limitRules: {

+ 4 - 0
src/app/[locale]/dashboard/_components/user/user-key-table-row.tsx

@@ -617,6 +617,10 @@ export function UserKeyTableRow({
                 limitMonthlyUsd: editingKey.limitMonthlyUsd,
                 limitTotalUsd: editingKey.limitTotalUsd,
                 limitConcurrentSessions: editingKey.limitConcurrentSessions,
+                costResetAt:
+                  typeof editingKey.costResetAt === "string"
+                    ? editingKey.costResetAt
+                    : ((editingKey.costResetAt as Date | undefined)?.toISOString() ?? null),
               }}
               user={{
                 id: user.id,

+ 1 - 1
src/app/[locale]/dashboard/leaderboard/user/[userId]/_components/user-insights-view.tsx

@@ -42,7 +42,7 @@ export function UserInsightsView({ userId, userName }: UserInsightsViewProps) {
         </div>
       </div>
 
-      <UserOverviewCards userId={userId} />
+      <UserOverviewCards userId={userId} startDate={startDate} endDate={endDate} />
 
       <UserInsightsFilterBar userId={userId} filters={filters} onFiltersChange={setFilters} />
 

+ 12 - 10
src/app/[locale]/dashboard/leaderboard/user/[userId]/_components/user-overview-cards.tsx

@@ -10,6 +10,8 @@ import { type CurrencyCode, formatCurrency } from "@/lib/utils";
 
 interface UserOverviewCardsProps {
   userId: number;
+  startDate?: string;
+  endDate?: string;
 }
 
 function formatResponseTime(ms: number): string {
@@ -17,13 +19,13 @@ function formatResponseTime(ms: number): string {
   return `${(ms / 1000).toFixed(1)}s`;
 }
 
-export function UserOverviewCards({ userId }: UserOverviewCardsProps) {
+export function UserOverviewCards({ userId, startDate, endDate }: UserOverviewCardsProps) {
   const t = useTranslations("dashboard.leaderboard.userInsights");
 
   const { data, isLoading, isError } = useQuery({
-    queryKey: ["user-insights-overview", userId],
+    queryKey: ["user-insights-overview", userId, startDate, endDate],
     queryFn: async () => {
-      const result = await getUserInsightsOverview(userId);
+      const result = await getUserInsightsOverview(userId, startDate, endDate);
       if (!result.ok) throw new Error(result.error);
       return result.data;
     },
@@ -64,15 +66,15 @@ export function UserOverviewCards({ userId }: UserOverviewCardsProps) {
 
   const metrics = [
     {
-      key: "todayRequests",
-      label: t("todayRequests"),
-      value: overview.todayRequests.toLocaleString(),
+      key: "requestCount",
+      label: t("requests"),
+      value: overview.requestCount.toLocaleString(),
       icon: TrendingUp,
     },
     {
-      key: "todayCost",
-      label: t("todayCost"),
-      value: formatCurrency(overview.todayCost, cc),
+      key: "cost",
+      label: t("cost"),
+      value: formatCurrency(overview.totalCost, cc),
       icon: DollarSign,
     },
     {
@@ -84,7 +86,7 @@ export function UserOverviewCards({ userId }: UserOverviewCardsProps) {
     {
       key: "errorRate",
       label: t("errorRate"),
-      value: `${overview.todayErrorRate.toFixed(1)}%`,
+      value: `${overview.errorRate.toFixed(1)}%`,
       icon: Activity,
     },
   ];

+ 2 - 4
src/app/[locale]/dashboard/logs/_components/provider-chain-popover.test.tsx

@@ -427,10 +427,8 @@ describe("provider-chain-popover hedge/abort reason handling", () => {
     // hedge_triggered is informational, not an actual request
     // so the request count should be 2 (winner + loser), not 3
     const document = parseHtml(html);
-    const countBadge = Array.from(document.querySelectorAll('[data-slot="badge"]')).find((node) =>
-      (node.textContent ?? "").includes("times")
-    );
-    expect(countBadge?.textContent).toContain("2");
+    const requestRows = document.querySelectorAll("#root .relative.flex.gap-2");
+    expect(requestRows).toHaveLength(2);
   });
 
   test("hedge_winner is treated as successful provider", () => {

+ 117 - 109
src/app/[locale]/dashboard/logs/_components/usage-logs-view-virtualized.tsx

@@ -1,7 +1,7 @@
 "use client";
 
 import { useQuery, useQueryClient } from "@tanstack/react-query";
-import { Expand, Filter, ListOrdered, Minimize2, Pause, Play, RefreshCw } from "lucide-react";
+import { ChevronDown, Expand, Filter, Minimize2, RefreshCw } from "lucide-react";
 import { useRouter, useSearchParams } from "next/navigation";
 import { useLocale, useTranslations } from "next-intl";
 import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -10,11 +10,13 @@ import { getKeys } from "@/actions/keys";
 import type { OverviewData } from "@/actions/overview";
 import { getOverviewData } from "@/actions/overview";
 import { getProviders } from "@/actions/providers";
+import { Badge } from "@/components/ui/badge";
 import { Button } from "@/components/ui/button";
-import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/components/ui/collapsible";
 import { Switch } from "@/components/ui/switch";
 import { useFullscreen } from "@/hooks/use-fullscreen";
 import { getHiddenColumns, type LogsTableColumn } from "@/lib/column-visibility";
+import { cn } from "@/lib/utils";
 import type { CurrencyCode } from "@/lib/utils/currency";
 import { formatCurrency } from "@/lib/utils/currency";
 import type { Key } from "@/types/key";
@@ -268,129 +270,135 @@ function UsageLogsViewContent({
 
   const hasStatsFilters = Object.values(statsFilters).some((v) => v !== undefined && v !== false);
 
+  const activeFilterCount = useMemo(() => {
+    let count = 0;
+    if (statsFilters.startTime || statsFilters.endTime) count++;
+    if (statsFilters.userId !== undefined) count++;
+    if (statsFilters.keyId !== undefined) count++;
+    if (statsFilters.providerId !== undefined) count++;
+    if (statsFilters.sessionId) count++;
+    if (statsFilters.statusCode !== undefined || statsFilters.excludeStatusCode200) count++;
+    if (statsFilters.model) count++;
+    if (statsFilters.endpoint) count++;
+    if (statsFilters.minRetryCount !== undefined && statsFilters.minRetryCount > 0) count++;
+    return count;
+  }, [statsFilters]);
+  const [isFilterOpen, setIsFilterOpen] = useState(activeFilterCount > 0);
+
   return (
     <>
-      <div className="space-y-4">
-        {/* Stats Summary - Collapsible */}
+      <div className="space-y-3">
+        {/* Stats Summary */}
         {hasStatsFilters && (
           <UsageLogsStatsPanel filters={statsFilters} currencyCode={resolvedCurrencyCode} />
         )}
 
-        {/* Filter Criteria */}
-        <Card className="border-border/50">
-          <CardHeader className="pb-3">
-            <div className="flex items-center gap-2">
-              <div className="flex items-center justify-center w-8 h-8 rounded-lg bg-muted/50">
-                <Filter className="h-4 w-4 text-muted-foreground" />
-              </div>
-              <div>
-                <CardTitle className="text-base">{t("title.filterCriteria")}</CardTitle>
-                <CardDescription className="text-xs">
-                  {t("title.filterCriteriaDescription")}
-                </CardDescription>
-              </div>
-            </div>
-          </CardHeader>
-          <CardContent className="pt-0">
-            <UsageLogsFilters
-              isAdmin={isAdmin}
-              providers={resolvedProviders}
-              initialKeys={resolvedKeys}
-              filters={filters}
-              onChange={handleFilterChange}
-              onReset={() => router.push("/dashboard/logs")}
-              isProvidersLoading={isProvidersLoading}
-              isKeysLoading={isKeysLoading}
-              serverTimeZone={serverTimeZone}
-            />
-          </CardContent>
-        </Card>
-
-        {/* Usage Records Table */}
-        <Card className="border-border/50">
-          <CardHeader className="pb-3">
-            <div className="flex items-center justify-between">
-              <div className="flex items-center gap-2">
-                <div className="flex items-center justify-center w-8 h-8 rounded-lg bg-muted/50">
-                  <ListOrdered className="h-4 w-4 text-muted-foreground" />
-                </div>
-                <div>
-                  <CardTitle className="text-base">{t("title.usageLogs")}</CardTitle>
-                  <CardDescription className="text-xs">
-                    {t("title.usageLogsDescription")}
-                  </CardDescription>
-                </div>
-              </div>
-              <div className="flex items-center gap-2">
-                <ColumnVisibilityDropdown
-                  userId={userId}
-                  tableId="usage-logs"
-                  onVisibilityChange={setHiddenColumns}
+        {/* Toolbar + Filter */}
+        <Collapsible open={isFilterOpen} onOpenChange={setIsFilterOpen}>
+          <div className="flex items-center justify-between gap-3">
+            {/* Left: Filter trigger */}
+            <CollapsibleTrigger asChild>
+              <button
+                type="button"
+                className="inline-flex items-center gap-1.5 rounded-lg border border-border/60 bg-card px-3 py-1.5 text-sm text-muted-foreground hover:text-foreground hover:border-border cursor-pointer select-none transition-colors"
+              >
+                <Filter className="h-3.5 w-3.5" />
+                <span>{t("title.filterCriteria")}</span>
+                {activeFilterCount > 0 && (
+                  <Badge
+                    variant="secondary"
+                    className="bg-primary/10 text-primary text-[10px] h-4.5 min-w-[18px] px-1 rounded-full"
+                  >
+                    {activeFilterCount}
+                  </Badge>
+                )}
+                <ChevronDown
+                  className={cn(
+                    "h-3.5 w-3.5 text-muted-foreground/50 transition-transform duration-200",
+                    isFilterOpen && "rotate-180"
+                  )}
                 />
+              </button>
+            </CollapsibleTrigger>
 
-                <Button
-                  variant="outline"
-                  size="sm"
-                  onClick={() => void handleEnterFullscreen()}
-                  className="gap-1.5 h-8"
-                  aria-label={t("logs.actions.fullscreen")}
-                >
-                  <Expand className="h-3.5 w-3.5" />
-                  <span className="hidden sm:inline">{t("logs.actions.fullscreen")}</span>
-                </Button>
-
-                <Button
-                  variant="outline"
-                  size="sm"
-                  onClick={handleManualRefresh}
-                  className="gap-1.5 h-8"
-                  disabled={isFullscreenOpen}
-                  aria-label={t("logs.actions.refresh")}
-                >
-                  <RefreshCw
-                    className={`h-3.5 w-3.5 ${isManualRefreshing ? "animate-spin" : ""}`}
-                  />
-                  <span className="hidden sm:inline">{t("logs.actions.refresh")}</span>
-                </Button>
-
-                <Button
-                  variant={isAutoRefresh ? "default" : "outline"}
-                  size="sm"
-                  onClick={() => setIsAutoRefresh(!isAutoRefresh)}
-                  className="gap-1.5 h-8"
+            {/* Right: Table controls */}
+            <div className="flex items-center gap-1">
+              <ColumnVisibilityDropdown
+                userId={userId}
+                tableId="usage-logs"
+                onVisibilityChange={setHiddenColumns}
+              />
+
+              <Button
+                variant="ghost"
+                size="icon"
+                onClick={() => void handleEnterFullscreen()}
+                className="h-8 w-8"
+                aria-label={t("logs.actions.fullscreen")}
+              >
+                <Expand className="h-3.5 w-3.5" />
+              </Button>
+
+              <Button
+                variant="ghost"
+                size="icon"
+                onClick={handleManualRefresh}
+                className="h-8 w-8"
+                disabled={isFullscreenOpen}
+                aria-label={t("logs.actions.refresh")}
+              >
+                <RefreshCw className={cn("h-3.5 w-3.5", isManualRefreshing && "animate-spin")} />
+              </Button>
+
+              <div className="flex items-center gap-1.5 ml-1 pl-2 border-l border-border/40">
+                {isAutoRefresh && (
+                  <span className="relative flex h-1.5 w-1.5">
+                    <span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-emerald-400 opacity-75" />
+                    <span className="relative inline-flex h-1.5 w-1.5 rounded-full bg-emerald-500" />
+                  </span>
+                )}
+                <Switch
+                  checked={isAutoRefresh}
+                  onCheckedChange={setIsAutoRefresh}
                   disabled={isFullscreenOpen}
                   aria-label={
                     isAutoRefresh
                       ? t("logs.actions.stopAutoRefresh")
                       : t("logs.actions.startAutoRefresh")
                   }
-                >
-                  {isAutoRefresh ? (
-                    <>
-                      <Pause className="h-3.5 w-3.5" />
-                      <span className="hidden sm:inline">{t("logs.actions.stopAutoRefresh")}</span>
-                    </>
-                  ) : (
-                    <>
-                      <Play className="h-3.5 w-3.5" />
-                      <span className="hidden sm:inline">{t("logs.actions.startAutoRefresh")}</span>
-                    </>
-                  )}
-                </Button>
+                />
               </div>
             </div>
-          </CardHeader>
-          <CardContent className="px-0 pt-0">
-            <VirtualizedLogsTable
-              filters={filters}
-              currencyCode={resolvedCurrencyCode}
-              billingModelSource={resolvedBillingModelSource}
-              autoRefreshEnabled={!isFullscreenOpen && isAutoRefresh}
-              autoRefreshIntervalMs={logsRefreshIntervalMs ?? 5000}
-              hiddenColumns={hiddenColumns}
-            />
-          </CardContent>
-        </Card>
+          </div>
+
+          <CollapsibleContent forceMount className={cn(!isFilterOpen && "hidden")}>
+            <div className="mt-3 rounded-lg border border-border/60 bg-card p-4">
+              <UsageLogsFilters
+                isAdmin={isAdmin}
+                providers={resolvedProviders}
+                initialKeys={resolvedKeys}
+                filters={filters}
+                onChange={handleFilterChange}
+                onReset={() => router.push("/dashboard/logs")}
+                isProvidersLoading={isProvidersLoading}
+                isKeysLoading={isKeysLoading}
+                serverTimeZone={serverTimeZone}
+              />
+            </div>
+          </CollapsibleContent>
+        </Collapsible>
+
+        {/* Table */}
+        <div className="rounded-lg border border-border/60 overflow-hidden">
+          <VirtualizedLogsTable
+            filters={filters}
+            currencyCode={resolvedCurrencyCode}
+            billingModelSource={resolvedBillingModelSource}
+            autoRefreshEnabled={!isFullscreenOpen && isAutoRefresh}
+            autoRefreshIntervalMs={logsRefreshIntervalMs ?? 5000}
+            hiddenColumns={hiddenColumns}
+          />
+        </div>
       </div>
 
       {isFullscreenOpen ? (

+ 6 - 6
src/app/[locale]/dashboard/logs/_components/virtualized-logs-table.tsx

@@ -208,7 +208,7 @@ export function VirtualizedLogsTable({
     <div className="space-y-4">
       {/* Status bar */}
       {hideStatusBar ? null : (
-        <div className="flex items-center justify-between text-sm text-muted-foreground">
+        <div className="flex items-center justify-between text-xs text-muted-foreground/70 px-3 pt-2">
           <span>{t("logs.table.loadedCount", { count: allLogs.length })}</span>
           {isFetchingNextPage && (
             <span className="flex items-center gap-2">
@@ -221,11 +221,11 @@ export function VirtualizedLogsTable({
       )}
 
       {/* Table with virtual scrolling */}
-      <div className="border-t overflow-x-auto">
+      <div className="overflow-x-auto">
         <div className="min-w-[800px]">
           {/* Fixed header */}
-          <div className="bg-muted/40 border-b sticky top-0 z-10">
-            <div className="flex items-center h-9 text-xs font-medium text-muted-foreground uppercase tracking-wider">
+          <div className="bg-muted/30 border-b sticky top-0 z-10">
+            <div className="flex items-center h-8 text-[11px] font-medium text-muted-foreground/80 tracking-wide">
               <div className="flex-[0.6] min-w-[56px] pl-3 truncate" title={t("logs.columns.time")}>
                 {t("logs.columns.time")}
               </div>
@@ -360,8 +360,8 @@ export function VirtualizedLogsTable({
                       transform: `translateY(${virtualRow.start}px)`,
                     }}
                     className={cn(
-                      "flex items-center text-sm border-b transition-colors hover:bg-muted/30",
-                      isNonBilling ? "bg-muted/40 text-muted-foreground dark:bg-muted/20" : ""
+                      "flex items-center text-sm border-b border-border/40 transition-colors hover:bg-accent/50",
+                      isNonBilling ? "bg-muted/30 text-muted-foreground dark:bg-muted/15" : ""
                     )}
                   >
                     {/* Time */}

+ 11 - 4
src/app/[locale]/dashboard/quotas/users/page.tsx

@@ -6,6 +6,7 @@ import { QuotaToolbar } from "@/components/quota/quota-toolbar";
 import { Alert, AlertDescription } from "@/components/ui/alert";
 import { Link, redirect } from "@/i18n/routing";
 import { getSession } from "@/lib/auth";
+import { resolveKeyCostResetAt } from "@/lib/rate-limit/cost-reset-utils";
 import { sumKeyTotalCostBatchByIds, sumUserTotalCostBatch } from "@/repository/statistics";
 import { getSystemSettings } from "@/repository/system-config";
 import { UsersQuotaSkeleton } from "../_components/users-quota-skeleton";
@@ -27,8 +28,14 @@ async function getUsersWithQuotas(): Promise<UserQuotaWithUsage[]> {
   for (const u of users) {
     if (u.costResetAt instanceof Date) {
       userResetAtMap.set(u.id, u.costResetAt);
-      for (const k of u.keys) {
-        keyResetAtMap.set(k.id, u.costResetAt);
+    }
+    for (const k of u.keys) {
+      const resolved = resolveKeyCostResetAt(
+        k.costResetAt ? new Date(k.costResetAt) : null,
+        u.costResetAt instanceof Date ? u.costResetAt : null
+      );
+      if (resolved) {
+        keyResetAtMap.set(k.id, resolved);
       }
     }
   }
@@ -38,12 +45,12 @@ async function getUsersWithQuotas(): Promise<UserQuotaWithUsage[]> {
     Promise.all(users.map((u) => getUserLimitUsage(u.id))),
     sumUserTotalCostBatch(
       allUserIds,
-      undefined,
+      Infinity,
       userResetAtMap.size > 0 ? userResetAtMap : undefined
     ),
     sumKeyTotalCostBatchByIds(
       allKeyIds,
-      undefined,
+      Infinity,
       keyResetAtMap.size > 0 ? keyResetAtMap : undefined
     ),
   ]);

+ 1 - 1
src/app/[locale]/settings/providers/_components/batch-edit/build-patch-draft.ts

@@ -33,7 +33,7 @@ export function buildPatchDraftFromFormState(
     draft.cost_multiplier = { set: state.routing.costMultiplier };
   }
   if (dirtyFields.has("routing.groupTag")) {
-    const joined = state.routing.groupTag.join(", ");
+    const joined = state.routing.groupTag.join(",");
     if (joined === "") {
       draft.group_tag = { clear: true };
     } else {

+ 4 - 4
src/app/[locale]/settings/providers/_components/forms/provider-form.legacy.tsx

@@ -55,7 +55,7 @@ import { ApiTestButton } from "./api-test-button";
 import { ProxyTestButton } from "./proxy-test-button";
 import { UrlPreview } from "./url-preview";
 
-const GROUP_TAG_MAX_TOTAL_LENGTH = 50;
+const GROUP_TAG_MAX_TOTAL_LENGTH = 255;
 
 type Mode = "create" | "edit";
 
@@ -430,7 +430,7 @@ export function ProviderForm({
       return;
     }
 
-    // group_tag 在 DB/schema 中限制为 varchar(50),并且后端按整串校验 max(50)
+    // group_tag 在 DB/schema 中限制为 varchar(255),并且后端按整串校验 max(255)
     // 这里限制逗号拼接后的总长度,避免"UI 看似可选多标签,但保存必失败"的体验
     const serializedGroupTag = groupTag.join(",");
     if (serializedGroupTag.length > GROUP_TAG_MAX_TOTAL_LENGTH) {
@@ -890,13 +890,13 @@ export function ProviderForm({
                     onChange={handleGroupTagChange}
                     placeholder={t("sections.routing.scheduleParams.group.placeholder")}
                     disabled={isPending}
-                    maxTagLength={GROUP_TAG_MAX_TOTAL_LENGTH}
+                    maxTagLength={50}
                     suggestions={groupSuggestions}
                     onInvalidTag={(_tag, reason) => {
                       const messages: Record<string, string> = {
                         empty: tUI("emptyTag"),
                         duplicate: tUI("duplicateTag"),
-                        too_long: tUI("tooLong", { max: GROUP_TAG_MAX_TOTAL_LENGTH }),
+                        too_long: tUI("tooLong", { max: 50 }),
                         invalid_format: tUI("invalidFormat"),
                         max_tags: tUI("maxTags"),
                       };

+ 34 - 92
src/app/[locale]/settings/providers/_components/forms/provider-form/index.tsx

@@ -4,7 +4,7 @@ import { useQuery, useQueryClient } from "@tanstack/react-query";
 import { useTranslations } from "next-intl";
 import { useCallback, useEffect, useMemo, useRef, useState, useTransition } from "react";
 import { toast } from "sonner";
-import { getProviderEndpoints, getProviderVendors } from "@/actions/provider-endpoints";
+import { getProviderEndpoints } from "@/actions/provider-endpoints";
 import {
   addProvider,
   editProvider,
@@ -27,12 +27,8 @@ import {
 import { Button } from "@/components/ui/button";
 import { PROVIDER_BATCH_PATCH_ERROR_CODES } from "@/lib/provider-batch-patch-error-codes";
 import { isValidUrl } from "@/lib/utils/validation";
-import type {
-  ProviderDisplay,
-  ProviderEndpoint,
-  ProviderType,
-  ProviderVendor,
-} from "@/types/provider";
+import type { ProviderDisplay, ProviderEndpoint, ProviderType } from "@/types/provider";
+import { invalidateProviderQueries } from "../../invalidate-provider-queries";
 import { FormTabNav, NAV_ORDER, PARENT_MAP, TAB_ORDER } from "./components/form-tab-nav";
 import { ProviderFormProvider, useProviderForm } from "./provider-form-context";
 import type { NavTargetId, SubTabId, TabId } from "./provider-form-types";
@@ -43,29 +39,6 @@ import { OptionsSection } from "./sections/options-section";
 import { RoutingSection } from "./sections/routing-section";
 import { TestingSection } from "./sections/testing-section";
 
-function normalizeWebsiteDomainFromUrl(rawUrl: string): string | null {
-  const trimmed = rawUrl.trim();
-  if (!trimmed) return null;
-
-  const candidates = [trimmed];
-  if (!/^[a-zA-Z][a-zA-Z\d+.-]*:\/\//.test(trimmed)) {
-    candidates.push(`https://${trimmed}`);
-  }
-
-  for (const candidate of candidates) {
-    try {
-      const parsed = new URL(candidate);
-      const hostname = parsed.hostname?.toLowerCase();
-      if (!hostname) continue;
-      return hostname.startsWith("www.") ? hostname.slice(4) : hostname;
-    } catch {
-      // ignore
-    }
-  }
-
-  return null;
-}
-
 export interface ProviderFormProps {
   mode: "create" | "edit";
   onSuccess?: () => void;
@@ -101,29 +74,12 @@ function ProviderFormContent({
   const isEdit = mode === "edit";
 
   const queryClient = useQueryClient();
-  const { data: vendors = [] } = useQuery<ProviderVendor[]>({
-    queryKey: ["provider-vendors"],
-    queryFn: getProviderVendors,
-    staleTime: 60_000,
-    refetchOnWindowFocus: false,
-  });
 
-  const websiteDomain = useMemo(
-    () => normalizeWebsiteDomainFromUrl(state.basic.websiteUrl),
-    [state.basic.websiteUrl]
-  );
+  const doInvalidate = useCallback(() => invalidateProviderQueries(queryClient), [queryClient]);
 
   const resolvedEndpointPoolVendorId = useMemo(() => {
-    // Edit mode: vendor id already attached to provider record
-    if (isEdit) {
-      return provider?.providerVendorId ?? null;
-    }
-
-    // Create/clone: resolve vendor from websiteUrl hostname
-    if (!websiteDomain) return null;
-    const vendor = vendors.find((v) => v.websiteDomain === websiteDomain);
-    return vendor?.id ?? null;
-  }, [isEdit, provider?.providerVendorId, vendors, websiteDomain]);
+    return isEdit ? (provider?.providerVendorId ?? null) : null;
+  }, [isEdit, provider?.providerVendorId]);
 
   const endpointPoolQueryKey = useMemo(() => {
     if (resolvedEndpointPoolVendorId == null) return null;
@@ -162,22 +118,6 @@ function ProviderFormContent({
     !hideUrl && resolvedEndpointPoolVendorId != null && endpointPoolHasEnabledEndpoints;
 
   // Keep state.basic.url usable across other sections when legacy URL input is hidden.
-  useEffect(() => {
-    if (isEdit) return;
-    if (hideUrl) return;
-    if (!endpointPoolHideLegacyUrlInput) return;
-    if (!endpointPoolPreferredUrl) return;
-    if (state.basic.url.trim()) return;
-    dispatch({ type: "SET_URL", payload: endpointPoolPreferredUrl });
-  }, [
-    isEdit,
-    hideUrl,
-    endpointPoolHideLegacyUrlInput,
-    endpointPoolPreferredUrl,
-    state.basic.url,
-    dispatch,
-  ]);
-
   // Update URL when resolved URL changes
   useEffect(() => {
     if (resolvedUrl && !state.basic.url && !isEdit) {
@@ -198,6 +138,15 @@ function ProviderFormContent({
   const scrollLockTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
   const scrollEndListenerRef = useRef<(() => void) | null>(null);
 
+  // Refs for scroll handler to avoid re-creating the callback on every tab change
+  const activeTabRef = useRef(state.ui.activeTab);
+  const activeSubTabRef = useRef(state.ui.activeSubTab);
+
+  useEffect(() => {
+    activeTabRef.current = state.ui.activeTab;
+    activeSubTabRef.current = state.ui.activeSubTab;
+  }, [state.ui.activeTab, state.ui.activeSubTab]);
+
   useEffect(() => {
     return () => {
       if (rafRef.current !== null) cancelAnimationFrame(rafRef.current);
@@ -264,11 +213,11 @@ function ProviderFormContent({
           ? PARENT_MAP[activeSection as SubTabId]
           : (activeSection as TabId);
       const subTab = activeSection in PARENT_MAP ? (activeSection as SubTabId) : null;
-      if (state.ui.activeTab !== parentTab || state.ui.activeSubTab !== subTab) {
+      if (activeTabRef.current !== parentTab || activeSubTabRef.current !== subTab) {
         dispatch({ type: "SET_ACTIVE_NAV", payload: { tab: parentTab, subTab } });
       }
     });
-  }, [dispatch, state.ui.activeSubTab, state.ui.activeTab]);
+  }, [dispatch]);
 
   const handleTabChange = (tab: TabId) => {
     dispatch({ type: "SET_ACTIVE_TAB", payload: tab });
@@ -422,10 +371,7 @@ function ProviderFormContent({
                   const undoResult = await undoProviderPatch({ undoToken, operationId });
                   if (undoResult.ok) {
                     toast.success(tBatchEdit("undo.singleEditUndone"));
-                    await queryClient.invalidateQueries({ queryKey: ["providers"] });
-                    await queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-                    await queryClient.invalidateQueries({ queryKey: ["providers-statistics"] });
-                    await queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+                    await doInvalidate();
                   } else if (
                     undoResult.errorCode === PROVIDER_BATCH_PATCH_ERROR_CODES.UNDO_EXPIRED
                   ) {
@@ -440,10 +386,7 @@ function ProviderFormContent({
             },
           });
 
-          void queryClient.invalidateQueries({ queryKey: ["providers"] });
-          void queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-          void queryClient.invalidateQueries({ queryKey: ["providers-statistics"] });
-          void queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+          void doInvalidate();
         } else {
           // For create: key is required
           const createFormData = { ...baseFormData, key: trimmedKey };
@@ -453,10 +396,7 @@ function ProviderFormContent({
             return;
           }
 
-          void queryClient.invalidateQueries({ queryKey: ["providers"] });
-          void queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-          void queryClient.invalidateQueries({ queryKey: ["providers-statistics"] });
-          void queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+          void doInvalidate();
 
           toast.success(t("success.created"));
           dispatch({ type: "RESET_FORM" });
@@ -514,10 +454,7 @@ function ProviderFormContent({
                 const undoResult = await undoProviderDelete({ undoToken, operationId });
                 if (undoResult.ok) {
                   toast.success(tBatchEdit("undo.singleDeleteUndone"));
-                  await queryClient.invalidateQueries({ queryKey: ["providers"] });
-                  await queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-                  await queryClient.invalidateQueries({ queryKey: ["providers-statistics"] });
-                  await queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+                  await doInvalidate();
                 } else if (undoResult.errorCode === PROVIDER_BATCH_PATCH_ERROR_CODES.UNDO_EXPIRED) {
                   toast.error(tBatchEdit("undo.expired"));
                 } else {
@@ -530,10 +467,7 @@ function ProviderFormContent({
           },
         });
 
-        void queryClient.invalidateQueries({ queryKey: ["providers"] });
-        void queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-        void queryClient.invalidateQueries({ queryKey: ["providers-statistics"] });
-        void queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+        void doInvalidate();
         onSuccess?.();
       } catch (e) {
         console.error("Delete error:", e);
@@ -542,8 +476,8 @@ function ProviderFormContent({
     });
   };
 
-  // Tab status indicators
-  const getTabStatus = (): Partial<Record<TabId, "default" | "warning" | "configured">> => {
+  // Tab status indicators (memoized to avoid object recreation per render)
+  const tabStatus = useMemo((): Partial<Record<TabId, "default" | "warning" | "configured">> => {
     const status: Partial<Record<TabId, "default" | "warning" | "configured">> = {};
 
     // Basic - warning if required fields missing
@@ -607,7 +541,15 @@ function ProviderFormContent({
     }
 
     return status;
-  };
+  }, [
+    state.basic,
+    state.routing,
+    state.rateLimit,
+    state.network,
+    state.mcp,
+    hideUrl,
+    endpointPoolHideLegacyUrlInput,
+  ]);
 
   return (
     <form
@@ -624,7 +566,7 @@ function ProviderFormContent({
             onTabChange={handleTabChange}
             onSubTabChange={handleSubTabChange}
             disabled={isPending}
-            tabStatus={getTabStatus()}
+            tabStatus={tabStatus}
           />
         </div>
 

+ 8 - 3
src/app/[locale]/settings/providers/_components/forms/provider-form/sections/routing-section.tsx

@@ -25,7 +25,7 @@ import { ModelRedirectEditor } from "../../../model-redirect-editor";
 import { FieldGroup, SectionCard, SmartInputWrapper, ToggleRow } from "../components/section-card";
 import { useProviderForm } from "../provider-form-context";
 
-const GROUP_TAG_MAX_TOTAL_LENGTH = 50;
+const GROUP_TAG_MAX_TOTAL_LENGTH = 255;
 
 interface RoutingSectionProps {
   subSectionRefs?: {
@@ -158,13 +158,13 @@ export function RoutingSection({ subSectionRefs }: RoutingSectionProps) {
                 onChange={handleGroupTagChange}
                 placeholder={t("sections.routing.scheduleParams.group.placeholder")}
                 disabled={state.ui.isPending}
-                maxTagLength={GROUP_TAG_MAX_TOTAL_LENGTH}
+                maxTagLength={50}
                 suggestions={groupSuggestions}
                 onInvalidTag={(_tag, reason) => {
                   const messages: Record<string, string> = {
                     empty: tUI("emptyTag"),
                     duplicate: tUI("duplicateTag"),
-                    too_long: tUI("tooLong", { max: GROUP_TAG_MAX_TOTAL_LENGTH }),
+                    too_long: tUI("tooLong", { max: 50 }),
                     invalid_format: tUI("invalidFormat"),
                     max_tags: tUI("maxTags"),
                   };
@@ -306,6 +306,11 @@ export function RoutingSection({ subSectionRefs }: RoutingSectionProps) {
                     "sdk-py": t("sections.routing.clientRestrictions.subClients.sdk-py"),
                     "cli-sdk": t("sections.routing.clientRestrictions.subClients.cli-sdk"),
                     "gh-action": t("sections.routing.clientRestrictions.subClients.gh-action"),
+                    "codex-cli-core": t(
+                      "sections.routing.clientRestrictions.subClients.codex-cli-core"
+                    ),
+                    desktop: t("sections.routing.clientRestrictions.subClients.desktop"),
+                    exec: t("sections.routing.clientRestrictions.subClients.exec"),
                   },
                   nSelected: t("sections.routing.clientRestrictions.nSelected", {
                     count: "{count}",

+ 16 - 0
src/app/[locale]/settings/providers/_components/invalidate-provider-queries.ts

@@ -0,0 +1,16 @@
+import type { QueryClient } from "@tanstack/react-query";
+
+/** Invalidate all provider-related queries in one batch */
+export function invalidateProviderQueries(queryClient: QueryClient): Promise<void> {
+  return queryClient.invalidateQueries({
+    predicate: (query) => {
+      const key = query.queryKey[0];
+      return (
+        key === "providers" ||
+        key === "providers-health" ||
+        key === "providers-statistics" ||
+        key === "provider-vendors"
+      );
+    },
+  });
+}

+ 21 - 3
src/app/[locale]/settings/providers/_components/provider-endpoints-table.tsx

@@ -234,6 +234,7 @@ function EndpointRow({
   circuitState: EndpointCircuitState | null;
 }) {
   const t = useTranslations("settings.providers");
+  const tErrors = useTranslations("errors");
   const tStatus = useTranslations("settings.providers.endpointStatus");
   const tCommon = useTranslations("settings.common");
   const queryClient = useQueryClient();
@@ -274,7 +275,9 @@ function EndpointRow({
   const deleteMutation = useMutation({
     mutationFn: async () => {
       const res = await removeProviderEndpoint({ endpointId: endpoint.id });
-      if (!res.ok) throw new Error(res.error);
+      if (!res.ok) {
+        throw Object.assign(new Error(res.error), { actionResult: res });
+      }
       return res.data;
     },
     onSuccess: () => {
@@ -282,8 +285,21 @@ function EndpointRow({
       queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
       toast.success(t("endpointDeleteSuccess"));
     },
-    onError: () => {
-      toast.error(t("endpointDeleteFailed"));
+    onError: (
+      error: Error & {
+        actionResult?: {
+          error?: string;
+          errorCode?: string;
+          errorParams?: Record<string, string | number>;
+        };
+      }
+    ) => {
+      const actionResult = error.actionResult;
+      toast.error(
+        actionResult?.errorCode
+          ? getErrorMessage(tErrors, actionResult.errorCode, actionResult.errorParams)
+          : (actionResult?.error ?? t("endpointDeleteFailed"))
+      );
     },
   });
 
@@ -511,6 +527,7 @@ export function AddEndpointButton({
 
   const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
     e.preventDefault();
+    e.stopPropagation();
     setIsSubmitting(true);
     const formData = new FormData(e.currentTarget);
     const endpointUrl = formData.get("url") as string;
@@ -680,6 +697,7 @@ function EditEndpointDialog({ endpoint }: { endpoint: ProviderEndpoint }) {
 
   const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
     e.preventDefault();
+    e.stopPropagation();
     setIsSubmitting(true);
     const formData = new FormData(e.currentTarget);
     const url = formData.get("url") as string;

+ 10 - 5
src/app/[locale]/settings/providers/_components/provider-list.tsx

@@ -11,6 +11,11 @@ import type { User } from "@/types/user";
 import type { EndpointCircuitInfoMap } from "./provider-manager";
 import { ProviderRichListItem } from "./provider-rich-list-item";
 
+// Stable default references to avoid re-creating on every render (defeats React.memo)
+const EMPTY_STRING_ARRAY: string[] = [];
+const EMPTY_OBJECT: Record<string, never> = {};
+const EMPTY_SET = new Set<number>();
+
 interface ProviderListProps {
   providers: ProviderDisplay[];
   currentUser?: User;
@@ -43,17 +48,17 @@ export function ProviderList({
   providers,
   currentUser,
   healthStatus,
-  endpointCircuitInfo = {},
-  statistics = {},
+  endpointCircuitInfo = EMPTY_OBJECT,
+  statistics = EMPTY_OBJECT,
   statisticsLoading = false,
   currencyCode = "USD",
   enableMultiProviderTypes,
   activeGroupFilter = null,
   isMultiSelectMode = false,
-  selectedProviderIds = new Set(),
+  selectedProviderIds = EMPTY_SET,
   onSelectProvider,
-  allGroups = [],
-  userGroups = [],
+  allGroups = EMPTY_STRING_ARRAY,
+  userGroups = EMPTY_STRING_ARRAY,
   isAdmin = false,
 }: ProviderListProps) {
   const t = useTranslations("settings.providers");

+ 168 - 51
src/app/[locale]/settings/providers/_components/provider-rich-list-item.tsx

@@ -16,7 +16,7 @@ import {
   XCircle,
 } from "lucide-react";
 import { useTranslations } from "next-intl";
-import { useEffect, useState, useTransition } from "react";
+import { memo, useCallback, useEffect, useState, useTransition } from "react";
 import { toast } from "sonner";
 import {
   editProvider,
@@ -64,6 +64,7 @@ import {
 } from "@/lib/constants/provider.constants";
 import { PROVIDER_BATCH_PATCH_ERROR_CODES } from "@/lib/provider-batch-patch-error-codes";
 import { getProviderTypeConfig, getProviderTypeTranslationKey } from "@/lib/provider-type-utils";
+import { cn } from "@/lib/utils";
 import { copyToClipboard, isClipboardSupported } from "@/lib/utils/clipboard";
 import { getContrastTextColor, getGroupColor } from "@/lib/utils/color";
 import type { CurrencyCode } from "@/lib/utils/currency";
@@ -73,6 +74,7 @@ import type { User } from "@/types/user";
 import { ProviderForm } from "./forms/provider-form";
 import { GroupEditCombobox } from "./group-edit-combobox";
 import { InlineEditPopover } from "./inline-edit-popover";
+import { invalidateProviderQueries } from "./invalidate-provider-queries";
 import { PriorityEditPopover } from "./priority-edit-popover";
 import { ProviderEndpointHover } from "./provider-endpoint-hover";
 
@@ -110,7 +112,7 @@ interface ProviderRichListItemProps {
   isAdmin?: boolean;
 }
 
-export function ProviderRichListItem({
+function ProviderRichListItemInner({
   provider,
   vendor,
   currentUser,
@@ -133,9 +135,47 @@ export function ProviderRichListItem({
 }: ProviderRichListItemProps) {
   const queryClient = useQueryClient();
 
+  const doInvalidate = useCallback(() => invalidateProviderQueries(queryClient), [queryClient]);
+
   const [openEdit, setOpenEdit] = useState(false);
   const [openClone, setOpenClone] = useState(false);
   const [showKeyDialog, setShowKeyDialog] = useState(false);
+
+  // Defer heavy ProviderForm mount so dialog animation doesn't compete with React work
+  const [editFormReady, setEditFormReady] = useState(false);
+  const [cloneFormReady, setCloneFormReady] = useState(false);
+
+  useEffect(() => {
+    if (openEdit) {
+      let cancelled = false;
+      const id = requestAnimationFrame(() => {
+        requestAnimationFrame(() => {
+          if (!cancelled) setEditFormReady(true);
+        });
+      });
+      return () => {
+        cancelled = true;
+        cancelAnimationFrame(id);
+      };
+    }
+    setEditFormReady(false);
+  }, [openEdit]);
+
+  useEffect(() => {
+    if (openClone) {
+      let cancelled = false;
+      const id = requestAnimationFrame(() => {
+        requestAnimationFrame(() => {
+          if (!cancelled) setCloneFormReady(true);
+        });
+      });
+      return () => {
+        cancelled = true;
+        cancelAnimationFrame(id);
+      };
+    }
+    setCloneFormReady(false);
+  }, [openClone]);
   const [mobileDeleteDialogOpen, setMobileDeleteDialogOpen] = useState(false);
   const [unmaskedKey, setUnmaskedKey] = useState<string | null>(null);
   const [copied, setCopied] = useState(false);
@@ -231,9 +271,7 @@ export function ProviderRichListItem({
                     const undoResult = await undoProviderDelete({ undoToken, operationId });
                     if (undoResult.ok) {
                       toast.success(tBatchEdit("undo.singleDeleteUndone"));
-                      await queryClient.invalidateQueries({ queryKey: ["providers"] });
-                      await queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-                      await queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+                      await doInvalidate();
                     } else if (
                       undoResult.errorCode === PROVIDER_BATCH_PATCH_ERROR_CODES.UNDO_EXPIRED
                     ) {
@@ -248,9 +286,7 @@ export function ProviderRichListItem({
               },
             });
 
-            queryClient.invalidateQueries({ queryKey: ["providers"] });
-            queryClient.invalidateQueries({ queryKey: ["providers-health"] });
-            queryClient.invalidateQueries({ queryKey: ["provider-vendors"] });
+            doInvalidate();
           } else {
             toast.error(tList("deleteFailed"), {
               description: res.error || tList("unknownError"),
@@ -319,8 +355,7 @@ export function ProviderRichListItem({
           toast.success(tList("resetCircuitSuccess"), {
             description: tList("resetCircuitSuccessDesc", { name: provider.name }),
           });
-          queryClient.invalidateQueries({ queryKey: ["providers"] });
-          queryClient.invalidateQueries({ queryKey: ["providers-health"] });
+          doInvalidate();
         } else {
           toast.error(tList("resetCircuitFailed"), {
             description: res.error || tList("unknownError"),
@@ -344,8 +379,7 @@ export function ProviderRichListItem({
           toast.success(tList("resetUsageSuccess"), {
             description: tList("resetUsageSuccessDesc", { name: provider.name }),
           });
-          queryClient.invalidateQueries({ queryKey: ["providers"] });
-          queryClient.invalidateQueries({ queryKey: ["providers-health"] });
+          doInvalidate();
         } else {
           toast.error(tList("resetUsageFailed"), {
             description: res.error || tList("unknownError"),
@@ -372,8 +406,7 @@ export function ProviderRichListItem({
           toast.success(tList("toggleSuccess", { status }), {
             description: tList("toggleSuccessDesc", { name: provider.name }),
           });
-          queryClient.invalidateQueries({ queryKey: ["providers"] });
-          queryClient.invalidateQueries({ queryKey: ["providers-health"] });
+          doInvalidate();
         } else {
           toast.error(tList("toggleFailed"), {
             description: res.error || tList("unknownError"),
@@ -396,7 +429,7 @@ export function ProviderRichListItem({
         >[1]);
         if (res.ok) {
           toast.success(tInline("saveSuccess"));
-          queryClient.invalidateQueries({ queryKey: ["providers"] });
+          doInvalidate();
           return true;
         }
         toast.error(tInline("saveFailed"), { description: res.error || tList("unknownError") });
@@ -462,9 +495,27 @@ export function ProviderRichListItem({
     }
   };
 
+  const hasKeyCircuitOpen = healthStatus?.circuitState === "open";
+  const hasEndpointCircuitOpen = endpointCircuitInfo?.some((ep) => ep.circuitState === "open");
+  const accentColor = hasKeyCircuitOpen
+    ? "border-l-red-500"
+    : hasEndpointCircuitOpen
+      ? "border-l-amber-500"
+      : provider.isEnabled
+        ? "border-l-emerald-500"
+        : "border-l-gray-300 dark:border-l-gray-600";
+
   return (
     <>
-      <div className="rounded-lg border bg-card p-4 md:rounded-none md:border-0 md:border-b md:bg-transparent md:p-0 md:py-3 md:px-4 flex flex-col gap-3 md:flex-row md:items-center md:gap-4 hover:bg-muted/50 transition-colors">
+      <div
+        className={cn(
+          "rounded-lg border border-l-[3px] bg-card shadow-sm p-4",
+          "md:shadow-none md:rounded-none md:border-0 md:border-b md:border-l-[3px] md:bg-transparent md:p-0 md:py-3 md:px-4",
+          "flex flex-col gap-3 md:flex-row md:items-center md:gap-4",
+          "hover:bg-muted/50 transition-colors",
+          accentColor
+        )}
+      >
         {/* Checkbox: shared between mobile and desktop */}
         {isMultiSelectMode && (
           <Checkbox
@@ -830,10 +881,12 @@ export function ProviderRichListItem({
         </div>
 
         {/* Desktop: metrics */}
-        <div className="hidden md:grid grid-cols-3 gap-4 text-center flex-shrink-0">
-          <div>
-            <div className="text-xs text-muted-foreground">{tList("priority")}</div>
-            <div className="font-medium">
+        <div className="hidden md:grid grid-cols-3 gap-2 text-center flex-shrink-0">
+          <div className="rounded-md bg-muted/30 px-2.5 py-1.5">
+            <div className="text-[10px] uppercase tracking-wider text-muted-foreground/70">
+              {tList("priority")}
+            </div>
+            <div className="font-semibold text-sm">
               {canEdit ? (
                 <PriorityEditPopover
                   globalPriority={provider.priority}
@@ -848,9 +901,11 @@ export function ProviderRichListItem({
               )}
             </div>
           </div>
-          <div>
-            <div className="text-xs text-muted-foreground">{tList("weight")}</div>
-            <div className="font-medium">
+          <div className="rounded-md bg-muted/30 px-2.5 py-1.5">
+            <div className="text-[10px] uppercase tracking-wider text-muted-foreground/70">
+              {tList("weight")}
+            </div>
+            <div className="font-semibold text-sm">
               {canEdit ? (
                 <InlineEditPopover
                   value={provider.weight}
@@ -864,9 +919,11 @@ export function ProviderRichListItem({
               )}
             </div>
           </div>
-          <div>
-            <div className="text-xs text-muted-foreground">{tList("costMultiplier")}</div>
-            <div className="font-medium">
+          <div className="rounded-md bg-muted/30 px-2.5 py-1.5">
+            <div className="text-[10px] uppercase tracking-wider text-muted-foreground/70">
+              {tList("costMultiplier")}
+            </div>
+            <div className="font-semibold text-sm">
               {canEdit ? (
                 <InlineEditPopover
                   value={provider.costMultiplier}
@@ -884,8 +941,10 @@ export function ProviderRichListItem({
         </div>
 
         {/* Desktop: today usage */}
-        <div className="hidden lg:block text-center flex-shrink-0 min-w-[100px]">
-          <div className="text-xs text-muted-foreground">{tList("todayUsageLabel")}</div>
+        <div className="hidden lg:block text-center flex-shrink-0 min-w-[100px] rounded-md bg-muted/30 px-2.5 py-1.5">
+          <div className="text-[10px] uppercase tracking-wider text-muted-foreground/70">
+            {tList("todayUsageLabel")}
+          </div>
           {statisticsLoading ? (
             <>
               <Skeleton className="h-5 w-16 mx-auto my-0.5" />
@@ -893,7 +952,7 @@ export function ProviderRichListItem({
             </>
           ) : (
             <>
-              <div className="font-medium">
+              <div className="font-semibold text-sm">
                 {tList("todayUsageCount", {
                   count: statistics?.todayCalls ?? provider.todayCallCount ?? 0,
                 })}
@@ -1009,41 +1068,49 @@ export function ProviderRichListItem({
         </div>
       </div>
 
-      {/* 编辑 Dialog */}
+      {/* Edit Dialog */}
       <Dialog open={openEdit} onOpenChange={setOpenEdit}>
         <DialogContent className="max-w-6xl max-h-[var(--cch-viewport-height-90)] flex flex-col overflow-hidden p-0 gap-0">
           <VisuallyHidden>
             <DialogTitle>{t("editProvider")}</DialogTitle>
           </VisuallyHidden>
-          <FormErrorBoundary>
-            <ProviderForm
-              mode="edit"
-              provider={provider}
-              onSuccess={() => {
-                setOpenEdit(false);
-              }}
-              enableMultiProviderTypes={enableMultiProviderTypes}
-            />
-          </FormErrorBoundary>
+          {editFormReady ? (
+            <FormErrorBoundary>
+              <ProviderForm
+                mode="edit"
+                provider={provider}
+                onSuccess={() => {
+                  setOpenEdit(false);
+                }}
+                enableMultiProviderTypes={enableMultiProviderTypes}
+              />
+            </FormErrorBoundary>
+          ) : (
+            <DialogFormSkeleton />
+          )}
         </DialogContent>
       </Dialog>
 
-      {/* 克隆 Dialog */}
+      {/* Clone Dialog */}
       <Dialog open={openClone} onOpenChange={setOpenClone}>
         <DialogContent className="max-w-6xl max-h-[var(--cch-viewport-height-90)] flex flex-col overflow-hidden p-0 gap-0">
           <VisuallyHidden>
             <DialogTitle>{t("clone")}</DialogTitle>
           </VisuallyHidden>
-          <FormErrorBoundary>
-            <ProviderForm
-              mode="create"
-              cloneProvider={provider}
-              onSuccess={() => {
-                setOpenClone(false);
-              }}
-              enableMultiProviderTypes={enableMultiProviderTypes}
-            />
-          </FormErrorBoundary>
+          {cloneFormReady ? (
+            <FormErrorBoundary>
+              <ProviderForm
+                mode="create"
+                cloneProvider={provider}
+                onSuccess={() => {
+                  setOpenClone(false);
+                }}
+                enableMultiProviderTypes={enableMultiProviderTypes}
+              />
+            </FormErrorBoundary>
+          ) : (
+            <DialogFormSkeleton />
+          )}
         </DialogContent>
       </Dialog>
 
@@ -1078,3 +1145,53 @@ export function ProviderRichListItem({
     </>
   );
 }
+
+export const ProviderRichListItem = memo(ProviderRichListItemInner, (prev, next) => {
+  // Skip function props — they are safe to ignore because:
+  // - onSelectProvider (parent) uses useCallback + functional setState (prev => ...)
+  // - onSelectChange (ProviderList) binds stable provider.id to the above
+  // - onEdit/onClone/onDelete are undefined in ProviderList (use internal handlers)
+  // If any of these assumptions change, add the relevant prop to this comparison.
+  return (
+    prev.provider === next.provider &&
+    prev.vendor === next.vendor &&
+    prev.currentUser === next.currentUser &&
+    prev.healthStatus === next.healthStatus &&
+    prev.endpointCircuitInfo === next.endpointCircuitInfo &&
+    prev.statistics === next.statistics &&
+    prev.statisticsLoading === next.statisticsLoading &&
+    prev.currencyCode === next.currencyCode &&
+    prev.enableMultiProviderTypes === next.enableMultiProviderTypes &&
+    prev.isMultiSelectMode === next.isMultiSelectMode &&
+    prev.isSelected === next.isSelected &&
+    prev.activeGroupFilter === next.activeGroupFilter &&
+    prev.allGroups === next.allGroups &&
+    prev.userGroups === next.userGroups &&
+    prev.isAdmin === next.isAdmin
+  );
+});
+
+/** Lightweight placeholder shown while ProviderForm mounts (keeps dialog animation smooth) */
+function DialogFormSkeleton() {
+  return (
+    <div className="flex flex-col h-[60vh] animate-pulse">
+      <div className="flex flex-1 min-h-0">
+        <div className="hidden lg:block w-48 shrink-0 border-r p-4 space-y-3">
+          {Array.from({ length: 6 }).map((_, i) => (
+            <Skeleton key={i} className="h-8 w-full" />
+          ))}
+        </div>
+        <div className="flex-1 p-6 space-y-6">
+          <Skeleton className="h-6 w-48" />
+          <Skeleton className="h-10 w-full" />
+          <Skeleton className="h-10 w-full" />
+          <Skeleton className="h-6 w-36 mt-4" />
+          <Skeleton className="h-10 w-full" />
+        </div>
+      </div>
+      <div className="shrink-0 px-6 py-4 border-t">
+        <Skeleton className="h-10 w-24 ml-auto" />
+      </div>
+    </div>
+  );
+}

+ 35 - 0
src/app/api/actions/[...route]/route.ts

@@ -271,6 +271,14 @@ const { route: addKeyRoute, handler: addKeyHandler } = createActionRoute(
       limitMonthlyUsd: z.number().nullable().optional(),
       limitTotalUsd: z.number().nullable().optional(),
       limitConcurrentSessions: z.number().optional(),
+      providerGroup: z.string().max(200).nullable().optional(),
+      isEnabled: z.boolean().optional(),
+      dailyResetMode: z.enum(["fixed", "rolling"]).optional(),
+      dailyResetTime: z
+        .string()
+        .regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/)
+        .optional(),
+      cacheTtlPreference: z.enum(["inherit", "5m", "1h"]).optional(),
     }),
     responseSchema: z.object({
       generatedKey: z.string(),
@@ -299,6 +307,17 @@ const { route: editKeyRoute, handler: editKeyHandler } = createActionRoute(
       limitMonthlyUsd: z.number().nullable().optional(),
       limitTotalUsd: z.number().nullable().optional(),
       limitConcurrentSessions: z.number().optional(),
+      providerGroup: z.string().max(200).nullable().optional().openapi({
+        description:
+          "Admin-only: Only admins can edit this field. Non-admins may not change this field.",
+      }),
+      isEnabled: z.boolean().optional(),
+      dailyResetMode: z.enum(["fixed", "rolling"]).optional(),
+      dailyResetTime: z
+        .string()
+        .regex(/^([01]?[0-9]|2[0-3]):[0-5][0-9]$/)
+        .optional(),
+      cacheTtlPreference: z.enum(["inherit", "5m", "1h"]).optional(),
     }),
     description: "编辑密钥信息",
     summary: "编辑密钥信息",
@@ -342,6 +361,22 @@ const { route: getKeyLimitUsageRoute, handler: getKeyLimitUsageHandler } = creat
 );
 app.openapi(getKeyLimitUsageRoute, getKeyLimitUsageHandler);
 
+const { route: resetKeyLimitsOnlyRoute, handler: resetKeyLimitsOnlyHandler } = createActionRoute(
+  "keys",
+  "resetKeyLimitsOnly",
+  keyActions.resetKeyLimitsOnly,
+  {
+    requestSchema: z.object({
+      keyId: z.number().int().positive(),
+    }),
+    description: "仅重置单个密钥的消费限额累计(不删除日志)",
+    summary: "重置密钥限额累计",
+    tags: ["密钥管理"],
+    requiredRole: "admin",
+  }
+);
+app.openapi(resetKeyLimitsOnlyRoute, resetKeyLimitsOnlyHandler);
+
 // ==================== 供应商管理 ====================
 
 const ProviderTypeSchema = z.enum([

+ 43 - 11
src/app/v1/_lib/proxy/client-detector.ts

@@ -33,17 +33,49 @@ export interface ClientRestrictionResult {
 
 const normalize = (s: string) => s.toLowerCase().replace(/[-_]/g, "");
 
-function matchesCodexDesktopAlias(pattern: string, userAgent: string): boolean {
-  if (!/^codex desktop\b/i.test(userAgent)) {
-    return false;
+// Map: UA prefix regex -> set of alias values that should match
+// All matchValues must be lowercase (pattern is lowercased before lookup)
+const CODEX_FAMILY_RULES: Array<{ test: RegExp; matchValues: Set<string> }> = [
+  {
+    test: /^codex desktop\b/i,
+    matchValues: new Set(["codex-cli", "codex desktop"]),
+  },
+  {
+    test: /^codex[_-]?tui\b/i,
+    matchValues: new Set(["codex-cli", "codex_cli_core"]),
+  },
+  {
+    test: /^codex[_-]?cli[_-]?rs\b/i,
+    matchValues: new Set(["codex-cli", "codex_cli_core"]),
+  },
+  {
+    test: /^codex[_-]?exec\b/i,
+    matchValues: new Set(["codex-cli", "codex_exec"]),
+  },
+  {
+    test: /^codex[_-]?vscode\b/i,
+    matchValues: new Set(["codex-cli", "codex_vscode"]),
+  },
+];
+
+if (process.env.NODE_ENV !== "production") {
+  for (const rule of CODEX_FAMILY_RULES) {
+    for (const v of rule.matchValues) {
+      if (v !== v.toLowerCase()) {
+        throw new Error(`CODEX_FAMILY_RULES matchValue "${v}" must be lowercase`);
+      }
+    }
   }
+}
 
+function matchesCodexFamilyAlias(pattern: string, userAgent: string): boolean {
   const normalizedPattern = pattern.trim().toLowerCase();
-  return (
-    normalizedPattern === "codex-cli" ||
-    normalizedPattern === "codex_vscode" ||
-    normalizedPattern === "codex desktop"
-  );
+  for (const rule of CODEX_FAMILY_RULES) {
+    if (rule.test.test(userAgent)) {
+      return rule.matchValues.has(normalizedPattern);
+    }
+  }
+  return false;
 }
 
 function globMatch(pattern: string, text: string): boolean {
@@ -144,7 +176,7 @@ export function matchClientPattern(session: ProxySession, pattern: string): bool
       return false;
     }
 
-    if (matchesCodexDesktopAlias(pattern, ua)) {
+    if (matchesCodexFamilyAlias(pattern, ua)) {
       return true;
     }
 
@@ -187,7 +219,7 @@ export function detectClientFull(session: ProxySession, pattern: string): Client
   } else {
     const ua = session.userAgent?.trim();
     if (ua) {
-      if (matchesCodexDesktopAlias(pattern, ua)) {
+      if (matchesCodexFamilyAlias(pattern, ua)) {
         matched = true;
       } else if (pattern.includes("*")) {
         matched = globMatch(pattern, ua);
@@ -247,7 +279,7 @@ export function isClientAllowedDetailed(
   const matches = (pattern: string): boolean => {
     if (!isBuiltinKeyword(pattern)) {
       if (!ua) return false;
-      if (matchesCodexDesktopAlias(pattern, ua)) {
+      if (matchesCodexFamilyAlias(pattern, ua)) {
         return true;
       }
       if (pattern.includes("*")) {

+ 4 - 9
src/app/v1/_lib/proxy/client-guard.ts

@@ -32,15 +32,10 @@ export class ProxyClientGuard {
 
     if (!result.allowed) {
       const detected = result.detectedClient ? ` (detected: ${result.detectedClient})` : "";
-      let message: string;
-      if (result.matchType === "blocklist_hit") {
-        message = `Client blocked by pattern: ${result.matchedPattern}${detected}`;
-      } else {
-        message = `Client not in allowed list: [${allowedClients.join(", ")}]${detected}`;
-      }
-      if (result.signals) {
-        message += `\nSignals(${result.signals.length}/4): [${result.signals.join(", ")}]`;
-      }
+      const message =
+        result.matchType === "blocklist_hit"
+          ? `Client blocked${detected}`
+          : `Client not allowed${detected}`;
       return ProxyResponses.buildError(400, message, "invalid_request_error");
     }
 

+ 470 - 0
src/app/v1/_lib/proxy/endpoint-family-catalog.ts

@@ -0,0 +1,470 @@
+import { normalizeEndpointPath } from "./endpoint-paths";
+
+export type EndpointClientFormat = "response" | "openai" | "claude" | "gemini" | "gemini-cli";
+
+export type EndpointAccountingTier = "required_usage" | "optional_usage" | "none";
+
+export interface EndpointFamily {
+  readonly id: string;
+  readonly surface: EndpointClientFormat;
+  readonly accountingTier: EndpointAccountingTier;
+  readonly modelRequired: boolean;
+  readonly rawPassthrough: boolean;
+  readonly match: (normalizedPath: string) => boolean;
+}
+
+const GEMINI_GENERATION_ACTIONS = new Set(["generatecontent", "streamgeneratecontent"]);
+
+function hasPrefix(pathname: string, prefix: string): boolean {
+  return pathname === prefix || pathname.startsWith(`${prefix}/`);
+}
+
+type GeminiActionPrefix =
+  | "/v1beta/models/"
+  | "/v1/publishers/google/models/"
+  | "/v1/models/"
+  | "/v1internal/models/";
+
+const GEMINI_STANDARD_MODEL_PREFIXES = [
+  "/v1beta/models/",
+  "/v1/publishers/google/models/",
+  "/v1/models/",
+] as const satisfies readonly GeminiActionPrefix[];
+
+const GEMINI_PREDICT_MODEL_PREFIXES = [
+  "/v1beta/models/",
+  "/v1/publishers/google/models/",
+] as const satisfies readonly GeminiActionPrefix[];
+
+const GEMINI_CLI_MODEL_PREFIXES = [
+  "/v1internal/models/",
+] as const satisfies readonly GeminiActionPrefix[];
+
+/**
+ * 匹配受信任的 Gemini action 路径。
+ *
+ * 注意:`actions` 只能来自当前模块内的硬编码常量,绝不能接收用户输入。
+ */
+function matchGeminiModelAction(
+  pathname: string,
+  prefix: GeminiActionPrefix,
+  actions: readonly string[]
+): boolean {
+  if (!pathname.startsWith(prefix)) {
+    return false;
+  }
+
+  const remainder = pathname.slice(prefix.length);
+  const separatorIndex = remainder.indexOf(":");
+  if (separatorIndex <= 0) {
+    return false;
+  }
+
+  const model = remainder.slice(0, separatorIndex);
+  const action = remainder.slice(separatorIndex + 1);
+  if (!model || model.includes("/") || model.includes(":")) {
+    return false;
+  }
+
+  return action.length > 0 && !action.includes("/") && actions.includes(action);
+}
+
+function matchGeminiModelActionOnPrefixes(
+  pathname: string,
+  prefixes: readonly GeminiActionPrefix[],
+  actions: readonly string[]
+): boolean {
+  return prefixes.some((prefix) => matchGeminiModelAction(pathname, prefix, actions));
+}
+
+const KNOWN_ENDPOINT_FAMILIES: readonly EndpointFamily[] = Object.freeze([
+  {
+    id: "claude-messages",
+    surface: "claude",
+    accountingTier: "required_usage",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => pathname === "/v1/messages",
+  },
+  {
+    id: "claude-count-tokens",
+    surface: "claude",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: true,
+    match: (pathname) => pathname === "/v1/messages/count_tokens",
+  },
+  {
+    id: "response-compact",
+    surface: "response",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: true,
+    match: (pathname) => pathname === "/v1/responses/compact",
+  },
+  {
+    id: "response-execution",
+    surface: "response",
+    accountingTier: "required_usage",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => pathname === "/v1/responses",
+  },
+  {
+    id: "response-resources",
+    surface: "response",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/responses"),
+  },
+  {
+    id: "openai-chat-completions",
+    surface: "openai",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) => pathname === "/v1/chat/completions",
+  },
+  {
+    id: "openai-chat-completions-resources",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/chat/completions"),
+  },
+  {
+    id: "openai-models",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => /^\/v1\/models(?:\/[^/:]+)?$/i.test(pathname),
+  },
+  {
+    id: "gemini-generate-content",
+    surface: "gemini",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, [
+        "generatecontent",
+      ]),
+  },
+  {
+    id: "gemini-stream-generate-content",
+    surface: "gemini",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, [
+        "streamgeneratecontent",
+      ]),
+  },
+  {
+    id: "gemini-count-tokens",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, ["counttokens"]),
+  },
+  {
+    id: "gemini-embed-content",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, ["embedcontent"]),
+  },
+  {
+    id: "gemini-batch-generate-content",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, [
+        "batchgeneratecontent",
+      ]),
+  },
+  {
+    id: "gemini-batch-embed-contents",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, [
+        "batchembedcontents",
+      ]),
+  },
+  {
+    id: "gemini-async-batch-embed-content",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_STANDARD_MODEL_PREFIXES, [
+        "asyncbatchembedcontent",
+      ]),
+  },
+  {
+    id: "gemini-predict",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_PREDICT_MODEL_PREFIXES, ["predict"]),
+  },
+  {
+    id: "gemini-predict-long-running",
+    surface: "gemini",
+    accountingTier: "optional_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_PREDICT_MODEL_PREFIXES, [
+        "predictlongrunning",
+      ]),
+  },
+  {
+    id: "gemini-files",
+    surface: "gemini",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1beta/files"),
+  },
+  {
+    id: "gemini-models-resource",
+    surface: "gemini",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) =>
+      pathname === "/v1beta/models" ||
+      /^\/v1beta\/models\/[^/:]+$/i.test(pathname) ||
+      /^\/v1\/publishers\/google\/models\/[^/:]+$/i.test(pathname),
+  },
+  {
+    id: "gemini-cli-generate-content",
+    surface: "gemini-cli",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_CLI_MODEL_PREFIXES, ["generatecontent"]),
+  },
+  {
+    id: "gemini-cli-stream-generate-content",
+    surface: "gemini-cli",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) =>
+      matchGeminiModelActionOnPrefixes(pathname, GEMINI_CLI_MODEL_PREFIXES, [
+        "streamgeneratecontent",
+      ]),
+  },
+  {
+    id: "openai-completions",
+    surface: "openai",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/completions"),
+  },
+  {
+    id: "openai-embeddings",
+    surface: "openai",
+    accountingTier: "required_usage",
+    modelRequired: true,
+    rawPassthrough: false,
+    match: (pathname) => pathname === "/v1/embeddings",
+  },
+  {
+    id: "openai-moderations",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/moderations"),
+  },
+  {
+    id: "openai-audio-generation",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => pathname === "/v1/audio/speech",
+  },
+  {
+    id: "openai-audio-transcription",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) =>
+      pathname === "/v1/audio/transcriptions" || pathname === "/v1/audio/translations",
+  },
+  {
+    id: "openai-audio-resources",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) =>
+      hasPrefix(pathname, "/v1/audio/voice_consents") || hasPrefix(pathname, "/v1/audio/voices"),
+  },
+  {
+    id: "openai-images",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/images"),
+  },
+  {
+    id: "openai-files",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/files"),
+  },
+  {
+    id: "openai-uploads",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/uploads"),
+  },
+  {
+    id: "openai-batches",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/batches"),
+  },
+  {
+    id: "openai-fine-tuning",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/fine_tuning"),
+  },
+  {
+    id: "openai-evals",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/evals"),
+  },
+  {
+    id: "openai-assistants",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/assistants"),
+  },
+  {
+    id: "openai-threads",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/threads"),
+  },
+  {
+    id: "openai-conversations",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/conversations"),
+  },
+  {
+    id: "openai-vector-stores",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/vector_stores"),
+  },
+  {
+    id: "openai-containers",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/containers"),
+  },
+  {
+    id: "openai-realtime-http",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/realtime"),
+  },
+  {
+    id: "openai-videos",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/videos"),
+  },
+  {
+    id: "openai-skills",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/skills"),
+  },
+  {
+    id: "openai-chatkit",
+    surface: "openai",
+    accountingTier: "none",
+    modelRequired: false,
+    rawPassthrough: false,
+    match: (pathname) => hasPrefix(pathname, "/v1/chatkit"),
+  },
+]);
+
+export function listKnownEndpointFamilies(): readonly EndpointFamily[] {
+  return KNOWN_ENDPOINT_FAMILIES;
+}
+
+export function resolveEndpointFamilyByPath(pathname: string): EndpointFamily | null {
+  const normalizedPath = normalizeEndpointPath(pathname);
+  return KNOWN_ENDPOINT_FAMILIES.find((family) => family.match(normalizedPath)) ?? null;
+}
+
+export function detectEndpointFormat(pathname: string): EndpointClientFormat | null {
+  return resolveEndpointFamilyByPath(pathname)?.surface ?? null;
+}
+
+export function isStandardProxyEndpointPath(pathname: string): boolean {
+  return resolveEndpointFamilyByPath(pathname) !== null;
+}
+
+export function isGeminiGenerationEndpointPath(pathname: string): boolean {
+  const normalizedPath = normalizeEndpointPath(pathname);
+  const matches = normalizedPath.match(/:([^/]+)$/);
+  return matches?.[1] ? GEMINI_GENERATION_ACTIONS.has(matches[1]) : false;
+}

+ 3 - 0
src/app/v1/_lib/proxy/endpoint-paths.ts

@@ -6,6 +6,7 @@ export const V1_ENDPOINT_PATHS = {
   RESPONSES: "/v1/responses",
   RESPONSES_COMPACT: "/v1/responses/compact",
   CHAT_COMPLETIONS: "/v1/chat/completions",
+  EMBEDDINGS: "/v1/embeddings",
   MODELS: "/v1/models",
 } as const;
 
@@ -15,6 +16,7 @@ export const STANDARD_ENDPOINT_PATHS = [
   V1_ENDPOINT_PATHS.RESPONSES,
   V1_ENDPOINT_PATHS.RESPONSES_COMPACT,
   V1_ENDPOINT_PATHS.CHAT_COMPLETIONS,
+  V1_ENDPOINT_PATHS.EMBEDDINGS,
   V1_ENDPOINT_PATHS.MODELS,
 ] as const;
 
@@ -23,6 +25,7 @@ export const STRICT_STANDARD_ENDPOINT_PATHS = [
   V1_ENDPOINT_PATHS.RESPONSES,
   V1_ENDPOINT_PATHS.RESPONSES_COMPACT,
   V1_ENDPOINT_PATHS.CHAT_COMPLETIONS,
+  V1_ENDPOINT_PATHS.EMBEDDINGS,
 ] as const;
 
 const standardEndpointPathSet = new Set<string>(STANDARD_ENDPOINT_PATHS);

+ 1 - 1
src/app/v1/_lib/proxy/errors.ts

@@ -733,7 +733,7 @@ export function isClientAbortError(error: Error): boolean {
  * @param error - Error to check
  * @returns true if error is a transport error
  */
-function isTransportError(error: Error): boolean {
+export function isTransportError(error: Error): boolean {
   const TRANSPORT_ERROR_CODES = new Set([
     "UND_ERR_SOCKET",
     "UND_ERR_CONNECT_TIMEOUT",

+ 45 - 47
src/app/v1/_lib/proxy/format-mapper.ts

@@ -1,3 +1,5 @@
+import { detectEndpointFormat, type EndpointClientFormat } from "./endpoint-family-catalog";
+
 /**
  * API 格式映射工具
  *
@@ -20,7 +22,7 @@
  * - "gemini": 检测到 Gemini API 直接格式的请求(通过 `contents` 字段)
  * - "gemini-cli": 检测到 Gemini CLI 格式的请求(通过 `request` envelope)
  */
-export type ClientFormat = "response" | "openai" | "claude" | "gemini" | "gemini-cli";
+export type ClientFormat = EndpointClientFormat;
 
 /**
  * 根据请求端点检测客户端格式(优先级最高)
@@ -31,8 +33,8 @@ export type ClientFormat = "response" | "openai" | "claude" | "gemini" | "gemini
  * 支持的端点模式:
  * - Claude Messages API: `/v1/messages`, `/v1/messages/count_tokens`
  * - Codex Response API: `/v1/responses`
- * - OpenAI Compatible: `/v1/chat/completions`
- * - Gemini Direct: `/v1beta/models/{model}:generateContent`
+ * - OpenAI Compatible: `/v1/chat/completions`, `/v1/embeddings`
+ * - Gemini Direct: `/v1beta/models/{model}:generateContent`, `/v1beta/models/{model}:embedContent`
  * - Gemini CLI: `/v1internal/models/{model}:generateContent`
  *
  * @param pathname - URL 路径(如 `/v1/messages`)
@@ -47,47 +49,7 @@ export type ClientFormat = "response" | "openai" | "claude" | "gemini" | "gemini
  * ```
  */
 export function detectFormatByEndpoint(pathname: string): ClientFormat | null {
-  // 规范化路径:移除查询参数和末尾斜杠
-  const normalizedPath = pathname.split("?")[0].replace(/\/$/, "");
-
-  // 端点模式匹配(按优先级顺序)
-  const endpointPatterns: Array<{ pattern: RegExp; format: ClientFormat }> = [
-    // Claude Messages API
-    { pattern: /^\/v1\/messages(?:\/count_tokens)?$/i, format: "claude" },
-
-    // Codex / Response API
-    { pattern: /^\/v1\/responses$/i, format: "response" },
-
-    // OpenAI Chat Completions
-    { pattern: /^\/v1\/chat\/completions$/i, format: "openai" },
-
-    // Gemini Vertex AI (publishers path)
-    {
-      pattern:
-        /^\/v1\/publishers\/google\/models\/[^/:]+:(?:generateContent|streamGenerateContent|countTokens)$/i,
-      format: "gemini",
-    },
-
-    // Gemini Direct API
-    {
-      pattern: /^\/v1beta\/models\/[^/:]+:(?:generateContent|streamGenerateContent|countTokens)$/i,
-      format: "gemini",
-    },
-
-    // Gemini CLI (internal)
-    {
-      pattern: /^\/v1internal\/models\/[^/:]+:(?:generateContent|streamGenerateContent)$/i,
-      format: "gemini-cli",
-    },
-  ];
-
-  for (const { pattern, format } of endpointPatterns) {
-    if (pattern.test(normalizedPath)) {
-      return format;
-    }
-  }
-
-  return null; // 未知端点,需要回退到请求体检测
+  return detectEndpointFormat(pathname);
 }
 
 /**
@@ -120,13 +82,49 @@ export function detectClientFormat(requestBody: Record<string, unknown>): Client
     return "gemini-cli";
   }
 
-  // 3. 检测 Response API (Codex) 格式
+  // 3. 检测 Gemini batch 格式
+  if (Array.isArray(requestBody.requests)) {
+    const isGeminiContentPayload = (value: unknown): boolean => {
+      if (typeof value !== "object" || value === null || Array.isArray(value)) {
+        return false;
+      }
+
+      const payload = value as Record<string, unknown>;
+      return Array.isArray(payload.parts) || Array.isArray(payload.contents);
+    };
+
+    const hasGeminiBatchShape = requestBody.requests.some((entry) => {
+      if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
+        return false;
+      }
+
+      const record = entry as Record<string, unknown>;
+      if (typeof record.model === "string" && isGeminiContentPayload(record.content)) {
+        return true;
+      }
+
+      if (typeof record.request === "object" && record.request !== null) {
+        const nestedRequest = record.request as Record<string, unknown>;
+        return (
+          typeof nestedRequest.model === "string" && isGeminiContentPayload(nestedRequest.content)
+        );
+      }
+
+      return false;
+    });
+
+    if (hasGeminiBatchShape) {
+      return "gemini";
+    }
+  }
+
+  // 4. 检测 Response API (Codex) 格式
   // 仅通过 input 数组识别;字符串/单对象简写由 response-input-rectifier 在端点确认后规范化
   if (Array.isArray(requestBody.input)) {
     return "response";
   }
 
-  // 4. 检测 OpenAI Compatible 格式
+  // 5. 检测 OpenAI Compatible 格式
   if (Array.isArray(requestBody.messages)) {
     // 进一步区分 OpenAI 和 Claude
     // Claude 的 messages 可能包含 system,但 OpenAI 也可能有 system message
@@ -140,6 +138,6 @@ export function detectClientFormat(requestBody: Record<string, unknown>): Client
     return "openai";
   }
 
-  // 5. 默认为 Claude Messages API
+  // 6. 默认为 Claude Messages API
   return "claude";
 }

+ 94 - 83
src/app/v1/_lib/proxy/forwarder.ts

@@ -1,4 +1,3 @@
-import crypto from "node:crypto";
 import { STATUS_CODES } from "node:http";
 import type { Readable } from "node:stream";
 import { createGunzip, constants as zlibConstants } from "node:zlib";
@@ -11,6 +10,10 @@ import {
   recordFailure,
   recordSuccess,
 } from "@/lib/circuit-breaker";
+import {
+  hasUsableClaudeMetadataUserId,
+  injectClaudeMetadataUserIdWithContext,
+} from "@/lib/claude-code/metadata-user-id";
 import { applyCodexProviderOverridesWithAudit } from "@/lib/codex/provider-overrides";
 import { getCachedSystemSettings, isHttp2Enabled } from "@/lib/config";
 import { getEnvConfig } from "@/lib/config/env.schema";
@@ -43,6 +46,8 @@ import { GEMINI_PROTOCOL } from "../gemini/protocol";
 import { HeaderProcessor } from "../headers";
 import { buildProxyUrl } from "../url";
 import { rectifyBillingHeader } from "./billing-header-rectifier";
+import { isStandardProxyEndpointPath } from "./endpoint-family-catalog";
+import { isStrictStandardEndpointPath } from "./endpoint-paths";
 import {
   buildRequestDetails,
   categorizeErrorAsync,
@@ -73,17 +78,6 @@ import {
 export const DEFAULT_CODEX_USER_AGENT =
   "codex_cli_rs/0.93.0 (Windows 10.0.26200; x86_64) vscode/1.108.1";
 
-const STANDARD_ENDPOINTS = [
-  "/v1/messages",
-  "/v1/messages/count_tokens",
-  "/v1/responses",
-  "/v1/responses/compact",
-  "/v1/chat/completions",
-  "/v1/models",
-];
-
-const STRICT_STANDARD_ENDPOINTS = ["/v1/messages", "/v1/responses", "/v1/chat/completions"];
-
 const OUTBOUND_TRANSPORT_HEADER_BLACKLIST = ["content-length", "connection", "transfer-encoding"];
 
 const RETRY_LIMITS = PROVIDER_LIMITS.MAX_RETRY_ATTEMPTS;
@@ -262,6 +256,10 @@ function resolveMaxAttemptsForProvider(
   return clampRetryAttempts(provider.maxRetryAttempts);
 }
 
+function buildEndpointAttemptKey(endpointId: number | null, endpointUrl: string): string {
+  return endpointId != null ? `id:${endpointId}` : `url:${endpointUrl}`;
+}
+
 /**
  * undici request 超时配置(毫秒)
  *
@@ -356,9 +354,9 @@ async function persistSpecialSettings(session: ProxySession): Promise<void> {
 /**
  * 为 Claude 请求注入 metadata.user_id
  *
- * 格式:user_{stableHash}_account__session_{sessionId}
- * - stableHash: 基于 API Key ID 生成的稳定哈希(64位 hex),生成后保持不变
- * - sessionId: 当前请求的 session ID
+ * 格式选择
+ * - Claude Code < v2.1.78: `user_{stableHash}_account__session_{sessionId}`
+ * - 无法识别版本 / >= v2.1.78: JSON 字符串 `{"device_id":"...","account_uuid":"","session_id":"..."}`
  *
  * 注意:如果请求体中已存在 metadata.user_id,则保持原样不修改
  * @internal
@@ -367,40 +365,14 @@ export function injectClaudeMetadataUserId(
   message: Record<string, unknown>,
   session: ProxySession
 ): Record<string, unknown> {
-  const existingMetadata =
-    typeof message.metadata === "object" && message.metadata !== null
-      ? (message.metadata as Record<string, unknown>)
-      : undefined;
-
-  // 检查是否已存在 metadata.user_id
-  if (existingMetadata?.user_id !== undefined && existingMetadata?.user_id !== null) {
-    return message;
-  }
-
-  // 获取必要信息
   const keyId = session.authState?.key?.id;
   const sessionId = session.sessionId;
 
-  if (keyId == null || !sessionId) {
-    return message;
-  }
-
-  // 生成稳定的 user hash(基于 API Key ID)
-  const stableHash = crypto.createHash("sha256").update(`claude_user_${keyId}`).digest("hex");
-
-  // 构建 user_id
-  const userId = `user_${stableHash}_account__session_${sessionId}`;
-
-  // 注入 metadata
-  const newMetadata = {
-    ...existingMetadata,
-    user_id: userId,
-  };
-
-  return {
-    ...message,
-    metadata: newMetadata,
-  };
+  return injectClaudeMetadataUserIdWithContext(message, {
+    keyId,
+    sessionId,
+    userAgent: session.userAgent,
+  });
 }
 
 function applyClaudeMetadataUserIdInjectionWithAudit(
@@ -427,7 +399,7 @@ function applyClaudeMetadataUserIdInjectionWithAudit(
       ? (message.metadata as Record<string, unknown>)
       : undefined;
 
-  if (existingMetadata?.user_id !== undefined && existingMetadata?.user_id !== null) {
+  if (hasUsableClaudeMetadataUserId(existingMetadata?.user_id)) {
     logger.info("[ProxyForwarder] Claude metadata.user_id injection skipped", {
       enabled,
       hit: false,
@@ -557,9 +529,9 @@ export class ProxyForwarder {
       const isMcpRequest =
         currentProvider.providerType !== "gemini" &&
         currentProvider.providerType !== "gemini-cli" &&
-        !STANDARD_ENDPOINTS.includes(requestPath);
+        !isStandardProxyEndpointPath(requestPath);
       const shouldEnforceStrictEndpointPool =
-        !isMcpRequest && STRICT_STANDARD_ENDPOINTS.includes(requestPath) && providerVendorId > 0;
+        !isMcpRequest && isStrictStandardEndpointPath(requestPath) && providerVendorId > 0;
       let endpointSelectionError: Error | null = null;
 
       const endpointCandidates: Array<{ endpointId: number | null; baseUrl: string }> = [];
@@ -665,8 +637,12 @@ export class ProxyForwarder {
         });
       }
 
-      let endpointAttemptsEvaluated = 0;
-      let allEndpointAttemptsTimedOut = true;
+      const endpointCandidateKeys = new Set(
+        endpointCandidates.map((endpoint) =>
+          buildEndpointAttemptKey(endpoint.endpointId, endpoint.baseUrl)
+        )
+      );
+      const timedOutEndpointKeys = new Set<string>();
 
       // Endpoint stickiness: track current endpoint index separately from attemptCount
       // - SYSTEM_ERROR (network error): advance to next endpoint
@@ -1026,11 +1002,11 @@ export class ProxyForwarder {
               : lastError.message;
 
           const isTimeoutError = lastError instanceof ProxyError && lastError.statusCode === 524;
-          if (attemptCount <= endpointCandidates.length) {
-            endpointAttemptsEvaluated = attemptCount;
-            if (!isTimeoutError) {
-              allEndpointAttemptsTimedOut = false;
-            }
+
+          if (isTimeoutError) {
+            timedOutEndpointKeys.add(
+              buildEndpointAttemptKey(activeEndpoint.endpointId, activeEndpoint.baseUrl)
+            );
           }
 
           if (activeEndpoint.endpointId != null) {
@@ -1646,10 +1622,10 @@ export class ProxyForwarder {
             if (
               !isMcpRequest &&
               statusCode === 524 &&
-              endpointCandidates.length > 0 &&
-              endpointAttemptsEvaluated >= endpointCandidates.length &&
-              allEndpointAttemptsTimedOut &&
-              currentProvider.providerVendorId
+              currentProvider.providerVendorId &&
+              endpointCandidateKeys.size > 0 &&
+              timedOutEndpointKeys.size >= endpointCandidateKeys.size &&
+              !willRetry
             ) {
               // Record to decision chain BEFORE triggering vendor-type circuit breaker
               session.addProviderToChain(currentProvider, {
@@ -1736,6 +1712,16 @@ export class ProxyForwarder {
 
             // 未耗尽重试次数:等待 100ms 后继续重试当前供应商
             if (willRetry) {
+              if (statusCode === 524) {
+                currentEndpointIndex++;
+                logger.debug("ProxyForwarder: Advancing endpoint index due to upstream timeout", {
+                  providerId: currentProvider.id,
+                  previousEndpointIndex: currentEndpointIndex - 1,
+                  newEndpointIndex: currentEndpointIndex,
+                  maxEndpointIndex: endpointCandidates.length - 1,
+                });
+              }
+
               await new Promise((resolve) => setTimeout(resolve, 100));
               continue;
             }
@@ -1799,7 +1785,7 @@ export class ProxyForwarder {
 
     // ⭐ 不暴露供应商详情,仅返回简单错误
     await ProxyForwarder.clearSessionProviderBinding(session);
-    throw new ProxyError("所有供应商暂时不可用,请稍后重试", 503); // Service Unavailable
+    throw ProxyForwarder.buildAllProvidersUnavailableError(); // Service Unavailable
   }
 
   /**
@@ -1854,7 +1840,11 @@ export class ProxyForwarder {
 
         // Apply Gemini Google Search override if configured
         const { request: overriddenBody, audit: googleSearchAudit } =
-          applyGeminiGoogleSearchOverrideWithAudit(provider, bodyToSerialize);
+          applyGeminiGoogleSearchOverrideWithAudit(
+            provider,
+            bodyToSerialize,
+            session.requestUrl.pathname
+          );
         if (googleSearchAudit) {
           session.addSpecialSetting(googleSearchAudit);
           bodyToSerialize = overriddenBody;
@@ -2140,8 +2130,7 @@ export class ProxyForwarder {
 
       // 检测是否为 MCP 请求(非标准 Claude/Codex/OpenAI 端点)
       const requestPath = session.requestUrl.pathname;
-      // pathname does not include query params, so exact match is sufficient
-      const isStandardRequest = STANDARD_ENDPOINTS.includes(requestPath);
+      const isStandardRequest = isStandardProxyEndpointPath(requestPath);
       const isMcpRequest = !isStandardRequest;
 
       if (isMcpRequest && provider.mcpPassthroughType && provider.mcpPassthroughType !== "none") {
@@ -2957,6 +2946,7 @@ export class ProxyForwarder {
     let noMoreProviders = false;
     let launchingAlternative: Promise<void> | null = null;
     let lastError: Error | null = null;
+    let lastErrorCategory: ErrorCategory | null = null;
     const attempts = new Set<StreamingHedgeAttempt>();
 
     let resolveResult: ((result: { response?: Response; error?: Error }) => void) | null = null;
@@ -3012,13 +3002,7 @@ export class ProxyForwarder {
 
     const finishIfExhausted = async () => {
       if (!settled && noMoreProviders && attempts.size === 0) {
-        await settleFailure(
-          lastError ??
-            new ProxyError("No available providers", 503, {
-              body: "",
-              providerId: initialProvider.id,
-            })
-        );
+        await settleFailure(ProxyForwarder.resolveHedgeTerminalError(lastError, lastErrorCategory));
       }
     };
 
@@ -3056,11 +3040,8 @@ export class ProxyForwarder {
             providerName: initialProvider.name,
           });
 
-          lastError = new ProxyError("No available providers", 503, {
-            body: "",
-            providerId: initialProvider.id,
-            providerName: initialProvider.name,
-          });
+          lastError = ProxyForwarder.buildAllProvidersUnavailableError();
+          lastErrorCategory = null;
           noMoreProviders = true;
           abortAllAttempts(undefined, "hedge_launch_failed");
           await finishIfExhausted();
@@ -3084,6 +3065,7 @@ export class ProxyForwarder {
       lastError = error;
 
       const errorCategory = await categorizeErrorAsync(error);
+      lastErrorCategory = errorCategory;
       const statusCode = error instanceof ProxyError ? error.statusCode : undefined;
 
       if (attempt.endpointAudit.endpointId != null) {
@@ -3119,13 +3101,21 @@ export class ProxyForwarder {
         reason:
           errorCategory === ErrorCategory.RESOURCE_NOT_FOUND
             ? "resource_not_found"
-            : "retry_failed",
+            : errorCategory === ErrorCategory.NON_RETRYABLE_CLIENT_ERROR
+              ? "client_error_non_retryable"
+              : "retry_failed",
         attemptNumber: attempt.sequence,
         statusCode,
         errorMessage: error instanceof ProxyError ? error.getDetailedErrorMessage() : error.message,
         circuitState: getCircuitState(attempt.provider.id),
       });
 
+      if (errorCategory === ErrorCategory.NON_RETRYABLE_CLIENT_ERROR) {
+        abortAllAttempts(undefined, "client_error_non_retryable");
+        await settleFailure(error);
+        return;
+      }
+
       await launchAlternative();
       await finishIfExhausted();
     };
@@ -3234,6 +3224,7 @@ export class ProxyForwarder {
         endpointSelection = await ProxyForwarder.resolveStreamingHedgeEndpoint(session, provider);
       } catch (endpointError) {
         lastError = endpointError as Error;
+        lastErrorCategory = null;
         await launchAlternative();
         await finishIfExhausted();
         return;
@@ -3370,6 +3361,7 @@ export class ProxyForwarder {
           if (settled || winnerCommitted) return;
           noMoreProviders = true;
           lastError = new ProxyError("Request aborted by client", 499, undefined, true);
+          lastErrorCategory = ErrorCategory.CLIENT_ABORT;
           for (const attempt of Array.from(attempts)) {
             if (!attempt.settled) {
               session.addProviderToChain(attempt.provider, {
@@ -3405,9 +3397,9 @@ export class ProxyForwarder {
     const isMcpRequest =
       provider.providerType !== "gemini" &&
       provider.providerType !== "gemini-cli" &&
-      !STANDARD_ENDPOINTS.includes(requestPath);
+      !isStandardProxyEndpointPath(requestPath);
     const shouldEnforceStrictEndpointPool =
-      !isMcpRequest && STRICT_STANDARD_ENDPOINTS.includes(requestPath) && providerVendorId > 0;
+      !isMcpRequest && isStrictStandardEndpointPath(requestPath) && providerVendorId > 0;
 
     if (
       !isMcpRequest &&
@@ -3583,6 +3575,25 @@ export class ProxyForwarder {
     await SessionManager.clearSessionProvider(session.sessionId);
   }
 
+  private static buildAllProvidersUnavailableError(): ProxyError {
+    return new ProxyError("所有供应商暂时不可用,请稍后重试", 503);
+  }
+
+  private static resolveHedgeTerminalError(
+    lastError: Error | null,
+    lastErrorCategory: ErrorCategory | null
+  ): Error {
+    if (
+      lastError &&
+      (lastErrorCategory === ErrorCategory.CLIENT_ABORT ||
+        lastErrorCategory === ErrorCategory.NON_RETRYABLE_CLIENT_ERROR)
+    ) {
+      return lastError;
+    }
+
+    return ProxyForwarder.buildAllProvidersUnavailableError();
+  }
+
   private static async readFirstReadableChunk(
     reader: ReadableStreamDefaultReader<Uint8Array>
   ): Promise<ReadableStreamReadResult<Uint8Array>> {
@@ -4019,18 +4030,18 @@ export class ProxyForwarder {
           }
         });
 
-        // ⭐ 关键:吞掉错误事件,避免 "terminated" 冒泡
+        // ⭐ 关键:将上游流错误传播到下游 reader,确保 ResponseHandler 能检测到截断
         nodeStream.on("error", (err) => {
-          logger.warn("ProxyForwarder: Upstream stream error (gracefully closed)", {
+          logger.warn("ProxyForwarder: Upstream stream error (signaling downstream)", {
             providerId,
             providerName,
             error: err.message,
             errorName: err.name,
           });
           try {
-            controller.close();
+            controller.error(err);
           } catch {
-            // 如果已关闭,忽略
+            // 如果已关闭或已出错,忽略
           }
         });
       },

+ 4 - 3
src/app/v1/_lib/proxy/provider-selector.ts

@@ -843,10 +843,11 @@ export class ProxyProviderResolver {
         }
       }
 
-      // 2c. 模型匹配(保留原有逻辑)
+      // 2c. 模型匹配
       if (!requestedModel) {
-        // 没有模型信息时,只选择 Anthropic 提供商(向后兼容)
-        return provider.providerType === "claude";
+        // 资源类端点通常不携带 model,此时仅按格式兼容性筛选 provider,
+        // 不应再因为缺失模型而把请求错误收窄到 claude。
+        return true;
       }
 
       return providerSupportsModel(provider, requestedModel);

+ 8 - 5
src/app/v1/_lib/proxy/rate-limit-guard.ts

@@ -1,6 +1,7 @@
 import { logger } from "@/lib/logger";
 import { RateLimitService } from "@/lib/rate-limit";
 import { resolveKeyUserConcurrentSessionLimits } from "@/lib/rate-limit/concurrent-session-limit";
+import { resolveKeyCostResetAt } from "@/lib/rate-limit/cost-reset-utils";
 import { getResetInfo, getResetInfoWithMode } from "@/lib/rate-limit/time-utils";
 import { SessionManager } from "@/lib/session-manager";
 import { ERROR_CODES, getErrorMessageServer } from "@/lib/utils/error-messages";
@@ -57,6 +58,8 @@ export class ProxyRateLimitGuard {
 
     if (!user || !key) return;
 
+    const keyCostResetAt = resolveKeyCostResetAt(key.costResetAt ?? null, user.costResetAt ?? null);
+
     // ========== 第一层:永久硬限制 ==========
 
     // 1. Key 总限额(用户明确要求优先检查)
@@ -64,7 +67,7 @@ export class ProxyRateLimitGuard {
       key.id,
       "key",
       key.limitTotalUsd ?? null,
-      { keyHash: key.key, resetAt: user.costResetAt }
+      { keyHash: key.key, resetAt: keyCostResetAt }
     );
 
     if (!keyTotalCheck.allowed) {
@@ -230,7 +233,7 @@ export class ProxyRateLimitGuard {
       limit_daily_usd: null, // 仅检查 5h
       limit_weekly_usd: null,
       limit_monthly_usd: null,
-      cost_reset_at: user.costResetAt ?? null,
+      cost_reset_at: keyCostResetAt,
     });
 
     if (!key5hCheck.allowed) {
@@ -306,7 +309,7 @@ export class ProxyRateLimitGuard {
       daily_reset_time: key.dailyResetTime,
       limit_weekly_usd: null,
       limit_monthly_usd: null,
-      cost_reset_at: user.costResetAt ?? null,
+      cost_reset_at: keyCostResetAt,
     });
 
     if (!keyDailyCheck.allowed) {
@@ -455,7 +458,7 @@ export class ProxyRateLimitGuard {
       limit_daily_usd: null,
       limit_weekly_usd: key.limitWeeklyUsd,
       limit_monthly_usd: null,
-      cost_reset_at: user.costResetAt ?? null,
+      cost_reset_at: keyCostResetAt,
     });
 
     if (!keyWeeklyCheck.allowed) {
@@ -527,7 +530,7 @@ export class ProxyRateLimitGuard {
       limit_daily_usd: null,
       limit_weekly_usd: null,
       limit_monthly_usd: key.limitMonthlyUsd,
-      cost_reset_at: user.costResetAt ?? null,
+      cost_reset_at: keyCostResetAt,
     });
 
     if (!keyMonthlyCheck.allowed) {

+ 34 - 1
src/app/v1/_lib/proxy/response-handler.ts

@@ -39,7 +39,7 @@ import type { SessionUsageUpdate } from "@/types/session";
 import type { LongContextPricingSpecialSetting } from "@/types/special-settings";
 import { GeminiAdapter } from "../gemini/adapter";
 import type { GeminiResponse } from "../gemini/types";
-import { isClientAbortError } from "./errors";
+import { isClientAbortError, isTransportError } from "./errors";
 import type { ProxySession } from "./session";
 import { consumeDeferredStreamingFinalization } from "./stream-finalization";
 
@@ -2371,6 +2371,39 @@ export class ProxyResponseHandler {
               });
             }
           }
+        } else if (isTransportError(err)) {
+          // 上游流传输错误(SocketError, ECONNRESET 等):与 upstream abort 相同处理
+          // 参见 #916 — controller.error(err) 传播的 transport error
+          logger.error("ResponseHandler: Upstream stream transport error", {
+            taskId,
+            providerId: provider.id,
+            providerName: provider.name,
+            messageId: messageContext.id,
+            chunksCollected: chunks.length,
+            errorName: err.name,
+            errorMessage: err.message || "(empty message)",
+            errorCode: (err as NodeJS.ErrnoException).code,
+          });
+
+          try {
+            const allContent = flushAndJoin();
+            await finalizeStream(allContent, false, false, "STREAM_UPSTREAM_ABORTED");
+          } catch (finalizeError) {
+            logger.error("ResponseHandler: Failed to finalize transport-error stream", {
+              taskId,
+              messageId: messageContext.id,
+              finalizeError,
+            });
+
+            await persistRequestFailure({
+              session,
+              messageContext,
+              statusCode: 502,
+              error: err,
+              taskId,
+              phase: "stream",
+            });
+          }
         } else {
           logger.error("Failed to save SSE content:", error);
 

+ 24 - 1
src/app/v1/_lib/proxy/session-guard.ts

@@ -1,3 +1,4 @@
+import { injectClaudeMetadataUserIdWithContext } from "@/lib/claude-code/metadata-user-id";
 import { getCachedSystemSettings } from "@/lib/config";
 import { logger } from "@/lib/logger";
 import { resolveKeyUserConcurrentSessionLimits } from "@/lib/rate-limit/concurrent-session-limit";
@@ -53,6 +54,8 @@ export class ProxySessionGuard {
 
       // Codex Session ID 补全:在提取 clientSessionId 之前触发,避免落入不稳定的降级方案
       const codexCompletionEnabled = systemSettings.enableCodexSessionIdCompletion ?? true;
+      const claudeMetadataCompletionEnabled =
+        systemSettings.enableClaudeMetadataUserIdInjection ?? true;
       const requestMessage = session.request.message as Record<string, unknown>;
       const isCodexRequest = Array.isArray(requestMessage.input);
 
@@ -84,7 +87,7 @@ export class ProxySessionGuard {
         !!session.authState.apiKey &&
         systemSettings.interceptAnthropicWarmupRequests;
 
-      // 1. 尝试从客户端提取 session_id(metadata.session_id)
+      // 1. 尝试从客户端提取 session_id(兼容 metadata.user_id / metadata.session_id)
       const clientSessionId = SessionManager.extractClientSessionId(
         session.request.message,
         session.headers,
@@ -100,6 +103,26 @@ export class ProxySessionGuard {
       // 4. 设置到 session 对象
       session.setSessionId(sessionId);
 
+      if (
+        claudeMetadataCompletionEnabled &&
+        !warmupMaybeIntercepted &&
+        session.originalFormat === "claude" &&
+        !isCodexRequest
+      ) {
+        const completedMessage = injectClaudeMetadataUserIdWithContext(
+          session.request.message as Record<string, unknown>,
+          {
+            keyId,
+            sessionId,
+            userAgent: session.userAgent,
+          }
+        );
+
+        if (completedMessage !== session.request.message) {
+          session.request.message = completedMessage;
+        }
+      }
+
       // 4.1 获取并设置请求序号(Session 内唯一标识每个请求)
       const requestSequence = await SessionManager.getNextRequestSequence(sessionId);
       session.setRequestSequence(requestSequence);

+ 1 - 0
src/app/v1/_lib/url.ts

@@ -6,6 +6,7 @@ const targetEndpoints = [
   "/responses", // Codex Response API
   "/messages", // Claude Messages API
   "/chat/completions", // OpenAI Compatible
+  "/embeddings", // OpenAI Compatible Embeddings
   "/models", // Gemini & OpenAI models
 ] as const;
 

+ 3 - 0
src/components/form/client-restrictions-editor.test.tsx

@@ -31,6 +31,9 @@ const TEST_TRANSLATIONS = {
     "sdk-py": "SDK (Python)",
     "cli-sdk": "CLI SDK",
     "gh-action": "GitHub Action",
+    "codex-cli-core": "CLI / TUI",
+    desktop: "Desktop",
+    exec: "Exec",
   },
   nSelected: "{count} selected",
 };

+ 7 - 7
src/components/ui/alert-dialog.tsx

@@ -121,14 +121,14 @@ function AlertDialogCancel({
 
 export {
   AlertDialog,
-  AlertDialogPortal,
-  AlertDialogOverlay,
-  AlertDialogTrigger,
+  AlertDialogAction,
+  AlertDialogCancel,
   AlertDialogContent,
-  AlertDialogHeader,
+  AlertDialogDescription,
   AlertDialogFooter,
+  AlertDialogHeader,
+  AlertDialogOverlay,
+  AlertDialogPortal,
   AlertDialogTitle,
-  AlertDialogDescription,
-  AlertDialogAction,
-  AlertDialogCancel,
+  AlertDialogTrigger,
 };

+ 1 - 1
src/components/ui/alert.tsx

@@ -46,4 +46,4 @@ const AlertDescription = React.forwardRef<
 ));
 AlertDescription.displayName = "AlertDescription";
 
-export { Alert, AlertTitle, AlertDescription };
+export { Alert, AlertDescription, AlertTitle };

+ 1 - 1
src/components/ui/avatar.tsx

@@ -38,4 +38,4 @@ function AvatarFallback({
   );
 }
 
-export { Avatar, AvatarImage, AvatarFallback };
+export { Avatar, AvatarFallback, AvatarImage };

+ 1 - 1
src/components/ui/card.tsx

@@ -74,4 +74,4 @@ function CardFooter({ className, ...props }: React.ComponentProps<"div">) {
   );
 }
 
-export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
+export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle };

+ 2 - 2
src/components/ui/chart.tsx

@@ -332,9 +332,9 @@ function getPayloadConfigFromPayload(config: ChartConfig, payload: unknown, key:
 
 export {
   ChartContainer,
-  ChartTooltip,
-  ChartTooltipContent,
   ChartLegend,
   ChartLegendContent,
   ChartStyle,
+  ChartTooltip,
+  ChartTooltipContent,
 };

+ 1 - 1
src/components/ui/collapsible.tsx

@@ -18,4 +18,4 @@ function CollapsibleContent({
   return <CollapsiblePrimitive.CollapsibleContent data-slot="collapsible-content" {...props} />;
 }
 
-export { Collapsible, CollapsibleTrigger, CollapsibleContent };
+export { Collapsible, CollapsibleContent, CollapsibleTrigger };

+ 3 - 3
src/components/ui/command.tsx

@@ -150,11 +150,11 @@ function CommandShortcut({ className, ...props }: React.ComponentProps<"span">)
 export {
   Command,
   CommandDialog,
-  CommandInput,
-  CommandList,
   CommandEmpty,
   CommandGroup,
+  CommandInput,
   CommandItem,
-  CommandShortcut,
+  CommandList,
   CommandSeparator,
+  CommandShortcut,
 };

+ 5 - 5
src/components/ui/drawer.tsx

@@ -113,13 +113,13 @@ function DrawerDescription({
 
 export {
   Drawer,
-  DrawerPortal,
-  DrawerOverlay,
-  DrawerTrigger,
   DrawerClose,
   DrawerContent,
-  DrawerHeader,
+  DrawerDescription,
   DrawerFooter,
+  DrawerHeader,
+  DrawerOverlay,
+  DrawerPortal,
   DrawerTitle,
-  DrawerDescription,
+  DrawerTrigger,
 };

+ 5 - 5
src/components/ui/dropdown-menu.tsx

@@ -211,18 +211,18 @@ function DropdownMenuSubContent({
 
 export {
   DropdownMenu,
-  DropdownMenuPortal,
-  DropdownMenuTrigger,
+  DropdownMenuCheckboxItem,
   DropdownMenuContent,
   DropdownMenuGroup,
-  DropdownMenuLabel,
   DropdownMenuItem,
-  DropdownMenuCheckboxItem,
+  DropdownMenuLabel,
+  DropdownMenuPortal,
   DropdownMenuRadioGroup,
   DropdownMenuRadioItem,
   DropdownMenuSeparator,
   DropdownMenuShortcut,
   DropdownMenuSub,
-  DropdownMenuSubTrigger,
   DropdownMenuSubContent,
+  DropdownMenuSubTrigger,
+  DropdownMenuTrigger,
 };

+ 1 - 1
src/components/ui/popover.tsx

@@ -39,4 +39,4 @@ function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitiv
   return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
 }
 
-export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
+export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };

+ 3 - 3
src/components/ui/sheet.tsx

@@ -121,11 +121,11 @@ function SheetDescription({
 
 export {
   Sheet,
-  SheetTrigger,
   SheetClose,
   SheetContent,
-  SheetHeader,
+  SheetDescription,
   SheetFooter,
+  SheetHeader,
   SheetTitle,
-  SheetDescription,
+  SheetTrigger,
 };

+ 1 - 1
src/components/ui/table.tsx

@@ -89,4 +89,4 @@ function TableCaption({ className, ...props }: React.ComponentProps<"caption">)
   );
 }
 
-export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };
+export { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, TableHeader, TableRow };

+ 1 - 1
src/components/ui/tabs.tsx

@@ -51,4 +51,4 @@ function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPr
   );
 }
 
-export { Tabs, TabsList, TabsTrigger, TabsContent };
+export { Tabs, TabsContent, TabsList, TabsTrigger };

+ 5 - 2
src/components/ui/tag-input.tsx

@@ -189,7 +189,10 @@ export function TagInput({
     return normalizedSuggestions.filter((s) => {
       const keywords = s.keywords?.join(" ") || "";
       const haystack = `${s.label} ${s.value} ${keywords}`.toLowerCase();
-      return haystack.includes(search) && (allowDuplicates || !value.includes(s.value));
+      return (
+        haystack.includes(search) &&
+        (allowDuplicates || !value.some((v) => v.toLowerCase() === s.value.toLowerCase()))
+      );
     });
   }, [normalizedSuggestions, inputValue, value, allowDuplicates]);
 
@@ -206,7 +209,7 @@ export function TagInput({
         return false;
       }
 
-      if (!allowDuplicates && currentTags.includes(tag)) {
+      if (!allowDuplicates && currentTags.some((t) => t.toLowerCase() === tag.toLowerCase())) {
         onInvalidTag?.(tag, "duplicate");
         return false;
       }

+ 1 - 1
src/components/ui/tooltip.tsx

@@ -54,4 +54,4 @@ function TooltipContent({
   );
 }
 
-export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
+export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };

+ 2 - 1
src/drizzle/schema.ts

@@ -122,6 +122,7 @@ export const keys = pgTable('keys', {
   limitWeeklyUsd: numeric('limit_weekly_usd', { precision: 10, scale: 2 }),
   limitMonthlyUsd: numeric('limit_monthly_usd', { precision: 10, scale: 2 }),
   limitTotalUsd: numeric('limit_total_usd', { precision: 10, scale: 2 }),
+  costResetAt: timestamp('cost_reset_at', { withTimezone: true }),
   limitConcurrentSessions: integer('limit_concurrent_sessions').default(0),
 
   // Provider group for this key (explicit; defaults to "default")
@@ -176,7 +177,7 @@ export const providers = pgTable('providers', {
   priority: integer('priority').notNull().default(0),
   groupPriorities: jsonb('group_priorities').$type<Record<string, number> | null>().default(null),
   costMultiplier: numeric('cost_multiplier', { precision: 10, scale: 4 }).default('1.0'),
-  groupTag: varchar('group_tag', { length: 50 }),
+  groupTag: varchar('group_tag', { length: 255 }),
 
   // 供应商类型:扩展支持 5 种类型
   // - claude: Anthropic 提供商(标准认证)

+ 165 - 0
src/lib/claude-code/metadata-user-id.test.ts

@@ -0,0 +1,165 @@
+import { describe, expect, test } from "vitest";
+import {
+  buildClaudeMetadataDeviceId,
+  buildClaudeMetadataUserId,
+  CLAUDE_CODE_METADATA_USER_ID_JSON_SWITCH_VERSION,
+  injectClaudeMetadataUserIdWithContext,
+  parseClaudeMetadataUserId,
+  resolveClaudeMetadataUserIdFormat,
+} from "@/lib/claude-code/metadata-user-id";
+
+describe("Claude metadata.user_id helper", () => {
+  test("解析旧格式 user_id 时应提取 sessionId 和 deviceId", () => {
+    const userId =
+      "user_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_account__session_sess_legacy_123";
+
+    expect(parseClaudeMetadataUserId(userId)).toEqual({
+      sessionId: "sess_legacy_123",
+      format: "legacy",
+      deviceId: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+      accountUuid: null,
+    });
+  });
+
+  test("解析 JSON 字符串 user_id 时应提取 sessionId 和 deviceId", () => {
+    const userId = JSON.stringify({
+      device_id: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+      account_uuid: "",
+      session_id: "sess_json_123",
+    });
+
+    expect(parseClaudeMetadataUserId(userId)).toEqual({
+      sessionId: "sess_json_123",
+      format: "json",
+      deviceId: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+      accountUuid: "",
+    });
+  });
+
+  test("解析 JSON 字符串 user_id 时应 trim sessionId", () => {
+    const userId = JSON.stringify({
+      device_id: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+      account_uuid: "",
+      session_id: "  sess_json_trimmed  ",
+    });
+
+    expect(parseClaudeMetadataUserId(userId)).toEqual({
+      sessionId: "sess_json_trimmed",
+      format: "json",
+      deviceId: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
+      accountUuid: "",
+    });
+  });
+
+  test("解析旧格式 user_id 时应 trim sessionId", () => {
+    const userId =
+      "user_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa_account__session_  sess_legacy_trimmed  ";
+
+    expect(parseClaudeMetadataUserId(userId)).toEqual({
+      sessionId: "sess_legacy_trimmed",
+      format: "legacy",
+      deviceId: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
+      accountUuid: null,
+    });
+  });
+
+  test("无法解析的 user_id 应返回空结果", () => {
+    expect(parseClaudeMetadataUserId("not-a-valid-user-id")).toEqual({
+      sessionId: null,
+      format: null,
+      deviceId: null,
+      accountUuid: null,
+    });
+  });
+
+  test("低于切换版本的 Claude Code 客户端应使用旧格式", () => {
+    const keyId = 42;
+    const sessionId = "sess_old_format";
+
+    expect(resolveClaudeMetadataUserIdFormat("claude-cli/2.1.77 (external, cli)")).toBe("legacy");
+    expect(
+      buildClaudeMetadataUserId({
+        keyId,
+        sessionId,
+        userAgent: "claude-cli/2.1.77 (external, cli)",
+      })
+    ).toBe(`user_${buildClaudeMetadataDeviceId(keyId)}_account__session_${sessionId}`);
+  });
+
+  test(`版本为 ${CLAUDE_CODE_METADATA_USER_ID_JSON_SWITCH_VERSION} 的客户端应使用 JSON 字符串`, () => {
+    const keyId = 42;
+    const sessionId = "sess_json_format";
+
+    expect(resolveClaudeMetadataUserIdFormat("claude-cli/2.1.78 (external, cli)")).toBe("json");
+    expect(
+      JSON.parse(
+        buildClaudeMetadataUserId({
+          keyId,
+          sessionId,
+          userAgent: "claude-cli/2.1.78 (external, cli)",
+        })
+      )
+    ).toEqual({
+      device_id: buildClaudeMetadataDeviceId(keyId),
+      account_uuid: "",
+      session_id: sessionId,
+    });
+  });
+
+  test("无法获取版本时应默认使用 JSON 字符串", () => {
+    const keyId = 42;
+    const sessionId = "sess_unknown_version";
+
+    expect(resolveClaudeMetadataUserIdFormat(undefined)).toBe("json");
+    expect(
+      JSON.parse(
+        buildClaudeMetadataUserId({
+          keyId,
+          sessionId,
+        })
+      )
+    ).toEqual({
+      device_id: buildClaudeMetadataDeviceId(keyId),
+      account_uuid: "",
+      session_id: sessionId,
+    });
+  });
+
+  test("注入时应保留有效 metadata.user_id", () => {
+    const message = {
+      metadata: {
+        user_id: "existing_user_id",
+        source: "client",
+      },
+    };
+
+    expect(
+      injectClaudeMetadataUserIdWithContext(message, {
+        keyId: 1,
+        sessionId: "sess_should_not_override",
+        userAgent: "claude-cli/2.1.78 (external, cli)",
+      })
+    ).toBe(message);
+  });
+
+  test("注入时遇到空白 metadata.user_id 应继续补全", () => {
+    const message = {
+      metadata: {
+        user_id: "   ",
+      },
+    };
+
+    const result = injectClaudeMetadataUserIdWithContext(message, {
+      keyId: 1,
+      sessionId: "sess_fill_blank",
+      userAgent: "claude-cli/2.1.78 (external, cli)",
+    });
+
+    expect(result).not.toBe(message);
+    expect(JSON.parse((result.metadata as Record<string, unknown>).user_id as string)).toEqual({
+      device_id: buildClaudeMetadataDeviceId(1),
+      account_uuid: "",
+      session_id: "sess_fill_blank",
+    });
+  });
+});

+ 157 - 0
src/lib/claude-code/metadata-user-id.ts

@@ -0,0 +1,157 @@
+import crypto from "node:crypto";
+import { parseUserAgent } from "@/lib/ua-parser";
+import { isVersionLess } from "@/lib/version";
+
+export const CLAUDE_CODE_METADATA_USER_ID_JSON_SWITCH_VERSION = "2.1.78";
+
+export type ClaudeMetadataUserIdFormat = "legacy" | "json";
+
+export type ClaudeMetadataUserIdParseResult = {
+  sessionId: string | null;
+  format: ClaudeMetadataUserIdFormat | null;
+  deviceId: string | null;
+  accountUuid: string | null;
+};
+
+type BuildClaudeMetadataUserIdArgs = {
+  keyId: number;
+  sessionId: string;
+  userAgent?: string | null;
+};
+
+type InjectClaudeMetadataUserIdArgs = {
+  keyId: number | null | undefined;
+  sessionId: string | null | undefined;
+  userAgent?: string | null;
+};
+
+const LEGACY_PATTERN = /^user_(.+?)_account__session_(.+)$/;
+const CLAUDE_CODE_CLIENT_TYPES = new Set(["claude-cli", "claude-vscode", "claude-cli-unknown"]);
+
+function emptyParseResult(): ClaudeMetadataUserIdParseResult {
+  return {
+    sessionId: null,
+    format: null,
+    deviceId: null,
+    accountUuid: null,
+  };
+}
+
+export function buildClaudeMetadataDeviceId(keyId: number): string {
+  return crypto.createHash("sha256").update(`claude_user_${keyId}`).digest("hex");
+}
+
+export function hasUsableClaudeMetadataUserId(userId: unknown): boolean {
+  if (typeof userId === "string") {
+    return userId.trim().length > 0;
+  }
+
+  return userId !== undefined && userId !== null;
+}
+
+export function resolveClaudeMetadataUserIdFormat(
+  userAgent?: string | null
+): ClaudeMetadataUserIdFormat {
+  const clientInfo = parseUserAgent(userAgent);
+  if (!clientInfo || !CLAUDE_CODE_CLIENT_TYPES.has(clientInfo.clientType)) {
+    return "json";
+  }
+
+  return isVersionLess(clientInfo.version, CLAUDE_CODE_METADATA_USER_ID_JSON_SWITCH_VERSION)
+    ? "legacy"
+    : "json";
+}
+
+export function parseClaudeMetadataUserId(userId: unknown): ClaudeMetadataUserIdParseResult {
+  if (typeof userId !== "string") {
+    return emptyParseResult();
+  }
+
+  const trimmed = userId.trim();
+  if (!trimmed) {
+    return emptyParseResult();
+  }
+
+  try {
+    const parsed = JSON.parse(trimmed);
+    if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
+      const parsedObj = parsed as Record<string, unknown>;
+      const sessionId =
+        typeof parsedObj.session_id === "string" ? parsedObj.session_id.trim() : null;
+
+      if (sessionId) {
+        return {
+          sessionId,
+          format: "json",
+          deviceId: typeof parsedObj.device_id === "string" ? parsedObj.device_id : null,
+          accountUuid: typeof parsedObj.account_uuid === "string" ? parsedObj.account_uuid : null,
+        };
+      }
+    }
+  } catch {
+    // Ignore JSON parse failure and fall back to legacy format.
+  }
+
+  const legacyMatch = trimmed.match(LEGACY_PATTERN);
+  if (!legacyMatch) {
+    return emptyParseResult();
+  }
+
+  const [, deviceId, rawSessionId] = legacyMatch;
+  const sessionId = rawSessionId?.trim();
+  if (!sessionId) {
+    return emptyParseResult();
+  }
+
+  return {
+    sessionId,
+    format: "legacy",
+    deviceId: deviceId || null,
+    accountUuid: null,
+  };
+}
+
+export function buildClaudeMetadataUserId(args: BuildClaudeMetadataUserIdArgs): string {
+  const deviceId = buildClaudeMetadataDeviceId(args.keyId);
+  const format = resolveClaudeMetadataUserIdFormat(args.userAgent);
+
+  if (format === "legacy") {
+    return `user_${deviceId}_account__session_${args.sessionId}`;
+  }
+
+  return JSON.stringify({
+    device_id: deviceId,
+    account_uuid: "",
+    session_id: args.sessionId,
+  });
+}
+
+export function injectClaudeMetadataUserIdWithContext(
+  message: Record<string, unknown>,
+  args: InjectClaudeMetadataUserIdArgs
+): Record<string, unknown> {
+  const existingMetadata =
+    typeof message.metadata === "object" && message.metadata !== null
+      ? (message.metadata as Record<string, unknown>)
+      : undefined;
+
+  if (hasUsableClaudeMetadataUserId(existingMetadata?.user_id)) {
+    return message;
+  }
+
+  if (args.keyId == null || !args.sessionId) {
+    return message;
+  }
+
+  return {
+    ...message,
+    metadata: {
+      ...existingMetadata,
+      user_id: buildClaudeMetadataUserId({
+        keyId: args.keyId,
+        sessionId: args.sessionId,
+        userAgent: args.userAgent,
+      }),
+    },
+  };
+}

+ 28 - 1
src/lib/client-restrictions/client-presets.test.ts

@@ -52,9 +52,36 @@ describe("client restriction presets", () => {
     ).toEqual(["claude-code-sdk-ts", "codex-cli", "my-ide"]);
   });
 
+  describe("codex-cli preset children", () => {
+    test("codex-cli preset has children", () => {
+      const codexPreset = CLIENT_RESTRICTION_PRESET_OPTIONS.find((p) => p.value === "codex-cli");
+      expect(codexPreset).toBeDefined();
+      expect(codexPreset!.children).toBeDefined();
+      expect(codexPreset!.children!.length).toBe(4);
+    });
+
+    test("codex-cli aliases include new values", () => {
+      const codexPreset = CLIENT_RESTRICTION_PRESET_OPTIONS.find((p) => p.value === "codex-cli");
+      expect(codexPreset!.aliases).toContain("codex_cli_core");
+      expect(codexPreset!.aliases).toContain("codex_exec");
+      expect(codexPreset!.aliases).toContain("codex_vscode");
+      expect(codexPreset!.aliases).toContain("Codex Desktop");
+    });
+
+    test("new codex aliases are recognized as preset values", () => {
+      expect(isPresetClientValue("codex_cli_core")).toBe(true);
+      expect(isPresetClientValue("codex_exec")).toBe(true);
+    });
+
+    test("codex-cli is in second position (after claude-code)", () => {
+      expect(CLIENT_RESTRICTION_PRESET_OPTIONS[0].value).toBe("claude-code");
+      expect(CLIENT_RESTRICTION_PRESET_OPTIONS[1].value).toBe("codex-cli");
+    });
+  });
+
   describe("child selection helpers", () => {
     const claudeCodePreset = CLIENT_RESTRICTION_PRESET_OPTIONS[0];
-    const geminiPreset = CLIENT_RESTRICTION_PRESET_OPTIONS[1];
+    const geminiPreset = CLIENT_RESTRICTION_PRESET_OPTIONS.find((p) => p.value === "gemini-cli")!;
     const allChildValues = claudeCodePreset.children!.map((c) => c.value);
 
     test("getSelectedChildren returns all children when parent value is present", () => {

+ 10 - 1
src/lib/client-restrictions/client-presets.ts

@@ -32,9 +32,18 @@ export const CLIENT_RESTRICTION_PRESET_OPTIONS: readonly ClientRestrictionPreset
       { value: "claude-code-gh-action", labelKey: "gh-action" },
     ],
   },
+  {
+    value: "codex-cli",
+    aliases: ["codex-cli", "codex_cli_core", "codex_vscode", "Codex Desktop", "codex_exec"],
+    children: [
+      { value: "codex_cli_core", labelKey: "codex-cli-core" },
+      { value: "codex_vscode", labelKey: "vscode" },
+      { value: "Codex Desktop", labelKey: "desktop" },
+      { value: "codex_exec", labelKey: "exec" },
+    ],
+  },
   { value: "gemini-cli", aliases: ["gemini-cli"] },
   { value: "factory-cli", aliases: ["factory-cli"] },
-  { value: "codex-cli", aliases: ["codex-cli", "codex_vscode", "Codex Desktop"] },
 ];
 
 const PRESET_OPTION_MAP = new Map(

+ 14 - 3
src/lib/gemini/provider-overrides.ts

@@ -1,3 +1,4 @@
+import { isGeminiGenerationEndpointPath } from "@/app/v1/_lib/proxy/endpoint-family-catalog";
 import { logger } from "@/lib/logger";
 import type { GeminiGoogleSearchPreference, ProviderType } from "@/types/provider";
 import type { GeminiGoogleSearchOverrideSpecialSetting } from "@/types/special-settings";
@@ -44,12 +45,17 @@ function removeGoogleSearchTools(tools: unknown[]): unknown[] {
  */
 export function applyGeminiGoogleSearchOverride(
   provider: GeminiProviderOverrideConfig,
-  request: Record<string, unknown>
+  request: Record<string, unknown>,
+  endpointPathname?: string | null
 ): Record<string, unknown> {
   if (provider.providerType !== "gemini" && provider.providerType !== "gemini-cli") {
     return request;
   }
 
+  if (endpointPathname && !isGeminiGenerationEndpointPath(endpointPathname)) {
+    return request;
+  }
+
   const preference = provider.geminiGoogleSearchPreference;
 
   // inherit or not set -> pass through unchanged
@@ -95,12 +101,17 @@ export function applyGeminiGoogleSearchOverride(
  */
 export function applyGeminiGoogleSearchOverrideWithAudit(
   provider: GeminiProviderOverrideConfig,
-  request: Record<string, unknown>
+  request: Record<string, unknown>,
+  endpointPathname?: string | null
 ): { request: Record<string, unknown>; audit: GeminiGoogleSearchOverrideSpecialSetting | null } {
   if (provider.providerType !== "gemini" && provider.providerType !== "gemini-cli") {
     return { request, audit: null };
   }
 
+  if (endpointPathname && !isGeminiGenerationEndpointPath(endpointPathname)) {
+    return { request, audit: null };
+  }
+
   const preference = provider.geminiGoogleSearchPreference;
 
   // inherit or not set -> pass through unchanged, no audit
@@ -125,7 +136,7 @@ export function applyGeminiGoogleSearchOverrideWithAudit(
     return { request, audit: null };
   }
 
-  const nextRequest = applyGeminiGoogleSearchOverride(provider, request);
+  const nextRequest = applyGeminiGoogleSearchOverride(provider, request, endpointPathname);
 
   const audit: GeminiGoogleSearchOverrideSpecialSetting = {
     type: "gemini_google_search_override",

+ 2 - 0
src/lib/provider-endpoint-error-codes.ts

@@ -1,3 +1,5 @@
 export const PROVIDER_ENDPOINT_CONFLICT_CODE = "PROVIDER_ENDPOINT_CONFLICT";
 export const PROVIDER_ENDPOINT_WRITE_READ_INCONSISTENCY_CODE =
   "PROVIDER_ENDPOINT_WRITE_READ_INCONSISTENCY";
+export const ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS_CODE =
+  "ENDPOINT_REFERENCED_BY_ENABLED_PROVIDERS";

+ 1 - 0
src/lib/provider-patch-contract.ts

@@ -234,6 +234,7 @@ function isValidSetValue(field: ProviderBatchPatchField, value: unknown): boolea
     case "request_timeout_non_streaming_ms":
       return typeof value === "number" && Number.isFinite(value);
     case "group_tag":
+      return typeof value === "string" && value.length <= 255;
     case "daily_reset_time":
     case "proxy_url":
     case "mcp_passthrough_url":

+ 9 - 0
src/lib/rate-limit/cost-reset-utils.ts

@@ -0,0 +1,9 @@
+export function resolveKeyCostResetAt(
+  keyCostResetAt: Date | null | undefined,
+  userCostResetAt: Date | null | undefined
+): Date | null {
+  if (!keyCostResetAt && !userCostResetAt) return null;
+  if (!keyCostResetAt) return userCostResetAt ?? null;
+  if (!userCostResetAt) return keyCostResetAt;
+  return keyCostResetAt > userCostResetAt ? keyCostResetAt : userCostResetAt;
+}

+ 6 - 6
src/lib/rate-limit/service.ts

@@ -376,9 +376,9 @@ export class RateLimitService {
                 logger.warn("[RateLimit] Missing key hash for total cost check, skip enforcement");
                 return { allowed: true };
               }
-              current = await sumKeyTotalCost(options.keyHash, 365, options?.resetAt);
+              current = await sumKeyTotalCost(options.keyHash, Infinity, options?.resetAt);
             } else if (entityType === "user") {
-              current = await sumUserTotalCost(entityId, 365, options?.resetAt);
+              current = await sumUserTotalCost(entityId, Infinity, options?.resetAt);
             } else {
               current = await sumProviderTotalCost(entityId, options?.resetAt ?? null);
             }
@@ -394,9 +394,9 @@ export class RateLimitService {
             if (!options?.keyHash) {
               return { allowed: true };
             }
-            current = await sumKeyTotalCost(options.keyHash, 365, options?.resetAt);
+            current = await sumKeyTotalCost(options.keyHash, Infinity, options?.resetAt);
           } else if (entityType === "user") {
-            current = await sumUserTotalCost(entityId, 365, options?.resetAt);
+            current = await sumUserTotalCost(entityId, Infinity, options?.resetAt);
           } else {
             current = await sumProviderTotalCost(entityId, options?.resetAt ?? null);
           }
@@ -408,9 +408,9 @@ export class RateLimitService {
             logger.warn("[RateLimit] Missing key hash for total cost check, skip enforcement");
             return { allowed: true };
           }
-          current = await sumKeyTotalCost(options.keyHash, 365, options?.resetAt);
+          current = await sumKeyTotalCost(options.keyHash, Infinity, options?.resetAt);
         } else if (entityType === "user") {
-          current = await sumUserTotalCost(entityId, 365, options?.resetAt);
+          current = await sumUserTotalCost(entityId, Infinity, options?.resetAt);
         } else {
           current = await sumProviderTotalCost(entityId, options?.resetAt ?? null);
         }

+ 90 - 0
src/lib/redis/cost-cache-cleanup.ts

@@ -16,6 +16,11 @@ export interface ClearUserCostCacheResult {
   durationMs: number;
 }
 
+export interface ClearSingleKeyCostCacheOptions {
+  keyId: number;
+  keyHash: string;
+}
+
 /**
  * Scan and delete all Redis cost-cache keys for a user and their API keys.
  *
@@ -157,3 +162,88 @@ export async function clearUserCostCache(
     durationMs: Date.now() - startTime,
   };
 }
+
+export async function clearSingleKeyCostCache(
+  options: ClearSingleKeyCostCacheOptions
+): Promise<ClearUserCostCacheResult | null> {
+  const { keyId, keyHash } = options;
+
+  const redis = getRedisClient();
+  if (!redis || redis.status !== "ready") {
+    return null;
+  }
+
+  const startTime = Date.now();
+  const scanResults = await Promise.all([
+    scanPattern(redis, `key:${keyId}:cost_*`).catch((err) => {
+      logger.warn("Failed to scan key cost pattern", { keyId, error: err });
+      return [];
+    }),
+    scanPattern(redis, `total_cost:key:${keyHash}`).catch((err) => {
+      logger.warn("Failed to scan total cost key pattern", {
+        keyHash,
+        pattern: `total_cost:key:${keyHash}`,
+        error: err instanceof Error ? err.message : String(err),
+      });
+      return [];
+    }),
+    scanPattern(redis, `total_cost:key:${keyHash}:*`).catch((err) => {
+      logger.warn("Failed to scan total cost key pattern", {
+        keyHash,
+        pattern: `total_cost:key:${keyHash}:*`,
+        error: err instanceof Error ? err.message : String(err),
+      });
+      return [];
+    }),
+    scanPattern(redis, `lease:key:${keyId}:*`).catch((err) => {
+      logger.warn("Failed to scan lease key pattern", {
+        keyId,
+        error: err instanceof Error ? err.message : String(err),
+      });
+      return [];
+    }),
+  ]);
+
+  const allCostKeys = scanResults.flat();
+  if (allCostKeys.length === 0) {
+    return {
+      costKeysDeleted: 0,
+      activeSessionsDeleted: 0,
+      durationMs: Date.now() - startTime,
+    };
+  }
+
+  const pipeline = redis.pipeline();
+  for (const key of allCostKeys) {
+    pipeline.del(key);
+  }
+
+  let results: Array<[Error | null, unknown]> | null = null;
+  try {
+    results = await pipeline.exec();
+  } catch (error) {
+    logger.warn("Redis pipeline.exec() failed during single key cost cache cleanup", {
+      keyId,
+      error,
+    });
+    return {
+      costKeysDeleted: 0,
+      activeSessionsDeleted: 0,
+      durationMs: Date.now() - startTime,
+    };
+  }
+
+  const errors = results?.filter(([err]) => err);
+  if (errors && errors.length > 0) {
+    logger.warn("Some Redis deletes failed during single key cost cache cleanup", {
+      errorCount: errors.length,
+      keyId,
+    });
+  }
+
+  return {
+    costKeysDeleted: allCostKeys.length,
+    activeSessionsDeleted: 0,
+    durationMs: Date.now() - startTime,
+  };
+}

+ 1 - 1
src/lib/redis/leaderboard-cache.ts

@@ -33,7 +33,7 @@ import {
 import type { ProviderType } from "@/types/provider";
 import { getRedisClient } from "./client";
 
-export type { LeaderboardPeriod, DateRangeParams };
+export type { DateRangeParams, LeaderboardPeriod };
 export type LeaderboardScope = "user" | "provider" | "providerCacheHitRate" | "model";
 
 type LeaderboardData =

+ 2 - 0
src/lib/security/api-key-auth-cache.ts

@@ -141,6 +141,7 @@ function hydrateKeyFromCache(keyString: string, payload: CachedKeyPayloadV1): Ke
 
   const expiresAt = parseOptionalDate(key.expiresAt);
   const deletedAt = parseOptionalDate(key.deletedAt);
+  const costResetAt = parseOptionalDate(key.costResetAt);
   if (key.expiresAt != null && !expiresAt) return null;
   if (key.deletedAt != null && !deletedAt) return null;
 
@@ -151,6 +152,7 @@ function hydrateKeyFromCache(keyString: string, payload: CachedKeyPayloadV1): Ke
     updatedAt,
     expiresAt: expiresAt === undefined ? undefined : expiresAt,
     deletedAt: deletedAt === undefined ? undefined : deletedAt,
+    costResetAt: costResetAt === undefined ? undefined : costResetAt,
   } as Key;
 }
 

+ 94 - 16
src/lib/session-manager.ts

@@ -3,6 +3,7 @@ import "server-only";
 import crypto from "node:crypto";
 import { extractCodexSessionId } from "@/app/v1/_lib/codex/session-extractor";
 import { sanitizeHeaders, sanitizeUrl } from "@/app/v1/_lib/proxy/errors";
+import { parseClaudeMetadataUserId } from "@/lib/claude-code/metadata-user-id";
 import { getEnvConfig } from "@/lib/config/env.schema";
 import { logger } from "@/lib/logger";
 import {
@@ -119,7 +120,7 @@ export class SessionManager {
    * 从客户端请求中提取 session_id(支持 metadata 或 header)
    *
    * 优先级:
-   * 1. metadata.user_id (Claude Code 主要方式,典型格式: "user_{hash}_account__session_{sessionId}")
+   * 1. metadata.user_id (Claude Code 主要方式,兼容旧字符串格式和新 JSON 字符串格式)
    * 2. metadata.session_id (备选方式)
    */
   static extractClientSessionId(
@@ -149,21 +150,13 @@ export class SessionManager {
     const metadataObj = metadata as Record<string, unknown>;
 
     // 方案 A: 从 metadata.user_id 中提取 (Claude Code 主要方式)
-    // 典型格式: "user_{hash}_account__session_{sessionId}"
-    if (typeof metadataObj.user_id === "string" && metadataObj.user_id.length > 0) {
-      const userId = metadataObj.user_id;
-      const sessionMarker = "_session_";
-      const markerIndex = userId.indexOf(sessionMarker);
-
-      if (markerIndex !== -1) {
-        const extractedSessionId = userId.substring(markerIndex + sessionMarker.length);
-        if (extractedSessionId.length > 0) {
-          logger.trace("SessionManager: Extracted session from metadata.user_id", {
-            sessionId: extractedSessionId,
-          });
-          return extractedSessionId;
-        }
-      }
+    const extractedFromUserId = parseClaudeMetadataUserId(metadataObj.user_id);
+    if (extractedFromUserId.sessionId) {
+      logger.trace("SessionManager: Extracted session from metadata.user_id", {
+        sessionId: extractedFromUserId.sessionId,
+        format: extractedFromUserId.format,
+      });
+      return extractedFromUserId.sessionId;
     }
 
     // 方案 B: 直接从 metadata.session_id 读取 (备选方案)
@@ -2033,6 +2026,91 @@ export class SessionManager {
     }
   }
 
+  static async terminateProviderSessionsBatch(providerIds: number[]): Promise<number> {
+    const uniqueProviderIds = Array.from(
+      new Set(providerIds.filter((providerId) => Number.isInteger(providerId) && providerId > 0))
+    );
+    if (uniqueProviderIds.length === 0) {
+      return 0;
+    }
+
+    const redis = getRedisClient();
+    if (!redis || redis.status !== "ready") {
+      logger.warn("SessionManager: Redis not ready, cannot terminate provider sessions");
+      return 0;
+    }
+
+    try {
+      const pipeline = redis.pipeline();
+      for (const providerId of uniqueProviderIds) {
+        pipeline.zrange(`provider:${providerId}:active_sessions`, 0, -1);
+      }
+
+      const results = await pipeline.exec();
+      if (!results) {
+        return 0;
+      }
+
+      const sessionIds = new Set<string>();
+      for (const [err, result] of results) {
+        if (err) {
+          logger.warn("SessionManager: Pipeline command error in terminateProviderSessionsBatch", {
+            error: err,
+          });
+          continue;
+        }
+        if (!Array.isArray(result)) {
+          continue;
+        }
+
+        for (const sessionId of result) {
+          if (typeof sessionId === "string" && sessionId.trim()) {
+            sessionIds.add(sessionId);
+          }
+        }
+      }
+
+      if (sessionIds.size === 0) {
+        return 0;
+      }
+
+      const terminatedCount = await SessionManager.terminateSessionsBatch([...sessionIds]);
+      logger.info("SessionManager: Terminated provider sessions batch", {
+        providerIds: uniqueProviderIds,
+        sessionCount: sessionIds.size,
+        terminatedCount,
+      });
+      return terminatedCount;
+    } catch (error) {
+      logger.error("SessionManager: Failed to terminate provider sessions batch", {
+        error,
+        providerIds: uniqueProviderIds,
+      });
+      return 0;
+    }
+  }
+
+  static async terminateStickySessionsForProviders(
+    providerIds: number[],
+    context: string
+  ): Promise<void> {
+    const uniqueProviderIds = Array.from(
+      new Set(providerIds.filter((providerId) => Number.isInteger(providerId) && providerId > 0))
+    );
+    if (uniqueProviderIds.length === 0) {
+      return;
+    }
+
+    try {
+      await SessionManager.terminateProviderSessionsBatch(uniqueProviderIds);
+    } catch (error) {
+      logger.warn(`${context}:terminate_provider_sessions_failed`, {
+        providerIds: uniqueProviderIds,
+        error: error instanceof Error ? error.message : String(error),
+      });
+    }
+  }
+
   /**
    * 批量终止 Session
    *

+ 2 - 2
src/lib/validation/schemas.ts

@@ -441,7 +441,7 @@ export const CreateProviderSchema = z
       .optional()
       .default(null),
     cost_multiplier: z.coerce.number().min(0, "成本倍率不能为负数").optional().default(1.0),
-    group_tag: z.string().max(50, "分组标签不能超过50个字符").nullable().optional(),
+    group_tag: z.string().max(255, "分组标签不能超过255个字符").nullable().optional(),
     // Codex 支持:供应商类型和模型重定向
     provider_type: z
       .enum(["claude", "claude-auth", "codex", "gemini", "gemini-cli", "openai-compatible"])
@@ -679,7 +679,7 @@ export const UpdateProviderSchema = z
       .nullable()
       .optional(),
     cost_multiplier: z.coerce.number().min(0, "成本倍率不能为负数").optional(),
-    group_tag: z.string().max(50, "分组标签不能超过50个字符").nullable().optional(),
+    group_tag: z.string().max(255, "分组标签不能超过255个字符").nullable().optional(),
     // Codex 支持:供应商类型和模型重定向
     provider_type: z
       .enum(["claude", "claude-auth", "codex", "gemini", "gemini-cli", "openai-compatible"])

+ 1 - 0
src/repository/_shared/transformers.ts

@@ -72,6 +72,7 @@ export function toKey(dbKey: any): Key {
       dbKey?.limitTotalUsd !== null && dbKey?.limitTotalUsd !== undefined
         ? parseFloat(dbKey.limitTotalUsd)
         : null,
+    costResetAt: dbKey?.costResetAt ? new Date(dbKey.costResetAt) : null,
     limitConcurrentSessions: dbKey?.limitConcurrentSessions ?? 0,
     providerGroup: dbKey?.providerGroup ?? null,
     cacheTtlPreference: dbKey?.cacheTtlPreference ?? null,

+ 55 - 4
src/repository/_shared/usage-log-filters.ts

@@ -13,6 +13,58 @@ export interface UsageLogFilterParams {
   minRetryCount?: number;
 }
 
+// 重试次数计算:
+// - 对齐前端 getRetryCount/isActualRequest:只统计“实际请求”的次数,再 - 1 得到重试次数
+// - Hedge Race(并发尝试)按 0 处理(并发不算顺序重试,且 UI 优先展示 Hedge Race)
+// - provider_chain 为空/NULL 时按 0 处理
+export const RETRY_COUNT_EXPR: SQL = sql`(
+  SELECT
+    CASE
+      WHEN COALESCE(
+        bool_or(
+          (elem->>'reason') IN (
+            'hedge_triggered',
+            'hedge_launched',
+            'hedge_winner',
+            'hedge_loser_cancelled'
+          )
+        ),
+        false
+      )
+      THEN 0
+      ELSE GREATEST(
+        COALESCE(
+          sum(
+            CASE
+              WHEN (
+                (elem->>'reason') IN (
+                  'concurrent_limit_failed',
+                  'retry_failed',
+                  'system_error',
+                  'resource_not_found',
+                  'client_error_non_retryable',
+                  'endpoint_pool_exhausted',
+                  'vendor_type_all_timeout',
+                  'client_abort',
+                  'http2_fallback'
+                )
+                OR (
+                  (elem->>'reason') IN ('request_success', 'retry_success')
+                  AND (elem->>'statusCode') IS NOT NULL
+                )
+              )
+              THEN 1
+              ELSE 0
+            END
+          ),
+          0
+        ) - 1,
+        0
+      )
+    END
+  FROM jsonb_array_elements(COALESCE(${messageRequest.providerChain}, '[]'::jsonb)) AS elem
+)`;
+
 export function buildUsageLogConditions(filters: UsageLogFilterParams): SQL[] {
   const conditions: SQL[] = [];
 
@@ -47,10 +99,9 @@ export function buildUsageLogConditions(filters: UsageLogFilterParams): SQL[] {
     conditions.push(eq(messageRequest.endpoint, filters.endpoint));
   }
 
-  if (filters.minRetryCount !== undefined) {
-    conditions.push(
-      sql`GREATEST(COALESCE(jsonb_array_length(${messageRequest.providerChain}) - 1, 0), 0) >= ${filters.minRetryCount}`
-    );
+  const minRetryCount = filters.minRetryCount ?? 0;
+  if (minRetryCount > 0) {
+    conditions.push(sql`${RETRY_COUNT_EXPR} >= ${minRetryCount}`);
   }
 
   return conditions;

+ 53 - 1
src/repository/admin-user-insights.ts

@@ -1,11 +1,19 @@
 "use server";
 
-import { and, desc, eq, gte, lt, sql } from "drizzle-orm";
+import { and, avg, count, desc, eq, gte, lt, sql, sum } from "drizzle-orm";
 import { db } from "@/drizzle/db";
 import { providers, usageLedger } from "@/drizzle/schema";
+import { Decimal, toCostDecimal } from "@/lib/utils/currency";
 import { LEDGER_BILLING_CONDITION } from "./_shared/ledger-conditions";
 import { getSystemSettings } from "./system-config";
 
+export interface UserInsightsOverviewMetrics {
+  requestCount: number;
+  totalCost: number;
+  avgResponseTime: number;
+  errorRate: number;
+}
+
 export interface AdminUserModelBreakdownItem {
   model: string | null;
   requests: number;
@@ -31,6 +39,50 @@ export interface AdminUserProviderBreakdownItem {
   cacheReadTokens: number;
 }
 
+/**
+ * Get overview metrics for a specific user within a date range.
+ */
+export async function getUserOverviewMetrics(
+  userId: number,
+  startDate?: string,
+  endDate?: string
+): Promise<UserInsightsOverviewMetrics> {
+  const conditions = [LEDGER_BILLING_CONDITION, eq(usageLedger.userId, userId)];
+
+  if (startDate) {
+    conditions.push(gte(usageLedger.createdAt, sql`${startDate}::date`));
+  }
+
+  if (endDate) {
+    conditions.push(lt(usageLedger.createdAt, sql`(${endDate}::date + INTERVAL '1 day')`));
+  }
+
+  const [result] = await db
+    .select({
+      requestCount: count(),
+      totalCost: sum(usageLedger.costUsd),
+      avgDuration: avg(usageLedger.durationMs),
+      errorCount: sql<number>`count(*) FILTER (WHERE NOT ${usageLedger.isSuccess})`,
+    })
+    .from(usageLedger)
+    .where(and(...conditions));
+
+  const costDecimal = toCostDecimal(result?.totalCost) ?? new Decimal(0);
+  const totalCost = costDecimal.toDecimalPlaces(6).toNumber();
+  const requestCount = Number(result?.requestCount || 0);
+  const errorCount = Number(result?.errorCount || 0);
+  const avgResponseTime = result?.avgDuration ? Math.round(Number(result.avgDuration)) : 0;
+  const errorRate =
+    requestCount > 0 ? parseFloat(((errorCount / requestCount) * 100).toFixed(2)) : 0;
+
+  return {
+    requestCount,
+    totalCost,
+    avgResponseTime,
+    errorRate,
+  };
+}
+
 /**
  * Get model-level usage breakdown for a specific user.
  * Groups by the billingModelSource-resolved model field and orders by cost DESC.

+ 25 - 0
src/repository/key.ts

@@ -36,6 +36,7 @@ export async function findKeyById(id: number): Promise<Key | null> {
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -67,6 +68,7 @@ export async function findKeyList(userId: number): Promise<Key[]> {
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -106,6 +108,7 @@ export async function findKeyListBatch(userIds: number[]): Promise<Map<number, K
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -149,6 +152,7 @@ export async function createKey(keyData: CreateKeyData): Promise<Key> {
     limitMonthlyUsd:
       keyData.limit_monthly_usd != null ? keyData.limit_monthly_usd.toString() : null,
     limitTotalUsd: keyData.limit_total_usd != null ? keyData.limit_total_usd.toString() : null,
+    costResetAt: keyData.cost_reset_at ?? null,
     limitConcurrentSessions: keyData.limit_concurrent_sessions,
     providerGroup: keyData.provider_group ?? null,
     cacheTtlPreference: keyData.cache_ttl_preference ?? null,
@@ -169,6 +173,7 @@ export async function createKey(keyData: CreateKeyData): Promise<Key> {
     limitWeeklyUsd: keys.limitWeeklyUsd,
     limitMonthlyUsd: keys.limitMonthlyUsd,
     limitTotalUsd: keys.limitTotalUsd,
+    costResetAt: keys.costResetAt,
     limitConcurrentSessions: keys.limitConcurrentSessions,
     providerGroup: keys.providerGroup,
     cacheTtlPreference: keys.cacheTtlPreference,
@@ -237,6 +242,7 @@ export async function updateKey(id: number, keyData: UpdateKeyData): Promise<Key
   if (keyData.limit_total_usd !== undefined)
     dbData.limitTotalUsd =
       keyData.limit_total_usd != null ? keyData.limit_total_usd.toString() : null;
+  if (keyData.cost_reset_at !== undefined) dbData.costResetAt = keyData.cost_reset_at;
   if (keyData.limit_concurrent_sessions !== undefined)
     dbData.limitConcurrentSessions = keyData.limit_concurrent_sessions;
   if (keyData.provider_group !== undefined) dbData.providerGroup = keyData.provider_group;
@@ -262,6 +268,7 @@ export async function updateKey(id: number, keyData: UpdateKeyData): Promise<Key
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -304,6 +311,7 @@ export async function findActiveKeyByUserIdAndName(
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -449,6 +457,20 @@ export async function deleteKey(id: number): Promise<boolean> {
   return result.length > 0;
 }
 
+export async function resetKeyCostResetAt(keyId: number, resetAt: Date | null): Promise<boolean> {
+  const result = await db
+    .update(keys)
+    .set({ costResetAt: resetAt, updatedAt: new Date() })
+    .where(and(eq(keys.id, keyId), isNull(keys.deletedAt)))
+    .returning({ id: keys.id, key: keys.key });
+
+  if (result.length > 0) {
+    await invalidateCachedKey(result[0].key).catch(() => {});
+  }
+
+  return result.length > 0;
+}
+
 export async function findActiveKeyByKeyString(keyString: string): Promise<Key | null> {
   const vfSaysMissing = apiKeyVacuumFilter.isDefinitelyNotPresent(keyString) === true;
 
@@ -485,6 +507,7 @@ export async function findActiveKeyByKeyString(keyString: string): Promise<Key |
       limitWeeklyUsd: keys.limitWeeklyUsd,
       limitMonthlyUsd: keys.limitMonthlyUsd,
       limitTotalUsd: keys.limitTotalUsd,
+      costResetAt: keys.costResetAt,
       limitConcurrentSessions: keys.limitConcurrentSessions,
       providerGroup: keys.providerGroup,
       cacheTtlPreference: keys.cacheTtlPreference,
@@ -592,6 +615,7 @@ export async function validateApiKeyAndGetUser(
       keyLimitWeeklyUsd: keys.limitWeeklyUsd,
       keyLimitMonthlyUsd: keys.limitMonthlyUsd,
       keyLimitTotalUsd: keys.limitTotalUsd,
+      keyCostResetAt: keys.costResetAt,
       keyLimitConcurrentSessions: keys.limitConcurrentSessions,
       keyProviderGroup: keys.providerGroup,
       keyCacheTtlPreference: keys.cacheTtlPreference,
@@ -680,6 +704,7 @@ export async function validateApiKeyAndGetUser(
     limitWeeklyUsd: row.keyLimitWeeklyUsd,
     limitMonthlyUsd: row.keyLimitMonthlyUsd,
     limitTotalUsd: row.keyLimitTotalUsd,
+    costResetAt: row.keyCostResetAt,
     limitConcurrentSessions: row.keyLimitConcurrentSessions,
     providerGroup: row.keyProviderGroup,
     cacheTtlPreference: row.keyCacheTtlPreference,

Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů