安装
在 DeepSeek Harness 里通过 dsh-market 安装
dsh plugin --profile web add dshmarket
或使用命令行
dsh plugin --profile web add "https://github.com/lpf20200901/dsh-memory-delta/releases/download/v1.1.0/dsh-memory-delta-1.1.0.tgz"
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络。请先审阅源码,并尽量锁定 commit(github:owner/repo#sha)。
截图
README
English | 中文
给 AI 编码助手的、分层自动注入的跨会话记忆。 一个 DSH 插件 + 一个零依赖的独立 CLI。借鉴 OpenSpec 的 规格 / 变更 / 归档 纪律 —— 但走推送而不是拉取。
状态:M1–M3 已完成并在真实 DSH 上实机验证(差分注入 / 两个工具 / 蒸馏提醒)。 实机验证矩阵见下方「验证」。
有疑问? → 常见疑问 FAQ:"是不是每聊一句就把全部记忆发一遍?" "超预算会丢条目吗?""归档 / 撤回 / 取代有什么区别?""会不会和
AGENTS.md重复注入?" 英文版:FAQ。
为什么需要它
AI 编码助手有两个反复出现的毛病:
- 新会话不记得任何事 —— 每个会话都要重新交代背景、偏好、结论。
- 记住了也管不好 —— 全塞进一两个 Markdown,越写越大、越写越贵,而且结论过时了没人删。
已有的规格驱动工具(OpenSpec 等)解决的是"代码不跑偏",但它们是拉取式:靠指令要求 AI 去读, 新会话不会主动想起来。dsh-memory-delta 走推送:会话一开始就把该知道的塞进上下文,但只推最精炼的部分, 而且只推变化的部分,细节按需检索。
设计要点
┌─ PUSH:会话开始自动注入(字节预算硬约束)
│ T0 身份与约定 用户偏好 / 机器环境 / 账号约定
│ T1 索引与待办 接着办什么
库 ─────┤
└─ PULL:按需检索(不占常驻预算)
inbox/ 候选条目 —— **模型默认只能写这里**
facts/ 当前真相(只有 status=active 参与注入)
decisions/ 决策与理由(只增不改)
archive/ 被取代条目的归档
journal.md 流水(永不注入)
目录名要分两个轴看(这一点以前没写清,容易被 facts 这个词误导):
| 目录 | 在流程哪一步 | 记什么 | 谁能写 | 参与注入 |
|---|---|---|---|---|
inbox/ |
候选(还没确认) | 模型觉得值得长期留住的结论 | 只有模型(memory_write) |
❌ 从不 |
facts/ |
常驻 | 踩过的坑 + 怎么绕开:环境限制、工具行为、真实的失败与解法 | 只有人(promote) | ✅ 每轮 |
decisions/ |
常驻 | 你定下的约定:业务 / 流程 / 口味上的决定 —— 防止重复问你 | 只有人(promote) | ✅ 每轮 |
archive/ |
归档 | 退场的旧结论:被取代(supersede)或不再适用(archive) | 取代/归档时自动搬 | ❌ 永不(但仍搜得到、能取回) |
主流程:模型只能写 inbox/ → 人确认后 promote 进 facts/ 或 decisions/ → 退场的进 archive/。
拿不准放哪边就问:"明天世界变了,这条会不会失效?" 会 → facts/;只有你改主意才失效 → decisions/。
两条写起来的诀窍:facts/ 里写清**"什么情况下适用"(坑的价值是"下次别再踩",不是"曾经踩过");
decisions/ 里写清"为什么这么定"**(有了理由,下回它就能自己判断,不会再问你第二遍)。
这四个目录名(以及
journal.md/index.md/memory.config.json)的完整说明,mem init会写进库自己的README.md—— 打开记忆库目录就能看到,不用回来翻项目文档。
七条纪律:
- 推送的东西必须极小:注入层里的内容每次会话都要花 token。所以流水、设计文档都不进注入层。
实测一个 31 条常驻的真实记忆库:注入文本 4369 字节,平均 141 字节/条,
所以同规模的库用 5 KB 预算就装得下。文本里刻意不写两样东西:条目 id(它只是
差分用的元数据,落在侧车状态文件里,根本不进上下文;内联进正文曾吃掉 34% 的预算),
以及与 id 一字不差的 key
(
createEntry会拿 key 当文件名,于是真实库里 31 条有 30 条的 key 与 id 完全相同 —— 正文里再写一遍是纯重复,实测白占 15% 预算)。每条还会按 90 字截断首行。 - 只推变化的部分:每条条目带 12 位内容 hash,插件记住上一轮的状态,下一轮只推新增/已更新/已失效;
完全没变化时一个字都不注入。(上游
dsh-agent-instructions没有差分:文件一变就整篇重注入, 实测一个会话里改 15 次某个 8.5 KB 的文件 ≈ 白烧 58k tokens。) - 状态存侧车文件:
<harness home>/storages/dsh-memory-delta/inject-state/<会话id>.json(目录按config.stateDir→ 内核服务ctx.dshHomePath→$DSH_HOME→~/.dsh的顺序解析; ⚠️ 2026-10-01 修:以前只认$DSH_HOME,而官方桌面版的 home 就是默认的~/.dsh、 宿主进程里没有这个环境变量 → 侧车静默不落盘、每次重启重灌一次全量记忆)。 ⚠️ 2026-09-30 改的:早先把{id: hash}塞在消息的source里,那违反了 DSH 会话格式 v0 白名单 (plugin source 只允许kind/plugin/form/sections/summary),会让整条会话在格式迁移时被拒、 永久打不开(本机 14 条会话因此报废,只能手工修日志)。现在状态不碰会话格式, 且只在消息真的进了上下文之后才记账 —— 排队后又被清掉的消息不会让状态虚增。 - 模型只写收件箱:错误结论若静默进入常驻层,会被反复注入。提升需要显式
promote。 - 一个 key 一个真相:事实/决策带语义键
key,同一个scope+key上只能有一条 active。 新结论要进来,必须显式--supersedes旧的 —— 这是把"记忆腐化"挡在常驻层外的闸门。 - 结论有状态:
active/superseded/expired。被取代的打双向链接并归档,而不是无限追加。 - 纯 Markdown + frontmatter:人可读、可 git diff、可 review、能像代码一样提交。
安装(作为 DSH 插件)
⚠️ 这段是实机踩出来的,两条弯路都别再走:
❌ 往 package.json 的 dsh.profile.bundles 里加
→ DSH 启动时按市场注册表(.generations/desired.json)重新生成,未知条目被清掉
❌ 在 cordis.patch.yml 里写一个裸条目
→ 被静默忽略(patch 对不存在的 id 只做 config 覆盖/禁用)
✅ 在 cordis.patch.yml 里用 - insert: 包起来
步骤(DSH_HOME 通常是 %APPDATA%\dsh-desktop\harness):
把本包放进 profile 的
node_modules:<DSH_HOME>\profiles\web\node_modules\dsh-memory-delta\ package.json bin\mem.mjs src\plugin.mjs src\hook.mjs src\planner.mjs在
<DSH_HOME>\profiles\web\cordis.patch.yml末尾追加:- insert: - id: dsh-memory-delta name: dsh-memory-delta config: root: '' # 留空 = 会话工作目录下的 memory/ maxBytes: 3072 # baseline 注入的字节预算 enabled: true dueWithin: 0 # verify_when 提前几天提醒复核(0 = 只在已到期时) panel: true # 侧边栏「记忆」页签的数据/动作路由 allowWrite: true # 允许面板按钮写记忆库(收件箱提升 / 整理文件名) skill: true # 注册插件自带的技能(装了就能 /dsh-memory-delta 查用法与边界)保存即可 —— patch 层有
watchUserPatches,会热加载,不需要重启。
卸载:删掉 patch 里那段 - insert:,再删掉 node_modules\dsh-memory-delta 目录。
官方分发渠道(插件市场)的发布流程我还没摸;目前是本机安装方式。
插件提供什么
| 能力 | 说明 |
|---|---|
| 差分注入 | 首次注入全部 active 条目(baseline);之后每轮只推「新增 / 已更新 / 已失效」;无变化时零注入 |
memory_search |
按相关度排序的检索,覆盖 facts / decisions / inbox / archive / journal / 会话索引。字段有权重(key/id > tags > 结论 > 正文)、整串短语有加成;中文按 bigram 匹配,所以 沙箱禁管道 能命中 沙箱禁止命名管道,不用手动加空格。每条结果带 score 与"命中最多的那一行"的片段 |
memory_write |
把候选条目写进 inbox —— 模型不允许直接改事实层 |
| 蒸馏提醒 | 会话跑过若干轮而记忆已是最新时,提醒模型把本次结论落到 inbox;每会话只提醒一次,且提醒消息不带状态,不污染差分基线 |
| 到期复核提醒 | verify_when 不再是死字段:条目到了当初约定的复核期,会话里会提醒一次"这条结论可能过时了,请复核",并给出该用哪条命令取代/标过期。写成人话的值(等换机器时)永远不会触发它(否则每个会话都弹一次、怎么改都消不掉);只在"本轮本来不注入任何记忆"时才提醒,同样不带状态 |
| 自带技能 | 插件在 apply 时用 ctx.skills.register() 注册一个名为 dsh-memory-delta 的技能(运行时注册:不往用户目录写文件,插件卸载/重载即自动注销)。装了插件的工作区里,打 /dsh-memory-delta 就能调出用法与权限边界(模型只能写收件箱、提升/归档是人做的事),模型也能按描述判断相关性自己加载。不想要技能目录里多这一行,配 skill: false |
| 侧边栏「记忆」页签 | 装了 dsh-better-sidebar 后,侧边栏多一个记忆页:按流程阶段分组(待你确认 → 已在用 → 已归档,每组一句人话 + 顶部一条流程条)、可折叠(自绘箭头)、搜索框(搜条目 + 流水,中文连写也行 —— 与 mem recall、模型用的 memory_search 是同一套打分)。「已在用」可按四个维度看:主题(默认 —— 人指定的归纳,存成 frontmatter 的 topic:,用面板的「归类」按钮或 mem set --topic 设置)/ 类型(事实/决策,回答"该放哪边")/ 标签(按主题关键词)/ 日期(什么时候记的,带"今天/昨天/周几"人话标注),而且四个维度都作用于三个阶段(待你确认 / 已在用 / 已归档 都跟着分组,不再平铺)。每个分组头带**「选本组 N 条」,主题视图里还有「改主题名」(全库同名主题一起改,含归档层)与「搜这组」(只在这个主题里搜)。勾选条目(每行一个勾选框)会弹出批量条**:归类… / 提升 / 撤回 / 归档 / 取回 / 删除候选 / 清空勾选 —— 只有当所有选中条目都属于该动作要求的阶段时按钮才可用,危险动作走同一条行内确认条,部分失败逐条报出原因(撞"一个 key 只能有一个真相"时会点名哪几条、为什么)。点某条记忆 = 打开它那个 .md(走 better-sidebar 的官方 openFile,在侧边栏编辑器里预览/编辑)。双向迁移:候选「提升到 facts/ decisions/」⇄ 常驻「撤回」,常驻还能「归档」、归档能「取回」,候选可「删除」——危险动作一律走行内确认条(不用会阻塞无头截图的浏览器原生 confirm)。「已在用」里还会显示全局规范(~/.dsh/AGENTS.md:DSH 注入、每个工作区都生效,只读预览 + 默认折叠)与工作区规范(AGENTS.md / AGENTS.local.md,可直接点「编辑」进侧边栏编辑器 —— 它们在工作区内,编辑器允许打开)。客户端半边是手写的零构建浏览器 bundle(window.__ModuleLoader__.load({id, factory}) 包装,不引入任何打包器);数据来自本插件自己的只读路由 POST /dsh-memory-delta/state 与 POST /dsh-memory-delta/search —— 仅回环、JSON 进 JSON 出、不碰别的文件。唯一会写的路由是 POST /dsh-memory-delta/action(提升 / 撤回 / 归档 / 取回 / 删除候选 / 安全改名 / 归类 / 主题改名 / 批量),可用 allowWrite: false 关掉 |
| 为什么不把"编辑/删除记忆"做进面板 | 侧边栏本来就有编辑器(点条目即打开)和文件树(重命名/删除带确认)。在面板里再造一套完整增删改 = 重复实现 + 长期维护负担,所以面板只做入口加几个真正需要判断的动作:打开文件、候选提升、常驻撤回、候选删除、整理文件名(mem rename:id + 文件名 + 引用一起改)。"跳到目录"这类纯跳转按钮不做 —— 折叠箭头看内容 + 点条目打开详情已经够,多一个按钮只多一份噪音和一条会启动外部进程的路由。⚠️ 不要用文件树直接给记忆条目改名 —— id 写在 frontmatter 里且必须与文件名一致,mem validate 会报 id 与文件名不一致;这正是不做自由改名、只做"安全改名"的原因。常驻条目不能直接删(那等于静默消失)—— 它的出路是「撤回」或取代/标过期 |
为什么插件不去 spawn CLI:DSH 沙箱禁止命名管道,捕获子进程输出会 EPERM;而且没必要 ——
插件直接 import 同一份 store 逻辑(bin/mem.mjs 只在被直接执行时才跑 CLI)。
它也不强依赖侧边栏或技能服务:webServer 与 skills 都是可选能力,通过 ctx.inject([...], cb)
等服务就绪后再注册 —— 用 ctx.get 在 apply 那一刻读会静默拿不到(真机上踩过一次:页签点开只报 405),
所以 headless / 纯 CLI 组合下插件照常加载,只是不注册面板路由与自带技能。

从侧边栏的 + 菜单打开的**「记忆」页签**:可折叠分组(标题后的等宽字是磁盘上的目录名)、
常驻条目与其语义键/标签/日期/文件名、待复核区、收件箱候选,以及当前记忆库每轮会话要花多少字节。
点条目就在编辑器里打开它(面板自己的写操作只走一条白名单路由
POST /dsh-memory-delta/action:提升 / 撤回 / 归档 / 取回 / 删除候选 / 安全改名 / 归类 / 主题改名 / 批量 ——
没有通用改写后门,allowWrite: false 可整条关掉)。
两个省心的默认:「已归档」默认折叠(退场的旧结论不挤占在用的条目,点开才看),
归档区分三层:已归档 → 分类 → 主题 → 条目。
分类就是“它为什么退场”(category 字段)—— 其中三个是常驻的(一条都没有时也显示,报 0 条):
已蒸馏(结论进了文档 / 被新版本顶上)、已废弃(彻底没用了、不会再启用)、
暂时不用(这个工作区暂时用不上,但换个业务/项目可能又要 —— 想再用:条目上「取回」→「提升」);
归档时可以选现成的,也可以自己写一个新的(批量归档同样能选)。
而「已蒸馏」是自动的(被取代 / 结论已搬进文档时由 mem supersede 落下,不靠人选),
事后在条目行点「分类」可改(v1.2.x 的旧默认名 已过期 会按 已废弃 归组,不用预先迁移)。
分类下面是主题行(这条记忆原本的 topic)——点开主题才列出条目(归档区先给你一张目录,
不会一上来倒几十条);没写主题的归档条目直接列在分类下,一眼能看到。
归档层同样跟随头部维度:切类型/标签/日期它也跟着换。
主题只有一级:主题名就是一个字符串(同名即同组,名字里真有 / 也只是普通字符)。
CLI 用法
# 初始化(默认 <cwd>/memory,可用 --root 或 $DSH_MEMORY_ROOT 改)
mem init --root ./memory --scope "workspace:/path/to/project"
# 记一条候选(落在 inbox,不注入)
# --id 推荐显式给短 id;不给则从结论派生(压到 20 字符,撞车自动加序号)
# --key 语义键:一个 scope+key 上只能有一个 active 真相
mem new --type fact --id win-update-cache --key disk-cleanup \
--conclusion "清更新缓存实测收益为零" \
--reason "目录删空但可用空间未变" --tags windows,disk --source session-abc
# 只给 --key 不给 --id 时,**key 就是 id(也就是文件名)**:sandbox-no-pipe.md
# 不给 key 才退回「日期 + 截断的结论」派生 id(中文结论会被截在词中间,尽量给 key)
# 确认后提升到事实层;同 key 已有 active 时必须显式说明谁取代谁
mem promote win-update-cache
mem promote win-update-cache-v2 --supersedes win-update-cache
mem demote <id> # 撤回:facts/decisions → inbox("先不当真",不改 status,还能再 promote 回去)
mem archive <id> # 归档:不再适用**又没有替代** → archive/(status=expired;仍可搜、可 restore)
mem restore <id> # 取回:archive/ → inbox(status 复位 active,再 promote 一次才重新生效)
mem rm <id> # 删除**候选**(只允许 inbox/);常驻条目的出路是 demote / archive / 取代,不直接删
mem set <id> --key k --tags a,b --conclusion "…" # 改已有条目(补 key / 改措辞 / 标 expired)
mem rename <旧id> <新id> # 安全改名:frontmatter 的 id、文件名、别处的 supersedes 引用一起改
# (别用文件树手动改名 —— id 与文件名必须一致)
mem list --status active --tag windows
mem show <id>
mem validate [--fix] # 格式/id/双向链接/环/同 key 冲突/索引/注入预算
mem index # 重建 index.md
mem inject [--json] [--budget 3072] # 渲染应注入内容;--json 出带 hash 的差分载荷
mem recall <关键词> [--where all|facts|decisions|inbox|archive|journal|sessions|index] [--limit N] [--json]
# 按相关度排序;中文按 bigram 匹配,不用手动加空格
mem due [--within N] [--json] # 到了 verify_when 复核期的条目(--within N 提前 N 天也算)
mem journal add "流水一行"
verify_when 可以写日期(2027-03-01),也可以写相对条目自身日期的说法
(3个月后 / 2周后 / 立即);其它写法按"人话"处理,不会被自动提醒。
验证(实机)
在真实 DSH 会话里逐项确认过:
| 能力 | 实机证据 |
|---|---|
| baseline 注入 | 会话收到全部 active 条目 |
| 无变化 → 零注入 | 下一步没有重复注入,只补了一次蒸馏提醒 |
| delta·新增 | "新增:<新条目>",并注明"其余 N 条未变化" |
| delta·已更新 | 改一条后只推"已更新:<该条>" |
| 到期复核提醒 | 加一条 verify_when 已过期 16 天的条目 → 下一个"无变化"的步骤弹出一次复核提醒,再下一步零注入(提醒没污染差分基线) |
| 侧边栏记忆页签 | 真机打开后显示真实库路径、条目条数、"注入 1792 / 3072 字节"、事实/决策分组,以及(空的)收件箱 |
memory_search / memory_write |
真机调用成功 |
| 写入只落 inbox | 写进去的候选确实没进注入载荷,promote 后才以 delta 出现 |
开发
npm test # 1283 个断言,零依赖
| 套件 | 断言 | 覆盖 |
|---|---|---|
test/run-tests.mjs |
295 | CLI 端到端(含非 ASCII 路径回归、相关度检索、mem due、mem rename 与引用同步、key 当文件名、topic 全生命周期、保留主题名、注入正文瘦身、手写 frontmatter 保真) |
test/planner-tests.mjs |
53 | 差分算法 + 注入正文渲染 + 来源形状必须过 DSH 会话格式准入(v4 起 kind 必须是生产者自有 kind,绝不能是 plugin) |
test/search-tests.mjs |
56 | 分词 / 按层加权 / 打分 / 片段选择(纯逻辑) |
test/due-tests.mjs |
93 | verify_when 解析(日期、相对说法、人话)与到期收集(纯逻辑) |
test/session-format-tests.mjs |
17 | 会话格式契约:拿内核自己的准入函数验我们写出去的来源(现行形态过 v4 准入、退役的 plugin 包装仍被它拒、四种历史读回形态都认得出、全仓没有第二处手写 kind 字面量)。内核模块找不到时打印 SKIP 跳过 |
test/peer-range-tests.mjs |
28 | peer 契约:声明的宿主范围必须覆盖我们声称支持的每个内核 —— 写成「每条支持线一个带预发布子句的 caret」(^0.1.x 的 caret 跨不过 minor,且预发布的 tuple 规则会让"一条大范围"在不开 includePrerelease 的检查器上全判 false);另含 vendor 配对、版本边界,以及两条纠正过的因果对照(真预检两代内核都开 includePrerelease,所以旧范围其实能过 —— "官方版被 peer 静默禁用"是当时的误判)。没装 semver 时那 23 条语义断言打印 SKIP;DSH_REQUIRE_SEMVER=1 时 SKIP 变失败(发版自检用) |
test/hook-tests.mjs |
66 | 插件接线(假 agent / decision):差分注入、状态侧车落盘时机、蒸馏提醒、到期提醒 |
test/plugin-tests.mjs |
317 | 插件集成(桩 DSH 模块,真 apply + 两个工具 + 三条面板路由 + promote/rename/topic/batch 真的写库 + 400/500 错误码分类 + 白名单/来源校验 + 工具输出契约与 render 文本) |
test/client-tests.mjs |
358 | 侧边栏面板 bundle(假 React + 假 fetch:分组/折叠、四个维度覆盖三个阶段、归类、批量勾选、点条目调 openFile、检索时序与截断提示、提升/整理文件名、失败态;含"没装 better-sidebar 时 apply 必须安全跳过"的回归,以及敌意门面/卸载时机那组:读不到 inject 也不能抛、fiber 释放后 timer 不许把异常扔进宿主、有界轮询 40 次封顶) |
test/plugin-tests.mjs 用 test/stubs/ 下的桩模块替换 4 个 @deepseek-ai/* 包,
通过 test/stub-loader.mjs 真正 apply() 这个插件并驱动它,所以即使没有 DSH 也能验证插件行为。
另有 test/preflight-import.mjs:把包放进 profile 后用真实 @deepseek-ai/* 模块跑一遍
(真实 defineTool 是否接受工具定义、真实 schemastery 是否接受配置 schema)。
几条从真实踩坑固化来的回归测试:
- 路径含非 ASCII 字符时,Node 的
fs.rmSync会静默失败(配recursive时甚至崩进程), 必须用unlinkSync; - DSH 沙箱禁止命名管道,
spawnSync默认的stdio:'pipe'会 EPERM,测试要把输出重定向到文件; - 工具写出的条目 scope 必须跟随会话工作区,不能落到 harness 进程的 cwd;
new URL(import.meta.url).pathname会把非 ASCII 用户名百分号编码 (C:\Users\李鹏飞→C:\Users\%E6%9D%8E%E9%B9%8F%E9%A3%9E),"往插件目录里写"就变成 "往一个根本不存在的路径里写" —— 一律用fileURLToPath;- 内部函数只给部分 return 路径补字段(
due),解构出来就是undefined,每一步都抛错、 又被外层 try/catch 包装成"加载记忆失败" —— 于是有了防御式取值 + "零告警"断言; - 注入消息的
source被 DSH 会话格式反向收紧过两次,两次都会让会话彻底不能用 —— 写的时候必须同时满足两代规则: v4 起(DSH 0.1.7):kind必须是生产者自有 kind,即非空字符串且 ≠plugin。 规范形态是{kind:'plugin:<包名>'}(也就是 v3→v4 迁移给第三方插件分配的形态)。 还按老写法写{kind:'plugin', plugin:'<包名>'}的话,编码器每次写会话日志都抛format v4 message requires a producer-owned source kind—— 会话一个字都存不进去, 界面上表现为每个会话第一轮就「本轮运行失败」。 v3 及以前的约束仍在(历史日志要能读):插件包装里只能有kind/plugin/form/sections/summary(v0→v1 白名单),自定义source.kind(更老的'memory')会被 v2→v3 拒 (cannot safely transform unclassified message source),而源日志按设计保持原样 —— 于是凡是收到过这种消息的老会话都永久打不开。差分状态因此改存侧车文件,不随消息走。
路线图
- M1 ✅ CLI + 结构化条目 + validate + 索引/注入预算
- M2 ✅ 显式短 id、语义键与「一个 key 一个真相」、
inject --json差分载荷、validate --fix、mem set - M3 ✅ DSH 插件:差分注入 + 两个工具 + 蒸馏提醒(已实机验证)
- M4 ✅ 发布(GitHub 主 / Gitee 镜像)
- M5 ✅ 让记忆"规模上真的可用":注入改索引式(正文不写 id,平均约 159 字节/条)、
按相关度排序的检索(中文 bigram)、
verify_when落地成到期复核提醒 - 下一步 条目变多时保持注入体积可控;发布到 npm
借鉴与致谢
「规格 / 变更 / 归档」这套纪律 —— 一份人可读的当前真相,加上一份待生效的变更集,落地后归档 —— 借鉴自 OpenSpec(MIT)。
dsh-memory-delta 是独立实现:不包含、也不调用 OpenSpec 的任何代码,存储格式与 CLI 都是自研的; 而且方向是反的 —— 记忆是被推进会话,而不是等 agent 来拉。
「OpenSpec」是其作者的项目名/商标;本文只作来源说明,不表示与该项目的关联或背书。
许可
MIT
评论
评论存放在 GitHub Discussions。用 GitHub 账号登录后可发表评论或点表情。