DSH Plugins Marketplace

DSH Plugins

Plugins

/

Development & Infrastructure

/

dsh-ai-with-u

T

dsh-ai-with-u

Manifest valid★ 1

DeepSeek Harness 角色扮演插件:选卡即用、日记记忆、可视化面板

UI (client)hasBundlePatch

dsh-ai-with-u

给 DeepSeek Harness 的角色扮演插件。 蒸馏任意ip角色卡并让你的大肥鱼成为TA,选一张角色卡点「启用」,人设立刻生效;点「退出」,干净拔出,正常工作不受影响。

version npm license platform node self-checks

角色管理器面板:左侧角色簿,右侧角色卡详情与编辑入口

面板实拍:左侧角色簿,右侧是角色卡详情——34 个字段都可以就地编辑。


它是什么

一个 DSH 插件,负责三件事:把角色卡注入系统提示词、维护角色的日记记忆、提供一个管理面板。

自带完整的蒸馏系统,可指引大肥鱼联网收集资料,整理一张任意 IP 的角色卡并启用角色扮演——只要网上能搜到,就能蒸出来! 内置三张卡:Ave Mujica 的丰川祥子、明日方舟的阿米娅、崩坏的昔涟。 标准的酒馆卡格式,可导入现成酒馆卡,也可自制。

聊天本身仍然走 DSH 自己的会话——不做自定义聊天界面,不劫持消息流。插件只在「人设从哪来、记忆写到哪」这两个环节介入。

启用前:和普通 DSH 会话没有区别
启用后:模型以角色身份说话,但该跑测试跑测试、该读代码读代码
退出后:系统提示词里一个字都不留,和没装过一样

为什么会有它

原项目 ai-with-u 是一个 skill:角色卡、日记、时间差全有,但所有确定性逻辑都交给模型——建目录、读写 JSON、追加 markdown、算索引。模型得同时扮演角色和文件系统,出岔子是早晚的事。

这个插件把确定性部分收进代码,只把「怎么写台词」留给模型。

原 skill本插件
提示词SKILL.md 13 KB,每轮全量注入启用态约 2.8–3.3 KB(lite 档),不启用时为 0
文件读写模型自己动手插件代码保证,原子写 + 跨进程锁
角色管理在对话里说指令可视化面板
生效时机一直生效可插拔,退出即卸载

有两处是故意不做,别当成缺功能:

  • 8 个场景的扮演测试(原 skill 里那套「测一遍人设像不像」的用例)没搬。人像不像只能靠聊,靠脚本测不出来——能测的(提示词长度、字段完整性、世界书命中、导入解析)都已经进了自检,共八套。
  • manifest / full_card 不单独落文件,收进 card.json 的 extensions.aiwu 里。CCv3 本身只有一份真相,再存一份清单等于制造两个会互相漂移的事实来源;要读清单就 GET /character。

它是怎么工作的

flowchart LR
    U[你的消息] --> S[DSH 会话]
    S --> A{每轮组装系统提示词}
    A --> L0[L0 底线]
    A --> L05[L0.5 纪律包]
    A --> L1[L1 角色卡]
    A --> W[世界书命中]
    A --> D[日记与会话摘要]
    L0 --> M[模型]
    L05 --> M
    L1 --> M
    W --> M
    D --> M
    M --> R[角色口吻的回复]
    R --> DB[(写回日记 / 会话状态)]
    DB -. 下一轮 .-> A

分层注入

层级什么时候在内容体积
L0 底线启用期间优先级声明 + 扮演底线约 365 字符
L0.5 纪律包启用期间,按档位禁止词库、消息形态、动作格式、输入识别、内容边界lite 555 / full 736 字符
L1 角色启用期间CCv3 角色卡(声线优先)+ 时间差 + 最近日记约 1.9–2.4K,随卡增长
世界书命中才注入关键词 / 常驻条目,预算 12 条 · 6000 字符典型约 0.2K
L2 长流程工具按需蒸馏、建卡向导不进系统提示词

退出时五段全部返回空串,宿主会过滤掉——这是「干净拔出」的实现方式,不是靠删文件。

纪律包有三档:off(关掉)/ lite(默认)/ full(多一段「遮住名字也要猜得出是谁」的语态锚点 + 每 10 轮日记自检)。切档走 POST /_dsh/ai-with-u/discipline,偏好存在 _active.json 里,退出角色也保留。

插拔

  • 启用状态落盘,重启 DSH 自动恢复
  • awu_* 工具与角色同进同出:启用才挂载,退出即卸下
  • 世界书按关键词命中,同一轮复用结果,不重复注入、不跨轮累积

界面

入口在左侧栏底部(与用量统计插件同席位)。展开态显示「角色管理 + 当前角色名」,收起态收成 36px 圆徽,点击弹出悬浮面板。

四个分区:

  • 角色簿 — 卡片墙、导入角色卡、注入预览、详情页、完整编辑
  • 日记 — 时间线、关键词搜索、按月折叠、导出 markdown、逐条改写、危险区
  • 统计 — 角色数、记忆条数、对话轮次
  • 指南 — 首次打开时的使用说明

