@deepseek-ai/dsh-client-ui-settings-general 0.0.1-rc.1
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/LICENSE +28 -0
- package/README.i18n.yaml +6 -0
- package/README.md +21 -0
- package/README.zh.md +21 -0
- package/lib/client.js +612 -0
- package/lib/index.js +47 -0
- package/lib/invariant.js +25 -0
- package/lib/types/client/GeneralSection.d.ts +11 -0
- package/lib/types/client/SettingsDocumentAction.d.ts +21 -0
- package/lib/types/client/WelcomeNotice.d.ts +15 -0
- package/lib/types/client/chrome.d.ts +26 -0
- package/lib/types/client/index.d.ts +36 -0
- package/lib/types/client/locales.d.ts +35 -0
- package/lib/types/client/settings-document-store.d.ts +39 -0
- package/lib/types/client/welcome-store.d.ts +38 -0
- package/lib/types/index.d.ts +6 -0
- package/lib/types/invariant.d.ts +16 -0
- package/lib/types/onboarding-copy.d.ts +25 -0
- package/package.json +84 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026, DeepSeek
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
16
|
+
contributors may be used to endorse or promote products derived from
|
|
17
|
+
this software without specific prior written permission.
|
|
18
|
+
|
|
19
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
20
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
21
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
22
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
23
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
24
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
25
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
26
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
27
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.i18n.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Bilingual-pair consistency record (docs/i18n/README.md): the git blob hash of each
|
|
2
|
+
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
|
3
|
+
# after editing either side, bring the other along and re-record with:
|
|
4
|
+
# pnpm run verify-translation-pairing --write packages/client/ui-settings-general/README.md
|
|
5
|
+
README.md: ab27e073dc76335efc619f56365d1705007f7ef2
|
|
6
|
+
README.zh.md: 16ff5604bee5425569b783e27a29699344f630e3
|
package/README.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @deepseek-ai/dsh-client-ui-settings-general
|
|
2
|
+
|
|
3
|
+
English | [中文](README.zh.md)
|
|
4
|
+
|
|
5
|
+
Settings ownerless-copy and product-onboarding plugin: registers everything on the Settings surface that belongs to no single feature — the shell's trigger/header/close chrome content, the local configuration-file action, the General section and its `settings.general.item` slot, the `settings` dictionaries, and the first ordered welcome step. Feature-owned rows (Permission, Language, Appearance), sections (Models), and conditional onboarding steps stay with their feature packages.
|
|
6
|
+
|
|
7
|
+
A loopback browser loads the provider's `hasDocument` capability through `settings.describe` and renders **Open configuration file** only when the Host confirms that a provider-owned local document can be prepared. The action sends the pathless, loopback-only `settings.openDocument` request; the Host resolves the provider path again, materializes an absent document, and hands it to a native text editor (`open -t` on macOS, bypassing a browser file association; the desktop file association on Linux and Windows; Windows association after `wslpath -w` translation on WSL). Open failures keep the action available and render a localized error. Reopening the dialog or reconnecting refreshes availability after a transient read failure or Host topology change. Remote browsers never register the action and never issue the privileged settings read.
|
|
8
|
+
|
|
9
|
+
`src/onboarding-copy.ts` is the single editable owner of the complete notice plus `WELCOME_NOTICE_VERSION`; both supported GUI locales intentionally render the same Chinese copy. The Host half registers `ui-onboarding` in the user-settings seam. A loopback browser compares `welcomeNoticeVersion` for exact equality and writes the current value only after Continue succeeds. The path mutation is idempotent across tabs and preserves sibling settings, while `host/settings-changed` makes an externally acknowledged notice advance without a reload. A non-loopback browser cannot access the privileged settings API: it still presents the notice, but Continue advances only the current browser process and a reload presents the notice again. A different version deliberately presents the notice again. The welcome page preserves every authored paragraph, gives the requested clause in the final paragraph the sole emphasis, initially focuses the title, and has no close, Escape, mask-click, or secondary path. None of its copy or acknowledgement enters a Session log or model request. The notice identifies `DSH_TELEMETRY_DISABLED=1` as the telemetry opt-out.
|
|
10
|
+
|
|
11
|
+
## Model Experience
|
|
12
|
+
|
|
13
|
+
None, as the plugin renders browser settings UI; nothing here reaches a model request.
|
|
14
|
+
|
|
15
|
+
#### KV Cache effect
|
|
16
|
+
|
|
17
|
+
None; this package neither assembles nor sends a provider request.
|
|
18
|
+
|
|
19
|
+
## Known Limitations and Deferred Work
|
|
20
|
+
|
|
21
|
+
- The General section has no built-in rows; each row appears only when its owning feature plugin is mounted.
|
package/README.zh.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# @deepseek-ai/dsh-client-ui-settings-general
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 中文
|
|
4
|
+
|
|
5
|
+
设置界面无特定功能归属的文案与产品引导插件:在设置界面注册所有不属于单一功能的内容,包括外壳的触发器、标题栏与关闭控件内容、本地配置文件操作,「通用」分区及其 `settings.general.item` slot、`settings` 字典,以及第一个有序欢迎步骤。归具体功能所有的行(「权限」、「语言」、「外观」)、分区(「模型」)和条件式首次使用引导步骤仍由各自的功能包提供。
|
|
6
|
+
|
|
7
|
+
回环浏览器通过 `settings.describe` 加载提供方的 `hasDocument` 能力,且只有在 Host 确认可准备好一份由提供方持有的本地文档时才渲染**打开配置文件**。该操作发送无路径参数且仅限回环访问的 `settings.openDocument` 请求;Host 会再次解析提供方路径、在文档缺失时将其创建出来,并交给原生文本编辑器(macOS 上使用 `open -t`,绕过浏览器文件关联;Linux 和 Windows 上使用桌面文件关联;WSL 上经 `wslpath -w` 转换后使用 Windows 文件关联)。打开失败时该操作仍可使用,并渲染本地化错误。临时读取失败或 Host 拓扑变化后,重新打开对话框或重新连接会刷新可用性。远程浏览器从不注册该操作,也从不发起这项特权设置读取。
|
|
8
|
+
|
|
9
|
+
`src/onboarding-copy.ts` 是完整通知文案和 `WELCOME_NOTICE_VERSION` 的唯一可编辑来源;GUI 支持的两种 locale 都有意渲染同一份中文文案。宿主端在用户设置 seam 中注册 `ui-onboarding`。回环浏览器会比较 `welcomeNoticeVersion` 是否精确相等,仅在「继续」操作成功后写入当前值。该路径变更在不同标签页间幂等,并会保留同级设置;`host/settings-changed` 则让页面在通知被外部确认后,无需重新加载即可推进。非回环浏览器不能访问受保护的设置 API:它仍会显示通知,但「继续」只推进当前浏览器进程,重新加载后会再次显示通知。版本不同时,系统也会有意重新显示通知。欢迎页保留原文的每个段落,仅强调最后一段中指定的句段,初始焦点落在标题上,并且没有关闭操作、Escape、点击遮罩或次要操作路径。其文案和确认状态均不会进入会话日志或模型请求。通知明确以 `DSH_TELEMETRY_DISABLED=1` 作为遥测关闭方式。
|
|
10
|
+
|
|
11
|
+
## 模型体验
|
|
12
|
+
|
|
13
|
+
无。该插件渲染浏览器设置 UI;这里没有任何内容进入模型请求。
|
|
14
|
+
|
|
15
|
+
#### KV Cache 影响
|
|
16
|
+
|
|
17
|
+
无;该包既不组装也不发送提供方请求。
|
|
18
|
+
|
|
19
|
+
## 已知限制与暂缓事项
|
|
20
|
+
|
|
21
|
+
- 「通用」分区没有内置行;每一行仅在其所属功能插件挂载时出现。
|
package/lib/client.js
ADDED
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
window.__ModuleLoader__.load({
|
|
2
|
+
id: "@deepseek-ai/dsh-client-ui-settings-general",
|
|
3
|
+
factory: (require) => {
|
|
4
|
+
var module = { exports: {} };
|
|
5
|
+
var exports = module.exports;
|
|
6
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
+
let _deepseek_ai_dsh_client_web_react = require("@deepseek-ai/dsh-client-web-react");
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
10
|
+
let react = require("react");
|
|
11
|
+
let _deepseek_ai_dsh_client_runtime_client = require("@deepseek-ai/dsh-client-runtime/client");
|
|
12
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-general/src/client/chrome.module.css.mjs
|
|
13
|
+
const css$3 = ".UQsH_q_triggerLabel{white-space:nowrap;overflow:hidden}";
|
|
14
|
+
const tagId$3 = "@deepseek-ai/dsh-client-ui-settings-general/chrome.module.css";
|
|
15
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
16
|
+
const tag = document.createElement("style");
|
|
17
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-general";
|
|
18
|
+
tag.dataset.pluginCss = tagId$3;
|
|
19
|
+
tag.textContent = css$3;
|
|
20
|
+
document.head.appendChild(tag);
|
|
21
|
+
}
|
|
22
|
+
var chrome_module_css_default = { "triggerLabel": "UQsH_q_triggerLabel" };
|
|
23
|
+
//#endregion
|
|
24
|
+
//#region lib/types/client/chrome.js
|
|
25
|
+
/**
|
|
26
|
+
* Shell chrome content registered into the shell's trigger/header seats: the
|
|
27
|
+
* trigger row icon + label (figma sidebar foot) and the panel title text.
|
|
28
|
+
* The shell renders the surrounding chrome (button, nav heading row) and
|
|
29
|
+
* reads each entry's `label` option for aria text.
|
|
30
|
+
*/
|
|
31
|
+
/**
|
|
32
|
+
* Render the trigger row content (icon; label only in the wide column).
|
|
33
|
+
* @param props - composed slot props.
|
|
34
|
+
* @returns the trigger content fragment.
|
|
35
|
+
*/
|
|
36
|
+
function TriggerContent({ wide, t }) {
|
|
37
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [wide ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline16, { size: 16 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSettingsOutline14, { size: 18 }), wide && (0, react_jsx_runtime.jsx)("span", {
|
|
38
|
+
className: chrome_module_css_default.triggerLabel,
|
|
39
|
+
children: t("trigger")
|
|
40
|
+
})] });
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Render the panel title text.
|
|
44
|
+
* @param props - composed slot props.
|
|
45
|
+
* @returns the title text node.
|
|
46
|
+
*/
|
|
47
|
+
function HeaderContent({ t }) {
|
|
48
|
+
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t("title") });
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Render the close button's visually-hidden label text.
|
|
52
|
+
* @param props - composed slot props.
|
|
53
|
+
* @returns the label text node.
|
|
54
|
+
*/
|
|
55
|
+
function CloseLabel({ t }) {
|
|
56
|
+
return (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t("close") });
|
|
57
|
+
}
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-general/src/client/GeneralSection.module.css.mjs
|
|
60
|
+
const css$2 = "._WvWnq_section{flex-direction:column;width:100%;display:flex}._WvWnq_section>:last-child{border-bottom:none}";
|
|
61
|
+
const tagId$2 = "@deepseek-ai/dsh-client-ui-settings-general/GeneralSection.module.css";
|
|
62
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
63
|
+
const tag = document.createElement("style");
|
|
64
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-general";
|
|
65
|
+
tag.dataset.pluginCss = tagId$2;
|
|
66
|
+
tag.textContent = css$2;
|
|
67
|
+
document.head.appendChild(tag);
|
|
68
|
+
}
|
|
69
|
+
var GeneralSection_module_css_default = { "section": "_WvWnq_section" };
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region lib/types/client/GeneralSection.js
|
|
72
|
+
/**
|
|
73
|
+
* Render the General section content column.
|
|
74
|
+
* @param props - composed slot props (contract/slots.ts).
|
|
75
|
+
* @returns the section element tree.
|
|
76
|
+
*/
|
|
77
|
+
function GeneralSection({ renderSlot }) {
|
|
78
|
+
return (0, react_jsx_runtime.jsx)("div", {
|
|
79
|
+
className: GeneralSection_module_css_default.section,
|
|
80
|
+
children: renderSlot("settings.general.item", {})
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//#endregion
|
|
84
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-general/src/client/SettingsDocumentAction.module.css.mjs
|
|
85
|
+
const css$1 = ".me01iq_action{align-items:center;gap:8px;min-width:0;display:flex}.me01iq_error{max-width:180px;color:var(--dsw-alias-state-error-primary);text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}";
|
|
86
|
+
const tagId$1 = "@deepseek-ai/dsh-client-ui-settings-general/SettingsDocumentAction.module.css";
|
|
87
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
88
|
+
const tag = document.createElement("style");
|
|
89
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-general";
|
|
90
|
+
tag.dataset.pluginCss = tagId$1;
|
|
91
|
+
tag.textContent = css$1;
|
|
92
|
+
document.head.appendChild(tag);
|
|
93
|
+
}
|
|
94
|
+
var SettingsDocumentAction_module_css_default = {
|
|
95
|
+
"action": "me01iq_action",
|
|
96
|
+
"error": "me01iq_error"
|
|
97
|
+
};
|
|
98
|
+
//#endregion
|
|
99
|
+
//#region lib/types/client/SettingsDocumentAction.js
|
|
100
|
+
/** Optional settings-header action for opening a file-backed Host document. */
|
|
101
|
+
/**
|
|
102
|
+
* Render the open-document action only after Host metadata confirms document availability.
|
|
103
|
+
* @param props - header owner props, localized copy, and injected document state.
|
|
104
|
+
* @returns the action, or null while unavailable or unresolved.
|
|
105
|
+
*/
|
|
106
|
+
function SettingsDocumentAction({ controller, useSnapshot, t }) {
|
|
107
|
+
const state = useSnapshot((snapshot) => snapshot);
|
|
108
|
+
(0, react.useEffect)(() => {
|
|
109
|
+
controller.load();
|
|
110
|
+
}, [controller]);
|
|
111
|
+
if (state.status !== "ready") return null;
|
|
112
|
+
return (0, react_jsx_runtime.jsxs)("div", {
|
|
113
|
+
className: SettingsDocumentAction_module_css_default.action,
|
|
114
|
+
children: [state.error === null ? null : (0, react_jsx_runtime.jsx)("span", {
|
|
115
|
+
className: SettingsDocumentAction_module_css_default.error,
|
|
116
|
+
role: "alert",
|
|
117
|
+
children: t("openDocument.error")
|
|
118
|
+
}), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
119
|
+
variant: "outline",
|
|
120
|
+
size: "sm",
|
|
121
|
+
disabled: state.opening,
|
|
122
|
+
onClick: () => {
|
|
123
|
+
controller.open();
|
|
124
|
+
},
|
|
125
|
+
children: t("openDocument")
|
|
126
|
+
})]
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
//#endregion
|
|
130
|
+
//#region lib/types/client/settings-document-store.js
|
|
131
|
+
/** State owner for the optional local settings-document action. */
|
|
132
|
+
function messageOf$1(error) {
|
|
133
|
+
return error instanceof Error ? error.message : String(error);
|
|
134
|
+
}
|
|
135
|
+
/** Loads local-document availability and invokes the pathless Host-owned open operation. */
|
|
136
|
+
var SettingsDocumentStore = class {
|
|
137
|
+
api;
|
|
138
|
+
/** uSES-safe state source shared by the registered header action. */
|
|
139
|
+
store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
|
|
140
|
+
status: "idle",
|
|
141
|
+
opening: false,
|
|
142
|
+
error: null
|
|
143
|
+
});
|
|
144
|
+
generation = 0;
|
|
145
|
+
/**
|
|
146
|
+
* @param api - loopback settings wire face that reports and opens the provider document.
|
|
147
|
+
*/
|
|
148
|
+
constructor(api) {
|
|
149
|
+
this.api = api;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Load whether the current provider owns a local document.
|
|
153
|
+
* @returns after the latest metadata response updates the store.
|
|
154
|
+
*/
|
|
155
|
+
async load() {
|
|
156
|
+
const generation = ++this.generation;
|
|
157
|
+
this.store.update((state) => {
|
|
158
|
+
state.status = "loading";
|
|
159
|
+
state.error = null;
|
|
160
|
+
});
|
|
161
|
+
try {
|
|
162
|
+
const { result } = await this.api.settings.describe({});
|
|
163
|
+
if (generation !== this.generation) return;
|
|
164
|
+
if (!result.ok) {
|
|
165
|
+
this.store.update((state) => {
|
|
166
|
+
state.status = "unavailable";
|
|
167
|
+
state.error = result.error.message;
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
this.store.update((state) => {
|
|
172
|
+
state.status = result.value.hasDocument ? "ready" : "unavailable";
|
|
173
|
+
state.error = null;
|
|
174
|
+
});
|
|
175
|
+
} catch (error) {
|
|
176
|
+
if (generation !== this.generation) return;
|
|
177
|
+
this.store.update((state) => {
|
|
178
|
+
state.status = "unavailable";
|
|
179
|
+
state.error = messageOf$1(error);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Open the loaded document once; concurrent gestures collapse behind the in-flight action.
|
|
185
|
+
* @returns after the native-open request settles, or immediately when unavailable/already opening.
|
|
186
|
+
*/
|
|
187
|
+
async open() {
|
|
188
|
+
const current = this.store.getSnapshot();
|
|
189
|
+
if (current.status !== "ready" || current.opening) return;
|
|
190
|
+
this.store.update((state) => {
|
|
191
|
+
state.opening = true;
|
|
192
|
+
state.error = null;
|
|
193
|
+
});
|
|
194
|
+
try {
|
|
195
|
+
const response = await this.api.settings.openDocument({});
|
|
196
|
+
if (!response.result.ok) throw new Error(response.result.error.message);
|
|
197
|
+
} catch (error) {
|
|
198
|
+
this.store.update((state) => {
|
|
199
|
+
state.error = messageOf$1(error);
|
|
200
|
+
});
|
|
201
|
+
} finally {
|
|
202
|
+
this.store.update((state) => {
|
|
203
|
+
state.opening = false;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
/**
|
|
209
|
+
* Refresh document availability after reconnect only when a surface has already requested it.
|
|
210
|
+
* @param controller - optional loopback document state owner.
|
|
211
|
+
*/
|
|
212
|
+
function refreshDocumentIfLoaded(controller) {
|
|
213
|
+
if (controller === void 0 || controller.store.getSnapshot().status === "idle") return;
|
|
214
|
+
controller.load();
|
|
215
|
+
}
|
|
216
|
+
//#endregion
|
|
217
|
+
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-general/src/client/WelcomeNotice.module.css.mjs
|
|
218
|
+
const css = ".k2cPoG_page{z-index:1;box-sizing:border-box;width:min(640px,100vw - 64px);max-height:100vh;color:var(--dsw-alias-label-primary);--welcome-ease-out:cubic-bezier(.23, 1, .32, 1);padding:clamp(64px,9vh,104px) 0 40px;position:relative;overflow-y:auto}.k2cPoG_brand{color:var(--dsw-alias-label-primary);align-items:center;margin-bottom:42px;display:flex}.k2cPoG_title{letter-spacing:-.02em;outline:none;margin:0;font-size:28px;font-weight:600;line-height:36px}.k2cPoG_opening,.k2cPoG_reflection,.k2cPoG_feedback,.k2cPoG_error{margin:0}.k2cPoG_opening{margin-top:30px}.k2cPoG_reflection{margin-top:36px;padding:0}.k2cPoG_feedback{margin-top:30px}.k2cPoG_opening,.k2cPoG_reflection,.k2cPoG_feedback{color:var(--dsw-alias-label-secondary);font-size:16px;line-height:28px}.k2cPoG_feedback strong{color:inherit;font-weight:500}.k2cPoG_footer{justify-content:flex-end;margin-top:32px;display:flex}.k2cPoG_error{color:var(--dsw-alias-state-error-primary);margin-top:20px;font-size:14px;line-height:22px}.k2cPoG_primary{min-width:120px;transition:transform .14s var(--welcome-ease-out)}.k2cPoG_primary:active:not(:disabled){transform:scale(.97)}.k2cPoG_brand,.k2cPoG_title,.k2cPoG_opening,.k2cPoG_reflection,.k2cPoG_feedback,.k2cPoG_footer{animation:k2cPoG_welcome-enter .28s var(--welcome-ease-out) both}.k2cPoG_title{animation-delay:40ms}.k2cPoG_opening{animation-delay:80ms}.k2cPoG_reflection{animation-delay:.12s}.k2cPoG_feedback{animation-delay:.16s}.k2cPoG_footer{animation-delay:.2s}@keyframes k2cPoG_welcome-enter{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion:reduce){.k2cPoG_brand,.k2cPoG_title,.k2cPoG_opening,.k2cPoG_reflection,.k2cPoG_feedback,.k2cPoG_footer{animation:none}.k2cPoG_primary{transition:none}}@media (width<=560px){.k2cPoG_page{width:calc(100vw - 40px);padding-top:38px}.k2cPoG_brand{margin-bottom:30px}.k2cPoG_opening{margin-top:24px}.k2cPoG_reflection,.k2cPoG_feedback{margin-top:28px}.k2cPoG_footer{margin-top:30px}.k2cPoG_primary{width:100%}}";
|
|
219
|
+
const tagId = "@deepseek-ai/dsh-client-ui-settings-general/WelcomeNotice.module.css";
|
|
220
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
221
|
+
const tag = document.createElement("style");
|
|
222
|
+
tag.dataset.plugin = "@deepseek-ai/dsh-client-ui-settings-general";
|
|
223
|
+
tag.dataset.pluginCss = tagId;
|
|
224
|
+
tag.textContent = css;
|
|
225
|
+
document.head.appendChild(tag);
|
|
226
|
+
}
|
|
227
|
+
var WelcomeNotice_module_css_default = {
|
|
228
|
+
"page": "k2cPoG_page",
|
|
229
|
+
"error": "k2cPoG_error",
|
|
230
|
+
"title": "k2cPoG_title",
|
|
231
|
+
"footer": "k2cPoG_footer",
|
|
232
|
+
"brand": "k2cPoG_brand",
|
|
233
|
+
"welcome-enter": "k2cPoG_welcome-enter",
|
|
234
|
+
"feedback": "k2cPoG_feedback",
|
|
235
|
+
"primary": "k2cPoG_primary",
|
|
236
|
+
"reflection": "k2cPoG_reflection",
|
|
237
|
+
"opening": "k2cPoG_opening"
|
|
238
|
+
};
|
|
239
|
+
//#endregion
|
|
240
|
+
//#region lib/types/client/WelcomeNotice.js
|
|
241
|
+
/** Product-wide, versioned first-run welcome step. */
|
|
242
|
+
function emphasizedFeedback(paragraph, emphasis) {
|
|
243
|
+
const index = paragraph.indexOf(emphasis);
|
|
244
|
+
/* v8 ignore next -- both locale values derive from one owner object that contains the emphasis */
|
|
245
|
+
if (index < 0) return paragraph;
|
|
246
|
+
return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
247
|
+
paragraph.slice(0, index),
|
|
248
|
+
(0, react_jsx_runtime.jsx)("strong", { children: emphasis }),
|
|
249
|
+
paragraph.slice(index + emphasis.length)
|
|
250
|
+
] });
|
|
251
|
+
}
|
|
252
|
+
/** Render the mandatory notice until its current version is acknowledged. */
|
|
253
|
+
function WelcomeNotice(props) {
|
|
254
|
+
const { complete, controller, useSnapshot, t } = props;
|
|
255
|
+
const state = useSnapshot((snapshot) => snapshot);
|
|
256
|
+
const finished = (0, react.useRef)(false);
|
|
257
|
+
const titleRef = (0, react.useRef)(null);
|
|
258
|
+
const finish = (0, react.useCallback)(() => {
|
|
259
|
+
if (finished.current) return;
|
|
260
|
+
finished.current = true;
|
|
261
|
+
complete();
|
|
262
|
+
}, [complete]);
|
|
263
|
+
(0, react.useEffect)(() => {
|
|
264
|
+
if (state.status === "idle") controller.load();
|
|
265
|
+
}, [controller, state.status]);
|
|
266
|
+
(0, react.useEffect)(() => {
|
|
267
|
+
if (state.acknowledged) finish();
|
|
268
|
+
}, [finish, state.acknowledged]);
|
|
269
|
+
(0, react.useEffect)(() => {
|
|
270
|
+
if (state.status === "ready" && !state.acknowledged) titleRef.current?.focus();
|
|
271
|
+
}, [state.acknowledged, state.status]);
|
|
272
|
+
if (state.status === "idle" || state.status === "loading" || state.acknowledged) return null;
|
|
273
|
+
const acknowledge = async () => {
|
|
274
|
+
if (await controller.acknowledge()) finish();
|
|
275
|
+
};
|
|
276
|
+
return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.OnboardingSurface, { children: (0, react_jsx_runtime.jsxs)("section", {
|
|
277
|
+
className: WelcomeNotice_module_css_default.page,
|
|
278
|
+
role: "region",
|
|
279
|
+
"aria-labelledby": "welcome-notice-title",
|
|
280
|
+
children: [
|
|
281
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
282
|
+
className: WelcomeNotice_module_css_default.brand,
|
|
283
|
+
"aria-hidden": "true",
|
|
284
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.BrandWordmark, { size: 24 })
|
|
285
|
+
}),
|
|
286
|
+
(0, react_jsx_runtime.jsx)("h2", {
|
|
287
|
+
ref: titleRef,
|
|
288
|
+
id: "welcome-notice-title",
|
|
289
|
+
className: WelcomeNotice_module_css_default.title,
|
|
290
|
+
tabIndex: -1,
|
|
291
|
+
children: t("welcome.title")
|
|
292
|
+
}),
|
|
293
|
+
(0, react_jsx_runtime.jsx)("p", {
|
|
294
|
+
className: WelcomeNotice_module_css_default.opening,
|
|
295
|
+
children: t("welcome.paragraph.0")
|
|
296
|
+
}),
|
|
297
|
+
(0, react_jsx_runtime.jsx)("blockquote", {
|
|
298
|
+
className: WelcomeNotice_module_css_default.reflection,
|
|
299
|
+
children: t("welcome.paragraph.1")
|
|
300
|
+
}),
|
|
301
|
+
(0, react_jsx_runtime.jsx)("p", {
|
|
302
|
+
className: WelcomeNotice_module_css_default.feedback,
|
|
303
|
+
children: emphasizedFeedback(t("welcome.paragraph.2"), t("welcome.feedbackEmphasis"))
|
|
304
|
+
}),
|
|
305
|
+
state.error === null ? null : (0, react_jsx_runtime.jsx)("p", {
|
|
306
|
+
className: WelcomeNotice_module_css_default.error,
|
|
307
|
+
role: "alert",
|
|
308
|
+
children: t("welcome.error")
|
|
309
|
+
}),
|
|
310
|
+
(0, react_jsx_runtime.jsx)("div", {
|
|
311
|
+
className: WelcomeNotice_module_css_default.footer,
|
|
312
|
+
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
313
|
+
variant: "primary",
|
|
314
|
+
className: WelcomeNotice_module_css_default.primary,
|
|
315
|
+
disabled: state.status === "saving",
|
|
316
|
+
onClick: () => {
|
|
317
|
+
acknowledge();
|
|
318
|
+
},
|
|
319
|
+
children: t("welcome.continue")
|
|
320
|
+
})
|
|
321
|
+
})
|
|
322
|
+
]
|
|
323
|
+
}) });
|
|
324
|
+
}
|
|
325
|
+
//#endregion
|
|
326
|
+
//#region lib/types/onboarding-copy.js
|
|
327
|
+
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
328
|
+
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-onboarding";
|
|
329
|
+
/** Field storing the last welcome notice version the user acknowledged. */
|
|
330
|
+
const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
331
|
+
/**
|
|
332
|
+
* Bump only when the notice changes materially and every user should see it
|
|
333
|
+
* again. The acknowledgement is compared for exact equality.
|
|
334
|
+
*/
|
|
335
|
+
const WELCOME_NOTICE_VERSION = "2026-07-30.7";
|
|
336
|
+
/** The complete editable welcome notice in both supported GUI locales. */
|
|
337
|
+
const WELCOME_NOTICE_COPY = {
|
|
338
|
+
zh: {
|
|
339
|
+
title: "内测声明",
|
|
340
|
+
paragraphs: [
|
|
341
|
+
"感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。",
|
|
342
|
+
"“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。",
|
|
343
|
+
"为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"
|
|
344
|
+
],
|
|
345
|
+
feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们",
|
|
346
|
+
continueLabel: "继续"
|
|
347
|
+
},
|
|
348
|
+
en: {
|
|
349
|
+
title: "内测声明",
|
|
350
|
+
paragraphs: [
|
|
351
|
+
"感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。",
|
|
352
|
+
"“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。",
|
|
353
|
+
"为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"
|
|
354
|
+
],
|
|
355
|
+
feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们",
|
|
356
|
+
continueLabel: "继续"
|
|
357
|
+
}
|
|
358
|
+
};
|
|
359
|
+
//#endregion
|
|
360
|
+
//#region lib/types/client/welcome-store.js
|
|
361
|
+
/** Welcome-notice state, durable when the browser may use Host settings. */
|
|
362
|
+
function messageOf(error) {
|
|
363
|
+
return error instanceof Error ? error.message : String(error);
|
|
364
|
+
}
|
|
365
|
+
function acknowledgementOf(view) {
|
|
366
|
+
if (typeof view.value !== "object" || view.value === null) return void 0;
|
|
367
|
+
const value = view.value[WELCOME_NOTICE_ACK_FIELD];
|
|
368
|
+
return typeof value === "string" ? value : void 0;
|
|
369
|
+
}
|
|
370
|
+
/** Coordinates durable Host acknowledgement or a process-local remote fallback. */
|
|
371
|
+
var WelcomeNoticeStore = class {
|
|
372
|
+
api;
|
|
373
|
+
persistence;
|
|
374
|
+
/** uSES-safe state source shared by the registered welcome step. */
|
|
375
|
+
store = (0, _deepseek_ai_dsh_client_runtime_client.createSnapshotStore)({
|
|
376
|
+
status: "idle",
|
|
377
|
+
acknowledged: false,
|
|
378
|
+
error: null
|
|
379
|
+
});
|
|
380
|
+
generation = 0;
|
|
381
|
+
/**
|
|
382
|
+
* @param api - settings wire face used for durable reads and writes.
|
|
383
|
+
* @param persistence - remote browsers use memory because settings is loopback-only.
|
|
384
|
+
*/
|
|
385
|
+
constructor(api, persistence = "host") {
|
|
386
|
+
this.api = api;
|
|
387
|
+
this.persistence = persistence;
|
|
388
|
+
}
|
|
389
|
+
/** Load the acknowledgement from Host settings or initialize process-local state. */
|
|
390
|
+
async load() {
|
|
391
|
+
const generation = ++this.generation;
|
|
392
|
+
if (this.persistence === "memory") {
|
|
393
|
+
this.store.update((state) => {
|
|
394
|
+
state.status = "ready";
|
|
395
|
+
state.error = null;
|
|
396
|
+
});
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
this.store.update((state) => {
|
|
400
|
+
state.status = "loading";
|
|
401
|
+
state.error = null;
|
|
402
|
+
});
|
|
403
|
+
try {
|
|
404
|
+
const response = await this.api.settings.describe({});
|
|
405
|
+
if (!response.result.ok) throw new Error(response.result.error.message);
|
|
406
|
+
const view = response.result.value.namespaces.find((candidate) => candidate.ns === WELCOME_NOTICE_SETTINGS_NAMESPACE);
|
|
407
|
+
if (view === void 0) throw new Error("welcome acknowledgement settings are unavailable");
|
|
408
|
+
if (generation !== this.generation) return;
|
|
409
|
+
this.store.update((state) => {
|
|
410
|
+
state.status = "ready";
|
|
411
|
+
state.acknowledged = acknowledgementOf(view) === WELCOME_NOTICE_VERSION;
|
|
412
|
+
state.error = null;
|
|
413
|
+
});
|
|
414
|
+
} catch (error) {
|
|
415
|
+
if (generation !== this.generation) return;
|
|
416
|
+
this.store.update((state) => {
|
|
417
|
+
state.status = "error";
|
|
418
|
+
state.acknowledged = false;
|
|
419
|
+
state.error = messageOf(error);
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
424
|
+
* Acknowledge this copy version. The Host path mutation is idempotent across
|
|
425
|
+
* tabs and preserves sibling settings; remote fallback changes only this store.
|
|
426
|
+
* @returns true when the selected persistence mode accepted the acknowledgement.
|
|
427
|
+
*/
|
|
428
|
+
async acknowledge() {
|
|
429
|
+
const generation = ++this.generation;
|
|
430
|
+
if (this.persistence === "memory") {
|
|
431
|
+
this.store.update((state) => {
|
|
432
|
+
state.status = "ready";
|
|
433
|
+
state.acknowledged = true;
|
|
434
|
+
state.error = null;
|
|
435
|
+
});
|
|
436
|
+
return true;
|
|
437
|
+
}
|
|
438
|
+
this.store.update((state) => {
|
|
439
|
+
state.status = "saving";
|
|
440
|
+
state.error = null;
|
|
441
|
+
});
|
|
442
|
+
try {
|
|
443
|
+
const response = await this.api.settings.mutate({
|
|
444
|
+
ns: WELCOME_NOTICE_SETTINGS_NAMESPACE,
|
|
445
|
+
ops: [{
|
|
446
|
+
op: "set",
|
|
447
|
+
path: [WELCOME_NOTICE_ACK_FIELD],
|
|
448
|
+
value: WELCOME_NOTICE_VERSION
|
|
449
|
+
}]
|
|
450
|
+
});
|
|
451
|
+
if (!response.result.ok) throw new Error(response.result.error.message);
|
|
452
|
+
if (generation === this.generation) this.store.update((state) => {
|
|
453
|
+
state.status = "ready";
|
|
454
|
+
state.acknowledged = true;
|
|
455
|
+
state.error = null;
|
|
456
|
+
});
|
|
457
|
+
return true;
|
|
458
|
+
} catch (error) {
|
|
459
|
+
if (generation === this.generation) this.store.update((state) => {
|
|
460
|
+
state.status = "error";
|
|
461
|
+
state.acknowledged = false;
|
|
462
|
+
state.error = messageOf(error);
|
|
463
|
+
});
|
|
464
|
+
return false;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
/**
|
|
469
|
+
* Refresh only after welcome state has left idle. A memory-mode load retains
|
|
470
|
+
* acknowledgement so reconnect and settings-change refreshes do not reopen a
|
|
471
|
+
* process-local notice.
|
|
472
|
+
* @param controller - welcome state owner whose current status decides whether to load.
|
|
473
|
+
*/
|
|
474
|
+
function refreshWelcomeIfLoaded(controller) {
|
|
475
|
+
if (controller.store.getSnapshot().status === "idle") return;
|
|
476
|
+
controller.load();
|
|
477
|
+
}
|
|
478
|
+
//#endregion
|
|
479
|
+
//#region lib/types/client/locales.js
|
|
480
|
+
/** Shell chrome, General-nav, and welcome-notice dictionaries; feature rows own their copy. */
|
|
481
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
482
|
+
const zh = {
|
|
483
|
+
"trigger": "设置",
|
|
484
|
+
"title": "设置",
|
|
485
|
+
"close": "关闭",
|
|
486
|
+
"openDocument": "打开配置文件",
|
|
487
|
+
"openDocument.error": "无法打开配置文件",
|
|
488
|
+
"general.nav": "通用设置",
|
|
489
|
+
"welcome.title": WELCOME_NOTICE_COPY.zh.title,
|
|
490
|
+
"welcome.paragraph.0": WELCOME_NOTICE_COPY.zh.paragraphs[0],
|
|
491
|
+
"welcome.paragraph.1": WELCOME_NOTICE_COPY.zh.paragraphs[1],
|
|
492
|
+
"welcome.paragraph.2": WELCOME_NOTICE_COPY.zh.paragraphs[2],
|
|
493
|
+
"welcome.feedbackEmphasis": WELCOME_NOTICE_COPY.zh.feedbackEmphasis,
|
|
494
|
+
"welcome.continue": WELCOME_NOTICE_COPY.zh.continueLabel,
|
|
495
|
+
"welcome.error": "暂时无法保存确认状态,请重试。"
|
|
496
|
+
};
|
|
497
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
498
|
+
const en = {
|
|
499
|
+
"trigger": "Settings",
|
|
500
|
+
"title": "Settings",
|
|
501
|
+
"close": "Close",
|
|
502
|
+
"openDocument": "Open configuration file",
|
|
503
|
+
"openDocument.error": "Could not open configuration file",
|
|
504
|
+
"general.nav": "General",
|
|
505
|
+
"welcome.title": WELCOME_NOTICE_COPY.en.title,
|
|
506
|
+
"welcome.paragraph.0": WELCOME_NOTICE_COPY.en.paragraphs[0],
|
|
507
|
+
"welcome.paragraph.1": WELCOME_NOTICE_COPY.en.paragraphs[1],
|
|
508
|
+
"welcome.paragraph.2": WELCOME_NOTICE_COPY.en.paragraphs[2],
|
|
509
|
+
"welcome.feedbackEmphasis": WELCOME_NOTICE_COPY.en.feedbackEmphasis,
|
|
510
|
+
"welcome.continue": WELCOME_NOTICE_COPY.en.continueLabel,
|
|
511
|
+
"welcome.error": "The acknowledgement could not be saved. Please try again."
|
|
512
|
+
};
|
|
513
|
+
//#endregion
|
|
514
|
+
//#region lib/types/client/index.js
|
|
515
|
+
/** Dictionary namespace owned by this plugin (shell chrome + General copy). */
|
|
516
|
+
const NS = "settings";
|
|
517
|
+
/**
|
|
518
|
+
* Required services (cordis fiber inject). The target slots are declared by
|
|
519
|
+
* ui-settings' apply, whose activation order relative to this one is NOT
|
|
520
|
+
* constrained; registrations depend on their slots through `slots.inject()`.
|
|
521
|
+
*/
|
|
522
|
+
const inject = [
|
|
523
|
+
"slots",
|
|
524
|
+
"locale",
|
|
525
|
+
"connection"
|
|
526
|
+
];
|
|
527
|
+
/**
|
|
528
|
+
* Register the `settings` dictionaries, the chrome content, and the General
|
|
529
|
+
* section, each once its slot declaration is on the ledger.
|
|
530
|
+
* @param ctx - client root context.
|
|
531
|
+
*/
|
|
532
|
+
function apply(ctx) {
|
|
533
|
+
ctx.effect(() => ctx.locale.register(NS, {
|
|
534
|
+
zh,
|
|
535
|
+
en
|
|
536
|
+
}), "ui-settings-general: dictionaries");
|
|
537
|
+
const t = ctx.locale.bind(NS);
|
|
538
|
+
const connection = ctx.get("connection");
|
|
539
|
+
const documentController = connection.isLoopback ? new SettingsDocumentStore(connection.api) : void 0;
|
|
540
|
+
const documentInjected = documentController === void 0 ? void 0 : (() => {
|
|
541
|
+
const useSnapshot = (0, _deepseek_ai_dsh_client_web_react.bindSnapshotSelector)(documentController.store);
|
|
542
|
+
return () => ({
|
|
543
|
+
controller: documentController,
|
|
544
|
+
useSnapshot
|
|
545
|
+
});
|
|
546
|
+
})();
|
|
547
|
+
const welcomeController = new WelcomeNoticeStore(connection.api, connection.isLoopback ? "host" : "memory");
|
|
548
|
+
const useWelcomeSnapshot = (0, _deepseek_ai_dsh_client_web_react.bindSnapshotSelector)(welcomeController.store);
|
|
549
|
+
const welcomeInjected = () => ({
|
|
550
|
+
controller: welcomeController,
|
|
551
|
+
useSnapshot: useWelcomeSnapshot
|
|
552
|
+
});
|
|
553
|
+
ctx.effect(() => {
|
|
554
|
+
const refresh = (ns) => {
|
|
555
|
+
if (ns !== void 0 && ns !== "ui-onboarding") return;
|
|
556
|
+
refreshWelcomeIfLoaded(welcomeController);
|
|
557
|
+
};
|
|
558
|
+
const disposers = [ctx.on("settings/changed", refresh), ctx.on("connection/reset", () => {
|
|
559
|
+
refresh();
|
|
560
|
+
refreshDocumentIfLoaded(documentController);
|
|
561
|
+
})];
|
|
562
|
+
return () => {
|
|
563
|
+
for (const dispose of disposers) dispose();
|
|
564
|
+
};
|
|
565
|
+
}, "ui-settings-general: metadata invalidations");
|
|
566
|
+
ctx.slots.inject("settings.trigger", () => ctx.slots.register({
|
|
567
|
+
name: "settings.trigger",
|
|
568
|
+
locale: NS
|
|
569
|
+
}, TriggerContent));
|
|
570
|
+
ctx.slots.inject("settings.header", () => ctx.slots.register({
|
|
571
|
+
name: "settings.header",
|
|
572
|
+
locale: NS
|
|
573
|
+
}, HeaderContent));
|
|
574
|
+
if (documentInjected !== void 0) ctx.slots.inject("settings.action", () => ctx.slots.register({
|
|
575
|
+
name: "settings.action",
|
|
576
|
+
id: "open-document",
|
|
577
|
+
order: 0,
|
|
578
|
+
locale: NS,
|
|
579
|
+
inject: documentInjected
|
|
580
|
+
}, SettingsDocumentAction));
|
|
581
|
+
ctx.slots.inject("settings.close", () => ctx.slots.register({
|
|
582
|
+
name: "settings.close",
|
|
583
|
+
locale: NS
|
|
584
|
+
}, CloseLabel));
|
|
585
|
+
ctx.slots.inject("settings.section", () => ctx.slots.register({
|
|
586
|
+
name: "settings.section",
|
|
587
|
+
id: "general",
|
|
588
|
+
order: 0,
|
|
589
|
+
label: () => t("general.nav"),
|
|
590
|
+
locale: NS,
|
|
591
|
+
children: { "settings.general.item": {
|
|
592
|
+
kind: "list",
|
|
593
|
+
scope: "root"
|
|
594
|
+
} }
|
|
595
|
+
}, GeneralSection));
|
|
596
|
+
ctx.slots.inject("settings.onboarding", () => ctx.slots.register({
|
|
597
|
+
name: "settings.onboarding",
|
|
598
|
+
id: "welcome-notice",
|
|
599
|
+
order: -100,
|
|
600
|
+
locale: NS,
|
|
601
|
+
inject: welcomeInjected
|
|
602
|
+
}, WelcomeNotice));
|
|
603
|
+
}
|
|
604
|
+
//#endregion
|
|
605
|
+
exports.SettingsDocumentStore = SettingsDocumentStore;
|
|
606
|
+
exports.apply = apply;
|
|
607
|
+
exports.inject = inject;
|
|
608
|
+
return module.exports;
|
|
609
|
+
}
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
//# sourceMappingURL=client.js.map
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import z from "@deepseek-ai/schemastery";
|
|
2
|
+
import { settingsNamespace } from "@deepseek-ai/dsh-settings";
|
|
3
|
+
//#region lib/types/onboarding-copy.js
|
|
4
|
+
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
5
|
+
const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-onboarding";
|
|
6
|
+
/** Field storing the last welcome notice version the user acknowledged. */
|
|
7
|
+
const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
8
|
+
/**
|
|
9
|
+
* Bump only when the notice changes materially and every user should see it
|
|
10
|
+
* again. The acknowledgement is compared for exact equality.
|
|
11
|
+
*/
|
|
12
|
+
const WELCOME_NOTICE_VERSION = "2026-07-30.7";
|
|
13
|
+
/** The complete editable welcome notice in both supported GUI locales. */
|
|
14
|
+
const WELCOME_NOTICE_COPY = {
|
|
15
|
+
zh: {
|
|
16
|
+
title: "内测声明",
|
|
17
|
+
paragraphs: [
|
|
18
|
+
"感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。",
|
|
19
|
+
"“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。",
|
|
20
|
+
"为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"
|
|
21
|
+
],
|
|
22
|
+
feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们",
|
|
23
|
+
continueLabel: "继续"
|
|
24
|
+
},
|
|
25
|
+
en: {
|
|
26
|
+
title: "内测声明",
|
|
27
|
+
paragraphs: [
|
|
28
|
+
"感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。",
|
|
29
|
+
"“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。",
|
|
30
|
+
"为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"
|
|
31
|
+
],
|
|
32
|
+
feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们",
|
|
33
|
+
continueLabel: "继续"
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region lib/types/index.js
|
|
38
|
+
/** Host loader entry for the browser implementation exported from `./client`. */
|
|
39
|
+
const OnboardingSettingsSchema = z.object({ [WELCOME_NOTICE_ACK_FIELD]: z.string() });
|
|
40
|
+
/** Register the durable GUI-onboarding section when a settings provider exists. */
|
|
41
|
+
function apply(ctx) {
|
|
42
|
+
ctx.inject(["settings"], (settingsCtx) => {
|
|
43
|
+
settingsCtx.settings.register(settingsNamespace(WELCOME_NOTICE_SETTINGS_NAMESPACE), OnboardingSettingsSchema);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_COPY, WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_VERSION, apply };
|
package/lib/invariant.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//#region lib/types/invariant.js
|
|
2
|
+
/**
|
|
3
|
+
* Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-settings-general`.
|
|
4
|
+
* @module @deepseek-ai/dsh-client-ui-settings-general/invariant
|
|
5
|
+
*/
|
|
6
|
+
const PACKAGE_NAME = "@deepseek-ai/dsh-client-ui-settings-general";
|
|
7
|
+
/** Cordis companion plugin name. */
|
|
8
|
+
const name = "client-ui-settings-general-invariant";
|
|
9
|
+
/** Service required before the companion can reserve package ownership. */
|
|
10
|
+
const inject = ["invariants"];
|
|
11
|
+
/**
|
|
12
|
+
* No runtime invariant: the settings seam validates and publishes the durable
|
|
13
|
+
* welcome section, while slot conflicts fail loud in the slot core. The local
|
|
14
|
+
* document action is browser state over typed RPC responses and is covered by
|
|
15
|
+
* store/component tests rather than a Cordis runtime relationship.
|
|
16
|
+
*/
|
|
17
|
+
const install = () => {};
|
|
18
|
+
/**
|
|
19
|
+
* Register this package's invariant companion.
|
|
20
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
21
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
22
|
+
*/
|
|
23
|
+
const apply = (ctx) => Promise.resolve(ctx.invariants.register(PACKAGE_NAME, install));
|
|
24
|
+
//#endregion
|
|
25
|
+
export { apply, inject, name };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The General section: one column rendering feature-owned item contributions. */
|
|
2
|
+
import type { PropsRenderSlots, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
/** Full component props: section owner share plus item render share. */
|
|
4
|
+
export type GeneralSectionComponentProps = PropsRuntime<'settings.section'> & PropsRenderSlots<'settings.general.item'>;
|
|
5
|
+
/**
|
|
6
|
+
* Render the General section content column.
|
|
7
|
+
* @param props - composed slot props (contract/slots.ts).
|
|
8
|
+
* @returns the section element tree.
|
|
9
|
+
*/
|
|
10
|
+
export declare function GeneralSection({ renderSlot }: GeneralSectionComponentProps): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=GeneralSection.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Optional settings-header action for opening a file-backed Host document. */
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
|
+
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-web-react';
|
|
5
|
+
import type { SettingsDocumentState, SettingsDocumentStore } from './settings-document-store.ts';
|
|
6
|
+
/** Registrant-owned dependencies of {@link SettingsDocumentAction}. */
|
|
7
|
+
export interface SettingsDocumentActionInjected {
|
|
8
|
+
/** Provider metadata and action state owner. */
|
|
9
|
+
controller: SettingsDocumentStore;
|
|
10
|
+
/** Bound selector hook for the controller snapshot. */
|
|
11
|
+
useSnapshot: SnapshotSelectorHook<SettingsDocumentState>;
|
|
12
|
+
}
|
|
13
|
+
/** Header-action owner share, localized copy, and the registrant's state face. */
|
|
14
|
+
export type SettingsDocumentActionProps = PropsRuntime<'settings.action'> & PropsLocale<'settings'> & SettingsDocumentActionInjected;
|
|
15
|
+
/**
|
|
16
|
+
* Render the open-document action only after Host metadata confirms document availability.
|
|
17
|
+
* @param props - header owner props, localized copy, and injected document state.
|
|
18
|
+
* @returns the action, or null while unavailable or unresolved.
|
|
19
|
+
*/
|
|
20
|
+
export declare function SettingsDocumentAction({ controller, useSnapshot, t }: SettingsDocumentActionProps): ReactNode;
|
|
21
|
+
//# sourceMappingURL=SettingsDocumentAction.d.ts.map
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Product-wide, versioned first-run welcome step. */
|
|
2
|
+
import type { ReactNode } from 'react';
|
|
3
|
+
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
4
|
+
import type { SnapshotSelectorHook } from '@deepseek-ai/dsh-client-web-react';
|
|
5
|
+
import type { WelcomeNoticeState, WelcomeNoticeStore } from './welcome-store.ts';
|
|
6
|
+
/** Registrant-owned dependencies of {@link WelcomeNotice}. */
|
|
7
|
+
export interface WelcomeNoticeInjected {
|
|
8
|
+
controller: WelcomeNoticeStore;
|
|
9
|
+
useSnapshot: SnapshotSelectorHook<WelcomeNoticeState>;
|
|
10
|
+
}
|
|
11
|
+
/** Coordinator owner props plus the welcome step's injected face. */
|
|
12
|
+
export type WelcomeNoticeProps = PropsRuntime<'settings.onboarding'> & PropsLocale<'settings'> & WelcomeNoticeInjected;
|
|
13
|
+
/** Render the mandatory notice until its current version is acknowledged. */
|
|
14
|
+
export declare function WelcomeNotice(props: WelcomeNoticeProps): ReactNode;
|
|
15
|
+
//# sourceMappingURL=WelcomeNotice.d.ts.map
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
/** Trigger content props: the sidebar column state + the standard locale seat. */
|
|
3
|
+
export type TriggerContentProps = PropsRuntime<'settings.trigger'> & PropsLocale<'settings'>;
|
|
4
|
+
/** Header content props: the standard locale seat only. */
|
|
5
|
+
export type HeaderContentProps = PropsRuntime<'settings.header'> & PropsLocale<'settings'>;
|
|
6
|
+
/**
|
|
7
|
+
* Render the trigger row content (icon; label only in the wide column).
|
|
8
|
+
* @param props - composed slot props.
|
|
9
|
+
* @returns the trigger content fragment.
|
|
10
|
+
*/
|
|
11
|
+
export declare function TriggerContent({ wide, t }: TriggerContentProps): import("react").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Render the panel title text.
|
|
14
|
+
* @param props - composed slot props.
|
|
15
|
+
* @returns the title text node.
|
|
16
|
+
*/
|
|
17
|
+
export declare function HeaderContent({ t }: HeaderContentProps): import("react").JSX.Element;
|
|
18
|
+
/** Close-button label text props: the standard locale seat only. */
|
|
19
|
+
export type CloseLabelProps = PropsRuntime<'settings.close'> & PropsLocale<'settings'>;
|
|
20
|
+
/**
|
|
21
|
+
* Render the close button's visually-hidden label text.
|
|
22
|
+
* @param props - composed slot props.
|
|
23
|
+
* @returns the label text node.
|
|
24
|
+
*/
|
|
25
|
+
export declare function CloseLabel({ t }: CloseLabelProps): import("react").JSX.Element;
|
|
26
|
+
//# sourceMappingURL=chrome.d.ts.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings ownerless-copy plugin, browser half: registers everything on the
|
|
3
|
+
* Settings surface that belongs to no single feature — the trigger/header
|
|
4
|
+
* chrome content, local-document action, General section, and `settings`
|
|
5
|
+
* dictionaries. Feature-owned rows and sections stay with their features.
|
|
6
|
+
* Export discipline: packages/client/AGENTS.md.
|
|
7
|
+
*/
|
|
8
|
+
import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
|
|
9
|
+
import { type SettingsKey } from './locales.ts';
|
|
10
|
+
export type { CloseLabelProps, HeaderContentProps, TriggerContentProps, } from './chrome.tsx';
|
|
11
|
+
export type { GeneralSectionComponentProps, } from './GeneralSection.tsx';
|
|
12
|
+
export type { SettingsDocumentActionInjected, SettingsDocumentActionProps } from './SettingsDocumentAction.tsx';
|
|
13
|
+
export type { SettingsDocumentState } from './settings-document-store.ts';
|
|
14
|
+
export { SettingsDocumentStore } from './settings-document-store.ts';
|
|
15
|
+
export type { WelcomeNoticeInjected, WelcomeNoticeProps } from './WelcomeNotice.tsx';
|
|
16
|
+
export type { WelcomeNoticeState } from './welcome-store.ts';
|
|
17
|
+
export type { SettingsKey } from './locales.ts';
|
|
18
|
+
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
19
|
+
interface LocaleNamespaceMap {
|
|
20
|
+
/** Shell chrome + shell-owned General section copy. */
|
|
21
|
+
settings: SettingsKey;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Required services (cordis fiber inject). The target slots are declared by
|
|
26
|
+
* ui-settings' apply, whose activation order relative to this one is NOT
|
|
27
|
+
* constrained; registrations depend on their slots through `slots.inject()`.
|
|
28
|
+
*/
|
|
29
|
+
export declare const inject: string[];
|
|
30
|
+
/**
|
|
31
|
+
* Register the `settings` dictionaries, the chrome content, and the General
|
|
32
|
+
* section, each once its slot declaration is on the ledger.
|
|
33
|
+
* @param ctx - client root context.
|
|
34
|
+
*/
|
|
35
|
+
export declare function apply(ctx: ClientContext): void;
|
|
36
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** Simplified Chinese dictionary (the key-set source of truth). */
|
|
2
|
+
export declare const zh: {
|
|
3
|
+
trigger: string;
|
|
4
|
+
title: string;
|
|
5
|
+
close: string;
|
|
6
|
+
openDocument: string;
|
|
7
|
+
'openDocument.error': string;
|
|
8
|
+
'general.nav': string;
|
|
9
|
+
'welcome.title': "内测声明";
|
|
10
|
+
'welcome.paragraph.0': "感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。";
|
|
11
|
+
'welcome.paragraph.1': "“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。";
|
|
12
|
+
'welcome.paragraph.2': "为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。";
|
|
13
|
+
'welcome.feedbackEmphasis': "如果您有任何反馈与建议,请在企业微信群中留言告诉我们";
|
|
14
|
+
'welcome.continue': "继续";
|
|
15
|
+
'welcome.error': string;
|
|
16
|
+
};
|
|
17
|
+
/** The settings namespace key union. */
|
|
18
|
+
export type SettingsKey = keyof typeof zh;
|
|
19
|
+
/** English dictionary, checked complete against the zh key set. */
|
|
20
|
+
export declare const en: {
|
|
21
|
+
trigger: string;
|
|
22
|
+
title: string;
|
|
23
|
+
close: string;
|
|
24
|
+
openDocument: string;
|
|
25
|
+
'openDocument.error': string;
|
|
26
|
+
'general.nav': string;
|
|
27
|
+
'welcome.title': "内测声明";
|
|
28
|
+
'welcome.paragraph.0': "感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。";
|
|
29
|
+
'welcome.paragraph.1': "“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。";
|
|
30
|
+
'welcome.paragraph.2': "为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。";
|
|
31
|
+
'welcome.feedbackEmphasis': "如果您有任何反馈与建议,请在企业微信群中留言告诉我们";
|
|
32
|
+
'welcome.continue': "继续";
|
|
33
|
+
'welcome.error': string;
|
|
34
|
+
};
|
|
35
|
+
//# sourceMappingURL=locales.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** State owner for the optional local settings-document action. */
|
|
2
|
+
import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client';
|
|
3
|
+
import { type SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
|
+
/** Browser state of the Host-owned settings document. */
|
|
5
|
+
export interface SettingsDocumentState {
|
|
6
|
+
/** Metadata-loading phase; unavailable means the provider has no local document or the read failed. */
|
|
7
|
+
status: 'idle' | 'loading' | 'ready' | 'unavailable';
|
|
8
|
+
/** Whether one native-open request is in flight. */
|
|
9
|
+
opening: boolean;
|
|
10
|
+
/** Last metadata/native-open diagnostic; UI exposes only localized copy. */
|
|
11
|
+
error: string | null;
|
|
12
|
+
}
|
|
13
|
+
/** Loads local-document availability and invokes the pathless Host-owned open operation. */
|
|
14
|
+
export declare class SettingsDocumentStore {
|
|
15
|
+
private readonly api;
|
|
16
|
+
/** uSES-safe state source shared by the registered header action. */
|
|
17
|
+
readonly store: SnapshotStore<SettingsDocumentState>;
|
|
18
|
+
private generation;
|
|
19
|
+
/**
|
|
20
|
+
* @param api - loopback settings wire face that reports and opens the provider document.
|
|
21
|
+
*/
|
|
22
|
+
constructor(api: Pick<IApiClient, 'settings'>);
|
|
23
|
+
/**
|
|
24
|
+
* Load whether the current provider owns a local document.
|
|
25
|
+
* @returns after the latest metadata response updates the store.
|
|
26
|
+
*/
|
|
27
|
+
load(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Open the loaded document once; concurrent gestures collapse behind the in-flight action.
|
|
30
|
+
* @returns after the native-open request settles, or immediately when unavailable/already opening.
|
|
31
|
+
*/
|
|
32
|
+
open(): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Refresh document availability after reconnect only when a surface has already requested it.
|
|
36
|
+
* @param controller - optional loopback document state owner.
|
|
37
|
+
*/
|
|
38
|
+
export declare function refreshDocumentIfLoaded(controller: SettingsDocumentStore | undefined): void;
|
|
39
|
+
//# sourceMappingURL=settings-document-store.d.ts.map
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** Welcome-notice state, durable when the browser may use Host settings. */
|
|
2
|
+
import type { IApiClient } from '@deepseek-ai/dsh-client-connection/client';
|
|
3
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
4
|
+
/** State rendered by the welcome step. */
|
|
5
|
+
export interface WelcomeNoticeState {
|
|
6
|
+
status: 'idle' | 'loading' | 'ready' | 'saving' | 'error';
|
|
7
|
+
acknowledged: boolean;
|
|
8
|
+
error: string | null;
|
|
9
|
+
}
|
|
10
|
+
/** Coordinates durable Host acknowledgement or a process-local remote fallback. */
|
|
11
|
+
export declare class WelcomeNoticeStore {
|
|
12
|
+
private readonly api;
|
|
13
|
+
private readonly persistence;
|
|
14
|
+
/** uSES-safe state source shared by the registered welcome step. */
|
|
15
|
+
readonly store: SnapshotStore<WelcomeNoticeState>;
|
|
16
|
+
private generation;
|
|
17
|
+
/**
|
|
18
|
+
* @param api - settings wire face used for durable reads and writes.
|
|
19
|
+
* @param persistence - remote browsers use memory because settings is loopback-only.
|
|
20
|
+
*/
|
|
21
|
+
constructor(api: Pick<IApiClient, 'settings'>, persistence?: 'host' | 'memory');
|
|
22
|
+
/** Load the acknowledgement from Host settings or initialize process-local state. */
|
|
23
|
+
load(): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Acknowledge this copy version. The Host path mutation is idempotent across
|
|
26
|
+
* tabs and preserves sibling settings; remote fallback changes only this store.
|
|
27
|
+
* @returns true when the selected persistence mode accepted the acknowledgement.
|
|
28
|
+
*/
|
|
29
|
+
acknowledge(): Promise<boolean>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Refresh only after welcome state has left idle. A memory-mode load retains
|
|
33
|
+
* acknowledgement so reconnect and settings-change refreshes do not reopen a
|
|
34
|
+
* process-local notice.
|
|
35
|
+
* @param controller - welcome state owner whose current status decides whether to load.
|
|
36
|
+
*/
|
|
37
|
+
export declare function refreshWelcomeIfLoaded(controller: WelcomeNoticeStore): void;
|
|
38
|
+
//# sourceMappingURL=welcome-store.d.ts.map
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Host loader entry for the browser implementation exported from `./client`. */
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
export { WELCOME_NOTICE_ACK_FIELD, WELCOME_NOTICE_COPY, WELCOME_NOTICE_SETTINGS_NAMESPACE, WELCOME_NOTICE_VERSION, } from './onboarding-copy.ts';
|
|
4
|
+
/** Register the durable GUI-onboarding section when a settings provider exists. */
|
|
5
|
+
export declare function apply(ctx: Context): void;
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package-owned invariant companion for `@deepseek-ai/dsh-client-ui-settings-general`.
|
|
3
|
+
* @module @deepseek-ai/dsh-client-ui-settings-general/invariant
|
|
4
|
+
*/
|
|
5
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
6
|
+
/** Cordis companion plugin name. */
|
|
7
|
+
export declare const name = "client-ui-settings-general-invariant";
|
|
8
|
+
/** Service required before the companion can reserve package ownership. */
|
|
9
|
+
export declare const inject: string[];
|
|
10
|
+
/**
|
|
11
|
+
* Register this package's invariant companion.
|
|
12
|
+
* @param ctx - Cordis context carrying the invariant service.
|
|
13
|
+
* @returns the installed registration's disposer after setup succeeds.
|
|
14
|
+
*/
|
|
15
|
+
export declare const apply: (ctx: Context) => Promise<() => void>;
|
|
16
|
+
//# sourceMappingURL=invariant.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Durable settings namespace for product-wide GUI onboarding facts. */
|
|
2
|
+
export declare const WELCOME_NOTICE_SETTINGS_NAMESPACE = "ui-onboarding";
|
|
3
|
+
/** Field storing the last welcome notice version the user acknowledged. */
|
|
4
|
+
export declare const WELCOME_NOTICE_ACK_FIELD = "welcomeNoticeVersion";
|
|
5
|
+
/**
|
|
6
|
+
* Bump only when the notice changes materially and every user should see it
|
|
7
|
+
* again. The acknowledgement is compared for exact equality.
|
|
8
|
+
*/
|
|
9
|
+
export declare const WELCOME_NOTICE_VERSION = "2026-07-30.7";
|
|
10
|
+
/** The complete editable welcome notice in both supported GUI locales. */
|
|
11
|
+
export declare const WELCOME_NOTICE_COPY: {
|
|
12
|
+
readonly zh: {
|
|
13
|
+
readonly title: "内测声明";
|
|
14
|
+
readonly paragraphs: readonly ["感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。", "“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。", "为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"];
|
|
15
|
+
readonly feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们";
|
|
16
|
+
readonly continueLabel: "继续";
|
|
17
|
+
};
|
|
18
|
+
readonly en: {
|
|
19
|
+
readonly title: "内测声明";
|
|
20
|
+
readonly paragraphs: readonly ["感谢您愿意拨冗试用 DeepSeek Harness。当前版本仍处于内部测试阶段,功能仍待完善,体验难免有些粗糙。", "“如切如磋,如琢如磨。” 产品的成长,离不开一次次真实的碰撞与坦诚的反馈。您在真实使用中发现的问题,也可能促使我们重新审视,甚至推翻已有的设计。", "为了帮助我们更准确地还原您真实使用中的问题,内测版本默认会上传所有 Session Log;如需关闭,可以设置环境变量 DSH_TELEMETRY_DISABLED=1。另外,如果您有任何反馈与建议,请在企业微信群中留言告诉我们。每一条反馈,都会帮助我们把它打磨得更好。"];
|
|
21
|
+
readonly feedbackEmphasis: "如果您有任何反馈与建议,请在企业微信群中留言告诉我们";
|
|
22
|
+
readonly continueLabel: "继续";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=onboarding-copy.d.ts.map
|
package/package.json
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@deepseek-ai/dsh-client-ui-settings-general",
|
|
3
|
+
"description": "Settings ownerless-copy and product onboarding plugin: the General section, shell trigger/header chrome content, settings dictionaries, and the versioned welcome notice",
|
|
4
|
+
"version": "0.0.1-rc.1",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "restricted"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
|
|
11
|
+
"directory": "packages/client/ui-settings-general"
|
|
12
|
+
},
|
|
13
|
+
"type": "module",
|
|
14
|
+
"main": "lib/index.js",
|
|
15
|
+
"types": "lib/types/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/types/index.d.ts",
|
|
19
|
+
"default": "./lib/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./invariant": {
|
|
22
|
+
"types": "./lib/types/invariant.d.ts",
|
|
23
|
+
"default": "./lib/invariant.js"
|
|
24
|
+
},
|
|
25
|
+
"./client": {
|
|
26
|
+
"types": "./lib/types/client/index.d.ts",
|
|
27
|
+
"default": "./lib/client.js"
|
|
28
|
+
},
|
|
29
|
+
"./src/*": "./src/*",
|
|
30
|
+
"./package.json": "./package.json"
|
|
31
|
+
},
|
|
32
|
+
"dsh": {
|
|
33
|
+
"client": {
|
|
34
|
+
"inject": [
|
|
35
|
+
"@deepseek-ai/dsh-client-runtime",
|
|
36
|
+
"@deepseek-ai/dsh-client-ui-settings",
|
|
37
|
+
"@deepseek-ai/dsh-client-locale",
|
|
38
|
+
"@deepseek-ai/dsh-client-connection"
|
|
39
|
+
],
|
|
40
|
+
"platform": "web"
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"license": "BSD-3-Clause",
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@deepseek-ai/dsh-settings": "^0.0.1-rc.1",
|
|
46
|
+
"@deepseek-ai/schemastery": "^3.18.1-rc.1"
|
|
47
|
+
},
|
|
48
|
+
"peerDependencies": {
|
|
49
|
+
"react": "^18.2.0",
|
|
50
|
+
"@deepseek-ai/dsh-client-connection": "^0.0.1-rc.1",
|
|
51
|
+
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.1",
|
|
52
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.0.1-rc.1",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.1",
|
|
56
|
+
"@deepseek-ai/dsh-client-web-react": "^0.0.1-rc.1",
|
|
57
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
58
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.1"
|
|
59
|
+
},
|
|
60
|
+
"devDependencies": {
|
|
61
|
+
"@types/react": "~18.3.1",
|
|
62
|
+
"react": "^18.2.0",
|
|
63
|
+
"@deepseek-ai/dsh-client-connection": "^0.0.1-rc.1",
|
|
64
|
+
"@deepseek-ai/dsh-client-locale": "^0.0.1-rc.1",
|
|
65
|
+
"@deepseek-ai/dsh-client-runtime": "^0.0.1-rc.1",
|
|
66
|
+
"@deepseek-ai/dsh-client-test-runtime": "^0.0.1-rc.1",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.0.1-rc.1",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.0.1-rc.1",
|
|
69
|
+
"@deepseek-ai/dsh-client-web-react": "^0.0.1-rc.1",
|
|
70
|
+
"@deepseek-ai/dsh-invariants": "^0.0.1-rc.1",
|
|
71
|
+
"@deepseek-ai/cordis": "^4.0.1-rc.1",
|
|
72
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.0.1-rc.1"
|
|
73
|
+
},
|
|
74
|
+
"files": [
|
|
75
|
+
"lib/index.js",
|
|
76
|
+
"lib/invariant.js",
|
|
77
|
+
"lib/client.js",
|
|
78
|
+
"lib/types/**/*.d.ts"
|
|
79
|
+
],
|
|
80
|
+
"scripts": {
|
|
81
|
+
"bundle": "tsdown",
|
|
82
|
+
"watch": "tsdown --watch"
|
|
83
|
+
}
|
|
84
|
+
}
|