deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
把 DSH(deepseek-harness)扩展成兼容 SillyTavern 生态的原生角色扮演工作区。
第一版主线已经可用:插件复用 DSH 的 LLM 路由、默认模型、密钥管理、Web 容器和插件安装机制,同时在 DSH 原生侧边栏和 conversation 区域提供 Tavern 角色扮演体验。管理入口是独立的 Tavern 面板;设置页保留当前配置的快速切换,不再承载全部资产管理表单。
当前面向 DSH 0.2.0-rc.2 验证。Fabric 不在第一版运行路径中。
chara/ccv3,以及 CHARX card.json 和 embeded:// assets。prompts[]、prompt_order[]、marker 和采样参数。swipes、swipe_id、swipe_info。chat_metadata.bookmark_link 回链,视图可跳回父聊天。position/depth/role 注入。group_only_greetings、group nudge 和 {{group}} 宏。USER_INPUT/AI_OUTPUT/WORLD_INFO/REASONING placement、minDepth/maxDepth、substituteRegex、trimStrings。/if 条件、随机/掷骰和聊天动作(/send、/trigger、/regenerate、/cut),composer / 前缀触发。409,客户端重新加载最新内容,不静默覆盖。0.1.0-rc.6(宿主尚未提供 agent/context 历史投影和 projection-aware compaction);0.2.0-rc.2 已确认仍未提供该 seam。插件不会把普通 compaction 冒充为主动遗忘,也不会静默回退到伪 managed 模式。详见 docs/exploration/2026-08-16-dsh-agentloop-native-audit.md。html 代码块会在隔离 iframe 中运行,支持内联 CSS、JavaScript 和常用 CDN 资源;普通文本与不完整流式内容仍按文本显示。把完整 HTML 文档、<head>/<body> 片段放进助手消息,或使用 html Markdown 代码块。消息保存后,
Tavern transcript 会识别并挂载前端;流式生成和编辑消息时仍显示源码,避免半成品脚本被重复执行。
支持的输入形式:
<!doctype html>... 或同时包含 <html> 与 <head>/<body> 的文档。<head> 或 <body> 的片段;缺少外层文档时,运行时会自动补齐 doctype、viewport 和基础样式。html;普通代码块和不完整 HTML 仍按文本显示。例如:
```html
<!doctype html>
<html>
<body>
<button id="counter">0</button>
<script>
let count = 0
document.querySelector('#counter').onclick = () => {
document.querySelector('#counter').textContent = String(++count)
}
</script>
</body>
</html>
```
每个前端使用 sandbox="allow-scripts" 的独立 iframe,且不授予 allow-same-origin:脚本不能读取或操作宿主页面、
Cookie、window.parent、TavernHelper 和 DSH API(高度回传仅使用受校验的 postMessage)。运行时 CSP 允许内联 CSS/JavaScript,
以及以下静态资源源:cdn.jsdelivr.net、testingcf.jsdelivr.net、cdn.tailwindcss.com、
cdnjs.cloudflare.com、unpkg.com、esm.sh、fonts.googleapis.com 和 fonts.gstatic.com;图片、字体和媒体
可使用 https:、data: 或 blob: URL。
以下能力明确不在运行时范围内:
fetch、XHR、WebSocket 等业务网络连接(connect-src 'none')。object/插件、表单提交和访问宿主 DOM、Cookie、存储或 API。iframe 高度由 ResizeObserver 回传,并限制在 80-1200px;超出部分在 iframe 内滚动。TUI/headless
仍显示原始消息文本,不执行前端脚本。
安装插件并重启 DSH 后,可以在 Tavern 聊天中发送上面的示例,或让模型生成一个带按钮的 html 代码块,
保存消息后点击按钮即可验证 HTML、CSS 和 JavaScript 是否正常运行。
点击 DSH 原生侧栏底部的 Tavern 按钮即可打开管理面板。面板采用与 DSH Settings 接近的两栏布局,左侧切换分区,右侧集中处理资产和行为配置;窄屏会自动将分区导航折叠为横向滚动栏。
面板包含以下分区:
编辑器会显示未保存状态,取消离开时提示确认,页面关闭时提供浏览器级离开保护。角色卡、世界书和预设的保存都经过服务端格式校验,再写回 $DSH_HOME/tavern/。
插件保留独立的 RP prompt/生成循环,但 UI 进入 DSH 原生表面:
| DSH slot | 用途 |
|---|---|
conversation.view |
Tavern JSONL transcript |
conversation.composer |
Tavern session 的 RP 输入框、模型选择与 Stop |
conversation.session.header.actions |
当前角色、regenerate 与原生 session stats |
settings.section |
Active setup 快速切换与打开 Tavern 面板的入口 |
shell.overlay |
Tavern 管理面板 Modal,以及侧栏聊天树 adapter 的生命周期承载 |
sidebar.footer.action |
常驻 Tavern 面板按钮,与原生 Settings 并列 |
DSH rc.6 没有可追加到原生 session tree 的正式 list slot。侧边栏因此使用一个集中、版本敏感但失败关闭的 DOM adapter:只匹配可见左侧 [role="tree"],按 workspace 路径/ID 隐藏 Tavern (internal) 分组,并按 state.sessionBindings 过滤旧版 Tavern 会话行;同时插入具名 data-dsh-tavern-sidebar-host。宿主重绘或虚拟列表更新时会重新应用过滤,解绑或卸载时可逆恢复。面板入口本身走官方 sidebar.footer.action,不会替换 Settings,也不依赖 adapter 是否成功挂载。
每个 Tavern chat 绑定一个正式 DSH session。绑定 API 通过插件内部桥接追加 plugin notice marker,使 session 进入 active 状态而不调用模型;Tavern view、composer 和标题栏 action 仅接管带有效 Tavern marker 的 session,普通 DSH 会话保持原生表面。酒馆标题栏会局部隐藏 DSH 自带的 agent preset 标签,并在切换回普通会话时恢复;Tavern 自建生成循环会把 turn/step、流式 chunk、assistant message 和 provider usage 镜像进同一 session,因此标题栏直接复用 DSH 的 sessionStats / tokenUsage projection。删除聊天时会追加 close marker 并归档对应 DSH session。
| 架构 / 模式 | 状态 | 实际行为 |
|---|---|---|
agent-tavern + dsh-native |
rc.6 可用,单角色新聊天默认启用 | 使用 DSH 原生 AgentLoop 和 composer;模型、工具调用、Stop、错误与统计都由宿主处理,原生 user/final assistant 事件投影到 Tavern JSONL。 |
agent-tavern + agent-managed |
rc.6 不可用 | 设置页显示宿主缺少 agent/context 与 projection-aware compaction 的原因并禁用选项;服务端也会拒绝该模式。 |
st |
保留并兼容 | 使用 Tavern 自有 /generate、流式生成、swipe、regenerate 和 STscript 路径。 |
| 群聊 | 固定使用 st |
宿主尚未提供可靠的 actor 元数据前,不创建群聊 AgentTavern 会话。 |
AgentTavern 工具的身份来自真实 DSH agent binding,模型不能通过参数伪造 sessionId、scopeId、角色或聊天身份。当前工具面如下:
| 工具 | 作用 |
|---|---|
tavern_character_get |
读取当前绑定角色的名称、昵称、身份摘要、描述、性格、场景和角色卡版本。 |
tavern_lore_search |
按查询词和预算检索全局启用、角色关联及卡内嵌世界书。 |
tavern_history_search |
在当前绑定聊天(可选回溯 bookmark 父分支)按词法检索历史消息。 |
tavern_scene_get |
读取当前绑定聊天的场景、消息数量和聊天元数据。 |
memory_search |
在当前 chat、character、agent 或 global 作用域做有来源的词法记忆检索。 |
memory_read |
按稳定 id 读取一条记忆及其来源。 |
memory_write |
在选定作用域写入带来源、标签、置信度的记忆;global 写入需在设置中显式开启。 |
memory_update |
按 id + expected revision 条件更新记忆,未提供的字段保持原值。 |
memory_forget |
按 id + expected revision 软删除记忆,保留审计记录。 |
variable_get |
读取当前作用域中的 typed JSON 变量。 |
variable_set |
写入变量并支持 expected revision 的 CAS 冲突保护。 |
variable_patch |
在同一作用域原子写入多个变量,任一 revision 冲突则整批失败。 |
variable_delete |
删除当前作用域变量,需 revision 匹配。 |
variable_list |
按前缀列出作用域内变量名和值摘要。 |
变量工具支持 chat、character、agent、global 与 turn 作用域;turn 作用域是单轮 scratch 状态,turn 结束时自动清空,global 写入默认关闭、需在设置中开启。角色卡支持可编辑的 agentTavern.identitySummary 身份摘要(管理面板角色编辑器内),AgentTavern 内核每轮注入该摘要;缺失时回退为名称和极短描述。投影失败时管理面板"变量"分区提供状态查询和一键重放入口。
ST 与 AgentTavern 新聊天共用 $DSH_HOME/tavern/workspace/ 下的 Tavern (internal) 工作区;插件按 workspace 路径/ID 从原生侧边栏隐藏整个分组,旧宿主没有身份属性时仅在标题唯一时回退。升级前已经存在的宿主会话不会跨工作区迁移,但绑定的 Tavern 会话行仍会按插件过滤。
agent-novel 是与 AgentTavern、ST 并列的第三种会话架构:全自动小说推演(提案 0005、写手子代理补充见 提案 0007)。先落盘大纲再分单元写作,正文只经 novel_body_commit 原子提交,作者指令走台账 + 修订协议,冲突指令必须引用用户澄清/撤回消息才能解除。
| 能力面 | 状态 |
|---|---|
| 存储 / 调度 / 提交协议 | 可用:HEAD 单一提交点、不可变修订快照、单写者所有权、认领令牌与幂等重试 |
| 作者干预 | 可用:指令接收屏障、修订覆盖层(chapters overlay + droppedChapterIds)、blocked 冲突暂停与澄清引用解除 |
| 写手子代理 | 可用(writerMode: inline | subagent,默认 inline):W1 产稿 + W2 单单元委托自提交,真机 A/B 后再切默认 |
| 阅读 / 导出 | 可用:章节 Markdown 投影、ZIP 导出、记忆检索索引 |
模型侧工具面(novel_*,身份一律来自会话绑定,不接受参数传入 novelId):novel_status_read、novel_requirements_read、novel_outline_read/create/revise、novel_requirement_block、novel_unit_claim/supersede、novel_body_commit/read/search、novel_chapter_complete、novel_finish、novel_character_read、novel_lore_search、novel_facts_read、novel_writer_draft/delegate,以及绑定小说作用域的 memory_search / memory_read 和 tavern_deduce 适配器。设计契约以提案 0005 §11 工具表为准。
| Package | 说明 |
|---|---|
@dsh-tavern/format |
卡、PNG/CHARX、世界书、preset(chat completion / context / instruct / textgen)、群组文件、regex 脚本和 chat JSONL 的解析与无损往返 |
@dsh-tavern/lore |
World Info 激活和 timed effects 引擎 |
@dsh-tavern/macros |
角色、时间、随机、变量等宏引擎 |
@dsh-tavern/pipeline |
preset 顺序、lore、persona、历史和 token budget 的 prompt 装配(chat completion + 群聊回合) |
@dsh-tavern/script |
ST regex 脚本执行器与 STscript 解释器 |
@dsh-tavern/store |
$DSH_HOME/tavern/ 原子文件存储、revision 和 session binding |
dsh-tavern |
自包含 Node half、Web client half、安装元数据和 gates |
要求 Node.js 22+,并已安装 DSH。
git clone https://github.com/LingyeSoul/dsh-tavern.git
cd dsh-tavern
pnpm install
pnpm run build:plugin
dsh plugin --profile web add ./packages/plugin
dsh --profile web
DSH 桌面版的插件安装框等价于在 profile 目录执行 pnpm add <spec>,安装目标是 desktop profile。spec 必须落到 packages/plugin:仓库根是 monorepo 容器,不声明 dsh.bundle.patch,插件管理器会以「这个包没有声明组合包,不能作为插件管理」拒绝,并回滚 package.json 与 pnpm-lock.yaml。
桌面版「设置 → 插件 → Git 仓库」填子目录 spec:
github:LingyeSoul/dsh-tavern#path:/packages/plugin
等价的 HTTPS 写法(#path: 参数相同):
https://github.com/LingyeSoul/dsh-tavern#path:/packages/plugin
命令行安装到 desktop profile(dsh plugin 把参数原样转发给 pnpm):
dsh plugin --profile desktop add github:LingyeSoul/dsh-tavern#path:/packages/plugin
dsh --profile desktop
已有源码检出时可直接挂本地目录;桌面版安装框只接受绝对路径,相对路径会被 install-spec 拒绝:
dsh plugin --profile desktop add <仓库绝对路径>/packages/plugin
git spec 固定到安装时的提交,不跟随源码更新;version.json 不纳入 Git,设置页显示的是构建期注入的版本与 commit(scripts/build-plugin.mjs 经 esbuild define 写入 __TAVERN_VERSION__/__TAVERN_COMMIT__)。
插件自带从 GitHub 发现新版本与一键更新,桌面版不需要再手敲 dsh plugin。
已安装 v0.3.9 (8271f20))、GitHub 上的最新构建、待合入的 commit 列表与上次检查时间。启动后延迟 12s 首查、每 6h 复查,结果缓存在 $DSH_HOME/tavern/update-state.json;「检查更新」按钮穿透缓存立即查。packages/plugin/package.json 的 version 为准(规则见 decisions/2026-10-05-desktop-plugin-self-update.md)。dsh plugin(桌面版自带 CLI,直接改 profile 的 package.json + pnpm-lock.yaml)→ plugin-manager 服务 → GitHub checkout 覆写的顺序落地,进度日志实时显示在卡片里。三条路径都需要重启 DeepSeek Harness:包替换要新的 JS module generation,宿主 HMR 不监听 node_modules。api.github.com → raw.githubusercontent.com + git ls-remote → commits atom feed。企业 TLS 中间人会让 node 的 fetch 证书校验失败(unable to verify the first certificate),因此每个 HTTP 请求在 fetch 失败后自动用系统 curl 重试。dsh-tavern 行写 checkForUpdates: false,或设 DSH_TAVERN_DISABLE_UPDATE_CHECK=1 关闭自动发现;DSH_TAVERN_DISABLE_CURL=1 关闭 curl 兜底;GITHUB_TOKEN/GH_TOKEN 可提高 GitHub 限流配额。GET /api/dsh-tavern/update(缓存快照,?refresh=1 穿透 TTL)、POST /api/dsh-tavern/update/check、POST /api/dsh-tavern/update/install({ "wait": false } 立刻返回,进度轮询 GET update)。装了插件之后优先用面板里的内置自更新(见「内置自更新」一节):发现新版本 → 一键更新 → 重启 DSH。手改源码的开发流程仍是:
dsh plugin add 以本地 link 方式挂载插件,因此代码更新后只需重新构建并重启 DSH:
cd dsh-tavern
git pull
pnpm install
pnpm run build:plugin
dsh --profile web
若遇到依赖残留或版本不一致,可先移除再重新添加:
dsh plugin --profile web remove dsh-tavern
dsh plugin --profile web add ./packages/plugin
跨 DSH 版本的宿主形状兼容层(会话事件日志探测、宿主包锚解析、client 工作区
连接双面回退、client UI 原子解析、宿主形状诊断)集中在 packages/bind
(@dsh-tavern/bind),更新版本适配时先改这里。client half 的源文件是
packages/plugin/client/main.js;
client/index.js 是 pnpm run build:plugin 的拼接产物(把 bind 的 client
探测模块注入 __DSH_BIND_CLIENT_SLOT__ 标记处),不要直接手改,改了会被下次
构建覆盖。插件激活时会输出一行 dsh-tavern host shape: {...} 日志,报告命中的
宿主形状绑定路径,排查宿主版本差异从它读起。
pnpm run check
打开 DSH 后:
Tavern tab。插件 Node bundle 是单一 packages/plugin/index.mjs,五个纯库均已内联。无需用户额外安装公共 @deepseek-ai/* 运行时依赖;client closure 由 DSH profile 注入。
pnpm run check
当前基线:42 个测试文件、574 项测试通过;12 个插件 gates(含 update-routes、构建 stamp 断言、AgentTavern 隔离、native header adapter、内部工作区和 client VM mount)全部通过。完整 pnpm run check 需要可解析 DSH 官方运行时;本仓库验证使用 DSH 0.2.0-rc.2 的隔离 runtime(.npm-cache/dsh-runtime,受限环境依次回落 NODE_PATH 与全局安装)。会话事件写入的宿主契约(V4 关系准入、assistant 结算 usage/stream)由 packages/plugin/tests/agent-tavern-session-admission.spec.ts 直接对真实宿主代码回归。
GUI 已在桌面和 390x844 移动视口验证,包括原生 sidebar、Tavern 管理面板、角色卡/世界书/预设编辑器、conversation view/composer、流式生成、Stop、edit、swipe、regenerate、rename/delete 和 revision 冲突。
docs/proposals/0001-tavern-architecture.md:当前架构、边界与后备路线。docs/proposals/0002-branch-persona-groups-script-textcompletion.md:branch/bookmark、persona 管理、群聊、STscript/regex 与 Text Completion/Kobold 的范围与格式。docs/exploration/2026-08-14-fabric-architecture.md:Fabric 调研与后备定位。docs/exploration/2026-08-14-st-formats.md:SillyTavern 互操作格式与行为参考。decisions/2026-08-14-card-raw-passthrough.md:角色卡未知字段透传决策。decisions/2026-08-15-v2-feature-scope.md:v2 功能面的范围与形态选择。docs/proposals/0003-tavern-management-panel.md:Tavern 管理面板的信息架构、slot 选择和交互范围。docs/proposals/0004-agent-tavern-architecture.md:AgentTavern 原生 AgentLoop 架构、记忆/变量工具、遗忘策略和 ST 兼容模式。docs/plans/2026-08-16-agent-tavern-implementation.md:AgentTavern 的分阶段施工计划、宿主门禁、迁移规则与验证矩阵。docs/exploration/2026-08-16-dsh-agentloop-native-audit.md:DSH 0.1.0-rc.6 原生注入、compaction 与 Fabric fallback 审计。decisions/2026-08-15-tavern-management-panel.md:面板入口、角色删除级联、变量与侧栏共存的落地决策。decisions/2026-10-05-desktop-plugin-self-update.md:桌面版内置自更新(GitHub 版本发现、落地路径顺序、curl 兜底、构建期 stamp)。已安装插件建议使用 plugin-registry 的薄控制台管理 profile 中的 bundle 层栈、insert 行和启停状态,避免手改配置。将 <plugin-registry> 替换为该工具仓库的本地路径:
dsh plugin --profile web add <plugin-registry>/packages/plugin/console
GPL-3.0。项目只实现公开规范和可观察行为语义,不复制 SillyTavern 的 AGPL 源码。Fabric 与 dsh-ads 仅用于架构调研;第一版运行时不依赖它们。
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。