注入预览在角色簿详情的「预览」入口:列出此刻真正会进系统提示词的五段(L0 底线 / L0.5 纪律包 / L1 角色 / 世界书 / 时间差),每段给段名与字符数,下面是逐段正文,最后给总字符数。它显示的是宿主那一刻的真实渲染结果(GET /preview,纯只读:不刷新缓存、不写盘),不是面板自己另算的一份——两套算法的预览迟早会和实际注入对不上。

日记页支持记忆回顾:关键词搜索(标题、正文、日期都能命中)、按月份折叠,以及把当前角色的日记导出成 markdown 文件(浏览器里直接下载,不经过宿主)。

角色簿左栏顶部并排两枚同级按钮:蒸馏角色卡(从作品里蒸一张)和 自创角色卡(从零写一张)。旁边是对话模式的胶囊「纯文本 / 文本 + 动作」,当前值高亮,点一下立刻生效——不需要先启用角色,因为模式是偏好不是角色属性。

自创角色卡填三格(名字 / 身份 / 一句话背景)就能落档。想省事就勾「让 AI 补全人设」:插件先把这张骨架卡存好,再把补全指令发到当前会话,AI 会先问你 3–5 个关键问题(声线、关系、雷区、称呼),然后按酒馆卡格式补齐人设、开场白和世界书。合理推断标 [AI推断],推不出来的标 [待补],不编造。

角色簿左栏还有「导入角色卡」,吃酒馆卡的三种形态:带立绘的 .png、.charx 压缩包、裸 .json。选完文件先出预览(识别到的名字、格式、全部 warnings),同名卡会提醒冲突并要二次确认;确认后才写盘,取消不落任何文件。文件上限 11 MB——base64 会膨胀 4/3,11 MB 传到宿主正好还在 16 MB 收包线内;带立绘的 PNG 卡常见 3–10 MB。

「世界书太大」不再拦导入,只给警告:世界书是按需注入的(12 条 / 6000 字预算),超大书不会把提示词撑爆,只是超出预算的条目进不去当轮上下文。真正没有预算、直进提示词的那五个原生字段(描述 / 性格 / 场景 / 系统提示 / 历史后指令)仍然有硬上限。

角色卡编辑器是 10 组 34 字段,第 11 个分区是世界书:条目名、关键词 / 副关键词(逗号分隔)、内容长文本(可全屏写)、常驻、优先级、插入顺序、逐条启用与上移下移。高级项里有位置(角色设定前 / 后)、大小写敏感、selective、正则。

顶部体检按三档给结论,「必须处理」的只有两种真正会失效的情况:

档报什么
必须处理(error)非常驻且没有关键词(永远命不中)、内容为空(注入了等于没注入)
建议看(warn)条数超过建议线(30 条)——不会报错,超出预算的条目这一轮不进提示词,去「被裁条目」看清单
知道就好(info)偏长条目聚合一条(默认不逐条;单条超 3000 字才会单独点名,因为命中一次就挤掉别人)、共享关键词聚合一条

字数不是问题:世界书按需注入,总量再大也只是命中变少,所以「总字数超出」这条提醒已整条删掉(v0.3 之前会报,纯噪音)。体检只提示,不拦保存。

编辑器里「声线基因」是灵魂字段:说话节奏、自称、口头禅、禁忌词、小动作。这些决定「听起来像不像他」,所以给了金色描边和独立徽记。


安装

前提

  • DeepSeek Harness 桌面版(desktop profile)
  • Node 22.19+ 或 24+
  • 不需要编译 C++,零原生依赖

步骤

包已发布到 npm,可以跳过克隆直接装(装完仍要按第 3 步配 bundles):

npm install dsh-ai-with-u

GitHub Packages 上也有同一版本(scoped 名,需要带 read:packages 的 token):

npm install @treasure-hub-agent/dsh-ai-with-u --registry=https://npm.pkg.github.com

或者从源码构建:

git clone https://github.com/Treasure-hub-agent/dsh-ai-with-u.git
cd dsh-ai-with-u
npm install && npm run build
# 建 junction(Windows 上不要用 ln -sfn,它会静默退化成目录拷贝)
New-Item -ItemType Junction `
  -Path "$env:USERPROFILE\.dsh\profiles\desktop\node_modules\dsh-ai-with-u" `
  -Target "<你的克隆路径>"

然后编辑 ~/.dsh/profiles/desktop/package.json:

{
  "dependencies": {
    "dsh-ai-with-u": "link:<你的克隆路径>"
  },
  "dsh": {
    "profile": {
      "bundles": [
        // ...
        "dsh-ai-with-u"
      ]
    }
  }
}

最后重启 DSH。宿主不会热加载 lib/index.js。

⚠️ 不要在 profile 的 cordis.patch.yml 里手写插件行——包内 cordis.patch.yml 的 bundle.patch 会自动挂载,重复写只会干扰故障定位。


