@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 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.2
1
+ # Con's 自动审查 — DCAR 1.2.3
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@lytharalab/dsh-cons-auto-review.svg)](https://www.npmjs.com/package/@lytharalab/dsh-cons-auto-review)
4
4
  [![CI](https://github.com/LytharaLab/DSH-Cons-Auto-Review/actions/workflows/ci.yml/badge.svg)](https://github.com/LytharaLab/DSH-Cons-Auto-Review/actions/workflows/ci.yml)
5
5
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](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 — workspace writes, declared temp/external roots, literal read-only shell commands — and only what a program cannot approve is escalated to the LLM auto-review. The deterministic layer returns `allow` or `escalate`, never a silent denial. Install with `dsh plugin --profile desktop add @lytharalab/dsh-cons-auto-review`; Node.js 22.19+ or 24+, tested against DSH `0.1.7-rc.2`, `0.2.0-rc.2`, `0.2.1-rc.2` and `0.2.1-rc.5`. The detailed documentation below is in Chinese.
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
- 包已发布到 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**。DSH 的插件 API 仍在变化,其他版本不作为 1.2.2 的兼容承诺。
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.2.tgz"
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 版本;新增模型能力动态变化及能力查询失败的真实服务回归验证。
@@ -2,7 +2,9 @@
2
2
 
3
3
  ## 支持版本
4
4
 
5
- DCAR 1.2.2 固定支持 DSH **0.1.7-rc.2**、**0.2.0-rc.2**、**0.2.1-rc.2** 与 **0.2.1-rc.5**。关键路径使用官方扩展点 `tools/pre-execute`、权限 Session 投影、命令注册表、文件系统解析和 `ctx.llm.stream`。
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;停用时取消审查、回退已加载会话,再撤销审查注册并还原服务原始属性;已保存的默认设置保留只读守护项。它需要官方类中 `specOf/derive/apply/emitCatalogChanged` 的运行时方法;这些不是通用稳定第三方扩展接口,因此依赖版本明确固定为以上四个版本,并在加载时检查方法可用性。插件不修改 DSH 安装目录中的源码,也不注册第二个权限服务。
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/`:四个发布版本分别安装对应的真实 DSH npm 包,运行完整插件测试;旧版显式跳过新版独有的目录服务场景。测试使用真实 Cordis、权限目录、Session、Session 投影、工具执行管线、原生文件读写工具、原生审批和命令服务;模型响应由本地测试 Adapter 提供。
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
- 1.2.2 与 1.2.1 验证环境为 Windows、Node.js 24.13.0;历史验证环境为 Linux、Node.js 24.19.0。未实际运行 Desktop 窗口、真实模型 API 或 OS 级沙箱进程。这里的 PTC 检查使用真实工具管线的 nested dispatch 输入,未启动 PTC VM。Node.js 22 / 24 的 Linux CI 矩阵仍需推送后运行。
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
- - 打标签(`v*`)触发真正的发布;手动 `workflow_dispatch` 只会跑校验与 `npm publish --dry-run`,不会真的上传。
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` 在每次推送与 PR 上跑 Node 22/24 × DSH `0.1.7-rc.2` / `0.2.0-rc.2` 矩阵,另外单独校验 npm 包内容:必需文件齐全、`tests/`、`test-results/`、`.github/` 不得进入发布包。
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.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.4",
80
- "@deepseek-ai/cordis-plugin-loader": "1.0.5",
81
- "@deepseek-ai/dsh-attachment": "0.2.1-rc.5",
82
- "@deepseek-ai/dsh-commands": "0.2.1-rc.5",
83
- "@deepseek-ai/dsh-fs": "0.2.1-rc.5",
84
- "@deepseek-ai/dsh-fs-local": "0.2.1-rc.5",
85
- "@deepseek-ai/dsh-llm": "0.2.1-rc.5",
86
- "@deepseek-ai/dsh-permission-presets": "0.2.1-rc.5",
87
- "@deepseek-ai/dsh-sandbox": "0.2.1-rc.5",
88
- "@deepseek-ai/dsh-sandbox-policy": "0.2.1-rc.5",
89
- "@deepseek-ai/dsh-scope": "0.2.1-rc.5",
90
- "@deepseek-ai/dsh-session": "0.2.1-rc.5",
91
- "@deepseek-ai/dsh-session-projection": "0.2.1-rc.5",
92
- "@deepseek-ai/dsh-settings": "0.2.1-rc.5",
93
- "@deepseek-ai/dsh-shell": "0.2.1-rc.5",
94
- "@deepseek-ai/dsh-system-prompt": "0.2.1-rc.5",
95
- "@deepseek-ai/dsh-tool-fs": "0.2.1-rc.5",
96
- "@deepseek-ai/dsh-tools": "0.2.1-rc.5",
97
- "@deepseek-ai/dsh-user-approval": "0.2.1-rc.5",
98
- "@deepseek-ai/dsh-util-values": "0.2.1-rc.5",
99
- "@deepseek-ai/dsh-working-directory": "0.2.1-rc.5",
100
- "@deepseek-ai/schemastery": "3.18.4",
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
- const state = ctx.sessionProjections.stateOf(session, "permissions");
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
- presets.apply(session, PRESET, (policy) => setApprovalPolicy(session, pending.approval === "never" ? "never" : policy));
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
@@ -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
- const provider = Object.getOwnPropertyDescriptor(service, "ctx")?.value?.fiber;
46
- if (!provider) return () => {};
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(provider, handler);
76
+ registry.handlers.set(providerId, handler);
75
77
  return () => {
76
- if (registry.handlers.get(provider) !== handler) return;
77
- registry.handlers.delete(provider);
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);