@deepseek-ai/dsh-client-ui-settings 0.1.1-rc.2 → 0.1.2-alpha.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/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-settings/README.md
5
- README.md: 990469573309b3a92b5eeb8bc41d89b226dbd0d4
6
- README.zh.md: a0ce9d5cf6d4633cec9fbf466083c7a11a947e8e
5
+ README.md: 1dbefefe51086a68d1f2afd36d098a118337f0b9
6
+ README.zh.md: 7009b4a7f156a613a7a1ef4e38b14c11d40fa85a
package/README.md CHANGED
@@ -1,13 +1,87 @@
1
+ ---
2
+ description: "Settings domain base plugin: the settings-namespace scope service, schema service, and the canonical settings slot-type contract for the dsh web client."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-settings
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- The settings domain's base layer, with no presentation of its own. It provides `ctx.settingsScope`, the Host transport every preference row binds its durable namespace section through; `ctx.settingsSchema`, the synchronous schema-rehydration, validation, and immutable path-editing service used by settings plugins; and the settings slot types registrants fill: `settings.trigger` / `settings.header` / `settings.close` (chrome content), `settings.action` (ordered content-header actions), `settings.section` (one page per feature), `settings.plugins.tab` (feature-owned pages inside the Plugins section), and `settings.onboarding` (ordered feature-owned pages). It depends on no `ui-*` presentation package, so any feature that owns a preference can reach it; the settings SHELL — the `sidebar.settings` occupant, its navigation, and the chrome — lives in ui-settings-general, because a shell dependency on ui-sidebar would close a reference graph cycle through ui-layout and ui-theme. The shell's own contract types live beside the shell for the same reason.
10
+ ## Summary
11
+
12
+ `dsh-client-ui-settings` is the base every preference surface in the dsh web client builds on: a feature plugin binds a namespace and stores or edits its preference rows in the Host settings document without re-implementing transport or schema handling. `ctx.settingsScope` derives a per-namespace scope from the shared document mirror with revision fencing, so a concurrent write from another surface is refused instead of silently overwritten; `ctx.settingsSchema` rehydrates and validates schemas and edits immutable paths synchronously. It declares the slot types settings surfaces fill — `settings.trigger`/`settings.header`/`settings.close` (chrome), `settings.action` (ordered header actions), `settings.section` (one page per feature), `settings.plugins.tab`, and `settings.onboarding` — and renders nothing itself. Because it depends on no `ui-*` presentation package, any feature that owns a preference can reach it; the settings shell itself lives in ui-settings-general.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Feature plugins use this package to store and edit their preferences without re-implementing transport or schema handling. Mount it once per composition; it injects the `remote` service with its `settings` namespace and owns the single `settings.describe` reader in the browser.
29
+
30
+ ### Binding a namespace
31
+
32
+ A feature calls `ctx.settingsScope.bind(spec)` with a per-namespace spec and gets a scope derived from the shared document mirror. The scope snapshot carries the resolved section, composition `base`, raw `user`, revision, writability, and host/memory mode; a field is overridden when it is present in `user`, even when its value equals `base`, and `unset` clears that override. Writes go through the scope: `set` and `unset` submit one operation, while `mutate` submits several ordered operations atomically. Each write is fenced by the namespace revision as `expectedRevision`, so a concurrent write from another surface is refused instead of silently overwritten. A staged editor can supply the revision where its draft began as a fixed fence; otherwise the scope uses the latest queued or mirrored revision.
33
+
34
+ ### Filling the settings slots
35
+
36
+ A settings surface registers into the slot types this package declares. The shell (`sidebar.settings` occupant, navigation, chrome) lives in ui-settings-general; feature pages register `settings.section` contributions; the Plugins section hosts `settings.plugins.tab` pages; onboarding steps register `settings.onboarding`. Cross-namespace surfaces (schema introspection, the served-namespace directory, `hasDocument`) read the same mirror through `ctx.settingsScope.describe()`.
37
+
38
+ ### Observable success and failures
39
+
40
+ A bound scope reflects the current document revision immediately; a committed write folds its answer back into the mirror with no re-read. A rejected or failed latest write triggers one mirror recovery read; a superseded write leaves recovery to its successor. Without a `decode` in the spec, a section that is not a plain object or fails schema rehydration publishes no value, so a row renders its own absent state instead of a half-decoded one.
41
+
42
+ -----
43
+
44
+ <a id="understand-the-implementation"></a>
45
+ ## Understand the implementation
46
+
47
+ <details>
48
+ <summary>Implementation internals — click to expand</summary>
49
+
50
+ The package realizes one ownership rule: the browser keeps one shared mirror of the settings document, and every derived surface reads that single source, so any moment in time shows the same document revision.
51
+
52
+ ### The describe mirror
6
53
 
