@lytharalab/dsh-cons-auto-review 1.2.2 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/README.md +8 -4
- package/docs/COMPATIBILITY.md +6 -4
- package/docs/RELEASING.md +2 -2
- package/package.json +30 -28
- package/src/engine.js +2 -0
- package/src/index.js +22 -7
- package/src/preset-defaults.js +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
# 1.2.3
|
|
2
|
+
|
|
3
|
+
- 适配 DSH **0.2.2-rc.1**,保留此前四个版本的支持。CI 在 Node.js 22 和 24 上分别验证五个 DSH 版本。
|
|
4
|
+
- 适配 Cordis 4.1 的权限配置保存与 DSH 新版 Agent 初始化。CAutoR 默认值继续保存只读守护项,子 Agent 在服务重载后保留 `never` 审批策略。
|
|
5
|
+
- 模型审查和审批说明翻译都携带当前会话 ID 与 `auto-review` 用途,满足新版 OpenCode 路由的请求要求。
|
|
6
|
+
|
|
1
7
|
# 1.2.2
|
|
2
8
|
|
|
3
9
|
- 适配 DSH **0.2.1-rc.5**,保留 **0.1.7-rc.2**、**0.2.0-rc.2** 与 **0.2.1-rc.2** 支持;测试依赖升级,CI 扩展为 Node.js 22 / 24 × 四个 DSH 版本。
|
package/README.md
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
# Con's 自动审查 — DCAR 1.2.
|
|
1
|
+
# Con's 自动审查 — DCAR 1.2.3
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@lytharalab/dsh-cons-auto-review)
|
|
4
4
|
[](https://github.com/LytharaLab/DSH-Cons-Auto-Review/actions/workflows/ci.yml)
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
|
-
> **English.** DCAR (`@lytharalab/dsh-cons-auto-review`) adds a **CAutoR** preset to the DeepSeek Harness permission menu. Deterministic rules approve safe operations first
|
|
7
|
+
> **English.** DCAR (`@lytharalab/dsh-cons-auto-review`) adds a **CAutoR** preset to the DeepSeek Harness permission menu. Deterministic rules approve safe workspace operations first. Other operations go to the LLM for review. Install with `dsh plugin --profile desktop add @lytharalab/dsh-cons-auto-review`. Requires Node.js 22.19+ or 24+ and supports DSH `0.1.7-rc.2`, `0.2.0-rc.2`, `0.2.1-rc.2`, `0.2.1-rc.5`, and `0.2.2-rc.1`.
|
|
8
8
|
|
|
9
9
|
**`@lytharalab/dsh-cons-auto-review`** 为 DeepSeek Harness 的「权限」菜单添加 **CAutoR** 模式:先用 DSH「工作区内修改」的确定性路径规则自动放行安全操作,仅将无法由程序自动批准的操作交给 LLM Auto Review。第一层只返回 `allow` 或 `escalate`。
|
|
10
10
|
|
|
11
11
|
## 安装与启用
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
通过 npm 安装 [`@lytharalab/dsh-cons-auto-review`](https://www.npmjs.com/package/@lytharalab/dsh-cons-auto-review)。要求 Node.js 22.19+ 或 24+,兼容并测试 DSH **0.1.7-rc.2**、**0.2.0-rc.2**、**0.2.1-rc.2**、**0.2.1-rc.5** 和 **0.2.2-rc.1**。
|
|
14
14
|
|
|
15
15
|
```powershell
|
|
16
16
|
dsh plugin --profile desktop add @lytharalab/dsh-cons-auto-review
|
|
@@ -20,7 +20,7 @@ Web 使用 `--profile web`。也可以离线安装解压的项目目录或仓库
|
|
|
20
20
|
|
|
21
21
|
```powershell
|
|
22
22
|
dsh plugin --profile desktop add "L:\Projects\DSH-Cons-Auto-Review"
|
|
23
|
-
dsh plugin --profile desktop add "L:\Projects\DSH-Cons-Auto-Review\lytharalab-dsh-cons-auto-review-1.2.
|
|
23
|
+
dsh plugin --profile desktop add "L:\Projects\DSH-Cons-Auto-Review\lytharalab-dsh-cons-auto-review-1.2.3.tgz"
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
**从旧包名升级:**包在首次公开发布时由 `dsh-cons-auto-review` 改名为 `@lytharalab/dsh-cons-auto-review`。关闭 Desktop,先移除旧包再装新包,然后重新打开:
|
|
@@ -66,6 +66,10 @@ profile 配置里若残留 `name: dsh-cons-auto-review` 的插件行或覆盖片
|
|
|
66
66
|
|
|
67
67
|
CAutoR 的执行策略是 `danger-full-access`。它复用原模式的路径审查逻辑,并以程序检查及 LLM 作为授权入口;不使用原执行沙箱隔离进程。
|
|
68
68
|
|
|
69
|
+
## 1.2.3 · DSH 0.2.2-rc.1 适配
|
|
70
|
+
|
|
71
|
+
适配新版的会话权限初始化、默认权限保存和工具执行器。审查请求携带当前会话 ID 与用途,供 OpenCode 路由识别。CI 在 Node.js 22 和 24 上验证五个受支持的 DSH 版本。
|
|
72
|
+
|
|
69
73
|
## 1.2.2 · DSH 0.2.1-rc.5 适配
|
|
70
74
|
|
|
71
75
|
支持 DSH **0.2.1-rc.5**,保留此前三个版本的兼容性。测试依赖使用新版真实服务,CI 覆盖 Node.js 22 / 24 × 四个 DSH 版本;新增模型能力动态变化及能力查询失败的真实服务回归验证。
|
package/docs/COMPATIBILITY.md
CHANGED
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
## 支持版本
|
|
4
4
|
|
|
5
|
-
DCAR 1.2.
|
|
5
|
+
DCAR 1.2.3 固定支持 DSH **0.1.7-rc.2**、**0.2.0-rc.2**、**0.2.1-rc.2**、**0.2.1-rc.5** 和 **0.2.2-rc.1**。关键路径使用官方扩展点 `tools/pre-execute`、权限 Session 投影、命令注册表、文件系统解析和 `ctx.llm.stream`。
|
|
6
|
+
|
|
7
|
+
DSH 0.2.2-rc.1 的权限初始化移到 Agent 发布阶段,DCAR 在同一阶段设置 CAutoR 默认值并读取子 Agent 已捕获的委派权限。默认值持久化适配 Cordis 4.1,审查与说明翻译都附带宿主要求的会话 ID 与请求用途。新版集成测试使用 DSH 原生工具执行器。[DSH 0.2.2-rc.1 源码基线](https://github.com/deepseek-ai/deepseek-harness/tree/66491b05e3f05ad35bcdd4f6cd7ed26041d9e3db)
|
|
6
8
|
|
|
7
9
|
源码基线:DeepSeek Harness `639ed015397290b3745d163aafe02ffee4aa3f84`(`dsh-v0.2.0-rc.2`);旧版本基线为 `477b4f420553e8a52c2fbccc464d7561b239c443`(`dsh-v0.1.7-rc.2`)。两版使用的 reviewer、permission service、containment 与文件路径解析源码一致。
|
|
8
10
|
|
|
@@ -14,7 +16,7 @@ DCAR 1.2.2 固定支持 DSH **0.1.7-rc.2**、**0.2.0-rc.2**、**0.2.1-rc.2** 与
|
|
|
14
16
|
|
|
15
17
|
官方权限服务只提供固定 `registerAuto()` 动态接口,通用自定义模式依赖静态预设表。1.0.2 由主插件在激活时给已存在的权限服务实例附加动态模式注册能力;安装补丁只插入 `dcar`,不替换宿主的权限服务行。
|
|
16
18
|
|
|
17
|
-
运行时适配覆盖该服务实例的 `names/specOf/derive/apply`,复用原始 Session 事件、沙箱和审批 setter、`/permission`、Remote `catalog()`、投影及官方 Auto 注册。审查入口安装后注册 CAutoR
|
|
19
|
+
运行时适配覆盖该服务实例的 `names/specOf/derive/apply`,复用原始 Session 事件、沙箱和审批 setter、`/permission`、Remote `catalog()`、投影及官方 Auto 注册。审查入口安装后注册 CAutoR;停用时取消审查、回退已加载会话,再撤销审查注册并还原服务原始属性;已保存的默认设置保留只读守护项。由于适配依赖权限服务的运行时方法,插件明确列出支持的 DSH 版本,并在加载时检查方法可用性。
|
|
18
20
|
|
|
19
21
|
DSH Web/desktop 的权限 UI 从该 `catalog()` 读取选项,自定义标签按服务端 `name` 显示,CAutoR 无需修改前端 bundle。
|
|
20
22
|
|
|
@@ -28,7 +30,7 @@ DSH Web/desktop 的权限 UI 从该 `catalog()` 读取选项,自定义标签
|
|
|
28
30
|
|
|
29
31
|
## 已运行的检查
|
|
30
32
|
|
|
31
|
-
见 `TEST_REPORT.md` 与 `test-results
|
|
33
|
+
见 `TEST_REPORT.md` 与 `test-results/`。五个版本分别安装对应的 DSH npm 包并运行插件测试。最早两个版本跳过三个依赖会话目录服务的用例。测试使用真实 Cordis、权限目录、Session、Session 投影、工具执行管线、原生文件读写工具、原生审批和命令服务,模型响应由本地测试 Adapter 提供。
|
|
32
34
|
|
|
33
35
|
覆盖本地零模型写入、按需升级、拒绝不执行、询问只在批准后执行、符号链接和目录前缀、Shell 混合语法、PTC 内部调用、子 Agent 与创建竞态、卸载回退、缺失审查提供者、配置验证、模型路由、重试、超时、并发、缓存和默认日志参数省略。
|
|
34
36
|
|
|
@@ -38,7 +40,7 @@ DSH Web/desktop 的权限 UI 从该 `catalog()` 读取选项,自定义标签
|
|
|
38
40
|
|
|
39
41
|
## 验证范围
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
CI 在 Linux 上使用 Node.js 22 和 24 运行兼容性矩阵。自动化验证通过宿主服务检查权限行为,覆盖范围包括 PTC 内层调用的审查,但未启动 PTC VM、真实远端模型 API、Desktop 窗口或 OS 级沙箱进程。
|
|
42
44
|
|
|
43
45
|
默认设置测试使用真实 Settings、Loader 和权限服务,并将配置保存到测试 JSON 文件后重新加载。测试存储替代 DSH 的完整多层 YAML 配置编辑器;未启动实际 Desktop 设置页面。
|
|
44
46
|
|
package/docs/RELEASING.md
CHANGED
|
@@ -64,10 +64,10 @@
|
|
|
64
64
|
|
|
65
65
|
## 工作流的几个约定
|
|
66
66
|
|
|
67
|
-
-
|
|
67
|
+
- 推送 `v*` 标签触发发布。手动 `workflow_dispatch` 运行校验和 `npm pack --dry-run`。
|
|
68
68
|
- 只有 `publish.yml` 会执行 `npm publish`。npm 的 trusted publisher 绑定的是 workflow 文件名,出现第二个能发布的 workflow 会互相干扰。
|
|
69
69
|
- 发布步骤使用 `--access public --provenance`;`actions/setup-node` 故意**不设置** `registry-url`,避免生成依赖 `NODE_AUTH_TOKEN` 的 `.npmrc`,发布目标由 `publishConfig.registry` 决定。
|
|
70
|
-
- `.github/workflows/ci.yml`
|
|
70
|
+
- `.github/workflows/ci.yml` 在分支推送与 PR 上用 Node.js 22 和 24 验证[受支持的 DSH 版本](COMPATIBILITY.md),并单独检查 npm 包内容。必需文件须齐全,测试、测试记录及工作流仅留在仓库。
|
|
71
71
|
|
|
72
72
|
## 发布包内容
|
|
73
73
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lytharalab/dsh-cons-auto-review",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3",
|
|
4
4
|
"description": "Con's 自动审查(DCAR):确定性规则优先、LLM 按需升级的 DeepSeek Harness 工具审查插件,提供 CAutoR 权限模式。Deterministic-first auto review for DeepSeek Harness.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -68,36 +68,38 @@
|
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"@deepseek-ai/cordis": "^4.0.0",
|
|
71
|
-
"@deepseek-ai/dsh-llm": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5",
|
|
72
|
-
"@deepseek-ai/dsh-permission-presets": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5",
|
|
73
|
-
"@deepseek-ai/dsh-sandbox": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5",
|
|
74
|
-
"@deepseek-ai/dsh-util-values": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5",
|
|
71
|
+
"@deepseek-ai/dsh-llm": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5 || 0.2.2-rc.1",
|
|
72
|
+
"@deepseek-ai/dsh-permission-presets": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5 || 0.2.2-rc.1",
|
|
73
|
+
"@deepseek-ai/dsh-sandbox": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5 || 0.2.2-rc.1",
|
|
74
|
+
"@deepseek-ai/dsh-util-values": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5 || 0.2.2-rc.1",
|
|
75
75
|
"@deepseek-ai/schemastery": "*",
|
|
76
|
-
"@deepseek-ai/dsh-user-approval": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5"
|
|
76
|
+
"@deepseek-ai/dsh-user-approval": "0.1.7-rc.2 || 0.2.0-rc.2 || 0.2.1-rc.2 || 0.2.1-rc.5 || 0.2.2-rc.1"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
|
-
"@deepseek-ai/cordis": "4.0
|
|
80
|
-
"@deepseek-ai/cordis-plugin-loader": "1.0
|
|
81
|
-
"@deepseek-ai/dsh-
|
|
82
|
-
"@deepseek-ai/dsh-
|
|
83
|
-
"@deepseek-ai/dsh-
|
|
84
|
-
"@deepseek-ai/dsh-fs
|
|
85
|
-
"@deepseek-ai/dsh-
|
|
86
|
-
"@deepseek-ai/dsh-
|
|
87
|
-
"@deepseek-ai/dsh-
|
|
88
|
-
"@deepseek-ai/dsh-sandbox
|
|
89
|
-
"@deepseek-ai/dsh-
|
|
90
|
-
"@deepseek-ai/dsh-
|
|
91
|
-
"@deepseek-ai/dsh-session
|
|
92
|
-
"@deepseek-ai/dsh-
|
|
93
|
-
"@deepseek-ai/dsh-
|
|
94
|
-
"@deepseek-ai/dsh-
|
|
95
|
-
"@deepseek-ai/dsh-
|
|
96
|
-
"@deepseek-ai/dsh-
|
|
97
|
-
"@deepseek-ai/dsh-
|
|
98
|
-
"@deepseek-ai/dsh-
|
|
99
|
-
"@deepseek-ai/dsh-
|
|
100
|
-
"@deepseek-ai/
|
|
79
|
+
"@deepseek-ai/cordis": "4.1.0",
|
|
80
|
+
"@deepseek-ai/cordis-plugin-loader": "1.1.0",
|
|
81
|
+
"@deepseek-ai/dsh-agent": "0.2.2-rc.1",
|
|
82
|
+
"@deepseek-ai/dsh-attachment": "0.2.2-rc.1",
|
|
83
|
+
"@deepseek-ai/dsh-commands": "0.2.2-rc.1",
|
|
84
|
+
"@deepseek-ai/dsh-fs": "0.2.2-rc.1",
|
|
85
|
+
"@deepseek-ai/dsh-fs-local": "0.2.2-rc.1",
|
|
86
|
+
"@deepseek-ai/dsh-llm": "0.2.2-rc.1",
|
|
87
|
+
"@deepseek-ai/dsh-permission-presets": "0.2.2-rc.1",
|
|
88
|
+
"@deepseek-ai/dsh-sandbox": "0.2.2-rc.1",
|
|
89
|
+
"@deepseek-ai/dsh-sandbox-policy": "0.2.2-rc.1",
|
|
90
|
+
"@deepseek-ai/dsh-scope": "0.2.2-rc.1",
|
|
91
|
+
"@deepseek-ai/dsh-session": "0.2.2-rc.1",
|
|
92
|
+
"@deepseek-ai/dsh-session-projection": "0.2.2-rc.1",
|
|
93
|
+
"@deepseek-ai/dsh-settings": "0.2.2-rc.1",
|
|
94
|
+
"@deepseek-ai/dsh-shell": "0.2.2-rc.1",
|
|
95
|
+
"@deepseek-ai/dsh-system-prompt": "0.2.2-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-tool-executor-native": "0.2.2-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-tool-fs": "0.2.2-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-tools": "0.2.2-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-user-approval": "0.2.2-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-util-values": "0.2.2-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-working-directory": "0.2.2-rc.1",
|
|
102
|
+
"@deepseek-ai/schemastery": "3.19.0",
|
|
101
103
|
"yaml": "2.8.3"
|
|
102
104
|
},
|
|
103
105
|
"icon": "./icon.svg",
|
package/src/engine.js
CHANGED
|
@@ -113,6 +113,8 @@ export class ReviewEngine {
|
|
|
113
113
|
const options = {
|
|
114
114
|
provider: c.review.provider || snapshot.provider,
|
|
115
115
|
model: c.review.model || snapshot.model,
|
|
116
|
+
sessionId: exec.agent.session.id,
|
|
117
|
+
purpose: "auto-review",
|
|
116
118
|
system:
|
|
117
119
|
REVIEW_POLICY +
|
|
118
120
|
(c.review.allowAsk
|
package/src/index.js
CHANGED
|
@@ -109,6 +109,16 @@ export function apply(ctx, input = {}) {
|
|
|
109
109
|
if (!accepting || !config.enabled) throw new Error("DCAR is disabled or closing");
|
|
110
110
|
};
|
|
111
111
|
const getConfig = (session) => overrides.get(session) ?? config;
|
|
112
|
+
// Hosts that seed permissions at agent creation forbid Session writes
|
|
113
|
+
// during session/created, which can still veto publication.
|
|
114
|
+
const defaultOnAgentCreated = presets.constructor.inject?.includes("agents");
|
|
115
|
+
function applyFreshDefault(session) {
|
|
116
|
+
const state = ctx.sessionProjections.stateOf(session, "permissions");
|
|
117
|
+
if (!session.header.parentSession && state?.preset === null &&
|
|
118
|
+
state.sandbox === null && state.approval === null && !state.seeded &&
|
|
119
|
+
presets.defaultPreset === PRESET)
|
|
120
|
+
presets.set(session, config.enabled ? PRESET : config.lifecycle.fallbackPreset);
|
|
121
|
+
}
|
|
112
122
|
function selected(session) {
|
|
113
123
|
if (presets.current(session) === PRESET) return true;
|
|
114
124
|
const state = ctx.sessionProjections.stateOf(session, "permissions");
|
|
@@ -144,19 +154,19 @@ export function apply(ctx, input = {}) {
|
|
|
144
154
|
(session) => {
|
|
145
155
|
if (!accepting) return;
|
|
146
156
|
markInherited(session);
|
|
147
|
-
|
|
148
|
-
if (!session.header.parentSession && state?.preset === null &&
|
|
149
|
-
state.sandbox === null && state.approval === null && !state.seeded &&
|
|
150
|
-
presets.defaultPreset === PRESET)
|
|
151
|
-
presets.set(session, accepting && config.enabled ? PRESET : config.lifecycle.fallbackPreset);
|
|
157
|
+
if (!defaultOnAgentCreated) applyFreshDefault(session);
|
|
152
158
|
},
|
|
153
159
|
{ prepend: true },
|
|
154
160
|
);
|
|
155
161
|
yield stopAgentCreated = ctx.on("agent/created", ({ agent }) => {
|
|
156
162
|
if (!accepting) return;
|
|
163
|
+
// Newer hosts append delegation overrides after session/created, before
|
|
164
|
+
// agent/created. Read them before the host fills in a missing preset.
|
|
165
|
+
markInherited(agent.session);
|
|
166
|
+
if (defaultOnAgentCreated) applyFreshDefault(agent.session);
|
|
157
167
|
if (inherited.has(agent.session))
|
|
158
168
|
agent.session.append("permission/preset", { preset: PRESET });
|
|
159
|
-
});
|
|
169
|
+
}, { prepend: true });
|
|
160
170
|
yield stopGate = ctx.on(
|
|
161
171
|
"tools/pre-execute",
|
|
162
172
|
async (exec, next) => {
|
|
@@ -210,7 +220,12 @@ export function apply(ctx, input = {}) {
|
|
|
210
220
|
const pending = handoff.get(session);
|
|
211
221
|
handoff.delete(session);
|
|
212
222
|
if (!config.enabled || !pending || pending.seq !== session.seq) continue;
|
|
213
|
-
|
|
223
|
+
const keepNever = pending.approval === "never";
|
|
224
|
+
if (keepNever && ctx.approval.overrideOf(session) !== "never")
|
|
225
|
+
setApprovalPolicy(session, "never");
|
|
226
|
+
presets.apply(session, PRESET, (policy) => {
|
|
227
|
+
if (!keepNever) setApprovalPolicy(session, policy);
|
|
228
|
+
});
|
|
214
229
|
if (pending.inherited) inherited.add(session);
|
|
215
230
|
}
|
|
216
231
|
// A session created while the persisted default's provider was absent starts
|
package/src/preset-defaults.js
CHANGED
|
@@ -42,8 +42,10 @@ export function registerReviewPreset(service, entries, name, spec, admit) {
|
|
|
42
42
|
/** Persist a confined CAutoR entry through the host's normal config editor. */
|
|
43
43
|
const persistenceKey = Symbol.for("dcar.default-persistence");
|
|
44
44
|
export function attachDefaultPersistence(editor, service, admit) {
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// Cordis can expose different views of one fiber through the service and
|
|
46
|
+
// loader. Within this editor's registry both views share a unique uid.
|
|
47
|
+
const providerId = Object.getOwnPropertyDescriptor(service, "ctx")?.value?.fiber.uid;
|
|
48
|
+
if (providerId == null) return () => {};
|
|
47
49
|
let registry = Object.getOwnPropertyDescriptor(editor, persistenceKey)?.value;
|
|
48
50
|
if (!registry) {
|
|
49
51
|
const previous = Object.getOwnPropertyDescriptor(editor, "edit");
|
|
@@ -56,7 +58,7 @@ export function attachDefaultPersistence(editor, service, admit) {
|
|
|
56
58
|
if (previous && !previous.configurable) throw new Error("DCAR cannot extend this config editor instance");
|
|
57
59
|
const handlers = new Map();
|
|
58
60
|
const wrapper = function (entry, change) {
|
|
59
|
-
const handler = handlers.get(entry.fiber);
|
|
61
|
+
const handler = handlers.get(entry.fiber?.uid);
|
|
60
62
|
if (!handler) return original.call(this, entry, change);
|
|
61
63
|
return original.call(this, entry, (current, inherited) => {
|
|
62
64
|
const next = change(current, inherited);
|
|
@@ -71,10 +73,10 @@ export function attachDefaultPersistence(editor, service, admit) {
|
|
|
71
73
|
Object.defineProperty(editor, persistenceKey, { value: registry, configurable: true });
|
|
72
74
|
}
|
|
73
75
|
const handler = { service, admit };
|
|
74
|
-
registry.handlers.set(
|
|
76
|
+
registry.handlers.set(providerId, handler);
|
|
75
77
|
return () => {
|
|
76
|
-
if (registry.handlers.get(
|
|
77
|
-
registry.handlers.delete(
|
|
78
|
+
if (registry.handlers.get(providerId) !== handler) return;
|
|
79
|
+
registry.handlers.delete(providerId);
|
|
78
80
|
if (registry.handlers.size) return;
|
|
79
81
|
if (Object.getOwnPropertyDescriptor(editor, "edit")?.value === registry.wrapper) {
|
|
80
82
|
if (registry.previous) Object.defineProperty(editor, "edit", registry.previous);
|