dsh-ui-fortifier 0.5.2 → 0.6.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 +2 -0
- package/README.zh.md +2 -0
- package/lib/client.js +353 -69
- package/lib/index.js +3 -1
- 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 +1 -1
- package/lib/types/client/locales.d.ts +1 -1
- package/lib/types/client/session-id-copy/SessionIdCopyAction.d.ts +11 -0
- package/lib/types/client/session-id-copy/index.d.ts +13 -0
- package/lib/types/types.d.ts +4 -0
- package/package.json +13 -12
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@ Adds a "ui-fortifier" tab in Settings to toggle every feature module of this plu
|
|
|
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
29
|
| open-dsh-folder | Adds an "Open .dsh folder" button next to "Open configuration file" at the top-right of the Settings page. |
|
package/README.zh.md
CHANGED
|
@@ -22,6 +22,8 @@ dsh plugin --profile web add dsh-ui-fortifier
|
|
|
22
22
|
|
|
23
23
|
| 功能 | 描述 |
|
|
24
24
|
| --- | --- |
|
|
25
|
+
| session-id-copy | 会话标题栏工具区提供复制会话 ID 按钮。 |
|
|
26
|
+
| compact-button | 输入框工具行左组右端提供压缩上下文按钮,等价于提交 `/compact` 指令。 |
|
|
25
27
|
| provider-label | 在模型选择按钮左侧显示当前选择的提供方。 |
|
|
26
28
|
| model-picker | 输入行模型选择器旁提供级联模型选择器(提供商 → 模型)。 |
|
|
27
29
|
| open-dsh-folder | 在设置页右上角「打开配置文件」旁增加「打开 .dsh 文件夹」。 |
|
package/lib/client.js
CHANGED
|
@@ -9,13 +9,13 @@ window.__ModuleLoader__.load({
|
|
|
9
9
|
let react = require("react");
|
|
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;max-width:520px;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}.t1_2kq_switch{box-sizing:border-box;background:var(--dsw-alias-border-l3);cursor:pointer;border:0;border-radius:10px;flex:none;width:36px;height:20px;padding:2px;position:relative}.t1_2kq_switchOn{background:var(--dsw-alias-brand-primary)}.t1_2kq_switch:disabled{cursor:default;opacity:.5}.t1_2kq_switch:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.t1_2kq_thumb{corner-shape:round;background:var(--dsw-alias-label-primary-foreground);border-radius:50%;width:16px;height:16px;transition:transform .12s;display:block}.t1_2kq_switchOn .t1_2kq_thumb{transform:translate(16px)}";
|
|
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 = {
|
|
@@ -74,6 +74,8 @@ window.__ModuleLoader__.load({
|
|
|
74
74
|
"config.open-dsh-folder": "Settings top-right - Open .dsh folder",
|
|
75
75
|
"config.settings-frame": "Settings panel - Drag and resize",
|
|
76
76
|
"config.model-picker": "Input - Cascading model picker",
|
|
77
|
+
"config.session-id-copy": "Session header - Copy session ID",
|
|
78
|
+
"config.compact-button": "Input left group - Compact context",
|
|
77
79
|
openDshFolder: "Open .dsh folder",
|
|
78
80
|
"openDshFolder.error": "Could not open the .dsh folder",
|
|
79
81
|
"openDshFolder.pathLabel": "Path: ",
|
|
@@ -90,7 +92,14 @@ window.__ModuleLoader__.load({
|
|
|
90
92
|
"modelPicker.loadError": "Failed to load models",
|
|
91
93
|
"modelPicker.retry": "Retry",
|
|
92
94
|
"modelPicker.provider": "Provider: {name}",
|
|
93
|
-
"modelPicker.model": "Model: {name}"
|
|
95
|
+
"modelPicker.model": "Model: {name}",
|
|
96
|
+
"sessionIdCopy.action": "Copy Session ID",
|
|
97
|
+
"sessionIdCopy.hint": "Session ID: {id}",
|
|
98
|
+
"sessionIdCopy.copied": "Copied",
|
|
99
|
+
"compactButton.action": "Compact context",
|
|
100
|
+
"compactButton.confirmTitle": "Compact context",
|
|
101
|
+
"compactButton.confirmText": "Confirm compaction?",
|
|
102
|
+
"compactButton.confirm": "Confirm"
|
|
94
103
|
};
|
|
95
104
|
/** 中文文案。 */
|
|
96
105
|
const zh = {
|
|
@@ -100,6 +109,8 @@ window.__ModuleLoader__.load({
|
|
|
100
109
|
"config.open-dsh-folder": "设置右上角 - 打开 .dsh 文件夹",
|
|
101
110
|
"config.settings-frame": "设置面板 - 拖动与缩放",
|
|
102
111
|
"config.model-picker": "输入框 - 级联模型选择器",
|
|
112
|
+
"config.session-id-copy": "会话标题栏 - 复制 Session ID",
|
|
113
|
+
"config.compact-button": "输入框左组 - 压缩上下文",
|
|
103
114
|
openDshFolder: "打开 .dsh 文件夹",
|
|
104
115
|
"openDshFolder.error": "无法打开 .dsh 文件夹",
|
|
105
116
|
"openDshFolder.pathLabel": "路径:",
|
|
@@ -116,7 +127,14 @@ window.__ModuleLoader__.load({
|
|
|
116
127
|
"modelPicker.loadError": "模型加载失败",
|
|
117
128
|
"modelPicker.retry": "重试",
|
|
118
129
|
"modelPicker.provider": "提供商:{name}",
|
|
119
|
-
"modelPicker.model": "模型:{name}"
|
|
130
|
+
"modelPicker.model": "模型:{name}",
|
|
131
|
+
"sessionIdCopy.action": "复制 Session ID",
|
|
132
|
+
"sessionIdCopy.hint": "Session ID: {id}",
|
|
133
|
+
"sessionIdCopy.copied": "已复制",
|
|
134
|
+
"compactButton.action": "压缩上下文",
|
|
135
|
+
"compactButton.confirmTitle": "压缩上下文",
|
|
136
|
+
"compactButton.confirmText": "确认压缩?",
|
|
137
|
+
"compactButton.confirm": "确认"
|
|
120
138
|
};
|
|
121
139
|
//#endregion
|
|
122
140
|
//#region src/client/settings/index.ts
|
|
@@ -180,13 +198,13 @@ window.__ModuleLoader__.load({
|
|
|
180
198
|
}
|
|
181
199
|
//#endregion
|
|
182
200
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\provider-label\ProviderLabel.module.css.mjs
|
|
183
|
-
const css$
|
|
184
|
-
const tagId$
|
|
185
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
201
|
+
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}";
|
|
202
|
+
const tagId$5 = "dsh-ui-fortifier/ProviderLabel.module.css";
|
|
203
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$5) + "]") === null) {
|
|
186
204
|
const tag = document.createElement("style");
|
|
187
205
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
188
|
-
tag.dataset.pluginCss = tagId$
|
|
189
|
-
tag.textContent = css$
|
|
206
|
+
tag.dataset.pluginCss = tagId$5;
|
|
207
|
+
tag.textContent = css$5;
|
|
190
208
|
document.head.appendChild(tag);
|
|
191
209
|
}
|
|
192
210
|
var ProviderLabel_module_css_default = { "label": "LjXNpG_label" };
|
|
@@ -194,7 +212,7 @@ window.__ModuleLoader__.load({
|
|
|
194
212
|
//#region src/client/provider-label/ProviderLabel.tsx
|
|
195
213
|
function ProviderLabel(props) {
|
|
196
214
|
const provider = props.useDirectory((value) => value).current?.provider;
|
|
197
|
-
if (provider
|
|
215
|
+
if (!provider) return null;
|
|
198
216
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
199
217
|
className: ProviderLabel_module_css_default.label,
|
|
200
218
|
title: provider,
|
|
@@ -218,13 +236,13 @@ window.__ModuleLoader__.load({
|
|
|
218
236
|
}
|
|
219
237
|
//#endregion
|
|
220
238
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\open-dsh-folder\OpenDshFolderAction.module.css.mjs
|
|
221
|
-
const css$
|
|
222
|
-
const tagId$
|
|
223
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
239
|
+
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}";
|
|
240
|
+
const tagId$4 = "dsh-ui-fortifier/OpenDshFolderAction.module.css";
|
|
241
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
224
242
|
const tag = document.createElement("style");
|
|
225
243
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
226
|
-
tag.dataset.pluginCss = tagId$
|
|
227
|
-
tag.textContent = css$
|
|
244
|
+
tag.dataset.pluginCss = tagId$4;
|
|
245
|
+
tag.textContent = css$4;
|
|
228
246
|
document.head.appendChild(tag);
|
|
229
247
|
}
|
|
230
248
|
var OpenDshFolderAction_module_css_default = {
|
|
@@ -239,11 +257,11 @@ window.__ModuleLoader__.load({
|
|
|
239
257
|
* @returns 操作按钮及其结果提示。
|
|
240
258
|
*/
|
|
241
259
|
function OpenDshFolderAction(props) {
|
|
242
|
-
const
|
|
260
|
+
const t = props.t;
|
|
243
261
|
const [state, setState] = (0, react.useState)({ kind: "idle" });
|
|
244
262
|
const open = async () => {
|
|
245
263
|
setState({ kind: "opening" });
|
|
246
|
-
const result = await openDshFolder();
|
|
264
|
+
const result = await props.openDshFolder();
|
|
247
265
|
if (!result.ok) {
|
|
248
266
|
setState({ kind: "error" });
|
|
249
267
|
return;
|
|
@@ -281,7 +299,7 @@ window.__ModuleLoader__.load({
|
|
|
281
299
|
//#endregion
|
|
282
300
|
//#region src/client/open-dsh-folder/index.ts
|
|
283
301
|
/** 本模块文案命名空间(与 host 侧一致)。 */
|
|
284
|
-
const NS$
|
|
302
|
+
const NS$2 = "ui-fortifier";
|
|
285
303
|
/**
|
|
286
304
|
* 注册「打开 .dsh 文件夹」到设置页右上角操作区,仅在回环连接下注册。
|
|
287
305
|
* @param ctx - 需已提供 slots/connection 的客户端上下文。
|
|
@@ -295,19 +313,19 @@ window.__ModuleLoader__.load({
|
|
|
295
313
|
name: "settings.action",
|
|
296
314
|
id: "open-dsh-folder",
|
|
297
315
|
order: 1,
|
|
298
|
-
locale: NS$
|
|
316
|
+
locale: NS$2,
|
|
299
317
|
inject: () => ({ openDshFolder })
|
|
300
318
|
}, OpenDshFolderAction));
|
|
301
319
|
}
|
|
302
320
|
//#endregion
|
|
303
321
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\settings-frame\SettingsFrameEnhancer.module.css.mjs
|
|
304
|
-
const css$
|
|
305
|
-
const tagId$
|
|
306
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$
|
|
322
|
+
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)}";
|
|
323
|
+
const tagId$3 = "dsh-ui-fortifier/SettingsFrameEnhancer.module.css";
|
|
324
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$3) + "]") === null) {
|
|
307
325
|
const tag = document.createElement("style");
|
|
308
326
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
309
|
-
tag.dataset.pluginCss = tagId$
|
|
310
|
-
tag.textContent = css$
|
|
327
|
+
tag.dataset.pluginCss = tagId$3;
|
|
328
|
+
tag.textContent = css$3;
|
|
311
329
|
document.head.appendChild(tag);
|
|
312
330
|
}
|
|
313
331
|
var SettingsFrameEnhancer_module_css_default = {
|
|
@@ -332,7 +350,7 @@ window.__ModuleLoader__.load({
|
|
|
332
350
|
/** 读取持久化的面板几何;缺失或损坏返回 undefined。 */
|
|
333
351
|
function readFrameGeometry() {
|
|
334
352
|
const raw = localStorage.getItem(FRAME_STORAGE_KEY);
|
|
335
|
-
if (raw
|
|
353
|
+
if (!raw) return void 0;
|
|
336
354
|
try {
|
|
337
355
|
const parsed = JSON.parse(raw);
|
|
338
356
|
if (typeof parsed.left === "number" && Number.isFinite(parsed.left) && typeof parsed.top === "number" && Number.isFinite(parsed.top) && typeof parsed.width === "number" && Number.isFinite(parsed.width) && typeof parsed.height === "number" && Number.isFinite(parsed.height)) return parsed;
|
|
@@ -431,16 +449,16 @@ window.__ModuleLoader__.load({
|
|
|
431
449
|
const [headerRow, setHeaderRow] = (0, react.useState)(null);
|
|
432
450
|
(0, react.useEffect)(() => {
|
|
433
451
|
const anchor = anchorRef.current;
|
|
434
|
-
if (anchor
|
|
452
|
+
if (!anchor) return;
|
|
435
453
|
const dialog = anchor.closest("[role=\"dialog\"]");
|
|
436
454
|
if (!(dialog instanceof HTMLElement)) return;
|
|
437
455
|
const rect = dialog.getBoundingClientRect();
|
|
438
456
|
const saved = readFrameGeometry();
|
|
439
457
|
dialog.style.position = "fixed";
|
|
440
|
-
dialog.style.left = `${saved
|
|
441
|
-
dialog.style.top = `${saved
|
|
442
|
-
dialog.style.width = `${saved
|
|
443
|
-
dialog.style.height = `${saved
|
|
458
|
+
dialog.style.left = `${saved ? saved.left : rect.left}px`;
|
|
459
|
+
dialog.style.top = `${saved ? saved.top : rect.top}px`;
|
|
460
|
+
dialog.style.width = `${saved ? saved.width : rect.width}px`;
|
|
461
|
+
dialog.style.height = `${saved ? saved.height : rect.height}px`;
|
|
444
462
|
dialog.style.margin = "0";
|
|
445
463
|
dialog.style.maxWidth = "none";
|
|
446
464
|
constrainToViewport(dialog);
|
|
@@ -450,7 +468,7 @@ window.__ModuleLoader__.load({
|
|
|
450
468
|
setHeaderRow(row instanceof HTMLElement ? row : null);
|
|
451
469
|
let windowResizeFrame = null;
|
|
452
470
|
const onWindowResize = () => {
|
|
453
|
-
if (windowResizeFrame
|
|
471
|
+
if (windowResizeFrame) return;
|
|
454
472
|
windowResizeFrame = requestAnimationFrame(() => {
|
|
455
473
|
windowResizeFrame = null;
|
|
456
474
|
constrainToViewport(dialog);
|
|
@@ -459,7 +477,7 @@ window.__ModuleLoader__.load({
|
|
|
459
477
|
};
|
|
460
478
|
window.addEventListener("resize", onWindowResize);
|
|
461
479
|
return () => {
|
|
462
|
-
if (windowResizeFrame
|
|
480
|
+
if (windowResizeFrame) {
|
|
463
481
|
cancelAnimationFrame(windowResizeFrame);
|
|
464
482
|
windowResizeFrame = null;
|
|
465
483
|
}
|
|
@@ -477,7 +495,7 @@ window.__ModuleLoader__.load({
|
|
|
477
495
|
}, []);
|
|
478
496
|
(0, react.useEffect)(() => {
|
|
479
497
|
const handle = dragHandleRef.current;
|
|
480
|
-
if (handle
|
|
498
|
+
if (!handle || !headerRow) return;
|
|
481
499
|
if (headerRow.firstChild === handle) return;
|
|
482
500
|
headerRow.insertBefore(handle, headerRow.firstChild);
|
|
483
501
|
}, [headerRow]);
|
|
@@ -488,7 +506,7 @@ window.__ModuleLoader__.load({
|
|
|
488
506
|
});
|
|
489
507
|
const frame = (0, react.useRef)(null);
|
|
490
508
|
const onDragPointerDown = (event) => {
|
|
491
|
-
if (panel
|
|
509
|
+
if (!panel) return;
|
|
492
510
|
event.preventDefault();
|
|
493
511
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
494
512
|
dragState.current = {
|
|
@@ -497,28 +515,28 @@ window.__ModuleLoader__.load({
|
|
|
497
515
|
};
|
|
498
516
|
};
|
|
499
517
|
const onDragPointerMove = (event) => {
|
|
500
|
-
if (dragState.current
|
|
518
|
+
if (!dragState.current) return;
|
|
501
519
|
latest.current = {
|
|
502
520
|
x: event.clientX,
|
|
503
521
|
y: event.clientY
|
|
504
522
|
};
|
|
505
523
|
frame.current ??= requestAnimationFrame(() => {
|
|
506
524
|
frame.current = null;
|
|
507
|
-
if (panel
|
|
525
|
+
if (!panel || !dragState.current) return;
|
|
508
526
|
panel.style.left = `${latest.current.x - dragState.current.offsetX}px`;
|
|
509
527
|
panel.style.top = `${latest.current.y - dragState.current.offsetY}px`;
|
|
510
528
|
constrainPanel(panel);
|
|
511
529
|
});
|
|
512
530
|
};
|
|
513
531
|
const onDragPointerUp = (event) => {
|
|
514
|
-
if (dragState.current
|
|
515
|
-
if (frame.current
|
|
532
|
+
if (!dragState.current) return;
|
|
533
|
+
if (frame.current) {
|
|
516
534
|
cancelAnimationFrame(frame.current);
|
|
517
535
|
frame.current = null;
|
|
518
536
|
}
|
|
519
537
|
dragState.current = null;
|
|
520
538
|
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
521
|
-
if (panel
|
|
539
|
+
if (!panel) return;
|
|
522
540
|
constrainPanel(panel);
|
|
523
541
|
persistGeometry(panel);
|
|
524
542
|
};
|
|
@@ -527,7 +545,7 @@ window.__ModuleLoader__.load({
|
|
|
527
545
|
const resizeMax = (0, react.useRef)(null);
|
|
528
546
|
const resizeFrame = (0, react.useRef)(null);
|
|
529
547
|
const onResizePointerDown = (event) => {
|
|
530
|
-
if (panel
|
|
548
|
+
if (!panel) return;
|
|
531
549
|
event.preventDefault();
|
|
532
550
|
event.stopPropagation();
|
|
533
551
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
@@ -545,14 +563,14 @@ window.__ModuleLoader__.load({
|
|
|
545
563
|
};
|
|
546
564
|
};
|
|
547
565
|
const onResizePointerMove = (event) => {
|
|
548
|
-
if (resizeOrigin.current
|
|
566
|
+
if (!resizeOrigin.current || !resizeBase.current || !resizeMax.current) return;
|
|
549
567
|
latest.current = {
|
|
550
568
|
x: event.clientX,
|
|
551
569
|
y: event.clientY
|
|
552
570
|
};
|
|
553
571
|
resizeFrame.current ??= requestAnimationFrame(() => {
|
|
554
572
|
resizeFrame.current = null;
|
|
555
|
-
if (panel
|
|
573
|
+
if (!panel || !resizeOrigin.current || !resizeBase.current || !resizeMax.current) return;
|
|
556
574
|
const width = clamp(resizeBase.current.width + (latest.current.x - resizeOrigin.current.x), MIN_WIDTH, Math.max(MIN_WIDTH, resizeMax.current.width));
|
|
557
575
|
const height = clamp(resizeBase.current.height + (latest.current.y - resizeOrigin.current.y), MIN_HEIGHT, Math.max(MIN_HEIGHT, resizeMax.current.height));
|
|
558
576
|
panel.style.width = `${width}px`;
|
|
@@ -561,15 +579,15 @@ window.__ModuleLoader__.load({
|
|
|
561
579
|
});
|
|
562
580
|
};
|
|
563
581
|
const onResizePointerUp = (event) => {
|
|
564
|
-
if (resizeOrigin.current
|
|
565
|
-
if (resizeFrame.current
|
|
582
|
+
if (!resizeOrigin.current) return;
|
|
583
|
+
if (resizeFrame.current) {
|
|
566
584
|
cancelAnimationFrame(resizeFrame.current);
|
|
567
585
|
resizeFrame.current = null;
|
|
568
586
|
}
|
|
569
587
|
resizeOrigin.current = null;
|
|
570
588
|
resizeBase.current = null;
|
|
571
589
|
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
572
|
-
if (panel
|
|
590
|
+
if (panel) persistGeometry(panel);
|
|
573
591
|
};
|
|
574
592
|
const dragHandle = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
575
593
|
ref: dragHandleRef,
|
|
@@ -597,14 +615,14 @@ window.__ModuleLoader__.load({
|
|
|
597
615
|
ref: anchorRef,
|
|
598
616
|
className: SettingsFrameEnhancer_module_css_default.hostAnchor
|
|
599
617
|
}),
|
|
600
|
-
headerRow
|
|
601
|
-
panel
|
|
618
|
+
headerRow && (0, react_dom.createPortal)(dragHandle, headerRow),
|
|
619
|
+
panel && (0, react_dom.createPortal)(resizeHandle, panel)
|
|
602
620
|
] });
|
|
603
621
|
}
|
|
604
622
|
//#endregion
|
|
605
623
|
//#region src/client/settings-frame/index.ts
|
|
606
624
|
/** 本模块文案命名空间(与 host 侧一致)。 */
|
|
607
|
-
const NS = "ui-fortifier";
|
|
625
|
+
const NS$1 = "ui-fortifier";
|
|
608
626
|
/**
|
|
609
627
|
* 注册「拖动位置/大小」增强到设置页右上角操作区。
|
|
610
628
|
* @param ctx - 需已提供 slots 的客户端上下文。
|
|
@@ -616,19 +634,19 @@ window.__ModuleLoader__.load({
|
|
|
616
634
|
name: "settings.action",
|
|
617
635
|
id: "settings-frame-enhancer",
|
|
618
636
|
order: 2,
|
|
619
|
-
locale: NS,
|
|
637
|
+
locale: NS$1,
|
|
620
638
|
inject: injected
|
|
621
639
|
}, SettingsFrameEnhancer));
|
|
622
640
|
}
|
|
623
641
|
//#endregion
|
|
624
642
|
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\model-picker\ModelPicker.module.css.mjs
|
|
625
|
-
const css = ".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;background:var(--dsw-specific-menu);--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;border-radius:16px;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}";
|
|
626
|
-
const tagId = "dsh-ui-fortifier/ModelPicker.module.css";
|
|
627
|
-
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
643
|
+
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;background:var(--dsw-specific-menu);--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;border-radius:16px;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}";
|
|
644
|
+
const tagId$2 = "dsh-ui-fortifier/ModelPicker.module.css";
|
|
645
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$2) + "]") === null) {
|
|
628
646
|
const tag = document.createElement("style");
|
|
629
647
|
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
630
|
-
tag.dataset.pluginCss = tagId;
|
|
631
|
-
tag.textContent = css;
|
|
648
|
+
tag.dataset.pluginCss = tagId$2;
|
|
649
|
+
tag.textContent = css$2;
|
|
632
650
|
document.head.appendChild(tag);
|
|
633
651
|
}
|
|
634
652
|
var ModelPicker_module_css_default = {
|
|
@@ -670,7 +688,7 @@ window.__ModuleLoader__.load({
|
|
|
670
688
|
* @param target - 目标元素,缺失(如已被搜索过滤掉)时不处理。
|
|
671
689
|
*/
|
|
672
690
|
function scrollIntoViewWithin(container, target) {
|
|
673
|
-
if (container
|
|
691
|
+
if (!container || !target) return;
|
|
674
692
|
const containerRect = container.getBoundingClientRect();
|
|
675
693
|
const targetRect = target.getBoundingClientRect();
|
|
676
694
|
if (targetRect.top < containerRect.top) {
|
|
@@ -683,7 +701,7 @@ window.__ModuleLoader__.load({
|
|
|
683
701
|
* 未定位态:隐藏但按原点参与布局,使首帧 offsetWidth/offsetHeight 为真实尺寸,
|
|
684
702
|
* 定位不存在时也不会闪现在原点(与官方 ModelSelect 同法)。
|
|
685
703
|
*/
|
|
686
|
-
const MEASURE_STYLE = {
|
|
704
|
+
const MEASURE_STYLE$1 = {
|
|
687
705
|
visibility: "hidden",
|
|
688
706
|
left: 0,
|
|
689
707
|
top: 0
|
|
@@ -707,7 +725,7 @@ window.__ModuleLoader__.load({
|
|
|
707
725
|
}
|
|
708
726
|
const place = () => {
|
|
709
727
|
const rect = anchorRef.current?.getBoundingClientRect();
|
|
710
|
-
if (rect
|
|
728
|
+
if (!rect) return;
|
|
711
729
|
const panel = panelRef.current;
|
|
712
730
|
const width = panel?.offsetWidth ?? 0;
|
|
713
731
|
const height = panel?.offsetHeight ?? 0;
|
|
@@ -725,7 +743,7 @@ window.__ModuleLoader__.load({
|
|
|
725
743
|
window.addEventListener("resize", place);
|
|
726
744
|
const panel = panelRef.current;
|
|
727
745
|
let observer = null;
|
|
728
|
-
if (typeof ResizeObserver !== "undefined" && panel
|
|
746
|
+
if (typeof ResizeObserver !== "undefined" && panel) {
|
|
729
747
|
observer = new ResizeObserver(place);
|
|
730
748
|
observer.observe(panel);
|
|
731
749
|
}
|
|
@@ -785,7 +803,7 @@ window.__ModuleLoader__.load({
|
|
|
785
803
|
const activeGroup = visibleGroups.find((group) => group.id === picker.provider) ?? visibleGroups[0];
|
|
786
804
|
const activeProvider = activeGroup?.id ?? null;
|
|
787
805
|
const activeModels = (0, react.useMemo)(() => {
|
|
788
|
-
if (activeGroup
|
|
806
|
+
if (!activeGroup) return [];
|
|
789
807
|
if (query === "") return activeGroup.models;
|
|
790
808
|
if (hasModelHit) return activeGroup.models.filter((model) => matchesQuery(model.name, query));
|
|
791
809
|
return activeGroup.models;
|
|
@@ -801,13 +819,13 @@ window.__ModuleLoader__.load({
|
|
|
801
819
|
return;
|
|
802
820
|
}
|
|
803
821
|
if (pendingCurrentScrollRef.current) {
|
|
804
|
-
if (currentModelRef.current
|
|
822
|
+
if (!currentModelRef.current) return;
|
|
805
823
|
scrollIntoViewWithin(modelsRef.current, currentModelRef.current);
|
|
806
824
|
pendingCurrentScrollRef.current = false;
|
|
807
825
|
return;
|
|
808
826
|
}
|
|
809
827
|
if (positionedRef.current) return;
|
|
810
|
-
if (currentProviderRef.current
|
|
828
|
+
if (!currentProviderRef.current && !currentModelRef.current) return;
|
|
811
829
|
scrollIntoViewWithin(providersRef.current, currentProviderRef.current);
|
|
812
830
|
scrollIntoViewWithin(modelsRef.current, currentModelRef.current);
|
|
813
831
|
positionedRef.current = true;
|
|
@@ -871,12 +889,12 @@ window.__ModuleLoader__.load({
|
|
|
871
889
|
return;
|
|
872
890
|
}
|
|
873
891
|
pendingCurrentScrollRef.current = false;
|
|
874
|
-
if (modelsRef.current
|
|
892
|
+
if (modelsRef.current) modelsRef.current.scrollTop = 0;
|
|
875
893
|
};
|
|
876
894
|
const chooseModel = (modelId) => {
|
|
877
895
|
if (activeProvider === null) return;
|
|
878
896
|
const model = activeGroup?.models.find((m) => m.id === modelId);
|
|
879
|
-
if (model
|
|
897
|
+
if (!model) return;
|
|
880
898
|
const selection = {
|
|
881
899
|
provider: activeProvider,
|
|
882
900
|
model: modelId,
|
|
@@ -960,7 +978,7 @@ window.__ModuleLoader__.load({
|
|
|
960
978
|
className: ModelPicker_module_css_default.menu,
|
|
961
979
|
role: "dialog",
|
|
962
980
|
"aria-label": t("modelPicker.trigger"),
|
|
963
|
-
style: position ?? MEASURE_STYLE,
|
|
981
|
+
style: position ?? MEASURE_STYLE$1,
|
|
964
982
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
965
983
|
className: ModelPicker_module_css_default.search,
|
|
966
984
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -1106,6 +1124,261 @@ window.__ModuleLoader__.load({
|
|
|
1106
1124
|
}, ModelPicker));
|
|
1107
1125
|
}
|
|
1108
1126
|
//#endregion
|
|
1127
|
+
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\session-id-copy\SessionIdCopyAction.module.css.mjs
|
|
1128
|
+
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}";
|
|
1129
|
+
const tagId$1 = "dsh-ui-fortifier/SessionIdCopyAction.module.css";
|
|
1130
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
|
|
1131
|
+
const tag = document.createElement("style");
|
|
1132
|
+
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
1133
|
+
tag.dataset.pluginCss = tagId$1;
|
|
1134
|
+
tag.textContent = css$1;
|
|
1135
|
+
document.head.appendChild(tag);
|
|
1136
|
+
}
|
|
1137
|
+
var SessionIdCopyAction_module_css_default = { "button": "i0sS3a_button" };
|
|
1138
|
+
//#endregion
|
|
1139
|
+
//#region src/client/session-id-copy/SessionIdCopyAction.tsx
|
|
1140
|
+
/**
|
|
1141
|
+
* session-id-copy 功能:会话标题栏的复制 Session ID 按钮。
|
|
1142
|
+
*/
|
|
1143
|
+
/**
|
|
1144
|
+
* 井号字形:官方图标库没有标识符类图标,故内联两竖两横的 # 描边。
|
|
1145
|
+
* 与相邻的复制图标并排,让按钮直接表达「复制标识符」而非只有复制。
|
|
1146
|
+
* @returns 装饰性内联图标(按钮已有 aria-label)。
|
|
1147
|
+
*/
|
|
1148
|
+
function HashGlyph() {
|
|
1149
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1150
|
+
viewBox: "0 0 16 16",
|
|
1151
|
+
fill: "none",
|
|
1152
|
+
"aria-hidden": "true",
|
|
1153
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1154
|
+
d: "M6.2 2.2 4.9 13.8M11.1 2.2 9.8 13.8M2.6 5.6h11.2M2.2 10.4h11.2",
|
|
1155
|
+
stroke: "currentColor",
|
|
1156
|
+
strokeWidth: "1.4",
|
|
1157
|
+
strokeLinecap: "round"
|
|
1158
|
+
})
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
/**
|
|
1162
|
+
* 渲染复制 Session ID 的图标按钮:悬停提示直接给出会话 ID,点击写入剪贴板,
|
|
1163
|
+
* 成功后按钮短暂换成对勾。
|
|
1164
|
+
* @param props - owner 参数(含当前会话 ID)与文案。
|
|
1165
|
+
* @returns 会话标题栏工具区的复制按钮。
|
|
1166
|
+
*/
|
|
1167
|
+
function SessionIdCopyAction(props) {
|
|
1168
|
+
const t = props.t;
|
|
1169
|
+
const id = String(props.sessionId);
|
|
1170
|
+
const [copied, setCopied] = (0, react.useState)(false);
|
|
1171
|
+
const pending = (0, react.useRef)(false);
|
|
1172
|
+
const timer = (0, react.useRef)(null);
|
|
1173
|
+
const epoch = (0, react.useRef)(0);
|
|
1174
|
+
(0, react.useEffect)(() => () => {
|
|
1175
|
+
epoch.current += 1;
|
|
1176
|
+
pending.current = false;
|
|
1177
|
+
if (timer.current) clearTimeout(timer.current);
|
|
1178
|
+
}, []);
|
|
1179
|
+
const copy = () => {
|
|
1180
|
+
if (copied || pending.current) return;
|
|
1181
|
+
const started = epoch.current;
|
|
1182
|
+
pending.current = true;
|
|
1183
|
+
(0, _deepseek_ai_dsh_client_ui_primitives.writeClipboard)(id).then((accepted) => {
|
|
1184
|
+
if (started !== epoch.current) return;
|
|
1185
|
+
pending.current = false;
|
|
1186
|
+
if (!accepted) return;
|
|
1187
|
+
setCopied(true);
|
|
1188
|
+
timer.current = window.setTimeout(() => {
|
|
1189
|
+
timer.current = null;
|
|
1190
|
+
setCopied(false);
|
|
1191
|
+
}, 1e3);
|
|
1192
|
+
});
|
|
1193
|
+
};
|
|
1194
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1195
|
+
label: copied ? t("sessionIdCopy.copied") : t("sessionIdCopy.hint", { id }),
|
|
1196
|
+
side: "bottom",
|
|
1197
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1198
|
+
type: "button",
|
|
1199
|
+
className: SessionIdCopyAction_module_css_default.button,
|
|
1200
|
+
"aria-label": t("sessionIdCopy.action"),
|
|
1201
|
+
onClick: copy,
|
|
1202
|
+
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCheckOutline16, {}) : /* @__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.IconCopyOutline16, {})] })
|
|
1203
|
+
})
|
|
1204
|
+
});
|
|
1205
|
+
}
|
|
1206
|
+
//#endregion
|
|
1207
|
+
//#region src/client/session-id-copy/index.ts
|
|
1208
|
+
/** 本模块文案命名空间(与 host 侧一致)。 */
|
|
1209
|
+
const NS = "ui-fortifier";
|
|
1210
|
+
/**
|
|
1211
|
+
* 注册复制会话 ID 按钮到会话标题栏工具区(list 槽,追加式;order -20 排在最左,
|
|
1212
|
+
* 位于「在本地打开」按钮之前)。官方三点菜单的菜单项为硬编码、无插槽,
|
|
1213
|
+
* 故本功能以相邻按钮而非菜单项实现。
|
|
1214
|
+
* @param ctx - 需已提供 slots/locale 的客户端上下文。
|
|
1215
|
+
* @returns 停止注入并卸载注册的 disposer。
|
|
1216
|
+
*/
|
|
1217
|
+
function installSessionIdCopy(ctx) {
|
|
1218
|
+
return ctx.slots.inject("conversation.session.header.utilities", () => ctx.slots.register({
|
|
1219
|
+
name: "conversation.session.header.utilities",
|
|
1220
|
+
id: "session-id-copy",
|
|
1221
|
+
order: -20,
|
|
1222
|
+
locale: NS
|
|
1223
|
+
}, SessionIdCopyAction));
|
|
1224
|
+
}
|
|
1225
|
+
//#endregion
|
|
1226
|
+
//#region \0dsh-css:D:\data\code\deepseek-harness\packages\my\dsh-ui-fortifier\src\client\compact-button\CompactContextButton.module.css.mjs
|
|
1227
|
+
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;background:var(--dsw-specific-menu);max-width:min(260px,100vw - 32px);box-shadow:var(--dsw-elevation-prominent);color:var(--dsw-alias-label-primary);border-radius:12px;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}";
|
|
1228
|
+
const tagId = "dsh-ui-fortifier/CompactContextButton.module.css";
|
|
1229
|
+
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
|
|
1230
|
+
const tag = document.createElement("style");
|
|
1231
|
+
tag.dataset.plugin = "dsh-ui-fortifier";
|
|
1232
|
+
tag.dataset.pluginCss = tagId;
|
|
1233
|
+
tag.textContent = css;
|
|
1234
|
+
document.head.appendChild(tag);
|
|
1235
|
+
}
|
|
1236
|
+
var CompactContextButton_module_css_default = {
|
|
1237
|
+
"button": "zxJg-q_button",
|
|
1238
|
+
"glyph": "zxJg-q_glyph",
|
|
1239
|
+
"popover": "zxJg-q_popover",
|
|
1240
|
+
"popoverText": "zxJg-q_popoverText",
|
|
1241
|
+
"root": "zxJg-q_root"
|
|
1242
|
+
};
|
|
1243
|
+
//#endregion
|
|
1244
|
+
//#region src/client/compact-button/CompactContextButton.tsx
|
|
1245
|
+
/**
|
|
1246
|
+
* compact-button 功能:输入框工具行左组右端的压缩上下文按钮。
|
|
1247
|
+
*/
|
|
1248
|
+
/** 气泡与按钮之间的间距。 */
|
|
1249
|
+
const POPOVER_GAP = 8;
|
|
1250
|
+
/** 气泡与视口边缘保留的距离。 */
|
|
1251
|
+
const POPOVER_MARGIN = 12;
|
|
1252
|
+
const MEASURE_STYLE = {
|
|
1253
|
+
visibility: "hidden",
|
|
1254
|
+
left: 0,
|
|
1255
|
+
top: 0
|
|
1256
|
+
};
|
|
1257
|
+
/**
|
|
1258
|
+
* 压缩字形:官方图标库没有压缩语义的字形(`IconApiOutline14` 是终端提示符、
|
|
1259
|
+
* `IconEnhanceOutline16` 是四条段落横线,在此都会误读),故内联字形,与
|
|
1260
|
+
* `session-id-copy` 因官方无井号而内联 `HashGlyph` 同一做法。字形由用户提供。
|
|
1261
|
+
* @returns 装饰性内联图标(按钮已有 aria-label)。
|
|
1262
|
+
*/ function CompressGlyph() {
|
|
1263
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1264
|
+
className: CompactContextButton_module_css_default.glyph,
|
|
1265
|
+
viewBox: "0 0 1024 1024",
|
|
1266
|
+
"aria-hidden": "true",
|
|
1267
|
+
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" })
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
/**
|
|
1271
|
+
* 渲染压缩上下文按钮:点击先弹出确认气泡,气泡内确认后才提交 `/compact` 指令;
|
|
1272
|
+
* 点气泡外或按 Escape 取消。回合运行中与提交等待期间按钮禁用。
|
|
1273
|
+
* @param props - 会话标准套件、本地化文案与注入的压缩回调。
|
|
1274
|
+
* @returns 工具行左组右端的图标按钮与确认气泡。
|
|
1275
|
+
*/
|
|
1276
|
+
function CompactContextButton(props) {
|
|
1277
|
+
const running = props.useSession((snapshot) => snapshot.running);
|
|
1278
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
1279
|
+
const [pending, setPending] = (0, react.useState)(false);
|
|
1280
|
+
const rootRef = (0, react.useRef)(null);
|
|
1281
|
+
const panelRef = (0, react.useRef)(null);
|
|
1282
|
+
const alive = (0, react.useRef)(true);
|
|
1283
|
+
const position = (0, _deepseek_ai_dsh_client_ui_primitives.useAnchoredPosition)({
|
|
1284
|
+
open,
|
|
1285
|
+
anchorRef: rootRef,
|
|
1286
|
+
panelRef,
|
|
1287
|
+
side: "top",
|
|
1288
|
+
gap: POPOVER_GAP,
|
|
1289
|
+
margin: POPOVER_MARGIN
|
|
1290
|
+
});
|
|
1291
|
+
(0, _deepseek_ai_dsh_client_ui_primitives.useDismissOnOutsidePointer)(rootRef, open, setOpen, panelRef);
|
|
1292
|
+
(0, react.useEffect)(() => {
|
|
1293
|
+
alive.current = true;
|
|
1294
|
+
return () => {
|
|
1295
|
+
alive.current = false;
|
|
1296
|
+
};
|
|
1297
|
+
}, []);
|
|
1298
|
+
(0, react.useEffect)(() => {
|
|
1299
|
+
if (running) setOpen(false);
|
|
1300
|
+
}, [running]);
|
|
1301
|
+
(0, react.useEffect)(() => {
|
|
1302
|
+
if (!open) return;
|
|
1303
|
+
const onKeyDown = (event) => {
|
|
1304
|
+
if (event.key === "Escape") setOpen(false);
|
|
1305
|
+
};
|
|
1306
|
+
document.addEventListener("keydown", onKeyDown);
|
|
1307
|
+
return () => {
|
|
1308
|
+
document.removeEventListener("keydown", onKeyDown);
|
|
1309
|
+
};
|
|
1310
|
+
}, [open]);
|
|
1311
|
+
const compact = () => {
|
|
1312
|
+
if (pending) return;
|
|
1313
|
+
setOpen(false);
|
|
1314
|
+
setPending(true);
|
|
1315
|
+
const settle = () => {
|
|
1316
|
+
if (alive.current) setPending(false);
|
|
1317
|
+
};
|
|
1318
|
+
props.compact().then(settle, settle);
|
|
1319
|
+
};
|
|
1320
|
+
const disabled = running || pending;
|
|
1321
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1322
|
+
ref: rootRef,
|
|
1323
|
+
className: CompactContextButton_module_css_default.root,
|
|
1324
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Tooltip, {
|
|
1325
|
+
label: props.t("compactButton.action"),
|
|
1326
|
+
side: "top",
|
|
1327
|
+
delayMs: 500,
|
|
1328
|
+
disabled: open,
|
|
1329
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1330
|
+
type: "button",
|
|
1331
|
+
className: CompactContextButton_module_css_default.button,
|
|
1332
|
+
"aria-label": props.t("compactButton.action"),
|
|
1333
|
+
"aria-haspopup": "dialog",
|
|
1334
|
+
"aria-expanded": open,
|
|
1335
|
+
disabled,
|
|
1336
|
+
onMouseDown: (event) => {
|
|
1337
|
+
event.preventDefault();
|
|
1338
|
+
},
|
|
1339
|
+
onClick: () => {
|
|
1340
|
+
setOpen((value) => !value);
|
|
1341
|
+
},
|
|
1342
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CompressGlyph, {})
|
|
1343
|
+
})
|
|
1344
|
+
}), open && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1345
|
+
ref: panelRef,
|
|
1346
|
+
className: CompactContextButton_module_css_default.popover,
|
|
1347
|
+
role: "dialog",
|
|
1348
|
+
"aria-label": props.t("compactButton.confirmTitle"),
|
|
1349
|
+
style: position ?? MEASURE_STYLE,
|
|
1350
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1351
|
+
className: CompactContextButton_module_css_default.popoverText,
|
|
1352
|
+
children: props.t("compactButton.confirmText")
|
|
1353
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
|
|
1354
|
+
variant: "primary",
|
|
1355
|
+
size: "sm",
|
|
1356
|
+
disabled,
|
|
1357
|
+
onClick: compact,
|
|
1358
|
+
children: props.t("compactButton.confirm")
|
|
1359
|
+
})]
|
|
1360
|
+
}), document.body)]
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
//#endregion
|
|
1364
|
+
//#region src/client/compact-button/index.ts
|
|
1365
|
+
/**
|
|
1366
|
+
* 注册压缩上下文按钮到 conversation.input.left。
|
|
1367
|
+
* @param ctx - 需已提供 slots 与 remote.commands 的客户端上下文。
|
|
1368
|
+
* @returns 停止注入并卸载注册的 disposer。
|
|
1369
|
+
*/
|
|
1370
|
+
function installCompactButton(ctx) {
|
|
1371
|
+
return ctx.slots.inject("conversation.input.left", () => ctx.slots.register({
|
|
1372
|
+
name: "conversation.input.left",
|
|
1373
|
+
id: "compact-button",
|
|
1374
|
+
order: 100,
|
|
1375
|
+
locale: "ui-fortifier",
|
|
1376
|
+
inject: (sessionId) => ({ compact: async () => {
|
|
1377
|
+
await ctx.remote.commands.execute(sessionId, "/compact", []);
|
|
1378
|
+
} })
|
|
1379
|
+
}, CompactContextButton));
|
|
1380
|
+
}
|
|
1381
|
+
//#endregion
|
|
1109
1382
|
//#region src/client/index.ts
|
|
1110
1383
|
/** 功能模块清单:字段名(settings 开关 key) → 模块安装面。 */
|
|
1111
1384
|
const modules = {
|
|
@@ -1124,10 +1397,20 @@ window.__ModuleLoader__.load({
|
|
|
1124
1397
|
"model-picker": {
|
|
1125
1398
|
module: installModelPicker,
|
|
1126
1399
|
dispose: void 0
|
|
1400
|
+
},
|
|
1401
|
+
"session-id-copy": {
|
|
1402
|
+
module: installSessionIdCopy,
|
|
1403
|
+
dispose: void 0
|
|
1404
|
+
},
|
|
1405
|
+
"compact-button": {
|
|
1406
|
+
module: installCompactButton,
|
|
1407
|
+
dispose: void 0
|
|
1127
1408
|
}
|
|
1128
1409
|
};
|
|
1129
|
-
/**
|
|
1410
|
+
/** 设置页开关行的显示顺序:按各模块在界面上的位置,从会话标题栏到输入行再到设置页。 */
|
|
1130
1411
|
const MODULE_ORDER = [
|
|
1412
|
+
"session-id-copy",
|
|
1413
|
+
"compact-button",
|
|
1131
1414
|
"provider-label",
|
|
1132
1415
|
"model-picker",
|
|
1133
1416
|
"open-dsh-folder",
|
|
@@ -1141,7 +1424,8 @@ window.__ModuleLoader__.load({
|
|
|
1141
1424
|
"connection",
|
|
1142
1425
|
"sessions",
|
|
1143
1426
|
"remote",
|
|
1144
|
-
"remote.session"
|
|
1427
|
+
"remote.session",
|
|
1428
|
+
"remote.commands"
|
|
1145
1429
|
];
|
|
1146
1430
|
/**
|
|
1147
1431
|
* 客户端插件体:注册设置页并据开关状态挂载各功能模块。
|
package/lib/index.js
CHANGED
|
@@ -161,7 +161,9 @@ const Config = z.object({
|
|
|
161
161
|
"provider-label": z.boolean().default(true),
|
|
162
162
|
"open-dsh-folder": z.boolean().default(true),
|
|
163
163
|
"settings-frame": z.boolean().default(true),
|
|
164
|
-
"model-picker": z.boolean().default(true)
|
|
164
|
+
"model-picker": z.boolean().default(true),
|
|
165
|
+
"session-id-copy": z.boolean().default(true),
|
|
166
|
+
"compact-button": z.boolean().default(true)
|
|
165
167
|
});
|
|
166
168
|
/**
|
|
167
169
|
* 注册功能开关的 settings 命名空间并暴露打开 .dsh 文件夹的 Remote 服务。
|
|
@@ -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
|
|
@@ -10,7 +10,7 @@ interface ModuleEntry {
|
|
|
10
10
|
}
|
|
11
11
|
/** 功能模块清单:字段名(settings 开关 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
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** dsh-ui-fortifier 的文案。 */
|
|
2
2
|
/** locale key。 */
|
|
3
|
-
export type UiFortifierLocaleKey = 'nav' | 'empty' | 'config.provider-label' | 'config.open-dsh-folder' | 'config.settings-frame' | 'config.model-picker' | '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';
|
|
3
|
+
export type UiFortifierLocaleKey = 'nav' | 'empty' | '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
|
/** 中文文案。 */
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
/** 槽位 owner 参数与本地化文案。 */
|
|
3
|
+
export type SessionIdCopyActionProps = PropsRuntime<'conversation.session.header.utilities'> & PropsLocale<'ui-fortifier'>;
|
|
4
|
+
/**
|
|
5
|
+
* 渲染复制 Session ID 的图标按钮:悬停提示直接给出会话 ID,点击写入剪贴板,
|
|
6
|
+
* 成功后按钮短暂换成对勾。
|
|
7
|
+
* @param props - owner 参数(含当前会话 ID)与文案。
|
|
8
|
+
* @returns 会话标题栏工具区的复制按钮。
|
|
9
|
+
*/
|
|
10
|
+
export declare function SessionIdCopyAction(props: SessionIdCopyActionProps): import("react").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=SessionIdCopyAction.d.ts.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* session-id-copy 功能:在会话标题栏工具区注册复制会话 ID 的按钮。
|
|
3
|
+
*/
|
|
4
|
+
import type { Context as ClientContext } from '@deepseek-ai/cordis';
|
|
5
|
+
/**
|
|
6
|
+
* 注册复制会话 ID 按钮到会话标题栏工具区(list 槽,追加式;order -20 排在最左,
|
|
7
|
+
* 位于「在本地打开」按钮之前)。官方三点菜单的菜单项为硬编码、无插槽,
|
|
8
|
+
* 故本功能以相邻按钮而非菜单项实现。
|
|
9
|
+
* @param ctx - 需已提供 slots/locale 的客户端上下文。
|
|
10
|
+
* @returns 停止注入并卸载注册的 disposer。
|
|
11
|
+
*/
|
|
12
|
+
export declare function installSessionIdCopy(ctx: ClientContext): () => void;
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
package/lib/types/types.d.ts
CHANGED
|
@@ -12,6 +12,10 @@ export interface Config {
|
|
|
12
12
|
'settings-frame': boolean;
|
|
13
13
|
/** 输入框右侧显示级联模型选择器(先选提供商、再选模型)。 */
|
|
14
14
|
'model-picker': boolean;
|
|
15
|
+
/** 会话标题栏显示复制会话 ID 按钮。 */
|
|
16
|
+
'session-id-copy': boolean;
|
|
17
|
+
/** 输入框工具行左组右端显示压缩上下文按钮。 */
|
|
18
|
+
'compact-button': boolean;
|
|
15
19
|
}
|
|
16
20
|
/** 打开 .dsh 文件夹的返回值。 */
|
|
17
21
|
export interface DshFolderOpenValue {
|
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.6.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"contributors": [
|
|
7
7
|
"pgnqukezrdxmhjso"
|
|
@@ -44,9 +44,9 @@
|
|
|
44
44
|
"lib/types/**/*.d.ts"
|
|
45
45
|
],
|
|
46
46
|
"peerDependencies": {
|
|
47
|
-
"@deepseek-ai/dsh-native-command": "^0.1.5-rc.2",
|
|
48
|
-
"@deepseek-ai/dsh-home-paths": "^0.1.5-rc.2",
|
|
49
47
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
48
|
+
"@deepseek-ai/dsh-home-paths": "^0.1.5-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-native-command": "^0.1.5-rc.2",
|
|
50
50
|
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.2",
|
|
51
51
|
"@deepseek-ai/schemastery": "^3.18.2"
|
|
52
52
|
},
|
|
@@ -55,23 +55,24 @@
|
|
|
55
55
|
"@types/react-dom": "~18.3.0",
|
|
56
56
|
"react": "^18.2.0",
|
|
57
57
|
"react-dom": "^18.2.0",
|
|
58
|
-
"@deepseek-ai/cordis": "^4.0.2",
|
|
59
58
|
"@deepseek-ai/dsh-api-remotes": "^0.1.5-rc.2",
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
59
|
+
"@deepseek-ai/dsh-api-session-controller": "^0.1.5-rc.2",
|
|
60
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
61
61
|
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-client-ui-conversation": "^0.1.5-rc.2",
|
|
62
63
|
"@deepseek-ai/dsh-client-ui-model-selection": "^0.1.5-rc.2",
|
|
63
64
|
"@deepseek-ai/dsh-client-ui-primitives": "^0.1.5-rc.2",
|
|
64
|
-
"@deepseek-ai/dsh-api-session-controller": "^0.1.5-rc.2",
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
66
65
|
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
67
66
|
"@deepseek-ai/dsh-client-ui-renderer": "^0.1.5-rc.2",
|
|
68
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
69
67
|
"@deepseek-ai/dsh-home-paths": "^0.1.5-rc.2",
|
|
70
|
-
"@deepseek-ai/dsh-
|
|
68
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-client-ui-session": "^0.1.5-rc.2",
|
|
71
71
|
"@deepseek-ai/dsh-native-command": "^0.1.5-rc.2",
|
|
72
|
-
"@deepseek-ai/dsh-settings": "^0.1.5-rc.2",
|
|
73
72
|
"@deepseek-ai/dsh-typert-protocol": "^0.1.5-rc.2",
|
|
74
|
-
"@deepseek-ai/schemastery": "^3.18.2"
|
|
73
|
+
"@deepseek-ai/schemastery": "^3.18.2",
|
|
74
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2",
|
|
75
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.2"
|
|
75
76
|
},
|
|
76
77
|
"dsh": {
|
|
77
78
|
"bundle": {
|
|
@@ -98,7 +99,7 @@
|
|
|
98
99
|
"pub": "pnpm run build && pnpm login --registry=https://registry.npmjs.org && pnpm publish --registry=https://registry.npmjs.org --no-git-checks",
|
|
99
100
|
"pack": "pnpm run build && pnpm pack --pack-destination lib",
|
|
100
101
|
"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%",
|
|
102
|
+
"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
103
|
"test-create": "pnpm dsh --profile pkgtest --from-default-profile web",
|
|
103
104
|
"test-start": "pnpm dsh --profile pkgtest --port 3081 --no-open"
|
|
104
105
|
}
|