Kaynağa Gözat

feat(anthropic): add adaptive thinking override support (#758)

* feat(anthropic): add adaptive thinking override support

Add adaptive thinking as a new option in the Anthropic thinking override
settings on the provider form, supporting the new API format:
- thinking: { type: "adaptive" } + output_config: { effort: "low"|"medium"|"high"|"max" }
- Model-level targeting: apply to all models or specific models with prefix matching
- Full audit trail tracking output_config.effort changes
- Rectifier safety: skip budget rectification for adaptive mode
- DB: new JSONB column anthropic_adaptive_thinking on providers table
- i18n: all 5 locales (en, zh-CN, zh-TW, ja, ru)
- Tests: 10 override tests + 5 rectifier tests (56/56 passing)

* fix: address bugbot review comments on adaptive thinking PR

1. Add anthropic_adaptive_thinking, anthropic_max_tokens_preference, and
   anthropic_thinking_budget_preference to addProvider/editProvider type
   signatures for IDE autocomplete and compile-time safety.

2. Add .refine() validation ensuring models array is non-empty when
   modelMatchMode is "specific" in adaptive thinking config schema.

* fix(migration): use SQL NULL instead of JSONB null for default value

Change DEFAULT 'null'::jsonb to DEFAULT NULL in the migration for
anthropic_adaptive_thinking column. JSONB null and SQL NULL have
different semantics in queries and indexing.
Ding 3 gün önce
ebeveyn
işleme
129f69d4b1

+ 1 - 0
drizzle/0066_hot_mauler.sql

@@ -0,0 +1 @@
+ALTER TABLE "providers" ADD COLUMN "anthropic_adaptive_thinking" jsonb DEFAULT NULL;

+ 2983 - 0
drizzle/meta/0066_snapshot.json

@@ -0,0 +1,2983 @@
+{
+  "id": "6acf6a64-a2b1-41a1-aeda-ee47a6304e29",
+  "prevId": "5d3e46c6-0881-4776-ae60-4b8e4d06f999",
+  "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
+        },
+        "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_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
+        },
+        "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_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_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_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": {}
+        }
+      },
+      "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
+        },
+        "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_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"
+        },
+        "join_claude_pool": {
+          "name": "join_claude_pool",
+          "type": "boolean",
+          "primaryKey": false,
+          "notNull": false,
+          "default": 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
+        },
+        "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
+        },
+        "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_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": {}
+        }
+      },
+      "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
+        },
+        "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": {}
+        }
+      },
+      "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_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.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
+        },
+        "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"
+        },
+        "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_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"
+      ]
+    },
+    "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": {}
+  }
+}

+ 8 - 1
drizzle/meta/_journal.json

@@ -463,6 +463,13 @@
       "when": 1770607089556,
       "tag": "0065_stale_vertigo",
       "breakpoints": true
+    },
+    {
+      "idx": 66,
+      "version": "7",
+      "when": 1770728835628,
+      "tag": "0066_hot_mauler",
+      "breakpoints": true
     }
   ]
-}
+}

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

@@ -233,10 +233,37 @@
         "help": "Override thinking.budget_tokens in request body. Range: 1024-32000. Forces thinking.type to 'enabled' when set.",
         "options": {
           "inherit": "No override (follow client)",
-          "custom": "Custom"
+          "custom": "Custom",
+          "adaptive": "Adaptive Thinking"
         },
         "placeholder": "e.g. 10240",
         "maxOutButton": "Max Out (32000)"
