diff --git a/locales/en-US/components.json b/locales/en-US/components.json index 94f7b1d5c77f5..09a4268f526f4 100644 --- a/locales/en-US/components.json +++ b/locales/en-US/components.json @@ -111,8 +111,8 @@ } }, "Thinking": { - "thinking": "Deep in thought...", - "thought": "Deeply thought (took {{duration}} seconds)", - "thoughtWithDuration": "Deeply thought" + "thinking": "Deep Thinking...", + "thought": "Deeply Thought (in {{duration}} seconds)", + "thoughtWithDuration": "Deeply Thought" } } diff --git a/package.json b/package.json index ccc898e13574c..9d053bdd648a3 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,7 @@ "@lobehub/chat-plugins-gateway": "^1.9.0", "@lobehub/icons": "^1.73.1", "@lobehub/tts": "^1.28.0", - "@lobehub/ui": "^1.164.15", + "@lobehub/ui": "^1.165.0", "@neondatabase/serverless": "^0.10.4", "@next/third-parties": "^15.1.4", "@react-spring/web": "^9.7.5", diff --git a/src/components/ModelSelect/index.tsx b/src/components/ModelSelect/index.tsx index f83a0a35ff349..3fe5978fe9099 100644 --- a/src/components/ModelSelect/index.tsx +++ b/src/components/ModelSelect/index.tsx @@ -2,7 +2,14 @@ import { IconAvatarProps, ModelIcon, ProviderIcon } from '@lobehub/icons'; import { Avatar, Icon, Tooltip } from '@lobehub/ui'; import { Typography } from 'antd'; import { createStyles } from 'antd-style'; -import { Infinity, AtomIcon, LucideEye, LucidePaperclip, ToyBrick } from 'lucide-react'; +import { + Infinity, + AtomIcon, + LucideEye, + LucideGlobe, + LucidePaperclip, + ToyBrick, +} from 'lucide-react'; import numeral from 'numeral'; import { rgba } from 'polished'; import { FC, memo } from 'react'; @@ -14,7 +21,7 @@ import { AiProviderSourceType } from '@/types/aiProvider'; import { ChatModelCard } from '@/types/llm'; import { formatTokenNumber } from '@/utils/format'; -const useStyles = createStyles(({ css, token }) => ({ +const useStyles = createStyles(({ css, token, isDarkMode }) => ({ custom: css` width: 36px; height: 20px; @@ -41,6 +48,10 @@ const useStyles = createStyles(({ css, token }) => ({ color: ${token.geekblue}; background: ${token.geekblue1}; `, + tagCyan: css` + color: ${isDarkMode ? token.cyan7 : token.cyan10}; + background: ${isDarkMode ? token.cyan1 : token.cyan2}; + `, tagGreen: css` color: ${token.green}; background: ${token.green1}; @@ -122,6 +133,17 @@ export const ModelInfoTags = memo( )} + {model.search && ( + +
+ +
+
+ )} {typeof model.contextWindowTokens === 'number' && ( ({ container: css` width: fit-content; @@ -59,13 +61,14 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({ })); interface ThinkingProps { + citations?: CitationItem[]; content?: string; duration?: number; style?: CSSProperties; thinking?: boolean; } -const Thinking = memo(({ content, duration, thinking, style }) => { +const Thinking = memo(({ content, duration, thinking, style, citations }) => { const { t } = useTranslation(['components', 'common']); const { styles, cx } = useStyles(); @@ -135,7 +138,9 @@ const Thinking = memo(({ content, duration, thinking, style }) => }} > {typeof content === 'string' ? ( - {content} + + {content} + ) : ( content )} diff --git a/src/config/aiModels/jina.ts b/src/config/aiModels/jina.ts index 4b13ddff5e1c5..569e050335f01 100644 --- a/src/config/aiModels/jina.ts +++ b/src/config/aiModels/jina.ts @@ -4,19 +4,21 @@ const jinaChatModels: AIChatModelCard[] = [ { abilities: { reasoning: true, + search: true, }, contextWindowTokens: 1_000_000, - description: '深度搜索结合了网络搜索、阅读和推理,可进行全面调查。您可以将其视为一个代理,接受您的研究任务 - 它会进行广泛搜索并经过多次迭代,然后才能给出答案。这个过程涉及持续的研究、推理和从各个角度解决问题。这与直接从预训练数据生成答案的标准大模型以及依赖一次性表面搜索的传统 RAG 系统有着根本的不同。', + description: + '深度搜索结合了网络搜索、阅读和推理,可进行全面调查。您可以将其视为一个代理,接受您的研究任务 - 它会进行广泛搜索并经过多次迭代,然后才能给出答案。这个过程涉及持续的研究、推理和从各个角度解决问题。这与直接从预训练数据生成答案的标准大模型以及依赖一次性表面搜索的传统 RAG 系统有着根本的不同。', displayName: 'Jina DeepSearch v1', enabled: true, id: 'jina-deepsearch-v1', pricing: { input: 0.02, - output: 0.02 + output: 0.02, }, - type: 'chat' - } -] + type: 'chat', + }, +]; export const allModels = [...jinaChatModels]; diff --git a/src/config/aiModels/perplexity.ts b/src/config/aiModels/perplexity.ts index 0c6e8c6f7b81f..e5ac36e967d4e 100644 --- a/src/config/aiModels/perplexity.ts +++ b/src/config/aiModels/perplexity.ts @@ -4,6 +4,7 @@ const perplexityChatModels: AIChatModelCard[] = [ { abilities: { reasoning: true, + search: true, }, contextWindowTokens: 127_072, description: '由 DeepSeek 推理模型提供支持的新 API 产品。', @@ -16,6 +17,7 @@ const perplexityChatModels: AIChatModelCard[] = [ { abilities: { reasoning: true, + search: true, }, contextWindowTokens: 127_072, description: '由 DeepSeek 推理模型提供支持的新 API 产品。', @@ -26,6 +28,9 @@ const perplexityChatModels: AIChatModelCard[] = [ type: 'chat', }, { + abilities: { + search: true, + }, contextWindowTokens: 200_000, description: '支持搜索上下文的高级搜索产品,支持高级查询和跟进。', displayName: 'Sonar Pro', @@ -34,6 +39,9 @@ const perplexityChatModels: AIChatModelCard[] = [ type: 'chat', }, { + abilities: { + search: true, + }, contextWindowTokens: 127_072, description: '基于搜索上下文的轻量级搜索产品,比 Sonar Pro 更快、更便宜。', displayName: 'Sonar', diff --git a/src/database/client/migrations.json b/src/database/client/migrations.json index 17e4dddd3a591..543549ad41233 100644 --- a/src/database/client/migrations.json +++ b/src/database/client/migrations.json @@ -223,10 +223,7 @@ "hash": "9646161fa041354714f823d726af27247bcd6e60fa3be5698c0d69f337a5700b" }, { - "sql": [ - "DROP TABLE \"user_budgets\";", - "\nDROP TABLE \"user_subscriptions\";" - ], + "sql": ["DROP TABLE \"user_budgets\";", "\nDROP TABLE \"user_subscriptions\";"], "bps": true, "folderMillis": 1729699958471, "hash": "7dad43a2a25d1aec82124a4e53f8d82f8505c3073f23606c1dc5d2a4598eacf9" @@ -298,11 +295,18 @@ "hash": "845a692ceabbfc3caf252a97d3e19a213bc0c433df2689900135f9cfded2cf49" }, { - "sql": [ - "ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;" - ], + "sql": ["ALTER TABLE \"messages\" ADD COLUMN \"reasoning\" jsonb;"], "bps": true, "folderMillis": 1737609172353, "hash": "2cb36ae4fcdd7b7064767e04bfbb36ae34518ff4bb1b39006f2dd394d1893868" + }, + { + "sql": [ + "ALTER TABLE \"messages\" ADD COLUMN \"search\" jsonb;", + "\nALTER TABLE \"messages\" ADD COLUMN \"metadata\" jsonb;" + ], + "bps": true, + "folderMillis": 1739901891891, + "hash": "78d8fefd8c58938d7bc3da2295a73b35ce2e8d7cb2820f8e817acdb8dd5bebb2" } -] \ No newline at end of file +] diff --git a/src/database/migrations/0015_add_message_search_metadata.sql b/src/database/migrations/0015_add_message_search_metadata.sql new file mode 100644 index 0000000000000..d0be76bc6a24f --- /dev/null +++ b/src/database/migrations/0015_add_message_search_metadata.sql @@ -0,0 +1,2 @@ +ALTER TABLE "messages" ADD COLUMN "search" jsonb;--> statement-breakpoint +ALTER TABLE "messages" ADD COLUMN "metadata" jsonb; \ No newline at end of file diff --git a/src/database/migrations/meta/0015_snapshot.json b/src/database/migrations/meta/0015_snapshot.json new file mode 100644 index 0000000000000..658ff5bb04de8 --- /dev/null +++ b/src/database/migrations/meta/0015_snapshot.json @@ -0,0 +1,3616 @@ +{ + "_meta": { + "columns": {}, + "schemas": {}, + "tables": {} + }, + "dialect": "postgresql", + "enums": {}, + "id": "e133c53b-895a-48a2-9bf0-9a363fc02b7c", + "policies": {}, + "prevId": "e5491c42-8e2f-4a2d-8612-25e7052d2055", + "roles": {}, + "schemas": {}, + "sequences": {}, + "tables": { + "public.agents": { + "name": "agents", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tags": { + "name": "tags", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "background_color": { + "name": "background_color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "plugins": { + "name": "plugins", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'[]'::jsonb" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "chat_config": { + "name": "chat_config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "few_shots": { + "name": "few_shots", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "params": { + "name": "params", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'::jsonb" + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "system_role": { + "name": "system_role", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "tts": { + "name": "tts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "agents_user_id_users_id_fk": { + "name": "agents_user_id_users_id_fk", + "tableFrom": "agents", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "agents_slug_unique": { + "name": "agents_slug_unique", + "nullsNotDistinct": false, + "columns": ["slug"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agents_files": { + "name": "agents_files", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "agents_files_file_id_files_id_fk": { + "name": "agents_files_file_id_files_id_fk", + "tableFrom": "agents_files", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_files_agent_id_agents_id_fk": { + "name": "agents_files_agent_id_agents_id_fk", + "tableFrom": "agents_files", + "tableTo": "agents", + "columnsFrom": ["agent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_files_user_id_users_id_fk": { + "name": "agents_files_user_id_users_id_fk", + "tableFrom": "agents_files", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "agents_files_file_id_agent_id_user_id_pk": { + "name": "agents_files_file_id_agent_id_user_id_pk", + "columns": ["file_id", "agent_id", "user_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agents_knowledge_bases": { + "name": "agents_knowledge_bases", + "schema": "", + "columns": { + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": true + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "agents_knowledge_bases_agent_id_agents_id_fk": { + "name": "agents_knowledge_bases_agent_id_agents_id_fk", + "tableFrom": "agents_knowledge_bases", + "tableTo": "agents", + "columnsFrom": ["agent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_knowledge_bases_knowledge_base_id_knowledge_bases_id_fk": { + "name": "agents_knowledge_bases_knowledge_base_id_knowledge_bases_id_fk", + "tableFrom": "agents_knowledge_bases", + "tableTo": "knowledge_bases", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_knowledge_bases_user_id_users_id_fk": { + "name": "agents_knowledge_bases_user_id_users_id_fk", + "tableFrom": "agents_knowledge_bases", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "agents_knowledge_bases_agent_id_knowledge_base_id_pk": { + "name": "agents_knowledge_bases_agent_id_knowledge_base_id_pk", + "columns": ["agent_id", "knowledge_base_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_models": { + "name": "ai_models", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(150)", + "primaryKey": false, + "notNull": true + }, + "display_name": { + "name": "display_name", + "type": "varchar(200)", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "organization": { + "name": "organization", + "type": "varchar(100)", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "provider_id": { + "name": "provider_id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "varchar(20)", + "primaryKey": false, + "notNull": true, + "default": "'chat'" + }, + "sort": { + "name": "sort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "pricing": { + "name": "pricing", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "parameters": { + "name": "parameters", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'::jsonb" + }, + "config": { + "name": "config", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "abilities": { + "name": "abilities", + "type": "jsonb", + "primaryKey": false, + "notNull": false, + "default": "'{}'::jsonb" + }, + "context_window_tokens": { + "name": "context_window_tokens", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "released_at": { + "name": "released_at", + "type": "varchar(10)", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ai_models_user_id_users_id_fk": { + "name": "ai_models_user_id_users_id_fk", + "tableFrom": "ai_models", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ai_models_id_provider_id_user_id_pk": { + "name": "ai_models_id_provider_id_user_id_pk", + "columns": ["id", "provider_id", "user_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.ai_providers": { + "name": "ai_providers", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "varchar(64)", + "primaryKey": false, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort": { + "name": "sort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "enabled": { + "name": "enabled", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "fetch_on_client": { + "name": "fetch_on_client", + "type": "boolean", + "primaryKey": false, + "notNull": false + }, + "check_model": { + "name": "check_model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "logo": { + "name": "logo", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "key_vaults": { + "name": "key_vaults", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "source": { + "name": "source", + "type": "varchar(20)", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "ai_providers_user_id_users_id_fk": { + "name": "ai_providers_user_id_users_id_fk", + "tableFrom": "ai_providers", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "ai_providers_id_user_id_pk": { + "name": "ai_providers_id_user_id_pk", + "columns": ["id", "user_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.async_tasks": { + "name": "async_tasks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "async_tasks_user_id_users_id_fk": { + "name": "async_tasks_user_id_users_id_fk", + "tableFrom": "async_tasks", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.files": { + "name": "files", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_type": { + "name": "file_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "file_hash": { + "name": "file_hash", + "type": "varchar(64)", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "chunk_task_id": { + "name": "chunk_task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "embedding_task_id": { + "name": "embedding_task_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "files_user_id_users_id_fk": { + "name": "files_user_id_users_id_fk", + "tableFrom": "files", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "files_file_hash_global_files_hash_id_fk": { + "name": "files_file_hash_global_files_hash_id_fk", + "tableFrom": "files", + "tableTo": "global_files", + "columnsFrom": ["file_hash"], + "columnsTo": ["hash_id"], + "onDelete": "no action", + "onUpdate": "no action" + }, + "files_chunk_task_id_async_tasks_id_fk": { + "name": "files_chunk_task_id_async_tasks_id_fk", + "tableFrom": "files", + "tableTo": "async_tasks", + "columnsFrom": ["chunk_task_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "files_embedding_task_id_async_tasks_id_fk": { + "name": "files_embedding_task_id_async_tasks_id_fk", + "tableFrom": "files", + "tableTo": "async_tasks", + "columnsFrom": ["embedding_task_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.global_files": { + "name": "global_files", + "schema": "", + "columns": { + "hash_id": { + "name": "hash_id", + "type": "varchar(64)", + "primaryKey": true, + "notNull": true + }, + "file_type": { + "name": "file_type", + "type": "varchar(255)", + "primaryKey": false, + "notNull": true + }, + "size": { + "name": "size", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "url": { + "name": "url", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_base_files": { + "name": "knowledge_base_files", + "schema": "", + "columns": { + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knowledge_base_files_knowledge_base_id_knowledge_bases_id_fk": { + "name": "knowledge_base_files_knowledge_base_id_knowledge_bases_id_fk", + "tableFrom": "knowledge_base_files", + "tableTo": "knowledge_bases", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "knowledge_base_files_file_id_files_id_fk": { + "name": "knowledge_base_files_file_id_files_id_fk", + "tableFrom": "knowledge_base_files", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "knowledge_base_files_knowledge_base_id_file_id_pk": { + "name": "knowledge_base_files_knowledge_base_id_file_id_pk", + "columns": ["knowledge_base_id", "file_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.knowledge_bases": { + "name": "knowledge_bases", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "is_public": { + "name": "is_public", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "knowledge_bases_user_id_users_id_fk": { + "name": "knowledge_bases_user_id_users_id_fk", + "tableFrom": "knowledge_bases", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_chunks": { + "name": "message_chunks", + "schema": "", + "columns": { + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_chunks_message_id_messages_id_fk": { + "name": "message_chunks_message_id_messages_id_fk", + "tableFrom": "message_chunks", + "tableTo": "messages", + "columnsFrom": ["message_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "message_chunks_chunk_id_chunks_id_fk": { + "name": "message_chunks_chunk_id_chunks_id_fk", + "tableFrom": "message_chunks", + "tableTo": "chunks", + "columnsFrom": ["chunk_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "message_chunks_chunk_id_message_id_pk": { + "name": "message_chunks_chunk_id_message_id_pk", + "columns": ["chunk_id", "message_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_plugins": { + "name": "message_plugins", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tool_call_id": { + "name": "tool_call_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'default'" + }, + "api_name": { + "name": "api_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "arguments": { + "name": "arguments", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "state": { + "name": "state", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_plugins_id_messages_id_fk": { + "name": "message_plugins_id_messages_id_fk", + "tableFrom": "message_plugins", + "tableTo": "messages", + "columnsFrom": ["id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_queries": { + "name": "message_queries", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "rewrite_query": { + "name": "rewrite_query", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_query": { + "name": "user_query", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "embeddings_id": { + "name": "embeddings_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_queries_message_id_messages_id_fk": { + "name": "message_queries_message_id_messages_id_fk", + "tableFrom": "message_queries", + "tableTo": "messages", + "columnsFrom": ["message_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "message_queries_embeddings_id_embeddings_id_fk": { + "name": "message_queries_embeddings_id_embeddings_id_fk", + "tableFrom": "message_queries", + "tableTo": "embeddings", + "columnsFrom": ["embeddings_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_query_chunks": { + "name": "message_query_chunks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "query_id": { + "name": "query_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "similarity": { + "name": "similarity", + "type": "numeric(6, 5)", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_query_chunks_id_messages_id_fk": { + "name": "message_query_chunks_id_messages_id_fk", + "tableFrom": "message_query_chunks", + "tableTo": "messages", + "columnsFrom": ["id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "message_query_chunks_query_id_message_queries_id_fk": { + "name": "message_query_chunks_query_id_message_queries_id_fk", + "tableFrom": "message_query_chunks", + "tableTo": "message_queries", + "columnsFrom": ["query_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "message_query_chunks_chunk_id_chunks_id_fk": { + "name": "message_query_chunks_chunk_id_chunks_id_fk", + "tableFrom": "message_query_chunks", + "tableTo": "chunks", + "columnsFrom": ["chunk_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "message_query_chunks_chunk_id_id_query_id_pk": { + "name": "message_query_chunks_chunk_id_id_query_id_pk", + "columns": ["chunk_id", "id", "query_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_tts": { + "name": "message_tts", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content_md5": { + "name": "content_md5", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "voice": { + "name": "voice", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_tts_id_messages_id_fk": { + "name": "message_tts_id_messages_id_fk", + "tableFrom": "message_tts", + "tableTo": "messages", + "columnsFrom": ["id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "message_tts_file_id_files_id_fk": { + "name": "message_tts_file_id_files_id_fk", + "tableFrom": "message_tts", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.message_translates": { + "name": "message_translates", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "from": { + "name": "from", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "to": { + "name": "to", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "message_translates_id_messages_id_fk": { + "name": "message_translates_id_messages_id_fk", + "tableFrom": "message_translates", + "tableTo": "messages", + "columnsFrom": ["id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.messages": { + "name": "messages", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "role": { + "name": "role", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "content": { + "name": "content", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reasoning": { + "name": "reasoning", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "search": { + "name": "search", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "favorite": { + "name": "favorite", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "error": { + "name": "error", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "tools": { + "name": "tools", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "trace_id": { + "name": "trace_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "observation_id": { + "name": "observation_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "topic_id": { + "name": "topic_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "thread_id": { + "name": "thread_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "parent_id": { + "name": "parent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "quota_id": { + "name": "quota_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "messages_created_at_idx": { + "name": "messages_created_at_idx", + "columns": [ + { + "expression": "created_at", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": false, + "concurrently": false, + "method": "btree", + "with": {} + }, + "message_client_id_user_unique": { + "name": "message_client_id_user_unique", + "columns": [ + { + "expression": "client_id", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "messages_user_id_users_id_fk": { + "name": "messages_user_id_users_id_fk", + "tableFrom": "messages", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_session_id_sessions_id_fk": { + "name": "messages_session_id_sessions_id_fk", + "tableFrom": "messages", + "tableTo": "sessions", + "columnsFrom": ["session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_topic_id_topics_id_fk": { + "name": "messages_topic_id_topics_id_fk", + "tableFrom": "messages", + "tableTo": "topics", + "columnsFrom": ["topic_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_thread_id_threads_id_fk": { + "name": "messages_thread_id_threads_id_fk", + "tableFrom": "messages", + "tableTo": "threads", + "columnsFrom": ["thread_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_parent_id_messages_id_fk": { + "name": "messages_parent_id_messages_id_fk", + "tableFrom": "messages", + "tableTo": "messages", + "columnsFrom": ["parent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "messages_quota_id_messages_id_fk": { + "name": "messages_quota_id_messages_id_fk", + "tableFrom": "messages", + "tableTo": "messages", + "columnsFrom": ["quota_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "messages_agent_id_agents_id_fk": { + "name": "messages_agent_id_agents_id_fk", + "tableFrom": "messages", + "tableTo": "agents", + "columnsFrom": ["agent_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.messages_files": { + "name": "messages_files", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "message_id": { + "name": "message_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "messages_files_file_id_files_id_fk": { + "name": "messages_files_file_id_files_id_fk", + "tableFrom": "messages_files", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "messages_files_message_id_messages_id_fk": { + "name": "messages_files_message_id_messages_id_fk", + "tableFrom": "messages_files", + "tableTo": "messages", + "columnsFrom": ["message_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "messages_files_file_id_message_id_pk": { + "name": "messages_files_file_id_message_id_pk", + "columns": ["file_id", "message_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.nextauth_accounts": { + "name": "nextauth_accounts", + "schema": "", + "columns": { + "access_token": { + "name": "access_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "expires_at": { + "name": "expires_at", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "id_token": { + "name": "id_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "provider": { + "name": "provider", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "refresh_token": { + "name": "refresh_token", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "scope": { + "name": "scope", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "session_state": { + "name": "session_state", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "token_type": { + "name": "token_type", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "nextauth_accounts_userId_users_id_fk": { + "name": "nextauth_accounts_userId_users_id_fk", + "tableFrom": "nextauth_accounts", + "tableTo": "users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "nextauth_accounts_provider_providerAccountId_pk": { + "name": "nextauth_accounts_provider_providerAccountId_pk", + "columns": ["provider", "providerAccountId"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.nextauth_authenticators": { + "name": "nextauth_authenticators", + "schema": "", + "columns": { + "counter": { + "name": "counter", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "credentialBackedUp": { + "name": "credentialBackedUp", + "type": "boolean", + "primaryKey": false, + "notNull": true + }, + "credentialDeviceType": { + "name": "credentialDeviceType", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credentialID": { + "name": "credentialID", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "credentialPublicKey": { + "name": "credentialPublicKey", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "providerAccountId": { + "name": "providerAccountId", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "transports": { + "name": "transports", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "nextauth_authenticators_userId_users_id_fk": { + "name": "nextauth_authenticators_userId_users_id_fk", + "tableFrom": "nextauth_authenticators", + "tableTo": "users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "nextauth_authenticators_userId_credentialID_pk": { + "name": "nextauth_authenticators_userId_credentialID_pk", + "columns": ["userId", "credentialID"] + } + }, + "uniqueConstraints": { + "nextauth_authenticators_credentialID_unique": { + "name": "nextauth_authenticators_credentialID_unique", + "nullsNotDistinct": false, + "columns": ["credentialID"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.nextauth_sessions": { + "name": "nextauth_sessions", + "schema": "", + "columns": { + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "sessionToken": { + "name": "sessionToken", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "userId": { + "name": "userId", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "nextauth_sessions_userId_users_id_fk": { + "name": "nextauth_sessions_userId_users_id_fk", + "tableFrom": "nextauth_sessions", + "tableTo": "users", + "columnsFrom": ["userId"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.nextauth_verificationtokens": { + "name": "nextauth_verificationtokens", + "schema": "", + "columns": { + "expires": { + "name": "expires", + "type": "timestamp", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "token": { + "name": "token", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": { + "nextauth_verificationtokens_identifier_token_pk": { + "name": "nextauth_verificationtokens_identifier_token_pk", + "columns": ["identifier", "token"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.chunks": { + "name": "chunks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "abstract": { + "name": "abstract", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "index": { + "name": "index", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "chunks_user_id_users_id_fk": { + "name": "chunks_user_id_users_id_fk", + "tableFrom": "chunks", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.embeddings": { + "name": "embeddings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "embeddings": { + "name": "embeddings", + "type": "vector(1024)", + "primaryKey": false, + "notNull": false + }, + "model": { + "name": "model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "embeddings_chunk_id_chunks_id_fk": { + "name": "embeddings_chunk_id_chunks_id_fk", + "tableFrom": "embeddings", + "tableTo": "chunks", + "columnsFrom": ["chunk_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "embeddings_user_id_users_id_fk": { + "name": "embeddings_user_id_users_id_fk", + "tableFrom": "embeddings", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "embeddings_chunk_id_unique": { + "name": "embeddings_chunk_id_unique", + "nullsNotDistinct": false, + "columns": ["chunk_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.unstructured_chunks": { + "name": "unstructured_chunks", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "uuid", + "primaryKey": true, + "notNull": true, + "default": "gen_random_uuid()" + }, + "text": { + "name": "text", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "index": { + "name": "index", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "parent_id": { + "name": "parent_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "composite_id": { + "name": "composite_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "file_id": { + "name": "file_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "unstructured_chunks_composite_id_chunks_id_fk": { + "name": "unstructured_chunks_composite_id_chunks_id_fk", + "tableFrom": "unstructured_chunks", + "tableTo": "chunks", + "columnsFrom": ["composite_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "unstructured_chunks_user_id_users_id_fk": { + "name": "unstructured_chunks_user_id_users_id_fk", + "tableFrom": "unstructured_chunks", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "unstructured_chunks_file_id_files_id_fk": { + "name": "unstructured_chunks_file_id_files_id_fk", + "tableFrom": "unstructured_chunks", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rag_eval_dataset_records": { + "name": "rag_eval_dataset_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "rag_eval_dataset_records_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "dataset_id": { + "name": "dataset_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "ideal": { + "name": "ideal", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "question": { + "name": "question", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "reference_files": { + "name": "reference_files", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "rag_eval_dataset_records_dataset_id_rag_eval_datasets_id_fk": { + "name": "rag_eval_dataset_records_dataset_id_rag_eval_datasets_id_fk", + "tableFrom": "rag_eval_dataset_records", + "tableTo": "rag_eval_datasets", + "columnsFrom": ["dataset_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_dataset_records_user_id_users_id_fk": { + "name": "rag_eval_dataset_records_user_id_users_id_fk", + "tableFrom": "rag_eval_dataset_records", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rag_eval_datasets": { + "name": "rag_eval_datasets", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "rag_eval_datasets_id_seq", + "schema": "public", + "increment": "1", + "startWith": "30000", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "rag_eval_datasets_knowledge_base_id_knowledge_bases_id_fk": { + "name": "rag_eval_datasets_knowledge_base_id_knowledge_bases_id_fk", + "tableFrom": "rag_eval_datasets", + "tableTo": "knowledge_bases", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_datasets_user_id_users_id_fk": { + "name": "rag_eval_datasets_user_id_users_id_fk", + "tableFrom": "rag_eval_datasets", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rag_eval_evaluations": { + "name": "rag_eval_evaluations", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "rag_eval_evaluations_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "eval_records_url": { + "name": "eval_records_url", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "dataset_id": { + "name": "dataset_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "knowledge_base_id": { + "name": "knowledge_base_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "language_model": { + "name": "language_model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "rag_eval_evaluations_dataset_id_rag_eval_datasets_id_fk": { + "name": "rag_eval_evaluations_dataset_id_rag_eval_datasets_id_fk", + "tableFrom": "rag_eval_evaluations", + "tableTo": "rag_eval_datasets", + "columnsFrom": ["dataset_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_evaluations_knowledge_base_id_knowledge_bases_id_fk": { + "name": "rag_eval_evaluations_knowledge_base_id_knowledge_bases_id_fk", + "tableFrom": "rag_eval_evaluations", + "tableTo": "knowledge_bases", + "columnsFrom": ["knowledge_base_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_evaluations_user_id_users_id_fk": { + "name": "rag_eval_evaluations_user_id_users_id_fk", + "tableFrom": "rag_eval_evaluations", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.rag_eval_evaluation_records": { + "name": "rag_eval_evaluation_records", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "integer", + "primaryKey": true, + "notNull": true, + "identity": { + "type": "always", + "name": "rag_eval_evaluation_records_id_seq", + "schema": "public", + "increment": "1", + "startWith": "1", + "minValue": "1", + "maxValue": "2147483647", + "cache": "1", + "cycle": false + } + }, + "question": { + "name": "question", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "answer": { + "name": "answer", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "context": { + "name": "context", + "type": "text[]", + "primaryKey": false, + "notNull": false + }, + "ideal": { + "name": "ideal", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "error": { + "name": "error", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "language_model": { + "name": "language_model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "embedding_model": { + "name": "embedding_model", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "question_embedding_id": { + "name": "question_embedding_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "duration": { + "name": "duration", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "dataset_record_id": { + "name": "dataset_record_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "evaluation_id": { + "name": "evaluation_id", + "type": "integer", + "primaryKey": false, + "notNull": true + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "rag_eval_evaluation_records_question_embedding_id_embeddings_id_fk": { + "name": "rag_eval_evaluation_records_question_embedding_id_embeddings_id_fk", + "tableFrom": "rag_eval_evaluation_records", + "tableTo": "embeddings", + "columnsFrom": ["question_embedding_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "rag_eval_evaluation_records_dataset_record_id_rag_eval_dataset_records_id_fk": { + "name": "rag_eval_evaluation_records_dataset_record_id_rag_eval_dataset_records_id_fk", + "tableFrom": "rag_eval_evaluation_records", + "tableTo": "rag_eval_dataset_records", + "columnsFrom": ["dataset_record_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_evaluation_records_evaluation_id_rag_eval_evaluations_id_fk": { + "name": "rag_eval_evaluation_records_evaluation_id_rag_eval_evaluations_id_fk", + "tableFrom": "rag_eval_evaluation_records", + "tableTo": "rag_eval_evaluations", + "columnsFrom": ["evaluation_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "rag_eval_evaluation_records_user_id_users_id_fk": { + "name": "rag_eval_evaluation_records_user_id_users_id_fk", + "tableFrom": "rag_eval_evaluation_records", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.agents_to_sessions": { + "name": "agents_to_sessions", + "schema": "", + "columns": { + "agent_id": { + "name": "agent_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "agents_to_sessions_agent_id_agents_id_fk": { + "name": "agents_to_sessions_agent_id_agents_id_fk", + "tableFrom": "agents_to_sessions", + "tableTo": "agents", + "columnsFrom": ["agent_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "agents_to_sessions_session_id_sessions_id_fk": { + "name": "agents_to_sessions_session_id_sessions_id_fk", + "tableFrom": "agents_to_sessions", + "tableTo": "sessions", + "columnsFrom": ["session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "agents_to_sessions_agent_id_session_id_pk": { + "name": "agents_to_sessions_agent_id_session_id_pk", + "columns": ["agent_id", "session_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.file_chunks": { + "name": "file_chunks", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "varchar", + "primaryKey": false, + "notNull": false + }, + "chunk_id": { + "name": "chunk_id", + "type": "uuid", + "primaryKey": false, + "notNull": false + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "file_chunks_file_id_files_id_fk": { + "name": "file_chunks_file_id_files_id_fk", + "tableFrom": "file_chunks", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "file_chunks_chunk_id_chunks_id_fk": { + "name": "file_chunks_chunk_id_chunks_id_fk", + "tableFrom": "file_chunks", + "tableTo": "chunks", + "columnsFrom": ["chunk_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "file_chunks_file_id_chunk_id_pk": { + "name": "file_chunks_file_id_chunk_id_pk", + "columns": ["file_id", "chunk_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.files_to_sessions": { + "name": "files_to_sessions", + "schema": "", + "columns": { + "file_id": { + "name": "file_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": true + } + }, + "indexes": {}, + "foreignKeys": { + "files_to_sessions_file_id_files_id_fk": { + "name": "files_to_sessions_file_id_files_id_fk", + "tableFrom": "files_to_sessions", + "tableTo": "files", + "columnsFrom": ["file_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "files_to_sessions_session_id_sessions_id_fk": { + "name": "files_to_sessions_session_id_sessions_id_fk", + "tableFrom": "files_to_sessions", + "tableTo": "sessions", + "columnsFrom": ["session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "files_to_sessions_file_id_session_id_pk": { + "name": "files_to_sessions_file_id_session_id_pk", + "columns": ["file_id", "session_id"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.session_groups": { + "name": "session_groups", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "name": { + "name": "name", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "sort": { + "name": "sort", + "type": "integer", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "session_groups_user_id_users_id_fk": { + "name": "session_groups_user_id_users_id_fk", + "tableFrom": "session_groups", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "session_group_client_id_user_unique": { + "name": "session_group_client_id_user_unique", + "nullsNotDistinct": false, + "columns": ["client_id", "user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.sessions": { + "name": "sessions", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "slug": { + "name": "slug", + "type": "varchar(100)", + "primaryKey": false, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "description": { + "name": "description", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "background_color": { + "name": "background_color", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'agent'" + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "group_id": { + "name": "group_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "pinned": { + "name": "pinned", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": { + "slug_user_id_unique": { + "name": "slug_user_id_unique", + "columns": [ + { + "expression": "slug", + "isExpression": false, + "asc": true, + "nulls": "last" + }, + { + "expression": "user_id", + "isExpression": false, + "asc": true, + "nulls": "last" + } + ], + "isUnique": true, + "concurrently": false, + "method": "btree", + "with": {} + } + }, + "foreignKeys": { + "sessions_user_id_users_id_fk": { + "name": "sessions_user_id_users_id_fk", + "tableFrom": "sessions", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "sessions_group_id_session_groups_id_fk": { + "name": "sessions_group_id_session_groups_id_fk", + "tableFrom": "sessions", + "tableTo": "session_groups", + "columnsFrom": ["group_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "sessions_client_id_user_id_unique": { + "name": "sessions_client_id_user_id_unique", + "nullsNotDistinct": false, + "columns": ["client_id", "user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.threads": { + "name": "threads", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "status": { + "name": "status", + "type": "text", + "primaryKey": false, + "notNull": false, + "default": "'active'" + }, + "topic_id": { + "name": "topic_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "source_message_id": { + "name": "source_message_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "parent_thread_id": { + "name": "parent_thread_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "last_active_at": { + "name": "last_active_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false, + "default": "now()" + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "threads_topic_id_topics_id_fk": { + "name": "threads_topic_id_topics_id_fk", + "tableFrom": "threads", + "tableTo": "topics", + "columnsFrom": ["topic_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "threads_parent_thread_id_threads_id_fk": { + "name": "threads_parent_thread_id_threads_id_fk", + "tableFrom": "threads", + "tableTo": "threads", + "columnsFrom": ["parent_thread_id"], + "columnsTo": ["id"], + "onDelete": "set null", + "onUpdate": "no action" + }, + "threads_user_id_users_id_fk": { + "name": "threads_user_id_users_id_fk", + "tableFrom": "threads", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.topics": { + "name": "topics", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "title": { + "name": "title", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "favorite": { + "name": "favorite", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "session_id": { + "name": "session_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "client_id": { + "name": "client_id", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "history_summary": { + "name": "history_summary", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "metadata": { + "name": "metadata", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "topics_session_id_sessions_id_fk": { + "name": "topics_session_id_sessions_id_fk", + "tableFrom": "topics", + "tableTo": "sessions", + "columnsFrom": ["session_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + }, + "topics_user_id_users_id_fk": { + "name": "topics_user_id_users_id_fk", + "tableFrom": "topics", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "topic_client_id_user_id_unique": { + "name": "topic_client_id_user_id_unique", + "nullsNotDistinct": false, + "columns": ["client_id", "user_id"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_installed_plugins": { + "name": "user_installed_plugins", + "schema": "", + "columns": { + "user_id": { + "name": "user_id", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "identifier": { + "name": "identifier", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "type": { + "name": "type", + "type": "text", + "primaryKey": false, + "notNull": true + }, + "manifest": { + "name": "manifest", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "settings": { + "name": "settings", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "custom_params": { + "name": "custom_params", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": { + "user_installed_plugins_user_id_users_id_fk": { + "name": "user_installed_plugins_user_id_users_id_fk", + "tableFrom": "user_installed_plugins", + "tableTo": "users", + "columnsFrom": ["user_id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": { + "user_installed_plugins_user_id_identifier_pk": { + "name": "user_installed_plugins_user_id_identifier_pk", + "columns": ["user_id", "identifier"] + } + }, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.user_settings": { + "name": "user_settings", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "tts": { + "name": "tts", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "key_vaults": { + "name": "key_vaults", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "general": { + "name": "general", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "language_model": { + "name": "language_model", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "system_agent": { + "name": "system_agent", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "default_agent": { + "name": "default_agent", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "tool": { + "name": "tool", + "type": "jsonb", + "primaryKey": false, + "notNull": false + } + }, + "indexes": {}, + "foreignKeys": { + "user_settings_id_users_id_fk": { + "name": "user_settings_id_users_id_fk", + "tableFrom": "user_settings", + "tableTo": "users", + "columnsFrom": ["id"], + "columnsTo": ["id"], + "onDelete": "cascade", + "onUpdate": "no action" + } + }, + "compositePrimaryKeys": {}, + "uniqueConstraints": {}, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + }, + "public.users": { + "name": "users", + "schema": "", + "columns": { + "id": { + "name": "id", + "type": "text", + "primaryKey": true, + "notNull": true + }, + "username": { + "name": "username", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "email": { + "name": "email", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "avatar": { + "name": "avatar", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "phone": { + "name": "phone", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "first_name": { + "name": "first_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "last_name": { + "name": "last_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "full_name": { + "name": "full_name", + "type": "text", + "primaryKey": false, + "notNull": false + }, + "is_onboarded": { + "name": "is_onboarded", + "type": "boolean", + "primaryKey": false, + "notNull": false, + "default": false + }, + "clerk_created_at": { + "name": "clerk_created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "email_verified_at": { + "name": "email_verified_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": false + }, + "preference": { + "name": "preference", + "type": "jsonb", + "primaryKey": false, + "notNull": false + }, + "accessed_at": { + "name": "accessed_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "created_at": { + "name": "created_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + }, + "updated_at": { + "name": "updated_at", + "type": "timestamp with time zone", + "primaryKey": false, + "notNull": true, + "default": "now()" + } + }, + "indexes": {}, + "foreignKeys": {}, + "compositePrimaryKeys": {}, + "uniqueConstraints": { + "users_username_unique": { + "name": "users_username_unique", + "nullsNotDistinct": false, + "columns": ["username"] + } + }, + "policies": {}, + "checkConstraints": {}, + "isRLSEnabled": false + } + }, + "version": "7", + "views": {} +} diff --git a/src/database/migrations/meta/_journal.json b/src/database/migrations/meta/_journal.json index ed8c7b905c421..25800bc3ab7d9 100644 --- a/src/database/migrations/meta/_journal.json +++ b/src/database/migrations/meta/_journal.json @@ -105,6 +105,13 @@ "when": 1737609172353, "tag": "0014_add_message_reasoning", "breakpoints": true + }, + { + "idx": 15, + "version": "7", + "when": 1739901891891, + "tag": "0015_add_message_search_metadata", + "breakpoints": true } ], "version": "6" diff --git a/src/database/schemas/message.ts b/src/database/schemas/message.ts index a532627b7f52b..4c0c659bc558b 100644 --- a/src/database/schemas/message.ts +++ b/src/database/schemas/message.ts @@ -13,7 +13,7 @@ import { import { createSelectSchema } from 'drizzle-zod'; import { idGenerator } from '@/database/utils/idGenerator'; -import { ModelReasoning } from '@/types/message'; +import { GroundingSearch, ModelReasoning } from '@/types/message'; import { timestamps } from './_helpers'; import { agents } from './agent'; @@ -34,6 +34,8 @@ export const messages = pgTable( role: text('role', { enum: ['user', 'system', 'assistant', 'tool'] }).notNull(), content: text('content'), reasoning: jsonb('reasoning').$type(), + search: jsonb('search').$type(), + metadata: jsonb('metadata'), model: text('model'), provider: text('provider'), diff --git a/src/database/server/models/message.ts b/src/database/server/models/message.ts index 0ea7a3bf57637..4dd8bcec75b19 100644 --- a/src/database/server/models/message.ts +++ b/src/database/server/models/message.ts @@ -74,6 +74,8 @@ export class MessageModel { role: messages.role, content: messages.content, reasoning: messages.reasoning, + search: messages.search, + metadata: messages.metadata, error: messages.error, model: messages.model, diff --git a/src/features/Conversation/components/ChatItem/index.tsx b/src/features/Conversation/components/ChatItem/index.tsx index fac434a611b64..16591daa3ef62 100644 --- a/src/features/Conversation/components/ChatItem/index.tsx +++ b/src/features/Conversation/components/ChatItem/index.tsx @@ -172,12 +172,21 @@ const Item = memo( const markdownProps = useMemo( () => ({ + citations: item?.role === 'user' ? undefined : item?.search?.citations, components, customRender: markdownCustomRender, rehypePlugins: item?.role === 'user' ? undefined : rehypePlugins, remarkPlugins: item?.role === 'user' ? undefined : remarkPlugins, + showCitations: + item?.role === 'user' + ? undefined + : item?.search?.citations && + // if the citations are all empty, we should not show the citations + item?.search?.citations.length > 0 && + // if the citations's url and title are all the same, we should not show the citations + item?.search?.citations.every((item) => item.title !== item.url), }), - [components, markdownCustomRender, item?.role], + [components, markdownCustomRender, item?.role, item?.search], ); const onChange = useCallback((value: string) => updateMessageContent(id, value), [id]); diff --git a/src/features/Conversation/components/MarkdownElements/Thinking/Render.tsx b/src/features/Conversation/components/MarkdownElements/Thinking/Render.tsx index 8d300771d547d..33dd79561205f 100644 --- a/src/features/Conversation/components/MarkdownElements/Thinking/Render.tsx +++ b/src/features/Conversation/components/MarkdownElements/Thinking/Render.tsx @@ -18,10 +18,14 @@ const Render = memo(({ children, id }) => { const message = chatSelectors.getMessageById(id)(s); return [!isThinkingClosed(message?.content)]; }); + const citations = useChatStore((s) => { + const message = chatSelectors.getMessageById(id)(s); + return message?.search?.citations; + }); if (!isGenerating && !children) return; - return ; + return ; }); export default Render; diff --git a/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkCustomTagPlugin.ts b/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkCustomTagPlugin.ts index 85f8027f0c2db..ae95f2a797c8f 100644 --- a/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkCustomTagPlugin.ts +++ b/src/features/Conversation/components/MarkdownElements/remarkPlugins/createRemarkCustomTagPlugin.ts @@ -32,6 +32,7 @@ export const createRemarkCustomTagPlugin = (tag: string) => () => { ); // 转换为 Markdown 字符串 + const content = treeNodeToString(contentNodes); // 创建自定义节点 diff --git a/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts b/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts index 1084b91ca62e7..e95ed53ee94e9 100644 --- a/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts +++ b/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.test.ts @@ -393,4 +393,111 @@ describe('treeNodeToString', () => { 1. 求 $a_2$ 和 $a_3$,根据前三项的规律猜想该数列的通项公式 2. 用数学归纳法证明你的猜想。`); }); + + describe('link node', () => { + it('with url', () => { + const nodes = [ + { + type: 'paragraph', + children: [ + { + type: 'link', + title: null, + url: 'citation-1', + children: [ + { + type: 'text', + value: '#citation-1', + position: { + start: { + line: 5, + column: 26, + offset: 78, + }, + end: { + line: 5, + column: 37, + offset: 89, + }, + }, + }, + ], + position: { + start: { + line: 5, + column: 25, + offset: 77, + }, + end: { + line: 5, + column: 50, + offset: 102, + }, + }, + }, + ], + position: { + start: { + line: 5, + column: 1, + offset: 53, + }, + end: { + line: 5, + column: 220, + offset: 272, + }, + }, + }, + ]; + + const result = treeNodeToString(nodes as Parent[]); + + expect(result).toEqual(`[#citation-1](citation-1)`); + }); + + it('handle error case', () => { + const nodes = [ + { + type: 'paragraph', + children: [ + { + type: 'link', + title: null, + url: 'citation-1', + children: [], + position: { + start: { + line: 5, + column: 25, + offset: 77, + }, + end: { + line: 5, + column: 50, + offset: 102, + }, + }, + }, + ], + position: { + start: { + line: 5, + column: 1, + offset: 53, + }, + end: { + line: 5, + column: 220, + offset: 272, + }, + }, + }, + ]; + + const result = treeNodeToString(nodes as Parent[]); + + expect(result).toEqual(`[](citation-1)`); + }); + }); }); diff --git a/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts b/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts index 4ddf8942e1128..ce14a0777f831 100644 --- a/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts +++ b/src/features/Conversation/components/MarkdownElements/remarkPlugins/getNodeContent.ts @@ -7,6 +7,12 @@ const processNode = (node: any): string => { return `$${node.value}$`; } + if (node.type === 'link') { + const text = node.children?.[0] ? processNode(node.children?.[0]) : ''; + + return `[${text}](${node.url})`; + } + // 处理带有子节点的容器 if (node.children) { const content = node.children.map((element: Parent) => processNode(element)).join(''); diff --git a/src/libs/agent-runtime/perplexity/index.test.ts b/src/libs/agent-runtime/perplexity/index.test.ts index 952c3028d3adb..032dd303ace82 100644 --- a/src/libs/agent-runtime/perplexity/index.test.ts +++ b/src/libs/agent-runtime/perplexity/index.test.ts @@ -28,17 +28,9 @@ beforeEach(() => { ); }); -afterEach(() => { - vi.clearAllMocks(); -}); - describe('LobePerplexityAI', () => { describe('chat', () => { it('should call chat method with temperature', async () => { - vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue( - new ReadableStream() as any, - ); - await instance.chat({ messages: [{ content: 'Hello', role: 'user' }], model: 'text-davinci-003', @@ -56,10 +48,6 @@ describe('LobePerplexityAI', () => { }); it('should be undefined when temperature >= 2', async () => { - vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue( - new ReadableStream() as any, - ); - await instance.chat({ messages: [{ content: 'Hello', role: 'user' }], model: 'text-davinci-003', @@ -75,5 +63,161 @@ describe('LobePerplexityAI', () => { expect.any(Object), ); }); + + it('should with search citations', async () => { + const data = [ + { + id: '506d64fb-e7f2-4d94-b80f-158369e9446d', + model: 'sonar-pro', + created: 1739896615, + usage: { + prompt_tokens: 4, + completion_tokens: 3, + total_tokens: 7, + citation_tokens: 2217, + num_search_queries: 1, + }, + citations: [ + 'https://www.weather.com.cn/weather/101210101.shtml', + 'https://tianqi.moji.com/weather/china/zhejiang/hangzhou', + 'https://weather.cma.cn/web/weather/58457.html', + 'https://tianqi.so.com/weather/101210101', + 'https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832', + 'https://www.hzqx.com', + 'https://www.hzqx.com/pc/hztq/', + ], + object: 'chat.completion', + choices: [ + { + index: 0, + finish_reason: null, + message: { + role: 'assistant', + content: '杭州今', + }, + delta: { + role: 'assist', + content: '杭州今', + }, + }, + ], + }, + { + id: '506d64fb-e7f2-4d94-b80f-158369e9446d', + model: 'sonar-pro', + created: 1739896615, + usage: { + prompt_tokens: 4, + completion_tokens: 9, + total_tokens: 13, + citation_tokens: 2217, + num_search_queries: 1, + }, + citations: [ + 'https://www.weather.com.cn/weather/101210101.shtml', + 'https://tianqi.moji.com/weather/china/zhejiang/hangzhou', + 'https://weather.cma.cn/web/weather/58457.html', + 'https://tianqi.so.com/weather/101210101', + 'https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832', + 'https://www.hzqx.com', + 'https://www.hzqx.com/pc/hztq/', + ], + object: 'chat.completion', + choices: [ + { + index: 0, + finish_reason: null, + message: { + role: 'assistant', + content: '杭州今天和未来几天的', + }, + delta: { + role: 'assistant', + content: '天和未来几天的', + }, + }, + ], + }, + { + id: '506d64fb-e7f2-4d94-b80f-158369e9446d', + model: 'sonar-pro', + created: 1739896615, + usage: { + prompt_tokens: 4, + completion_tokens: 14, + total_tokens: 18, + citation_tokens: 2217, + num_search_queries: 1, + }, + citations: [ + 'https://www.weather.com.cn/weather/101210101.shtml', + 'https://tianqi.moji.com/weather/china/zhejiang/hangzhou', + 'https://weather.cma.cn/web/weather/58457.html', + 'https://tianqi.so.com/weather/101210101', + 'https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832', + 'https://www.hzqx.com', + 'https://www.hzqx.com/pc/hztq/', + ], + object: 'chat.completion', + choices: [ + { + index: 0, + finish_reason: null, + message: { + role: 'assistant', + content: '杭州今天和未来几天的天气预报如', + }, + }, + ], + }, + ]; + + const mockStream = new ReadableStream({ + start(controller) { + data.forEach((chunk) => { + controller.enqueue(chunk); + }); + + controller.close(); + }, + }); + + vi.spyOn(instance['client'].chat.completions, 'create').mockResolvedValue(mockStream as any); + + const result = await instance.chat({ + messages: [{ content: 'Hello', role: 'user' }], + model: 'mistralai/mistral-7b-instruct:free', + temperature: 0, + }); + + const decoder = new TextDecoder(); + const reader = result.body!.getReader(); + const stream: string[] = []; + + while (true) { + const { value, done } = await reader.read(); + if (done) break; + stream.push(decoder.decode(value)); + } + + expect(stream).toEqual( + [ + 'id: 506d64fb-e7f2-4d94-b80f-158369e9446d', + 'event: citations', + 'data: [{"title":"https://www.weather.com.cn/weather/101210101.shtml","url":"https://www.weather.com.cn/weather/101210101.shtml"},{"title":"https://tianqi.moji.com/weather/china/zhejiang/hangzhou","url":"https://tianqi.moji.com/weather/china/zhejiang/hangzhou"},{"title":"https://weather.cma.cn/web/weather/58457.html","url":"https://weather.cma.cn/web/weather/58457.html"},{"title":"https://tianqi.so.com/weather/101210101","url":"https://tianqi.so.com/weather/101210101"},{"title":"https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832","url":"https://www.accuweather.com/zh/cn/hangzhou/106832/weather-forecast/106832"},{"title":"https://www.hzqx.com","url":"https://www.hzqx.com"},{"title":"https://www.hzqx.com/pc/hztq/","url":"https://www.hzqx.com/pc/hztq/"}]\n', + 'id: 506d64fb-e7f2-4d94-b80f-158369e9446d', + 'event: text', + 'data: "杭州今"\n', + 'id: 506d64fb-e7f2-4d94-b80f-158369e9446d', + 'event: text', + 'data: "天和未来几天的"\n', + 'id: 506d64fb-e7f2-4d94-b80f-158369e9446d', + 'event: data', + 'data: {"id":"506d64fb-e7f2-4d94-b80f-158369e9446d","index":0}\n', + ].map((line) => `${line}\n`), + ); + + expect((await reader.read()).done).toBe(true); + }); }); }); diff --git a/src/libs/agent-runtime/utils/streams/anthropic.ts b/src/libs/agent-runtime/utils/streams/anthropic.ts index ebdeea5572695..337c8178d99b9 100644 --- a/src/libs/agent-runtime/utils/streams/anthropic.ts +++ b/src/libs/agent-runtime/utils/streams/anthropic.ts @@ -3,9 +3,9 @@ import type { Stream } from '@anthropic-ai/sdk/streaming'; import { ChatStreamCallbacks } from '../../types'; import { + StreamContext, StreamProtocolChunk, StreamProtocolToolCallChunk, - StreamStack, StreamToolCallChunkData, convertIterableToStream, createCallbacksTransformer, @@ -14,7 +14,7 @@ import { export const transformAnthropicStream = ( chunk: Anthropic.MessageStreamEvent, - stack: StreamStack, + stack: StreamContext, ): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices switch (chunk.type) { @@ -100,7 +100,7 @@ export const AnthropicStream = ( stream: Stream | ReadableStream, callbacks?: ChatStreamCallbacks, ) => { - const streamStack: StreamStack = { id: '' }; + const streamStack: StreamContext = { id: '' }; const readableStream = stream instanceof ReadableStream ? stream : convertIterableToStream(stream); diff --git a/src/libs/agent-runtime/utils/streams/bedrock/claude.ts b/src/libs/agent-runtime/utils/streams/bedrock/claude.ts index ac74a985c813e..76e2e1de197a5 100644 --- a/src/libs/agent-runtime/utils/streams/bedrock/claude.ts +++ b/src/libs/agent-runtime/utils/streams/bedrock/claude.ts @@ -4,14 +4,18 @@ import { nanoid } from '@/utils/uuid'; import { ChatStreamCallbacks } from '../../../types'; import { transformAnthropicStream } from '../anthropic'; -import { StreamStack, createCallbacksTransformer, createSSEProtocolTransformer } from '../protocol'; +import { + StreamContext, + createCallbacksTransformer, + createSSEProtocolTransformer, +} from '../protocol'; import { createBedrockStream } from './common'; export const AWSBedrockClaudeStream = ( res: InvokeModelWithResponseStreamResponse | ReadableStream, cb?: ChatStreamCallbacks, ): ReadableStream => { - const streamStack: StreamStack = { id: 'chat_' + nanoid() }; + const streamStack: StreamContext = { id: 'chat_' + nanoid() }; const stream = res instanceof ReadableStream ? res : createBedrockStream(res); diff --git a/src/libs/agent-runtime/utils/streams/bedrock/llama.ts b/src/libs/agent-runtime/utils/streams/bedrock/llama.ts index 78e0f5b327d5e..35b7763fb6f18 100644 --- a/src/libs/agent-runtime/utils/streams/bedrock/llama.ts +++ b/src/libs/agent-runtime/utils/streams/bedrock/llama.ts @@ -4,8 +4,8 @@ import { nanoid } from '@/utils/uuid'; import { ChatStreamCallbacks } from '../../../types'; import { + StreamContext, StreamProtocolChunk, - StreamStack, createCallbacksTransformer, createSSEProtocolTransformer, } from '../protocol'; @@ -27,7 +27,7 @@ interface BedrockLlamaStreamChunk { export const transformLlamaStream = ( chunk: BedrockLlamaStreamChunk, - stack: StreamStack, + stack: StreamContext, ): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices if (chunk.stop_reason) { @@ -41,7 +41,7 @@ export const AWSBedrockLlamaStream = ( res: InvokeModelWithResponseStreamResponse | ReadableStream, cb?: ChatStreamCallbacks, ): ReadableStream => { - const streamStack: StreamStack = { id: 'chat_' + nanoid() }; + const streamStack: StreamContext = { id: 'chat_' + nanoid() }; const stream = res instanceof ReadableStream ? res : createBedrockStream(res); diff --git a/src/libs/agent-runtime/utils/streams/google-ai.ts b/src/libs/agent-runtime/utils/streams/google-ai.ts index e669404e92232..766bdbfc2579f 100644 --- a/src/libs/agent-runtime/utils/streams/google-ai.ts +++ b/src/libs/agent-runtime/utils/streams/google-ai.ts @@ -4,8 +4,8 @@ import { nanoid } from '@/utils/uuid'; import { ChatStreamCallbacks } from '../../types'; import { + StreamContext, StreamProtocolChunk, - StreamStack, StreamToolCallChunkData, createCallbacksTransformer, createSSEProtocolTransformer, @@ -14,7 +14,7 @@ import { const transformGoogleGenerativeAIStream = ( chunk: EnhancedGenerateContentResponse, - stack: StreamStack, + stack: StreamContext, ): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices const functionCalls = chunk.functionCalls(); @@ -49,7 +49,7 @@ export const GoogleGenerativeAIStream = ( rawStream: ReadableStream, callbacks?: ChatStreamCallbacks, ) => { - const streamStack: StreamStack = { id: 'chat_' + nanoid() }; + const streamStack: StreamContext = { id: 'chat_' + nanoid() }; return rawStream .pipeThrough(createSSEProtocolTransformer(transformGoogleGenerativeAIStream, streamStack)) diff --git a/src/libs/agent-runtime/utils/streams/ollama.ts b/src/libs/agent-runtime/utils/streams/ollama.ts index 6ba13874cc81b..9da633827773c 100644 --- a/src/libs/agent-runtime/utils/streams/ollama.ts +++ b/src/libs/agent-runtime/utils/streams/ollama.ts @@ -4,14 +4,14 @@ import { ChatStreamCallbacks } from '@/libs/agent-runtime'; import { nanoid } from '@/utils/uuid'; import { + StreamContext, StreamProtocolChunk, - StreamStack, createCallbacksTransformer, createSSEProtocolTransformer, generateToolCallId, } from './protocol'; -const transformOllamaStream = (chunk: ChatResponse, stack: StreamStack): StreamProtocolChunk => { +const transformOllamaStream = (chunk: ChatResponse, stack: StreamContext): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices if (chunk.done && !chunk.message.content) { return { data: 'finished', id: stack.id, type: 'stop' }; @@ -39,7 +39,7 @@ export const OllamaStream = ( res: ReadableStream, cb?: ChatStreamCallbacks, ): ReadableStream => { - const streamStack: StreamStack = { id: 'chat_' + nanoid() }; + const streamStack: StreamContext = { id: 'chat_' + nanoid() }; return res .pipeThrough(createSSEProtocolTransformer(transformOllamaStream, streamStack)) diff --git a/src/libs/agent-runtime/utils/streams/openai.ts b/src/libs/agent-runtime/utils/streams/openai.ts index f9f354ee16d8f..9afd68fb7799c 100644 --- a/src/libs/agent-runtime/utils/streams/openai.ts +++ b/src/libs/agent-runtime/utils/streams/openai.ts @@ -1,15 +1,15 @@ import OpenAI from 'openai'; import type { Stream } from 'openai/streaming'; -import { ChatMessageError } from '@/types/message'; +import { ChatMessageError, CitationItem } from '@/types/message'; import { AgentRuntimeErrorType, ILobeAgentRuntimeErrorType } from '../../error'; import { ChatStreamCallbacks } from '../../types'; import { FIRST_CHUNK_ERROR_KEY, + StreamContext, StreamProtocolChunk, StreamProtocolToolCallChunk, - StreamStack, StreamToolCallChunkData, convertIterableToStream, createCallbacksTransformer, @@ -20,8 +20,8 @@ import { export const transformOpenAIStream = ( chunk: OpenAI.ChatCompletionChunk, - stack?: StreamStack, -): StreamProtocolChunk => { + streamContext: StreamContext, +): StreamProtocolChunk | StreamProtocolChunk[] => { // handle the first chunk error if (FIRST_CHUNK_ERROR_KEY in chunk) { delete chunk[FIRST_CHUNK_ERROR_KEY]; @@ -48,8 +48,8 @@ export const transformOpenAIStream = ( if (typeof item.delta?.tool_calls === 'object' && item.delta.tool_calls?.length > 0) { return { data: item.delta.tool_calls.map((value, index): StreamToolCallChunkData => { - if (stack && !stack.tool) { - stack.tool = { id: value.id!, index: value.index, name: value.function!.name! }; + if (streamContext && !streamContext.tool) { + streamContext.tool = { id: value.id!, index: value.index, name: value.function!.name! }; } return { @@ -57,7 +57,10 @@ export const transformOpenAIStream = ( arguments: value.function?.arguments ?? '{}', name: value.function?.name ?? null, }, - id: value.id || stack?.tool?.id || generateToolCallId(index, value.function?.name), + id: + value.id || + streamContext?.tool?.id || + generateToolCallId(index, value.function?.name), // mistral's tool calling don't have index and function field, it's data like: // [{"id":"xbhnmTtY7","function":{"name":"lobe-image-designer____text2image____builtin","arguments":"{\"prompts\": [\"A photo of a small, fluffy dog with a playful expression and wagging tail.\", \"A watercolor painting of a small, energetic dog with a glossy coat and bright eyes.\", \"A vector illustration of a small, adorable dog with a short snout and perky ears.\", \"A drawing of a small, scruffy dog with a mischievous grin and a wagging tail.\"], \"quality\": \"standard\", \"seeds\": [123456, 654321, 111222, 333444], \"size\": \"1024x1024\", \"style\": \"vivid\"}"}}] @@ -114,6 +117,21 @@ export const transformOpenAIStream = ( } if (typeof content === 'string') { + // in Perplexity api, the citation is in every chunk, but we only need to return it once + + if ('citations' in chunk && !streamContext?.returnedPplxCitation) { + streamContext.returnedPplxCitation = true; + + const citations = (chunk.citations as any[]).map((item) => + typeof item === 'string' ? ({ title: item, url: item } as CitationItem) : item, + ); + + return [ + { data: citations, id: chunk.id, type: 'citations' }, + { data: content, id: chunk.id, type: 'text' }, + ]; + } + return { data: content, id: chunk.id, type: 'text' }; } } @@ -164,7 +182,7 @@ export const OpenAIStream = ( stream: Stream | ReadableStream, { callbacks, provider, bizErrorTypeTransformer }: OpenAIStreamOptions = {}, ) => { - const streamStack: StreamStack = { id: '' }; + const streamStack: StreamContext = { id: '' }; const readableStream = stream instanceof ReadableStream ? stream : convertIterableToStream(stream); diff --git a/src/libs/agent-runtime/utils/streams/protocol.ts b/src/libs/agent-runtime/utils/streams/protocol.ts index 61ff76eda26a2..fbf37547c3ef2 100644 --- a/src/libs/agent-runtime/utils/streams/protocol.ts +++ b/src/libs/agent-runtime/utils/streams/protocol.ts @@ -2,8 +2,16 @@ import { ChatStreamCallbacks } from '@/libs/agent-runtime'; import { AgentRuntimeErrorType } from '../../error'; -export interface StreamStack { +/** + * context in the stream to save temporarily data + */ +export interface StreamContext { id: string; + /** + * As pplx citations is in every chunk, but we only need to return it once + * this flag is used to check if the pplx citation is returned,and then not return it again + */ + returnedPplxCitation?: boolean; tool?: { id: string; index: number; @@ -15,7 +23,20 @@ export interface StreamStack { export interface StreamProtocolChunk { data: any; id?: string; - type: 'text' | 'tool_calls' | 'data' | 'stop' | 'error' | 'reasoning'; + type: // pure text + | 'text' + // Tools use + | 'tool_calls' + // Model Thinking + | 'reasoning' + // Search or Grounding + | 'citations' + // stop signal + | 'stop' + // Error + | 'error' + // unknown data result + | 'data'; } export interface StreamToolCallChunkData { @@ -85,16 +106,20 @@ export const convertIterableToStream = (stream: AsyncIterable) => { * Create a transformer to convert the response into an SSE format */ export const createSSEProtocolTransformer = ( - transformer: (chunk: any, stack: StreamStack) => StreamProtocolChunk, - streamStack?: StreamStack, + transformer: (chunk: any, stack: StreamContext) => StreamProtocolChunk | StreamProtocolChunk[], + streamStack?: StreamContext, ) => new TransformStream({ transform: (chunk, controller) => { - const { type, id, data } = transformer(chunk, streamStack || { id: '' }); + const result = transformer(chunk, streamStack || { id: '' }); + + const buffers = Array.isArray(result) ? result : [result]; - controller.enqueue(`id: ${id}\n`); - controller.enqueue(`event: ${type}\n`); - controller.enqueue(`data: ${JSON.stringify(data)}\n\n`); + buffers.forEach(({ type, id, data }) => { + controller.enqueue(`id: ${id}\n`); + controller.enqueue(`event: ${type}\n`); + controller.enqueue(`data: ${JSON.stringify(data)}\n\n`); + }); }, }); diff --git a/src/libs/agent-runtime/utils/streams/vertex-ai.ts b/src/libs/agent-runtime/utils/streams/vertex-ai.ts index edd9dc9e24a49..9c8b29a1a84bf 100644 --- a/src/libs/agent-runtime/utils/streams/vertex-ai.ts +++ b/src/libs/agent-runtime/utils/streams/vertex-ai.ts @@ -4,8 +4,8 @@ import { nanoid } from '@/utils/uuid'; import { ChatStreamCallbacks } from '../../types'; import { + StreamContext, StreamProtocolChunk, - StreamStack, createCallbacksTransformer, createSSEProtocolTransformer, generateToolCallId, @@ -13,7 +13,7 @@ import { const transformVertexAIStream = ( chunk: GenerateContentResponse, - stack: StreamStack, + stack: StreamContext, ): StreamProtocolChunk => { // maybe need another structure to add support for multiple choices const candidates = chunk.candidates; @@ -67,7 +67,7 @@ export const VertexAIStream = ( rawStream: ReadableStream, callbacks?: ChatStreamCallbacks, ) => { - const streamStack: StreamStack = { id: 'chat_' + nanoid() }; + const streamStack: StreamContext = { id: 'chat_' + nanoid() }; return rawStream .pipeThrough(createSSEProtocolTransformer(transformVertexAIStream, streamStack)) diff --git a/src/locales/default/components.ts b/src/locales/default/components.ts index ddaa0e9065110..90b2f4c829e45 100644 --- a/src/locales/default/components.ts +++ b/src/locales/default/components.ts @@ -79,6 +79,7 @@ export default { file: '该模型支持上传文件读取与识别', functionCall: '该模型支持函数调用(Function Call)', reasoning: '该模型支持深度思考', + search: '该模型支持联网搜索', tokens: '该模型单个会话最多支持 {{tokens}} Tokens', vision: '该模型支持视觉识别', }, diff --git a/src/store/chat/slices/aiChat/actions/generateAIChat.ts b/src/store/chat/slices/aiChat/actions/generateAIChat.ts index 14a85e2b667e9..67b3b0ba15058 100644 --- a/src/store/chat/slices/aiChat/actions/generateAIChat.ts +++ b/src/store/chat/slices/aiChat/actions/generateAIChat.ts @@ -455,7 +455,7 @@ export const generateAIChat: StateCreator< await messageService.updateMessageError(messageId, error); await refreshMessages(); }, - onFinish: async (content, { traceId, observationId, toolCalls, reasoning }) => { + onFinish: async (content, { traceId, observationId, toolCalls, reasoning, citations }) => { // if there is traceId, update it if (traceId) { msgTraceId = traceId; @@ -470,15 +470,26 @@ export const generateAIChat: StateCreator< } // update the content after fetch result - await internal_updateMessageContent( - messageId, - content, + await internal_updateMessageContent(messageId, content, { toolCalls, - !!reasoning ? { content: reasoning, duration } : undefined, - ); + reasoning: !!reasoning ? { content: reasoning, duration } : undefined, + search: !!citations ? { citations } : undefined, + }); }, onMessageHandle: async (chunk) => { switch (chunk.type) { + case 'citations': { + // if there is no citations, then stop + if (!chunk.citations || chunk.citations.length <= 0) return; + + internal_dispatchMessage({ + id: messageId, + type: 'updateMessage', + value: { search: { citations: chunk.citations } }, + }); + break; + } + case 'text': { output += chunk.text; diff --git a/src/store/chat/slices/message/action.ts b/src/store/chat/slices/message/action.ts index 383e53e11c292..df0838b3bed06 100644 --- a/src/store/chat/slices/message/action.ts +++ b/src/store/chat/slices/message/action.ts @@ -16,6 +16,7 @@ import { ChatMessage, ChatMessageError, CreateMessageParams, + GroundingSearch, MessageToolCall, ModelReasoning, } from '@/types/message'; @@ -73,8 +74,11 @@ export interface ChatMessageAction { internal_updateMessageContent: ( id: string, content: string, - toolCalls?: MessageToolCall[], - reasoning?: ModelReasoning, + extra?: { + toolCalls?: MessageToolCall[]; + reasoning?: ModelReasoning; + search?: GroundingSearch; + }, ) => Promise; /** * update the message error with optimistic update @@ -272,17 +276,17 @@ export const chatMessage: StateCreator< await messageService.updateMessage(id, { error }); await get().refreshMessages(); }, - internal_updateMessageContent: async (id, content, toolCalls, reasoning) => { + internal_updateMessageContent: async (id, content, extra) => { const { internal_dispatchMessage, refreshMessages, internal_transformToolCalls } = get(); // Due to the async update method and refresh need about 100ms // we need to update the message content at the frontend to avoid the update flick // refs: https://medium.com/@kyledeguzmanx/what-are-optimistic-updates-483662c3e171 - if (toolCalls) { + if (extra?.toolCalls) { internal_dispatchMessage({ id, type: 'updateMessage', - value: { tools: internal_transformToolCalls(toolCalls) }, + value: { tools: internal_transformToolCalls(extra?.toolCalls) }, }); } else { internal_dispatchMessage({ id, type: 'updateMessage', value: { content } }); @@ -290,8 +294,9 @@ export const chatMessage: StateCreator< await messageService.updateMessage(id, { content, - tools: toolCalls ? internal_transformToolCalls(toolCalls) : undefined, - reasoning, + tools: extra?.toolCalls ? internal_transformToolCalls(extra?.toolCalls) : undefined, + reasoning: extra?.reasoning, + search: extra?.search, }); await refreshMessages(); }, diff --git a/src/types/aiModel.ts b/src/types/aiModel.ts index 57fa549f9b1ae..f40220455018b 100644 --- a/src/types/aiModel.ts +++ b/src/types/aiModel.ts @@ -34,6 +34,11 @@ export interface ModelAbilities { * whether model supports reasoning */ reasoning?: boolean; + /** + * whether model supports search web + */ + search?: boolean; + /** * whether model supports vision */ diff --git a/src/types/message/base.ts b/src/types/message/base.ts index 788c417593dfd..c0c010a4b209a 100644 --- a/src/types/message/base.ts +++ b/src/types/message/base.ts @@ -1,3 +1,15 @@ +export interface CitationItem { + id?: string; + onlyUrl?: boolean; + title?: string; + url: string; +} + +export interface GroundingSearch { + citations?: CitationItem[]; + searchQueries?: string[]; +} + export interface ModelReasoning { content?: string; duration?: number; @@ -20,6 +32,7 @@ export interface MessageItem { quotaId: string | null; reasoning: ModelReasoning | null; role: string; + search: GroundingSearch | null; sessionId: string | null; threadId: string | null; // jsonb type diff --git a/src/types/message/chat.ts b/src/types/message/chat.ts index 8a99730c5c662..bbd9154d06763 100644 --- a/src/types/message/chat.ts +++ b/src/types/message/chat.ts @@ -2,7 +2,7 @@ import { IPluginErrorType } from '@lobehub/chat-plugin-sdk'; import { ILobeAgentRuntimeErrorType } from '@/libs/agent-runtime'; import { ErrorType } from '@/types/fetch'; -import { MessageRoleType, ModelReasoning } from '@/types/message/base'; +import { GroundingSearch, MessageRoleType, ModelReasoning } from '@/types/message/base'; import { ChatPluginPayload, ChatToolPayload } from '@/types/message/tools'; import { Translate } from '@/types/message/translate'; import { MetaData } from '@/types/meta'; @@ -100,11 +100,12 @@ export interface ChatMessage { ragRawQuery?: string | null; reasoning?: ModelReasoning | null; - /** * message role type */ role: MessageRoleType; + + search?: GroundingSearch | null; sessionId?: string; threadId?: string | null; tool_call_id?: string; diff --git a/src/utils/fetch/fetchSSE.ts b/src/utils/fetch/fetchSSE.ts index f37d22d40bd6f..cb624b83aad0f 100644 --- a/src/utils/fetch/fetchSSE.ts +++ b/src/utils/fetch/fetchSSE.ts @@ -6,6 +6,7 @@ import { ChatErrorType } from '@/types/fetch'; import { SmoothingParams } from '@/types/llm'; import { ChatMessageError, + CitationItem, MessageToolCall, MessageToolCallChunk, MessageToolCallSchema, @@ -20,6 +21,7 @@ type SSEFinishType = 'done' | 'error' | 'abort'; export type OnFinishHandler = ( text: string, context: { + citations?: CitationItem[]; observationId?: string | null; reasoning?: string; toolCalls?: MessageToolCall[]; @@ -38,6 +40,11 @@ export interface MessageReasoningChunk { type: 'reasoning'; } +export interface MessageCitationsChunk { + citations: CitationItem[]; + type: 'citations'; +} + interface MessageToolCallsChunk { isAnimationActives?: boolean[]; tool_calls: MessageToolCall[]; @@ -50,7 +57,7 @@ export interface FetchSSEOptions { onErrorHandle?: (error: ChatMessageError) => void; onFinish?: OnFinishHandler; onMessageHandle?: ( - chunk: MessageTextChunk | MessageToolCallsChunk | MessageReasoningChunk, + chunk: MessageTextChunk | MessageToolCallsChunk | MessageReasoningChunk | MessageCitationsChunk, ) => void; smoothing?: SmoothingParams | boolean; } @@ -279,6 +286,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio startSpeed: smoothingSpeed, }); + let citations: CitationItem[] | undefined = undefined; await fetchEventSource(url, { body: options.body, fetch: options?.fetcher, @@ -350,6 +358,13 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio break; } + + case 'citations': { + citations = data; + options.onMessageHandle?.({ citations: data, type: 'citations' }); + break; + } + case 'reasoning': { if (textSmoothing) { thinkingController.pushToQueue(data); @@ -419,6 +434,7 @@ export const fetchSSE = async (url: string, options: RequestInit & FetchSSEOptio } await options?.onFinish?.(output, { + citations, observationId, reasoning: !!thinking ? thinking : undefined, toolCalls,