7
- The plugin injects `connection` and `remote` and owns the one `settings.describe` reader in the browser: a shared mirror holding the whole answer, refreshed on every forwarded `settings/document-updated` event and on `connection/reset` (the first connection included that read closes the window where a commit lands between the eager read and the SSE subscription). Schema operations are synchronous and live on the `settingsSchema` service. `ctx.settingsScope.bind(spec)` returns a per-namespace scope DERIVED from the mirror on the CALLER's context — the scope's disposer belongs to the calling fiber, binding adds no wire read, a row's activation never blocks on the settings transport, and every derived surface shows the same document revision at any moment. Cross-namespace surfaces (schema introspection, the served-namespace directory, `hasDocument`) read the same mirror through `ctx.settingsScope.describe()`, a read/fold face (`getSnapshot`/`subscribe`/`ensure`, plus `acceptView` folding a write answer in). The scope snapshot carries the resolved section, composition `base`, raw `user`, revision, writability, and host/memory mode; a field is overridden when it is present in `user`, even when its value equals `base`, and `unset` clears that override. Writes stay per-scope: one field path fenced by the namespace revision as `expectedRevision`; a committed write folds its answer back into the mirror with no re-read, a rejected or failed latest write triggers one mirror recovery read, and a superseded one leaves recovery to its successor. Without a `decode` in the spec, a section that is not a plain object, fails its rehydrated schema, or carries a schema envelope this client cannot rehydrate publishes no value at all, so a row renders its own absent state instead of a half-decoded one. The cold-boot read count is pinned by `apps/web/tests/startup-rpc-budget.e2e.ts`; a new direct `settings.describe` caller in client code is a regression against it.
54
+ The plugin injects `remote` with its `settings` namespace, resolves Host persistence once from the fixed `remote.$host` facts, and owns the one `settings.describe` reader in the browser: a shared mirror refreshed on every forwarded `settings/document-updated` event and on `connection/reset` (the first connection included, closing the window where a commit lands between the eager read and the SSE subscription). Cross-namespace surfaces read it through `ctx.settingsScope.describe()`, a read/fold face (`getSnapshot`/`subscribe`/`ensure`, plus `acceptView` folding a write answer in).
55
+
56
+ ### Scope derivation
57
+
58
+ `ctx.settingsScope.bind(spec)` returns a per-namespace scope derived from the mirror on the caller's context: the scope's disposer belongs to the calling fiber, binding adds no wire read, and a row's activation never blocks on the settings transport. Writes stay per-scope: `set` and `unset` are single-operation forms of `mutate`, which copies and queues several ordered field operations behind one namespace revision as `expectedRevision`. A committed mutation folds its answer in, a rejected or failed latest mutation triggers one recovery read, and a superseded one leaves recovery to its successor. The cold-boot read count is pinned by `../../../apps/web/tests/startup-rpc-budget.e2e.ts`; a new direct `settings.describe` caller in client code is a regression against it.
59
+
60
+ ### Schema service
61
+
62
+ `ctx.settingsSchema` performs synchronous schema rehydration, validation, and immutable path editing for settings plugins. Without a `decode` in the spec, a section that is not a plain object, fails its rehydrated schema, or carries a schema envelope this client cannot rehydrate publishes no value at all.
63
+
64
+ </details>
65
+
66
+ -----
67
+
68
+ <a id="further-exploration"></a>
69
+ ## Further Exploration
70
+
71
+ These pages cover the settings surface family and the durable seam behind it.
72
+
73
+ - [ui-settings-general](../ui-settings-general/README.md) — the settings shell: trigger chrome, navigation, General section, onboarding projection.
74
+ - [ui-settings-plugins](../ui-settings-plugins/README.md) — the Plugins section and its configurable host-plane cards.
75
+ - [ui-settings-models](../ui-settings-models/README.md) — the Models page and DeepSeek onboarding over this base.
76
+ - [settings](../../settings/README.md) — the durable user-settings seam and its file provider.
77
+ - [ui-sidebar](../ui-sidebar/README.md) — the sidebar shell whose bottom seat hosts the settings trigger.
78
+
79
+ -----
80
+
81
+ <a id="model-experience"></a>
8
82
  ## Model Experience
9
83
 
10
- None, as the settings domain base serves browser preference storage and slot declarations; nothing here reaches a model request.
84
+ None, as the package is a browser-side UI plugin layer that registers nothing model-facing.
11
85
 
12
86
  #### KV Cache effect
13
87
 
@@ -15,5 +89,19 @@ None; this package neither assembles nor sends a provider request.
15
89
 
16
90
  ## Known Limitations and Deferred Work
17
91
 
18
- - **Remote browsers get no durable settings** — the settings RPCs are loopback-only, so a scope bound in a non-loopback browser starts `unavailable` and never crosses the wire; every row it backs is inert there.
19
- - **One field per write** — `set` sends a single `set` op, so a row that must move two fields together has no transaction and publishes two revisions.
92
+ <a id="known-limitations-and-deferred-work"></a>
93
+
94
+
95
+ These limits define where the settings transport cannot reach; they are current package constraints.
96
+
97
+ - **Non-loopback pages get no durable settings** — this Client keeps Host persistence disabled there, so a scope starts `unavailable` and never crosses the wire; every row it backs is inert even though Connection authentication covers the API.
98
+
99
+ <a id="dev-note"></a>
100
+ ### Dev Note
101
+
102
+ <details>
103
+ <summary>Working context for maintainers — click to expand</summary>
104
+
105
+ None.
106
+
107
+ </details>
package/README.zh.md CHANGED
@@ -1,19 +1,107 @@
1
+ ---
2
+ description: "设置领域底座插件:设置命名空间 scope 服务、schema 服务,以及 dsh Web 客户端的规范设置 slot 类型约定。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-settings
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 设置领域的底座,本身不含任何呈现内容。它提供 `ctx.settingsScope`——每个偏好设置行绑定自己那份持久化命名空间分区所用的宿主传输层;`ctx.settingsSchema`——设置插件使用的同步 schema 重建、校验与不可变路径编辑服务;并声明由注册方填充的设置 slot 类型:`settings.trigger`/`settings.header`/`settings.close`(界面框架内容)、`settings.action`(内容标题栏中的有序操作)、`settings.section`(每项功能一页)、`settings.plugins.tab`(“插件”分区内由各功能持有的页面)和 `settings.onboarding`(由各功能持有的有序页面)。它不依赖任何 `ui-*` 呈现包,因此任何持有偏好设置的功能都能够到它;设置**外壳**——`sidebar.settings` 占位方、它的导航与界面框架——位于 ui-settings-general,因为外壳一旦依赖 ui-sidebar,就会经 ui-layout 与 ui-theme 闭合出一条引用图环路。外壳自身的契约类型出于同一原因与外壳放在一起。
10
+ ## 概述
11
+
12
+ `dsh-client-ui-settings` 是 dsh Web 客户端每个偏好设置界面都依赖的底座:功能插件绑定一个命名空间,即可在宿主设置文档中存储或编辑自己的偏好设置行,而无需重新实现传输层或 schema 处理。`ctx.settingsScope` 从共享文档镜像派生按命名空间的 scope,并以 revision 设栅,因此来自另一界面的并发写入会被拒绝,而不是被静默覆盖;`ctx.settingsSchema` 同步重建并校验 schema、编辑不可变路径。它声明设置界面所填充的 slot 类型——`settings.trigger`/`settings.header`/`settings.close`(界面框架)、`settings.action`(有序标题栏操作)、`settings.section`(每项功能一页)、`settings.plugins.tab` 与 `settings.onboarding`——而自身不渲染任何内容。由于它不依赖任何 `ui-*` 呈现包,任何持有偏好设置的功能都能够到它;设置外壳本身位于 ui-settings-general。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 功能插件用本包存储与编辑自己的偏好设置,而无需重新实现传输层或 schema 处理。每个组合挂载一次即可;它注入 `remote` 服务及其 `settings` 命名空间,并持有浏览器中唯一的 `settings.describe` 读取方。
29
+
30
+ ### 绑定命名空间
31
+
32
+ 功能调用 `ctx.settingsScope.bind(spec)` 并传入按命名空间的 spec,得到一个由共享文档镜像派生的 scope。scope 快照携带解析后的分区、组合 `base`、原始 `user`、revision、可写性以及 host/内存模式;字段只要出现在 `user` 中即视为覆盖,即使其值与 `base` 相等,`unset` 会清除该覆盖。写入经 scope 进行:`set` 与 `unset` 提交一个操作,`mutate` 则原子提交多个有序操作。每次写入都以命名空间 revision 作为 `expectedRevision` 围栏,因此来自另一界面的并发写入会被拒绝,而不是被静默覆盖。暂存编辑器可以把开始草拟时读取的 revision 作为固定围栏传入;否则 scope 使用最新排队或镜像 revision。
33
+
34
+ ### 填充设置 slot
35
+
36
+ 设置界面会注册进本包声明的 slot 类型。外壳(`sidebar.settings` 占位方、导航、界面框架)位于 ui-settings-general;功能页面注册 `settings.section` 贡献;「插件」分区承载 `settings.plugins.tab` 页面;首次使用引导步骤注册 `settings.onboarding`。跨命名空间的表面(schema 内省、已服务命名空间目录、`hasDocument`)通过 `ctx.settingsScope.describe()` 读同一面镜像。
37
+
38
+ ### 可观察的成功与失败
39
+
40
+ 绑定后的 scope 会立即反映当前文档 revision;提交成功的写入把应答折回镜像、不再重读。被拒绝或失败的最新写入触发一次镜像恢复读取;被取代的写入把恢复留给后继者。若 spec 未提供 `decode`,则分区不是普通对象或未通过 schema 重建时一律不发布任何值,于是行渲染自己的缺失状态,而不是一份半解码的值。
41
+
42
+ -----
43
+
44
+ <a id="understand-the-implementation"></a>
45
+ ## 理解实现
46
+
47
+ <details>
48
+ <summary>实现细节——点击展开</summary>
49
+
50
+ 本包实现一条归属规则:浏览器保留设置文档的一面共享镜像,每个派生表面都读这同一真源,因此任一时刻看到的都是同一份文档 revision。
51
+
52
+ ### Describe 镜像
6
53
 