+      },
+      "adaptiveThinking": {
+        "effort": {
+          "label": "Effort Level",
+          "help": "Controls depth of reasoning. Higher effort = deeper thinking.",
+          "options": {
+            "low": "Low",
+            "medium": "Medium",
+            "high": "High (Recommended)",
+            "max": "Max"
+          }
+        },
+        "modelMatchMode": {
+          "label": "Model Matching",
+          "help": "Which models should use adaptive thinking.",
+          "options": {
+            "all": "All models",
+            "specific": "Specific models only"
+          }
+        },
+        "models": {
+          "label": "Target Models",
+          "help": "Models that will use adaptive thinking. Non-matching models pass through unchanged.",
+          "placeholder": "e.g. claude-opus-4-6",
+          "addButton": "Add Model"
+        }
       }
     },
     "geminiOverrides": {

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

@@ -234,10 +234,37 @@
         "help": "リクエストボディの thinking.budget_tokens を上書きします。範囲:1024-32000。設定すると thinking.type が 'enabled' に強制されます。",
         "options": {
           "inherit": "上書きなし(クライアントに従う)",
-          "custom": "カスタム"
+          "custom": "カスタム",
+          "adaptive": "アダプティブ思考"
         },
         "placeholder": "例: 10240",
         "maxOutButton": "最大化 (32000)"
+      },
+      "adaptiveThinking": {
+        "effort": {
+          "label": "思考レベル",
+          "help": "推論の深さを制御します。高いほど深く考えます。",
+          "options": {
+            "low": "低",
+            "medium": "中",
+            "high": "高(推奨)",
+            "max": "最大"
+          }
+        },
+        "modelMatchMode": {
+          "label": "モデルマッチング",
+          "help": "アダプティブ思考を使用するモデル。",
+          "options": {
+            "all": "全モデル",
+            "specific": "特定モデルのみ"
+          }
+        },
+        "models": {
+          "label": "対象モデル",
+          "help": "アダプティブ思考を使用するモデルリスト。一致しないモデルはそのまま透過されます。",
+          "placeholder": "例: claude-opus-4-6",
+          "addButton": "モデル追加"
+        }
       }
     },
     "geminiOverrides": {

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

@@ -234,10 +234,37 @@
         "help": "Переопределяет thinking.budget_tokens в теле запроса. Диапазон: 1024-32000. При установке принудительно включает thinking.type = 'enabled'.",
         "options": {
           "inherit": "Без переопределения (следовать клиенту)",
-          "custom": "Пользовательское"
+          "custom": "Пользовательское",
+          "adaptive": "Адаптивное мышление"
         },
         "placeholder": "напр. 10240",
         "maxOutButton": "Максимум (32000)"
+      },
+      "adaptiveThinking": {
+        "effort": {
+          "label": "Уровень усилий",
+          "help": "Управляет глубиной рассуждений. Выше = глубже.",
+          "options": {
+            "low": "Низкий",
+            "medium": "Средний",
+            "high": "Высокий (Рекомендуется)",
+            "max": "Максимальный"
+          }
+        },
+        "modelMatchMode": {
+          "label": "Сопоставление моделей",
+          "help": "Какие модели используют адаптивное мышление.",
+          "options": {
+            "all": "Все модели",
+            "specific": "Только определённые модели"
+          }
+        },
+        "models": {
+          "label": "Целевые модели",
+          "help": "Модели с адаптивным мышлением. Несовпадающие модели передаются без изменений.",
+          "placeholder": "напр. claude-opus-4-6",
+          "addButton": "Добавить модель"
+        }
       }
     },
     "geminiOverrides": {

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

@@ -156,10 +156,37 @@
         "help": "覆写请求体中的 thinking.budget_tokens。范围:1024-32000。设置后会强制 thinking.type 为 'enabled'。",
         "options": {
           "inherit": "不覆写(遵循客户端)",
-          "custom": "自定义"
+          "custom": "自定义",
+          "adaptive": "自适应思考"
         },
         "placeholder": "如 10240",
         "maxOutButton": "拉满 (32000)"
+      },
+      "adaptiveThinking": {
+        "effort": {
+          "label": "思考深度",
+          "help": "控制推理深度。越高 = 思考越深入。",
+          "options": {
+            "low": "低",
+            "medium": "中",
+            "high": "高(推荐)",
+            "max": "最大"
+          }
+        },
+        "modelMatchMode": {
+          "label": "模型匹配",
+          "help": "哪些模型启用自适应思考。",
+          "options": {
+            "all": "所有模型",
+            "specific": "仅特定模型"
+          }
+        },
+        "models": {
+          "label": "目标模型",
+          "help": "启用自适应思考的模型列表。不匹配的模型保持原样透传。",
+          "placeholder": "如 claude-opus-4-6",
+          "addButton": "添加模型"
+        }
       }
     },
     "geminiOverrides": {

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

@@ -234,10 +234,37 @@
         "help": "覆寫請求體中的 thinking.budget_tokens。範圍:1024-32000。設置後會強制 thinking.type 為 'enabled'。",
         "options": {
           "inherit": "不覆寫(遵循客戶端)",
-          "custom": "自訂"
+          "custom": "自訂",
+          "adaptive": "自適應思考"
         },
         "placeholder": "如 10240",
         "maxOutButton": "拉滿 (32000)"
+      },
+      "adaptiveThinking": {
+        "effort": {
+          "label": "思考深度",
+          "help": "控制推理深度。越高 = 思考越深入。",
+          "options": {
+            "low": "低",
+            "medium": "中",
+            "high": "高(推薦)",
+            "max": "最大"
+          }
+        },
+        "modelMatchMode": {
+          "label": "模型匹配",
+          "help": "哪些模型啟用自適應思考。",
+          "options": {
+            "all": "所有模型",
+            "specific": "僅特定模型"
+          }
+        },
+        "models": {
+          "label": "目標模型",
+          "help": "啟用自適應思考的模型列表。不匹配的模型保持原樣透傳。",
+          "placeholder": "如 claude-opus-4-6",
+          "addButton": "新增模型"
+        }
       }
     },
     "geminiOverrides": {

+ 10 - 0
src/actions/providers.ts

@@ -56,6 +56,9 @@ import {
 } from "@/repository/provider-endpoints";
 import type { CacheTtlPreference } from "@/types/cache";
 import type {
+  AnthropicAdaptiveThinkingConfig,
+  AnthropicMaxTokensPreference,
+  AnthropicThinkingBudgetPreference,
   CodexParallelToolCallsPreference,
   CodexReasoningEffortPreference,
   CodexReasoningSummaryPreference,
@@ -281,6 +284,7 @@ export async function getProviders(): Promise<ProviderDisplay[]> {
         codexParallelToolCallsPreference: provider.codexParallelToolCallsPreference,
         anthropicMaxTokensPreference: provider.anthropicMaxTokensPreference,
         anthropicThinkingBudgetPreference: provider.anthropicThinkingBudgetPreference,
+        anthropicAdaptiveThinking: provider.anthropicAdaptiveThinking,
         geminiGoogleSearchPreference: provider.geminiGoogleSearchPreference,
         tpm: provider.tpm,
         rpm: provider.rpm,
@@ -468,6 +472,9 @@ export async function addProvider(data: {
   codex_reasoning_summary_preference?: CodexReasoningSummaryPreference | null;
   codex_text_verbosity_preference?: CodexTextVerbosityPreference | null;
   codex_parallel_tool_calls_preference?: CodexParallelToolCallsPreference | null;
+  anthropic_max_tokens_preference?: AnthropicMaxTokensPreference | null;
+  anthropic_thinking_budget_preference?: AnthropicThinkingBudgetPreference | null;
+  anthropic_adaptive_thinking?: AnthropicAdaptiveThinkingConfig | null;
   max_retry_attempts?: number | null;
   circuit_breaker_failure_threshold?: number;
   circuit_breaker_open_duration?: number;
@@ -635,6 +642,9 @@ export async function editProvider(
     codex_reasoning_summary_preference?: CodexReasoningSummaryPreference | null;
     codex_text_verbosity_preference?: CodexTextVerbosityPreference | null;
     codex_parallel_tool_calls_preference?: CodexParallelToolCallsPreference | null;
+    anthropic_max_tokens_preference?: AnthropicMaxTokensPreference | null;
+    anthropic_thinking_budget_preference?: AnthropicThinkingBudgetPreference | null;
+    anthropic_adaptive_thinking?: AnthropicAdaptiveThinkingConfig | null;
     max_retry_attempts?: number | null;
     circuit_breaker_failure_threshold?: number;
     circuit_breaker_open_duration?: number;

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

@@ -323,6 +323,10 @@ function ProviderFormContent({
           codex_parallel_tool_calls_preference: state.routing.codexParallelToolCallsPreference,
           anthropic_max_tokens_preference: state.routing.anthropicMaxTokensPreference,
           anthropic_thinking_budget_preference: state.routing.anthropicThinkingBudgetPreference,
+          anthropic_adaptive_thinking:
+            state.routing.anthropicThinkingBudgetPreference === "adaptive"
+              ? state.routing.anthropicAdaptiveThinking
+              : null,
           gemini_google_search_preference: state.routing.geminiGoogleSearchPreference,
           limit_5h_usd: state.rateLimit.limit5hUsd,
           limit_daily_usd: state.rateLimit.limitDailyUsd,

+ 51 - 1
src/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-context.tsx

@@ -62,6 +62,7 @@ export function createInitialState(
       anthropicMaxTokensPreference: sourceProvider?.anthropicMaxTokensPreference ?? "inherit",
       anthropicThinkingBudgetPreference:
         sourceProvider?.anthropicThinkingBudgetPreference ?? "inherit",
+      anthropicAdaptiveThinking: sourceProvider?.anthropicAdaptiveThinking ?? null,
       geminiGoogleSearchPreference: sourceProvider?.geminiGoogleSearchPreference ?? "inherit",
     },
     rateLimit: {
@@ -178,9 +179,58 @@ export function providerFormReducer(
         routing: { ...state.routing, anthropicMaxTokensPreference: action.payload },
       };
     case "SET_ANTHROPIC_THINKING_BUDGET":
+      if (action.payload === "adaptive") {
+        return {
+          ...state,
+          routing: {
+            ...state.routing,
+            anthropicThinkingBudgetPreference: "adaptive",
+            anthropicAdaptiveThinking: state.routing.anthropicAdaptiveThinking ?? {
+              effort: "high",
+              modelMatchMode: "specific",
+              models: ["claude-opus-4-6"],
+            },
+          },
+        };
+      }
       return {
         ...state,
-        routing: { ...state.routing, anthropicThinkingBudgetPreference: action.payload },
+        routing: {
+          ...state.routing,
+          anthropicThinkingBudgetPreference: action.payload,
+          anthropicAdaptiveThinking:
+            action.payload === "inherit" ? null : state.routing.anthropicAdaptiveThinking,
+        },
+      };
+    case "SET_ADAPTIVE_THINKING_EFFORT":
+      return {
+        ...state,
+        routing: {
+          ...state.routing,
+          anthropicAdaptiveThinking: state.routing.anthropicAdaptiveThinking
+            ? { ...state.routing.anthropicAdaptiveThinking, effort: action.payload }
+            : null,
+        },
+      };
+    case "SET_ADAPTIVE_THINKING_MODEL_MATCH_MODE":
+      return {
+        ...state,
+        routing: {
+          ...state.routing,
+          anthropicAdaptiveThinking: state.routing.anthropicAdaptiveThinking
+            ? { ...state.routing.anthropicAdaptiveThinking, modelMatchMode: action.payload }
+            : null,
+        },
+      };
+    case "SET_ADAPTIVE_THINKING_MODELS":
+      return {
+        ...state,
+        routing: {
+          ...state.routing,
+          anthropicAdaptiveThinking: state.routing.anthropicAdaptiveThinking
+            ? { ...state.routing.anthropicAdaptiveThinking, models: action.payload }
+            : null,
+        },
       };
     case "SET_GEMINI_GOOGLE_SEARCH":
       return {

+ 10 - 0
src/app/[locale]/settings/providers/_components/forms/provider-form/provider-form-types.ts

@@ -1,5 +1,8 @@
 import type { Dispatch } from "react";
 import type {
+  AnthropicAdaptiveThinkingConfig,
+  AnthropicAdaptiveThinkingEffort,
+  AnthropicAdaptiveThinkingModelMatchMode,
   AnthropicMaxTokensPreference,
   AnthropicThinkingBudgetPreference,
   CodexParallelToolCallsPreference,
@@ -53,6 +56,7 @@ export interface RoutingState {
   // Anthropic-specific
   anthropicMaxTokensPreference: AnthropicMaxTokensPreference;
   anthropicThinkingBudgetPreference: AnthropicThinkingBudgetPreference;
+  anthropicAdaptiveThinking: AnthropicAdaptiveThinkingConfig | null;
   // Gemini-specific
   geminiGoogleSearchPreference: GeminiGoogleSearchPreference;
 }
@@ -130,6 +134,12 @@ export type ProviderFormAction =
   | { type: "SET_CODEX_PARALLEL_TOOL_CALLS"; payload: CodexParallelToolCallsPreference }
   | { type: "SET_ANTHROPIC_MAX_TOKENS"; payload: AnthropicMaxTokensPreference }
   | { type: "SET_ANTHROPIC_THINKING_BUDGET"; payload: AnthropicThinkingBudgetPreference }
+  | { type: "SET_ADAPTIVE_THINKING_EFFORT"; payload: AnthropicAdaptiveThinkingEffort }
+  | {
+      type: "SET_ADAPTIVE_THINKING_MODEL_MATCH_MODE";
+      payload: AnthropicAdaptiveThinkingModelMatchMode;
+    }
+  | { type: "SET_ADAPTIVE_THINKING_MODELS"; payload: string[] }
   | { type: "SET_GEMINI_GOOGLE_SEARCH"; payload: GeminiGoogleSearchPreference }
   // Rate limit actions
   | { type: "SET_LIMIT_5H_USD"; payload: number | null }

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

@@ -18,6 +18,8 @@ import { TagInput } from "@/components/ui/tag-input";
 import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
 import { getProviderTypeConfig } from "@/lib/provider-type-utils";
 import type {
+  AnthropicAdaptiveThinkingEffort,
+  AnthropicAdaptiveThinkingModelMatchMode,
   CodexParallelToolCallsPreference,
   CodexReasoningEffortPreference,
   CodexReasoningSummaryPreference,
@@ -605,7 +607,9 @@ export function RoutingSection() {
                         value={
                           state.routing.anthropicThinkingBudgetPreference === "inherit"
                             ? "inherit"
-                            : "custom"
+                            : state.routing.anthropicThinkingBudgetPreference === "adaptive"
+                              ? "adaptive"
+                              : "custom"
                         }
                         onValueChange={(val) => {
                           if (val === "inherit") {
@@ -613,6 +617,11 @@ export function RoutingSection() {
                               type: "SET_ANTHROPIC_THINKING_BUDGET",
                               payload: "inherit",
                             });
+                          } else if (val === "adaptive") {
+                            dispatch({
+                              type: "SET_ANTHROPIC_THINKING_BUDGET",
+                              payload: "adaptive",
+                            });
                           } else {
                             dispatch({
                               type: "SET_ANTHROPIC_THINKING_BUDGET",
@@ -634,54 +643,56 @@ export function RoutingSection() {
                           <SelectItem value="custom">
                             {t("sections.routing.anthropicOverrides.thinkingBudget.options.custom")}
                           </SelectItem>
+                          <SelectItem value="adaptive">
+                            {t(
+                              "sections.routing.anthropicOverrides.thinkingBudget.options.adaptive"
+                            )}
+                          </SelectItem>
                         </SelectContent>
                       </Select>
-                      {state.routing.anthropicThinkingBudgetPreference !== "inherit" && (
-                        <>
-                          <Input
-                            type="number"
-                            value={
-                              state.routing.anthropicThinkingBudgetPreference === "inherit"
-                                ? ""
-                                : state.routing.anthropicThinkingBudgetPreference
-                            }
-                            onChange={(e) => {
-                              const val = e.target.value;
-                              if (val === "") {
+                      {state.routing.anthropicThinkingBudgetPreference !== "inherit" &&
+                        state.routing.anthropicThinkingBudgetPreference !== "adaptive" && (
+                          <>
+                            <Input
+                              type="number"
+                              value={state.routing.anthropicThinkingBudgetPreference}
+                              onChange={(e) => {
+                                const val = e.target.value;
+                                if (val === "") {
+                                  dispatch({
+                                    type: "SET_ANTHROPIC_THINKING_BUDGET",
+                                    payload: "inherit",
+                                  });
+                                } else {
+                                  dispatch({
+                                    type: "SET_ANTHROPIC_THINKING_BUDGET",
+                                    payload: val,
+                                  });
+                                }
+                              }}
+                              placeholder={t(
+                                "sections.routing.anthropicOverrides.thinkingBudget.placeholder"
+                              )}
+                              disabled={state.ui.isPending}
+                              min="1024"
+                              max="32000"
+                              className="flex-1"
+                            />
+                            <button
+                              type="button"
+                              onClick={() =>
                                 dispatch({
                                   type: "SET_ANTHROPIC_THINKING_BUDGET",
-                                  payload: "inherit",
-                                });
-                              } else {
-                                dispatch({
-                                  type: "SET_ANTHROPIC_THINKING_BUDGET",
-                                  payload: val,
-                                });
+                                  payload: "32000",
+                                })
                               }
-                            }}
-                            placeholder={t(
-                              "sections.routing.anthropicOverrides.thinkingBudget.placeholder"
-                            )}
-                            disabled={state.ui.isPending}
-                            min="1024"
-                            max="32000"
-                            className="flex-1"
-                          />
-                          <button
-                            type="button"
-                            onClick={() =>
-                              dispatch({
-                                type: "SET_ANTHROPIC_THINKING_BUDGET",
-                                payload: "32000",
-                              })
-                            }
-                            className="px-3 py-2 text-xs bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors whitespace-nowrap"
-                            disabled={state.ui.isPending}
-                          >
-                            {t("sections.routing.anthropicOverrides.thinkingBudget.maxOutButton")}
-                          </button>
-                        </>
-                      )}
+                              className="px-3 py-2 text-xs bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors whitespace-nowrap"
+                              disabled={state.ui.isPending}
+                            >
+                              {t("sections.routing.anthropicOverrides.thinkingBudget.maxOutButton")}
+                            </button>
+                          </>
+                        )}
                       <Info className="h-4 w-4 text-muted-foreground shrink-0" />
                     </div>
                   </TooltipTrigger>
@@ -692,6 +703,134 @@ export function RoutingSection() {
                   </TooltipContent>
                 </Tooltip>
               </SmartInputWrapper>
+
+              {state.routing.anthropicThinkingBudgetPreference === "adaptive" &&
+                state.routing.anthropicAdaptiveThinking && (
+                  <div className="ml-4 space-y-3 border-l-2 border-primary/20 pl-4">
+                    <SmartInputWrapper
+                      label={t("sections.routing.anthropicOverrides.adaptiveThinking.effort.label")}
+                    >
+                      <Tooltip>
+                        <TooltipTrigger asChild>
+                          <div className="flex gap-2 items-center">
+                            <Select
+                              value={state.routing.anthropicAdaptiveThinking.effort}
+                              onValueChange={(val) =>
+                                dispatch({
+                                  type: "SET_ADAPTIVE_THINKING_EFFORT",
+                                  payload: val as AnthropicAdaptiveThinkingEffort,
+                                })
+                              }
+                              disabled={state.ui.isPending}
+                            >
+                              <SelectTrigger className="w-40">
+                                <SelectValue />
+                              </SelectTrigger>
+                              <SelectContent>
+                                {(["low", "medium", "high", "max"] as const).map((level) => (
+                                  <SelectItem key={level} value={level}>
+                                    {t(
+                                      `sections.routing.anthropicOverrides.adaptiveThinking.effort.options.${level}`
+                                    )}
+                                  </SelectItem>
+                                ))}
+                              </SelectContent>
+                            </Select>
+                            <Info className="h-4 w-4 text-muted-foreground shrink-0" />
+                          </div>
+                        </TooltipTrigger>
+                        <TooltipContent side="top" className="max-w-xs">
+                          <p className="text-sm">
+                            {t("sections.routing.anthropicOverrides.adaptiveThinking.effort.help")}
+                          </p>
+                        </TooltipContent>
+                      </Tooltip>
+                    </SmartInputWrapper>
+
+                    <SmartInputWrapper
+                      label={t(
+                        "sections.routing.anthropicOverrides.adaptiveThinking.modelMatchMode.label"
+                      )}
+                    >
+                      <Tooltip>
+                        <TooltipTrigger asChild>
+                          <div className="flex gap-2 items-center">
+                            <Select
+                              value={state.routing.anthropicAdaptiveThinking.modelMatchMode}
+                              onValueChange={(val) =>
+                                dispatch({
+                                  type: "SET_ADAPTIVE_THINKING_MODEL_MATCH_MODE",
+                                  payload: val as AnthropicAdaptiveThinkingModelMatchMode,
+                                })
+                              }
+                              disabled={state.ui.isPending}
+                            >
+                              <SelectTrigger className="w-40">
+                                <SelectValue />
+                              </SelectTrigger>
+                              <SelectContent>
+                                <SelectItem value="all">
+                                  {t(
+                                    "sections.routing.anthropicOverrides.adaptiveThinking.modelMatchMode.options.all"
+                                  )}
+                                </SelectItem>
+                                <SelectItem value="specific">
+                                  {t(
+                                    "sections.routing.anthropicOverrides.adaptiveThinking.modelMatchMode.options.specific"
+                                  )}
+                                </SelectItem>
+                              </SelectContent>
+                            </Select>
+                            <Info className="h-4 w-4 text-muted-foreground shrink-0" />
+                          </div>
+                        </TooltipTrigger>
+                        <TooltipContent side="top" className="max-w-xs">
+                          <p className="text-sm">
+                            {t(
+                              "sections.routing.anthropicOverrides.adaptiveThinking.modelMatchMode.help"
+                            )}
+                          </p>
+                        </TooltipContent>
+                      </Tooltip>
+                    </SmartInputWrapper>
+
+                    {state.routing.anthropicAdaptiveThinking.modelMatchMode === "specific" && (
+                      <SmartInputWrapper
+                        label={t(
+                          "sections.routing.anthropicOverrides.adaptiveThinking.models.label"
+                        )}
+                      >
+                        <Tooltip>
+                          <TooltipTrigger asChild>
+                            <div className="flex gap-2 items-center">
+                              <TagInput
+                                value={state.routing.anthropicAdaptiveThinking.models}
+                                onChange={(models) =>
+                                  dispatch({
+                                    type: "SET_ADAPTIVE_THINKING_MODELS",
+                                    payload: models,
+                                  })
+                                }
+                                placeholder={t(
+                                  "sections.routing.anthropicOverrides.adaptiveThinking.models.placeholder"
+                                )}
+                                disabled={state.ui.isPending}
+                              />
+                              <Info className="h-4 w-4 text-muted-foreground shrink-0" />
+                            </div>
+                          </TooltipTrigger>
+                          <TooltipContent side="top" className="max-w-xs">
+                            <p className="text-sm">
+                              {t(
+                                "sections.routing.anthropicOverrides.adaptiveThinking.models.help"
+                              )}
+                            </p>
+                          </TooltipContent>
+                        </Tooltip>
+                      </SmartInputWrapper>
+                    )}
+                  </div>
+                )}
             </div>
           </SectionCard>
         )}

+ 18 - 0
src/app/v1/_lib/proxy/thinking-budget-rectifier.ts

@@ -61,6 +61,24 @@ export function rectifyThinkingBudget(
 
   const thinking = message.thinking as Record<string, unknown> | undefined;
   const currentThinkingType = thinking && typeof thinking.type === "string" ? thinking.type : null;
+
+  if (currentThinkingType === "adaptive") {
+    return {
+      applied: false,
+      before: {
+        maxTokens: currentMaxTokens,
+        thinkingType: currentThinkingType,
+        thinkingBudgetTokens:
+          thinking && typeof thinking.budget_tokens === "number" ? thinking.budget_tokens : null,
+      },
+      after: {
+        maxTokens: currentMaxTokens,
+        thinkingType: currentThinkingType,
+        thinkingBudgetTokens:
+          thinking && typeof thinking.budget_tokens === "number" ? thinking.budget_tokens : null,
+      },
+    };
+  }
   const currentThinkingBudgetTokens =
     thinking && typeof thinking.budget_tokens === "number" ? thinking.budget_tokens : null;
 

+ 6 - 0
src/drizzle/schema.ts

@@ -283,6 +283,12 @@ export const providers = pgTable('providers', {
   anthropicMaxTokensPreference: varchar('anthropic_max_tokens_preference', { length: 20 }),
   anthropicThinkingBudgetPreference: varchar('anthropic_thinking_budget_preference', { length: 20 }),
 
+  // Anthropic adaptive thinking config (JSONB)
+  // When anthropicThinkingBudgetPreference === "adaptive", this stores the structured config
+  anthropicAdaptiveThinking: jsonb('anthropic_adaptive_thinking')
+    .$type<{ effort: string; modelMatchMode: string; models: string[] } | null>()
+    .default(null),
+
   // Gemini (generateContent API) parameter overrides (only for gemini/gemini-cli providers)
   // - 'inherit' or null: follow client request
   // - 'enabled': force inject googleSearch tool

+ 40 - 2
src/lib/anthropic/provider-overrides.ts

@@ -1,3 +1,4 @@
+import type { AnthropicAdaptiveThinkingConfig } from "@/types/provider";
 import type { ProviderParameterOverrideSpecialSetting } from "@/types/special-settings";
 
 type AnthropicProviderOverrideConfig = {
@@ -6,6 +7,7 @@ type AnthropicProviderOverrideConfig = {
   providerType?: string;
   anthropicMaxTokensPreference?: string | null;
   anthropicThinkingBudgetPreference?: string | null;
+  anthropicAdaptiveThinking?: AnthropicAdaptiveThinkingConfig | null;
 };
 
 function isPlainObject(value: unknown): value is Record<string, unknown> {
@@ -58,6 +60,26 @@ export function applyAnthropicProviderOverrides(
     output.max_tokens = maxTokens;
   }
 
+  if (provider.anthropicThinkingBudgetPreference === "adaptive") {
+    const config = provider.anthropicAdaptiveThinking;
+    if (config) {
+      const modelId = typeof request.model === "string" ? request.model : null;
+      const isMatch =
+        config.modelMatchMode === "all" ||
+        (modelId !== null &&
+          config.models.some((m) => modelId === m || modelId.startsWith(`${m}-`)));
+      if (isMatch) {
+        ensureCloned();
+        output.thinking = { type: "adaptive" };
+        const existingOutputConfig = isPlainObject(output.output_config)
+          ? output.output_config
+          : {};
+        output.output_config = { ...existingOutputConfig, effort: config.effort };
+      }
+    }
+    return output;
+  }
+
   const thinkingBudget = normalizeNumericPreference(provider.anthropicThinkingBudgetPreference);
   if (thinkingBudget !== null) {
     ensureCloned();
@@ -94,9 +116,12 @@ export function applyAnthropicProviderOverridesWithAudit(
   }
 
   const maxTokens = normalizeNumericPreference(provider.anthropicMaxTokensPreference);
-  const thinkingBudget = normalizeNumericPreference(provider.anthropicThinkingBudgetPreference);
+  const isAdaptive = provider.anthropicThinkingBudgetPreference === "adaptive";
+  const thinkingBudget = isAdaptive
+    ? null
+    : normalizeNumericPreference(provider.anthropicThinkingBudgetPreference);
 
-  const hit = maxTokens !== null || thinkingBudget !== null;
+  const hit = maxTokens !== null || thinkingBudget !== null || isAdaptive;
 
   if (!hit) {
     return { request, audit: null };
@@ -114,6 +139,13 @@ export function applyAnthropicProviderOverridesWithAudit(
   const afterThinkingType = toAuditValue(afterThinking?.type);
   const afterThinkingBudgetTokens = toAuditValue(afterThinking?.budget_tokens);
 
+  const afterOutputConfig = isPlainObject(nextRequest.output_config)
+    ? nextRequest.output_config
+    : null;
+  const beforeOutputConfig = isPlainObject(request.output_config) ? request.output_config : null;
+  const afterOutputConfigEffort = toAuditValue(afterOutputConfig?.effort);
+  const beforeOutputConfigEffort = toAuditValue(beforeOutputConfig?.effort);
+
   const changes: ProviderParameterOverrideSpecialSetting["changes"] = [
     {
       path: "max_tokens",
@@ -133,6 +165,12 @@ export function applyAnthropicProviderOverridesWithAudit(
       after: afterThinkingBudgetTokens,
       changed: !Object.is(beforeThinkingBudgetTokens, afterThinkingBudgetTokens),
     },
+    {
+      path: "output_config.effort",
+      before: beforeOutputConfigEffort,
+      after: afterOutputConfigEffort,
+      changed: !Object.is(beforeOutputConfigEffort, afterOutputConfigEffort),
+    },
   ];
 
   const audit: ProviderParameterOverrideSpecialSetting = {

+ 37 - 0
src/lib/validation/schemas.ts

@@ -43,6 +43,7 @@ const ANTHROPIC_MAX_TOKENS_PREFERENCE = z.union([
 
 const ANTHROPIC_THINKING_BUDGET_PREFERENCE = z.union([
   z.literal("inherit"),
+  z.literal("adaptive"),
   z
     .string()
     .regex(/^\d+$/, 'thinking.budget_tokens 必须为 "inherit" 或数字字符串')
@@ -55,6 +56,19 @@ const ANTHROPIC_THINKING_BUDGET_PREFERENCE = z.union([
     ),
 ]);
 
+const ANTHROPIC_ADAPTIVE_THINKING_CONFIG = z
+  .object({
+    effort: z.enum(["low", "medium", "high", "max"]),
+    modelMatchMode: z.enum(["specific", "all"]),
+    models: z.array(z.string().min(1).max(100)).max(50),
+  })
+  .refine((data) => data.modelMatchMode !== "specific" || data.models.length > 0, {
+    message: "models must not be empty when modelMatchMode is 'specific'",
+    path: ["models"],
+  })
+  .nullable()
+  .optional();
+
 // Gemini (generateContent API) Google Search preference
 // - 'inherit': follow client request (default)
 // - 'enabled': force inject googleSearch tool
@@ -488,6 +502,7 @@ export const CreateProviderSchema = z
     anthropic_max_tokens_preference: ANTHROPIC_MAX_TOKENS_PREFERENCE.optional().default("inherit"),
     anthropic_thinking_budget_preference:
       ANTHROPIC_THINKING_BUDGET_PREFERENCE.optional().default("inherit"),
+    anthropic_adaptive_thinking: ANTHROPIC_ADAPTIVE_THINKING_CONFIG,
     gemini_google_search_preference: GEMINI_GOOGLE_SEARCH_PREFERENCE.optional().default("inherit"),
     max_retry_attempts: z.coerce
       .number()
@@ -581,6 +596,16 @@ export const CreateProviderSchema = z
   .superRefine((data, ctx) => {
     const maxTokens = data.anthropic_max_tokens_preference;
     const budget = data.anthropic_thinking_budget_preference;
+    if (budget === "adaptive") {
+      if (!data.anthropic_adaptive_thinking) {
+        ctx.addIssue({
+          code: z.ZodIssueCode.custom,
+          message: "adaptive thinking config is required when mode is adaptive",
+          path: ["anthropic_adaptive_thinking"],
+        });
+      }
+      return;
+    }
     if (maxTokens && maxTokens !== "inherit" && budget && budget !== "inherit") {
       const maxTokensNum = Number.parseInt(maxTokens, 10);
       const budgetNum = Number.parseInt(budget, 10);
@@ -686,6 +711,7 @@ export const UpdateProviderSchema = z
     codex_parallel_tool_calls_preference: CODEX_PARALLEL_TOOL_CALLS_PREFERENCE.optional(),
     anthropic_max_tokens_preference: ANTHROPIC_MAX_TOKENS_PREFERENCE.optional(),
     anthropic_thinking_budget_preference: ANTHROPIC_THINKING_BUDGET_PREFERENCE.optional(),
+    anthropic_adaptive_thinking: ANTHROPIC_ADAPTIVE_THINKING_CONFIG,
     gemini_google_search_preference: GEMINI_GOOGLE_SEARCH_PREFERENCE.optional(),
     max_retry_attempts: z.coerce
       .number()
@@ -780,6 +806,16 @@ export const UpdateProviderSchema = z
   .superRefine((data, ctx) => {
     const maxTokens = data.anthropic_max_tokens_preference;
     const budget = data.anthropic_thinking_budget_preference;
+    if (budget === "adaptive") {
+      if (!data.anthropic_adaptive_thinking) {
+        ctx.addIssue({
+          code: z.ZodIssueCode.custom,
+          message: "adaptive thinking config is required when mode is adaptive",
+          path: ["anthropic_adaptive_thinking"],
+        });
+      }
+      return;
+    }
     if (maxTokens && maxTokens !== "inherit" && budget && budget !== "inherit") {
       const maxTokensNum = Number.parseInt(maxTokens, 10);
       const budgetNum = Number.parseInt(budget, 10);
@@ -905,3 +941,4 @@ export const UpdateSystemSettingsSchema = z.object({
 
 export const anthropicMaxTokensPreferenceSchema = ANTHROPIC_MAX_TOKENS_PREFERENCE;
 export const anthropicThinkingBudgetPreferenceSchema = ANTHROPIC_THINKING_BUDGET_PREFERENCE;
+export const anthropicAdaptiveThinkingConfigSchema = ANTHROPIC_ADAPTIVE_THINKING_CONFIG;

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

@@ -126,6 +126,7 @@ export function toProvider(dbProvider: any): Provider {
     codexParallelToolCallsPreference: dbProvider?.codexParallelToolCallsPreference ?? null,
     anthropicMaxTokensPreference: dbProvider?.anthropicMaxTokensPreference ?? null,
     anthropicThinkingBudgetPreference: dbProvider?.anthropicThinkingBudgetPreference ?? null,
+    anthropicAdaptiveThinking: dbProvider?.anthropicAdaptiveThinking ?? null,
     geminiGoogleSearchPreference: dbProvider?.geminiGoogleSearchPreference ?? null,
     tpm: dbProvider?.tpm ?? null,
     rpm: dbProvider?.rpm ?? null,

+ 5 - 0
src/repository/provider.ts

@@ -66,6 +66,7 @@ export async function createProvider(providerData: CreateProviderData): Promise<
     codexParallelToolCallsPreference: providerData.codex_parallel_tool_calls_preference ?? null,
     anthropicMaxTokensPreference: providerData.anthropic_max_tokens_preference ?? null,
     anthropicThinkingBudgetPreference: providerData.anthropic_thinking_budget_preference ?? null,
+    anthropicAdaptiveThinking: providerData.anthropic_adaptive_thinking ?? null,
     geminiGoogleSearchPreference: providerData.gemini_google_search_preference ?? null,
     tpm: providerData.tpm,
     rpm: providerData.rpm,
@@ -135,6 +136,7 @@ export async function createProvider(providerData: CreateProviderData): Promise<
         codexParallelToolCallsPreference: providers.codexParallelToolCallsPreference,
         anthropicMaxTokensPreference: providers.anthropicMaxTokensPreference,
         anthropicThinkingBudgetPreference: providers.anthropicThinkingBudgetPreference,
+        anthropicAdaptiveThinking: providers.anthropicAdaptiveThinking,
         geminiGoogleSearchPreference: providers.geminiGoogleSearchPreference,
         tpm: providers.tpm,
         rpm: providers.rpm,
@@ -483,6 +485,8 @@ export async function updateProvider(
   if (providerData.anthropic_thinking_budget_preference !== undefined)
     dbData.anthropicThinkingBudgetPreference =
       providerData.anthropic_thinking_budget_preference ?? null;
+  if (providerData.anthropic_adaptive_thinking !== undefined)
+    dbData.anthropicAdaptiveThinking = providerData.anthropic_adaptive_thinking ?? null;
   if (providerData.gemini_google_search_preference !== undefined)
     dbData.geminiGoogleSearchPreference = providerData.gemini_google_search_preference ?? null;
   if (providerData.tpm !== undefined) dbData.tpm = providerData.tpm;
@@ -584,6 +588,7 @@ export async function updateProvider(
         codexParallelToolCallsPreference: providers.codexParallelToolCallsPreference,
         anthropicMaxTokensPreference: providers.anthropicMaxTokensPreference,
         anthropicThinkingBudgetPreference: providers.anthropicThinkingBudgetPreference,
+        anthropicAdaptiveThinking: providers.anthropicAdaptiveThinking,
         geminiGoogleSearchPreference: providers.geminiGoogleSearchPreference,
         tpm: providers.tpm,
         rpm: providers.rpm,

+ 15 - 1
src/types/provider.ts

@@ -33,8 +33,18 @@ export type CodexParallelToolCallsPreference = "inherit" | "true" | "false";
 // Anthropic (Messages API) parameter overrides
 // - "inherit": follow client request (default)
 // - numeric string: force override to that value
+// - "adaptive": use adaptive thinking mode (read config from anthropicAdaptiveThinking)
 export type AnthropicMaxTokensPreference = "inherit" | string;
-export type AnthropicThinkingBudgetPreference = "inherit" | string;
+export type AnthropicThinkingBudgetPreference = "inherit" | "adaptive" | string;
+
+// Anthropic adaptive thinking configuration
+export type AnthropicAdaptiveThinkingEffort = "low" | "medium" | "high" | "max";
+export type AnthropicAdaptiveThinkingModelMatchMode = "specific" | "all";
+export interface AnthropicAdaptiveThinkingConfig {
+  effort: AnthropicAdaptiveThinkingEffort;
+  modelMatchMode: AnthropicAdaptiveThinkingModelMatchMode;
+  models: string[];
+}
 
 // Gemini (generateContent API) parameter overrides
 // - "inherit": follow client request (default)
@@ -134,6 +144,7 @@ export interface Provider {
   // Anthropic (Messages API) parameter overrides (only for claude/claude-auth providers)
   anthropicMaxTokensPreference: AnthropicMaxTokensPreference | null;
   anthropicThinkingBudgetPreference: AnthropicThinkingBudgetPreference | null;
+  anthropicAdaptiveThinking: AnthropicAdaptiveThinkingConfig | null;
 
   // Gemini (generateContent API) parameter overrides (only for gemini/gemini-cli providers)
   geminiGoogleSearchPreference: GeminiGoogleSearchPreference | null;
@@ -211,6 +222,7 @@ export interface ProviderDisplay {
   codexParallelToolCallsPreference: CodexParallelToolCallsPreference | null;
   anthropicMaxTokensPreference: AnthropicMaxTokensPreference | null;
   anthropicThinkingBudgetPreference: AnthropicThinkingBudgetPreference | null;
+  anthropicAdaptiveThinking: AnthropicAdaptiveThinkingConfig | null;
   geminiGoogleSearchPreference: GeminiGoogleSearchPreference | null;
   // 废弃字段(保留向后兼容)
   tpm: number | null;
@@ -301,6 +313,7 @@ export interface CreateProviderData {
   codex_parallel_tool_calls_preference?: CodexParallelToolCallsPreference | null;
   anthropic_max_tokens_preference?: AnthropicMaxTokensPreference | null;
   anthropic_thinking_budget_preference?: AnthropicThinkingBudgetPreference | null;
+  anthropic_adaptive_thinking?: AnthropicAdaptiveThinkingConfig | null;
   gemini_google_search_preference?: GeminiGoogleSearchPreference | null;
 
   // 废弃字段(保留向后兼容)
@@ -373,6 +386,7 @@ export interface UpdateProviderData {
   codex_parallel_tool_calls_preference?: CodexParallelToolCallsPreference | null;
   anthropic_max_tokens_preference?: AnthropicMaxTokensPreference | null;
   anthropic_thinking_budget_preference?: AnthropicThinkingBudgetPreference | null;
+  anthropic_adaptive_thinking?: AnthropicAdaptiveThinkingConfig | null;
   gemini_google_search_preference?: GeminiGoogleSearchPreference | null;
 
   // 废弃字段(保留向后兼容)

+ 228 - 0
tests/unit/proxy/anthropic-provider-overrides.test.ts

@@ -772,4 +772,232 @@ describe("Anthropic Provider Overrides", () => {
       expect(budgetChange?.after).toBe(10000);
     });
   });
+
+  describe("Adaptive thinking mode", () => {
+    it("should apply adaptive thinking for matching model (all models mode)", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+        max_tokens: 8000,
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output.thinking).toEqual({ type: "adaptive" });
+      expect(output.output_config).toEqual({ effort: "high" });
+    });
+
+    it("should apply adaptive thinking for matching model (specific models mode)", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "max" as const,
+          modelMatchMode: "specific" as const,
+          models: ["claude-opus-4-6"],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output.thinking).toEqual({ type: "adaptive" });
+      expect(output.output_config).toEqual({ effort: "max" });
+    });
+
+    it("should passthrough for non-matching model (specific models mode)", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "specific" as const,
+          models: ["claude-opus-4-6"],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-sonnet-4-5",
+        messages: [],
+        max_tokens: 8000,
+        thinking: { type: "enabled", budget_tokens: 5000 },
+      };
+      const snapshot = structuredClone(input);
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output).toEqual(snapshot);
+    });
+
+    it("should preserve existing output_config properties", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "medium" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+        output_config: { some_other_field: "preserve" },
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      const outputConfig = output.output_config as Record<string, unknown>;
+      expect(outputConfig.effort).toBe("medium");
+      expect(outputConfig.some_other_field).toBe("preserve");
+    });
+
+    it("should apply adaptive with effort 'low'", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "low" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output.output_config).toEqual({ effort: "low" });
+    });
+
+    it("should remove budget_tokens from existing thinking when applying adaptive", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+        thinking: { type: "enabled", budget_tokens: 10240 },
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      const thinking = output.thinking as Record<string, unknown>;
+      expect(thinking.type).toBe("adaptive");
+      expect(thinking.budget_tokens).toBeUndefined();
+    });
+
+    it("should passthrough when adaptive config is null (defensive)", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: null,
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+        max_tokens: 8000,
+      };
+      const snapshot = structuredClone(input);
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output).toEqual(snapshot);
+    });
+
+    it("should apply adaptive + max_tokens override together", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicMaxTokensPreference: "32000",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+        max_tokens: 8000,
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output.max_tokens).toBe(32000);
+      expect(output.thinking).toEqual({ type: "adaptive" });
+      expect(output.output_config).toEqual({ effort: "high" });
+    });
+
+    it("should match model prefix (claude-opus-4-6 matches claude-opus-4-6-20250514)", () => {
+      const provider = {
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "specific" as const,
+          models: ["claude-opus-4-6"],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6-20250514",
+        messages: [],
+      };
+
+      const output = applyAnthropicProviderOverrides(provider, input);
+      expect(output.thinking).toEqual({ type: "adaptive" });
+      expect(output.output_config).toEqual({ effort: "high" });
+    });
+
+    it("should track output_config.effort in audit for adaptive mode", () => {
+      const provider = {
+        id: 1,
+        name: "adaptive-provider",
+        providerType: "claude",
+        anthropicThinkingBudgetPreference: "adaptive",
+        anthropicAdaptiveThinking: {
+          effort: "high" as const,
+          modelMatchMode: "all" as const,
+          models: [],
+        },
+      };
+
+      const input: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        messages: [],
+      };
+
+      const result = applyAnthropicProviderOverridesWithAudit(provider, input);
+      expect(result.audit?.hit).toBe(true);
+      expect(result.audit?.changed).toBe(true);
+
+      const effortChange = result.audit?.changes.find((c) => c.path === "output_config.effort");
+      expect(effortChange?.before).toBeNull();
+      expect(effortChange?.after).toBe("high");
+      expect(effortChange?.changed).toBe(true);
+
+      const thinkingTypeChange = result.audit?.changes.find((c) => c.path === "thinking.type");
+      expect(thinkingTypeChange?.after).toBe("adaptive");
+    });
+  });
 });

+ 54 - 0
tests/unit/proxy/thinking-budget-rectifier.test.ts

@@ -0,0 +1,54 @@
+import { describe, expect, it } from "vitest";
+import {
+  detectThinkingBudgetRectifierTrigger,
+  rectifyThinkingBudget,
+} from "@/app/v1/_lib/proxy/thinking-budget-rectifier";
+
+describe("ThinkingBudgetRectifier", () => {
+  describe("detectThinkingBudgetRectifierTrigger", () => {
+    it("should detect budget_tokens_too_low from typical Anthropic error", () => {
+      const trigger = detectThinkingBudgetRectifierTrigger(
+        "thinking.enabled.budget_tokens: Input should be greater than or equal to 1024"
+      );
+      expect(trigger).toBe("budget_tokens_too_low");
+    });
+
+    it("should return null for unrelated errors", () => {
+      const trigger = detectThinkingBudgetRectifierTrigger("rate limit exceeded");
+      expect(trigger).toBeNull();
+    });
+
+    it("should return null for null/undefined input", () => {
+      expect(detectThinkingBudgetRectifierTrigger(null)).toBeNull();
+      expect(detectThinkingBudgetRectifierTrigger(undefined)).toBeNull();
+    });
+  });
+
+  describe("rectifyThinkingBudget", () => {
+    it("should rectify standard thinking budget", () => {
+      const message: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        max_tokens: 4000,
+        thinking: { type: "enabled", budget_tokens: 500 },
+      };
+
+      const result = rectifyThinkingBudget(message);
+      expect(result.applied).toBe(true);
+      expect(result.after.thinkingBudgetTokens).toBe(32000);
+      expect(result.after.thinkingType).toBe("enabled");
+    });
+
+    it("should skip rectification when thinking.type is adaptive", () => {
+      const message: Record<string, unknown> = {
+        model: "claude-opus-4-6",
+        max_tokens: 8000,
+        thinking: { type: "adaptive" },
+      };
+
+      const result = rectifyThinkingBudget(message);
+      expect(result.applied).toBe(false);
+      expect(result.before.thinkingType).toBe("adaptive");
+      expect(result.after.thinkingType).toBe("adaptive");
+    });
+  });
+});