dsh-ui-fortifier 0.5.3 → 0.7.0
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.md +5 -4
- package/README.zh.md +5 -4
- package/lib/client.js +315 -115
- package/lib/index.js +22 -21
- package/lib/types/client/compact-button/CompactContextButton.d.ts +16 -0
- package/lib/types/client/compact-button/index.d.ts +11 -0
- package/lib/types/client/index.d.ts +4 -4
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/open-dsh-folder/OpenDshFolderAction.d.ts +3 -3
- package/lib/types/client/open-dsh-folder/index.d.ts +2 -2
- package/lib/types/client/settings/FortifierSettingsPage.d.ts +13 -8
- package/lib/types/client/settings/index.d.ts +10 -7
- package/lib/types/index.d.ts +57 -12
- package/lib/types/open-dsh-folder.d.ts +4 -4
- package/lib/types/types.d.ts +13 -8
- package/package.json +28 -24
package/README.md
CHANGED
|
@@ -18,19 +18,20 @@ dsh plugin --profile web add dsh-ui-fortifier
|
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
21
|
-
Adds a
|
|
21
|
+
Adds a configuration area to this plugin's own card on the sidebar's Plugins page, toggling every feature module of this plugin.
|
|
22
22
|
|
|
23
23
|
| Feature | Description |
|
|
24
24
|
| --- | --- |
|
|
25
|
+
| session-id-copy | Copy-session-ID button in the Session header's utility group. |
|
|
26
|
+
| compact-button | Compact-context button at the right end of the composer tool row's left group; runs `/compact`. |
|
|
25
27
|
| provider-label | Shows the currently selected provider to the left of the model selector. |
|
|
26
28
|
| model-picker | Cascading model picker (provider → model) next to the model selector in the input row. |
|
|
27
|
-
|
|
|
28
|
-
| open-dsh-folder | Adds an "Open .dsh folder" button next to "Open configuration file" at the top-right of the Settings page. |
|
|
29
|
+
| open-dsh-folder | Adds an "Open dshHome folder" button next to "Open configuration file" at the top-right of the Settings page. |
|
|
29
30
|
| settings-frame | Makes the Settings panel draggable and resizable. |
|
|
30
31
|
|
|
31
32
|
## dsh version used for development
|
|
32
33
|
|
|
33
|
-
- dsh version used for development: `0.1.
|
|
34
|
+
- dsh version used for development: `0.1.7-rc.2`. `@deepseek-ai/dsh-*` dependencies use `workspace:^`.
|
|
34
35
|
|
|
35
36
|
## Secondary Development
|
|
36
37
|
|
package/README.zh.md
CHANGED
|
@@ -18,19 +18,20 @@ dsh plugin --profile web add dsh-ui-fortifier
|
|
|
18
18
|
|
|
19
19
|
## 功能
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
在侧边栏「插件」页本插件自己的卡片上提供配置区,集中开关本插件各功能模块。
|
|
22
22
|
|
|
23
23
|
| 功能 | 描述 |
|
|
24
24
|
| --- | --- |
|
|
25
|
+
| session-id-copy | 会话标题栏工具区提供复制会话 ID 按钮。 |
|
|
26
|
+
| compact-button | 输入框工具行左组右端提供压缩上下文按钮,等价于提交 `/compact` 指令。 |
|
|
25
27
|
| provider-label | 在模型选择按钮左侧显示当前选择的提供方。 |
|
|
26
28
|
| model-picker | 输入行模型选择器旁提供级联模型选择器(提供商 → 模型)。 |
|
|
27
|
-
|
|
|
28
|
-
| open-dsh-folder | 在设置页右上角「打开配置文件」旁增加「打开 .dsh 文件夹」。 |
|
|
29
|
+
| open-dsh-folder | 在设置页右上角「打开配置文件」旁增加「打开dshHome文件夹」。 |
|
|
29
30
|
| settings-frame | 设置面板可拖动位置与拖动大小。 |
|
|
30
31
|
|
|
31
32
|
## 构建时使用的 dsh 版本
|
|
32
33
|
|
|
33
|
-
- 构建时使用的 dsh 版本:`0.1.
|
|
34
|
+
- 构建时使用的 dsh 版本:`0.1.7-rc.2`;`@deepseek-ai/dsh-*` 依赖使用 `workspace:^`。
|
|
34
35
|
|
|
35
36
|
## 二次开发说明
|
|
36
37
|
|
package/lib/client.js
CHANGED
|
@@ -4,18 +4,18 @@ 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 react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
-
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
7
|
let react = require("react");
|
|
8
|
+
let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
let react_dom = require("react-dom");
|
|
11
11
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\settings\FortifierSettingsPage.module.css.mjs
|
|
12
|
-
const css$
|
|
13
|
-
const tagId$
|
|
14
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
12
|
+
const css$6 = ".t1_2kq_page{flex-direction:column;gap:8px;padding:16px;display:flex}.t1_2kq_heading{color:var(--dsw-alias-label-primary);margin:0;font-size:16px;line-height:24px}.t1_2kq_list{flex-direction:column;margin:0;padding:0;list-style:none;display:flex}.t1_2kq_row{justify-content:space-between;align-items:center;gap:12px;padding:10px 12px;display:flex}.t1_2kq_row+.t1_2kq_row{border-top:.5px solid var(--dsw-alias-border-l3)}.t1_2kq_row:hover{background:var(--dsw-alias-interactive-bg-hover)}.t1_2kq_rowLabel{color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px}";
|
|
13
|
+
const tagId$6 = "dsh-ui-fortifier/FortifierSettingsPage.module.css";
|
|
14
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$6) + "]") === null) {
|
|
15
15
|
const tag = document.createElement("style");
|
|
16
16
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
17
|
-
tag.dataset.pluginCss = tagId$
|
|
18
|
-
tag.textContent = css$
|
|
17
|
+
tag.dataset.pluginCss = tagId$6;
|
|
18
|
+
tag.textContent = css$6;
|
|
19
19
|
document.head.appendChild(tag);
|
|
20
20
|
}
|
|
21
21
|
var FortifierSettingsPage_module_css_default = {
|
|
@@ -23,23 +23,57 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
"list": "t1_2kq_list",
|
|
24
24
|
"page": "t1_2kq_page",
|
|
25
25
|
"row": "t1_2kq_row",
|
|
26
|
-
"rowLabel": "t1_2kq_rowLabel"
|
|
27
|
-
"switch": "t1_2kq_switch",
|
|
28
|
-
"switchOn": "t1_2kq_switchOn",
|
|
29
|
-
"thumb": "t1_2kq_thumb"
|
|
26
|
+
"rowLabel": "t1_2kq_rowLabel"
|
|
30
27
|
};
|
|
31
28
|
//#endregion
|
|
32
29
|
//#region src/client/settings/FortifierSettingsPage.tsx
|
|
33
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* 配置区:插件页上本包卡片里的六个功能开关。
|
|
32
|
+
*/
|
|
33
|
+
/**
|
|
34
|
+
* 渲染六个功能开关。
|
|
35
|
+
* @param props - 组装后的插槽 props。
|
|
36
|
+
* @returns 插件页本包卡片上的配置区。
|
|
37
|
+
*/
|
|
34
38
|
function FortifierSettingsPage(props) {
|
|
35
39
|
const t = props.t;
|
|
36
40
|
const rows = props.useToggles((value) => value);
|
|
41
|
+
const [local, setLocal] = (0, react.useState)(() => /* @__PURE__ */ new Map());
|
|
42
|
+
const [pendingWrites, setPendingWrites] = (0, react.useState)(0);
|
|
43
|
+
const synced = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
44
|
+
(0, react.useEffect)(() => {
|
|
45
|
+
const host = new Map(rows.map((row) => [row.field, row.value]));
|
|
46
|
+
const unchanged = [...host].every(([field, value]) => synced.current.get(field) === value) && host.size === synced.current.size;
|
|
47
|
+
if (pendingWrites > 0 || unchanged) return;
|
|
48
|
+
synced.current = host;
|
|
49
|
+
setLocal(/* @__PURE__ */ new Map());
|
|
50
|
+
}, [rows, pendingWrites]);
|
|
51
|
+
/** 记一次未落定的写入,落定后减一;被拒或传输失败也照样放行,好让宿主值接管。 */
|
|
52
|
+
const trackWrite = (write) => {
|
|
53
|
+
setPendingWrites((count) => count + 1);
|
|
54
|
+
write.catch(() => false).finally(() => {
|
|
55
|
+
setPendingWrites((count) => Math.max(0, count - 1));
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
/**
|
|
59
|
+
* 提交一个开关:先落在本地(控件立即显示新值),再写宿主。
|
|
60
|
+
* @param row - 要切换的开关行。
|
|
61
|
+
*/
|
|
62
|
+
const commit = (row) => {
|
|
63
|
+
const next = !(local.get(row.field) ?? row.value);
|
|
64
|
+
const pending = new Map(local);
|
|
65
|
+
pending.set(row.field, next);
|
|
66
|
+
setLocal(pending);
|
|
67
|
+
synced.current = new Map(synced.current).set(row.field, next);
|
|
68
|
+
trackWrite(props.set(row.field, next));
|
|
69
|
+
};
|
|
70
|
+
if (props.view === "summary") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: t("nav") });
|
|
37
71
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
38
72
|
className: FortifierSettingsPage_module_css_default.page,
|
|
39
73
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
40
74
|
className: FortifierSettingsPage_module_css_default.heading,
|
|
41
75
|
children: t("nav")
|
|
42
|
-
}),
|
|
76
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ul", {
|
|
43
77
|
className: FortifierSettingsPage_module_css_default.list,
|
|
44
78
|
children: rows.map((row) => {
|
|
45
79
|
const label = t(`config.${row.field}`);
|
|
@@ -48,16 +82,12 @@ window.__ModuleLoader__.load({
|
|
|
48
82
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
49
83
|
className: FortifierSettingsPage_module_css_default.rowLabel,
|
|
50
84
|
children: label
|
|
51
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
onClick: () => {
|
|
58
|
-
props.set(row.field, !row.value);
|
|
59
|
-
},
|
|
60
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: FortifierSettingsPage_module_css_default.thumb })
|
|
85
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Switch, {
|
|
86
|
+
checked: local.get(row.field) ?? row.value,
|
|
87
|
+
label,
|
|
88
|
+
onChange: () => {
|
|
89
|
+
commit(row);
|
|
90
|
+
}
|
|
61
91
|
})]
|
|
62
92
|
}, row.field);
|
|
63
93
|
})
|
|
@@ -69,14 +99,14 @@ window.__ModuleLoader__.load({
|
|
|
69
99
|
/** 英文文案。 */
|
|
70
100
|
const en = {
|
|
71
101
|
nav: "ui-fortifier",
|
|
72
|
-
empty: "No feature modules registered.",
|
|
73
102
|
"config.provider-label": "Input - Provider",
|
|
74
|
-
"config.open-dsh-folder": "Settings top-right - Open
|
|
103
|
+
"config.open-dsh-folder": "Settings top-right - Open dshHome folder",
|
|
75
104
|
"config.settings-frame": "Settings panel - Drag and resize",
|
|
76
105
|
"config.model-picker": "Input - Cascading model picker",
|
|
77
106
|
"config.session-id-copy": "Session header - Copy session ID",
|
|
78
|
-
|
|
79
|
-
|
|
107
|
+
"config.compact-button": "Input left group - Compact context",
|
|
108
|
+
openDshFolder: "Open dshHome folder",
|
|
109
|
+
"openDshFolder.error": "Could not open the dshHome folder",
|
|
80
110
|
"openDshFolder.pathLabel": "Path: ",
|
|
81
111
|
"settingsFrame.drag": "Drag the settings panel",
|
|
82
112
|
"settingsFrame.resize": "Resize the settings panel",
|
|
@@ -94,19 +124,23 @@ window.__ModuleLoader__.load({
|
|
|
94
124
|
"modelPicker.model": "Model: {name}",
|
|
95
125
|
"sessionIdCopy.action": "Copy Session ID",
|
|
96
126
|
"sessionIdCopy.hint": "Session ID: {id}",
|
|
97
|
-
"sessionIdCopy.copied": "Copied"
|
|
127
|
+
"sessionIdCopy.copied": "Copied",
|
|
128
|
+
"compactButton.action": "Compact context",
|
|
129
|
+
"compactButton.confirmTitle": "Compact context",
|
|
130
|
+
"compactButton.confirmText": "Confirm compaction?",
|
|
131
|
+
"compactButton.confirm": "Confirm"
|
|
98
132
|
};
|
|
99
133
|
/** 中文文案。 */
|
|
100
134
|
const zh = {
|
|
101
135
|
nav: "ui-fortifier",
|
|
102
|
-
empty: "没有已注册的功能模块。",
|
|
103
136
|
"config.provider-label": "输入框 - 提供商",
|
|
104
|
-
"config.open-dsh-folder": "设置右上角 - 打开
|
|
137
|
+
"config.open-dsh-folder": "设置右上角 - 打开dshHome文件夹",
|
|
105
138
|
"config.settings-frame": "设置面板 - 拖动与缩放",
|
|
106
139
|
"config.model-picker": "输入框 - 级联模型选择器",
|
|
107
140
|
"config.session-id-copy": "会话标题栏 - 复制 Session ID",
|
|
108
|
-
|
|
109
|
-
|
|
141
|
+
"config.compact-button": "输入框左组 - 压缩上下文",
|
|
142
|
+
openDshFolder: "打开dshHome文件夹",
|
|
143
|
+
"openDshFolder.error": "无法打开dshHome文件夹",
|
|
110
144
|
"openDshFolder.pathLabel": "路径:",
|
|
111
145
|
"settingsFrame.drag": "拖动设置面板",
|
|
112
146
|
"settingsFrame.resize": "缩放设置面板",
|
|
@@ -124,77 +158,76 @@ window.__ModuleLoader__.load({
|
|
|
124
158
|
"modelPicker.model": "模型:{name}",
|
|
125
159
|
"sessionIdCopy.action": "复制 Session ID",
|
|
126
160
|
"sessionIdCopy.hint": "Session ID: {id}",
|
|
127
|
-
"sessionIdCopy.copied": "已复制"
|
|
161
|
+
"sessionIdCopy.copied": "已复制",
|
|
162
|
+
"compactButton.action": "压缩上下文",
|
|
163
|
+
"compactButton.confirmTitle": "压缩上下文",
|
|
164
|
+
"compactButton.confirmText": "确认压缩?",
|
|
165
|
+
"compactButton.confirm": "确认"
|
|
128
166
|
};
|
|
129
167
|
//#endregion
|
|
130
168
|
//#region src/client/settings/index.ts
|
|
131
|
-
/**
|
|
169
|
+
/** 本插件在 profile 里的入口 id,同时是设置契约的命名空间。 */
|
|
132
170
|
const UI_FORTIFIER = "ui-fortifier";
|
|
133
171
|
/**
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
172
|
+
* 本插件在 profile 里的包名,也是插件页派发配置区的键。
|
|
173
|
+
*
|
|
174
|
+
* 该页以 `pkg.name` 派发(`renderSlot('plugins.bundle.config', ..., { entryKey: pkg.name })`),
|
|
175
|
+
* 所以这里的值必须与 package.json 的 `name` 逐字一致;写错不会报错,只会让配置区静默
|
|
176
|
+
* 地不出现。
|
|
177
|
+
*/
|
|
178
|
+
const BUNDLE_NAME = "dsh-ui-fortifier";
|
|
179
|
+
/**
|
|
180
|
+
* 注册配置区并把入口配置的表单绑成本页的数据源。
|
|
181
|
+
* @param ctx - 需已提供 slots/locale/configForms 的客户端上下文。
|
|
182
|
+
* @param moduleOrder - 功能开关字段的显示顺序。
|
|
183
|
+
* @returns 本入口的表单,供调用方控制子模块注册。
|
|
138
184
|
*/
|
|
139
185
|
function installSettings(ctx, moduleOrder) {
|
|
140
186
|
ctx.effect(() => ctx.locale.register(UI_FORTIFIER, {
|
|
141
187
|
zh,
|
|
142
188
|
en
|
|
143
189
|
}), "dsh-ui-fortifier: copy dictionaries");
|
|
144
|
-
const
|
|
145
|
-
const
|
|
146
|
-
const view = () => mirror.getSnapshot().view?.namespaces.find((row) => row.ns === UI_FORTIFIER);
|
|
147
|
-
const sectionInjected = () => {
|
|
190
|
+
const form = ctx.configForms.get(UI_FORTIFIER);
|
|
191
|
+
const injected = () => {
|
|
148
192
|
let cached = [];
|
|
149
|
-
let
|
|
193
|
+
let signature = "";
|
|
150
194
|
return {
|
|
151
195
|
hooks: { toggles: {
|
|
152
196
|
getSnapshot: () => {
|
|
153
|
-
const value =
|
|
197
|
+
const value = form.getSnapshot().value;
|
|
154
198
|
const rows = moduleOrder.map((field) => ({
|
|
155
199
|
field,
|
|
156
|
-
value: value[field] ?? true
|
|
200
|
+
value: value?.[field] ?? true
|
|
157
201
|
}));
|
|
158
|
-
const
|
|
159
|
-
if (
|
|
202
|
+
const current = JSON.stringify(rows);
|
|
203
|
+
if (current !== signature) {
|
|
160
204
|
cached = rows;
|
|
161
|
-
|
|
205
|
+
signature = current;
|
|
162
206
|
}
|
|
163
207
|
return cached;
|
|
164
208
|
},
|
|
165
|
-
subscribe: (listener) =>
|
|
166
|
-
const offScope = scope.subscribe(listener);
|
|
167
|
-
const offMirror = mirror.subscribe(listener);
|
|
168
|
-
return () => {
|
|
169
|
-
offScope();
|
|
170
|
-
offMirror();
|
|
171
|
-
};
|
|
172
|
-
}
|
|
209
|
+
subscribe: (listener) => form.subscribe(listener)
|
|
173
210
|
} },
|
|
174
|
-
set: (field, value) =>
|
|
175
|
-
scope.set(field, value);
|
|
176
|
-
}
|
|
211
|
+
set: (field, value) => form.set(field, value)
|
|
177
212
|
};
|
|
178
213
|
};
|
|
179
|
-
ctx.slots.inject("
|
|
180
|
-
name: "
|
|
181
|
-
|
|
182
|
-
order: 30,
|
|
183
|
-
label: () => ctx.locale.bind(UI_FORTIFIER)("nav"),
|
|
214
|
+
ctx.slots.inject("plugins.bundle.config", () => ctx.slots.register({
|
|
215
|
+
name: "plugins.bundle.config",
|
|
216
|
+
key: BUNDLE_NAME,
|
|
184
217
|
locale: UI_FORTIFIER,
|
|
185
|
-
inject:
|
|
218
|
+
inject: injected
|
|
186
219
|
}, FortifierSettingsPage));
|
|
187
|
-
return
|
|
220
|
+
return form;
|
|
188
221
|
}
|
|
189
222
|
//#endregion
|
|
190
223
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\provider-label\ProviderLabel.module.css.mjs
|
|
191
|
-
const css$
|
|
192
|
-
const tagId$
|
|
193
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
224
|
+
const css$5 = ".LjXNpG_label{text-overflow:ellipsis;white-space:nowrap;max-width:160px;color:var(--dsw-alias-label-secondary);font-size:13px;line-height:20px;overflow:hidden}";
|
|
225
|
+
const tagId$5 = "dsh-ui-fortifier/ProviderLabel.module.css";
|
|
226
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
|
|
194
227
|
const tag = document.createElement("style");
|
|
195
228
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
196
|
-
tag.dataset.pluginCss = tagId$
|
|
197
|
-
tag.textContent = css$
|
|
229
|
+
tag.dataset.pluginCss = tagId$5;
|
|
230
|
+
tag.textContent = css$5;
|
|
198
231
|
document.head.appendChild(tag);
|
|
199
232
|
}
|
|
200
233
|
var ProviderLabel_module_css_default = { "label": "LjXNpG_label" };
|
|
@@ -226,13 +259,13 @@ window.__ModuleLoader__.load({
|
|
|
226
259
|
}
|
|
227
260
|
//#endregion
|
|
228
261
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\open-dsh-folder\OpenDshFolderAction.module.css.mjs
|
|
229
|
-
const css$
|
|
230
|
-
const tagId$
|
|
231
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
262
|
+
const css$4 = "._8KsKXW_action{align-items:center;gap:8px;min-width:0;display:flex}._8KsKXW_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}";
|
|
263
|
+
const tagId$4 = "dsh-ui-fortifier/OpenDshFolderAction.module.css";
|
|
264
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
232
265
|
const tag = document.createElement("style");
|
|
233
266
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
234
|
-
tag.dataset.pluginCss = tagId$
|
|
235
|
-
tag.textContent = css$
|
|
267
|
+
tag.dataset.pluginCss = tagId$4;
|
|
268
|
+
tag.textContent = css$4;
|
|
236
269
|
document.head.appendChild(tag);
|
|
237
270
|
}
|
|
238
271
|
var OpenDshFolderAction_module_css_default = {
|
|
@@ -242,7 +275,7 @@ window.__ModuleLoader__.load({
|
|
|
242
275
|
//#endregion
|
|
243
276
|
//#region src/client/open-dsh-folder/OpenDshFolderAction.tsx
|
|
244
277
|
/**
|
|
245
|
-
* 渲染「打开
|
|
278
|
+
* 渲染「打开 dshHome 文件夹」操作,点击后请求 Host 打开 dshHome 目录。
|
|
246
279
|
* @param props - header owner 参数、本地化文案与注入的打开回调。
|
|
247
280
|
* @returns 操作按钮及其结果提示。
|
|
248
281
|
*/
|
|
@@ -291,7 +324,7 @@ window.__ModuleLoader__.load({
|
|
|
291
324
|
/** 本模块文案命名空间(与 host 侧一致)。 */
|
|
292
325
|
const NS$2 = "ui-fortifier";
|
|
293
326
|
/**
|
|
294
|
-
* 注册「打开
|
|
327
|
+
* 注册「打开 dshHome 文件夹」到设置页右上角操作区,仅在回环连接下注册。
|
|
295
328
|
* @param ctx - 需已提供 slots/connection 的客户端上下文。
|
|
296
329
|
* @returns 停止注入并卸载注册的 disposer。
|
|
297
330
|
*/
|
|
@@ -309,13 +342,13 @@ window.__ModuleLoader__.load({
|
|
|
309
342
|
}
|
|
310
343
|
//#endregion
|
|
311
344
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\settings-frame\SettingsFrameEnhancer.module.css.mjs
|
|
312
|
-
const css$
|
|
313
|
-
const tagId$
|
|
314
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
345
|
+
const css$3 = ".hB-7Ba_hostAnchor{display:none}.hB-7Ba_dragHandle{box-sizing:border-box;width:22px;height:22px;color:var(--dsw-alias-label-secondary);cursor:grab;vertical-align:middle;touch-action:none;background:0 0;border:none;border-radius:6px;flex:none;justify-content:center;align-items:center;margin:0 8px 0 0;padding:0;display:inline-flex}.hB-7Ba_dragHandle:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.hB-7Ba_gripIcon{flex:none;width:10px;height:14px}.hB-7Ba_resizeHandle{cursor:nwse-resize;touch-action:none;background:0 0;border:none;width:16px;height:16px;margin:0;padding:0;position:absolute;bottom:8px;right:8px}.hB-7Ba_resizeHandle:before,.hB-7Ba_resizeHandle:after{content:\"\";pointer-events:none;position:absolute;bottom:0;right:0}.hB-7Ba_resizeHandle:after{border-right:2px solid var(--dsw-alias-label-secondary);border-bottom:2px solid var(--dsw-alias-label-secondary);width:10px;height:10px}.hB-7Ba_resizeHandle:before{border-right:2px solid var(--dsw-alias-label-tertiary);border-bottom:2px solid var(--dsw-alias-label-tertiary);width:6px;height:6px;bottom:4px;right:4px}.hB-7Ba_resizeHandle:hover:after{border-color:var(--dsw-alias-label-primary)}";
|
|
346
|
+
const tagId$3 = "dsh-ui-fortifier/SettingsFrameEnhancer.module.css";
|
|
347
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
315
348
|
const tag = document.createElement("style");
|
|
316
349
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
317
|
-
tag.dataset.pluginCss = tagId$
|
|
318
|
-
tag.textContent = css$
|
|
350
|
+
tag.dataset.pluginCss = tagId$3;
|
|
351
|
+
tag.textContent = css$3;
|
|
319
352
|
document.head.appendChild(tag);
|
|
320
353
|
}
|
|
321
354
|
var SettingsFrameEnhancer_module_css_default = {
|
|
@@ -630,13 +663,13 @@ window.__ModuleLoader__.load({
|
|
|
630
663
|
}
|
|
631
664
|
//#endregion
|
|
632
665
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\model-picker\ModelPicker.module.css.mjs
|
|
633
|
-
const css$
|
|
634
|
-
const tagId$
|
|
635
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
666
|
+
const css$2 = ".AGI7WG_root{flex:none;display:inline-flex}.AGI7WG_trigger{box-sizing:border-box;width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:14px;justify-content:center;align-items:center;padding:0;display:inline-flex}.AGI7WG_trigger:hover{background:var(--dsw-alias-interactive-bg-hover)}.AGI7WG_trigger:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}.AGI7WG_triggerIcon{flex:none;width:14px;height:14px}.AGI7WG_menu{z-index:1100;box-sizing:border-box;--dsw-elevation-stroke-color:var(--dsw-alias-border-l1);min-width:min(420px,100vw - 32px);max-width:min(520px,100vw - 32px);height:min(420px,100vh - 96px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);--dsh-scrollbar-thumb:var(--dsw-alias-scrollbar-bg-l2);--dsh-scrollbar-thumb-hover:var(--dsw-alias-scrollbar-hover-l2);border:0;flex-direction:column;padding:6px;display:flex;position:fixed;overflow:hidden}.AGI7WG_search{box-sizing:border-box;background:var(--dsw-alias-bg-layer-2);border:.5px solid var(--dsw-alias-border-l3);border-radius:10px;flex:none;align-items:center;gap:6px;height:28px;margin:0 2px 6px;padding:0 8px;display:flex}.AGI7WG_search:focus-within{border-color:var(--dsw-alias-brand-primary)}.AGI7WG_searchIcon{color:var(--dsw-alias-label-tertiary);flex:none;display:inline-flex}.AGI7WG_searchIcon svg{width:13px;height:13px}.AGI7WG_searchInput{min-width:0;color:var(--dsw-alias-label-primary);font:inherit;background:0 0;border:none;outline:none;flex:1;padding:0;font-size:13px;line-height:20px}.AGI7WG_searchInput::placeholder{color:var(--dsw-alias-label-tertiary)}.AGI7WG_columns{flex:1;min-height:0;display:flex;overflow:hidden}.AGI7WG_providers{flex:none;width:160px;padding-right:4px;overflow-y:auto}.AGI7WG_models{flex:1;min-width:0;padding-left:4px;overflow-y:auto}.AGI7WG_columnTitle{color:var(--dsw-alias-label-tertiary);padding:5px 8px 3px;font-size:12px;font-weight:500;line-height:18px}.AGI7WG_cell{box-sizing:border-box;width:100%;min-height:34px;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border:none;border-radius:10px;align-items:center;gap:8px;padding:6px 8px;display:flex}.AGI7WG_cell:hover:not(:disabled),.AGI7WG_cell:focus-visible{background:var(--dsw-alias-interactive-bg-hover)}.AGI7WG_cellActive{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.AGI7WG_cellSelected{color:var(--dsw-alias-label-primary);font-weight:500}.AGI7WG_cell:disabled{color:var(--dsw-alias-label-dimmed);cursor:default}.AGI7WG_modelName{overflow-wrap:anywhere;flex:1;min-width:0}.AGI7WG_check{color:var(--dsw-alias-brand-primary);flex:none}.AGI7WG_status{color:var(--dsw-alias-label-tertiary);padding:10px;font-size:13px;line-height:20px}.AGI7WG_error{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);border-radius:8px;justify-content:space-between;align-items:flex-start;gap:8px;margin-bottom:4px;padding:7px 8px;font-size:12px;line-height:18px;display:flex}.AGI7WG_retry{color:inherit;font:inherit;cursor:pointer;background:0 0;border:none;flex:none;padding:0;font-weight:600}";
|
|
667
|
+
const tagId$2 = "dsh-ui-fortifier/ModelPicker.module.css";
|
|
668
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
636
669
|
const tag = document.createElement("style");
|
|
637
670
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
638
|
-
tag.dataset.pluginCss = tagId$
|
|
639
|
-
tag.textContent = css$
|
|
671
|
+
tag.dataset.pluginCss = tagId$2;
|
|
672
|
+
tag.textContent = css$2;
|
|
640
673
|
document.head.appendChild(tag);
|
|
641
674
|
}
|
|
642
675
|
var ModelPicker_module_css_default = {
|
|
@@ -691,7 +724,7 @@ window.__ModuleLoader__.load({
|
|
|
691
724
|
* 未定位态:隐藏但按原点参与布局,使首帧 offsetWidth/offsetHeight 为真实尺寸,
|
|
692
725
|
* 定位不存在时也不会闪现在原点(与官方 ModelSelect 同法)。
|
|
693
726
|
*/
|
|
694
|
-
const MEASURE_STYLE = {
|
|
727
|
+
const MEASURE_STYLE$1 = {
|
|
695
728
|
visibility: "hidden",
|
|
696
729
|
left: 0,
|
|
697
730
|
top: 0
|
|
@@ -963,12 +996,12 @@ window.__ModuleLoader__.load({
|
|
|
963
996
|
})
|
|
964
997
|
]
|
|
965
998
|
})
|
|
966
|
-
}), picker.open && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(
|
|
999
|
+
}), picker.open && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.MenuSurface, {
|
|
967
1000
|
ref: menuRef,
|
|
968
1001
|
className: ModelPicker_module_css_default.menu,
|
|
969
1002
|
role: "dialog",
|
|
970
1003
|
"aria-label": t("modelPicker.trigger"),
|
|
971
|
-
style: position ?? MEASURE_STYLE,
|
|
1004
|
+
style: position ?? MEASURE_STYLE$1,
|
|
972
1005
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
973
1006
|
className: ModelPicker_module_css_default.search,
|
|
974
1007
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -1115,13 +1148,13 @@ window.__ModuleLoader__.load({
|
|
|
1115
1148
|
}
|
|
1116
1149
|
//#endregion
|
|
1117
1150
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\session-id-copy\SessionIdCopyAction.module.css.mjs
|
|
1118
|
-
const css = ".i0sS3a_button{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:14px;flex:none;justify-content:center;align-items:center;gap:3px;padding:0 7px;display:inline-flex}.i0sS3a_button svg{width:13px;height:13px}.i0sS3a_button:hover{background:var(--dsw-alias-interactive-bg-hover)}.i0sS3a_button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}";
|
|
1119
|
-
const tagId = "dsh-ui-fortifier/SessionIdCopyAction.module.css";
|
|
1120
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1151
|
+
const css$1 = ".i0sS3a_button{box-sizing:border-box;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:14px;flex:none;justify-content:center;align-items:center;gap:3px;padding:0 7px;display:inline-flex}.i0sS3a_button svg{width:13px;height:13px}.i0sS3a_button:hover{background:var(--dsw-alias-interactive-bg-hover)}.i0sS3a_button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}";
|
|
1152
|
+
const tagId$1 = "dsh-ui-fortifier/SessionIdCopyAction.module.css";
|
|
1153
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1121
1154
|
const tag = document.createElement("style");
|
|
1122
1155
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
1123
|
-
tag.dataset.pluginCss = tagId;
|
|
1124
|
-
tag.textContent = css;
|
|
1156
|
+
tag.dataset.pluginCss = tagId$1;
|
|
1157
|
+
tag.textContent = css$1;
|
|
1125
1158
|
document.head.appendChild(tag);
|
|
1126
1159
|
}
|
|
1127
1160
|
var SessionIdCopyAction_module_css_default = { "button": "i0sS3a_button" };
|
|
@@ -1189,7 +1222,7 @@ window.__ModuleLoader__.load({
|
|
|
1189
1222
|
className: SessionIdCopyAction_module_css_default.button,
|
|
1190
1223
|
"aria-label": t("sessionIdCopy.action"),
|
|
1191
1224
|
onClick: copy,
|
|
1192
|
-
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
1225
|
+
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutlineRegular, {}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(HashGlyph, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCopyOutlineRegular, {})] })
|
|
1193
1226
|
})
|
|
1194
1227
|
});
|
|
1195
1228
|
}
|
|
@@ -1213,8 +1246,165 @@ window.__ModuleLoader__.load({
|
|
|
1213
1246
|
}, SessionIdCopyAction));
|
|
1214
1247
|
}
|
|
1215
1248
|
//#endregion
|
|
1249
|
+
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\compact-button\CompactContextButton.module.css.mjs
|
|
1250
|
+
const css = ".zxJg-q_root{flex:none;display:inline-flex}.zxJg-q_button{corner-shape:round;background:var(--dsw-specific-selector);width:28px;height:28px;color:var(--dsw-alias-label-primary);cursor:pointer;border:none;border-radius:999px;flex:none;place-items:center;display:grid}.zxJg-q_button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-solid)}.zxJg-q_button:disabled{opacity:.5;cursor:default}.zxJg-q_glyph{fill:currentColor;flex:none;width:16px;height:16px;overflow:hidden}.zxJg-q_popover{z-index:1100;box-sizing:border-box;max-width:min(260px,100vw - 32px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);flex-direction:column;align-items:flex-start;gap:10px;padding:10px 12px;display:flex;position:fixed}.zxJg-q_popoverText{margin:0;font-size:13px;line-height:20px}";
|
|
1251
|
+
const tagId = "dsh-ui-fortifier/CompactContextButton.module.css";
|
|
1252
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1253
|
+
const tag = document.createElement("style");
|
|
1254
|
+
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
1255
|
+
tag.dataset.pluginCss = tagId;
|
|
1256
|
+
tag.textContent = css;
|
|
1257
|
+
document.head.appendChild(tag);
|
|
1258
|
+
}
|
|
1259
|
+
var CompactContextButton_module_css_default = {
|
|
1260
|
+
"button": "zxJg-q_button",
|
|
1261
|
+
"glyph": "zxJg-q_glyph",
|
|
1262
|
+
"popover": "zxJg-q_popover",
|
|
1263
|
+
"popoverText": "zxJg-q_popoverText",
|
|
1264
|
+
"root": "zxJg-q_root"
|
|
1265
|
+
};
|
|
1266
|
+
//#endregion
|
|
1267
|
+
//#region src/client/compact-button/CompactContextButton.tsx
|
|
1268
|
+
/**
|
|
1269
|
+
* compact-button 功能:输入框工具行左组右端的压缩上下文按钮。
|
|
1270
|
+
*/
|
|
1271
|
+
/** 气泡与按钮之间的间距。 */
|
|
1272
|
+
const POPOVER_GAP = 8;
|
|
1273
|
+
/** 气泡与视口边缘保留的距离。 */
|
|
1274
|
+
const POPOVER_MARGIN = 12;
|
|
1275
|
+
const MEASURE_STYLE = {
|
|
1276
|
+
visibility: "hidden",
|
|
1277
|
+
left: 0,
|
|
1278
|
+
top: 0
|
|
1279
|
+
};
|
|
1280
|
+
/**
|
|
1281
|
+
* 压缩字形:官方图标库没有压缩语义的字形(`IconApiOutline14` 是终端提示符、
|
|
1282
|
+
* `IconEnhanceOutline16` 是四条段落横线,在此都会误读),故内联字形,与
|
|
1283
|
+
* `session-id-copy` 因官方无井号而内联 `HashGlyph` 同一做法。字形由用户提供。
|
|
1284
|
+
* @returns 装饰性内联图标(按钮已有 aria-label)。
|
|
1285
|
+
*/ function CompressGlyph() {
|
|
1286
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1287
|
+
className: CompactContextButton_module_css_default.glyph,
|
|
1288
|
+
viewBox: "0 0 1024 1024",
|
|
1289
|
+
"aria-hidden": "true",
|
|
1290
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M318.1248 840.533333l31.5264-99.8336a759.4624 759.4624 0 0 0 0-457.399466L318.1248 183.466667h332.7296l67.6416 67.6416a733.216 733.216 0 0 0-32.590933 526.184533L705.8752 840.533333H318.1248z m0-733.866666c-51.908267 0-88.866133 50.427733-73.2352 99.925333l31.5264 99.835733a682.658133 682.658133 0 0 1 0 411.144534l-31.5264 99.8336C229.258667 866.9056 266.216533 917.333333 318.1248 917.333333h387.7504c51.908267 0 88.866133-50.427733 73.2352-99.927466l-19.970133-63.240534a656.420267 656.420267 0 0 1 29.947733-472.744533 73.845333 73.845333 0 0 0-14.833067-83.165867l-69.0944-69.0944A76.8 76.8 0 0 0 650.8544 106.666667H318.1248zM152.123733 764.7168c-13.051733-5.437867-19.170133-20.413867-14.2656-33.674667a631.473067 631.473067 0 0 0 0-438.0864c-4.904533-13.2608 1.216-28.2368 14.2656-33.674666l15.752534-6.564267c13.051733-5.437867 28.087467 0.7232 33.045333 13.9648a699.746133 699.746133 0 0 1 0 490.634667c-4.957867 13.2416-19.9936 19.402667-33.045333 13.9648l-15.752534-6.564267z m733.538134-33.474133l-12.343467-29.6256a419.4688 419.4688 0 0 1 8.7744-342.293334c6.101333-12.7552 1.725867-28.311467-10.632533-35.178666l-14.920534-8.288c-12.3584-6.8672-28.010667-2.4384-34.2208 10.263466a487.741867 487.741867 0 0 0-12.017066 401.7536l12.343466 29.623467c5.437867 13.051733 20.426667 19.223467 33.4784 13.7856l15.752534-6.564267c13.051733-5.437867 19.223467-20.426667 13.7856-33.476266z" })
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* 渲染压缩上下文按钮:点击先弹出确认气泡,气泡内确认后才提交 `/compact` 指令;
|
|
1295
|
+
* 点气泡外或按 Escape 取消。回合运行中与提交等待期间按钮禁用。
|
|
1296
|
+
* @param props - 会话标准套件、本地化文案与注入的压缩回调。
|
|
1297
|
+
* @returns 工具行左组右端的图标按钮与确认气泡。
|
|
1298
|
+
*/
|
|
1299
|
+
function CompactContextButton(props) {
|
|
1300
|
+
const running = props.useSession((snapshot) => snapshot.running);
|
|
1301
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1302
|
+
const [pending, setPending] = (0, react.useState)(false);
|
|
1303
|
+
const rootRef = (0, react.useRef)(null);
|
|
1304
|
+
const panelRef = (0, react.useRef)(null);
|
|
1305
|
+
const alive = (0, react.useRef)(true);
|
|
1306
|
+
const position = (0, _deepseek_ai_dsh_client_ui_primitives.useAnchoredPosition)({
|
|
1307
|
+
open,
|
|
1308
|
+
anchorRef: rootRef,
|
|
1309
|
+
panelRef,
|
|
1310
|
+
side: "top",
|
|
1311
|
+
gap: POPOVER_GAP,
|
|
1312
|
+
margin: POPOVER_MARGIN
|
|
1313
|
+
});
|
|
1314
|
+
(0, _deepseek_ai_dsh_client_ui_primitives.useDismissOnOutsidePointer)(rootRef, open, setOpen, panelRef);
|
|
1315
|
+
(0, react.useEffect)(() => {
|
|
1316
|
+
alive.current = true;
|
|
1317
|
+
return () => {
|
|
1318
|
+
alive.current = false;
|
|
1319
|
+
};
|
|
1320
|
+
}, []);
|
|
1321
|
+
(0, react.useEffect)(() => {
|
|
1322
|
+
if (running) setOpen(false);
|
|
1323
|
+
}, [running]);
|
|
1324
|
+
(0, react.useEffect)(() => {
|
|
1325
|
+
if (!open) return;
|
|
1326
|
+
const onKeyDown = (event) => {
|
|
1327
|
+
if (event.key === "Escape") setOpen(false);
|
|
1328
|
+
};
|
|
1329
|
+
document.addEventListener("keydown", onKeyDown);
|
|
1330
|
+
return () => {
|
|
1331
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1332
|
+
};
|
|
1333
|
+
}, [open]);
|
|
1334
|
+
const compact = () => {
|
|
1335
|
+
if (pending) return;
|
|
1336
|
+
setOpen(false);
|
|
1337
|
+
setPending(true);
|
|
1338
|
+
const settle = () => {
|
|
1339
|
+
if (alive.current) setPending(false);
|
|
1340
|
+
};
|
|
1341
|
+
props.compact().then(settle, settle);
|
|
1342
|
+
};
|
|
1343
|
+
const disabled = running || pending;
|
|
1344
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1345
|
+
ref: rootRef,
|
|
1346
|
+
className: CompactContextButton_module_css_default.root,
|
|
1347
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1348
|
+
label: props.t("compactButton.action"),
|
|
1349
|
+
side: "top",
|
|
1350
|
+
delayMs: 500,
|
|
1351
|
+
disabled: open,
|
|
1352
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1353
|
+
type: "button",
|
|
1354
|
+
className: CompactContextButton_module_css_default.button,
|
|
1355
|
+
"aria-label": props.t("compactButton.action"),
|
|
1356
|
+
"aria-haspopup": "dialog",
|
|
1357
|
+
"aria-expanded": open,
|
|
1358
|
+
disabled,
|
|
1359
|
+
onMouseDown: (event) => {
|
|
1360
|
+
event.preventDefault();
|
|
1361
|
+
},
|
|
1362
|
+
onClick: () => {
|
|
1363
|
+
setOpen((value) => !value);
|
|
1364
|
+
},
|
|
1365
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompressGlyph, {})
|
|
1366
|
+
})
|
|
1367
|
+
}), open && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.MenuSurface, {
|
|
1368
|
+
ref: panelRef,
|
|
1369
|
+
compact: true,
|
|
1370
|
+
className: CompactContextButton_module_css_default.popover,
|
|
1371
|
+
role: "dialog",
|
|
1372
|
+
"aria-label": props.t("compactButton.confirmTitle"),
|
|
1373
|
+
style: position ?? MEASURE_STYLE,
|
|
1374
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1375
|
+
className: CompactContextButton_module_css_default.popoverText,
|
|
1376
|
+
children: props.t("compactButton.confirmText")
|
|
1377
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1378
|
+
variant: "primary",
|
|
1379
|
+
size: "sm",
|
|
1380
|
+
disabled,
|
|
1381
|
+
onClick: compact,
|
|
1382
|
+
children: props.t("compactButton.confirm")
|
|
1383
|
+
})]
|
|
1384
|
+
}), document.body)]
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
//#endregion
|
|
1388
|
+
//#region src/client/compact-button/index.ts
|
|
1389
|
+
/**
|
|
1390
|
+
* 注册压缩上下文按钮到 conversation.input.left。
|
|
1391
|
+
* @param ctx - 需已提供 slots 与 remote.commands 的客户端上下文。
|
|
1392
|
+
* @returns 停止注入并卸载注册的 disposer。
|
|
1393
|
+
*/
|
|
1394
|
+
function installCompactButton(ctx) {
|
|
1395
|
+
return ctx.slots.inject("conversation.input.left", () => ctx.slots.register({
|
|
1396
|
+
name: "conversation.input.left",
|
|
1397
|
+
id: "compact-button",
|
|
1398
|
+
order: 100,
|
|
1399
|
+
locale: "ui-fortifier",
|
|
1400
|
+
inject: (sessionId) => ({ compact: async () => {
|
|
1401
|
+
await ctx.remote.commands.execute(sessionId, "/compact", []);
|
|
1402
|
+
} })
|
|
1403
|
+
}, CompactContextButton));
|
|
1404
|
+
}
|
|
1405
|
+
//#endregion
|
|
1216
1406
|
//#region src/client/index.ts
|
|
1217
|
-
/** 功能模块清单:字段名(
|
|
1407
|
+
/** 功能模块清单:字段名(配置开关 key) → 模块安装面。 */
|
|
1218
1408
|
const modules = {
|
|
1219
1409
|
"provider-label": {
|
|
1220
1410
|
module: installProviderLabel,
|
|
@@ -1235,43 +1425,53 @@ window.__ModuleLoader__.load({
|
|
|
1235
1425
|
"session-id-copy": {
|
|
1236
1426
|
module: installSessionIdCopy,
|
|
1237
1427
|
dispose: void 0
|
|
1428
|
+
},
|
|
1429
|
+
"compact-button": {
|
|
1430
|
+
module: installCompactButton,
|
|
1431
|
+
dispose: void 0
|
|
1238
1432
|
}
|
|
1239
1433
|
};
|
|
1240
|
-
/**
|
|
1434
|
+
/** 配置区开关行的显示顺序:按各模块在界面上的位置,从会话标题栏到输入行再到插件页。 */
|
|
1241
1435
|
const MODULE_ORDER = [
|
|
1436
|
+
"session-id-copy",
|
|
1437
|
+
"compact-button",
|
|
1242
1438
|
"provider-label",
|
|
1243
1439
|
"model-picker",
|
|
1244
|
-
"session-id-copy",
|
|
1245
1440
|
"open-dsh-folder",
|
|
1246
1441
|
"settings-frame"
|
|
1247
1442
|
];
|
|
1248
1443
|
const inject = [
|
|
1249
1444
|
"slots",
|
|
1250
1445
|
"locale",
|
|
1251
|
-
"
|
|
1446
|
+
"configForms",
|
|
1252
1447
|
"modelDirectories",
|
|
1253
1448
|
"connection",
|
|
1254
1449
|
"sessions",
|
|
1255
1450
|
"remote",
|
|
1256
|
-
"remote.session"
|
|
1451
|
+
"remote.session",
|
|
1452
|
+
"remote.commands"
|
|
1257
1453
|
];
|
|
1258
1454
|
/**
|
|
1259
|
-
*
|
|
1260
|
-
* @param ctx - 需已提供 slots/locale/
|
|
1455
|
+
* 客户端插件体:注册插件页上的配置区并据开关状态挂载各功能模块。
|
|
1456
|
+
* @param ctx - 需已提供 slots/locale/configForms/modelDirectories/connection/sessions/remote 的客户端上下文。
|
|
1261
1457
|
*/
|
|
1262
1458
|
function apply(ctx) {
|
|
1263
|
-
const
|
|
1264
|
-
|
|
1459
|
+
const form = installSettings(ctx, MODULE_ORDER);
|
|
1460
|
+
const mounted = /* @__PURE__ */ new Map();
|
|
1461
|
+
const sync = (snapshot, field) => {
|
|
1462
|
+
const enabled = snapshot.value?.[field] ?? true;
|
|
1463
|
+
if (mounted.get(field) === enabled) return;
|
|
1464
|
+
mounted.set(field, enabled);
|
|
1265
1465
|
const item = modules[field];
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1466
|
+
item.dispose?.();
|
|
1467
|
+
item.dispose = enabled ? item.module(ctx) : void 0;
|
|
1468
|
+
};
|
|
1469
|
+
const syncAll = () => {
|
|
1470
|
+
const snapshot = form.getSnapshot();
|
|
1471
|
+
for (const field of Object.keys(modules)) sync(snapshot, field);
|
|
1472
|
+
};
|
|
1473
|
+
form.subscribe(syncAll);
|
|
1474
|
+
syncAll();
|
|
1275
1475
|
}
|
|
1276
1476
|
//#endregion
|
|
1277
1477
|
exports.MODULE_ORDER = MODULE_ORDER;
|
package/lib/index.js
CHANGED
|
@@ -93,7 +93,7 @@ async function openWindowsFolderInForeground(path, signal) {
|
|
|
93
93
|
windowsOpenScript(path)
|
|
94
94
|
], signal);
|
|
95
95
|
}
|
|
96
|
-
/** 用系统默认方式打开
|
|
96
|
+
/** 用系统默认方式打开 dshHome 文件夹;无原生打开器时返回路径让 UI 展示。 */
|
|
97
97
|
let OpenDshFolderService = (() => {
|
|
98
98
|
let _classSuper = TypertRemoteService;
|
|
99
99
|
let _instanceExtraInitializers = [];
|
|
@@ -125,9 +125,9 @@ let OpenDshFolderService = (() => {
|
|
|
125
125
|
__runInitializers(this, _instanceExtraInitializers);
|
|
126
126
|
}
|
|
127
127
|
/**
|
|
128
|
-
* 打开
|
|
128
|
+
* 打开 dshHome 文件夹。
|
|
129
129
|
* @param signal - 调用方可取消信号。
|
|
130
|
-
* @returns opened 为 false 时 path 为
|
|
130
|
+
* @returns opened 为 false 时 path 为 dshHome 文件夹路径。
|
|
131
131
|
*/
|
|
132
132
|
async openDshFolder(signal) {
|
|
133
133
|
const home = resolveDshHome();
|
|
@@ -143,7 +143,7 @@ let OpenDshFolderService = (() => {
|
|
|
143
143
|
path: home
|
|
144
144
|
};
|
|
145
145
|
} catch (error) {
|
|
146
|
-
if (signal.aborted) throw new RemoteError("gateway/cancelled", "
|
|
146
|
+
if (signal.aborted) throw new RemoteError("gateway/cancelled", "dshHome folder open was aborted", {});
|
|
147
147
|
throw new RemoteError("gateway/internal", `path open failed: ${messageOf(error)}`, {}, { cause: error });
|
|
148
148
|
}
|
|
149
149
|
}
|
|
@@ -154,29 +154,30 @@ function messageOf(error) {
|
|
|
154
154
|
}
|
|
155
155
|
//#endregion
|
|
156
156
|
//#region lib/types/index.js
|
|
157
|
-
/**
|
|
158
|
-
|
|
159
|
-
|
|
157
|
+
/**
|
|
158
|
+
* 插件配置 schema。
|
|
159
|
+
*
|
|
160
|
+
* 不写成 `z<Config>`:`Config` 的字段是 `Volatile<T>`,而 volatile 字段的 schema 类型
|
|
161
|
+
* 处于 `"volatile-defined"` 模式,两者在双向方差下互不可赋值,加了注解反而编译不过
|
|
162
|
+
* (官方与已迁移的插件同样只写 `z.object`)。
|
|
163
|
+
*/
|
|
160
164
|
const Config = z.object({
|
|
161
|
-
"provider-label": z.boolean().default(true),
|
|
162
|
-
"open-dsh-folder": z.boolean().default(true),
|
|
163
|
-
"settings-frame": z.boolean().default(true),
|
|
164
|
-
"model-picker": z.boolean().default(true),
|
|
165
|
-
"session-id-copy": z.boolean().default(true)
|
|
165
|
+
"provider-label": z.boolean().default(true).volatile(),
|
|
166
|
+
"open-dsh-folder": z.boolean().default(true).volatile(),
|
|
167
|
+
"settings-frame": z.boolean().default(true).volatile(),
|
|
168
|
+
"model-picker": z.boolean().default(true).volatile(),
|
|
169
|
+
"session-id-copy": z.boolean().default(true).volatile(),
|
|
170
|
+
"compact-button": z.boolean().default(true).volatile()
|
|
166
171
|
});
|
|
167
172
|
/**
|
|
168
|
-
*
|
|
169
|
-
* @param ctx -
|
|
170
|
-
* @param config - 插件配置,作为 base 层。
|
|
173
|
+
* 挂载插件:暴露打开 dshHome 文件夹的 Remote 服务,并声明本插件自带配置区。
|
|
174
|
+
* @param ctx - 需已提供 reflect(Typert 网关)的 Cordis 上下文。
|
|
171
175
|
*/
|
|
172
|
-
function apply(ctx
|
|
176
|
+
function apply(ctx) {
|
|
173
177
|
new OpenDshFolderService(ctx);
|
|
174
178
|
ctx.inject(["settings"], (settingsCtx) => {
|
|
175
|
-
settingsCtx.settings.
|
|
176
|
-
setSource: () => {},
|
|
177
|
-
onChange: () => {}
|
|
178
|
-
});
|
|
179
|
+
settingsCtx.effect(() => settingsCtx.settings.configure({ auto: false }, ctx.fiber));
|
|
179
180
|
});
|
|
180
181
|
}
|
|
181
182
|
//#endregion
|
|
182
|
-
export { Config,
|
|
183
|
+
export { Config, apply };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
/** 注入面:提交一次压缩指令。 */
|
|
3
|
+
export interface CompactContextButtonInjected {
|
|
4
|
+
/** 提交 `/compact` 指令;指令生命周期由 host 写入会话流。 */
|
|
5
|
+
compact: () => Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
/** 槽位 owner 参数、本地化文案与注入回调。 */
|
|
8
|
+
export type CompactContextButtonProps = PropsRuntime<'conversation.input.left'> & PropsLocale<'ui-fortifier'> & InjectFace<CompactContextButtonInjected>;
|
|
9
|
+
/**
|
|
10
|
+
* 渲染压缩上下文按钮:点击先弹出确认气泡,气泡内确认后才提交 `/compact` 指令;
|
|
11
|
+
* 点气泡外或按 Escape 取消。回合运行中与提交等待期间按钮禁用。
|
|
12
|
+
* @param props - 会话标准套件、本地化文案与注入的压缩回调。
|
|
13
|
+
* @returns 工具行左组右端的图标按钮与确认气泡。
|
|
14
|
+
*/
|
|
15
|
+
export declare function CompactContextButton(props: CompactContextButtonProps): import("react").JSX.Element;
|
|
16
|
+
//# sourceMappingURL=CompactContextButton.d.ts.map
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compact-button 功能:在输入框工具行左组右端注册压缩上下文按钮。
|
|
3
|
+
*/
|
|
4
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
5
|
+
/**
|
|
6
|
+
* 注册压缩上下文按钮到 conversation.input.left。
|
|
7
|
+
* @param ctx - 需已提供 slots 与 remote.commands 的客户端上下文。
|
|
8
|
+
* @returns 停止注入并卸载注册的 disposer。
|
|
9
|
+
*/
|
|
10
|
+
export declare function installCompactButton(ctx: ClientContext): () => void;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -8,14 +8,14 @@ interface ModuleEntry {
|
|
|
8
8
|
/** 当前注册的 disposer;归位后为 undefined。 */
|
|
9
9
|
dispose: (() => void) | undefined;
|
|
10
10
|
}
|
|
11
|
-
/** 功能模块清单:字段名(
|
|
11
|
+
/** 功能模块清单:字段名(配置开关 key) → 模块安装面。 */
|
|
12
12
|
export declare const modules: Record<keyof Config, ModuleEntry>;
|
|
13
|
-
/**
|
|
13
|
+
/** 配置区开关行的显示顺序:按各模块在界面上的位置,从会话标题栏到输入行再到插件页。 */
|
|
14
14
|
export declare const MODULE_ORDER: readonly (keyof Config)[];
|
|
15
15
|
export declare const inject: string[];
|
|
16
16
|
/**
|
|
17
|
-
*
|
|
18
|
-
* @param ctx - 需已提供 slots/locale/
|
|
17
|
+
* 客户端插件体:注册插件页上的配置区并据开关状态挂载各功能模块。
|
|
18
|
+
* @param ctx - 需已提供 slots/locale/configForms/modelDirectories/connection/sessions/remote 的客户端上下文。
|
|
19
19
|
*/
|
|
20
20
|
export declare function apply(ctx: Context): void;
|
|
21
21
|
declare module '@deepseek-ai/dsh-client-ui-slots' {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** dsh-ui-fortifier 的文案。 */
|
|
2
2
|
/** locale key。 */
|
|
3
|
-
export type UiFortifierLocaleKey = 'nav' | '
|
|
3
|
+
export type UiFortifierLocaleKey = 'nav' | 'config.provider-label' | 'config.open-dsh-folder' | 'config.settings-frame' | 'config.model-picker' | 'config.session-id-copy' | 'config.compact-button' | 'openDshFolder' | 'openDshFolder.error' | 'openDshFolder.pathLabel' | 'settingsFrame.drag' | 'settingsFrame.resize' | 'modelPicker.trigger' | 'modelPicker.searchPlaceholder' | 'modelPicker.providers' | 'modelPicker.models' | 'modelPicker.emptyProviders' | 'modelPicker.emptySearch' | 'modelPicker.emptyModels' | 'modelPicker.loading' | 'modelPicker.loadError' | 'modelPicker.retry' | 'modelPicker.provider' | 'modelPicker.model' | 'sessionIdCopy.action' | 'sessionIdCopy.hint' | 'sessionIdCopy.copied' | 'compactButton.action' | 'compactButton.confirmTitle' | 'compactButton.confirmText' | 'compactButton.confirm';
|
|
4
4
|
/** 英文文案。 */
|
|
5
5
|
export declare const en: Record<UiFortifierLocaleKey, string>;
|
|
6
6
|
/** 中文文案。 */
|
|
@@ -2,15 +2,15 @@ import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-cli
|
|
|
2
2
|
import type { ReactNode } from 'react';
|
|
3
3
|
import type { ConnectionRpcResult } from '@deepseek-ai/dsh-client-connection/client';
|
|
4
4
|
import type { DshFolderOpenValue } from '../../types.ts';
|
|
5
|
-
/** 打开
|
|
5
|
+
/** 打开 dshHome 文件夹的注入面。 */
|
|
6
6
|
export interface OpenDshFolderInjected {
|
|
7
|
-
/** 请求 Host 打开
|
|
7
|
+
/** 请求 Host 打开 dshHome 文件夹。 */
|
|
8
8
|
openDshFolder: () => Promise<ConnectionRpcResult<DshFolderOpenValue>>;
|
|
9
9
|
}
|
|
10
10
|
/** header 操作区的 owner 参数、本地化文案与注入回调。 */
|
|
11
11
|
export type OpenDshFolderActionProps = PropsRuntime<'settings.action'> & PropsLocale<'ui-fortifier'> & InjectFace<OpenDshFolderInjected>;
|
|
12
12
|
/**
|
|
13
|
-
* 渲染「打开
|
|
13
|
+
* 渲染「打开 dshHome 文件夹」操作,点击后请求 Host 打开 dshHome 目录。
|
|
14
14
|
* @param props - header owner 参数、本地化文案与注入的打开回调。
|
|
15
15
|
* @returns 操作按钮及其结果提示。
|
|
16
16
|
*/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* open-dsh-folder 功能:在设置页右上角「打开配置文件」旁增加「打开
|
|
2
|
+
* open-dsh-folder 功能:在设置页右上角「打开配置文件」旁增加「打开 dshHome 文件夹」。
|
|
3
3
|
*/
|
|
4
4
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
5
5
|
export type { OpenDshFolderActionProps, OpenDshFolderInjected } from './OpenDshFolderAction.tsx';
|
|
6
6
|
/**
|
|
7
|
-
* 注册「打开
|
|
7
|
+
* 注册「打开 dshHome 文件夹」到设置页右上角操作区,仅在回环连接下注册。
|
|
8
8
|
* @param ctx - 需已提供 slots/connection 的客户端上下文。
|
|
9
9
|
* @returns 停止注入并卸载注册的 disposer。
|
|
10
10
|
*/
|
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
import type { HostObservable, InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { Config } from '../../types.ts';
|
|
2
3
|
/** 一个功能开关行的状态。 */
|
|
3
4
|
export interface FortifierToggleRow {
|
|
4
|
-
/** 字段名(
|
|
5
|
-
field:
|
|
5
|
+
/** 字段名(即配置的 key)。 */
|
|
6
|
+
field: keyof Config;
|
|
6
7
|
/** 当前值。 */
|
|
7
8
|
value: boolean;
|
|
8
9
|
}
|
|
9
|
-
/**
|
|
10
|
+
/** 配置区渲染所需的面。 */
|
|
10
11
|
export interface FortifierPageInjected {
|
|
11
12
|
hooks: {
|
|
12
13
|
/** 所有功能开关的当前值(响应式)。 */
|
|
13
14
|
toggles: HostObservable<readonly FortifierToggleRow[]>;
|
|
14
15
|
};
|
|
15
|
-
/** 写入一个开关值(user 层)。 */
|
|
16
|
-
set: (field:
|
|
16
|
+
/** 写入一个开关值(user 层);落定后 resolve。 */
|
|
17
|
+
set: (field: keyof Config, value: boolean) => Promise<boolean>;
|
|
17
18
|
}
|
|
18
|
-
/**
|
|
19
|
-
export type FortifierSettingsPageProps = PropsRuntime<'
|
|
20
|
-
/**
|
|
19
|
+
/** 配置区 props:挂在插件页本包详情页的 `plugins.bundle.config` 上。 */
|
|
20
|
+
export type FortifierSettingsPageProps = PropsRuntime<'plugins.bundle.config'> & PropsLocale<'ui-fortifier'> & InjectFace<FortifierPageInjected>;
|
|
21
|
+
/**
|
|
22
|
+
* 渲染六个功能开关。
|
|
23
|
+
* @param props - 组装后的插槽 props。
|
|
24
|
+
* @returns 插件页本包卡片上的配置区。
|
|
25
|
+
*/
|
|
21
26
|
export declare function FortifierSettingsPage(props: FortifierSettingsPageProps): import("react").JSX.Element;
|
|
22
27
|
//# sourceMappingURL=FortifierSettingsPage.d.ts.map
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 注册本插件的配置区(插件页上本包自己的卡片),并把入口配置的表单绑成本页的数据源。
|
|
3
|
+
*/
|
|
1
4
|
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
2
|
-
import type {
|
|
5
|
+
import type { ConfigForm } from '@deepseek-ai/dsh-client-ui-settings/client';
|
|
3
6
|
import type { Config } from '../../types.ts';
|
|
4
7
|
export type { FortifierPageInjected, FortifierSettingsPageProps } from './FortifierSettingsPage.tsx';
|
|
5
|
-
/**
|
|
8
|
+
/** 本插件在 profile 里的入口 id,同时是设置契约的命名空间。 */
|
|
6
9
|
export declare const UI_FORTIFIER = "ui-fortifier";
|
|
7
10
|
/**
|
|
8
|
-
*
|
|
9
|
-
* @param ctx - 需已提供 slots/locale/
|
|
10
|
-
* @param moduleOrder -
|
|
11
|
-
* @returns
|
|
11
|
+
* 注册配置区并把入口配置的表单绑成本页的数据源。
|
|
12
|
+
* @param ctx - 需已提供 slots/locale/configForms 的客户端上下文。
|
|
13
|
+
* @param moduleOrder - 功能开关字段的显示顺序。
|
|
14
|
+
* @returns 本入口的表单,供调用方控制子模块注册。
|
|
12
15
|
*/
|
|
13
|
-
export declare function installSettings(ctx: ClientContext, moduleOrder: readonly
|
|
16
|
+
export declare function installSettings(ctx: ClientContext, moduleOrder: readonly (keyof Config)[]): ConfigForm<Config>;
|
|
14
17
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,17 +1,62 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* dsh-ui-fortifier 的宿主半侧。
|
|
3
|
+
*
|
|
4
|
+
* 只做两件事:暴露「打开 dshHome 文件夹」的 Remote 服务,以及声明本插件自带配置区。
|
|
5
|
+
* 六个功能开关的值由浏览器半侧经设置表单读写(见 `src/client/settings/index.ts`),
|
|
6
|
+
* 宿主不读它们,因此 `apply` 不接配置参数。
|
|
7
|
+
*
|
|
8
|
+
* @module dsh-ui-fortifier
|
|
9
|
+
*/
|
|
10
|
+
import type { Context, Volatile } from '@deepseek-ai/cordis';
|
|
2
11
|
import z from '@deepseek-ai/schemastery';
|
|
3
|
-
import type { Config as FortifierConfig } from './types.ts';
|
|
4
|
-
/** 插件配置类型(定义见 `./types.ts`,与 Client 面共享)。 */
|
|
5
|
-
export type Config = FortifierConfig;
|
|
6
12
|
export type { DshFolderOpenValue } from './types.ts';
|
|
7
|
-
/** 功能开关的 settings 命名空间。 */
|
|
8
|
-
export declare const UI_FORTIFIER_SETTINGS_NAMESPACE = "ui-fortifier";
|
|
9
|
-
/** 插件配置 schema。 */
|
|
10
|
-
export declare const Config: z<FortifierConfig>;
|
|
11
13
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* 插件配置。
|
|
15
|
+
*
|
|
16
|
+
* 六个字段都是 **volatile 引用**:设置表单只投影入口 `Config` 里声明为 `.volatile()`
|
|
17
|
+
* 的字段,写入由 Loader 经 `updateVolatile` 落回本入口的 profile patch。volatile 引用
|
|
18
|
+
* 原地更新,所以表单每次 `.get()` 都拿到当前值,不必重挂插件。
|
|
19
|
+
* 解引用之后的普通值见 [src/types.ts](./types.ts) 的 `Config`。
|
|
20
|
+
*/
|
|
21
|
+
export interface Config {
|
|
22
|
+
/** 输入框显示当前提供商。 */
|
|
23
|
+
'provider-label': Volatile<boolean>;
|
|
24
|
+
/** 插件页右上角显示打开 dshHome 文件夹按钮。 */
|
|
25
|
+
'open-dsh-folder': Volatile<boolean>;
|
|
26
|
+
/** 设置面板可拖动位置与大小。 */
|
|
27
|
+
'settings-frame': Volatile<boolean>;
|
|
28
|
+
/** 输入框右侧显示级联模型选择器(先选提供商、再选模型)。 */
|
|
29
|
+
'model-picker': Volatile<boolean>;
|
|
30
|
+
/** 会话标题栏显示复制会话 ID 按钮。 */
|
|
31
|
+
'session-id-copy': Volatile<boolean>;
|
|
32
|
+
/** 输入框工具行左组右端显示压缩上下文按钮。 */
|
|
33
|
+
'compact-button': Volatile<boolean>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 插件配置 schema。
|
|
37
|
+
*
|
|
38
|
+
* 不写成 `z<Config>`:`Config` 的字段是 `Volatile<T>`,而 volatile 字段的 schema 类型
|
|
39
|
+
* 处于 `"volatile-defined"` 模式,两者在双向方差下互不可赋值,加了注解反而编译不过
|
|
40
|
+
* (官方与已迁移的插件同样只写 `z.object`)。
|
|
41
|
+
*/
|
|
42
|
+
export declare const Config: z<Schemastery.ObjectS<NoInfer<{
|
|
43
|
+
'provider-label': z<boolean, boolean, "volatile-defined">;
|
|
44
|
+
'open-dsh-folder': z<boolean, boolean, "volatile-defined">;
|
|
45
|
+
'settings-frame': z<boolean, boolean, "volatile-defined">;
|
|
46
|
+
'model-picker': z<boolean, boolean, "volatile-defined">;
|
|
47
|
+
'session-id-copy': z<boolean, boolean, "volatile-defined">;
|
|
48
|
+
'compact-button': z<boolean, boolean, "volatile-defined">;
|
|
49
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
50
|
+
'provider-label': z<boolean, boolean, "volatile-defined">;
|
|
51
|
+
'open-dsh-folder': z<boolean, boolean, "volatile-defined">;
|
|
52
|
+
'settings-frame': z<boolean, boolean, "volatile-defined">;
|
|
53
|
+
'model-picker': z<boolean, boolean, "volatile-defined">;
|
|
54
|
+
'session-id-copy': z<boolean, boolean, "volatile-defined">;
|
|
55
|
+
'compact-button': z<boolean, boolean, "volatile-defined">;
|
|
56
|
+
}>>, "plain">;
|
|
57
|
+
/**
|
|
58
|
+
* 挂载插件:暴露打开 dshHome 文件夹的 Remote 服务,并声明本插件自带配置区。
|
|
59
|
+
* @param ctx - 需已提供 reflect(Typert 网关)的 Cordis 上下文。
|
|
15
60
|
*/
|
|
16
|
-
export declare function apply(ctx: Context
|
|
61
|
+
export declare function apply(ctx: Context): void;
|
|
17
62
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* 打开本机
|
|
2
|
+
* 打开本机 dshHome 文件夹的 Host Remote 服务。
|
|
3
3
|
* 端点 `uiFortifier/openDshFolder` 由网关的 SRC 反射发现,无需 typert 生成器产物。
|
|
4
4
|
*/
|
|
5
5
|
import { Context } from '@deepseek-ai/cordis';
|
|
6
6
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
7
7
|
import type { DshFolderOpenValue } from './types.ts';
|
|
8
8
|
export type { DshFolderOpenValue };
|
|
9
|
-
/** 用系统默认方式打开
|
|
9
|
+
/** 用系统默认方式打开 dshHome 文件夹;无原生打开器时返回路径让 UI 展示。 */
|
|
10
10
|
export declare class OpenDshFolderService extends TypertRemoteService {
|
|
11
11
|
constructor(ctx: Context);
|
|
12
12
|
/**
|
|
13
|
-
* 打开
|
|
13
|
+
* 打开 dshHome 文件夹。
|
|
14
14
|
* @param signal - 调用方可取消信号。
|
|
15
|
-
* @returns opened 为 false 时 path 为
|
|
15
|
+
* @returns opened 为 false 时 path 为 dshHome 文件夹路径。
|
|
16
16
|
*/
|
|
17
17
|
openDshFolder(signal: AbortSignal): Promise<DshFolderOpenValue>;
|
|
18
18
|
}
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 本包 Host/Client 两面共享的类型。
|
|
3
3
|
* 仅类型、无运行时代码:双面工程各自编译本文件,无需跨面引用。
|
|
4
|
+
*
|
|
5
|
+
* 这里的 `Config` 是**解引用之后的普通值**,也就是配置区读写的那一份;Host 面的
|
|
6
|
+
* `Config` 六个字段都包在 volatile 引用里,见 [src/index.ts](./index.ts)。
|
|
4
7
|
*/
|
|
5
8
|
/** 插件配置:功能开关状态(配置默认值)。 */
|
|
6
9
|
export interface Config {
|
|
7
10
|
/** 输入框显示当前提供商。 */
|
|
8
|
-
'provider-label': boolean;
|
|
9
|
-
/**
|
|
10
|
-
'open-dsh-folder': boolean;
|
|
11
|
+
readonly 'provider-label': boolean;
|
|
12
|
+
/** 插件页右上角显示打开 dshHome 文件夹按钮。 */
|
|
13
|
+
readonly 'open-dsh-folder': boolean;
|
|
11
14
|
/** 设置面板可拖动位置与大小。 */
|
|
12
|
-
'settings-frame': boolean;
|
|
15
|
+
readonly 'settings-frame': boolean;
|
|
13
16
|
/** 输入框右侧显示级联模型选择器(先选提供商、再选模型)。 */
|
|
14
|
-
'model-picker': boolean;
|
|
17
|
+
readonly 'model-picker': boolean;
|
|
15
18
|
/** 会话标题栏显示复制会话 ID 按钮。 */
|
|
16
|
-
'session-id-copy': boolean;
|
|
19
|
+
readonly 'session-id-copy': boolean;
|
|
20
|
+
/** 输入框工具行左组右端显示压缩上下文按钮。 */
|
|
21
|
+
readonly 'compact-button': boolean;
|
|
17
22
|
}
|
|
18
|
-
/** 打开
|
|
23
|
+
/** 打开 dshHome 文件夹的返回值。 */
|
|
19
24
|
export interface DshFolderOpenValue {
|
|
20
25
|
/** 是否已发起系统打开。 */
|
|
21
26
|
readonly opened: boolean;
|
|
22
|
-
/**
|
|
27
|
+
/** dshHome 文件夹绝对路径(未打开时供 UI 展示)。 */
|
|
23
28
|
readonly path: string;
|
|
24
29
|
}
|
|
25
30
|
//# sourceMappingURL=types.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ui-fortifier",
|
|
3
3
|
"description": "UI 强化",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.7.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"pgnqukezrdxmhjso"
|
|
@@ -44,34 +44,36 @@
|
|
|
44
44
|
"lib/types/**/*.d.ts"
|
|
45
45
|
],
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@deepseek-ai/cordis": "^4.0.
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
47
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
48
|
+
"@deepseek-ai/dsh-native-command": "^0.1.7-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.7-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.7-rc.2",
|
|
51
|
+
"@deepseek-ai/schemastery": "^3.18.4"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/react": "~18.3.1",
|
|
55
55
|
"@types/react-dom": "~18.3.0",
|
|
56
56
|
"react": "^18.2.0",
|
|
57
57
|
"react-dom": "^18.2.0",
|
|
58
|
-
"@deepseek-ai/
|
|
59
|
-
"@deepseek-ai/
|
|
60
|
-
"@deepseek-ai/dsh-api-
|
|
61
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.
|
|
62
|
-
"@deepseek-ai/dsh-client-ui-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-client-ui-
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-
|
|
66
|
-
"@deepseek-ai/dsh-client-ui-
|
|
67
|
-
"@deepseek-ai/dsh-client-ui-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
69
|
-
"@deepseek-ai/dsh-session": "^0.1.
|
|
70
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.
|
|
71
|
-
"@deepseek-ai/dsh-
|
|
72
|
-
"@deepseek-ai/dsh-
|
|
73
|
-
"@deepseek-ai/dsh-
|
|
74
|
-
"@deepseek-ai/
|
|
58
|
+
"@deepseek-ai/cordis": "^4.0.4",
|
|
59
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.7-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-api-remotes": "^0.1.7-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.7-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-model-selection": "^0.1.7-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.7-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager": "^0.1.7-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.7-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.7-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.7-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.7-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.7-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.7-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.7-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-native-command": "^0.1.7-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-session": "^0.1.7-rc.2",
|
|
74
|
+
"@deepseek-ai/dsh-settings": "^0.1.7-rc.2",
|
|
75
|
+
"@deepseek-ai/schemastery": "^3.18.4",
|
|
76
|
+
"@deepseek-ai/dsh-typert-protocol": "^0.1.7-rc.2"
|
|
75
77
|
},
|
|
76
78
|
"dsh": {
|
|
77
79
|
"bundle": {
|
|
@@ -84,6 +86,7 @@
|
|
|
84
86
|
"@deepseek-ai/dsh-client-connection",
|
|
85
87
|
"@deepseek-ai/dsh-client-ui-conversation",
|
|
86
88
|
"@deepseek-ai/dsh-client-ui-model-selection",
|
|
89
|
+
"@deepseek-ai/dsh-client-ui-plugin-manager",
|
|
87
90
|
"@deepseek-ai/dsh-client-ui-renderer",
|
|
88
91
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
89
92
|
"@deepseek-ai/dsh-client-locale"
|
|
@@ -97,8 +100,9 @@
|
|
|
97
100
|
"verify": "node ../dsh-pgnqukezrdxmhjso-base/verify.mjs",
|
|
98
101
|
"pub": "pnpm run build && pnpm login --registry=https://registry.npmjs.org && pnpm publish --registry=https://registry.npmjs.org --no-git-checks",
|
|
99
102
|
"pack": "pnpm run build && pnpm pack --pack-destination lib",
|
|
103
|
+
"link-test-i": "pnpm run build && (pnpm dsh plugin --profile pkgtest remove %npm_package_name% & pnpm dsh plugin --profile pkgtest add link:./)",
|
|
100
104
|
"pack-test-i": "pnpm run pack && (pnpm dsh plugin --profile pkgtest remove %npm_package_name% & pnpm dsh plugin --profile pkgtest add ./lib/%npm_package_name%-%npm_package_version%.tgz)",
|
|
101
|
-
"npm-test-i": "pnpm dsh plugin --profile pkgtest remove %npm_package_name% & pnpm dsh plugin --profile pkgtest add %npm_package_name%@%npm_package_version%",
|
|
105
|
+
"npm-test-i": "pnpm dsh plugin --profile pkgtest remove %npm_package_name% & pnpm dsh plugin --profile pkgtest add --registry=https://registry.npmjs.org %npm_package_name%@%npm_package_version%",
|
|
102
106
|
"test-create": "pnpm dsh --profile pkgtest --from-default-profile web",
|
|
103
107
|
"test-start": "pnpm dsh --profile pkgtest --port 3081 --no-open"
|
|
104
108
|
}
|