feat(数据库): 添加多模型类型支持

- 在 models 表中新增 modelType 字段,支持区分 claude 和 codex 类型
- 添加 Codex 系列模型数据(gpt-5.1-codex, gpt-5.1-codex-max, gpt-5.2-codex)
- 更新 Claude 模型的 displayName 命名
- 新增数据库迁移文件
This commit is contained in:
gaoziman 2025-12-20 01:04:02 +08:00
parent 54578ddd2d
commit c978504f4a
5 changed files with 860 additions and 2 deletions

View File

@ -0,0 +1 @@
ALTER TABLE "models" ADD COLUMN "model_type" varchar(20) DEFAULT 'claude' NOT NULL;

View File

@ -0,0 +1,798 @@
{
"id": "49959b08-d376-4e91-ac85-116b888b6d9a",
"prevId": "593838ef-b7eb-4197-aa54-b1d2912da729",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.conversations": {
"name": "conversations",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"conversation_id": {
"name": "conversation_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"title": {
"name": "title",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true,
"default": "'新对话'"
},
"summary": {
"name": "summary",
"type": "text",
"primaryKey": false,
"notNull": false
},
"model": {
"name": "model",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"tools": {
"name": "tools",
"type": "jsonb",
"primaryKey": false,
"notNull": false,
"default": "'[]'::jsonb"
},
"enable_thinking": {
"name": "enable_thinking",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"system_prompt": {
"name": "system_prompt",
"type": "text",
"primaryKey": false,
"notNull": false
},
"temperature": {
"name": "temperature",
"type": "varchar(10)",
"primaryKey": false,
"notNull": false
},
"message_count": {
"name": "message_count",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 0
},
"total_tokens": {
"name": "total_tokens",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 0
},
"is_archived": {
"name": "is_archived",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"is_pinned": {
"name": "is_pinned",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": 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()"
},
"last_message_at": {
"name": "last_message_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"conversations_conversation_id_unique": {
"name": "conversations_conversation_id_unique",
"nullsNotDistinct": false,
"columns": [
"conversation_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.messages": {
"name": "messages",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"message_id": {
"name": "message_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"conversation_id": {
"name": "conversation_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"role": {
"name": "role",
"type": "varchar(20)",
"primaryKey": false,
"notNull": true
},
"content": {
"name": "content",
"type": "text",
"primaryKey": false,
"notNull": true
},
"thinking_content": {
"name": "thinking_content",
"type": "text",
"primaryKey": false,
"notNull": false
},
"thinking_collapsed": {
"name": "thinking_collapsed",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"tool_calls": {
"name": "tool_calls",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"tool_results": {
"name": "tool_results",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"images": {
"name": "images",
"type": "jsonb",
"primaryKey": false,
"notNull": false
},
"input_tokens": {
"name": "input_tokens",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 0
},
"output_tokens": {
"name": "output_tokens",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 0
},
"status": {
"name": "status",
"type": "varchar(20)",
"primaryKey": false,
"notNull": false,
"default": "'completed'"
},
"error_message": {
"name": "error_message",
"type": "text",
"primaryKey": false,
"notNull": false
},
"feedback": {
"name": "feedback",
"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()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"messages_message_id_unique": {
"name": "messages_message_id_unique",
"nullsNotDistinct": false,
"columns": [
"message_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.models": {
"name": "models",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"model_id": {
"name": "model_id",
"type": "varchar(128)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"display_name": {
"name": "display_name",
"type": "varchar(128)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"model_type": {
"name": "model_type",
"type": "varchar(20)",
"primaryKey": false,
"notNull": true,
"default": "'claude'"
},
"supports_tools": {
"name": "supports_tools",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"supports_thinking": {
"name": "supports_thinking",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"supports_vision": {
"name": "supports_vision",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"max_tokens": {
"name": "max_tokens",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 8192
},
"context_window": {
"name": "context_window",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 200000
},
"is_enabled": {
"name": "is_enabled",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"is_default": {
"name": "is_default",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"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()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"models_model_id_unique": {
"name": "models_model_id_unique",
"nullsNotDistinct": false,
"columns": [
"model_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tools": {
"name": "tools",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"tool_id": {
"name": "tool_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"name": {
"name": "name",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"display_name": {
"name": "display_name",
"type": "varchar(128)",
"primaryKey": false,
"notNull": true
},
"description": {
"name": "description",
"type": "text",
"primaryKey": false,
"notNull": false
},
"icon": {
"name": "icon",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"input_schema": {
"name": "input_schema",
"type": "jsonb",
"primaryKey": false,
"notNull": true
},
"is_enabled": {
"name": "is_enabled",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": true
},
"is_default": {
"name": "is_default",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"sort_order": {
"name": "sort_order",
"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()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"tools_tool_id_unique": {
"name": "tools_tool_id_unique",
"nullsNotDistinct": false,
"columns": [
"tool_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.user_settings": {
"name": "user_settings",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false
},
"cch_url": {
"name": "cch_url",
"type": "varchar(512)",
"primaryKey": false,
"notNull": true,
"default": "'http://localhost:13500'"
},
"cch_api_key": {
"name": "cch_api_key",
"type": "varchar(512)",
"primaryKey": false,
"notNull": false
},
"cch_api_key_configured": {
"name": "cch_api_key_configured",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"default_model": {
"name": "default_model",
"type": "varchar(64)",
"primaryKey": false,
"notNull": false,
"default": "'claude-sonnet-4-20250514'"
},
"default_tools": {
"name": "default_tools",
"type": "jsonb",
"primaryKey": false,
"notNull": false,
"default": "'[\"web_search\",\"code_execution\",\"web_fetch\"]'::jsonb"
},
"system_prompt": {
"name": "system_prompt",
"type": "text",
"primaryKey": false,
"notNull": false
},
"temperature": {
"name": "temperature",
"type": "varchar(10)",
"primaryKey": false,
"notNull": false,
"default": "'0.7'"
},
"theme": {
"name": "theme",
"type": "varchar(20)",
"primaryKey": false,
"notNull": false,
"default": "'light'"
},
"language": {
"name": "language",
"type": "varchar(10)",
"primaryKey": false,
"notNull": false,
"default": "'zh-CN'"
},
"font_size": {
"name": "font_size",
"type": "integer",
"primaryKey": false,
"notNull": false,
"default": 15
},
"enable_thinking": {
"name": "enable_thinking",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"save_chat_history": {
"name": "save_chat_history",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"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": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"user_settings_user_id_unique": {
"name": "user_settings_user_id_unique",
"nullsNotDistinct": false,
"columns": [
"user_id"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"user_id": {
"name": "user_id",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"password": {
"name": "password",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"nickname": {
"name": "nickname",
"type": "varchar(64)",
"primaryKey": false,
"notNull": true
},
"avatar": {
"name": "avatar",
"type": "varchar(512)",
"primaryKey": false,
"notNull": false
},
"plan": {
"name": "plan",
"type": "varchar(20)",
"primaryKey": false,
"notNull": false,
"default": "'free'"
},
"status": {
"name": "status",
"type": "varchar(20)",
"primaryKey": false,
"notNull": false,
"default": "'active'"
},
"email_verified": {
"name": "email_verified",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"last_login_at": {
"name": "last_login_at",
"type": "timestamp with time zone",
"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": {
"users_user_id_unique": {
"name": "users_user_id_unique",
"nullsNotDistinct": false,
"columns": [
"user_id"
]
},
"users_email_unique": {
"name": "users_email_unique",
"nullsNotDistinct": false,
"columns": [
"email"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.verification_codes": {
"name": "verification_codes",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "serial",
"primaryKey": true,
"notNull": true
},
"email": {
"name": "email",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"code": {
"name": "code",
"type": "varchar(6)",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "varchar(20)",
"primaryKey": false,
"notNull": true
},
"expires_at": {
"name": "expires_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": true
},
"used": {
"name": "used",
"type": "boolean",
"primaryKey": false,
"notNull": false,
"default": false
},
"created_at": {
"name": "created_at",
"type": "timestamp with time zone",
"primaryKey": false,
"notNull": false,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@ -36,6 +36,13 @@
"when": 1766149111995,
"tag": "0004_lowly_red_shift",
"breakpoints": true
},
{
"idx": 5,
"version": "7",
"when": 1766155643018,
"tag": "0005_spotty_sister_grimm",
"breakpoints": true
}
]
}

View File

@ -178,6 +178,8 @@ export const models = pgTable('models', {
name: varchar('name', { length: 64 }).notNull(),
displayName: varchar('display_name', { length: 128 }).notNull(),
description: text('description'),
// 模型类型claude | codex
modelType: varchar('model_type', { length: 20 }).notNull().default('claude'),
// 模型特性
supportsTools: boolean('supports_tools').default(true),
supportsThinking: boolean('supports_thinking').default(true),

View File

@ -100,11 +100,13 @@ async function seedTools() {
// 初始化模型
async function seedModels() {
const modelsData = [
// Claude 模型
{
modelId: 'claude-sonnet-4-5-20250929',
name: 'claude-sonnet-4-5-20250929',
displayName: 'Default (recommended)',
description: '使用默认模型Sonnet 4.5$3/$15 per Mtok',
displayName: 'Sonnet',
description: 'Sonnet 4.5 - 智能与速度的最佳平衡,$3/$15 per Mtok',
modelType: 'claude',
supportsTools: true,
supportsThinking: true,
supportsVision: true,
@ -119,6 +121,7 @@ async function seedModels() {
name: 'claude-opus-4-5-20251101',
displayName: 'Opus',
description: 'Opus 4.5 - 最强大的复杂工作,$5/$25 per Mtok',
modelType: 'claude',
supportsTools: true,
supportsThinking: true,
supportsVision: true,
@ -133,6 +136,7 @@ async function seedModels() {
name: 'claude-haiku-4-5-20251001',
displayName: 'Haiku',
description: 'Haiku 4.5 - 快速回答,$1/$5 per Mtok',
modelType: 'claude',
supportsTools: true,
supportsThinking: false,
supportsVision: false,
@ -142,6 +146,52 @@ async function seedModels() {
isDefault: false,
sortOrder: 3,
},
// Codex 模型
{
modelId: 'gpt-5.1-codex',
name: 'gpt-5.1-codex',
displayName: 'Codex',
description: 'Codex 标准版 - 快速高效的代码生成',
modelType: 'codex',
supportsTools: true,
supportsThinking: false,
supportsVision: false,
maxTokens: 8192,
contextWindow: 128000,
isEnabled: true,
isDefault: false,
sortOrder: 10,
},
{
modelId: 'gpt-5.1-codex-max',
name: 'gpt-5.1-codex-max',
displayName: 'Codex Max',
description: 'Codex 增强版 - 更强的上下文理解能力',
modelType: 'codex',
supportsTools: true,
supportsThinking: false,
supportsVision: false,
maxTokens: 16384,
contextWindow: 128000,
isEnabled: true,
isDefault: false,
sortOrder: 11,
},
{
modelId: 'gpt-5.2-codex',
name: 'gpt-5.2-codex',
displayName: 'Codex Pro',
description: 'Codex 专业版 - 最新最强的代码模型',
modelType: 'codex',
supportsTools: true,
supportsThinking: false,
supportsVision: false,
maxTokens: 16384,
contextWindow: 200000,
isEnabled: true,
isDefault: false,
sortOrder: 12,
},
];
for (const model of modelsData) {