description: "Loader 补丁列表文件:cordis.patch.yml 各层共用的解析器,以及带锁、原子替换与回读的、保留注释的键级写入器。"
English | 中文
dsh-patch-file 拥有 harness 每一个组合层所使用的文件格式:一个 cordis.patch.yml 是 Loader 补丁条目的顶层 YAML 序列——按 id 定位的覆盖(如 disabled: true 或替换 config)与插入新行的 insert 列表——采用 Loader 自己的方言,其中 !!js 标量是由该行 fiber 求值的表达式。parsePatchList 是 profile launcher、组合包层、--patch 覆盖层与 agent preset 用户层共用的唯一解析器,因此其中一方接受的文件所有人都接受。PatchDocument 在键级编辑这样的文件,同时保留作者写下的注释、空行与 !!js 标量;mutatePatchFile 在跨进程写锁下提交一次编辑,经原子替换落盘,并在报告结果前把写入的文本经解析器回读,告诉调用方每个读者此后会加载到什么。
用 parsePatchList(已有文本)或 readPatchListFile(文件不存在时读到 undefined)读取一个补丁层。两者都把 insert 行中相对的名字(如 ./plugin.js)锚定到文件自己的目录,并对任何不是"映射序列"的内容直接报错,因为一个完全无法施加的补丁文件就是配置错误;而目标行不存在的单条补丁仍然只是 Loader 的逐条警告。
通过 mutatePatchFile 写入。回调拿到一个 PatchDocument,按 Loader 寻址行的方式以行 id 编辑:
await mutatePatchFile(file, (document) => {
document.setRowField('tool-web', 'disabled', true) // the id-targeted patch is created when absent
document.deleteRowField('tool-web', 'config') // a patch reduced to its id is removed whole
document.appendInsert({ id: 'tool-foo', name: 'dsh-tool-foo' }) // into the root list
document.appendInsert({ id: 'sql', name: 'dsh-sql' }, 'agents') // into the group with that id
document.removeInsert('tool-foo') // an emptied insert patch is removed whole
}, { binName: 'dsh', mode: 0o600, dirMode: 0o700 })
setRowField 永远不接受 id 与 insert;rowField 读回一个键,!!js 标量以其源文本返回。appendInsert 拒绝文件已插入的 id;insertedRow/removeInsert 也能找到插入组内部的行。写入的值都是普通数据;别的键上的 !!js 标量原样不动,这正是用户层能撤回自己写的 disabled: true 而不惊动组合包在另一行上的 !!js 门的原因。
mutatePatchFile 像 dsh-atomic-write 一样占用 <file>.lock 兄弟文件,读取文件(不存在按空处理),施加编辑,在文本有变化时以声明的权限位原子替换文件,然后返回从写入文本重新读出的补丁列表。什么都没改的编辑什么都不写。
当问题在于这种文件格式在组合中的位置时,读这些。
applyEntryPatches,每一层施加时所用的补丁语义。无,本包只读写组合补丁文件;这些文件点名的行拥有全部面向模型的注册。
无;本包既不组装也不发送 provider 请求。
这些限制界定写入器不会对文件做什么。它们是当前包的约束,不是任务清单。
setRowField('x', 'config', value) 替换该补丁的整个 config 映射;只想改一个嵌套字段的调用方先用 rowField 读出当前值,再把合并后的映射写回。!!js 门是作者敲进文件的东西,从不是某个 API 调用的产物。dsh-atomic-write 记录了同样的选择。