Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add dsh-instruction-memory
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
README
This plugin publishes its README in Chinese only.
在 DSH 设置界面中维护长期指令记忆:保存后自动注入此后每一轮对话的系统提示词。

想先看看界面?在 GitHub 仓库中打开
docs/demo.html,无需安装 DSH,浏览器直接体验真实设置页(内置演示数据)。
安装
dsh plugin --profile web add dsh-instruction-memory
宿主版本必须落在兼容性声明的范围内。范围之外宿主会拒绝安装/启动(1.0.14 起,
因为 peerDependencies 已声明);确需强行安装可用 dsh plugin allow-version 授予该精确版本的
豁免,风险自负。
装完重启 DSH,设置页会出现「指令记忆」入口。卸载:
dsh plugin --profile web remove dsh-instruction-memory
只由用户本人维护
这份记忆的内容只属于用户。 本插件刻意不注册任何面向模型的工具——模型没有任何 途径自行添加、修改或删除记忆条目。写入入口只有设置页(以及用户本人直接编辑存储文件), 因此不会出现 AI 悄悄给用户"记下"指令的情况。
条目内容由用户输入并被原样注入,本插件不对其做语义判断或自动生成。
组成
| 文件 | 作用 |
|---|---|
lib/index.js |
Host 半:读取/保存记忆,注册 systemPrompt 段落,暴露同源 JSON 路由 |
lib/client.js |
Client 半:在 settings.section 注册「指令记忆」设置页(手写模块,无需构建) |
cordis.patch.yml |
bundle patch:把 Host 行插入宿主组合 |
contract-test.mjs |
契约测试:驱动真实路由,验证两半之间的响应格式 |
verify.mjs |
装载验证:按 DSH 的方式加载两半 |
smoke-test.mjs |
注入渲染逻辑的单元测试 |
host-range-test.mjs |
宿主版本范围契约测试:固定矩阵 × 两种 semver 判定模式,并把 peerDependencies(被执行的那个)、dsh.engines.dsh、dsh.compatibility.dsh 三处声明锁到同一个生成值 |
docs/demo.html |
离线演示页:桩掉 DSH 外壳、加载真实 Client 半渲染设置页(不随 npm 包发布) |
生效方式
- 始终 条目:无条件遵守。
- 按需 条目:由模型按相关性自行判断是否适用,不相关时忽略;可填「适用场景」辅助判断。
- 优先级 高 > 普通 > 低,决定注入顺序。
- 注入字数上限:超出时按优先级保留,被略过的条目数会在注入文本末尾注明。
条目全部停用或总开关关闭时,该提示词段落整个注销,系统提示词与未安装本插件时逐字节一致。
存储
记忆保存在 DSH 数据根目录下(设置页会显示完整绝对路径):
<DSH_HOME>/instruction-memory/memory.json # DSH_HOME 默认为 ~/.dsh
路径优先级与官方 @deepseek-ai/dsh-home-paths 一致:显式 $DSH_HOME → ~/.dsh。
空白的 $DSH_HOME 视为未设置,绝不会退回当前工作目录——否则用户换个目录启动
DSH 就会得到第二份空记忆,看起来像"记忆消失"。
1.0.0 之前的构建曾把数据写在宿主进程 cwd 下(
.dsh-instruction-memory.json)。 首次启动新版本时会自动迁移到上述位置,并把原文件改名为*.migrated保留。
该文件可手工编辑,改完点设置页的「重新载入」即可读回。每次保存先写临时文件再原子替换,
进程崩溃不会留下损坏的半截 memory.json;保存前把上一版复制为 memory.json.bak,
若 memory.json 解析失败会自动临时回退到该备份并明确提示。
备份为什么是"复制"而不是"改名":曾经的做法是先把
memory.json改名成.bak、 再改名临时文件顶上。这两步之间memory.json是不存在的——只要第二步失败(文件被占用、 磁盘满、杀软扫描),主路径就一直空着,下次启动找不到文件就会建一份空存储,用户的 记忆看起来凭空消失,而真实数据其实好好躺在.bak里。改为复制后主文件在原子替换成功 前始终待在原位;同时启动时若发现memory.json缺失而.bak可用,会从备份恢复并写回 主路径,而不是从零开始。
若手工编辑后的文件有条目为空或超过 200 条上限,设置页会明确提示哪些条目未能载入 (它们将在下次保存时从文件中移除),不会静默丢弃。导入时若某条超出长度上限 (标题 120 / 内容 6000 / 适用场景 200 字符),会明确提示有几条、哪个字段被截断, 而不是悄悄改短。
设置页支持导出 / 导入:导出为自带说明的 JSON 文件;导入采用合并语义——按 id 与
「标题+内容」去重,只新增、绝不覆盖或清空现有条目。请求体上限由条目上限推导
(MAX_ENTRIES × (MAX_CONTENT + MAX_TITLE + MAX_WHEN + 200) × 2 + 100000),保证本插件
导出的文件一定能被自己导回——早先写死的 1,000,000 小于满配导出(200 × 6000 = 1.2 M 字符),
导致满配记忆导出后无法导入。
首次运行不写文件(惰性创建)
全新安装、尚无任何记忆时,插件不会在宿主启动那一刻创建空的 memory.json。
这里曾主动物化一份空存储,只为让设置页有个真实路径可显示。但那意味着插件在进程启动、 零会话、零任务的状态下执行了一次磁盘写入——这正是行为审计中唯一能被正当称为 "没活干还在动"的副作用。现在文件由第一个真正需要它的动作创建:一次保存、一次导入, 或设置页读取
state(面板打开时就会读)。
在这之前:storage.path 仍会显示路径,但 storage.onDisk 为 false,设置页显示
「尚未写入磁盘」(该文案本就存在),state.injection.registered === false,pulls === 0。
挂载日志相应为 from=first run (no store on disk yet) onDisk=no。
不受影响:从 .bak 恢复、以及从旧位置迁移——这两条分支只有在磁盘上已有真实数据时才会走,
它们仍然会立即写回。
无 Web 服务器时依然生效
systemPrompt 是本插件唯一的硬依赖。Web 服务器不是前置条件:设置页那部分路由通过
非阻塞的 ctx.inject(['webServer'], …) 子 fiber 注册,服务出现时自动挂上;没有 Web 服务器
的 profile(headless、tui)里,系统提示词注入照常工作,只是设置页不可用。
这里曾声明
inject = ['systemPrompt', 'webServer']。声明式依赖是前置条件,于是没有 Web 服务器的 profile 里整行插件永远停在 pending、apply()根本不执行——用户同时失去设置页 和记忆注入,而记忆本身根本不需要 Web 服务器。非阻塞注册同时把最初那个竞态修得更彻底: 回调在服务发布时就会执行,而不只是在它"抢在插件挂载之前"发布时才生效。
诊断日志
插件此前只有失败才有输出:每次载入、保存、注入成功都不留任何记录,只有失败分支走
console.error。于是"记忆到底有没有在干活"完全无法从日志回答。现在它挂载时写一行
info,过程细节写 debug(走宿主的 ctx.logger):
[instruction-memory] mounted: store=<DSH_HOME>\instruction-memory\memory.json from=memory.json onDisk=yes entries=2 enabled=true section=437 chars (pending assembly) pulls=0
挂载行含数据来源(memory.json / memory.json.bak (main file missing) / memory.json.bak (main file corrupt)
/ legacy cwd file (migrated) / first run (no store on disk yet))、是否已在磁盘上(onDisk)、
条目数、总开关状态、段落就绪时的字符数,以及 pulls。
为什么是 section=… (pending assembly) 而不是 injected=…
「段落已就绪」≠「已经注入」。 注入发生在宿主装配提示词时;插件在挂载那一刻什么都没注入过,
打印 injected=437 chars 会让人误以为记忆已经进入了某个提示词。这是本插件此前一处会误导排查的措辞。
真正的"到达了提示词"的信号是 pulls:宿主每次对这段做装配,插件注册的那个 thunk 就被求值一次,
计数器加一。因此
pulls=0= 已准备、从未装配(进程刚起来、或会话空闲);pulls=N= 已被拉进提示词 N 次。
插件看不到会话或轮次,不会报告 sessions= 之类的数字——那会是编造。它只报告自己能真正观测到的东西。
pulls 同时出现在路由的 state 快照里(injection.pulls)。每次拉取另有一条 debug 行:
section pulled into a prompt (pull #N)。
这是纯日志,绝不影响注入内容:同一份存储在"有 logger"和"没有 logger"下渲染出的文本
逐字节相同(verify.mjs 有断言锁定这一点)。debug 级别由宿主日志级别过滤;
没有 logger 服务的环境下需要 DSH_INSTRUCTION_MEMORY_DEBUG=1 才会输出到标准错误。
请求来源防护(Host / Origin)
设置页路由之所以要求 content-type: application/json,是因为 HTML 表单无法伪造 JSON body,
而跨源 fetch 带 JSON 会先在 preflight 失败。这两条防线都建立在"浏览器认为这是跨源"之上,
DNS 重绑定恰好推翻了它:evil.com 解析到 127.0.0.1 之后,页面与服务器在浏览器眼里是
同源——不发 preflight、JSON 也合法,于是任何网页都能改写用户那份"注入到此后每一轮
对话"的长期指令。此时唯一无法伪造的就是浏览器发出的 Host 头。
因此当服务器绑定在回环地址(默认)时,路由要求 Host 是回环,另外校验 Origin(若存在)
与 Host 同源。命中即 403,并记一行日志:
[instruction-memory] route rejected a request: Host 头不是回环地址(可能是 DNS 重绑定攻击):evil.com:8080
- 绑定
--host 0.0.0.0(主动对所有网卡开放)时 Host 校验自动关闭——那种情况下无法预知合法 Host,强行限制只会打断所有正常客户端;Origin校验仍然生效。 - 无
Host的 HTTP/1.1 请求由 Node 的 HTTP 解析器先以 400 拒掉,根本到不了路由。 - 端口不参与
Origin比对(反向代理可能改写端口),主机名才是重绑定攻击的对象。
兼容性
同一串范围写在三处,而只有一处会被宿主强制执行——这一点以前写错过,现在按实测更正:
| 位置 | 谁读它 | 作用 |
|---|---|---|
peerDependencies(@deepseek-ai/dsh-system-prompt) |
宿主:evaluatePluginCompatibility()(dsh-app-boot/lib/index.js),在安装与 profile 启动时执行 |
真正的门禁。不满足即拒绝(或要求显式授予精确版本豁免:dsh plugin allow-version)。门禁把 peer 的范围值与宿主版本(dsh --version)比较,peer 的包名不参与解析,只用来点名报错 |
dsh.engines.dsh |
插件市场(第三方,服务端读取) | 市场卡片上的兼容性判定与展示 |
dsh.compatibility.dsh |
未找到读取方(官方文档与 DSH 树内均无) | 仅作人类可读的重复声明 |
1.0.14 之前这里只有后两处,没有 peerDependencies——而宿主的门禁在读到缺失的 peerDependencies 时会直接 return undefined(if (!Object.hasOwn(fields, "peerDependencies")) return void 0),也就是跳过检查。换句话说,范围之外的宿主在此之前可以装上而没有任何拦截或警告;那串范围当时只是市场元数据,不是门禁。1.0.14 补上 peer 之后,它才真正生效。
同一串范围(三处逐字节一致,由测试锁定):
>=0.1.3-alpha.2 <0.1.4 || >=0.1.4-0 <0.1.5-0 || >=0.1.5-alpha.1 <0.1.6-0 || >=0.1.6-alpha.0 <0.1.7-0 || >=0.1.7-alpha.0 <0.2.0-0 || >=0.2.0-0
验证范围与证据等级——三者不可混为一谈,下面每一行都标了它到底证明了什么:
| 等级 | 证明什么 | 覆盖 |
|---|---|---|
| ① 真实启动 | 在该宿主版本上真的把 DSH 跑起来:插件装载、注入真的进入组装后的提示、插件 HTTP 路由可应答、客户端设置页模块被下发(Windows / Node 22) | 0.1.3-alpha.2 · 0.1.5-alpha.1 · 0.1.5-alpha.2 · 0.1.5-rc.1 · 0.1.5-rc.2 · 0.2.0-rc.1 ⁽*⁾ |
| ② 契约核验 | 抓该版本真实发布的源码,逐个核验本插件实际用到的每个符号:systemPrompt.section()、assemble() 是否求值函数型 text、FILE_REFERENCE=900 / TOOL_BASH=1000 仍在(决定 order 950 是否空档)、重名注册是否抛错、webServer.register() / get host()、ctx.inject() / ctx.effect()、dsh.client.inject 两包在该版本是否存在且声明了 dsh.client |
声明范围接住的全部 13 个已发布版本(0.1.3-alpha.2 → 0.2.0-rc.1) |
| ③ 真实执行 | 把插件真的挂载进该版本的 @deepseek-ai/cordis,跑装载 / 路由注册 / 卸载共 9 项断言 |
cordis 4.0.2 与 4.0.4(各 9/9) |
⁽⁾ 0.2.0-rc.1 的①档有一条要说明:插件装载、注入进入组装后的提示、HTTP 路由可应答三项*均已实测(路由 HTTP 200;injection.registered=true、chars=437、pulls=38——即 0.2.0-rc.1 的 agent loop 真的求值了 38 次函数型 text)。第四项"客户端模块被下发"没有直接抓取:首页需要鉴权(/ 返回 401),我无法取到 window.__DSH_BOOT__。这一项的支撑是间接但强的两条:① dsh-client-modules 在合成阶段对 dsh.client 声明做硬校验,不合格会抛 ClientPackageCompositionError 直接导致启动失败——宿主正常启动即说明声明通过了 0.2.0-rc.1 的校验;② 本插件用到的三个客户端契约包(-slots / -renderer / -settings)相对升级前真正在跑的 0.1.7-rc.2 逐字节未变。未做人工视觉确认(没有打开设置页看)。
此外 host-range-test.mjs 的固定矩阵覆盖 0.1.6-alpha.2、0.1.7-rc.2 与 0.2.0-rc.1,并会读取本机实际安装的宿主版本做实时断言。
关于 1.0.10 新增的 ctx.inject。 这是新版唯一的硬依赖增量:inject 去掉了 webServer,设置页路由改为非阻塞的 ctx.inject(['webServer'], …) 子 fiber(原因见上)。为此逐个核验了 cordis 全部 6 个已发布版本(4.0.1-rc.1 → 4.0.4)——每一个都具备 ctx.inject,因此声明范围内不存在因它而失效的宿主版本。
关于声明范围是否"超范围承诺"。 已对全部 28 个已发布宿主版本穷举核验:范围内 13 个版本的 API 面全部齐备,超范围承诺 0 项。范围外的 15 个版本(0.0.1-rc.1 → 0.1.2-rc.1)API 面同样齐备,但它们从未真实启动验证过,所以下限维持不动、不向外放宽——不把没验证过的东西写进声明。
0.2.0-rc.1 的核验口径(2026-09-29 增补):基准取 npm 上真实发布的 0.1.7-rc.2(升级前本机真正在跑的版本),逐文件 SHA256 与 0.2.0-rc.1 比对。本插件的 6 个耦合点里 6 个逐字节未变(dsh-system-prompt 4/4、dsh-client-ui-slots 4/4、-renderer 12/12、-settings 11/11、dsh-host-webserver 3/3、dsh-client-modules 10/10);变动的只有 dsh-agent-loop(注入通路 preStep / assemble 逐行等同)与 dsh-app-boot(兼容门禁函数逐字节等同)。方法带阴性对照:同法比对 0.1.6-alpha.2 得到的哈希不同,证明这套比对确实能检出变化,而不是恒真。
一个运维上值得知道的事实。 早期 DSH 用 caret 范围声明同族依赖(如 ^0.1.5-alpha.2),范围会随时间"往前漂":今天安装旧版 DSH,npm 在 includePrerelease 语义下会把同族子包解析到当前最新的 0.1.x,而不是当年那份(实测 7/10 个采样版本会漂移,3 个因精确锁定不会)。这不影响本插件的结论——漂移目标同样在已核验范围内——但"今天装出来的树"与"当年装出来的树"可能不同。
为什么写成分段形式:node-semver 规定"候选版本带预发布标签时,区间里必须存在同一个
major.minor.patch 且自身带预发布标签的比较符"。这条规则是集合级的——一个 || 分支最多
覆盖一个 minor 的预发布版本。由此产生两个必须遵守的约束:
- 宽写法接不住预发布:
>=0.1.3-alpha.2、>=0.1.3-alpha.2 <0.2.0-0都匹配不到0.1.4-0/0.1.5-rc.1/0.1.6-alpha.2——因为0.1.3与0.2.0的 tuple 都不等于 它们各自的 tuple(已用 node-semver 7.8.5 实测确认)。 - 每段的上界不能省:省略会被上一段的比较符"续接"。例如单写
>=0.1.5-alpha.1(不封顶), 在把0.1.3当 token 时会放行0.1.3-alpha.0/1。
⚠️ 一个必须知道的上限(注意它是"模式相关"的,别当成普适结论):未声明的未来 minor 的预发布版本,在 npm 的默认语义下无法被任何范围覆盖。
0.1.8-rc.1 这类版本 tuple 与所有比较符都不同,在 npm 默认语义下永远匹配不到——与
^0.1.0 无法匹配 0.1.8-rc.1 是同一个限制。正式版(0.1.8、0.2.0、1.0.0 等)不受影响。
但在 includePrerelease: true 下这条上限不成立。 实测同一串范围:0.1.8-rc.1 在默认语义下 false、
在 includePrerelease: true 下 true(已用 DSH 自带的 semver 7.8.5 验证)。而这个区别是有后果的,
因为两条消费路径用的模式不同:
| 消费方 | 模式 | 0.1.8-rc.1 会被放行吗 |
|---|---|---|
npm / pnpm 解析 peerDependencies(包管理器) |
默认 | 否 |
宿主门禁 evaluatePluginCompatibility |
includePrerelease: true(dsh-app-boot L300) |
是 |
| 插件市场(第三方,服务端) | includePrerelease: true |
是 |
也就是说:对包管理器而言那个上限成立,对宿主门禁而言它其实已经被宽松模式接住了。
所以"未声明的新 minor 预发布版会不会被拒"不能只看一句话,要问清楚是哪种模式。
(host-range-test.mjs 里那条 0.1.8-rc.1 is unreachable 的断言取的是默认模式,其用例名
因此容易被误读成普适结论——这一点已在 1.0.14 的核验里记录。)
这个限制无法用代码消除,但它的后果已经被消掉了。 范围现在是生成出来的:
host-range-test.mjs 顶部的 COVERED_LINES 是唯一事实来源,package.json 里那串长字符串必须
逐字节等于由它生成的结果(有专门的漂移断言),所以手改长串导致"枚举漏了一段"这类错误不可能
再发生——DSH 发新 minor 时只需在列表末尾加一行。
同时实时守卫(直接读本机实际安装的宿主版本)在发现未覆盖的宿主时,会打印精确到行的 修复配方,并且在打印前先验证该配方真的能让那个版本被放行:
FAIL LIVE GUARD: the installed host 0.1.8-rc.1 is admitted by both modes -> ...
Fix: append { floor: '0.1.8-alpha.0', below: '0.2.0-0' } to COVERED_LINES
and set the preceding line's below to '0.1.8-0'
[verified: that edit admits 0.1.8-rc.1]
这份配方本身也有测试:host-range-test.mjs 会拿 0.1.8-rc.1 走一遍"确认当前范围拒收 →
套用配方 → 确认放行 → 确认下方版本仍被拒收 → 确认所有已覆盖版本仍被放行"。配方失效会先失败在
测试里,而不是失败在用户的安装上。
历史修复说明(同一个 bug 出现过两次,值得记下来):
- 1.0.7 及以前,范围末段是
>=0.1.5-alpha.1,使宿主0.1.6-alpha.2在 npm 默认语义下 被判为不兼容(预发布门禁要求 tuple 相同:0.1.5 ≠ 0.1.6,>=的大小比较根本走不到)。 - 1.0.8 改为逐段枚举,但只枚举到
0.1.6。DSH 随后发布0.1.7-rc.2,同一个假阴性再次出现: 范围里最后一个预发布 tuple 是0.1.6,而0.1.7 ≠ 0.1.6。1.0.9 补上0.1.7段。 - 1.0.10 把枚举抽成
COVERED_LINES单一事实来源 + 漂移/可达/递增断言,并让实时守卫给出 自验证的修复配方——这个 bug 的成因(手改长串)从此被消掉。
两次都因为插件市场传入 includePrerelease: true 而侥幸放行,但任何标准 semver 判定
(npm / pnpm 的依赖解析)都会拒绝。现在 host-range-test.mjs 同时具备固定矩阵与实时守卫。
未验证范围:macOS / Linux、headless 与 tui profile,以及除上表等级①那几个之外的任何版本的真实启动,均未实测。
等级②只证明"该版本里有这些 API",不证明端到端可用。
关于"市场读哪个字段"这条的证据等级。 这里说的是**插件市场(第三方)**的行为,不是 dsh 自身:
市场从已发布的 npm manifest 读 engines.dsh(顶层优先)或 dsh.engines.dsh,与 @deepseek-ai/dsh* 的
peerDependencies(若有)求交,再用 semver + includePrerelease: true 与宿主版本比较,据此在卡片上
显示兼容性;dsh.compatibility.dsh 不是市场读取的那个字段。
需要如实说明它的来源等级:这一条在官方文档里没有,树内也没有可核验的市场客户端
(dshmarket / alldsh 均为第三方,读取发生在服务端)。它的依据是一份独立的第三方实证记录
——本机安装的 dsh-vibe-math@2.3.16 在其 dsh.compatNote 里逐字写明了上述读取路径与"自用的
dsh.compatibility.dshReleases 市场不读"。所以请把它当作第三方实证,不要当成官方保证。
(1.0.14 之前这段把它与官方事实并列陈述,措辞已按证据分级修正。)
范围之外的宿主会发生什么(1.0.14 起变了)。 在此之前,本插件没有 peerDependencies,宿主门禁
直接跳过检查,范围外宿主可以装上且没有警告。1.0.14 起 peer 生效:
- 宿主(
dsh plugin add/ profile 启动)会拒绝,除非用户显式授予该精确版本的豁免 (dsh plugin allow-version),这正是 DSH 设计的正常流程; - 市场会把"确认不兼容"的条目隐藏并拒绝安装/更新("未声明"或"无法确认"的条目照常显示)。
host-range-test.mjs 会断言 peerDependencies 与另外两处字段逐字节一致,并断言 peer 只声明这一个包名——
三处任一被手改都会在测试里失败。
发布(维护者)
正规流程是推 tag,由 CI 通过 OIDC(Trusted Publishing)发布,不需要任何长期令牌:
# 1. 自检(prepublishOnly 也会自动跑;占位符未替换会中止发布)
npm test
node check-metadata.mjs
# 2. 升版本并提交
# package.json 的 version 必须与 tag 完全一致,否则工作流会拒绝发布
git commit -am "1.0.N: ..."
git push origin main
# 3. 打 tag 推送 → 触发 .github/workflows/publish.yml
git tag -a v1.0.N -m "1.0.N: ..."
git push origin v1.0.N
工作流会先跑 npm test 与"tag ↔ version 一致"校验,再 npm publish --access public;
公开仓库 + OIDC 会自动附带 provenance 存证。
npm 侧的一次性配置(发布前必须完成,且 npm 不会校验你填了什么): Package → Settings → Trusted publishing → Add trusted publisher
| 字段 | 值 |
|---|---|
| Organization or user | HERO476 |
| Repository | dsh-instruction-memory |
| Workflow filename | publish.yml(只写文件名,须完全一致) |
| Environment name | (留空) |
| Allowed actions | 勾选 npm publish |
⚠️ 2026-09-03 之后创建的 trusted publisher 默认只允许
npm stage publish,直发必须显式勾选。 字段填错不会在保存时报错,只会在第一次发布尝试时以ENEEDAUTH之类的错误暴露。
这就是本仓库 1.0.10 / 1.0.11 / 1.0.12 由本地 npm publish 发布的原因:这三版发布时该配置尚未就绪,
Publish 工作流的唯一失败步骤正是 npm publish(其余步骤含 npm test 全部通过),因此那三版没有 provenance、也没有对应的 git tag。
不要为这三个版本补推 tag —— 版本已被占用,重跑只会再得到一次必红的 CI。从下一个新版本起走上面的正规流程。
本地兜底发布(仅在 OIDC 不可用时):npm login 后直接 npm publish --access public。
本机若已有 ~/.npmrc 令牌即可直接发布,但产物不含 provenance。
数据格式
{
"version": 1,
"enabled": true,
"budgetChars": 4000,
"entries": [
{
"id": "im-xxxx",
"title": "回答语言",
"content": "所有回答使用简体中文。",
"mode": "always",
"when": "",
"priority": 1,
"enabled": true,
"updatedAt": 1700000000000
}
]
}
mode 为 always | auto;priority 为 2 高 / 1 普通 / 0 低。
Comments
Comments live in GitHub Discussions. Sign in with GitHub to post or react.