V4.15.0(环境变量变更、升级脚本)
FastGPT V4.15.0 更新说明
📦 升级指南
1. 环境变量变更
1.1 fastgpt-app 与 fastgpt-pro
检查是否缺少变量
4.15.0 版本引入了更为严格的环境变量检查,升级后需确保以下环境变量正确配置.
# 密钥加密密钥,两个服务需一致
AES256_SECRET_KEY=
# 文件 token 密钥,两个服务需一致
FILE_TOKEN_KEY=
# Invoke 反向调用 JWT 密钥,至少 32 位,两个服务需一致
INVOKE_TOKEN_SECRET=新增环境变量
必须新增的变量
# SSE mcp server 服务地址,如果不需要 SSE 的话,可以不配置
SSE_MCP_SERVER_PROXY_ENDPOINT=可选的变量
以下变量均有默认值,或者不配置不影响使用。
# 文件解析 worker 并发数(可选)
PARSE_FILE_WORKERS=10
# 文件解析超时时间(秒)(可选)
PARSE_FILE_TIMEOUT_SECONDS=600
# HTML 转 Markdown worker 并发数(可选)
HTML_TO_MARKDOWN_WORKERS=10
# 文本切块 worker 并发数(可选)
TEXT_TO_CHUNKS_WORKERS=10
# 自动同步 mongo 数据库索引, 改成 boolean 字符串值,而不是 0 和 1(可选)
SYNC_INDEX=true
# 是否启用可信反向代理客户端 IP 校验(可选)
TRUSTED_PROXY_ENABLE=false
# 可信反向代理 IP/CIDR 列表,逗号或空白分隔。仅 TRUSTED_PROXY_ENABLE=true 时生效;仅显式可信代理传入的 X-Forwarded-For/X-Real-IP 会用于客户端 IP 解析(可选)
TRUSTED_PROXY_IPS=
# 系统变量替换等同步字符串处理的最大字符数,单位 M,范围 1~100
SYSTEM_MAX_STRING_LENGTH_M=100
# 允许的最深文件夹层级,默认 4,范围 2~20
MAX_FOLDER_DEPTH=4
# 循环/并行节点最大输入数组长度
WORKFLOW_MAX_LOOP_TIMES=100
# 并行节点并发上限,最终会 clamp 到 [5, 100]
WORKFLOW_PARALLEL_MAX_CONCURRENCY=10开源版环境变量变更
开源版移除 config.json 配置文件,改成环境变量,可新增这些变量来替代。移除 volumn 挂载后加入以下变量:
# 自定义 PDF 解析服务地址
CUSTOM_PDF_PARSE_URL=
# 自定义 PDF 解析服务密钥
CUSTOM_PDF_PARSE_KEY=
# Doc2x PDF 解析服务密钥
DOC2X_KEY=
# 合合信息 Textin 服务 App ID
TEXTIN_APP_ID=
# 合合信息 Textin 服务 Secret Code
TEXTIN_SECRET_CODE=
# 向量检索 hnsw ef_search 参数,仅对 PG / OB / OpenGauss 生效
HNSW_EF_SEARCH=100
# 向量检索最大扫描数据量,仅对 PG 生效
HNSW_MAX_SCAN_TUPLES=100000
# 知识库文件解析队列最大并发数
DATASET_PARSE_MAX_PROCESS=10
# 向量训练队列最大并发数
VECTOR_MAX_PROCESS=10
# 问答拆分队列最大并发数
QA_MAX_PROCESS=10
# 图片理解模型处理队列最大并发数
VLM_MAX_PROCESS=101.2 code-sandbox
Code Sandbox 新增 SANDBOX_API_MAX_BODY_MB、SANDBOX_MAX_OUTPUT_MB 等安全相关环境变量,并支持通过 queueId 对运行接口做分组排队;完整默认值如下:
| 变量 | 默认值 | 说明 |
|---|---|---|
SANDBOX_API_MAX_BODY_MB | 8 | /sandbox API JSON 请求体总大小上限,包含 variables,单位 MB。 |
SANDBOX_MAX_OUTPUT_MB | 10 | 单次代码执行输出 JSON 大小上限,包含返回值和日志,单位 MB。 |
CHECK_INTERNAL_IP | true | 沙箱网络请求默认开启内网 IP 检查,降低 SSRF 风险。 |
SANDBOX_MAX_TIMEOUT | 60000 | 单次代码执行超时时间,单位毫秒。 |
SANDBOX_MAX_MEMORY_MB | 256 | 单个沙箱内存上限,单位 MB;运行时会额外预留 50 MB 开销。 |
SANDBOX_POOL_SIZE | 20 | JS/Python 预热 worker 数量。 |
SANDBOX_REQUEST_MAX_COUNT | 30 | 单次代码执行允许发起的最大网络请求数。 |
SANDBOX_REQUEST_TIMEOUT | 60000 | 沙箱内单次网络请求超时时间,单位毫秒。 |
SANDBOX_REQUEST_MAX_RESPONSE_MB | 10 | 沙箱内单次网络响应体最大大小,单位 MB。 |
SANDBOX_REQUEST_MAX_BODY_MB | 5 | 沙箱内单次网络请求体最大大小,单位 MB。 |
SANDBOX_QUEUE_ID_CONCURRENCY | 空 | 同一个 queueId 同时可进入执行流程的请求数;为空时不启用排队。 |
1.3 fastgpt-plugin
插件服务进行了重构,必须增加 AUTH_TOKEN 和 FASTGPT_BASE_URL 两个环境变量,并且需要修改 MONGODB_URI 变量:
- 修改
fastgpt-plugin的环境变量AUTH_TOKEN,要求 32 位以上。 - 同时修改
fastgpt和fastgpt-pro的环境变量PLUGIN_TOKEN,与fastgpt-plugin的AUTH_TOKEN一致。 - 修改
fastgpt-plugin的环境变量MONGODB_URI中的数据库名,不与fastgpt的 Mongo 数据库名重名即可,例如:mongodb://myusername:mypassword@fastgpt-mongo:27017/fastgpt-plugin?authSource=admin
更多变量,可按需修改
# ================ 系统 =====================
# 鉴权 token
AUTH_TOKEN=
# 最大 API 请求体大小(MB)
MAX_API_SIZE=10
# FastGPT 服务的地址,可以为内网连接串,用于反向调用 fastgpt 接口。
FASTGPT_BASE_URL=http://fastgpt-app:3000
# ================ 插件运行 =====================
# 可选值: localPool
PLUGIN_RUNTIME_MODE=localPool
# 临时文件存储目录,可以为空
LOCAL_FILE_BASE_PATH=
# ================ 进程池 =====================
# 健康检查时间(ms)
POOL_HEALTH_CHECK_INTERVAL=30000
# 最大总进程数
POOL_MAX_TOTAL_PODS=100
# 某个 Service 的最小进程数
POOL_SERVICE_MIN_PODS=0
# 某个 Service 的最大进程数
POOL_SERVICE_MAX_PODS=5
# 全局空闲超时时间(ms)
POOL_SERVICE_IDLE_TIMEOUT=60000
# 进程运行超时时间(ms)
POOL_SERVICE_POD_TIMEOUT=120000
# 单个进程最大并发请求数
POOL_SERVICE_MAX_CONCURRENT_REQUESTS_PER_POD=10
# 全局单个进程最大请求数,超出后自动轮换
POOL_SERVICE_MAX_REQUESTS_PER_POD=100
# 全局进程队列最大长度
POOL_SERVICE_MAX_QUEUE_SIZE=500
# 全局进程队列超时时间(ms)
POOL_SERVICE_QUEUE_TIMEOUT=60000
# 启动超时退避基础时间(ms)
POOL_SERVICE_STARTUP_RETRY_BASE_DELAY=1000
# 启动超时退避最大时间(ms)
POOL_SERVICE_STARTUP_RETRY_MAX_DELAY=10000
# ================ 数据库 =====================
MONGODB_URI=mongodb://username:password@localhost:27017/fastgpt?authSource=admin&directConnection=true
MONGO_MAX_LINK=20
SYNC_INDEX=true
REDIS_URL=redis://default:password@localhost:6379/0
# ================ 对象存储 =====================
# S3 文件前缀,使用后不可随意修改
S3_FILE_BASE_PATH=system/plugin
STORAGE_VENDOR=minio
STORAGE_REGION=us-east-1
STORAGE_ACCESS_KEY_ID=minioadmin
STORAGE_SECRET_ACCESS_KEY=minioadmin
STORAGE_PUBLIC_BUCKET=fastgpt-public
STORAGE_PRIVATE_BUCKET=fastgpt-private
STORAGE_EXTERNAL_ENDPOINT=http://localhost:9000
STORAGE_S3_ENDPOINT=http://localhost:9000
STORAGE_S3_FORCE_PATH_STYLE=true
STORAGE_S3_MAX_RETRIES=3
STORAGE_PUBLIC_ACCESS_EXTRA_SUB_PATH=
# ================ 日志 =====================
LOG_ENABLE_CONSOLE=true
# 控制台日志等级: "trace" | "debug" | "info" | "warning" | "error" | "fatal"
LOG_CONSOLE_LEVEL=info
LOG_ENABLE_OTEL=false
# OTEL 存储的最低日志等级
LOG_OTEL_LEVEL=info
LOG_OTEL_SERVICE_NAME=fastgpt-plugin
LOG_OTEL_URL=http://localhost:4318/v1/logs
# ================ 指标 =====================
METRICS_ENABLE_OTEL=false
METRICS_OTEL_SERVICE_NAME=fastgpt-plugin
METRICS_OTEL_URL=http://localhost:4318/v1/metrics
METRICS_EXPORT_INTERVAL_MS=30000
METRICS_EXPORT_TIMEOUT_MS=10000
METRICS_INCLUDE_PLUGIN_VERSION=true
METRICS_INCLUDE_PLUGIN_ETAG=false
METRICS_INCLUDE_HOSTNAME=true
# 多节点部署建议使用 Pod UID / container id / instance id;为空时进程会生成 opaque id。
SERVICE_INSTANCE_ID=
DEPLOYMENT_ENVIRONMENT=2. OpenSandbox 调整(按需)
Opensandbox 和其他沙盒提供商的配置单独移动到沙盒配置内,并不再内置到部署 yml 中。
本次升级主要需修改以下内容:
- 新部署
agent-sandbox-proxy服务。 - 更新
opensandbox相关镜像版本。 - 修改
fastgpt-app和fastgpt-pro里部分环境变量。
可以直接按新的 OpenSandbox 模板进行覆盖部署即可。
3. 镜像变更
- 更新 fastgpt-app(fastgpt 主服务) 镜像 tag: v4.15.0
- 更新 fastgpt-pro(fastgpt 商业版) 镜像 tag: v4.15.0
- 更新 fastgpt-code-sandbox 镜像 tag: v4.15.0
- 更新 fastgpt-plugin 镜像 tag: v1.0.0
- 更新 aiproxy 镜像 tag: v0.6.5
如果启用 opensandbox,需同步更新下面镜像:
更新 fastgpt-agent-sandbox-proxy 镜像 tag: v0.2.0 更新 fastgpt-agent-sandbox 镜像 tag: v0.2.0
4. 启动服务
docker compose up -d 重启服务。
5. 重装系统工具
插件服务升级后,需要重装旧的所有系统工具:
- 下载所有系统工具的 zip 包。
- 打开
fastgpt网页 - 点击管理员navbar - 点击添加插件 - 点击导入/更新插件- 上传 zip - 确认。
也可以打开插件市场逐个下载安装,插件市场地址为: https://v2.marketplace.fastgpt.cn,环境变量默认值已变成该地址,不设置相关环境变量即可。
6. 执行迁移脚本
执行前先完成三件事:
- 备份 MongoDB、对象存储和当前部署配置。
- 将
fastgpt-app/fastgpt-pro升级到包含这些 Root 管理员接口的镜像版本。 - 准备可访问 FastGPT 的
{{host}}和{{rootkey}}。下面所有接口都需要rootkey。
6.1 清理重复的 appId-chatId(可选,但建议执行)
正式版会同步 { appId, chatId } 和 { sourceType, appId, chatId } 两个唯一索引。正式版索引最终同步成功前,必须检查并清理 chats 集合中重复的 appId + chatId;否则开启 SYNC_INDEX=true 后,索引同步可能报 E11000 duplicate key error,唯一约束不会生效。
该接口依赖升级后的 fastgpt-app 镜像。如果首次启动正式版时已经出现唯一索引冲突,但服务仍可访问,可直接执行下面的 dry-run 和清理命令,完成后重启服务重新同步索引。
先执行 dry-run。该步骤不会删除数据,所有环境都应至少执行一次:
curl -X POST 'https://{{host}}/api/admin/dataClean/cleanupDuplicateChats' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":true,"sampleLimit":20}'重点查看返回值:
duplicateDocumentCount:预计需要删除的重复chats会话头数量。samples:重复样本,包含保留的keepId和候选删除的deleteIds。deletedDocumentCount:正式执行时实际删除数量,dry-run 时固定为0。
如果 duplicateDocumentCount=0,无需执行正式清理。如果大于 0,确认样本无误后执行:
curl -X POST 'https://{{host}}/api/admin/dataClean/cleanupDuplicateChats' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":false,"sampleLimit":20}'清理策略:每组重复的 appId + chatId 会保留 updateTime 最新的一条;如果时间相同,用 _id 倒序作为稳定兜底。接口只删除重复的 chats 会话头,不删除 chatitems、chat_item_responses 中的消息内容。
清理完成后,保持 SYNC_INDEX=true 并重启 fastgpt-app / fastgpt-pro,让服务重新同步索引。可进入 MongoDB 后确认两个索引都已经是 unique: true:
db.chats
.getIndexes()
.filter((idx) => ['appId_1_chatId_1', 'sourceType_1_appId_1_chatId_1'].includes(idx.name));6.2 Workflow V1 -> V2 迁移(可选)
只有从 <4.8 的旧版本直接升级,或历史上仍保留 V1 Workflow 数据的环境需要执行。该接口默认 dry-run,会扫描、转换并校验保存结构,但不写库。
curl -X POST 'https://{{host}}/api/admin/dataClean/v1WorkflowToV2' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":true}'确认返回统计后,执行正式迁移:
curl -X POST 'https://{{host}}/api/admin/dataClean/v1WorkflowToV2' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":false}'如果你已经在较早版本完成过 V1 -> V2 迁移,或从 v4.8 及以上版本升级,可跳过本步骤。
6.3 Workflow 脏数据清理(必须)
该脚本会扫描并修复 apps.modules 和 app_versions.nodes 中历史枚举表达式字符串、空值和旧结构兼容问题。所有自托管环境都应先执行 dry-run;如果返回统计显示存在可修复数据,再执行正式写入。
如果满足 6.2 条件,该脚本必须在 6.2 之后执行。
curl -X POST 'https://{{host}}/api/admin/dataClean/initWorkflowData' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":true,"batchSize":1000,"writeBatchSize":10}'确认 dry-run 结果后执行:
curl -X POST 'https://{{host}}/api/admin/dataClean/initWorkflowData' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"dryRun":false,"batchSize":1000,"writeBatchSize":10}'生产写入压力较高时,可以降低 writeBatchSize。未通过 Zod 校验的文档只会在响应中报告,不会被写回数据库。
6.4 归档旧沙盒(可选)
如果使用过旧版 sandbox workspace,可通过该接口修正历史 sandbox 状态字段,并按需把不活跃 workspace 归档到 S3。该步骤不影响新生成的 sandbox;不执行也不影响 v4.15 正式版升级,只是不会自动归档旧 workspace。可以手动删除旧的沙盒。
只检查、不触发归档:
curl -X POST 'https://{{host}}/api/admin/dataClean/initSandboxArchive' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"runArchive":false,"inactiveDays":0}'如果确认需要立即归档满足条件的不活跃 workspace:
curl -X POST 'https://{{host}}/api/admin/dataClean/initSandboxArchive' \
-H 'Content-Type: application/json' \
-H 'rootkey: {{rootkey}}' \
-d '{"runArchive":true,"inactiveDays":0}'一些大的影响
- ApiKey 功能调整,不再区分应用 key 和系统 key,只保留系统 key,如需兼容 openai sdk 用法,可使用
apikey-appId的方式传递 Token。已有的 apikey 保持兼容,不影响使用。具体和查阅 FastGPT API 文档说明 - 部分 API 增加了更为严格的数据格式校验,如过遇到报错:
zod parse error可提交 issue 反馈,可能因一些旧数据或者自定义数据结构与声明不一致。 - LLM 请求追踪记录新增团队隔离:
llm_request_records写入teamId,GET /api/core/ai/record/getRecord按{ requestId, teamId }查询,唯一索引调整为{ teamId, requestId }。升级前没有teamId的旧追踪记录将无法继续查询,页面会提示追踪记录已过期;如需排查历史调用详情,请在升级前导出相关日志或保留原始请求信息。自托管环境如关闭了SYNC_INDEX,升级后需要执行一次索引同步,确保旧的requestId_1唯一索引被移除。
🚀 新增内容
- 新增技能模块,Agent V2 可绑定静态 Skill 来运行。
- 重写 Agent V2 loop 逻辑,提升多轮工具调用和流程编排的稳定性。
- 沙盒支持自定义 npm 和 pip 源。
- 插件系统架构重写,支持插件级 runtime config,系统工具运行迁移到 local-pool。
- 商业版支持本地直连 FastGPT 调试插件。
- 重写 chatbox UI,支持快速滚动到底部、模型生成对话标题和更流畅的流式输出动效。
- 支持通过 LLM 生成对话标题。
- 新增循环节点,弃用旧的批量执行。
- 知识库搜索支持原生多模态 embedding 模型、图搜图和 Agent 模式权限过滤。
- 多模态模型支持音视频输入。
- API 密钥逻辑优化,统一 APIKey 管理并由请求显式传入应用上下文。
- 生成 DevAPI 和 System OpenAPI 两套 API 文档。
- 支持快速回复的输出语法。
- 第三方知识库新增钉钉知识库接入。
- 增加模型思考配置。
- 工作流模板导出支持同时导出名称和介绍。
- 全局变量输入框支持输入 object 类型数据。
- 工具调用模式下,如果开启虚拟机功能,用户对话框上传的文件会直接注入到虚拟机中。
- 增加文件解析、HTML 转 Markdown、文本切块 worker pool,避免并发太高导致资源耗尽。
- 支持目录深度环境变量,避免无限嵌套目录。可配置环境变量
MAX_FOLDER_DEPTH。 - S3 支持配置 CDN。
- Rerank 支持配置 defaultConfig。
- 分享链接/门户页支持语言切换,不再强制自动识别浏览器语言。
- Chat API 增加
dataId重复校验,避免脏数据进入工作流与流恢复合并逻辑。 - HTTP 节点支持配置忽略 TLS 证书校验,并支持返回完整错误对象。
⚙️ 优化
- 插件运行入口支持从对象存储拉取,并缓存到本地文件目录。
- 优化 OTEL 日志采集格式。
- 禁用工作流无效连接模式。
- 增加父子节点选中互斥功能,解决同时选中父子节点时移动节点抖动的问题。
- 优化工作流节点名称、介绍输入和超长名称适配。
- 工作流编辑页因登录失效跳出后,自动保存草稿用于恢复。
- 工作流运行详情中,表单输入节点的文件字段以文件列表形式展示。
- 工作流数组引用类型增强校验,避免与二维数据冲突。
- 图片处理线程支持配置是否转化成 base64 发送给模型,
MULTIPLE_DATA_TO_BASE64=true变量。 - HTML 输出后自动切换为预览,减少手动打开预览的操作。
- 流恢复暂停和异常中断恢复体验优化,减少会话卡在「生成中」或停止态不准确的问题。
- 切换应用时按应用恢复最近会话,切换团队时清除本地 chat 缓存。
- 优化知识库搜索测试交互和知识库数据编辑弹窗。
- 知识库被删除后,应用编排时优雅提示。
- 知识库训练出现错误时优化提示,并支持一键全部重试。
- 过滤掉无效的知识库引用角标。
- PDF 解析将 PDFJs 替换为
liteparse,速度提高 3 倍。 - xlsx 解析自动去除空行空列,并补充合并单元格。
- 输入引导配置增加校验,避免错误配置自定义词库地址。
- 加强第三方知识库请求、HTTP tool parse、IP 检测和 Code Sandbox AST 检查等安全防护。
- 文件注入 messages 位置从 system 调整至 user,便于命中缓存。
- reason hide 开关完善,确保 UI 不显示时,请求 LLM 仍可保留 reason。
- chat2messages adapt 优化,避免出现独立的 reason。
- 工具运行空响应时自动补充
none,避免部分模型报错。 - 非管理员/访客触发余额不足时,优化提示。
- 无创建权限时隐藏模板功能。
- 应用、知识库、文件和文件夹等长名称展示优化:超出宽度时自动省略,hover 名称时展示完整内容。
- 技能模块相关弹窗、编辑交互和列表接口性能优化。
- 登录页 UI 优化。
- 站点同步限流错误提示去重。
- 应用/知识库增加虚拟列表渲染,优化大列表加载性能。
- LLM 请求追踪记录增加团队隔离,避免
requestId被跨团队用于读取请求体、知识库召回片段和模型响应。
🐛 修复
- 修复 Agent V2 模式下,模型响应报错会导致 step 重复执行。
- 修复知识库源文件预览和下载时文本类型响应缺少 charset 的问题。
- 修复工作流单节点调试存在异常默认值的问题。
- 修复模型配置
defaultConfig覆盖异常。 - 修复 TTS 语音播放适配最新 OpenAI SDK 时的报错。
- 修复知识库数据分块遇到代码块时可能出现超大分块的问题。
- 修复模型获取多模态文件链接异常。
- 修复 training 接口、HTTP tool parse 和 S3 私有对象 key 相关的潜在安全风险。
- 修复交互节点后的工具调用展开 MCP 工具异常。
- 修复工作流工具 array 和 object 类型工具调用参数 schema 异常。
- 修复发布渠道 - 门户 UI 偏移。
- 修复 v1/completions 接口
nodeResponse中quoteList未返回q、a的问题。 - 修复对话流恢复过程中的表单回填、文件列表恢复、节点响应保留、重复交互追加、临时历史标题和跨应用会话串显问题。
- 停止会话提示改为与后端生成态同步,移除停止时的 warning toast。
- v1/chat/completions 接口,返回 nodeResponse 时候,过滤掉了 q/a/index,该版本恢复返回。
🛠️ 代码优化
- 调整整体代码结构,升级 Next.js 并切换至 Turbopack 构建;容器默认 Node.js 升级至 24。
- 统一 Agent tool 的声明和运行方式。
- 插件服务从旧
runtime结构调整为 pnpm workspace monorepo,拆分为 HTTP 服务入口、领域模型、用例、API adapter、基础设施、SDK 和 CLI。 - app API 接口统一使用 zod schema 编写并生成文档。
- 拆分 AI request、工作流运行详情和对话框相关代码,降低模块耦合。
- 优化用户自定义密钥计费逻辑和 token 计算依赖。
- 服务端 env 加载统一使用
@t3-oss/env-core,增加类型检查;其余服务也采用集中导出 env 的方式使用环境变量。 - 升级工程化工具链,包括 ESLint、Prettier、textlint、lint-staged 和 TS6。
- 优化单测性能,全量测试从 10 分钟降至 5 分钟。
- GitHub Action 增强安全性。
- 流恢复相关模块补充设计文档与单元测试。
- volume manager 从 Bun 改为 Node.js 运行。
- 及时处理 worker 内图片,不再存留 base64,降低内存消耗。
- 增加系统处理字符串时的长度保护,如果长度过大会停止继续同步替换,避免高 CPU 负载。
- 工作流运行的 nodeResponse 改为扁平化存储,避免大的嵌套工作流保存失败。
- 移除所有内置 LLM 请求中的
temperature和max_tokens,避免部分模型不兼容。 - 修复工作流节点配置中
FlowNodeInputTypeEnum.*、FlowNodeOutputTypeEnum.*和WorkflowIOValueTypeEnum.*枚举表达式字符串脏数据导致输入渲染和 IO 类型判断异常的问题。 - 工作流文本框,ctrl+c 复制文本内容时,会被节点复制抢占,导致无法复制文本。
- chat 接口抽象,不再绑定 app, 改成平台级别通用。