@deepseek-ai/dsh-client-ui-settings 0.0.1-rc.1 → 0.0.1-rc.2
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 +2 -2
- package/README.md +5 -4
- package/README.zh.md +5 -4
- package/lib/client.js +225 -297
- package/lib/index.js +1 -1
- package/lib/types/client/contract/slots.d.ts +28 -39
- package/lib/types/client/index.d.ts +17 -15
- package/lib/types/client/settings-scope.d.ts +102 -0
- package/lib/types/index.d.ts +1 -1
- package/package.json +23 -21
- package/lib/types/client/SettingsRoot.d.ts +0 -8
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:
|
|
6
|
-
README.zh.md:
|
|
5
|
+
README.md: 8bf085fd02e3c76148674065bb4f5708e9a6e8d8
|
|
6
|
+
README.zh.md: f7b6f18809c64be6830ea23c3968e9af70b70c41
|
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
English | [中文](README.zh.md)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
The settings domain's base layer, with two roles and no presentation of its own. It provides `ctx.settingsScope`, the Host transport every preference row binds its durable namespace section through, and it declares 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), 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.
|
|
6
6
|
|
|
7
|
-
The
|
|
7
|
+
The plugin injects nothing and waits for nothing: `ctx.settingsScope.bind(spec)` resolves the wire face through the CALLER's context at call time, so the bound scope's disposer belongs to the calling fiber, and the caller injects `connection` for the transport and `remote` for the invalidation. Listeners exist before the first background read starts, so a row's activation never blocks on the settings transport. A bound scope reloads on the forwarded `settings/document-updated` event for its own namespace and on `connection/reset`. Writes carry one field path and the last known namespace revision as `expectedRevision`; a rejected or failed write re-reads unless a newer write already superseded it, and a stale read never publishes over a newer one. 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.
|
|
8
8
|
|
|
9
9
|
## Model Experience
|
|
10
10
|
|
|
11
|
-
None, as the settings
|
|
11
|
+
None, as the settings domain base serves browser preference storage and slot declarations; nothing here reaches a model request.
|
|
12
12
|
|
|
13
13
|
#### KV Cache effect
|
|
14
14
|
|
|
@@ -16,4 +16,5 @@ None; this package neither assembles nor sends a provider request.
|
|
|
16
16
|
|
|
17
17
|
## Known Limitations and Deferred Work
|
|
18
18
|
|
|
19
|
-
- **
|
|
19
|
+
- **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.
|
|
20
|
+
- **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.
|
package/README.zh.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
[English](README.md) | 中文
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
设置领域的底座,承担两项职责,本身不含任何呈现内容。它提供 `ctx.settingsScope`——每个偏好设置行绑定自己那份持久化命名空间分区所用的宿主传输层;并声明由注册方填充的设置 slot 类型:`settings.trigger`/`settings.header`/`settings.close`(界面框架内容)、`settings.action`(内容标题栏中的有序操作)、`settings.section`(每项功能一页)和 `settings.onboarding`(由各功能持有的有序页面)。它不依赖任何 `ui-*` 呈现包,因此任何持有偏好设置的功能都能够到它;设置**外壳**——`sidebar.settings` 占位方、它的导航与界面框架——位于 ui-settings-general,因为外壳一旦依赖 ui-sidebar,就会经 ui-layout 与 ui-theme 闭合出一条引用图环路。外壳自身的契约类型出于同一原因与外壳放在一起。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
该插件不注入任何服务、也不等待任何服务:`ctx.settingsScope.bind(spec)` 在调用时经**调用方**的 context 解析线路面,因此绑定所得 scope 的 disposer 归调用方 fiber 所有,而由调用方注入 `connection` 取得传输层、注入 `remote` 取得失效通知。监听器在首次后台读取启动之前就已存在,因此某一行的激活绝不会阻塞在设置传输层上。已绑定的 scope 会在收到属于自己命名空间的转发 `settings/document-updated` 事件时、以及在 `connection/reset` 时重新读取。写入携带单一字段路径以及最近已知的命名空间 revision 作为 `expectedRevision`;被拒绝或失败的写入会重新读取,除非已有更新的写入取代了它,而过期的读取绝不会覆盖发布更新的结果。若 spec 未提供 `decode`,则分区不是普通对象、未通过其重建后的 schema 校验、或携带本客户端无法重建的 schema 信封时,一律不发布任何值,于是行渲染自己的缺失状态,而不是一份半解码的值。
|
|
8
8
|
|
|
9
9
|
## 模型体验
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
无。设置领域底座为浏览器提供偏好设置存储与 slot 声明;这里没有任何内容进入模型请求。
|
|
12
12
|
|
|
13
13
|
#### KV Cache 影响
|
|
14
14
|
|
|
@@ -16,4 +16,5 @@
|
|
|
16
16
|
|
|
17
17
|
## 已知限制与暂缓事项
|
|
18
18
|
|
|
19
|
-
-
|
|
19
|
+
- **远程浏览器没有持久化设置**:设置 RPC 仅限 loopback,因此在非 loopback 浏览器中绑定的 scope 以 `unavailable` 起步且从不跨线路,它支撑的每一行在那里都是无效的。
|
|
20
|
+
- **每次写入仅一个字段**:`set` 只发送单个 `set` op,因此需要同时改动两个字段的行没有事务可用,会发布两个 revision。
|
package/lib/client.js
CHANGED
|
@@ -4,319 +4,247 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let
|
|
8
|
-
let
|
|
9
|
-
let
|
|
10
|
-
|
|
11
|
-
//#region ../../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
12
|
-
function r(e) {
|
|
13
|
-
var t, f, n = "";
|
|
14
|
-
if ("string" == typeof e || "number" == typeof e) n += e;
|
|
15
|
-
else if ("object" == typeof e) if (Array.isArray(e)) {
|
|
16
|
-
var o = e.length;
|
|
17
|
-
for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f);
|
|
18
|
-
} else for (f in e) e[f] && (n && (n += " "), n += f);
|
|
19
|
-
return n;
|
|
20
|
-
}
|
|
21
|
-
function clsx() {
|
|
22
|
-
for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t);
|
|
23
|
-
return n;
|
|
24
|
-
}
|
|
25
|
-
//#endregion
|
|
26
|
-
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings/src/client/SettingsRoot.module.css.mjs
|
|
27
|
-
const css = ".Gph0iW_trigger{cursor:pointer;width:100%;height:49px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:12px;flex:none;align-items:center;gap:8px;margin:8px 0 0;padding:0 2px 0 6px;font-family:inherit;font-size:14px;display:flex;overflow:hidden}.Gph0iW_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.Gph0iW_trigger.Gph0iW_rail{border-radius:50%;justify-content:center;gap:0;width:36px;height:36px;margin:18px 0 10px;padding:0}.Gph0iW_triggerLabel{white-space:nowrap;overflow:hidden}.Gph0iW_overlay{z-index:1000;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.Gph0iW_mask{background:var(--dsw-alias-bg-mask-1);backdrop-filter:var(--dsw-mask-blur);position:absolute;inset:0}.Gph0iW_panel{z-index:1;background:var(--dsw-alias-bg-layer-2);width:800px;max-width:calc(100vw - 48px);height:min(800px,100vh - 48px);box-shadow:var(--dsw-shadow-lv3);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border-radius:24px;display:flex;position:relative;overflow:hidden}.Gph0iW_nav{box-sizing:border-box;flex-direction:column;flex:none;gap:18px;width:188px;padding:22px 12px 0;display:flex}.Gph0iW_navTitle{color:var(--dsw-alias-label-primary);padding:0 12px;font-size:16px;font-weight:500;line-height:24px}.Gph0iW_navList{flex-direction:column;gap:4px;display:flex}.Gph0iW_navCell{box-sizing:border-box;cursor:pointer;height:40px;color:var(--dsw-alias-label-primary);text-align:left;background:0 0;border:none;border-radius:12px;align-items:center;gap:8px;padding:9px 16px 9px 12px;font-family:inherit;font-size:14px;font-weight:400;line-height:22px;display:flex}.Gph0iW_navCell:hover{background:var(--dsw-specific-sidebar-nav-item-hover)}.Gph0iW_navCell.Gph0iW_active{background:var(--dsw-specific-sidebar-nav-item-active)}.Gph0iW_navIcon{flex:none}.Gph0iW_navLabel{white-space:nowrap;text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.Gph0iW_content{flex-direction:column;flex:1;min-width:0;display:flex}.Gph0iW_header{box-sizing:border-box;flex:none;justify-content:space-between;align-items:flex-start;gap:8px;height:54px;padding:20px 14px 8px 10px;display:flex}.Gph0iW_actions{justify-content:flex-end;align-items:center;gap:8px;min-width:0;margin-left:auto;display:flex}.Gph0iW_close{cursor:pointer;width:28px;height:28px;color:var(--dsw-alias-label-primary);background:0 0;border:none;border-radius:28px;justify-content:center;align-items:center;padding:0;display:inline-flex}.Gph0iW_close:hover{background:var(--dsw-alias-interactive-bg-hover)}.Gph0iW_options{flex:1;min-height:0;padding:0 24px 8px;overflow-y:auto}.Gph0iW_hiddenLabel{clip:rect(0 0 0 0);white-space:nowrap;width:1px;height:1px;position:absolute;overflow:hidden}";
|
|
28
|
-
const tagId = "@deepseek-ai/dsh-client-ui-settings/SettingsRoot.module.css";
|
|
29
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
30
|
-
const tag = document.createElement("style");
|
|
31
|
-
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings";
|
|
32
|
-
tag.dataset.pluginCss = tagId;
|
|
33
|
-
tag.textContent = css;
|
|
34
|
-
document.head.appendChild(tag);
|
|
35
|
-
}
|
|
36
|
-
var SettingsRoot_module_css_default = {
|
|
37
|
-
"hiddenLabel": "Gph0iW_hiddenLabel",
|
|
38
|
-
"active": "Gph0iW_active",
|
|
39
|
-
"panel": "Gph0iW_panel",
|
|
40
|
-
"navList": "Gph0iW_navList",
|
|
41
|
-
"header": "Gph0iW_header",
|
|
42
|
-
"nav": "Gph0iW_nav",
|
|
43
|
-
"trigger": "Gph0iW_trigger",
|
|
44
|
-
"navCell": "Gph0iW_navCell",
|
|
45
|
-
"content": "Gph0iW_content",
|
|
46
|
-
"rail": "Gph0iW_rail",
|
|
47
|
-
"overlay": "Gph0iW_overlay",
|
|
48
|
-
"navTitle": "Gph0iW_navTitle",
|
|
49
|
-
"triggerLabel": "Gph0iW_triggerLabel",
|
|
50
|
-
"mask": "Gph0iW_mask",
|
|
51
|
-
"navIcon": "Gph0iW_navIcon",
|
|
52
|
-
"actions": "Gph0iW_actions",
|
|
53
|
-
"close": "Gph0iW_close",
|
|
54
|
-
"navLabel": "Gph0iW_navLabel",
|
|
55
|
-
"options": "Gph0iW_options"
|
|
56
|
-
};
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region lib/types/client/SettingsRoot.js
|
|
7
|
+
let _deepseek_ai_cordis = require("@deepseek-ai/cordis");
|
|
8
|
+
let _deepseek_ai_dsh_client_schema_form = require("@deepseek-ai/dsh-client-schema-form");
|
|
9
|
+
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
10
|
+
//#region lib/types/client/settings-scope.js
|
|
59
11
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
* a
|
|
63
|
-
*
|
|
64
|
-
* names resolve to that content (trigger: its own text; dialog:
|
|
65
|
-
* aria-labelledby the title node; close: visually-hidden slot text). Modal
|
|
66
|
-
* open state and the active section id are component-local viewing state;
|
|
67
|
-
* the onboarding coordinator mounts exactly one ordered registrant while the
|
|
68
|
-
* sessions-derived empty-Hero fact is active — the takeover chrome
|
|
69
|
-
* (OnboardingSurface) belongs to the step, so a mounted-but-deciding step
|
|
70
|
-
* paints nothing here.
|
|
12
|
+
* Host transport for the settings-namespace scope contract. The contract types
|
|
13
|
+
* live in `dsh-client-runtime` (the common dependency of every feature that
|
|
14
|
+
* owns a preference); this file owns the wire behavior and the invalidation
|
|
15
|
+
* subscription, both of which are Settings-surface concerns.
|
|
71
16
|
*/
|
|
72
|
-
/** Nav glyph by section id; unknown ids fall back to the settings gear. */
|
|
73
|
-
function navIcon(id) {
|
|
74
|
-
if (id === "models") return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconDataOutline16, {
|
|
75
|
-
className: SettingsRoot_module_css_default.navIcon,
|
|
76
|
-
size: 16
|
|
77
|
-
});
|
|
78
|
-
if (id === "agent-presets") return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconThinkOutline16, {
|
|
79
|
-
className: SettingsRoot_module_css_default.navIcon,
|
|
80
|
-
size: 16
|
|
81
|
-
});
|
|
82
|
-
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, {
|
|
83
|
-
className: SettingsRoot_module_css_default.navIcon,
|
|
84
|
-
size: 16
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
17
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
18
|
+
* Serializes one namespace's Host reads and writes behind a snapshot store.
|
|
19
|
+
* Reads never block plugin activation; writes carry the latest known
|
|
20
|
+
* namespace revision and teardown waits for the operation already crossing
|
|
21
|
+
* the wire.
|
|
91
22
|
*/
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
23
|
+
var SettingsScopeController = class {
|
|
24
|
+
api;
|
|
25
|
+
spec;
|
|
26
|
+
persistence;
|
|
27
|
+
store;
|
|
28
|
+
tail = Promise.resolve();
|
|
29
|
+
readGeneration = 0;
|
|
30
|
+
writeGeneration = 0;
|
|
31
|
+
disposed = false;
|
|
32
|
+
/**
|
|
33
|
+
* @param api - settings wire face.
|
|
34
|
+
* @param spec - namespace identity and optional narrowing decoder.
|
|
35
|
+
* @param persistence - remote browsers remain process-local because settings RPCs are loopback-only.
|
|
36
|
+
*/
|
|
37
|
+
constructor(api, spec, persistence = "host") {
|
|
38
|
+
this.api = api;
|
|
39
|
+
this.spec = spec;
|
|
40
|
+
this.persistence = persistence;
|
|
41
|
+
this.store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
|
|
42
|
+
status: persistence === "host" ? "loading" : "unavailable",
|
|
43
|
+
value: void 0,
|
|
44
|
+
base: void 0,
|
|
45
|
+
user: void 0,
|
|
46
|
+
revision: void 0,
|
|
47
|
+
writable: false,
|
|
48
|
+
mode: persistence
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** @returns the current sync snapshot (stable reference until the next change). */
|
|
52
|
+
getSnapshot() {
|
|
53
|
+
return this.store.getSnapshot();
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Observe snapshot replacements.
|
|
57
|
+
* @param listener - invoked after each snapshot change.
|
|
58
|
+
* @returns the disposer removing this listener.
|
|
59
|
+
*/
|
|
60
|
+
subscribe(listener) {
|
|
61
|
+
return this.store.subscribe(listener);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Queue a Host refresh; a newer read or user write suppresses stale publication.
|
|
65
|
+
* @returns settlement after the queued read completes or is skipped.
|
|
66
|
+
*/
|
|
67
|
+
load() {
|
|
68
|
+
const generation = ++this.readGeneration;
|
|
69
|
+
return this.enqueue(() => this.read(generation));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Queue one field write; see {@link SettingsScope.set} for the ordering,
|
|
73
|
+
* revision, and recovery contract.
|
|
74
|
+
* @param field - scalar field inside the namespace section.
|
|
75
|
+
* @param value - JSON-shaped value selected by the user.
|
|
76
|
+
* @returns settlement after the write and any latest-write recovery read.
|
|
77
|
+
*/
|
|
78
|
+
set(field, value) {
|
|
79
|
+
return this.write({
|
|
80
|
+
op: "set",
|
|
81
|
+
path: [field],
|
|
82
|
+
value
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Queue one field clear; see {@link SettingsScope.unset} for the ordering,
|
|
87
|
+
* revision, and recovery contract.
|
|
88
|
+
* @param field - scalar field inside the namespace section.
|
|
89
|
+
* @returns settlement after the clear and any latest-write recovery read.
|
|
90
|
+
*/
|
|
91
|
+
unset(field) {
|
|
92
|
+
return this.write({
|
|
93
|
+
op: "unset",
|
|
94
|
+
path: [field]
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
write(op) {
|
|
98
|
+
this.readGeneration += 1;
|
|
99
|
+
const generation = ++this.writeGeneration;
|
|
100
|
+
return this.enqueue(async () => {
|
|
101
|
+
const revision = this.getSnapshot().revision;
|
|
102
|
+
let response;
|
|
103
|
+
try {
|
|
104
|
+
response = await this.api.settings.mutate({
|
|
105
|
+
ns: this.spec.namespace,
|
|
106
|
+
ops: [op],
|
|
107
|
+
...revision === void 0 ? {} : { expectedRevision: revision }
|
|
108
|
+
});
|
|
109
|
+
} catch (_settingsWriteFailure) {
|
|
110
|
+
if (!this.disposed && generation === this.writeGeneration) await this.read(++this.readGeneration);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (!response.result.ok) {
|
|
114
|
+
if (!this.disposed && generation === this.writeGeneration) await this.read(++this.readGeneration);
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.accept(response.result.value, generation === this.writeGeneration);
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Stop queued operations and wait for the current wire call to settle.
|
|
122
|
+
* @returns settlement after the controller reaches quiescence.
|
|
123
|
+
*/
|
|
124
|
+
async dispose() {
|
|
125
|
+
this.disposed = true;
|
|
126
|
+
this.readGeneration += 1;
|
|
127
|
+
this.writeGeneration += 1;
|
|
128
|
+
await this.tail;
|
|
129
|
+
}
|
|
130
|
+
enqueue(operation) {
|
|
131
|
+
if (this.persistence === "memory" || this.disposed) return Promise.resolve();
|
|
132
|
+
const task = this.tail.then(async () => {
|
|
133
|
+
if (this.disposed) return;
|
|
134
|
+
await operation();
|
|
135
|
+
});
|
|
136
|
+
this.tail = task.catch(() => {});
|
|
137
|
+
return task;
|
|
138
|
+
}
|
|
139
|
+
async read(generation) {
|
|
140
|
+
let response;
|
|
141
|
+
try {
|
|
142
|
+
response = await this.api.settings.describe({});
|
|
143
|
+
} catch (_settingsReadFailure) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (!response.result.ok || this.disposed) return;
|
|
147
|
+
const { namespaces, writable } = response.result.value;
|
|
148
|
+
const view = namespaces.find((candidate) => candidate.ns === this.spec.namespace);
|
|
149
|
+
const publish = generation === this.readGeneration;
|
|
150
|
+
if (view === void 0) {
|
|
151
|
+
if (publish) this.store.update((draft) => {
|
|
152
|
+
draft.status = "unavailable";
|
|
153
|
+
draft.writable = writable;
|
|
154
|
+
});
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
this.accept(view, publish, writable);
|
|
158
|
+
}
|
|
159
|
+
accept(view, publish, writable) {
|
|
160
|
+
const decoded = publish ? this.decode(view) : void 0;
|
|
161
|
+
this.store.update((draft) => {
|
|
162
|
+
draft.revision = view.revision;
|
|
163
|
+
draft.base = view.base;
|
|
164
|
+
draft.user = view.user;
|
|
165
|
+
if (writable !== void 0) draft.writable = writable;
|
|
166
|
+
if (decoded === void 0) return;
|
|
167
|
+
draft.status = "ready";
|
|
168
|
+
draft.value = decoded;
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
decode(view) {
|
|
172
|
+
if (this.spec.decode !== void 0) return this.spec.decode(view.value);
|
|
173
|
+
if (typeof view.value !== "object" || view.value === null || Array.isArray(view.value)) return void 0;
|
|
174
|
+
let failure;
|
|
175
|
+
try {
|
|
176
|
+
failure = (0, _deepseek_ai_dsh_client_schema_form.validateDraft)((0, _deepseek_ai_dsh_client_schema_form.rehydrateSchema)(view.schema), view.value);
|
|
177
|
+
} catch (_malformedSchemaEnvelope) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
return failure === void 0 ? view.value : void 0;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
166
183
|
/**
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
184
|
+
* The settings domain's base service. Features that own a preference reach the
|
|
185
|
+
* settings transport through this service rather than a shared function: the
|
|
186
|
+
* client bundle purity gate forbids cross-plugin value imports and directs
|
|
187
|
+
* cross-plugin collaboration through cordis services
|
|
188
|
+
* (`packages/client/tsdown.client.ts`).
|
|
170
189
|
*/
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
open && (0, react_jsx_runtime.jsx)(SettingsPanel, {
|
|
210
|
-
rows,
|
|
211
|
-
renderSlot,
|
|
212
|
-
activeId,
|
|
213
|
-
onSelect: setActiveId,
|
|
214
|
-
onClose: close
|
|
215
|
-
}),
|
|
216
|
-
onboardingStep !== void 0 && renderSlot("settings.onboarding", {
|
|
217
|
-
stepId: onboardingStep.id,
|
|
218
|
-
complete: () => {
|
|
219
|
-
completeOnboardingStep(onboardingStep.id);
|
|
220
|
-
},
|
|
221
|
-
openSection
|
|
222
|
-
}, { only: onboardingStep.id })
|
|
223
|
-
] });
|
|
224
|
-
}
|
|
190
|
+
var SettingsScopeService = class extends _deepseek_ai_cordis.Service {
|
|
191
|
+
/**
|
|
192
|
+
* @param ctx - the providing plugin's context.
|
|
193
|
+
*/
|
|
194
|
+
constructor(ctx) {
|
|
195
|
+
super(ctx, "settingsScope");
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Bind one namespace scope to settings and connection invalidations on the
|
|
199
|
+
* CALLER's plugin lifecycle — the service proxy binds `this.ctx` to the
|
|
200
|
+
* caller at call time, so the scope's disposer belongs to the calling fiber.
|
|
201
|
+
* Listeners exist before the initial background read starts, so activation
|
|
202
|
+
* never blocks on the settings transport. The caller injects `connection`
|
|
203
|
+
* for the transport and `remote` for the forwarded settings invalidation.
|
|
204
|
+
* @param spec - domain-owned namespace contract.
|
|
205
|
+
* @returns the bound scope consumed by the domain's services and rows.
|
|
206
|
+
*/
|
|
207
|
+
bind(spec) {
|
|
208
|
+
const ctx = this.ctx;
|
|
209
|
+
const connection = ctx.get("connection");
|
|
210
|
+
const controller = new SettingsScopeController(connection.api, spec, connection.isLoopback ? "host" : "memory");
|
|
211
|
+
ctx.effect(() => {
|
|
212
|
+
const refresh = (namespace) => {
|
|
213
|
+
if (namespace !== void 0 && namespace !== spec.namespace) return;
|
|
214
|
+
controller.load();
|
|
215
|
+
};
|
|
216
|
+
const disposers = [ctx.get("remote").$on("settings/document-updated", refresh), ctx.on("connection/reset", () => {
|
|
217
|
+
refresh();
|
|
218
|
+
})];
|
|
219
|
+
controller.load();
|
|
220
|
+
return async () => {
|
|
221
|
+
for (const dispose of disposers) dispose();
|
|
222
|
+
await controller.dispose();
|
|
223
|
+
};
|
|
224
|
+
}, `ui-settings: ${spec.namespace} settings scope`);
|
|
225
|
+
return controller;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
225
228
|
//#endregion
|
|
226
229
|
//#region lib/types/client/index.js
|
|
227
230
|
/**
|
|
228
|
-
* Required services
|
|
229
|
-
*
|
|
230
|
-
* constrained (dsh.client.inject edges are informational); registration
|
|
231
|
-
* depends on the slot through `slots.inject()`.
|
|
231
|
+
* Required services: none. The transport is resolved per caller through
|
|
232
|
+
* `this.ctx` at `bind` time, so this plugin waits for nothing.
|
|
232
233
|
*/
|
|
233
|
-
const inject = [
|
|
234
|
+
const inject = [];
|
|
234
235
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
236
|
+
* Provide the settings-namespace scope service.
|
|
237
|
+
*
|
|
238
|
+
* Constructing the service in this plugin's fiber keeps its traced methods
|
|
239
|
+
* bound to each consuming plugin's context.
|
|
237
240
|
* @param ctx - client root context.
|
|
238
241
|
*/
|
|
239
242
|
function apply(ctx) {
|
|
240
|
-
|
|
241
|
-
let rowsRevision = -1;
|
|
242
|
-
let rows = [];
|
|
243
|
-
let onboardingVersion = -1;
|
|
244
|
-
let onboardingSteps = [];
|
|
245
|
-
const localeRevision = () => ctx.get("locale")?.getSnapshot().revision ?? 0;
|
|
246
|
-
const injected = () => ({ hooks: {
|
|
247
|
-
sections: {
|
|
248
|
-
getSnapshot: () => {
|
|
249
|
-
const version = ctx.slots.getVersion("settings.section");
|
|
250
|
-
const revision = localeRevision();
|
|
251
|
-
if (version !== rowsVersion || revision !== rowsRevision) {
|
|
252
|
-
rowsVersion = version;
|
|
253
|
-
rowsRevision = revision;
|
|
254
|
-
rows = ctx.slots.entries("settings.section").map((e) => ({
|
|
255
|
-
/* v8 ignore next -- list-slot registration requires id (SlotCore rejects an entry without one) */
|
|
256
|
-
id: e.options.id ?? "",
|
|
257
|
-
order: e.options.order ?? 0,
|
|
258
|
-
label: (0, _deepseek_ai_dsh_client_ui_slots.resolveSlotLabel)(e.options.label) ?? ""
|
|
259
|
-
})).sort((a, b) => a.order - b.order);
|
|
260
|
-
}
|
|
261
|
-
return rows;
|
|
262
|
-
},
|
|
263
|
-
subscribe: (listener) => {
|
|
264
|
-
const offLedger = ctx.slots.subscribe("settings.section", listener);
|
|
265
|
-
const offLocale = ctx.get("locale")?.subscribe(listener);
|
|
266
|
-
return () => {
|
|
267
|
-
offLedger();
|
|
268
|
-
offLocale?.();
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
onboardingSteps: {
|
|
273
|
-
getSnapshot: () => {
|
|
274
|
-
const version = ctx.slots.getVersion("settings.onboarding");
|
|
275
|
-
if (version !== onboardingVersion) {
|
|
276
|
-
onboardingVersion = version;
|
|
277
|
-
onboardingSteps = ctx.slots.entries("settings.onboarding").map((e) => ({
|
|
278
|
-
/* v8 ignore next -- list-slot registration requires id */
|
|
279
|
-
id: e.options.id ?? "",
|
|
280
|
-
order: e.options.order ?? 0
|
|
281
|
-
})).sort((a, b) => a.order - b.order);
|
|
282
|
-
}
|
|
283
|
-
return onboardingSteps;
|
|
284
|
-
},
|
|
285
|
-
subscribe: (listener) => ctx.slots.subscribe("settings.onboarding", listener)
|
|
286
|
-
}
|
|
287
|
-
} });
|
|
288
|
-
ctx.slots.inject("sidebar.settings", () => ctx.slots.register({
|
|
289
|
-
name: "sidebar.settings",
|
|
290
|
-
children: {
|
|
291
|
-
"settings.trigger": {
|
|
292
|
-
kind: "single",
|
|
293
|
-
scope: "root"
|
|
294
|
-
},
|
|
295
|
-
"settings.header": {
|
|
296
|
-
kind: "single",
|
|
297
|
-
scope: "root"
|
|
298
|
-
},
|
|
299
|
-
"settings.action": {
|
|
300
|
-
kind: "list",
|
|
301
|
-
scope: "root"
|
|
302
|
-
},
|
|
303
|
-
"settings.close": {
|
|
304
|
-
kind: "single",
|
|
305
|
-
scope: "root"
|
|
306
|
-
},
|
|
307
|
-
"settings.section": {
|
|
308
|
-
kind: "list",
|
|
309
|
-
scope: "root"
|
|
310
|
-
},
|
|
311
|
-
"settings.onboarding": {
|
|
312
|
-
kind: "list",
|
|
313
|
-
scope: "root"
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
inject: injected
|
|
317
|
-
}, SettingsRoot));
|
|
243
|
+
new SettingsScopeService(ctx);
|
|
318
244
|
}
|
|
319
245
|
//#endregion
|
|
246
|
+
exports.SettingsScopeController = SettingsScopeController;
|
|
247
|
+
exports.SettingsScopeService = SettingsScopeService;
|
|
320
248
|
exports.apply = apply;
|
|
321
249
|
exports.inject = inject;
|
|
322
250
|
return module.exports;
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region lib/types/index.js
|
|
2
2
|
/** Host loader entry for the browser implementation exported from `./client`. */
|
|
3
|
-
/** Host plugin body — no host-side behavior for the settings
|
|
3
|
+
/** Host plugin body — no host-side behavior for the settings domain base plugin. */
|
|
4
4
|
function apply() {}
|
|
5
5
|
//#endregion
|
|
6
6
|
export { apply };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Settings
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* section content) arrives from registrants. A feature owns its
|
|
7
|
-
* setting never means editing the shell; copy
|
|
8
|
-
* feature (chrome, the General section) is owned by
|
|
2
|
+
* Settings slot contract — the canonical home of every settings slot type,
|
|
3
|
+
* owned by the settings domain base rather than by the shell that renders
|
|
4
|
+
* them (ui-settings-general, which occupies `sidebar.settings`). The shell has
|
|
5
|
+
* zero copy of its own: ALL text (trigger label, panel title, header actions,
|
|
6
|
+
* close aria, section content) arrives from registrants. A feature owns its
|
|
7
|
+
* own settings pages — adding a setting never means editing the shell; copy
|
|
8
|
+
* that belongs to no single feature (chrome, the General section) is owned by
|
|
9
|
+
* ui-settings-general too.
|
|
9
10
|
*/
|
|
10
|
-
import type { HostObservable, InjectFace, PropsRenderSlots, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
11
11
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
12
12
|
interface SlotMap {
|
|
13
13
|
/**
|
|
@@ -86,8 +86,28 @@ declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
|
86
86
|
scope: 'root';
|
|
87
87
|
owner: SettingsOnboardingOwnerProps;
|
|
88
88
|
};
|
|
89
|
+
/**
|
|
90
|
+
* One preference row inside the General section, contributed by the
|
|
91
|
+
* feature plugin that owns the preference (locale → Language, ui-theme →
|
|
92
|
+
* Appearance, ui-conversation → Composer Enter). Options: `id` (row key),
|
|
93
|
+
* `order` (row position). Rows draw their own internals; the section
|
|
94
|
+
* column only stacks them. Declared at runtime by ui-settings-general's
|
|
95
|
+
* General entry — the type lives here with every other settings slot type,
|
|
96
|
+
* because this package is the settings domain's base layer and every
|
|
97
|
+
* registrant already depends on it for `ctx.settingsScope`.
|
|
98
|
+
*/
|
|
99
|
+
'settings.general.item': {
|
|
100
|
+
kind: 'list';
|
|
101
|
+
scope: 'root';
|
|
102
|
+
owner: SettingsGeneralItemOwnerProps;
|
|
103
|
+
};
|
|
89
104
|
}
|
|
90
105
|
}
|
|
106
|
+
/** Owner share of a General preference row (the section supplies nothing). */
|
|
107
|
+
export interface SettingsGeneralItemOwnerProps {
|
|
108
|
+
/** Marker field: item owner props are intentionally empty. */
|
|
109
|
+
children?: never;
|
|
110
|
+
}
|
|
91
111
|
/** Owner share of the trigger content seat: the sidebar column state. */
|
|
92
112
|
export interface SettingsTriggerOwnerProps {
|
|
93
113
|
/** Whether the sidebar renders wide content (false = 56px rail, icon only). */
|
|
@@ -118,35 +138,4 @@ export interface SettingsOnboardingOwnerProps {
|
|
|
118
138
|
/** Open the settings panel directly on one registered section. */
|
|
119
139
|
openSection: (id: string) => void;
|
|
120
140
|
}
|
|
121
|
-
/** One nav row projected from a settings.section registration's options. */
|
|
122
|
-
export interface SettingsSectionRow {
|
|
123
|
-
id: string;
|
|
124
|
-
order: number;
|
|
125
|
-
label: string;
|
|
126
|
-
}
|
|
127
|
-
/** One ordered onboarding step projected from a slot registration. */
|
|
128
|
-
export interface SettingsOnboardingStep {
|
|
129
|
-
id: string;
|
|
130
|
-
order: number;
|
|
131
|
-
}
|
|
132
|
-
/**
|
|
133
|
-
* Registrant-private injected share of the settings shell (assembled in
|
|
134
|
-
* apply): the ledger's nav-row projection as a hooks-compartment source —
|
|
135
|
-
* the shell reads no locale state and subscribes through the bound hook.
|
|
136
|
-
*/
|
|
137
|
-
export type SettingsRootInjected = {
|
|
138
|
-
hooks: {
|
|
139
|
-
/** settings.section ledger projected into ordered nav rows. */
|
|
140
|
-
sections: HostObservable<readonly SettingsSectionRow[]>;
|
|
141
|
-
/** settings.onboarding ledger projected into coordinator order. */
|
|
142
|
-
onboardingSteps: HostObservable<readonly SettingsOnboardingStep[]>;
|
|
143
|
-
};
|
|
144
|
-
};
|
|
145
|
-
/**
|
|
146
|
-
* Full component props of the settings shell root: the sidebar owner share
|
|
147
|
-
* (wide/rail state) plus the declared render shares and the injected face
|
|
148
|
-
* (hooks compartment bound to useSections). No store is registered — modal
|
|
149
|
-
* open state and active section id are component-local viewing state.
|
|
150
|
-
*/
|
|
151
|
-
export type SettingsRootComponentProps = PropsRuntime<'sidebar.settings'> & PropsRenderSlots<'settings.trigger' | 'settings.header' | 'settings.action' | 'settings.close' | 'settings.section' | 'settings.onboarding'> & InjectFace<SettingsRootInjected>;
|
|
152
141
|
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Settings
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* Settings domain base plugin, browser half. Provides `ctx.settingsScope`, the
|
|
3
|
+
* settings-namespace Host transport every preference row binds its durable
|
|
4
|
+
* section through, and owns the canonical slot-type contract for the settings
|
|
5
|
+
* surface. It depends on no `ui-*` presentation package, so any feature that
|
|
6
|
+
* owns a preference can reach it: the settings SHELL — the `sidebar.settings`
|
|
7
|
+
* occupant, its navigation, and the chrome — lives in ui-settings-general,
|
|
8
|
+
* because a shell dependency on ui-sidebar would close a reference cycle
|
|
9
|
+
* through ui-layout and ui-theme. Export discipline: packages/client/AGENTS.md.
|
|
9
10
|
*/
|
|
10
11
|
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
11
|
-
export type {
|
|
12
|
+
export type { SettingsGeneralItemOwnerProps, SettingsHeaderOwnerProps, SettingsOnboardingOwnerProps, SettingsSectionOwnerProps, SettingsTriggerOwnerProps, } from './contract/slots.ts';
|
|
13
|
+
export { SettingsScopeController, SettingsScopeService } from './settings-scope.ts';
|
|
12
14
|
/**
|
|
13
|
-
* Required services
|
|
14
|
-
*
|
|
15
|
-
* constrained (dsh.client.inject edges are informational); registration
|
|
16
|
-
* depends on the slot through `slots.inject()`.
|
|
15
|
+
* Required services: none. The transport is resolved per caller through
|
|
16
|
+
* `this.ctx` at `bind` time, so this plugin waits for nothing.
|
|
17
17
|
*/
|
|
18
|
-
export declare const inject:
|
|
18
|
+
export declare const inject: never[];
|
|
19
19
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
20
|
+
* Provide the settings-namespace scope service.
|
|
21
|
+
*
|
|
22
|
+
* Constructing the service in this plugin's fiber keeps its traced methods
|
|
23
|
+
* bound to each consuming plugin's context.
|
|
22
24
|
* @param ctx - client root context.
|
|
23
25
|
*/
|
|
24
26
|
export declare function apply(ctx: ClientContext): void;
|
|
@@ -0,0 +1,102 @@
|
|
|
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 wire behavior and the invalidation
|
|
5
|
+
* subscription, both of which are Settings-surface concerns.
|
|
6
|
+
*/
|
|
7
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
8
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
9
|
+
import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client';
|
|
10
|
+
import { type SettingsScope, type SettingsScopeSnapshot, type SettingsScopeSpec } from '@deepseek-ai/dsh-client-runtime/client';
|
|
11
|
+
type SettingsFace = Pick<IApiClient, 'settings'>;
|
|
12
|
+
/**
|
|
13
|
+
* Serializes one namespace's Host reads and writes behind a snapshot store.
|
|
14
|
+
* Reads never block plugin activation; writes carry the latest known
|
|
15
|
+
* namespace revision and teardown waits for the operation already crossing
|
|
16
|
+
* the wire.
|
|
17
|
+
*/
|
|
18
|
+
export declare class SettingsScopeController<T> implements SettingsScope<T> {
|
|
19
|
+
private readonly api;
|
|
20
|
+
private readonly spec;
|
|
21
|
+
private readonly persistence;
|
|
22
|
+
private readonly store;
|
|
23
|
+
private tail;
|
|
24
|
+
private readGeneration;
|
|
25
|
+
private writeGeneration;
|
|
26
|
+
private disposed;
|
|
27
|
+
/**
|
|
28
|
+
* @param api - settings wire face.
|
|
29
|
+
* @param spec - namespace identity and optional narrowing decoder.
|
|
30
|
+
* @param persistence - remote browsers remain process-local because settings RPCs are loopback-only.
|
|
31
|
+
*/
|
|
32
|
+
constructor(api: SettingsFace, spec: SettingsScopeSpec<T>, persistence?: 'host' | 'memory');
|
|
33
|
+
/** @returns the current sync snapshot (stable reference until the next change). */
|
|
34
|
+
getSnapshot(): SettingsScopeSnapshot<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Observe snapshot replacements.
|
|
37
|
+
* @param listener - invoked after each snapshot change.
|
|
38
|
+
* @returns the disposer removing this listener.
|
|
39
|
+
*/
|
|
40
|
+
subscribe(listener: () => void): () => void;
|
|
41
|
+
/**
|
|
42
|
+
* Queue a Host refresh; a newer read or user write suppresses stale publication.
|
|
43
|
+
* @returns settlement after the queued read completes or is skipped.
|
|
44
|
+
*/
|
|
45
|
+
load(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Queue one field write; see {@link SettingsScope.set} for the ordering,
|
|
48
|
+
* revision, and recovery contract.
|
|
49
|
+
* @param field - scalar field inside the namespace section.
|
|
50
|
+
* @param value - JSON-shaped value selected by the user.
|
|
51
|
+
* @returns settlement after the write and any latest-write recovery read.
|
|
52
|
+
*/
|
|
53
|
+
set(field: string, value: unknown): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Queue one field clear; see {@link SettingsScope.unset} for the ordering,
|
|
56
|
+
* revision, and recovery contract.
|
|
57
|
+
* @param field - scalar field inside the namespace section.
|
|
58
|
+
* @returns settlement after the clear and any latest-write recovery read.
|
|
59
|
+
*/
|
|
60
|
+
unset(field: string): Promise<void>;
|
|
61
|
+
private write;
|
|
62
|
+
/**
|
|
63
|
+
* Stop queued operations and wait for the current wire call to settle.
|
|
64
|
+
* @returns settlement after the controller reaches quiescence.
|
|
65
|
+
*/
|
|
66
|
+
dispose(): Promise<void>;
|
|
67
|
+
private enqueue;
|
|
68
|
+
private read;
|
|
69
|
+
private accept;
|
|
70
|
+
private decode;
|
|
71
|
+
}
|
|
72
|
+
declare module '@deepseek-ai/cordis' {
|
|
73
|
+
interface Context {
|
|
74
|
+
settingsScope: SettingsScopeService;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The settings domain's base service. Features that own a preference reach the
|
|
79
|
+
* settings transport through this service rather than a shared function: the
|
|
80
|
+
* client bundle purity gate forbids cross-plugin value imports and directs
|
|
81
|
+
* cross-plugin collaboration through cordis services
|
|
82
|
+
* (`packages/client/tsdown.client.ts`).
|
|
83
|
+
*/
|
|
84
|
+
export declare class SettingsScopeService extends Service {
|
|
85
|
+
/**
|
|
86
|
+
* @param ctx - the providing plugin's context.
|
|
87
|
+
*/
|
|
88
|
+
constructor(ctx: Context);
|
|
89
|
+
/**
|
|
90
|
+
* Bind one namespace scope to settings and connection invalidations on the
|
|
91
|
+
* CALLER's plugin lifecycle — the service proxy binds `this.ctx` to the
|
|
92
|
+
* caller at call time, so the scope's disposer belongs to the calling fiber.
|
|
93
|
+
* Listeners exist before the initial background read starts, so activation
|
|
94
|
+
* never blocks on the settings transport. The caller injects `connection`
|
|
95
|
+
* for the transport and `remote` for the forwarded settings invalidation.
|
|
96
|
+
* @param spec - domain-owned namespace contract.
|
|
97
|
+
* @returns the bound scope consumed by the domain's services and rows.
|
|
98
|
+
*/
|
|
99
|
+
bind<T>(spec: SettingsScopeSpec<T>): SettingsScope<T>;
|
|
100
|
+
}
|
|
101
|
+
export {};
|
|
102
|
+
//# sourceMappingURL=settings-scope.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
/** Host loader entry for the browser implementation exported from `./client`. */
|
|
2
|
-
/** Host plugin body — no host-side behavior for the settings
|
|
2
|
+
/** Host plugin body — no host-side behavior for the settings domain base plugin. */
|
|
3
3
|
export declare function apply(): void;
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-settings",
|
|
3
|
-
"description": "Settings
|
|
4
|
-
"version": "0.0.1-rc.
|
|
3
|
+
"description": "Settings domain base plugin: the settings-namespace scope service and the canonical settings slot-type contract",
|
|
4
|
+
"version": "0.0.1-rc.2",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "restricted"
|
|
7
7
|
},
|
|
@@ -32,37 +32,39 @@
|
|
|
32
32
|
"dsh": {
|
|
33
33
|
"client": {
|
|
34
34
|
"inject": [
|
|
35
|
+
"@deepseek-ai/dsh-client-connection",
|
|
35
36
|
"@deepseek-ai/dsh-client-runtime",
|
|
36
|
-
"@deepseek-ai/dsh-
|
|
37
|
+
"@deepseek-ai/dsh-api-remotes"
|
|
37
38
|
],
|
|
38
39
|
"platform": "web"
|
|
39
40
|
}
|
|
40
41
|
},
|
|
41
42
|
"license": "BSD-3-Clause",
|
|
42
|
-
"dependencies": {
|
|
43
|
-
"clsx": "^2.0.0"
|
|
44
|
-
},
|
|
45
43
|
"peerDependencies": {
|
|
46
44
|
"react": "^18.2.0",
|
|
47
|
-
"
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-client-
|
|
50
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.
|
|
51
|
-
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.
|
|
52
|
-
"@deepseek-ai/
|
|
45
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
46
|
+
"@deepseek-ai/dsh-api-gateway": "^0.0.1-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-settings": "^0.0.1-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-api-remotes": "^0.0.1-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-client-connection": "^0.0.1-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-client-schema-form": "^0.0.1-rc.2"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|
|
55
|
-
"@types/react-dom": "~18.3.0",
|
|
56
56
|
"@types/react": "~18.3.1",
|
|
57
57
|
"react": "^18.2.0",
|
|
58
|
-
"
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-client-
|
|
61
|
-
"@deepseek-ai/dsh-client-
|
|
62
|
-
"@deepseek-ai/dsh-client-
|
|
63
|
-
"@deepseek-ai/
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/
|
|
58
|
+
"@deepseek-ai/dsh-api-gateway": "^0.0.1-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-api-remotes": "^0.0.1-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-client-connection": "^0.0.1-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-schema-form": "^0.0.1-rc.2",
|
|
63
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-client-test-runtime": "^0.0.1-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-settings": "^0.0.1-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.2"
|
|
66
68
|
},
|
|
67
69
|
"files": [
|
|
68
70
|
"lib/index.js",
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { SettingsRootComponentProps } from './contract/slots.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Render the settings trigger and panel.
|
|
4
|
-
* @param props - composed slot props (contract/slots.ts).
|
|
5
|
-
* @returns the settings shell element tree.
|
|
6
|
-
*/
|
|
7
|
-
export declare function SettingsRoot(props: SettingsRootComponentProps): import("react").JSX.Element;
|
|
8
|
-
//# sourceMappingURL=SettingsRoot.d.ts.map
|