使用

  1. 左侧栏底部点「角色管理」
  2. 选一张卡点「启用」
  3. 开个新会话,像给老朋友发消息一样聊
  4. 不想玩了点「退出」

想换说话方式(要不要带 (动作))不用回面板:角色簿左栏工具栏有「纯文本 / 文本 + 动作」两枚胶囊,点一下 POST /mode 立刻切;也可以在对话里让模型切(awu_mode)。

开箱自带三张范例卡(丰川祥子 / 阿米娅 / 昔涟,都由插件自己的蒸馏流程产出)。首次启用时幂等种入:characters/ 已存在就跳过,不会复活你删掉的卡。

角色启用:两种作用域

「启用」有两种,互不覆盖:

作用域管谁动作
全局启用所有没绑定的会话(以及子代理)POST /activate
当前会话启用只绑这一个会话POST /bind {name, sessionId}

决议优先级(写死、可被断言):

会话绑定 > 全局启用 > 未启用

举例:全局启用阿米娅、当前会话绑定丰川祥子 → 这个会话是祥子,其它会话是阿米娅。 全局切换不会动任何已有绑定;取消绑定后该会话自动回落到全局。

两条硬边界(不是限制,是防串台):

  1. 绑定的卡被删掉 → 该会话视为「未启用」,绝不回落到全局。 否则你会以为在跟祥子聊、其实在跟阿米娅聊——这种「静默串台」比报错难查得多。重新绑定会自动解除这个状态。
  2. 子代理固定用全局角色,不继承父会话的绑定。 子代理有自己的 agent/session 查不到绑定,于是自然走全局。这是设计选择:让子代理继承会让人设意外泄漏到工具链深处。

面板怎么显示两态:详情页把「启用」拆成两枚动作——「当前会话启用」和「全局启用」,状态条分行显示 「当前会话:X(已绑定)」与「全局:Y」。点两者都会就地提示影响范围(「只影响当前会话」/「所有未绑定会话」)。 拿不到会话标识时(面板不知道自己在哪个会话)「当前会话启用」会置灰并说明原因,不会瞎猜一个 id 写进去。

提示词级的隔离是真的:宿主每段提示词都能拿到当前 Agent,所以同一个插件可以按会话渲染不同角色。 技术细节(PromptSection 没有 scope、但 text(context) 里有 agent)写在 docs/DEVELOPMENT.md §十四。

兼容旧卡与酒馆卡

  • 旧 34 字段卡:直接放进 characters/<名>/card.json,读时自动归一成 CCv3,首次保存时才落成新格式并留下 card.v1.bak.json
  • 酒馆卡导入:支持 .png(tEXt / iTXt 的 ccv3、chara 段)、.charx(zip 里的 card.json)、裸 .json(CCv2 自动升到 V3)
  • 世界书超限:不再拒绝导入或保存,改为返回 warnings(实际字数 + 上限)并在预览里逐条列出。世界书按需注入,超出预算的部分不会进提示词——书是完整的,只是这一轮用不到那么多

酒馆卡兼容矩阵(SillyTavern 字段级)

一张真卡(CCv3、89 条世界书、98869 字)跑过一遍之后逐字段核对的结论。「支持」= 功能真的生效,不是「没报错」。