7
- 该插件注入 `connection` `remote`,并持有浏览器中唯一的 `settings.describe` 读取方:一面持有完整应答的共享镜像,在每次转发的 `settings/document-updated` 事件与 `connection/reset` 时刷新(首次连接也包含在内——这次读取关闭了「提交落在急切读取与 SSE 订阅之间、其失效通知丢失」的窗口)。schema 操作为同步调用,由 `settingsSchema` 服务承载。`ctx.settingsScope.bind(spec)` 在**调用方**的 context 上返回一个由镜像**派生**的按命名空间 scope——scope 的 disposer 归调用方 fiber 所有,绑定不新增任何线路读取,某一行的激活绝不会阻塞在设置传输层上,且任一时刻每个派生面看到的都是同一份文档 revision。跨命名空间的表面(schema 内省、已服务命名空间目录、`hasDocument`)通过 `ctx.settingsScope.describe()` 读同一面镜像,这是一个读取/折叠面(`getSnapshot`/`subscribe`/`ensure`,另有把写应答折入的 `acceptView`)。scope 快照携带解析后的分区、组合 `base`、原始 `user`、revision、可写性以及 host/内存模式;字段只要出现在 `user` 中即视为覆盖,即使其值与 `base` 相等,`unset` 会清除该覆盖。写入仍归各 scope:单一字段路径,以命名空间 revision 作为 `expectedRevision` 围栏;提交成功的写入将应答折回镜像、不再重读,被拒绝或失败的最新写入触发一次镜像恢复读取,被取代的写入则把恢复留给后继者。若 spec 未提供 `decode`,则分区不是普通对象、未通过其重建后的 schema 校验、或携带本客户端无法重建的 schema 信封时,一律不发布任何值,于是行渲染自己的缺失状态,而不是一份半解码的值。冷启动读取次数由 `apps/web/tests/startup-rpc-budget.e2e.ts` 钉住;客户端代码中新增直连 `settings.describe` 调用即是对它的回归。
54
+ 插件注入 `remote` 及其 `settings` 命名空间,从固定的 `remote.$host` 事实一次性解析 Host 持久化模式,并持有浏览器中唯一的 `settings.describe` 读取方:一面共享镜像,在每次转发的 `settings/document-updated` 事件与 `connection/reset` 时刷新(首次连接也包含在内,关闭「提交落在急切读取与 SSE 订阅之间」的窗口)。跨命名空间表面通过 `ctx.settingsScope.describe()` 读它,这是一个读取/折叠面(`getSnapshot`/`subscribe`/`ensure`,另有把写应答折入的 `acceptView`)。
55
+
56
+ ### Scope 派生
57
+
58
+ `ctx.settingsScope.bind(spec)` 在调用方的 context 上返回一个由镜像派生的按命名空间 scope:scope 的 disposer 归调用方 fiber 所有,绑定不新增任何线路读取,某一行的激活绝不会阻塞在设置传输层上。写入仍归各 scope:`set` 与 `unset` 是 `mutate` 的单操作形式,后者会复制操作列表,并把多个有序字段操作排在同一个作为 `expectedRevision` 的命名空间 revision 之后。提交成功的 mutation 把应答折回镜像,被拒绝或失败的最新 mutation 触发一次恢复读取,被取代的 mutation 把恢复留给后继者。冷启动读取次数由 `../../../apps/web/tests/startup-rpc-budget.e2e.ts` 钉住;客户端代码中新增直连 `settings.describe` 调用即是对它的回归。
59
+
60
+ ### Schema 服务
61
+
62
+ `ctx.settingsSchema` 为设置插件执行同步 schema 重建、校验与不可变路径编辑。若 spec 未提供 `decode`,则分区不是普通对象、未通过其重建后的 schema 校验、或携带本客户端无法重建的 schema 信封时,一律不发布任何值。
63
+
64
+ </details>
65
+
66
+ -----
67
+
68
+ <a id="further-exploration"></a>
69
+ ## 进一步探索
70
+
71
+ 以下页面覆盖设置界面家族及其背后的持久化 seam。
72
+
73
+ - [ui-settings-general](../ui-settings-general/README.zh.md)——设置外壳:触发控件、导航、「通用」分区、引导投影。
74
+ - [ui-settings-plugins](../ui-settings-plugins/README.zh.md)——「插件」分区及其可配置宿主平面卡片。
75
+ - [ui-settings-models](../ui-settings-models/README.zh.md)——建立在本底座之上的 Models 页面与 DeepSeek 引导。
76
+ - [settings](../../settings/README.zh.md)——持久化用户设置 seam 及其文件提供方。
77
+ - [ui-sidebar](../ui-sidebar/README.zh.md)——底部席位承载设置触发控件的侧边栏外壳。
78
+
79
+ -----
80
+
81
+ <a id="model-experience"></a>
8
82
  ## 模型体验
