跳到主要内容

Cordis 桥接

Cordis 桥接层将 DeepSeek Harness(DSH)引擎嵌入 Libre WebUI 后端。DSH 作为插件树运行在 Libre WebUI 托管的 Cordis 运行时中,其能力以 Cordis 服务而非直接导入模块的形式提供。

桥接功能默认关闭。只有运维人员启用后,本页描述的功能才会运行,详见 Cordis 配置

为什么使用桥接而非直接集成

在 Libre WebUI 服务中直接导入 DSH 软件包,代码虽然更短,却会形成编译时依赖。这样,无论更换模型适配器、替换智能体循环还是移除引擎,都需要修改并重新部署 Libre WebUI。

桥接层反转了这一依赖关系。Libre WebUI 只依赖一个抽象接口,由 Cordis 组合文档决定如何实现:

  • 无需重新构建即可切换目标。 组合是 YAML 文件,更换引擎的提供商只需修改配置。
  • 配置能力。 每项能力对应一个 Loader 行。运维人员维护的组合变更在宿主下次启动时生效。
  • 完整移除。 引擎安装的所有服务、监听器和副作用都归根纤程所有。释放根纤程即可撤销全部内容,因此可在不重启 Libre WebUI 的情况下停止引擎。

分层

具体的 DSH 依赖都限制在 backend/src/cordis/dsh/ 内。路由和应用服务使用桥接接口。Work 驱动使用独立的内存组合,绝不会挂载宿主文件系统插件。

接口约定

接口定义位于 backend/src/cordis/contracts.ts,刻意保持精简:仅以不依赖引擎术语的形式描述 Libre WebUI API 所需的数据。