ST 字段 / 特性状态说明
description personality scenario first_mes alternate_greetings✅ 支持原样保留并进 L1;开场白里的 {{char}} / {{user}} 按角色名展开
system_prompt / post_history_instructions✅ 支持前者作为「角色自带指令」进 L1(优先级低于系统提示词、高于角色描写),后者进收尾提醒
mes_example✅ 支持(有截断)进 L1「示例对话」,单卡上限 1200 字,超出截断并告警
creator_notes tags creator character_version group_only_greetings 等元字段✅ 保留不丢不参与注入;认不出的键进 extensions.aiwu.legacy.extra,一个字节都不丢
character_book(89 条 / 9.8 万字这种规模)✅ 支持(按需注入 + 双预算)每轮命中上限 12 条 / 6000 字;constant 条目走独立 allowance;被裁的条目在面板体检里列名字、日志里也带名字
use_regex(key 当正则)✅ 支持(带护栏)模式长度上限、只扫最近文本前 8000 字、明显灾难回溯的构造退化成字面量、坏正则不抛错(否则整轮对话进不去)
secondary_keys + selective✅ 支持四值 selectiveLogic(AND_ANY / NOT_ALL / NOT_ANY / AND_ALL);selective:false 时次级键不参与激活(与 ST 一致)
position: before_char / after_char✅ 支持分两个区块注入:「先读这些设定」与「相关设定」
position 写成数字(0 / 1)或 'before' / 'after'✅ 支持统一归一到 before_char / after_char(老 ST 导出常见数字写法)
@D 深度注入 / position: 4 / depth / role❌ 不支持(内容不丢)不做按消息深度插槽:这类条目仍会注入,只是当普通设定摆(默认 after 块),导入时统计条数并告警
constant✅ 支持(独立预算)常驻走自己的额度(默认 12000 字,卡级可覆盖),不再和关键词命中抢 6000 字。真卡实测 6 条有效常驻 9577 字,全部注入、0 条被裁
probability✅ 支持顶层 probability 优先,没有再读 extensions.probability(两种写法都有卡在用);稳定哈希,同一轮结果固定,不会每轮抖动
scan_depth / token_budget✅ 支持前者默认扫最近 4 条(近似 D0..Dn 槽),后者按 1 token ≈ 1.5 字换算成字符预算
recursive_scanning❌ 不支持字段认了但不执行:递归激活会放大预算与耗时,第一版明确不做
regex_scripts(正则脚本)🛡 屏蔽(不执行 · 不注入 · 不影响对话,字段保留)data.regex_scripts 与 data.extensions.regex_scripts 两个位置都保留不删(ST 卡是用户资产,删了将来导出/回灌会缺);同时可证明屏蔽:脚本正文不会出现在 L1 或注入预览里,去掉脚本后提示词逐字相同。导入预览给中性提示「本卡含 N 条酒馆正则脚本,已屏蔽」。口径常量 ST_SCRIPT_STANCE,详见 docs/DEVELOPMENT.md §十三 / §十四
depth_prompt❌ 不支持(字段保留)extensions.depth_prompt 随卡保留、写入不丢,但不读、不注入;非空时导入会明确告警「深度提示暂不支持,字段已保留」。需要的话把内容放进世界书常驻条目
assets(立绘)❌ 不支持导入时剥离并告警:本轮不做立绘落地,卡片其余内容不受影响
@@activate / @@dont_activate 装饰器✅ 支持影响该条目是否参与激活
@@depth / @@position / @@role / @@probability / @@cooldown 装饰器⚠️ 认识但不生效已知装饰器会从正文剥掉(绝不注入正文),但不改变注入行为;未知 @@xxx 整行丢弃
extensions.match_whole_words✅ 支持打开后按整词匹配(汉字里不误命中子串)

三条最容易踩的:① regex_scripts 不是「支持但没用到」,是屏蔽(DSH 侧没有可插入的渲染点,所以不执行、不注入,但字段保留); ② 深度注入(@D / position: 4)不支持,但内容不丢——按普通设定注入,只在位置上让步; ③ 世界书再大也不会整本注入,这是设计而非缺陷。

文件拖放归谁管

面板打开期间,文件拖放归面板处理。

DSH 的聊天区有一个「文件或图片拖动到此处即可添加」的拖放区,它是文档级的:文件在页面任何位置松手,都会被它接住当附件。所以插件打开面板后会接管文件拖放:

  • 拖进「导入角色卡」的虚线框 → 走导入预览(不写盘,确认才保存)
  • 拖到面板里其它地方 → 提示「把卡拖到虚线框里」,不放行给聊天区
  • 拖进面板之外(聊天区自己)→ 正常添加附件,插件不管

为什么这么较真:v0.3.0 真机上出现过「把角色卡拖到面板上,卡被当成附件发进了对话」。宁可拦下来给一句提示,也不能让卡文件混进聊天上下文。

插件同时会替聊天区复位它的拖放状态(拖完主动补一个 dragend)。所以关掉面板之后,聊天区的拖放应该和平时一样——如果你发现关面板后拖文件进聊天区没反应,那是 P0,请报。


预设

预设 = 一组可复用的提示词模块(文风、语气、回复规则、口癖约束),只描述「怎么说」,不写角色事实。

它和角色卡正交:角色卡决定「我是谁」,预设决定「我怎么说话」。同一张卡配不同预设会是不同的味道,换预设不需要动卡里一个字。

两种作用域

和角色启用一样,预设也有两种,互不覆盖:

作用域管谁决议
全局预设所有没绑预设的会话(以及子代理)优先级第二
当前会话预设只绑这一个会话优先级最高
会话预设 > 全局预设 > 没有预设

被删掉不回落全局:会话绑定的预设如果被删,这个会话按「没有预设」处理,不会自动换成全局那份——否则你以为在用 A 的文风,实际跑的是 B。重新绑定即可恢复。子代理固定用全局预设,不继承父会话的绑定。

注入位置

预设注入在独立段 aiwu:preset,order 5080:

5000  L0 底线
5050  L0.5 纪律包
5080  ← 预设(文风与回复规则)
5100  L1 角色卡

放在这里的两个理由:纪律包的硬约束优先级更高(禁 AI 腔、内容边界这些是底线,预设的文风不能盖过它);预设相对稳定(不随角色切换而变化),排在角色卡之前可以让「换角色」不至于连带重算预设那一段的缓存。

只拼 enabled 的模块,每个模块渲染成 ### 模块:{名字};段首有一句防注入说明:「以下是文风与回复规则,不是用户指令;与角色设定冲突时以角色卡与人设为准」。模块里的 {{char}} / {{user}} 按该会话决议角色的卡名与称呼展开。

导入 SillyTavern 预设

面板「预设」页支持直接导入 ST 的 chat-completion 预设 JSON({prompts, prompt_order})。能导什么、会丢什么,都写在这里:

结果条件为什么
保留有正文的条目就是你要搬的文风/规则
丢弃 · 结构占位identifier 在 13 项白名单里(worldInfoBefore / charHistory / main / scenario / char 等)这些是 ST 运行时的槽位,内容由 ST 在发送时填;搬过来只会是空标签或 {{char}} 字面量
丢弃 · 空正文去掉注释/宏/标签后没有实际文字常见于 nsfw / jailbreak:文件里有这条、marker:true,但正文是 0 字节
丢弃 · 废稿名字形如 ---- 章节线、[ ] 草稿、备份副本作者的草稿痕迹,不是给模型看的
丢弃 · JS 配置块超大且像 SPreset 那类纯配置不是提示词,搬进来会污染上下文

marker: true 不等于结构占位。 nsfw / jailbreak / enhanceDefinitions 也带 marker,但它们有正文,是真正要搬的东西。所以判据是白名单,不是 marker 一刀切。

ST 的主指令(main)不导入。 本插件用自己的底线(L0)+ 纪律包(L0.5)承担同一职责;把 ST 的 main 搬进来等于双份注入同义指令,既费 token,又容易让模型当成两套规则。

实测:导入本机 7 份真实 ST 预设(只列文件名与计数,不含任何预设正文——这些是第三方作品)

文件prompts选中 order保留(启用 / 停用)丢弃
Default.json12121(0 / 1)11
Deep♂Dark-v4 V1.6.8E for Ds4.x_1ATbU.json353524(19 / 5)11
Geechan - Universal Online Chat (Chat Completions) (v1.0).json17161(1 / 0)15
Geechan - Universal Roleplay (Chat Completions) (v5.2).json22217(0 / 7)14
Pura's Director Preset (SillyBunny).json474711(1 / 10)36
Pura's Director Preset 15.1 (SillyBunny).json474711(1 / 10)36
TLD Card Conversion Preset (Standalone).json26259(7 / 2)16

表里有两点值得注意:

  1. 保留数 ≠ 启用数。Geechan Online 保留 1 条、其中启用 1 条;Geechan RP 保留 7 条但全是停用——ST 里「在配置里存在」和「实际生效」是两件事,导入会把停用状态一起带过来(面板里可以再打开)。
  2. Default.json 只保留 1 条,这是正确结果。它是 ST 的「出厂默认」,main 是结构占位(我们已用 L0 + 纪律包承担同一职责),nsfw / jailbreak 在这份文件里正文是 0 字节。所以 12 条进、1 条出(Enhance Definitions,且是停用的),丢弃 11 = 结构占位 9 + 空正文 2。不是解析坏了。

数据存储

默认 ~/.dsh/ai-with-u/,可用 AIWU_STORAGE_ROOT 覆盖:

~/.dsh/ai-with-u/
├── _index.json                # 角色索引
├── _active.json               # 当前启用状态(含 mode / discipline 偏好)
├── _sessions.json             # 会话 → 角色绑定(会话作用域启用)
├── _presets.json              # 预设索引
├── _presets_active.json       # 预设启用态(全局 + 每会话)
├── presets/<id>.json          # 单个预设正文(id = p_ + 8 位 base36)
└── characters/<角色名>/
    ├── card.json              # CCv3 角色卡
    ├── card.v1.bak.json       # 迁移前原件,回滚就拷回来
    ├── diary.md               # 日记,按天分组
    └── session.json           # 会话状态与滚动摘要

session.json 是「这一册读到哪了」,认得这些字段:

字段含义
recent / turn_count / last_ts最近几轮、累计轮次、最后一次时间
mood / topic此刻的情绪、未竟的话题(写日记时一并落盘,下一轮 L1 用)
modetext 或 text+action,交互模式的权威位置
intimacy关系档位,五档之一:陌生 / 认识 / 熟悉 / 亲近 / 亲密
relation_log档位变化留痕:{ at, from, to, why? },最多 50 条,超出丢最旧

交互模式按 session.json → _active.json → text+action 的顺序解析:会话里用 awu_mode 切的档立刻生效,_active.json 只作没会话记录时的兜底。

纯 markdown / JSON,可读、可改、可备份、可迁移。不联网、不注册、不收藏数据。

接口安全