9
83
 
10
- 无。设置领域底座为浏览器提供偏好设置存储与 slot 声明;这里没有任何内容进入模型请求。
84
+ 无。该包是浏览器端 UI 插件层,不注册任何面向模型的内容。
11
85
 
12
86
  #### KV Cache 影响
13
87
 
14
88
  无;该包既不组装也不发送提供方请求。
15
89
 
16
- ## 已知限制与暂缓事项
90
+ ## 已知限制与延期工作
91
+
92
+ <a id="known-limitations-and-deferred-work"></a>
93
+
94
+
95
+ 这些限制说明设置传输层够不到的地方;它们是当前包约束。
96
+
97
+ - **非 loopback 页面没有持久化设置**:本 Client 在那里禁用 Host 持久化,因此 scope 以 `unavailable` 起步且从不跨线路;尽管 Connection 认证覆盖 API,它支撑的每一行仍在那里无效。
98
+
99
+ <a id="dev-note"></a>
100
+ ### 开发备注
101
+
102
+ <details>
103
+ <summary>维护者的工作上下文——点击展开</summary>
104
+
105
+ 无。
17
106
 
18
- - **远程浏览器没有持久化设置**:设置 RPC 仅限 loopback,因此在非 loopback 浏览器中绑定的 scope 以 `unavailable` 起步且从不跨线路,它支撑的每一行在那里都是无效的。
19
- - **每次写入仅一个字段**:`set` 只发送单个 `set` op,因此需要同时改动两个字段的行没有事务可用,会发布两个 revision。
107
+ </details>
package/lib/client.js CHANGED
@@ -5,7 +5,7 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
8
- let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
8
+ let _deepseek_ai_dsh_client_store = require("@deepseek-ai/dsh-client-store");
9
9
  //#region ../../../vendor/cosmokit/src/misc.ts
10
10
  /** Return true when a value is `null` or `undefined`. */