接口用途
DshEngine.status()各引擎服务的生命周期状态(pending / ready / failed
DshEngine.modelConfiguration()当前组合的模型和提供商默认值
DshEngine.listSessions()按最新优先排序的会话摘要
DshEngine.getSession(id)获取会话及其投影消息
DshEngine.createSession(opts)预留会话 ID 和工作目录
DshEngine.updateSessionSettings(id, settings)空闲时持久化真实模型选择和原生文件系统权限模式
DshEngine.decideApproval(id, approvalId, decision)为所属会话处理一项待决的原生工具审批
DshEngine.deleteSession(id)结束会话并释放其智能体
DshEngine.listAgents()列出运行中的智能体,并标记根或子智能体
DshEngine.listTools()引擎注册的模型可用工具
DshEngine.sendMessage(id, txt)开始一轮并返回流句柄
DshEngine.cancel(id)取消会话正在执行的一轮

此接口作为 Cordis 服务 libreDshEngine 提供。使用方通过 ctx.get('libreDshEngine') 读取它,不直接导入桥接模块。

EngineStreamChunk 携带 textreasoningtool-calltool-resultapproval-requestapproval-decisionerrordone。实时帧按所属智能体和会话路由,不会再次发送对应的持久化助手消息。sendMessage 返回的句柄通过 subscribe 重放已发送的内容,因此即使首个令牌在 HTTP 处理器挂接监听器之前就已生成,也不会丢失。

时序:一轮聊天

一次请求之后,一轮对话就是单向的服务器到客户端序列,因此使用 NDJSON。将它保留在 POST 请求内,可避免第二次握手、票据及重连协议,并让整轮对话都属于同一个经过身份验证的请求。

DONE 与 PENDING

Cordis 在插件声明的服务可用时才激活插件,因此配置行会处于尚未运行的状态。必须区分以下两个概念,混淆它们是引擎静默不响应的常见原因。

Loader 条目状态。 Loader 跟踪每一行的 PENDING → LOADING → ACTIVEFAILED 状态。缺少声明服务的行会一直等待,而不是报错,因此不完整的组合可能表现为引擎已启动,却不提供任何功能。

服务可用性。 宿主为每个预期服务报告以下状态:

状态含义原因
pending尚未在上下文上注册提供该服务的行尚未激活或已禁用
ready已注册且可用提供该服务的行已激活
failed已声明但不可用通过 detail 字符串说明原因

host.status() 列出每个预期服务的可用性,并指出缺少哪些必需服务;GET /api/cordis/health 提供相同信息。若组合缺少必需服务,启动会抛出错误,而不是提供只返回空列表的引擎。

以下两条依赖链容易配置错误:

  • 缺少 systemPrompt 时,dsh-tools 无法启动。
  • 只有 agentssessionsllmtoolssystemPromptsessionProjections 全部存在,dsh-agent-loop 才能启动。

缺少其中任一项时,组合可能拥有正常的会话存储,但引擎永远不会回复消息。

提供商配置

随附的 libre-webui-llm-adapter 行服务于 Libre WebUI 中配置的模型提供商。引擎页面的模型选择器为会话选择提供商模型,无需替换该行。

组合中插件行的变更在宿主下次启动时生效。请重启后端,或在管理员开关未锁定时关闭再启用 Cordis。持久化会话保留在配置的存储中,并通过当前组合恢复。

可信集成代码可以直接使用 Cordis Loader 生命周期 API。桥接层不暴露适配器替换端点,也不会在替换失败时自动恢复先前的适配器。

回滚

释放宿主的根纤程会移除引擎安装的全部内容。保证来自这一统一的归属关系:

  • 服务由插件注册,会随其纤程一起撤销。
  • session/event 订阅在桥接自身的构造函数内注册,归桥接行的纤程所有。
  • 桥接层跟踪智能体句柄,并在清理副作用中释放它们。
  • 宿主释放拥有全部配置行的根上下文。

stopCordisHost() 是幂等的,并已接入后端关闭流程。引擎的定时器和文件句柄会显式释放,而不是等待进程退出。

会话标识与持久化

引擎页面在创建会话时预留一个不透明的会话 ID。启用持久化时,会话头立即写入存储,因此空会话也能在重启后保留。桥接层同时列出已存储和运行中的会话,通过 DSH 验证过的持久化 API 读取日志,并在后续对话中以同一 ID 恢复智能体。新用户消息使用 DSH 的带标识消息构造器。

删除会话时,会先取消并释放其智能体,再移除会话文件。本地 JSONL 删除适配器验证存储和会话路径,并拒绝符号链接。不支持删除的自定义持久化后端会返回错误,不会声称数据已移除。

取消会传递给原生智能体、模型请求及工具执行。客户端断开连接会取消当前轮次;已完成的消息仍然可读。流重放缓冲区有容量限制,能保留在读取方连接之前快速返回的响应。

宿主引擎是单副本 solo 功能。团队部署不能挂载其本地 JSONL 运行时。沙箱化 Work 则使用现有的 SQL 任务、运行、消息、审批和事件仓库。

HTTP 接口

方法路径用途
GET/api/cordis/health桥接状态,无需身份验证
GET/api/cordis/sessions列出会话
POST/api/cordis/sessions创建会话
GET/api/cordis/sessions/:id读取会话及消息
DELETE/api/cordis/sessions/:id结束会话
POST/api/cordis/sessions/:id/messages发送消息并流式返回 NDJSON
POST/api/cordis/sessions/:id/cancel取消正在执行的轮次
GET/api/cordis/agents列出运行中的智能体
GET/api/cordis/tools列出注册的工具

/health 外,每条路由都要求经过身份验证的管理员会话。桥接层无法处理请求时返回 503,其中 codeCORDIS_DISABLEDCORDIS_STARTINGCORDIS_UNAVAILABLE

Libre WebUI Cordis 引擎页面,展示会话列表、引擎注册的工具和流式聊天记录。

页面实现位于 frontend/src/pages/CordisPage.tsx,可从侧边栏访问 /cordis。它列出会话及注册工具、创建会话,并将当前轮次流式写入记录。桥接关闭或无法启动时,页面显示原因而非空列表,避免把“没有会话”与“没有引擎”混为一谈。

浏览器客户端位于 frontend/src/utils/api/cordisApi.ts,只调用上述接口,不导入后端类型或任何 @deepseek-ai/* 软件包,因此替换引擎无需修改前端。通过 sendMessage(sessionId, text, { onChunk }) 消费一轮响应;客户端自行解析换行分隔的 JSON,并处理被网络读取边界拆开的数据块。

引擎聊天控件

引擎页面渲染 Markdown、表格和带语法高亮的代码块,并提供回复和代码的复制控件。系统提示词与注入的运行时上下文收纳在默认折叠的会话上下文中,不会显示成用户编写的消息。公开的推理和工具活动分别折叠展示,重新加载后工具结果仍与正确操作配对。

请在输入区选择真实的提供商模型。选择器列出当前管理员可用的本地和插件模型及其提供商标识。Chat 中的人设和智能体选择不是模型 ID,也不会将其指令注入引擎会话。旧的失败人设模型会话头不会用作默认模型提示,已保存日志保持不变。

每个会话都有独立的只读工作区写入设置,由 DSH 文件系统策略及桥接层的规范工作区边界强制执行。输入区显示工作区范围。设置以原生会话事件保存,重启后保留;轮次执行中拒绝修改。

原生提权请求会作为附属于该操作的允许一次 / 拒绝卡片显示。批准仅对这次请求有效,不改变长期权限模式。过期或已取消的请求无法获批,无界面的 Chat 调用会拒绝无法展示的询问。桥接层不提供无限制宿主访问。

额外的管理员端点包括:

方法路径用途
GET/api/cordis/models可用的提供商模型及当前真实模型默认值
PATCH/api/cordis/sessions/:id/settings设置会话的模型和/或权限模式
POST/api/cordis/sessions/:id/approvals/:approvalIdallowed-oncerejected 处理一项待决请求

在 Chat 中使用引擎

同时启用访问与策略 → CLI代理模型Cordis 引擎,管理员即可在 Chat 中选择 DeepSeek Harness。每个请求都会创建新的临时引擎会话,只包含该 Chat 请求提供的对话记录。常规 Chat 数据库仍是权威来源;不相关的对话、分支和重试不会共享隐藏的引擎历史。临时引擎日志在完成或取消后移除,也不会出现在引擎页面中。

标准提供商组合还会在智能体组列出 DeepSeek Harness · 模型(提供商)。保存的 ID 包装了引擎页面所用的同一限定提供商路由:dsh:lwui:ollama:<model>dsh:lwui:plugin:<plugin>:<model>,各提供商组成部分均使用百分号编码。可选的本地原生 DSH 连接从该实例的实时目录添加 dsh:native:<provider>:<model> 选项,并复用其原生提供商配置与凭据。可从 libre-webui/dsh-native-provider 安装 Apache-2.0 许可的独立软件包,或从 Libre WebUI 发行版准备包。两者使用 @libre-webui/dsh-native-provider 这一名称,并将提供商密钥保留在原生 DSH 中。连接要求同一 Unix 主机和 OS 账户,通过私有 Unix 套接字通信;它无法隔离共用该账户的应用。它只提供模型推理,不提供原生智能体会话或原生工具执行。安装、配置档重启、升级和移除方法请参阅配置指南。缺少连接或所选模型时会失败,不会切换提供商。原生调用也会出现在提供商使用情况中,显示所选模型、报告的令牌数、延迟及结果状态。基础 dsh 配置档继续使用当前组合的默认模型。自定义适配器组合只暴露基础配置档,不会宣传不受支持的 Libre WebUI 提供商覆盖选项。

标题和思考摘要会将 DSH 选择解析为底层提供商,直接发送文本请求,不使用工具或创建智能体会话。基础配置档请求读取运行中引擎的默认值,包括桥接行覆盖项,不会根据当前提供商目录猜测。自定义适配器需要为这些功能明确配置 Ollama 或插件任务模型。所选提供商不可用时,会正常失败或显示本地标题预览,不会向其他提供商发出请求。

请求使用经过身份验证的管理员的提供商设置和凭据,不会暗中选用其他管理员的凭据。默认工作区仍是配置的 Cordis 工作区;Chat 不会改用服务器用户的主目录。

沙箱化 Work

启用 Cordis 后,Work 提供独立的引擎控件,可选 Libre WebUIDeepSeek Harness。模型选择器保留普通模型名称和提供商标识。对 LWUI 支持的提供商,DSH 选择内部保存为 dsh:<model>;原生 DSH 选择则保存 providerType: dsh、确切的原生提供商 ID 和原始模型 ID。常规工具能力和访问检查仍然有效;使用原生凭据还要求活跃管理员身份。

每次运行都会创建隔离的内存 DSH 智能体循环。模型适配器接收当前 Work 记录、提供商元数据、图像及工具模式。工具函数只等待 Work 返回结果,无法读取宿主文件或启动宿主进程。

Work 继续负责验证参数、请求批准、在工作区运行时执行工具、在 SQL 中记录结果与提供商重放状态、强制预算和发布事件。被拒绝的工具返回正常的拒绝结果。取消会释放 DSH,并遵循 Work 既有的容器清理流程。工作进程恢复后,新的 DSH 驱动接收恢复的 Work 上下文,不会重复已完成工具的副作用。

Work 集成不需要宿主引擎组合或 JSONL 会话存储。它遵循 Work 既有的 Docker/Kubernetes 运行时和部署规则,包括团队模式的共享持久化要求。

安全边界

引擎页面和宿主侧 Chat 智能体仅供管理员使用。引擎会话及其系统提示词属于共享管理员控制台,不是按用户隔离的工作区。普通账户无法通过 API 读取、创建、修改或取消这些会话。

随附的宿主文件系统工具通过规范化目标路径(包括符号链接解析)将读写限制在配置的工作区内。会话覆盖的工作目录必须仍在该工作区中。原生 DSH 修改策略及引擎单次审批仍然适用。运维人员安装的组合插件属于可信服务器代码,可以授予额外能力。引擎审批独立于 Work 的审批与容器执行流程。

Work 的 DSH 驱动是独立的:它不挂载宿主文件系统、shell 或持久化插件,只能通过 Work 现有的授权和沙箱执行。远程模型提供商仍需主动启用,并使用所选账户配置的提供商路由。