面板接口 /_dsh/ai-with-u/* 只接受本机来源:Host 必须是回环或实际监听地址,Origin 必须同源,Sec-Fetch-Site: cross-site 直接拒绝;写接口强制 POST + application/json。浏览器里任何网页都无法跨站触发删除或读取卡片。

如果确实要通过隧道/反代从别的域名访问本机 GUI,用环境变量显式放行:

AIWU_TRUSTED_HOSTS=my.tunnel.example

默认拒绝,不靠猜。


能力清单

模型工具(9 个,仅启用角色时挂载)

工具用途
awu_diary_write追加日记(可同时记下 topic / mood)
awu_diary_read读取 / 筛选日记
awu_whoami查询当前身份
awu_forget忘记某事(日记 + 会话 + 角色卡三处同步)
awu_diary_edit就地改写日记条目
awu_session_reset全新开始 / 彻底重置
awu_relation查关系档位依据;带 set 时按里程碑写回档位
awu_mode切换纯文本 / 文本 + 动作
awu_opening_next换一句开场

另有一个条件挂载的 awu_card_save:只在点「蒸馏角色卡」后的两小时内、且保存一次后自动失效。平时模型拿不到写卡能力。

REST 接口(32 条,/_dsh/ai-with-u/)

overview  preview  characters  character  character/save  character/import  character/delete
activate  deactivate  bind  unbind  mode  discipline  relation  relation/set
opening/next  opening/state  diary/save  diary/edit  forget  session/reset  session/commit
presets  preset  preset/save  preset/delete  preset/import  preset/activate
distill/flow  distill/arm  distill/disarm  distill/state

/character 与 /characters 同时返回 card(34 字段视图)与 ccv3(完整卡);/character/save 收 { name, card?, ccv3? },只给 card 时保留既有世界书与 extensions。

/bind 与 /unbind 就是「当前会话启用」:POST /bind {name, sessionId} / POST /unbind {sessionId},返回 { ok, bound, character }。POST /activate 仍然是全局启用语义(向后兼容)。GET /overview?sessionId=… 会带上 sessionId、binding(本会话绑了谁)与 bindings 摘要,面板据此判断「当前会话启用」能不能点。

/character 与 /characters 同时返回 card(34 字段视图)与 ccv3(完整卡);/character/save 收 { name, card?, ccv3? },只给 card 时保留既有世界书与 extensions。

GET /preview 是纯只读快照:返回 { active, mode, discipline, segments[] },segments 现在六段(aiwu:baseline / aiwu:discipline / aiwu:preset / aiwu:active-character / aiwu:lore / aiwu:clock,按 order 升序;未启用角色时 text: ''、chars: 0)。文本走 PromptController 的真实渲染路径,不在预览里另拼一份——拼第二份等于给「预览与真实注入漂移」开口子。

/presets 列索引、/preset 读正文、/preset/save|delete|import|activate 是写操作;/preset/import 收 ST 预设 JSON 并返回 { modules, dropped, warnings }——丢弃条目带原因,面板据此解释「为什么只剩几条」。

世界书的改动必须随 ccv3 发:只发 card 时后端以磁盘上的旧卡为底重投影,character_book 按原卡保留——改动会被静默吞掉,还会提示保存成功。

awu_relation 的口径是「查看不写回」:用户只是问「关系如何」时只读档位、不改档;只有里程碑事件(第一次约定、第一次争吵、称呼改变、表白)才带 set 写回,并在 relation_log 留一条。对话里不出现「好感度 +1」这类数值。

面板与提示词

  • 注入预览 —— 五段真实渲染的段名 / 字符数 / 正文 + 总字符,纯只读快照
  • 记忆回顾 —— 日记关键词搜索、按月折叠、导出 markdown
  • 导入角色卡 —— 角色簿左栏入口,吃 PNG / CHARX / JSON,先预览后落盘;世界书超限只警告不拦
  • 自创角色卡 —— 三格表单落骨架卡,可选「让 AI 补全人设」(走当前会话,AI 先问 3–5 个问题)
  • 世界书编辑 —— 角色卡编辑器第 11 分区,条目增删改 + 体检
  • 对话模式 —— 角色簿工具栏的「纯文本 / 文本 + 动作」胶囊,点了立刻生效,不需要启用角色
  • 纪律包 L0.5 —— off / lite / full 三档,默认 lite,偏好落盘、退出角色也保留
  • awu_mode —— 对话里直接切纯文本 / 文本 + 动作,不需要回面板

开发

npm run build            # 宿主 tsc + 前端 tsc + 打包 + 九套自检(合计 981 项)
npm run verify           # 产物形状 / 新鲜度 / 孤儿产物(16 项)
npm run verify:bundle    # 客户端产物加载(9 项)
npm run verify:wiring    # 接线体检:25 组契约(72 项;后端做了前端没接 / 验收项回归)
npm run verify:tavern    # 卡格式 / 迁移幂等 / 世界书预算 / ST 兼容(303 项)
npm run verify:distill   # 蒸馏 / 补全武装与 kind(121 项)
npm run verify:import    # PNG / CHARX / JSON 导入解析 / 字段保真(58 项)
npm run verify:session   # 会话、指令、纪律包、关系、绑定、预设与预览只读(286 项)
npm run verify:host      # 真实 cordis 宿主装配(116 项)
npm run typecheck:client # 只查浏览器侧类型

npm run build 串的顺序是:tsc(宿主) → tsc(前端) → esbuild 打包 → verify-bundle → verify-wiring → verify → verify-tavern → verify-distill → verify-import → verify-session → verify-host。任何一项非 0 退出就整体失败。

徽章上的 1025 = build 串里所有自检的通过项之和,失败项必须为 0、skip 也必须为 0(bundle 9 + wiring 72 + verify 16 + tavern 303 + distill 121 + import 58 + session 324 + host 122)。旧徽章的 515 用的是更窄的口径(只数六套,不含 verify 与 verify-wiring),所以数字变大不全是因为新增了断言。

verify-wiring 补的是其余七套查不到的盲区:类型检查只问「类型对不对」,不问「有没有人调用」。一个 17 KB 的世界书数据层可以零引用地躺在仓库里,一个 POST /character/import 可以注册完就没下文——这两种状态下 tsc、打包、其余自检全绿,但用户打开面板什么都看不到。脚本只做静态扫描(读源码找路由字符串与调用点),失败文案写清「缺什么 + 该找谁」。最后一组会把 lib/prompt.js 拿回来跟源码逐字比纪律包文本,抓「改了源码没重编」;产物不存在或比源码旧时跳过,不报红。

抽查 lib/client.js 时别用中文去 grep:esbuild 默认 charset: ascii,打包产物里的中文一律转成 \uXXXX(如「导入角色卡」= \u5BFC\u5165\u89D2\u8272\u5361)。功能无损,但按字面搜中文会误判「产物里没有」。

宿主 API 的类型直接来自 @deepseek-ai/dsh-system-prompt / dsh-tools / cordis 的 devDependencies,inject、PromptSection、ToolDefinition 都有编译期校验——契约漂移会在构建阶段报错,而不是运行时「failed 但不给原因」。

目录结构

src/            宿主侧:存储、提示词、工具、路由、格式层、导入、蒸馏
client/         浏览器侧:面板、编辑器、日记、指南、统计
scripts/        构建与自检
docs/           设计文档与开发记录(含踩坑大全)
presets/        开箱角色卡
tools/preview/  脱离宿主的面板预览沙盒

常见问题

会不会覆盖我 AGENTS.md 里的人设?

AGENTS.md 是以 user 角色消息注入的,插件用的是 system prompt,层级更高。L0 里显式写了边界:只让「我是谁、我怎么说话」,不让「我怎么做事」——代码规范、工程流程、安全约束照常生效。

退出后真的什么都不留吗?

五段(L0 / L0.5 纪律 / L1 / 世界书 / 时间差)在退出后都返回空串,宿主会过滤空段。awu_* 工具同时全部卸载。数据文件仍然在磁盘上,但不参与任何提示词组装。

为什么不能用 dsh plugin CLI 安装?

desktop profile 由 Electron 独占管理,CLI 会直接报 managed exclusively by the Electron application。按上面的 junction + profile 配置方式装。

删了角色,日记还在吗?

删除时可以选「只删卡」或「连记忆一起删」。只删卡时 diary.md 留在磁盘上,重新创建同名角色还能接上。

提示词到底占多少 token?

启用态约 2.8–3.3 KB 字符量级(中文按字计),未启用 0。实测:丰川祥子的卡 + lite 档,整段渲染 3286 字符。默认 lite 档的纪律包占 555 字符;切 off 全省,切 full 多 181 字符。世界书常态只注入一两百字符。重内容(卡里的详细设定、长日记)不会无条件进提示词。

为什么我的大卡能导入了,但设定只用得上一部分?

因为世界书是按需注入的,不是整本塞进提示词。命中预算默认 12 条 / 6000 字(LORE_DEFAULTS),超出预算的条目这一轮就不进上下文——卡本身一个字都没被改,磁盘上仍是完整的世界书,你在编辑器里能看到全部条目。

constant: true 的常驻条目走独立额度,不和关键词命中抢那 6000 字(真卡实测:7 条常驻共 10512 字,修之前有 2 条被静默挤掉,而常驻正是「必须一直生效」的那类)。

哪里能看到被裁的条目:打开角色卡编辑器 → 世界书分区顶部的体检行,会按等级列出「这一轮被预算裁掉的条目」;宿主日志里也会带条目名(只带名字,不写正文)。想提高命中率就把关键词写准、把常驻留给「必须一直生效」的设定。

这是刻意的:一张 9.8 万字的世界书全量注入,要么撑爆上下文、要么每轮烧掉一大笔费用,而真正用得上的往往只有当轮提到的那几条。

现在导入/保存这类大书只会出警告(附实际字数与上限),不再拦你——v0.3.0 之前这里是硬拦,属于过严。

为什么我的卡里正则(regex_scripts)不起作用?

因为本插件不执行酒馆的正则脚本,而且这不是「暂时没接」——是宿主侧没有可插入的点。

酒馆的 regex_scripts 有两类用法,我们分开说:

  • 提示词侧(发送前改写 prompt 文本):能做但没做。理由很简单:它改的是发给模型的内容,属于「用户不知道自己在看什么」的黑箱,真出问题时极难排查。
  • 显示侧(收到回复后改写显示文本,比如把 *笑* 变成斜体、把某些词替换掉):做不了。DSH 的客户端插槽 conversation.chat.node 只能新增聊天行,改不了已经渲染出来的助手消息;agent/request 钩子只管 provider / model / reasoningEffort 路由,不碰文本;插件规范也明写不许读写组件外的 DOM。

生态里的做法是把这个能力交割出去:dsh-tavern 从 2.7.x 起把显示层整块交给 dsh-muv-engine(自己那套渲染器删掉了,因为两边的 beautifyContentEl 会互相覆盖)。想用正则美化显示,装 muv 系引擎即可,本插件不重复造第二套。

你的卡不会因此丢东西:regex_scripts 原样保留在卡里(data.regex_scripts 与 data.extensions.regex_scripts 两个位置都不动),只是不被执行。导入预览会给一条告警说清这一条——留着字段是为了你将来导出/回灌酒馆时不缺东西,「以为它在工作」则用告警解决,而不是删数据。

如果你依赖的是提示词侧的正则效果,请把规则改写进角色卡的 system_prompt 或世界书条目——那是我们能保证生效的地方。详见 docs/DEVELOPMENT.md §十三。

「当前会话启用」和「全局启用」有什么区别?

两个作用域,互不覆盖:

  • 全局启用:所有没绑定的会话都用它(还有子代理)。切换全局不影响任何已绑定会话。
  • 当前会话启用:只绑你点的这一个会话,别处照旧。

决议顺序写死:会话绑定 > 全局启用 > 未启用。所以「全局阿米娅 + 本会话祥子」= 这个会话是祥子、其余是阿米娅。

两条边界值得记住:

  1. 绑的卡被删掉,那个会话就当作未启用,不会偷偷回落到全局——否则你会以为在跟祥子聊、其实对面是阿米娅。重新绑定即可恢复。
  2. 子代理固定用全局角色,不继承父会话绑定:子代理有自己的身份查不到绑定,于是走全局。这是有意为之,防止人设意外漏进工具链。

面板上两态分行显示(「当前会话:X(已绑定)」/「全局:Y」),点哪个都会就地提示影响范围。如果面板拿不到会话标识,「当前会话启用」会置灰——它不会瞎猜一个 id 写进去。

面板说卡里有 N 条正则脚本、已屏蔽,会有什么影响?

没有任何影响,而且这是可以验证的:

  • 脚本不会被执行(提示词侧与显示侧都不做);
  • 脚本正文进不了提示词:自检里拿一个特征串做标记,跑完整 L1 与「注入预览」,产物里搜不到它;
  • 对注入零影响:同一张卡去掉 regex_scripts 后,L1 与预览的文本逐字相同;
  • 字段原样保留:你将来把卡导出回酒馆,脚本还在。

换句话说,看到的角色表现与「这张卡本来就没有正则脚本」完全一致。如果卡的表现依赖这些脚本(比如靠正则把某些词换成斜体、或替换成别的台词),那部分效果不会出现——想保留效果就把它改写成角色卡的人设描述,显示层的正则美化需要装 muv 系引擎(本插件不做第二套渲染器,原因见 docs/DEVELOPMENT.md §十三)。


致谢

License

MIT

Comments

Loading…

From the same category

awesome-dsh-plugin

by awesome-dsh-plugin

A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表

Development & Infrastructure

★ 21.9k

CC0-1.0

Python

Nov 1, 2026

Index only — not installable

by 0xsline

DeepSeek Harness (DSH) ecosystem: curated plugins, tools, and infrastructure from dsh-external/hub and the public dsh-plugin topic.

Development & Infrastructure

★ 1.3k

CC0-1.0

Python

Oct 16, 2026

Index only — not installable

by Yuuyuko-uu

DSH 鱼的记忆:给会话一份会淡忘的长期记忆,每条都带时间

Development & InfrastructureMemory & ContextSessions & MessagesManifest valid

★ 451

MIT

JavaScript

Nov 1, 2026

dsh plugin --profile web add dsh-fish-memory

by SAOS-3624

Scene-aware storyboard for DeepSeek Harness: 9-16 numbered cells with timestamps + transcript + an audio envelope, packed into ONE image (384 tokens). Two tools: video_storyboard and video_zoom.

Tools & CapabilitiesVision & MultimodalDevelopment & InfrastructureManifest valid

★ 352

↓ 4.4k/wk

MIT

JavaScript

Nov 1, 2026

dsh plugin --profile web add dsh-video-storyboard

by uumit-ai

Open dsh web from your phone or another computer through a UUMit account, without running your own server or installing another program: a built-in tunnel client connects to UUMit's hosted tunnel, and

Tools & CapabilitiesDevelopment & InfrastructureTerminal & ClientsManifest valid

★ 296

↓ 303/wk

MIT

JavaScript

Oct 21, 2026

dsh plugin --profile web add @uumit-ai/dsh-uumit-remote

by xiajiajun516

DeepSeek Harness (DSH) backup & restore plugin — export, import, migrate and sync your complete DSH configuration, plugins, MCP servers, skills and workspace. One-click migration to another machine.

Development & InfrastructureManifest valid

★ 287

↓ 8.4k/wk

MIT

TypeScript

Nov 1, 2026

dsh plugin --profile web add dsh-config-manager