11
11
  function isNullable(value) {
@@ -934,11 +934,9 @@ window.__ModuleLoader__.load({
934
934
  //#endregion
935
935
  //#region lib/types/client/settings-scope.js
936
936
  /**
937
- * Host transport for the settings-namespace scope contract. The contract types
938
- * live in `dsh-client-runtime` (the common dependency of every feature that
939
- * owns a preference); this file owns the per-namespace derivation over the
940
- * shared {@link SettingsDescribeMirror} and the serialized write path, both of
941
- * which are Settings-surface concerns. Reads never touch the wire here: the
937
+ * Host transport for the settings-namespace scope contract. This file owns the
938
+ * per-namespace derivation over the shared {@link SettingsDescribeMirror} and
939
+ * the serialized write path. Reads never touch the wire here: the
942
940
  * mirror is the one `settings.describe` reader, and every scope is a selector
943
941
  * over its snapshot.
944
942
  */
@@ -949,7 +947,7 @@ window.__ModuleLoader__.load({
949
947
  * the operation already crossing the wire.
950
948
  */
951
949
  var SettingsScopeController = class {
952
- api;
950
+ ctx;
953
951
  spec;
954
952
  mirror;
955
953
  persistence;
@@ -966,19 +964,20 @@ window.__ModuleLoader__.load({
966
964
  */
967
965
  pendingRevision;
968
966
  /**
969
- * @param api - settings wire face (writes only; reads ride the mirror).
967
+ * @param ctx - the providing plugin's context, whose `remote.settings`
968
+ * namespace carries this scope's writes (reads ride the mirror).
970
969
  * @param spec - namespace identity and optional narrowing decoder.
971
970
  * @param mirror - the shared describe mirror this scope derives from.
972
- * @param persistence - remote browsers remain process-local because settings RPCs are loopback-only.
971
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
973
972
  * @param schema - settings-owned schema operations.
974
973
  */
975
- constructor(api, spec, mirror, persistence, schema) {
976
- this.api = api;
974
+ constructor(ctx, spec, mirror, persistence, schema) {
975
+ this.ctx = ctx;
977
976
  this.spec = spec;
978
977
  this.mirror = mirror;
979
978
  this.persistence = persistence;
980
979
  this.schema = schema;
981
- this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
980
+ this.store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
982
981
  status: persistence === "host" ? "loading" : "unavailable",
983
982
  value: void 0,
984
983
  base: void 0,
@@ -1014,11 +1013,11 @@ window.__ModuleLoader__.load({
1014
1013
  * @returns settlement after the write and any latest-write recovery read.
1015
1014
  */
1016
1015
  set(field, value) {
1017
- return this.write({
1016
+ return this.mutate([{
1018
1017
  op: "set",
1019
1018
  path: [field],
1020
1019
  value
1021
- });
1020
+ }]);
1022
1021
  }
1023
1022
  /**
1024
1023
  * Queue one field clear; see {@link SettingsScope.unset} for the ordering,
@@ -1027,35 +1026,32 @@ window.__ModuleLoader__.load({
1027
1026
  * @returns settlement after the clear and any latest-write recovery read.
1028
1027
  */
1029
1028
  unset(field) {
1030
- return this.write({
1029
+ return this.mutate([{
1031
1030
  op: "unset",
1032
1031
  path: [field]
1033
- });
1032
+ }]);
1034
1033
  }
1035
- write(op) {
1034
+ /**
1035
+ * Queue one atomic namespace mutation; see {@link SettingsScope.mutate}.
1036
+ * @param ops - ordered field operations copied when queued.
1037
+ * @param expectedRevision - optional fixed revision read by the domain editor.
1038
+ * @returns settlement after the mutation and any latest-write recovery read.
1039
+ */
1040
+ mutate(ops, expectedRevision) {
1041
+ const ownedOps = structuredClone(ops);
1036
1042
  const generation = ++this.writeGeneration;
1037
1043
  return this.enqueue(async () => {
1038
- const revision = this.pendingRevision ?? this.getSnapshot().revision;
1039
- let response;
1040
- try {
1041
- response = await this.api.settings.mutate({
1042
- ns: this.spec.namespace,
1043
- ops: [op],
1044
- ...revision === void 0 ? {} : { expectedRevision: revision }
1045
- });
1046
- } catch (_settingsWriteFailure) {
1047
- await this.recover(generation);
1048
- return;
1049
- }
1050
- if (!response.result.ok) {
1044
+ const revision = expectedRevision ?? this.pendingRevision ?? this.getSnapshot().revision;
1045
+ const response = await this.ctx.remote.settings.mutate(this.spec.namespace, ownedOps, revision);
1046
+ if (!response.ok) {
1051
1047
  await this.recover(generation);
1052
1048
  return;
1053
1049
  }
1054
1050
  if (this.disposed) return;
1055
1051
  if (generation === this.writeGeneration) {
1056
1052
  this.pendingRevision = void 0;
1057
- this.mirror.acceptView(response.result.value);
1058
- } else this.pendingRevision = response.result.value.revision;
1053
+ this.mirror.acceptView(response.value);
1054
+ } else this.pendingRevision = response.value.revision;
1059
1055
  });
1060
1056
  }
1061
1057
  /** Reload Host state for the latest failed write; superseded failures leave recovery to it. */
@@ -1130,15 +1126,25 @@ window.__ModuleLoader__.load({
1130
1126
  var SettingsScopeBinder = class extends _deepseek_ai_cordis.Service {
1131
1127
  mirror;
1132
1128
  schema;
1129
+ persistence;
1130
+ /**
1131
+ * The PROVIDING fiber, kept because a Service reads `ctx` as its *consumer's*
1132
+ * fiber: letting a bound scope write through the caller's context would make
1133
+ * every caller declare `remote.settings` in its own `inject`.
1134
+ */
1135
+ owner;
1133
1136
  /**
1134
1137
  * @param ctx - the providing plugin's context.
1135
1138
  * @param config - the shared describe mirror every bound scope derives from,
1136
- * plus the settings-owned schema operations.
1139
+ * the settings-owned schema operations, and the Host persistence the provider
1140
+ * resolved from `remote.$host`.
1137
1141
  */
1138
1142
  constructor(ctx, config) {
1139
1143
  super(ctx, "settingsScope");
1140
1144
  this.mirror = config.mirror;
1141
1145
  this.schema = config.schema;
1146
+ this.persistence = config.persistence;
1147
+ this.owner = ctx;
1142
1148
  }
1143
1149
  /**
1144
1150
  * The shared mirror's read/fold face for cross-namespace surfaces (schema
@@ -1162,8 +1168,7 @@ window.__ModuleLoader__.load({
1162
1168
  */
1163
1169
  bind(spec) {
1164
1170
  const ctx = this.ctx;
1165
- const connection = ctx.get("connection");
1166
- const controller = new SettingsScopeController(connection.api, spec, this.mirror, connection.isLoopback ? "host" : "memory", this.schema);
1171
+ const controller = new SettingsScopeController(this.owner, spec, this.mirror, this.persistence, this.schema);
1167
1172
  ctx.effect(() => {
1168
1173
  this.mirror.ensure();
1169
1174
  return async () => {
@@ -1191,20 +1196,21 @@ window.__ModuleLoader__.load({
1191
1196
  * so an invalidation arriving mid-read is never lost and never duplicated.
1192
1197
  */
1193
1198
  var SettingsDescribeMirror = class {
1194
- api;
1199
+ ctx;
1195
1200
  persistence;
1196
1201
  store;
1197
1202
  inFlight;
1198
1203
  rerun = false;
1199
1204
  generation = 0;
1200
1205
  /**
1201
- * @param api - settings wire face.
1202
- * @param persistence - remote browsers stay process-local because settings RPCs are loopback-only.
1206
+ * @param ctx - the providing plugin's context, whose `remote.settings`
1207
+ * namespace answers the describe read.
1208
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
1203
1209
  */
1204
- constructor(api, persistence = "host") {
1205
- this.api = api;
1210
+ constructor(ctx, persistence = "host") {
1211
+ this.ctx = ctx;
1206
1212
  this.persistence = persistence;
1207
- this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
1213
+ this.store = (0, _deepseek_ai_dsh_client_store.createSnapshotStore)({
1208
1214
  status: persistence === "host" ? "idle" : "unavailable",
1209
1215
  view: void 0,
1210
1216
  error: null
@@ -1290,8 +1296,8 @@ window.__ModuleLoader__.load({
1290
1296
  const generation = ++this.generation;
1291
1297
  let outcome;
1292
1298
  try {
1293
- const response = await this.api.settings.describe({});
1294
- outcome = response.result.ok ? { view: response.result.value } : { failure: response.result.error.message };
1299
+ const response = await this.ctx.remote.settings.describe();
1300
+ outcome = response.ok ? { view: response.value } : { failure: response.error.message };
1295
1301
  } catch (error) {
1296
1302
  outcome = { failure: error instanceof Error ? error.message : String(error) };
1297
1303
  }
@@ -1321,10 +1327,10 @@ window.__ModuleLoader__.load({
1321
1327
  //#endregion
1322
1328
  //#region lib/types/client/index.js
1323
1329
  /**
1324
- * Required services: the wire handle for the mirror's reads and the forwarded
1325
- * settings invalidation the mirror refreshes on.
1330
+ * Required services: the Remote namespace the mirror reads through and the
1331
+ * forwarded settings invalidation it refreshes on.
1326
1332
  */
1327
- const inject = ["connection", "remote"];
1333
+ const inject = ["remote", "remote.settings"];
1328
1334
  /**
1329
1335
  * Provide the settings-namespace scope service over one shared describe
1330
1336
  * mirror, and keep that mirror fresh on the two signals that can move the
@@ -1336,10 +1342,10 @@ window.__ModuleLoader__.load({
1336
1342
  */
1337
1343
  function apply(ctx) {
1338
1344
  const schema = new SettingsSchemaService(ctx);
1339
- const connection = ctx.get("connection");
1340
- const mirror = new SettingsDescribeMirror(connection.api, connection.isLoopback ? "host" : "memory");
1345
+ const persistence = ctx.remote.$host.isLoopback ? "host" : "memory";
1346
+ const mirror = new SettingsDescribeMirror(ctx, persistence);
1341
1347
  ctx.effect(() => {
1342
- const disposers = [ctx.get("remote").$on("settings/document-updated", () => {
1348
+ const disposers = [ctx.remote.$on("settings/document-updated", () => {
1343
1349
  mirror.load();
1344
1350
  }), ctx.on("connection/reset", () => {
1345
1351
  mirror.load();
@@ -1351,7 +1357,8 @@ window.__ModuleLoader__.load({
1351
1357
  }, "ui-settings: describe mirror invalidations");
1352
1358
  new SettingsScopeBinder(ctx, {
1353
1359
  mirror,
1354
- schema
1360
+ schema,
1361
+ persistence
1355
1362
  });
1356
1363
  }
1357
1364
  //#endregion
@@ -11,15 +11,16 @@
11
11
  * ui-sidebar would close a reference cycle through ui-layout and ui-theme.
12
12
  * Export discipline: packages/client/AGENTS.md.
13
13
  */
14
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
14
+ import type { Context } from '@deepseek-ai/cordis';
15
15
  export type { SettingsGeneralItemOwnerProps, SettingsHeaderOwnerProps, SettingsOnboardingOwnerProps, SettingsPluginsTabOwnerProps, SettingsSectionOwnerProps, SettingsTriggerOwnerProps, } from './contract/slots.ts';
16
16
  export type { SettingsScopeController, SettingsScopeBinder } from './settings-scope.ts';
17
+ export type { SettingsScope, SettingsScopeSnapshot, SettingsScopeSpec } from './settings-contract.ts';
17
18
  export type { SettingsSchemaService } from './schema.ts';
18
19
  export type { SchemaNode } from './schema.ts';
19
- export type { SettingsDescribeFace, SettingsDescribeView, SettingsMirrorSnapshot } from './settings-mirror.ts';
20
+ export type { SettingsDescribeFace, SettingsDescribeView, SettingsMirrorSnapshot, } from './settings-mirror.ts';
20
21
  /**
21
- * Required services: the wire handle for the mirror's reads and the forwarded
22
- * settings invalidation the mirror refreshes on.
22
+ * Required services: the Remote namespace the mirror reads through and the
23
+ * forwarded settings invalidation it refreshes on.
23
24
  */
24
25
  export declare const inject: string[];
25
26
  /**
@@ -31,5 +32,5 @@ export declare const inject: string[];
31
32
  * bound to each consuming plugin's context.
32
33
  * @param ctx - client root context.
33
34
  */
34
- export declare function apply(ctx: ClientContext): void;
35
+ export declare function apply(ctx: Context): void;
35
36
  //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Settings-namespace scope contracts owned beside the settings transport.
3
+ */
4
+ import type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client';
5
+ /** Client-side sync state of one settings namespace. */
6
+ export interface SettingsScopeSnapshot<T> {
7
+ /**
8
+ * `loading` until the first accepted section, `ready` while one stands, and
9
+ * `unavailable` when the namespace is not exposed to this client or the
10
+ * connection keeps preferences process-local (memory mode).
11
+ */
12
+ status: 'loading' | 'ready' | 'unavailable';
13
+ /** Last accepted schema-resolved section; undefined before the first acceptance. */
14
+ value: T | undefined;
15
+ /**
16
+ * Composition layer the Host resolved {@link value} over, when the owning
17
+ * plugin declared one. What a field reverts to once cleared.
18
+ */
19
+ base: unknown;
20
+ /**
21
+ * Raw user layer as stored, when one exists. A field's PRESENCE here is what
22
+ * marks it overridden — an override whose value equals the composition
23
+ * default is still an override, and comparing values could not see it.
24
+ */
25
+ user: unknown;
26
+ /** Namespace revision fencing the next write; undefined before the first Host view. */
27
+ revision: number | undefined;
28
+ /** Whether the Host document accepts writes; memory mode never does. */
29
+ writable: boolean;
30
+ /** `host` syncs with the Host document; `memory` keeps a remote browser process-local. */
31
+ mode: 'host' | 'memory';
32
+ }
33
+ /** Domain-owned description of one settings namespace consumed by a browser plugin. */
34
+ export interface SettingsScopeSpec<T> {
35
+ /** Settings namespace registered by the owning Host plugin. */
36
+ namespace: string;
37
+ /**
38
+ * Narrow one wire section; undefined keeps the last accepted value. The
39
+ * default validates the section against the namespace's own serialized wire
40
+ * schema, so domains add a decoder only to narrow beyond that schema.
41
+ */
42
+ decode?: (section: unknown) => T | undefined;
43
+ }
44
+ /**
45
+ * Reactive owner handle over one namespace's durable section — the browser
46
+ * mirror of the Host-side `SettingsScope` owner seam. Domain services read
47
+ * and observe the snapshot and route explicit user choices through its
48
+ * mutation methods.
49
+ */
50
+ export interface SettingsScope<T> {
51
+ /** @returns the current sync snapshot (stable reference until the next change). */
52
+ getSnapshot(): SettingsScopeSnapshot<T>;
53
+ /**
54
+ * Observe snapshot replacements.
55
+ * @param listener - invoked after each snapshot change.
56
+ * @returns the disposer removing this listener.
57
+ */
58
+ subscribe(listener: () => void): () => void;
59
+ /**
60
+ * Queue one atomic namespace mutation. All operations share one revision
61
+ * fence, Host validation, persistence decision, and recovery read. Supplying
62
+ * `expectedRevision` preserves an earlier read as the fence instead of using
63
+ * the latest queued or mirrored revision.
64
+ * @param ops - ordered field operations copied when queued.
65
+ * @param expectedRevision - optional fixed revision read by the domain editor.
66
+ * @returns settlement after the mutation and any latest-write recovery read.
67
+ */
68
+ mutate(ops: readonly SettingsPathOpView[], expectedRevision?: number): Promise<void>;
69
+ /**
70
+ * Queue one field write. Rapid writes preserve mutation order, each carries
71
+ * the latest known namespace revision, and only the latest settlement may
72
+ * publish; a rejected or failed latest write reloads Host state instead.
73
+ * @param field - scalar field inside the namespace section.
74
+ * @param value - JSON-shaped value selected by the user.
75
+ * @returns settlement after the write and any latest-write recovery read.
76
+ */
77
+ set(field: string, value: unknown): Promise<void>;
78
+ /**
79
+ * Queue one field clear, so the field re-inherits the composition layer.
80
+ * Shares {@link set}'s ordering, revision, and recovery contract.
81
+ * @param field - scalar field inside the namespace section.
82
+ * @returns settlement after the clear and any latest-write recovery read.
83
+ */
84
+ unset(field: string): Promise<void>;
85
+ }
86
+ //# sourceMappingURL=settings-contract.d.ts.map
@@ -8,8 +8,8 @@
8
8
  * invalidations its owning plugin subscribes to and folds write answers in
9
9
  * through {@link SettingsDescribeMirror.acceptView}.
10
10
  */
11
- import type { IApiClient, SettingsNamespaceView } from '@deepseek-ai/dsh-api-remotes/client';
12
- type SettingsFace = Pick<IApiClient, 'settings'>;
11
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
12
+ import type { SettingsNamespaceView } from '@deepseek-ai/dsh-api-remotes/client';
13
13
  /** The full `settings.describe` answer the mirror serves. */
14
14
  export interface SettingsDescribeView {
15
15
  /** Every namespace a live Host plugin registered, as the Host reported it. */
@@ -65,17 +65,18 @@ export interface SettingsDescribeFace {
65
65
  * so an invalidation arriving mid-read is never lost and never duplicated.
66
66
  */
67
67
  export declare class SettingsDescribeMirror implements SettingsDescribeFace {
68
- private readonly api;
68
+ private readonly ctx;
69
69
  private readonly persistence;
70
70
  private readonly store;
71
71
  private inFlight;
72
72
  private rerun;
73
73
  private generation;
74
74
  /**
75
- * @param api - settings wire face.
76
- * @param persistence - remote browsers stay process-local because settings RPCs are loopback-only.
75
+ * @param ctx - the providing plugin's context, whose `remote.settings`
76
+ * namespace answers the describe read.
77
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
77
78
  */
78
- constructor(api: SettingsFace, persistence?: 'host' | 'memory');
79
+ constructor(ctx: ClientContext, persistence?: 'host' | 'memory');
79
80
  /** @returns the current sync snapshot (stable reference until the next change). */
80
81
  getSnapshot(): SettingsMirrorSnapshot;
81
82
  /**
@@ -114,5 +115,4 @@ export declare class SettingsDescribeMirror implements SettingsDescribeFace {
114
115
  private run;
115
116
  private shouldRerun;
116
117
  }
117
- export {};
118
118
  //# sourceMappingURL=settings-mirror.d.ts.map
@@ -1,19 +1,16 @@
1
1
  /**
2
- * Host transport for the settings-namespace scope contract. The contract types
3
- * live in `dsh-client-runtime` (the common dependency of every feature that
4
- * owns a preference); this file owns the per-namespace derivation over the
5
- * shared {@link SettingsDescribeMirror} and the serialized write path, both of
6
- * which are Settings-surface concerns. Reads never touch the wire here: the
2
+ * Host transport for the settings-namespace scope contract. This file owns the
3
+ * per-namespace derivation over the shared {@link SettingsDescribeMirror} and
4
+ * the serialized write path. Reads never touch the wire here: the
7
5
  * mirror is the one `settings.describe` reader, and every scope is a selector
8
6
  * over its snapshot.
9
7
  */
10
8
  import { Service } from '@deepseek-ai/cordis';
11
9
  import type { Context } from '@deepseek-ai/cordis';
12
- import type { IApiClient } from '@deepseek-ai/dsh-api-remotes/client';
13
- import { type SettingsScope, type SettingsScopeSnapshot, type SettingsScopeSpec } from '@deepseek-ai/dsh-client-runtime/client';
10
+ import type { SettingsPathOpView } from '@deepseek-ai/dsh-api-remotes/client';
14
11
  import type { SettingsSchemaService } from './schema.ts';
12
+ import type { SettingsScope, SettingsScopeSnapshot, SettingsScopeSpec } from './settings-contract.ts';
15
13
  import { SettingsDescribeMirror, type SettingsDescribeFace } from './settings-mirror.ts';
16
- type SettingsFace = Pick<IApiClient, 'settings'>;
17
14
  /**
18
15
  * One namespace's derived view over the shared describe mirror, plus that
19
16
  * namespace's serialized Host writes. Writes carry the latest known namespace
@@ -21,7 +18,7 @@ type SettingsFace = Pick<IApiClient, 'settings'>;
21
18
  * the operation already crossing the wire.
22
19
  */
23
20
  export declare class SettingsScopeController<T> implements SettingsScope<T> {
24
- private readonly api;
21
+ private readonly ctx;
25
22
  private readonly spec;
26
23
  private readonly mirror;
27
24
  private readonly persistence;
@@ -38,13 +35,14 @@ export declare class SettingsScopeController<T> implements SettingsScope<T> {
38
35
  */
39
36
  private pendingRevision;
40
37
  /**
41
- * @param api - settings wire face (writes only; reads ride the mirror).
38
+ * @param ctx - the providing plugin's context, whose `remote.settings`
39
+ * namespace carries this scope's writes (reads ride the mirror).
42
40
  * @param spec - namespace identity and optional narrowing decoder.
43
41
  * @param mirror - the shared describe mirror this scope derives from.
44
- * @param persistence - remote browsers remain process-local because settings RPCs are loopback-only.
42
+ * @param persistence - client-selected Host persistence; non-loopback pages may remain process-local.
45
43
  * @param schema - settings-owned schema operations.
46
44
  */
47
- constructor(api: SettingsFace, spec: SettingsScopeSpec<T>, mirror: SettingsDescribeMirror, persistence: 'host' | 'memory', schema: SettingsSchemaService);
45
+ constructor(ctx: Context, spec: SettingsScopeSpec<T>, mirror: SettingsDescribeMirror, persistence: 'host' | 'memory', schema: SettingsSchemaService);
48
46
  /** @returns the current sync snapshot (stable reference until the next change). */
49
47
  getSnapshot(): SettingsScopeSnapshot<T>;
50
48
  /**
@@ -68,7 +66,13 @@ export declare class SettingsScopeController<T> implements SettingsScope<T> {
68
66
  * @returns settlement after the clear and any latest-write recovery read.
69
67
  */
70
68
  unset(field: string): Promise<void>;
71
- private write;
69
+ /**
70
+ * Queue one atomic namespace mutation; see {@link SettingsScope.mutate}.
71
+ * @param ops - ordered field operations copied when queued.
72
+ * @param expectedRevision - optional fixed revision read by the domain editor.
73
+ * @returns settlement after the mutation and any latest-write recovery read.
74
+ */
75
+ mutate(ops: readonly SettingsPathOpView[], expectedRevision?: number): Promise<void>;
72
76
  /** Reload Host state for the latest failed write; superseded failures leave recovery to it. */
73
77
  private recover;
74
78
  /**
@@ -96,14 +100,23 @@ declare module '@deepseek-ai/cordis' {
96
100
  export declare class SettingsScopeBinder extends Service {
97
101
  private readonly mirror;
98
102
  private readonly schema;
103
+ private readonly persistence;
104
+ /**
105
+ * The PROVIDING fiber, kept because a Service reads `ctx` as its *consumer's*
106
+ * fiber: letting a bound scope write through the caller's context would make
107
+ * every caller declare `remote.settings` in its own `inject`.
108
+ */
109
+ private readonly owner;
99
110
  /**
100
111
  * @param ctx - the providing plugin's context.
101
112
  * @param config - the shared describe mirror every bound scope derives from,
102
- * plus the settings-owned schema operations.
113
+ * the settings-owned schema operations, and the Host persistence the provider
114
+ * resolved from `remote.$host`.
103
115
  */
104
116
  constructor(ctx: Context, config: {
105
117
  mirror: SettingsDescribeMirror;
106
118
  schema: SettingsSchemaService;
119
+ persistence: 'host' | 'memory';
107
120
  });
108
121
  /**
109
122
  * The shared mirror's read/fold face for cross-namespace surfaces (schema
@@ -125,5 +138,4 @@ export declare class SettingsScopeBinder extends Service {
125
138
  */
126
139
  bind<T>(spec: SettingsScopeSpec<T>): SettingsScope<T>;
127
140
  }
128
- export {};
129
141
  //# sourceMappingURL=settings-scope.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-settings",
3
3
  "description": "Settings domain base plugin: the settings-namespace scope service and the canonical settings slot-type contract",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.3",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,36 +32,27 @@
32
32
  "dsh": {
33
33
  "client": {
34
34
  "inject": [
35
- "@deepseek-ai/dsh-client-connection",
36
- "@deepseek-ai/dsh-client-runtime",
37
35
  "@deepseek-ai/dsh-api-remotes"
38
36
  ],
39
37
  "platform": "web"
40
38
  }
41
39
  },
42
40
  "license": "MIT",
43
- "dependencies": {
44
- "@deepseek-ai/schemastery": "^3.18.1"
45
- },
46
41
  "peerDependencies": {
47
- "@deepseek-ai/cordis": "^4.0.1",
48
- "@deepseek-ai/dsh-api-remotes": "^0.1.1-rc.2",
49
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
50
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2",
51
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
52
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2"
42
+ "@deepseek-ai/cordis": "^4.0.2"
53
43
  },
54
44
  "devDependencies": {
55
45
  "@types/react": "~18.3.1",
56
46
  "react": "^18.2.0",
57
- "@deepseek-ai/cordis": "^4.0.1",
58
- "@deepseek-ai/dsh-api-remotes": "^0.1.1-rc.2",
59
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
60
- "@deepseek-ai/dsh-client-test-runtime": "^0.1.1-rc.2",
61
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.1-rc.2",
62
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
63
- "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
64
- "@deepseek-ai/dsh-client-connection": "^0.1.1-rc.2"
47
+ "@deepseek-ai/cordis": "^4.0.2",
48
+ "@deepseek-ai/dsh-api-remotes": "^0.1.2-alpha.3",
49
+ "@deepseek-ai/dsh-client-test-runtime": "^0.1.2-alpha.3",
50
+ "@deepseek-ai/dsh-client-store": "^0.1.2-alpha.3",
51
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.2-alpha.3",
52
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.3",
53
+ "@deepseek-ai/schemastery": "^3.18.2",
54
+ "@deepseek-ai/dsh-util-values": "^0.1.2-alpha.3",
55
+ "@deepseek-ai/dsh-settings": "^0.1.2-alpha.3"
65
56
  },
66
57
  "files": [
67
58
  "lib/index.js",