dsh-desktop-enhance 0.2.5 → 0.2.6
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 +17 -5
- package/lib/client.js +482 -30
- package/lib/index.d.ts +37 -1
- package/lib/index.js +220 -15
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
# dsh-desktop-enhance
|
|
2
2
|
|
|
3
|
-
为 **DeepSeek Harness 桌面版**(DSH Desktop `0.2.
|
|
3
|
+
为 **DeepSeek Harness 桌面版**(DSH Desktop `0.2.1-rc.2`)补界面与效率增强能力的插件。**自用**。
|
|
4
|
+
|
|
5
|
+
## 功能列表
|
|
4
6
|
|
|
5
|
-
## 六个功能
|
|
6
7
|
|
|
7
8
|
### 页内查找
|
|
8
9
|
|
|
@@ -99,6 +100,16 @@ Web 版(浏览器里打开的那种)键位是 **`Cmd+Shift+.`** —— `Cmd+
|
|
|
99
100
|
- **折叠与展开**:点击顶栏可把整张卡片收起成一枚紧凑胶囊(`会话信息 · Skill N`),点击分节头可单独收起/展开该分节
|
|
100
101
|
- **全量 + 实时**:实时监听前端会话事件流,同时向 Host 查询完整会话日志基线,即使几百轮的长会话只加载了尾部窗口,第 1 轮注入的 Skill 也不会漏掉;被上下文压缩或裁剪替换掉的节点会自动剔除
|
|
101
102
|
|
|
103
|
+
### 工具管理
|
|
104
|
+
|
|
105
|
+
在插件设置卡片内以**可折叠前缀树**列出当前 DSH 注册的全部工具(跨全局层与所有 Agent Presets 全量扫描),并支持全局启停:
|
|
106
|
+
|
|
107
|
+
- **前缀分组与批量启停**:自动将有多个工具的前缀(如 `mcp`、`job`、`schedule`、`web`、`cordis`)收拢为可折叠分组,显示启用计数(如 `2/2`),支持一键「全部禁用 / 全部启用」整组工具;只有 1 个工具的普通名称(如 `working_directory`、`todo_write`)直接展示为单行条目,不套多余目录
|
|
108
|
+
- **实时搜索**:支持按工具名或描述关键词即时过滤
|
|
109
|
+
- **两层一致拦截**:被禁用的工具既从发给模型的 Prompt Tool Schemas 中隐藏(节省上下文 Token),又在执行守卫层(`ctx.tools.guard`)拒绝调用,跨会话持久化
|
|
110
|
+
- **总开关无损控制**:关闭「工具管理」总开关时立即放行所有工具,同时保留已保存的禁用列表;重新开启总开关即恢复生效
|
|
111
|
+
|
|
112
|
+
|
|
102
113
|
## 安装
|
|
103
114
|
|
|
104
115
|
从 npm 装:
|
|
@@ -128,15 +139,16 @@ dsh plugin --profile desktop update dsh-desktop-enhance
|
|
|
128
139
|
|
|
129
140
|
只改插件内容的话,**刷新页面即可**,不必重启。
|
|
130
141
|
|
|
131
|
-
> ⚠️ **例外:如果插件更新里改了「宿主半侧」(`src/index.ts` / `src/suggest/**`),必须重启 App** —— 刷新页面不够。此时设置卡片会直接把不可用的项**置灰**并提示你重启,而不是等你点了几次之后才报「设置没写进去」。**看到那句提示 = 重启即可解决。**
|
|
142
|
+
> ⚠️ **例外:如果插件更新里改了「宿主半侧」(`src/index.ts` / `src/suggest/**` / `src/session-info/**` / `src/tools-manager/**`),必须重启 App** —— 刷新页面不够。此时设置卡片会直接把不可用的项**置灰**并提示你重启,而不是等你点了几次之后才报「设置没写进去」。**看到那句提示 = 重启即可解决。**
|
|
132
143
|
|
|
133
144
|
## 开关
|
|
134
145
|
|
|
135
|
-
|
|
146
|
+
每个功能各有一个开关,在**本插件自己的页面**上:
|
|
136
147
|
|
|
137
148
|
> 侧栏 **插件** → 插件列表里选中 **`dsh-desktop-enhance`** → 页面里的 **「UI 增强」** 一栏
|
|
138
149
|
|
|
139
|
-
|
|
150
|
+
开关列表:**页内查找** / **轮次编号** / **压缩行高亮** / **建议** / **每步耗时** / **会话信息** / **工具管理**。默认全开,装完与之前行为一致,除非你自己去关。
|
|
151
|
+
|
|
140
152
|
|
|
141
153
|
「建议」关掉时,它那三个参数(模型 / 推理强度 / 指令模板)也会一并收起 —— 功能关着时它们不起作用。
|
|
142
154
|
|
package/lib/client.js
CHANGED
|
@@ -41,6 +41,21 @@ window.__ModuleLoader__.load({
|
|
|
41
41
|
"settings.stepDuration.hint": "紧跟每一行的文字显示这一步的开始时刻与耗时(如 14:32 · 23s):过程组头是整组、展开后的工具调用与思考行是它自己那一段;正在跑的那一行每秒更新",
|
|
42
42
|
"settings.sessionInfo": "会话信息",
|
|
43
43
|
"settings.sessionInfo.hint": "在主对话区右上角悬浮展示当前会话的信息看板(如已注入的 Skill、触发方式与轮次),点击条目可打开 Skill 预览",
|
|
44
|
+
"settings.toolsManager": "工具管理",
|
|
45
|
+
"settings.toolsManager.hint": "以可折叠前缀树列出全部已注册工具,支持单个或按前缀批量启停;被禁用的工具对模型不可见且拒绝执行,跨会话持久化",
|
|
46
|
+
"settings.disabledTools": "已禁用工具列表",
|
|
47
|
+
"settings.disabledTools.hint": "支持在下方工具树中勾选启停,或在目录未就绪时手动填写以逗号分隔的工具名",
|
|
48
|
+
"settings.disabledTools.placeholder": "输入要禁用的工具名(以逗号分隔,留空表示全部启用)",
|
|
49
|
+
"settings.tools.search": "搜索工具名或描述…",
|
|
50
|
+
"settings.tools.refresh": "刷新列表",
|
|
51
|
+
"settings.tools.enableAll": "全部启用",
|
|
52
|
+
"settings.tools.disableAll": "全部禁用",
|
|
53
|
+
"settings.tools.enable": "启用",
|
|
54
|
+
"settings.tools.disable": "禁用",
|
|
55
|
+
"settings.tools.enabled": "已启用",
|
|
56
|
+
"settings.tools.disabled": "已禁用",
|
|
57
|
+
"settings.tools.allDisabled": "全部已禁用",
|
|
58
|
+
"settings.tools.empty": "没有匹配的工具。",
|
|
44
59
|
"settings.suggestModel": "建议用哪个模型",
|
|
45
60
|
"settings.suggestModel.hint": "留空则跟随当前会话的模型;建议选一个非推理的轻量模型,否则每条建议都要等它想完",
|
|
46
61
|
"settings.suggestModel.follow": "跟随当前会话",
|
|
@@ -97,6 +112,21 @@ window.__ModuleLoader__.load({
|
|
|
97
112
|
"settings.stepDuration.hint": "Shows when each step started and how long it took, right after that row’s own text (e.g. 14:32 · 23s): the whole group on a process-group header, its own span on every expanded tool call and thinking row; running rows update every second",
|
|
98
113
|
"settings.sessionInfo": "Session info",
|
|
99
114
|
"settings.sessionInfo.hint": "Shows a floating Session Info inspector in the top-right corner of the conversation view (active skills, trigger source, and turn); click an item to open its skill preview",
|
|
115
|
+
"settings.toolsManager": "Tools manager",
|
|
116
|
+
"settings.toolsManager.hint": "Lists all registered tools as a collapsible prefix tree with individual and batch enable/disable controls; disabled tools are hidden from the model and denied at execution across sessions",
|
|
117
|
+
"settings.disabledTools": "Disabled tools",
|
|
118
|
+
"settings.disabledTools.hint": "Toggle tools in the prefix tree below, or enter comma-separated tool names when the catalog is unavailable",
|
|
119
|
+
"settings.disabledTools.placeholder": "Comma-separated tool names to disable (empty enables all)",
|
|
120
|
+
"settings.tools.search": "Search tool name or description…",
|
|
121
|
+
"settings.tools.refresh": "Refresh",
|
|
122
|
+
"settings.tools.enableAll": "Enable all",
|
|
123
|
+
"settings.tools.disableAll": "Disable all",
|
|
124
|
+
"settings.tools.enable": "Enable",
|
|
125
|
+
"settings.tools.disable": "Disable",
|
|
126
|
+
"settings.tools.enabled": "Enabled",
|
|
127
|
+
"settings.tools.disabled": "Disabled",
|
|
128
|
+
"settings.tools.allDisabled": "All disabled",
|
|
129
|
+
"settings.tools.empty": "No matching tools.",
|
|
100
130
|
"settings.suggestModel": "Model for suggestions",
|
|
101
131
|
"settings.suggestModel.hint": "Empty follows the current session model. Prefer a lightweight non-reasoning model, or every suggestion waits for it to finish thinking",
|
|
102
132
|
"settings.suggestModel.follow": "Follow the current session",
|
|
@@ -371,18 +401,25 @@ window.__ModuleLoader__.load({
|
|
|
371
401
|
//#region src/client/settings/gates.ts
|
|
372
402
|
const SETTINGS_NS = "desktop-enhance";
|
|
373
403
|
const PACKAGE_NAME = "dsh-desktop-enhance";
|
|
374
|
-
const
|
|
404
|
+
const SUGGEST_TEXT_FIELDS = [
|
|
375
405
|
"suggestModel",
|
|
376
406
|
"suggestReasoning",
|
|
377
407
|
"suggestPrompt"
|
|
378
408
|
];
|
|
409
|
+
const TEXT_FIELDS = [
|
|
410
|
+
"suggestModel",
|
|
411
|
+
"suggestReasoning",
|
|
412
|
+
"suggestPrompt",
|
|
413
|
+
"disabledTools"
|
|
414
|
+
];
|
|
379
415
|
const GATES = {
|
|
380
416
|
findBar: "data-desktop-enhance-off-find-bar",
|
|
381
417
|
turnPrefix: "data-desktop-enhance-off-turn-prefix",
|
|
382
418
|
compactionRow: "data-desktop-enhance-off-compaction-row",
|
|
383
419
|
suggest: "data-desktop-enhance-off-suggest",
|
|
384
420
|
stepDuration: "data-desktop-enhance-off-step-duration",
|
|
385
|
-
sessionInfo: "data-desktop-enhance-off-session-info"
|
|
421
|
+
sessionInfo: "data-desktop-enhance-off-session-info",
|
|
422
|
+
toolsManager: "data-desktop-enhance-off-tools-manager"
|
|
386
423
|
};
|
|
387
424
|
const FIELDS = [
|
|
388
425
|
"findBar",
|
|
@@ -390,7 +427,8 @@ window.__ModuleLoader__.load({
|
|
|
390
427
|
"compactionRow",
|
|
391
428
|
"suggest",
|
|
392
429
|
"stepDuration",
|
|
393
|
-
"sessionInfo"
|
|
430
|
+
"sessionInfo",
|
|
431
|
+
"toolsManager"
|
|
394
432
|
];
|
|
395
433
|
const ALL_FIELDS = [...FIELDS, ...TEXT_FIELDS];
|
|
396
434
|
function flagOn(value, field) {
|
|
@@ -419,7 +457,7 @@ window.__ModuleLoader__.load({
|
|
|
419
457
|
reasoning: "",
|
|
420
458
|
prompt: ""
|
|
421
459
|
};
|
|
422
|
-
for (const field of
|
|
460
|
+
for (const field of SUGGEST_TEXT_FIELDS) out[PREFERENCE_KEY[field]] = textOf(value, field);
|
|
423
461
|
return out;
|
|
424
462
|
}
|
|
425
463
|
function applyGates(value, root) {
|
|
@@ -457,6 +495,7 @@ window.__ModuleLoader__.load({
|
|
|
457
495
|
const SUGGEST_ROUTE = "/api/desktop-enhance/suggest";
|
|
458
496
|
const SUGGEST_MODELS_ROUTE = "/api/desktop-enhance/suggest-models";
|
|
459
497
|
const SESSION_INFO_ROUTE = "/api/desktop-enhance/session-info";
|
|
498
|
+
const TOOLS_ROUTE = "/api/desktop-enhance/tools";
|
|
460
499
|
//#endregion
|
|
461
500
|
//#region src/client/settings/catalog.ts
|
|
462
501
|
function parseModelCatalog(body) {
|
|
@@ -513,33 +552,40 @@ window.__ModuleLoader__.load({
|
|
|
513
552
|
const catalogCache = createCatalogCache();
|
|
514
553
|
const CACHE_MS = 3e4;
|
|
515
554
|
const SUGGEST_MODELS_URL = SUGGEST_MODELS_ROUTE;
|
|
555
|
+
const TOOLS_URL = TOOLS_ROUTE;
|
|
516
556
|
function createCatalogCache(now = () => Date.now()) {
|
|
517
557
|
const hits = new Map();
|
|
518
558
|
const pending = new Map();
|
|
519
|
-
return {
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
559
|
+
return {
|
|
560
|
+
invalidate(url) {
|
|
561
|
+
hits.delete(url);
|
|
562
|
+
pending.delete(url);
|
|
563
|
+
},
|
|
564
|
+
async get(url, fetchImpl) {
|
|
565
|
+
const hit = hits.get(url);
|
|
566
|
+
if (hit !== void 0 && now() - hit.at < 3e4) return hit.value;
|
|
567
|
+
const running = pending.get(url);
|
|
568
|
+
if (running !== void 0) return running;
|
|
569
|
+
const task = (async () => {
|
|
570
|
+
try {
|
|
571
|
+
const response = await fetchImpl(url, { method: "GET" });
|
|
572
|
+
if (!response.ok) return void 0;
|
|
573
|
+
const value = await response.json();
|
|
574
|
+
hits.set(url, {
|
|
575
|
+
at: now(),
|
|
576
|
+
value
|
|
577
|
+
});
|
|
578
|
+
return value;
|
|
579
|
+
} catch {
|
|
580
|
+
return;
|
|
581
|
+
} finally {
|
|
582
|
+
pending.delete(url);
|
|
583
|
+
}
|
|
584
|
+
})();
|
|
585
|
+
pending.set(url, task);
|
|
586
|
+
return task;
|
|
587
|
+
}
|
|
588
|
+
};
|
|
543
589
|
}
|
|
544
590
|
const ESCAPE_SEQUENCES = /\x1b\[[0-?]*[ -/]*[@-~]|\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)|\x1b[@-Z\\-_]/g;
|
|
545
591
|
const TAG_CHARACTERS = /[\u{E0000}-\u{E007F}]/u;
|
|
@@ -631,6 +677,196 @@ window.__ModuleLoader__.load({
|
|
|
631
677
|
};
|
|
632
678
|
}
|
|
633
679
|
//#endregion
|
|
680
|
+
//#region src/shared/tools-manager.ts
|
|
681
|
+
const DISABLED_TOOL_PREFIX = "tool is disabled by desktop-enhance:";
|
|
682
|
+
function compareCodeUnits(a, b) {
|
|
683
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
684
|
+
}
|
|
685
|
+
function parseDisabledTools(raw) {
|
|
686
|
+
const out = new Set();
|
|
687
|
+
if (typeof raw !== "string" || raw.length === 0) return out;
|
|
688
|
+
for (const piece of raw.split(/[\s,]+/)) {
|
|
689
|
+
const trimmed = piece.trim();
|
|
690
|
+
if (trimmed !== "") out.add(trimmed);
|
|
691
|
+
}
|
|
692
|
+
return out;
|
|
693
|
+
}
|
|
694
|
+
function formatDisabledTools(names) {
|
|
695
|
+
const unique = new Set();
|
|
696
|
+
for (const name of names) if (typeof name === "string") {
|
|
697
|
+
const trimmed = name.trim();
|
|
698
|
+
if (trimmed !== "") unique.add(trimmed);
|
|
699
|
+
}
|
|
700
|
+
return [...unique].sort(compareCodeUnits).join(",");
|
|
701
|
+
}
|
|
702
|
+
function splitToolName(name) {
|
|
703
|
+
const parts = name.split("__");
|
|
704
|
+
if (parts.length > 1) {
|
|
705
|
+
const result = [];
|
|
706
|
+
for (let i = 0; i < parts.length; i++) {
|
|
707
|
+
const part = parts[i];
|
|
708
|
+
if (part === void 0 || part === "") continue;
|
|
709
|
+
if (i === 0 || i === parts.length - 1) result.push(part);
|
|
710
|
+
else {
|
|
711
|
+
const sub = part.split("_").filter((s) => s !== "");
|
|
712
|
+
result.push(...sub);
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
return result.length > 0 ? result : [name];
|
|
716
|
+
}
|
|
717
|
+
const sub = name.split("_").filter((s) => s !== "");
|
|
718
|
+
return sub.length > 0 ? sub : [name];
|
|
719
|
+
}
|
|
720
|
+
function finalizeBranch(branch) {
|
|
721
|
+
const nodes = [];
|
|
722
|
+
for (const [, child] of branch.children) if (child.kind === "leaf") nodes.push(child);
|
|
723
|
+
else {
|
|
724
|
+
const children = finalizeBranch(child.branch);
|
|
725
|
+
const firstChild = children[0];
|
|
726
|
+
if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "leaf" && !child.prefix.startsWith("mcp")) {
|
|
727
|
+
nodes.push(firstChild);
|
|
728
|
+
continue;
|
|
729
|
+
}
|
|
730
|
+
if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "node") {
|
|
731
|
+
const sep = child.prefix === "mcp" ? "__" : "_";
|
|
732
|
+
nodes.push({
|
|
733
|
+
kind: "node",
|
|
734
|
+
prefix: firstChild.prefix,
|
|
735
|
+
label: `${child.label}${sep}${firstChild.label}`,
|
|
736
|
+
children: firstChild.children,
|
|
737
|
+
total: firstChild.total,
|
|
738
|
+
disabled: firstChild.disabled
|
|
739
|
+
});
|
|
740
|
+
continue;
|
|
741
|
+
}
|
|
742
|
+
let total = 0;
|
|
743
|
+
let disabled = 0;
|
|
744
|
+
for (const c of children) {
|
|
745
|
+
total += c.total;
|
|
746
|
+
disabled += c.kind === "leaf" ? c.disabledCount : c.disabled;
|
|
747
|
+
}
|
|
748
|
+
nodes.push({
|
|
749
|
+
kind: "node",
|
|
750
|
+
prefix: child.prefix,
|
|
751
|
+
label: child.label,
|
|
752
|
+
children,
|
|
753
|
+
total,
|
|
754
|
+
disabled
|
|
755
|
+
});
|
|
756
|
+
}
|
|
757
|
+
nodes.sort((a, b) => {
|
|
758
|
+
if (a.kind !== b.kind) return a.kind === "node" ? -1 : 1;
|
|
759
|
+
return compareCodeUnits(a.kind === "node" ? a.label : a.name, b.kind === "node" ? b.label : b.name);
|
|
760
|
+
});
|
|
761
|
+
return nodes;
|
|
762
|
+
}
|
|
763
|
+
function buildToolPrefixTree(tools, disabled, query = "") {
|
|
764
|
+
const needle = typeof query === "string" ? query.trim().toLowerCase() : "";
|
|
765
|
+
const filtered = needle === "" ? tools : tools.filter((t) => t.name.toLowerCase().includes(needle) || t.description.toLowerCase().includes(needle));
|
|
766
|
+
const root = { children: new Map() };
|
|
767
|
+
for (const tool of filtered) {
|
|
768
|
+
const segments = splitToolName(tool.name);
|
|
769
|
+
let current = root;
|
|
770
|
+
for (let i = 0; i < segments.length; i++) {
|
|
771
|
+
const seg = segments[i];
|
|
772
|
+
if (seg === void 0) continue;
|
|
773
|
+
if (i === segments.length - 1) {
|
|
774
|
+
const isOff = disabled.has(tool.name);
|
|
775
|
+
const leaf = {
|
|
776
|
+
kind: "leaf",
|
|
777
|
+
name: tool.name,
|
|
778
|
+
label: seg,
|
|
779
|
+
description: tool.description,
|
|
780
|
+
disabled: isOff,
|
|
781
|
+
total: 1,
|
|
782
|
+
disabledCount: isOff ? 1 : 0
|
|
783
|
+
};
|
|
784
|
+
const existing = current.children.get(seg);
|
|
785
|
+
if (existing !== void 0 && existing.kind === "branch") existing.branch.children.set(`__self__:${tool.name}`, leaf);
|
|
786
|
+
else current.children.set(seg, leaf);
|
|
787
|
+
} else {
|
|
788
|
+
let next = current.children.get(seg);
|
|
789
|
+
if (next === void 0) {
|
|
790
|
+
next = {
|
|
791
|
+
kind: "branch",
|
|
792
|
+
prefix: segments.slice(0, i + 1).join("_"),
|
|
793
|
+
label: seg,
|
|
794
|
+
branch: { children: new Map() }
|
|
795
|
+
};
|
|
796
|
+
current.children.set(seg, next);
|
|
797
|
+
} else if (next.kind === "leaf") {
|
|
798
|
+
const branch = { children: new Map() };
|
|
799
|
+
branch.children.set(`__self__:${next.name}`, next);
|
|
800
|
+
next = {
|
|
801
|
+
kind: "branch",
|
|
802
|
+
prefix: segments.slice(0, i + 1).join("_"),
|
|
803
|
+
label: seg,
|
|
804
|
+
branch
|
|
805
|
+
};
|
|
806
|
+
current.children.set(seg, next);
|
|
807
|
+
}
|
|
808
|
+
current = next.branch;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return finalizeBranch(root);
|
|
813
|
+
}
|
|
814
|
+
function collectNodeLeafNames(node) {
|
|
815
|
+
if (node.kind === "leaf") return [node.name];
|
|
816
|
+
const out = [];
|
|
817
|
+
for (const child of node.children) out.push(...collectNodeLeafNames(child));
|
|
818
|
+
return out;
|
|
819
|
+
}
|
|
820
|
+
function toggleToolInSet(current, toolName, nextDisabled) {
|
|
821
|
+
const next = new Set(current);
|
|
822
|
+
if (nextDisabled) next.add(toolName);
|
|
823
|
+
else next.delete(toolName);
|
|
824
|
+
return next;
|
|
825
|
+
}
|
|
826
|
+
function toggleNodeInSet(current, node) {
|
|
827
|
+
const names = collectNodeLeafNames(node);
|
|
828
|
+
const next = new Set(current);
|
|
829
|
+
if (names.some((name) => !current.has(name))) for (const name of names) next.add(name);
|
|
830
|
+
else for (const name of names) next.delete(name);
|
|
831
|
+
return next;
|
|
832
|
+
}
|
|
833
|
+
function disabledToolReason(toolName, enabled, disabled) {
|
|
834
|
+
if (!enabled || disabled.size === 0) return void 0;
|
|
835
|
+
if (disabled.has(toolName)) return `${DISABLED_TOOL_PREFIX} ${JSON.stringify(toolName)}`;
|
|
836
|
+
}
|
|
837
|
+
function filterToolSchemas(tools, enabled, disabled) {
|
|
838
|
+
if (!enabled || disabled.size === 0) return [...tools];
|
|
839
|
+
return tools.filter((tool) => !disabled.has(tool.name));
|
|
840
|
+
}
|
|
841
|
+
function parseToolCatalog(raw) {
|
|
842
|
+
if (raw === null || raw === void 0 || typeof raw !== "object") return {
|
|
843
|
+
tools: [],
|
|
844
|
+
available: false
|
|
845
|
+
};
|
|
846
|
+
const list = raw.tools;
|
|
847
|
+
if (!Array.isArray(list)) return {
|
|
848
|
+
tools: [],
|
|
849
|
+
available: false
|
|
850
|
+
};
|
|
851
|
+
const byName = new Map();
|
|
852
|
+
for (const item of list) {
|
|
853
|
+
if (item === null || item === void 0 || typeof item !== "object") continue;
|
|
854
|
+
const name = item.name;
|
|
855
|
+
if (typeof name !== "string" || name.trim() === "") continue;
|
|
856
|
+
const trimmed = name.trim();
|
|
857
|
+
if (byName.has(trimmed)) continue;
|
|
858
|
+
const desc = item.description;
|
|
859
|
+
byName.set(trimmed, {
|
|
860
|
+
name: trimmed,
|
|
861
|
+
description: typeof desc === "string" ? desc.trim() : ""
|
|
862
|
+
});
|
|
863
|
+
}
|
|
864
|
+
return {
|
|
865
|
+
tools: [...byName.values()].sort((a, b) => compareCodeUnits(a.name, b.name)),
|
|
866
|
+
available: true
|
|
867
|
+
};
|
|
868
|
+
}
|
|
869
|
+
//#endregion
|
|
634
870
|
//#region src/client/settings/card.ts
|
|
635
871
|
function withField(list, field) {
|
|
636
872
|
return list.includes(field) ? list : [...list, field];
|
|
@@ -773,6 +1009,7 @@ window.__ModuleLoader__.load({
|
|
|
773
1009
|
role: "alert"
|
|
774
1010
|
}, t("settings.staleHost") + "(" + drifted.map((field) => labelOf(t, field)).join("、") + ")") : null;
|
|
775
1011
|
const showSuggest = flagOn(value, "suggest") || readOnly;
|
|
1012
|
+
const showToolsManager = flagOn(value, "toolsManager") || readOnly;
|
|
776
1013
|
return h("div", { "data-desktop-enhance-settings": "" }, h("div", {}, h("div", { className: "de-head-title" }, t("settings.title")), h("div", { className: "de-head-desc" }, t("settings.description"))), ...items, showSuggest ? h(SuggestSettings, {
|
|
777
1014
|
key: "suggest",
|
|
778
1015
|
t,
|
|
@@ -781,6 +1018,14 @@ window.__ModuleLoader__.load({
|
|
|
781
1018
|
readOnly,
|
|
782
1019
|
write,
|
|
783
1020
|
drifted
|
|
1021
|
+
}) : null, showToolsManager ? h(ToolsManagerSettings, {
|
|
1022
|
+
key: "toolsManager",
|
|
1023
|
+
t,
|
|
1024
|
+
value,
|
|
1025
|
+
busy,
|
|
1026
|
+
readOnly,
|
|
1027
|
+
write,
|
|
1028
|
+
drifted
|
|
784
1029
|
}) : null, note);
|
|
785
1030
|
}
|
|
786
1031
|
function SuggestSettings({ t, value, busy, readOnly, write, drifted }) {
|
|
@@ -1008,6 +1253,199 @@ window.__ModuleLoader__.load({
|
|
|
1008
1253
|
}, t("settings.suggestPrompt.reset"))])
|
|
1009
1254
|
]);
|
|
1010
1255
|
}
|
|
1256
|
+
function ToolsManagerSettings({ t, value, busy, readOnly, write, drifted }) {
|
|
1257
|
+
const disabledSet = parseDisabledTools(textOf(value, "disabledTools"));
|
|
1258
|
+
const canonicalDisabled = formatDisabledTools(disabledSet);
|
|
1259
|
+
const controlDisabled = readOnly || busy.includes("disabledTools") || drifted.includes("disabledTools");
|
|
1260
|
+
const [catalog, setCatalog] = React.useState(null);
|
|
1261
|
+
const [query, setQuery] = React.useState("");
|
|
1262
|
+
const [expandedMap, setExpandedMap] = React.useState({});
|
|
1263
|
+
const [refreshTick, setRefreshTick] = React.useState(0);
|
|
1264
|
+
React.useEffect(() => {
|
|
1265
|
+
let live = true;
|
|
1266
|
+
catalogCache.get(TOOLS_URL, globalThis.fetch).then((body) => {
|
|
1267
|
+
if (live) setCatalog(parseToolCatalog(body));
|
|
1268
|
+
}).catch(() => {
|
|
1269
|
+
if (live) setCatalog({
|
|
1270
|
+
tools: [],
|
|
1271
|
+
available: false
|
|
1272
|
+
});
|
|
1273
|
+
});
|
|
1274
|
+
return () => {
|
|
1275
|
+
live = false;
|
|
1276
|
+
};
|
|
1277
|
+
}, [refreshTick]);
|
|
1278
|
+
const commitSet = (nextSet) => {
|
|
1279
|
+
write("disabledTools", formatDisabledTools(nextSet));
|
|
1280
|
+
};
|
|
1281
|
+
const toggleExpand = (prefix, defaultOpen) => {
|
|
1282
|
+
setExpandedMap((prev) => {
|
|
1283
|
+
const current = prev[prefix] ?? defaultOpen;
|
|
1284
|
+
return {
|
|
1285
|
+
...prev,
|
|
1286
|
+
[prefix]: !current
|
|
1287
|
+
};
|
|
1288
|
+
});
|
|
1289
|
+
};
|
|
1290
|
+
const renderTreeNode = (node, depth) => {
|
|
1291
|
+
const indentStyle = depth > 0 ? { paddingLeft: `${depth * 18 + 8}px` } : void 0;
|
|
1292
|
+
if (node.kind === "leaf") return h("div", {
|
|
1293
|
+
key: `leaf:${node.name}`,
|
|
1294
|
+
className: "de-tools-leaf-row",
|
|
1295
|
+
"data-desktop-enhance-tool-leaf": node.name,
|
|
1296
|
+
"data-disabled": node.disabled ? "true" : "false",
|
|
1297
|
+
style: indentStyle
|
|
1298
|
+
}, [h("div", {
|
|
1299
|
+
key: "info",
|
|
1300
|
+
className: "de-tools-leaf-info"
|
|
1301
|
+
}, [h("div", {
|
|
1302
|
+
key: "name",
|
|
1303
|
+
className: "de-tools-leaf-name"
|
|
1304
|
+
}, node.name), node.description !== "" ? h("div", {
|
|
1305
|
+
key: "desc",
|
|
1306
|
+
className: "de-tools-leaf-desc"
|
|
1307
|
+
}, node.description) : null]), h("div", {
|
|
1308
|
+
key: "ctrl",
|
|
1309
|
+
className: "de-tools-controls"
|
|
1310
|
+
}, [h("span", {
|
|
1311
|
+
key: "pill",
|
|
1312
|
+
className: "de-tools-pill",
|
|
1313
|
+
"data-disabled": node.disabled ? "true" : "false"
|
|
1314
|
+
}, node.disabled ? t("settings.tools.disabled") : t("settings.tools.enabled")), h("button", {
|
|
1315
|
+
key: "btn",
|
|
1316
|
+
type: "button",
|
|
1317
|
+
className: "de-button",
|
|
1318
|
+
"data-desktop-enhance-tool-toggle": node.name,
|
|
1319
|
+
disabled: controlDisabled,
|
|
1320
|
+
onClick: () => commitSet(toggleToolInSet(disabledSet, node.name, !node.disabled))
|
|
1321
|
+
}, node.disabled ? t("settings.tools.enable") : t("settings.tools.disable"))])]);
|
|
1322
|
+
const defaultOpen = query.trim() !== "" || depth < 1;
|
|
1323
|
+
const isOpen = expandedMap[node.prefix] ?? defaultOpen;
|
|
1324
|
+
const allDisabled = node.disabled === node.total;
|
|
1325
|
+
const anyEnabled = node.disabled < node.total;
|
|
1326
|
+
const enabledCount = node.total - node.disabled;
|
|
1327
|
+
return h("div", {
|
|
1328
|
+
key: `node:${node.prefix}`,
|
|
1329
|
+
className: "de-tools-node",
|
|
1330
|
+
"data-desktop-enhance-tool-node": node.prefix
|
|
1331
|
+
}, [h("div", {
|
|
1332
|
+
key: "head",
|
|
1333
|
+
className: "de-tools-node-header",
|
|
1334
|
+
style: indentStyle,
|
|
1335
|
+
onClick: () => toggleExpand(node.prefix, defaultOpen)
|
|
1336
|
+
}, [h("span", {
|
|
1337
|
+
key: "title",
|
|
1338
|
+
className: "de-tools-node-title"
|
|
1339
|
+
}, [h("span", {
|
|
1340
|
+
key: "arrow",
|
|
1341
|
+
"aria-hidden": "true"
|
|
1342
|
+
}, isOpen ? "▾" : "▸"), h("span", { key: "label" }, node.label)]), h("div", {
|
|
1343
|
+
key: "ctrl",
|
|
1344
|
+
className: "de-tools-controls"
|
|
1345
|
+
}, [h("span", {
|
|
1346
|
+
key: "pill",
|
|
1347
|
+
className: "de-tools-pill",
|
|
1348
|
+
"data-disabled": allDisabled ? "true" : "false"
|
|
1349
|
+
}, allDisabled ? t("settings.tools.allDisabled") : `${enabledCount}/${node.total}`), h("button", {
|
|
1350
|
+
key: "batch",
|
|
1351
|
+
type: "button",
|
|
1352
|
+
className: "de-button",
|
|
1353
|
+
"data-desktop-enhance-tool-batch": node.prefix,
|
|
1354
|
+
disabled: controlDisabled,
|
|
1355
|
+
onClick: (e) => {
|
|
1356
|
+
e?.stopPropagation?.();
|
|
1357
|
+
commitSet(toggleNodeInSet(disabledSet, node));
|
|
1358
|
+
}
|
|
1359
|
+
}, anyEnabled ? t("settings.tools.disableAll") : t("settings.tools.enableAll"))])]), isOpen ? h("div", {
|
|
1360
|
+
key: "children",
|
|
1361
|
+
className: "de-tools-node-children"
|
|
1362
|
+
}, node.children.map((child) => renderTreeNode(child, depth + 1))) : null]);
|
|
1363
|
+
};
|
|
1364
|
+
const treeNodes = catalog !== null && catalog.available ? buildToolPrefixTree(catalog.tools, disabledSet, query) : [];
|
|
1365
|
+
const disabledInCatalog = catalog !== null && catalog.available ? catalog.tools.filter((tool) => disabledSet.has(tool.name)).length : 0;
|
|
1366
|
+
const onSearchChange = (event) => {
|
|
1367
|
+
const next = event?.target?.value;
|
|
1368
|
+
if (typeof next === "string") setQuery(next);
|
|
1369
|
+
};
|
|
1370
|
+
return h("div", {
|
|
1371
|
+
className: "de-tools-settings",
|
|
1372
|
+
"data-desktop-enhance-tools-manager": ""
|
|
1373
|
+
}, [catalog === null || !catalog.available ? h("div", {
|
|
1374
|
+
key: "field",
|
|
1375
|
+
className: "de-item de-item-block"
|
|
1376
|
+
}, [h("div", {
|
|
1377
|
+
key: "text",
|
|
1378
|
+
className: "de-text"
|
|
1379
|
+
}, [h("div", {
|
|
1380
|
+
key: "title",
|
|
1381
|
+
className: "de-title"
|
|
1382
|
+
}, t("settings.disabledTools")), h("div", {
|
|
1383
|
+
key: "desc",
|
|
1384
|
+
className: "de-desc"
|
|
1385
|
+
}, t("settings.disabledTools.hint"))]), h("input", {
|
|
1386
|
+
key: "input",
|
|
1387
|
+
type: "text",
|
|
1388
|
+
className: "de-text-input",
|
|
1389
|
+
"data-desktop-enhance-field": "disabledTools",
|
|
1390
|
+
placeholder: t("settings.disabledTools.placeholder"),
|
|
1391
|
+
value: canonicalDisabled,
|
|
1392
|
+
disabled: controlDisabled,
|
|
1393
|
+
onChange: (event) => {
|
|
1394
|
+
const next = event?.target?.value;
|
|
1395
|
+
if (typeof next === "string") commitSet(parseDisabledTools(next));
|
|
1396
|
+
}
|
|
1397
|
+
})]) : h("div", {
|
|
1398
|
+
key: "catalog",
|
|
1399
|
+
className: "de-item de-item-block"
|
|
1400
|
+
}, [
|
|
1401
|
+
h("div", {
|
|
1402
|
+
key: "toolbar",
|
|
1403
|
+
className: "de-tools-toolbar"
|
|
1404
|
+
}, [h("span", {
|
|
1405
|
+
key: "summary",
|
|
1406
|
+
className: "de-tools-summary",
|
|
1407
|
+
"data-desktop-enhance-tools-summary": ""
|
|
1408
|
+
}, `${catalog.tools.length - disabledInCatalog}/${catalog.tools.length}`), h("div", {
|
|
1409
|
+
key: "actions",
|
|
1410
|
+
className: "de-tools-actions"
|
|
1411
|
+
}, [h("button", {
|
|
1412
|
+
key: "enable-all",
|
|
1413
|
+
type: "button",
|
|
1414
|
+
className: "de-button",
|
|
1415
|
+
"data-desktop-enhance-field": "disabledTools",
|
|
1416
|
+
"data-desktop-enhance-action": "tools-enable-all",
|
|
1417
|
+
disabled: controlDisabled || disabledSet.size === 0,
|
|
1418
|
+
onClick: () => write("disabledTools", "")
|
|
1419
|
+
}, t("settings.tools.enableAll")), h("button", {
|
|
1420
|
+
key: "refresh",
|
|
1421
|
+
type: "button",
|
|
1422
|
+
className: "de-button",
|
|
1423
|
+
"data-desktop-enhance-action": "tools-refresh",
|
|
1424
|
+
disabled: readOnly,
|
|
1425
|
+
onClick: () => {
|
|
1426
|
+
catalogCache.invalidate?.(TOOLS_URL);
|
|
1427
|
+
setRefreshTick((n) => n + 1);
|
|
1428
|
+
}
|
|
1429
|
+
}, t("settings.tools.refresh"))])]),
|
|
1430
|
+
h("input", {
|
|
1431
|
+
key: "search",
|
|
1432
|
+
type: "search",
|
|
1433
|
+
className: "de-text-input",
|
|
1434
|
+
"data-desktop-enhance-tools-search": "",
|
|
1435
|
+
placeholder: t("settings.tools.search"),
|
|
1436
|
+
value: query,
|
|
1437
|
+
onInput: onSearchChange,
|
|
1438
|
+
onChange: onSearchChange
|
|
1439
|
+
}),
|
|
1440
|
+
treeNodes.length === 0 ? h("div", {
|
|
1441
|
+
key: "empty",
|
|
1442
|
+
className: "de-tools-empty"
|
|
1443
|
+
}, t("settings.tools.empty")) : h("div", {
|
|
1444
|
+
key: "tree",
|
|
1445
|
+
className: "de-tools-tree"
|
|
1446
|
+
}, treeNodes.map((node) => renderTreeNode(node, 0)))
|
|
1447
|
+
])]);
|
|
1448
|
+
}
|
|
1011
1449
|
//#endregion
|
|
1012
1450
|
//#region src/client/timing/index.ts
|
|
1013
1451
|
function finite(value) {
|
|
@@ -2421,7 +2859,7 @@ window.__ModuleLoader__.load({
|
|
|
2421
2859
|
}
|
|
2422
2860
|
//#endregion
|
|
2423
2861
|
//#region \0dsh-desktop-enhance-css:/Users/lijiechengbj/projects/AI-agents/dsh-desktop-enhance/src/client/styles/enhance.css.mjs
|
|
2424
|
-
var enhance_css_default = "\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"]) {\n content-visibility: visible !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"][hidden=\"until-found\"],\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"][hidden=\"until-found\"] {\n content-visibility: visible !important;\n}\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n [data-turn-process-member=\"true\"]:not([data-chat-flow-kind=\"compaction\"]):not([data-chat-flow-kind=\"manual-compaction\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"])\n [data-turn-process-member=\"true\"]:not([data-chat-flow-kind=\"compaction\"]):not([data-chat-flow-kind=\"manual-compaction\"]) {\n display: none !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-step-process=\"true\"][hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n > div:has(> [data-process-activity]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-step-process=\"true\"][hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"])\n > div:has(> [data-process-activity]) {\n display: none !important;\n}\n\n\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"compaction\"],\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"manual-compaction\"] {\n padding: 6px 0 !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"compaction\"] button,\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"manual-compaction\"] button {\n width: fit-content !important;\n margin: 0 auto !important;\n height: auto !important;\n min-height: 28px;\n padding: 0 14px !important;\n justify-content: center !important;\n background: var(--dsw-alias-state-warn-tertiary) !important;\n border-radius: 999px !important;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-state-warn-primary) 45%, transparent);\n color: var(--dsw-alias-state-warn-label) !important;\n}\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button:hover:not(:disabled),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button:hover:not(:disabled) {\n background: var(--dsw-alias-state-warn-secondary) !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button:has([data-compaction-disclosure=\"expanded\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button:has([data-compaction-disclosure=\"expanded\"]) {\n width: 100% !important;\n margin: 0 !important;\n border-radius: var(--dsw-radius-sm) !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button > span:not([aria-hidden]):not(:last-child),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button > span:not([aria-hidden]):not(:last-child) {\n font-weight: 600;\n}\n\n\n[data-desktop-enhance-reveal] {\n content-visibility: visible !important;\n}\n[hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n [data-turn-process-member=\"true\"][data-desktop-enhance-reveal]:not([data-chat-flow-kind=\"compaction\"]) {\n display: revert !important;\n}\n\n\n:root:not([data-desktop-enhance-off-turn-prefix]) [data-desktop-enhance-turn]::before {\n content: attr(data-desktop-enhance-turn);\n flex: none;\n margin-right: 6px;\n padding: 0 5px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-secondary);\n font: var(--dsw-font-xxxs-strong-11);\n}\n\n\n\n:root[data-desktop-enhance-off-find-bar] [data-desktop-enhance-findbar] {\n display: none !important;\n}\n[data-desktop-enhance-findbar] {\n position: absolute;\n top: 12px;\n right: 20px;\n z-index: 30;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: var(--dsw-elevation-panel);\n}\n[data-desktop-enhance-findbar] input {\n width: 200px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n}\n[data-desktop-enhance-findbar] input:focus-visible {\n outline: 1px solid var(--dsw-focus-ring-color);\n outline-offset: 2px;\n}\n[data-desktop-enhance-findbar] .count {\n min-width: 44px;\n text-align: right;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-findbar] button {\n display: grid;\n place-items: center;\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n border-radius: var(--dsw-radius-xs);\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: var(--dsw-font-s-14);\n}\n[data-desktop-enhance-findbar] button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n[data-desktop-enhance-findbar] button:disabled {\n opacity: .4;\n cursor: default;\n}\n::highlight(desktop-enhance-find) {\n background-color: var(--dsw-alias-state-warn-tertiary);\n}\n::highlight(desktop-enhance-find-current) {\n background-color: var(--dsw-alias-state-warn-primary);\n color: var(--dsw-alias-label-primary-inverted);\n}\n\n\n[data-desktop-enhance-settings] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px 0;\n}\n[data-desktop-enhance-settings] .de-head-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n font-weight: 600;\n}\n[data-desktop-enhance-settings] .de-head-desc,\n[data-desktop-enhance-settings] .de-desc {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n[data-desktop-enhance-settings] .de-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n[data-desktop-enhance-settings] .de-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n}\n\n[data-desktop-enhance-settings] .de-switch {\n position: relative;\n flex: none;\n width: 36px;\n height: 20px;\n padding: 0;\n border: none;\n border-radius: 999px;\n background: var(--dsw-alias-interactive-bg-hover-solid);\n cursor: pointer;\n transition: background .15s;\n}\n[data-desktop-enhance-settings] .de-switch::after {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--dsw-alias-switch-thumb);\n transition: transform .15s;\n}\n[data-desktop-enhance-settings] .de-switch[aria-checked=\"true\"] {\n background: var(--dsw-alias-state-success-primary);\n}\n[data-desktop-enhance-settings] .de-switch[aria-checked=\"true\"]::after {\n transform: translateX(16px);\n}\n[data-desktop-enhance-settings] .de-switch:disabled {\n opacity: .5;\n cursor: default;\n}\n[data-desktop-enhance-settings] .de-note {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-error {\n color: var(--dsw-alias-state-error-primary);\n font: var(--dsw-font-xxs-12);\n}\n\n\n\n[data-desktop-enhance-settings] .de-suggest-settings {\n display: flex;\n flex-direction: column;\n gap: 12px;\n \n border-top: 1px solid var(--dsw-alias-border-l1);\n margin-top: 4px;\n padding-top: 12px;\n}\n[data-desktop-enhance-settings] .de-item-block {\n align-items: stretch;\n flex-direction: column;\n gap: 6px;\n}\n[data-desktop-enhance-settings] .de-select,\n[data-desktop-enhance-settings] .de-text-input,\n[data-desktop-enhance-settings] .de-textarea {\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xs-13);\n padding: 6px 8px;\n width: 100%;\n}\n[data-desktop-enhance-settings] .de-select:disabled,\n[data-desktop-enhance-settings] .de-text-input:disabled,\n[data-desktop-enhance-settings] .de-textarea:disabled {\n opacity: .5;\n}\n\n[data-desktop-enhance-settings] .de-textarea {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n line-height: 1.5;\n resize: vertical;\n white-space: pre-wrap;\n}\n[data-desktop-enhance-settings] .de-prompt {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n[data-desktop-enhance-settings] .de-prompt-meta {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-prompt-actions {\n display: flex;\n gap: 8px;\n}\n[data-desktop-enhance-settings] .de-button {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: var(--dsw-font-xxs-12);\n padding: 4px 10px;\n}\n[data-desktop-enhance-settings] .de-button:hover {\n border-color: var(--dsw-alias-border-l2);\n}\n[data-desktop-enhance-settings] .de-button:disabled {\n cursor: default;\n opacity: .5;\n}\n\n\n\n\n:root[data-desktop-enhance-off-suggest] [data-desktop-enhance='suggest'] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest {\n align-items: center;\n \n background: color-mix(in srgb, var(--dsw-alias-state-business-tertiary) 10%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 20%, transparent);\n border-radius: var(--dsw-radius-md);\n box-sizing: border-box;\n display: flex;\n \n flex-wrap: wrap;\n gap: 6px;\n \n margin: 0 auto 6px;\n max-width: var(--dsh-composer-card-max-width, 100%);\n \n min-width: 0;\n \n padding: 4px 10px 4px 13px;\n width: calc(100% - var(--dsh-composer-side-clearance, 0px) - var(--dsh-composer-side-clearance, 0px));\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-head {\n align-items: center;\n display: flex;\n flex: none;\n gap: 2px;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xs-13);\n font-weight: 500;\n \n white-space: nowrap;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-close {\n appearance: none;\n background: none;\n border: 0;\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n flex: none;\n font: var(--dsw-font-xxs-12);\n line-height: 1;\n padding: 2px 4px;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-close:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row {\n appearance: none;\n align-items: center;\n background: none;\n \n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 35%, transparent);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n display: flex;\n flex: 0 1 auto;\n font: var(--dsw-font-xs-13);\n gap: 6px;\n \n max-width: 100%;\n min-width: 0;\n padding: 4px 10px;\n text-align: left;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row:hover {\n background: var(--dsw-alias-state-business-tertiary);\n border-color: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-state-business-primary);\n transition: background-color .12s ease, border-color .12s ease, color .12s ease;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row[data-used='true'] {\n border-color: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-label-secondary);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-num {\n color: var(--dsw-alias-label-primary);\n flex: none;\n font: var(--dsw-font-xs-13);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-text {\n max-width: 22ch;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-loading {\n border-style: dashed;\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-error {\n color: var(--dsw-alias-state-error-primary);\n flex: 1 1 auto;\n font: var(--dsw-font-xxs-12);\n min-width: 0;\n padding: 2px;\n}\n\n\n:root:not([data-desktop-enhance-off-step-duration]) [data-desktop-enhance-duration]::after {\n content: attr(data-desktop-enhance-duration);\n \n margin-left: 8px;\n font-size: inherit;\n line-height: inherit;\n \n font-variant-numeric: tabular-nums;\n color: inherit;\n white-space: nowrap;\n pointer-events: none;\n user-select: none;\n}\n\n:root:not([data-desktop-enhance-off-step-duration])\n [data-desktop-enhance-duration]:has([data-step-process-icon])::after {\n margin-left: 2px;\n}\n\n\n:root[data-desktop-enhance-off-session-info] [data-desktop-enhance-session-info] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-session-info]) [data-desktop-enhance-session-info] {\n position: absolute;\n top: 12px;\n right: 36px;\n z-index: 10;\n width: 244px;\n box-sizing: border-box;\n border-radius: var(--dsw-radius-lg);\n border: 1px solid var(--dsw-alias-border-l2);\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-1) 90%, transparent);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n box-shadow: var(--dsw-elevation-panel);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n}\n:root:not([data-desktop-enhance-off-session-info])\n [data-desktop-enhance-session-info][data-minimized=\"true\"] {\n width: auto;\n border-radius: 999px;\n}\n[data-desktop-enhance-session-info] [data-session-info-header] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px;\n border: none;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n background: color-mix(in srgb, var(--dsw-alias-bg-module-platform) 60%, transparent);\n color: var(--dsw-alias-label-secondary);\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n cursor: pointer;\n user-select: none;\n}\n[data-desktop-enhance-session-info][data-minimized=\"true\"] [data-session-info-header] {\n border-bottom: none;\n background: transparent;\n padding: 5px 11px;\n}\n[data-desktop-enhance-session-info] [data-session-info-header]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n[data-desktop-enhance-session-info] [data-session-info-title] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-dot] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex: none;\n background: var(--dsw-alias-state-business-primary);\n box-shadow: 0 0 0 2.5px var(--dsw-alias-state-business-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-dot=\"idle\"] {\n background: var(--dsw-alias-label-caption);\n box-shadow: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-chevron] {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 1;\n}\n[data-desktop-enhance-session-info] [data-session-info-section] {\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n[data-desktop-enhance-session-info] [data-session-info-section]:last-child {\n border-bottom: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-section-header] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n cursor: pointer;\n user-select: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-section-header]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n[data-desktop-enhance-session-info] [data-session-info-section-label] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-arrow] {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n[data-desktop-enhance-session-info] [data-session-info-count] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n font-weight: 600;\n padding: 0 5px;\n line-height: 16px;\n border-radius: 999px;\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n}\n[data-desktop-enhance-session-info][data-empty=\"true\"] [data-session-info-count] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-body] {\n padding: 2px 6px 6px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 184px;\n overflow-y: auto;\n}\n[data-desktop-enhance-session-info] [data-session-info-empty] {\n padding: 4px 6px;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-session-info] [data-session-info-item] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 8px;\n border: none;\n border-radius: var(--dsw-radius-sm);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n text-align: left;\n}\n[data-desktop-enhance-session-info] [data-session-info-item]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n[data-desktop-enhance-session-info] [data-session-info-item-name] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-item-meta] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n flex: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-item-badge] {\n font-size: 10.5px;\n color: var(--dsw-alias-label-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-item-turn] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n padding: 0 5px;\n line-height: 16px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-secondary);\n}\n";
|
|
2862
|
+
var enhance_css_default = "\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"]) {\n content-visibility: visible !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"][hidden=\"until-found\"],\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"][hidden=\"until-found\"] {\n content-visibility: visible !important;\n}\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n [data-turn-process-member=\"true\"]:not([data-chat-flow-kind=\"compaction\"]):not([data-chat-flow-kind=\"manual-compaction\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"])\n [data-turn-process-member=\"true\"]:not([data-chat-flow-kind=\"compaction\"]):not([data-chat-flow-kind=\"manual-compaction\"]) {\n display: none !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-step-process=\"true\"][hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n > div:has(> [data-process-activity]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-step-process=\"true\"][hidden=\"until-found\"]:has([data-chat-flow-kind=\"manual-compaction\"])\n > div:has(> [data-process-activity]) {\n display: none !important;\n}\n\n\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"compaction\"],\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"manual-compaction\"] {\n padding: 6px 0 !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"compaction\"] button,\n:root:not([data-desktop-enhance-off-compaction-row]) [data-chat-flow-kind=\"manual-compaction\"] button {\n width: fit-content !important;\n margin: 0 auto !important;\n height: auto !important;\n min-height: 28px;\n padding: 0 14px !important;\n justify-content: center !important;\n background: var(--dsw-alias-state-warn-tertiary) !important;\n border-radius: 999px !important;\n box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--dsw-alias-state-warn-primary) 45%, transparent);\n color: var(--dsw-alias-state-warn-label) !important;\n}\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button:hover:not(:disabled),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button:hover:not(:disabled) {\n background: var(--dsw-alias-state-warn-secondary) !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button:has([data-compaction-disclosure=\"expanded\"]),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button:has([data-compaction-disclosure=\"expanded\"]) {\n width: 100% !important;\n margin: 0 !important;\n border-radius: var(--dsw-radius-sm) !important;\n}\n\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"compaction\"] button > span:not([aria-hidden]):not(:last-child),\n:root:not([data-desktop-enhance-off-compaction-row])\n [data-chat-flow-kind=\"manual-compaction\"] button > span:not([aria-hidden]):not(:last-child) {\n font-weight: 600;\n}\n\n\n[data-desktop-enhance-reveal] {\n content-visibility: visible !important;\n}\n[hidden=\"until-found\"]:has([data-chat-flow-kind=\"compaction\"])\n [data-turn-process-member=\"true\"][data-desktop-enhance-reveal]:not([data-chat-flow-kind=\"compaction\"]) {\n display: revert !important;\n}\n\n\n:root:not([data-desktop-enhance-off-turn-prefix]) [data-desktop-enhance-turn]::before {\n content: attr(data-desktop-enhance-turn);\n flex: none;\n margin-right: 6px;\n padding: 0 5px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-secondary);\n font: var(--dsw-font-xxxs-strong-11);\n}\n\n\n\n:root[data-desktop-enhance-off-find-bar] [data-desktop-enhance-findbar] {\n display: none !important;\n}\n[data-desktop-enhance-findbar] {\n position: absolute;\n top: 12px;\n right: 20px;\n z-index: 30;\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n background: var(--dsw-alias-bg-layer-1);\n box-shadow: var(--dsw-elevation-panel);\n}\n[data-desktop-enhance-findbar] input {\n width: 200px;\n border: none;\n outline: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n}\n[data-desktop-enhance-findbar] input:focus-visible {\n outline: 1px solid var(--dsw-focus-ring-color);\n outline-offset: 2px;\n}\n[data-desktop-enhance-findbar] .count {\n min-width: 44px;\n text-align: right;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-findbar] button {\n display: grid;\n place-items: center;\n width: 22px;\n height: 22px;\n padding: 0;\n border: none;\n border-radius: var(--dsw-radius-xs);\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: var(--dsw-font-s-14);\n}\n[data-desktop-enhance-findbar] button:hover:not(:disabled) {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n[data-desktop-enhance-findbar] button:disabled {\n opacity: .4;\n cursor: default;\n}\n::highlight(desktop-enhance-find) {\n background-color: var(--dsw-alias-state-warn-tertiary);\n}\n::highlight(desktop-enhance-find-current) {\n background-color: var(--dsw-alias-state-warn-primary);\n color: var(--dsw-alias-label-primary-inverted);\n}\n\n\n[data-desktop-enhance-settings] {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px 0;\n}\n[data-desktop-enhance-settings] .de-head-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n font-weight: 600;\n}\n[data-desktop-enhance-settings] .de-head-desc,\n[data-desktop-enhance-settings] .de-desc {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n}\n[data-desktop-enhance-settings] .de-text {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n[data-desktop-enhance-settings] .de-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-s-14);\n}\n\n[data-desktop-enhance-settings] .de-switch {\n position: relative;\n flex: none;\n width: 36px;\n height: 20px;\n padding: 0;\n border: none;\n border-radius: 999px;\n background: var(--dsw-alias-interactive-bg-hover-solid);\n cursor: pointer;\n transition: background .15s;\n}\n[data-desktop-enhance-settings] .de-switch::after {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n background: var(--dsw-alias-switch-thumb);\n transition: transform .15s;\n}\n[data-desktop-enhance-settings] .de-switch[aria-checked=\"true\"] {\n background: var(--dsw-alias-state-success-primary);\n}\n[data-desktop-enhance-settings] .de-switch[aria-checked=\"true\"]::after {\n transform: translateX(16px);\n}\n[data-desktop-enhance-settings] .de-switch:disabled {\n opacity: .5;\n cursor: default;\n}\n[data-desktop-enhance-settings] .de-note {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-error {\n color: var(--dsw-alias-state-error-primary);\n font: var(--dsw-font-xxs-12);\n}\n\n\n\n[data-desktop-enhance-settings] .de-suggest-settings {\n display: flex;\n flex-direction: column;\n gap: 12px;\n \n border-top: 1px solid var(--dsw-alias-border-l1);\n margin-top: 4px;\n padding-top: 12px;\n}\n[data-desktop-enhance-settings] .de-item-block {\n align-items: stretch;\n flex-direction: column;\n gap: 6px;\n}\n[data-desktop-enhance-settings] .de-select,\n[data-desktop-enhance-settings] .de-text-input,\n[data-desktop-enhance-settings] .de-textarea {\n background: var(--dsw-alias-bg-layer-2);\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xs-13);\n padding: 6px 8px;\n width: 100%;\n}\n[data-desktop-enhance-settings] .de-select:disabled,\n[data-desktop-enhance-settings] .de-text-input:disabled,\n[data-desktop-enhance-settings] .de-textarea:disabled {\n opacity: .5;\n}\n\n[data-desktop-enhance-settings] .de-textarea {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n line-height: 1.5;\n resize: vertical;\n white-space: pre-wrap;\n}\n[data-desktop-enhance-settings] .de-prompt {\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n[data-desktop-enhance-settings] .de-prompt-meta {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-settings] .de-prompt-actions {\n display: flex;\n gap: 8px;\n}\n[data-desktop-enhance-settings] .de-button {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: var(--dsw-font-xxs-12);\n padding: 4px 10px;\n}\n[data-desktop-enhance-settings] .de-button:hover {\n border-color: var(--dsw-alias-border-l2);\n}\n[data-desktop-enhance-settings] .de-button:disabled {\n cursor: default;\n opacity: .5;\n}\n\n\n\n\n:root[data-desktop-enhance-off-suggest] [data-desktop-enhance='suggest'] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest {\n align-items: center;\n \n background: color-mix(in srgb, var(--dsw-alias-state-business-tertiary) 10%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 20%, transparent);\n border-radius: var(--dsw-radius-md);\n box-sizing: border-box;\n display: flex;\n \n flex-wrap: wrap;\n gap: 6px;\n \n margin: 0 auto 6px;\n max-width: var(--dsh-composer-card-max-width, 100%);\n \n min-width: 0;\n \n padding: 4px 10px 4px 13px;\n width: calc(100% - var(--dsh-composer-side-clearance, 0px) - var(--dsh-composer-side-clearance, 0px));\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-head {\n align-items: center;\n display: flex;\n flex: none;\n gap: 2px;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-title {\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xs-13);\n font-weight: 500;\n \n white-space: nowrap;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-close {\n appearance: none;\n background: none;\n border: 0;\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n flex: none;\n font: var(--dsw-font-xxs-12);\n line-height: 1;\n padding: 2px 4px;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-close:hover {\n color: var(--dsw-alias-label-primary);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row {\n appearance: none;\n align-items: center;\n background: none;\n \n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 35%, transparent);\n border-radius: var(--dsw-radius-sm);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n display: flex;\n flex: 0 1 auto;\n font: var(--dsw-font-xs-13);\n gap: 6px;\n \n max-width: 100%;\n min-width: 0;\n padding: 4px 10px;\n text-align: left;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row:hover {\n background: var(--dsw-alias-state-business-tertiary);\n border-color: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-state-business-primary);\n transition: background-color .12s ease, border-color .12s ease, color .12s ease;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-row[data-used='true'] {\n border-color: var(--dsw-alias-brand-primary);\n color: var(--dsw-alias-label-secondary);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-num {\n color: var(--dsw-alias-label-primary);\n flex: none;\n font: var(--dsw-font-xs-13);\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-text {\n max-width: 22ch;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-loading {\n border-style: dashed;\n color: var(--dsw-alias-label-secondary);\n cursor: default;\n}\n\n:root:not([data-desktop-enhance-off-suggest]) .de-suggest-error {\n color: var(--dsw-alias-state-error-primary);\n flex: 1 1 auto;\n font: var(--dsw-font-xxs-12);\n min-width: 0;\n padding: 2px;\n}\n\n\n:root:not([data-desktop-enhance-off-step-duration]) [data-desktop-enhance-duration]::after {\n content: attr(data-desktop-enhance-duration);\n \n margin-left: 8px;\n font-size: inherit;\n line-height: inherit;\n \n font-variant-numeric: tabular-nums;\n color: inherit;\n white-space: nowrap;\n pointer-events: none;\n user-select: none;\n}\n\n:root:not([data-desktop-enhance-off-step-duration])\n [data-desktop-enhance-duration]:has([data-step-process-icon])::after {\n margin-left: 2px;\n}\n\n\n:root[data-desktop-enhance-off-session-info] [data-desktop-enhance-session-info] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-session-info]) [data-desktop-enhance-session-info] {\n position: absolute;\n top: 12px;\n right: 36px;\n z-index: 10;\n width: 244px;\n box-sizing: border-box;\n border-radius: var(--dsw-radius-lg);\n border: 1px solid var(--dsw-alias-border-l2);\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-1) 90%, transparent);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n box-shadow: var(--dsw-elevation-panel);\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n}\n:root:not([data-desktop-enhance-off-session-info])\n [data-desktop-enhance-session-info][data-minimized=\"true\"] {\n width: auto;\n border-radius: 999px;\n}\n[data-desktop-enhance-session-info] [data-session-info-header] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px;\n border: none;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n background: color-mix(in srgb, var(--dsw-alias-bg-module-platform) 60%, transparent);\n color: var(--dsw-alias-label-secondary);\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n cursor: pointer;\n user-select: none;\n}\n[data-desktop-enhance-session-info][data-minimized=\"true\"] [data-session-info-header] {\n border-bottom: none;\n background: transparent;\n padding: 5px 11px;\n}\n[data-desktop-enhance-session-info] [data-session-info-header]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n[data-desktop-enhance-session-info] [data-session-info-title] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-dot] {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex: none;\n background: var(--dsw-alias-state-business-primary);\n box-shadow: 0 0 0 2.5px var(--dsw-alias-state-business-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-dot=\"idle\"] {\n background: var(--dsw-alias-label-caption);\n box-shadow: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-chevron] {\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 1;\n}\n[data-desktop-enhance-session-info] [data-session-info-section] {\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n}\n[data-desktop-enhance-session-info] [data-session-info-section]:last-child {\n border-bottom: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-section-header] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px;\n border: none;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n cursor: pointer;\n user-select: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-section-header]:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n[data-desktop-enhance-session-info] [data-session-info-section-label] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-arrow] {\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n}\n[data-desktop-enhance-session-info] [data-session-info-count] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n font-weight: 600;\n padding: 0 5px;\n line-height: 16px;\n border-radius: 999px;\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n}\n[data-desktop-enhance-session-info][data-empty=\"true\"] [data-session-info-count] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-body] {\n padding: 2px 6px 6px;\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 184px;\n overflow-y: auto;\n}\n[data-desktop-enhance-session-info] [data-session-info-empty] {\n padding: 4px 6px;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n[data-desktop-enhance-session-info] [data-session-info-item] {\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 8px;\n border: none;\n border-radius: var(--dsw-radius-sm);\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n text-align: left;\n}\n[data-desktop-enhance-session-info] [data-session-info-item]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n[data-desktop-enhance-session-info] [data-session-info-item-name] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n[data-desktop-enhance-session-info] [data-session-info-item-meta] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n flex: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-item-badge] {\n font-size: 10.5px;\n color: var(--dsw-alias-label-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-item-turn] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n padding: 0 5px;\n line-height: 16px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-secondary);\n}\n\n\n:root[data-desktop-enhance-off-tools-manager] [data-desktop-enhance-tools-manager] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-settings {\n display: flex;\n flex-direction: column;\n gap: 10px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n margin-top: 4px;\n padding-top: 12px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n flex-wrap: wrap;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-summary {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11.5px;\n color: var(--dsw-alias-label-secondary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-tree {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 360px;\n overflow-y: auto;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: var(--dsw-radius-sm);\n padding: 6px;\n background: var(--dsw-alias-bg-layer-2);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-node-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 5px 8px;\n border-radius: var(--dsw-radius-xs);\n cursor: pointer;\n user-select: none;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-node-header:hover,\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-row:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-node-title {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12.5px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n min-width: 0;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: 10px;\n padding: 5px 8px;\n border-radius: var(--dsw-radius-xs);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-info {\n flex: 1 1 auto;\n min-width: 0;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-name {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12.5px;\n font-weight: 500;\n color: var(--dsw-alias-label-primary);\n word-break: break-all;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-row[data-disabled=\"true\"] .de-tools-leaf-name {\n color: var(--dsw-alias-label-tertiary);\n text-decoration: line-through;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-leaf-desc {\n font-size: 11.5px;\n line-height: 17px;\n color: var(--dsw-alias-label-tertiary);\n margin-top: 2px;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n word-break: break-word;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-controls {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-pill {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n padding: 1px 6px;\n line-height: 16px;\n border-radius: 999px;\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-pill[data-disabled=\"true\"] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-tertiary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) .de-tools-empty {\n padding: 8px;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n\n";
|
|
2425
2863
|
//#endregion
|
|
2426
2864
|
//#region src/client/index.tsx
|
|
2427
2865
|
const inject = [
|
|
@@ -2623,6 +3061,7 @@ window.__ModuleLoader__.load({
|
|
|
2623
3061
|
quietEffortOf,
|
|
2624
3062
|
splitRoute,
|
|
2625
3063
|
FOLLOW_SESSION,
|
|
3064
|
+
SUGGEST_TEXT_FIELDS,
|
|
2626
3065
|
TEXT_FIELDS,
|
|
2627
3066
|
ALL_FIELDS,
|
|
2628
3067
|
undeclaredFields,
|
|
@@ -2633,7 +3072,9 @@ window.__ModuleLoader__.load({
|
|
|
2633
3072
|
parseEfforts,
|
|
2634
3073
|
catalogCache,
|
|
2635
3074
|
CACHE_MS,
|
|
3075
|
+
TOOLS_URL,
|
|
2636
3076
|
SuggestSettings,
|
|
3077
|
+
ToolsManagerSettings,
|
|
2637
3078
|
ModelPicker,
|
|
2638
3079
|
zh,
|
|
2639
3080
|
en,
|
|
@@ -2661,7 +3102,18 @@ window.__ModuleLoader__.load({
|
|
|
2661
3102
|
SESSION_INFO_URL,
|
|
2662
3103
|
requestSessionInfo,
|
|
2663
3104
|
openSkillInHost,
|
|
2664
|
-
installSessionInfo
|
|
3105
|
+
installSessionInfo,
|
|
3106
|
+
DISABLED_TOOL_PREFIX,
|
|
3107
|
+
buildToolPrefixTree,
|
|
3108
|
+
collectNodeLeafNames,
|
|
3109
|
+
disabledToolReason,
|
|
3110
|
+
filterToolSchemas,
|
|
3111
|
+
formatDisabledTools,
|
|
3112
|
+
parseDisabledTools,
|
|
3113
|
+
parseToolCatalog,
|
|
3114
|
+
splitToolName,
|
|
3115
|
+
toggleNodeInSet,
|
|
3116
|
+
toggleToolInSet
|
|
2665
3117
|
};
|
|
2666
3118
|
exports.apply = apply;
|
|
2667
3119
|
exports.inject = inject;
|
package/lib/index.d.ts
CHANGED
|
@@ -94,6 +94,32 @@ declare function registerSuggestRoute(ctx: HostContext): () => void;
|
|
|
94
94
|
declare function handleSessionInfo(ctx: HostContext, request: Request): Promise<Response>;
|
|
95
95
|
declare function registerSessionInfoRoute(ctx: HostContext): () => void;
|
|
96
96
|
//#endregion
|
|
97
|
+
//#region src/shared/tools-manager.d.ts
|
|
98
|
+
interface ToolSummary {
|
|
99
|
+
readonly name: string;
|
|
100
|
+
readonly description: string;
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/tools-manager/host.d.ts
|
|
104
|
+
interface ToolsPolicyState {
|
|
105
|
+
readonly enabled: boolean;
|
|
106
|
+
readonly disabled: ReadonlySet<string>;
|
|
107
|
+
}
|
|
108
|
+
interface HostPromptAssembly {
|
|
109
|
+
readonly tools?: readonly {
|
|
110
|
+
readonly name: string;
|
|
111
|
+
}[];
|
|
112
|
+
readonly [key: string]: unknown;
|
|
113
|
+
}
|
|
114
|
+
interface ToolsHostContext extends HostContext {
|
|
115
|
+
on?(event: string, listener: (assembly: HostPromptAssembly, context: unknown, next: () => Promise<HostPromptAssembly>) => Promise<HostPromptAssembly>): () => void;
|
|
116
|
+
}
|
|
117
|
+
declare function readToolsConfig(config: unknown): ToolsPolicyState;
|
|
118
|
+
declare function collectAllToolSchemas(ctx: HostContext): Promise<readonly ToolSummary[]>;
|
|
119
|
+
declare function installToolsPolicy(ctx: ToolsHostContext, readState: () => ToolsPolicyState): () => void;
|
|
120
|
+
declare function handleToolsCatalog(ctx: HostContext): Promise<Response>;
|
|
121
|
+
declare function registerToolsRoute(ctx: HostContext): () => void;
|
|
122
|
+
//#endregion
|
|
97
123
|
//#region src/index.d.ts
|
|
98
124
|
export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
|
|
99
125
|
findBar: Schema<boolean, boolean, "volatile-defined">;
|
|
@@ -102,9 +128,11 @@ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
|
|
|
102
128
|
suggest: Schema<boolean, boolean, "volatile-defined">;
|
|
103
129
|
stepDuration: Schema<boolean, boolean, "volatile-defined">;
|
|
104
130
|
sessionInfo: Schema<boolean, boolean, "volatile-defined">;
|
|
131
|
+
toolsManager: Schema<boolean, boolean, "volatile-defined">;
|
|
105
132
|
suggestModel: Schema<string, string, "volatile-defined">;
|
|
106
133
|
suggestReasoning: Schema<string, string, "volatile-defined">;
|
|
107
134
|
suggestPrompt: Schema<string, string, "volatile-defined">;
|
|
135
|
+
disabledTools: Schema<string, string, "volatile-defined">;
|
|
108
136
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
109
137
|
findBar: Schema<boolean, boolean, "volatile-defined">;
|
|
110
138
|
turnPrefix: Schema<boolean, boolean, "volatile-defined">;
|
|
@@ -112,16 +140,19 @@ export declare const Config: Schema<Schemastery.ObjectS<NoInfer<{
|
|
|
112
140
|
suggest: Schema<boolean, boolean, "volatile-defined">;
|
|
113
141
|
stepDuration: Schema<boolean, boolean, "volatile-defined">;
|
|
114
142
|
sessionInfo: Schema<boolean, boolean, "volatile-defined">;
|
|
143
|
+
toolsManager: Schema<boolean, boolean, "volatile-defined">;
|
|
115
144
|
suggestModel: Schema<string, string, "volatile-defined">;
|
|
116
145
|
suggestReasoning: Schema<string, string, "volatile-defined">;
|
|
117
146
|
suggestPrompt: Schema<string, string, "volatile-defined">;
|
|
147
|
+
disabledTools: Schema<string, string, "volatile-defined">;
|
|
118
148
|
}>>, "plain">;
|
|
119
|
-
export declare function apply(ctx:
|
|
149
|
+
export declare function apply(ctx: ToolsHostContext, config?: unknown): void;
|
|
120
150
|
export declare const __test: {
|
|
121
151
|
SUGGEST_PATH: string;
|
|
122
152
|
SUGGEST_MODELS_PATH: string;
|
|
123
153
|
SUGGEST_EFFORTS_PATH: string;
|
|
124
154
|
SESSION_INFO_PATH: string;
|
|
155
|
+
TOOLS_PATH: string;
|
|
125
156
|
MODEL_TIMEOUT_MS: number;
|
|
126
157
|
MAX_OUTPUT_TOKENS: number;
|
|
127
158
|
buildPrompt: typeof buildPrompt;
|
|
@@ -130,8 +161,13 @@ export declare const __test: {
|
|
|
130
161
|
knownNamesOf: typeof knownNamesOf;
|
|
131
162
|
handleSuggest: typeof handleSuggest;
|
|
132
163
|
handleSessionInfo: typeof handleSessionInfo;
|
|
164
|
+
handleToolsCatalog: typeof handleToolsCatalog;
|
|
165
|
+
collectAllToolSchemas: typeof collectAllToolSchemas;
|
|
166
|
+
installToolsPolicy: typeof installToolsPolicy;
|
|
167
|
+
readToolsConfig: typeof readToolsConfig;
|
|
133
168
|
registerSuggestRoute: typeof registerSuggestRoute;
|
|
134
169
|
registerSessionInfoRoute: typeof registerSessionInfoRoute;
|
|
170
|
+
registerToolsRoute: typeof registerToolsRoute;
|
|
135
171
|
routeOf: typeof routeOf;
|
|
136
172
|
quietEffortFor: typeof quietEffortFor;
|
|
137
173
|
listModels: typeof listModels;
|
package/lib/index.js
CHANGED
|
@@ -94,6 +94,7 @@ const SUGGEST_ROUTE = "/api/desktop-enhance/suggest";
|
|
|
94
94
|
const SUGGEST_MODELS_ROUTE = "/api/desktop-enhance/suggest-models";
|
|
95
95
|
const SUGGEST_EFFORTS_ROUTE = "/api/desktop-enhance/suggest-efforts";
|
|
96
96
|
const SESSION_INFO_ROUTE = "/api/desktop-enhance/session-info";
|
|
97
|
+
const TOOLS_ROUTE = "/api/desktop-enhance/tools";
|
|
97
98
|
//#endregion
|
|
98
99
|
//#region src/suggest/host.ts
|
|
99
100
|
const SUGGEST_PATH = SUGGEST_ROUTE;
|
|
@@ -157,7 +158,7 @@ function knownNamesOf(messages) {
|
|
|
157
158
|
return found ? names : null;
|
|
158
159
|
}
|
|
159
160
|
async function handleSuggest(ctx, request, timeoutMs = MODEL_TIMEOUT_MS) {
|
|
160
|
-
const empty = () => json$
|
|
161
|
+
const empty = () => json$2({ items: [] });
|
|
161
162
|
let sessionId;
|
|
162
163
|
let preference = FOLLOW_SESSION;
|
|
163
164
|
try {
|
|
@@ -169,9 +170,9 @@ async function handleSuggest(ctx, request, timeoutMs = MODEL_TIMEOUT_MS) {
|
|
|
169
170
|
prompt: typeof body.prompt === "string" ? body.prompt : ""
|
|
170
171
|
};
|
|
171
172
|
} catch {
|
|
172
|
-
return json$
|
|
173
|
+
return json$2({ items: [] }, 400);
|
|
173
174
|
}
|
|
174
|
-
if (typeof sessionId !== "string" || sessionId === "") return json$
|
|
175
|
+
if (typeof sessionId !== "string" || sessionId === "") return json$2({ items: [] }, 400);
|
|
175
176
|
const sessions = ctx.get("sessions");
|
|
176
177
|
const llm = ctx.get("llm");
|
|
177
178
|
if (sessions === null || sessions === void 0 || llm === null || llm === void 0) return empty();
|
|
@@ -230,7 +231,7 @@ async function handleSuggest(ctx, request, timeoutMs = MODEL_TIMEOUT_MS) {
|
|
|
230
231
|
}
|
|
231
232
|
function withDiag(ctx, body, record) {
|
|
232
233
|
logDiag(ctx, record);
|
|
233
|
-
return json$
|
|
234
|
+
return json$2({
|
|
234
235
|
...body,
|
|
235
236
|
diag: record
|
|
236
237
|
});
|
|
@@ -302,7 +303,7 @@ async function listEfforts(ctx, provider, model) {
|
|
|
302
303
|
};
|
|
303
304
|
}
|
|
304
305
|
}
|
|
305
|
-
function json$
|
|
306
|
+
function json$2(body, status = 200) {
|
|
306
307
|
return new Response(JSON.stringify(body), {
|
|
307
308
|
status,
|
|
308
309
|
headers: { "content-type": "application/json" }
|
|
@@ -323,7 +324,7 @@ function registerSuggestRoute(ctx) {
|
|
|
323
324
|
path: SUGGEST_MODELS_PATH,
|
|
324
325
|
methods: ["GET"],
|
|
325
326
|
requestBody: "buffered",
|
|
326
|
-
fetch: async () => json$
|
|
327
|
+
fetch: async () => json$2(await listModels(ctx))
|
|
327
328
|
}));
|
|
328
329
|
disposers.push(registry.register({
|
|
329
330
|
path: SUGGEST_EFFORTS_PATH,
|
|
@@ -331,11 +332,11 @@ function registerSuggestRoute(ctx) {
|
|
|
331
332
|
requestBody: "buffered",
|
|
332
333
|
fetch: async (request) => {
|
|
333
334
|
const route = splitRoute(new URL(request.url).searchParams.get("model") ?? "");
|
|
334
|
-
if (route === null) return json$
|
|
335
|
+
if (route === null) return json$2({
|
|
335
336
|
efforts: [],
|
|
336
337
|
defaultEffort: null
|
|
337
338
|
});
|
|
338
|
-
return json$
|
|
339
|
+
return json$2(await listEfforts(ctx, route.provider, route.model));
|
|
339
340
|
}
|
|
340
341
|
}));
|
|
341
342
|
} catch (error) {
|
|
@@ -468,7 +469,7 @@ const EMPTY_PROJECTION = {
|
|
|
468
469
|
replacedRanges: [],
|
|
469
470
|
shadowedSeqs: []
|
|
470
471
|
};
|
|
471
|
-
function json(body, status = 200) {
|
|
472
|
+
function json$1(body, status = 200) {
|
|
472
473
|
return new Response(JSON.stringify(body), {
|
|
473
474
|
status,
|
|
474
475
|
headers: { "content-type": "application/json" }
|
|
@@ -513,12 +514,12 @@ async function handleSessionInfo(ctx, request) {
|
|
|
513
514
|
try {
|
|
514
515
|
sessionId = (await request.json())?.sessionId;
|
|
515
516
|
} catch {
|
|
516
|
-
return json(EMPTY_PROJECTION, 400);
|
|
517
|
+
return json$1(EMPTY_PROJECTION, 400);
|
|
517
518
|
}
|
|
518
|
-
if (typeof sessionId !== "string" || sessionId === "") return json(EMPTY_PROJECTION, 400);
|
|
519
|
+
if (typeof sessionId !== "string" || sessionId === "") return json$1(EMPTY_PROJECTION, 400);
|
|
519
520
|
const events = await readAllSessionEvents(ctx, sessionId);
|
|
520
|
-
if (events === null) return json(EMPTY_PROJECTION);
|
|
521
|
-
return json(projectSkills(events));
|
|
521
|
+
if (events === null) return json$1(EMPTY_PROJECTION);
|
|
522
|
+
return json$1(projectSkills(events));
|
|
522
523
|
}
|
|
523
524
|
function registerSessionInfoRoute(ctx) {
|
|
524
525
|
const connection = ctx.get("connection");
|
|
@@ -535,6 +536,192 @@ function registerSessionInfoRoute(ctx) {
|
|
|
535
536
|
};
|
|
536
537
|
}
|
|
537
538
|
//#endregion
|
|
539
|
+
//#region src/shared/tools-manager.ts
|
|
540
|
+
const DISABLED_TOOL_PREFIX = "tool is disabled by desktop-enhance:";
|
|
541
|
+
function compareCodeUnits(a, b) {
|
|
542
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
543
|
+
}
|
|
544
|
+
function parseDisabledTools(raw) {
|
|
545
|
+
const out = new Set();
|
|
546
|
+
if (typeof raw !== "string" || raw.length === 0) return out;
|
|
547
|
+
for (const piece of raw.split(/[\s,]+/)) {
|
|
548
|
+
const trimmed = piece.trim();
|
|
549
|
+
if (trimmed !== "") out.add(trimmed);
|
|
550
|
+
}
|
|
551
|
+
return out;
|
|
552
|
+
}
|
|
553
|
+
function disabledToolReason(toolName, enabled, disabled) {
|
|
554
|
+
if (!enabled || disabled.size === 0) return void 0;
|
|
555
|
+
if (disabled.has(toolName)) return `${DISABLED_TOOL_PREFIX} ${JSON.stringify(toolName)}`;
|
|
556
|
+
}
|
|
557
|
+
function filterToolSchemas(tools, enabled, disabled) {
|
|
558
|
+
if (!enabled || disabled.size === 0) return [...tools];
|
|
559
|
+
return tools.filter((tool) => !disabled.has(tool.name));
|
|
560
|
+
}
|
|
561
|
+
//#endregion
|
|
562
|
+
//#region src/tools-manager/host.ts
|
|
563
|
+
const TOOLS_PATH = TOOLS_ROUTE;
|
|
564
|
+
function json(body, status = 200) {
|
|
565
|
+
return new Response(JSON.stringify(body), {
|
|
566
|
+
status,
|
|
567
|
+
headers: { "content-type": "application/json" }
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
function isVolatileCell(cell) {
|
|
571
|
+
return cell !== null && typeof cell === "object" && typeof cell.get === "function";
|
|
572
|
+
}
|
|
573
|
+
function unwrapVolatile(cell) {
|
|
574
|
+
if (isVolatileCell(cell)) try {
|
|
575
|
+
return cell.get();
|
|
576
|
+
} catch {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
if (cell !== null && typeof cell === "object") return void 0;
|
|
580
|
+
return cell;
|
|
581
|
+
}
|
|
582
|
+
function readToolsConfig(config) {
|
|
583
|
+
if (config === null || config === void 0 || typeof config !== "object") return {
|
|
584
|
+
enabled: true,
|
|
585
|
+
disabled: new Set()
|
|
586
|
+
};
|
|
587
|
+
const raw = config;
|
|
588
|
+
const flag = unwrapVolatile(raw.toolsManager);
|
|
589
|
+
const list = unwrapVolatile(raw.disabledTools);
|
|
590
|
+
return {
|
|
591
|
+
enabled: typeof flag === "boolean" ? flag : true,
|
|
592
|
+
disabled: parseDisabledTools(list)
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
async function disposePresetLease(lease) {
|
|
596
|
+
if (lease === null || lease === void 0 || typeof lease !== "object") return;
|
|
597
|
+
try {
|
|
598
|
+
const asyncDispose = lease[Symbol.asyncDispose];
|
|
599
|
+
if (typeof asyncDispose === "function") {
|
|
600
|
+
await asyncDispose.call(lease);
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
603
|
+
const syncDispose = lease[Symbol.dispose];
|
|
604
|
+
if (typeof syncDispose === "function") syncDispose.call(lease);
|
|
605
|
+
} catch {}
|
|
606
|
+
}
|
|
607
|
+
function recordSchemas(target, list) {
|
|
608
|
+
if (!Array.isArray(list)) return;
|
|
609
|
+
for (const item of list) {
|
|
610
|
+
if (item === null || item === void 0 || typeof item !== "object") continue;
|
|
611
|
+
const name = typeof item.name === "string" ? item.name.trim() : "";
|
|
612
|
+
if (name === "" || name === "run_code" || target.has(name)) continue;
|
|
613
|
+
const description = typeof item.description === "string" ? item.description.trim() : "";
|
|
614
|
+
target.set(name, {
|
|
615
|
+
name,
|
|
616
|
+
description
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
async function collectAllToolSchemas(ctx) {
|
|
621
|
+
const toolsService = ctx.get("tools");
|
|
622
|
+
if (toolsService === null || toolsService === void 0 || typeof toolsService.schemas !== "function") return [];
|
|
623
|
+
const collected = new Map();
|
|
624
|
+
try {
|
|
625
|
+
recordSchemas(collected, toolsService.schemas());
|
|
626
|
+
} catch {}
|
|
627
|
+
const presetsService = ctx.get("agentPresets");
|
|
628
|
+
if (presetsService !== null && presetsService !== void 0 && typeof presetsService.list === "function" && typeof presetsService.acquireScope === "function") {
|
|
629
|
+
let presets = [];
|
|
630
|
+
try {
|
|
631
|
+
const rows = await presetsService.list();
|
|
632
|
+
if (Array.isArray(rows)) presets = rows;
|
|
633
|
+
} catch {}
|
|
634
|
+
for (const row of presets) {
|
|
635
|
+
if (row === null || row === void 0 || typeof row !== "object") continue;
|
|
636
|
+
if (row.broken !== void 0 && row.broken !== null && row.broken !== "") continue;
|
|
637
|
+
const id = typeof row.id === "string" ? row.id.trim() : "";
|
|
638
|
+
if (id === "") continue;
|
|
639
|
+
let lease;
|
|
640
|
+
try {
|
|
641
|
+
lease = await presetsService.acquireScope(id);
|
|
642
|
+
if (lease !== null && lease !== void 0 && lease.key !== void 0) recordSchemas(collected, toolsService.schemas(lease.key));
|
|
643
|
+
} catch {} finally {
|
|
644
|
+
await disposePresetLease(lease);
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
try {
|
|
649
|
+
const scopedMap = toolsService.layers?.scoped;
|
|
650
|
+
if (scopedMap !== void 0 && typeof scopedMap.keys === "function") for (const scopeKey of scopedMap.keys()) try {
|
|
651
|
+
recordSchemas(collected, toolsService.schemas(scopeKey));
|
|
652
|
+
} catch {}
|
|
653
|
+
} catch {}
|
|
654
|
+
return [...collected.values()].sort((a, b) => compareCodeUnits(a.name, b.name));
|
|
655
|
+
}
|
|
656
|
+
function installToolsPolicy(ctx, readState) {
|
|
657
|
+
const disposers = [];
|
|
658
|
+
if (typeof ctx.on === "function") try {
|
|
659
|
+
const offAssemble = ctx.on("system-prompt/assemble", async (_assembly, _context, next) => {
|
|
660
|
+
const result = await next();
|
|
661
|
+
const { enabled, disabled } = readState();
|
|
662
|
+
if (!enabled || disabled.size === 0 || !Array.isArray(result?.tools)) return result;
|
|
663
|
+
const filtered = filterToolSchemas(result.tools, enabled, disabled);
|
|
664
|
+
if (filtered.length === result.tools.length) return result;
|
|
665
|
+
return {
|
|
666
|
+
...result,
|
|
667
|
+
tools: filtered
|
|
668
|
+
};
|
|
669
|
+
});
|
|
670
|
+
if (typeof offAssemble === "function") disposers.push(offAssemble);
|
|
671
|
+
} catch (error) {
|
|
672
|
+
ctx.logger?.warn(`desktop-enhance: tools assemble hook failed: ${String(error)}`);
|
|
673
|
+
}
|
|
674
|
+
const attachGuard = (targetCtx) => {
|
|
675
|
+
const toolsService = targetCtx.get("tools");
|
|
676
|
+
if (toolsService === null || toolsService === void 0 || typeof toolsService.guard !== "function") return;
|
|
677
|
+
try {
|
|
678
|
+
const offGuard = toolsService.guard((exec) => {
|
|
679
|
+
const { enabled, disabled } = readState();
|
|
680
|
+
return disabledToolReason(exec.name, enabled, disabled);
|
|
681
|
+
});
|
|
682
|
+
if (typeof offGuard === "function") disposers.push(offGuard);
|
|
683
|
+
} catch (error) {
|
|
684
|
+
targetCtx.logger?.warn(`desktop-enhance: tools guard failed: ${String(error)}`);
|
|
685
|
+
}
|
|
686
|
+
};
|
|
687
|
+
const toolsNow = ctx.get("tools");
|
|
688
|
+
if (toolsNow !== null && toolsNow !== void 0 && typeof toolsNow.guard === "function") attachGuard(ctx);
|
|
689
|
+
else if (typeof ctx.inject === "function") try {
|
|
690
|
+
const offInject = ctx.inject(["tools"], (tctx) => {
|
|
691
|
+
attachGuard(tctx);
|
|
692
|
+
});
|
|
693
|
+
if (typeof offInject === "function") disposers.push(() => {
|
|
694
|
+
offInject();
|
|
695
|
+
});
|
|
696
|
+
} catch {}
|
|
697
|
+
return () => {
|
|
698
|
+
for (const dispose of disposers.splice(0)) try {
|
|
699
|
+
dispose();
|
|
700
|
+
} catch {}
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
async function handleToolsCatalog(ctx) {
|
|
704
|
+
try {
|
|
705
|
+
return json({ tools: await collectAllToolSchemas(ctx) });
|
|
706
|
+
} catch {
|
|
707
|
+
return json({ tools: [] });
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
function registerToolsRoute(ctx) {
|
|
711
|
+
const connection = ctx.get("connection");
|
|
712
|
+
const register = connection?.fetch?.register;
|
|
713
|
+
if (typeof register !== "function") return () => {};
|
|
714
|
+
const dispose = register.call(connection?.fetch, {
|
|
715
|
+
path: TOOLS_PATH,
|
|
716
|
+
methods: ["GET"],
|
|
717
|
+
requestBody: "buffered",
|
|
718
|
+
fetch: () => handleToolsCatalog(ctx)
|
|
719
|
+
});
|
|
720
|
+
return () => {
|
|
721
|
+
Promise.resolve().then(() => dispose()).catch(() => void 0);
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
//#endregion
|
|
538
725
|
//#region src/index.ts
|
|
539
726
|
const Config = Schema.object({
|
|
540
727
|
findBar: Schema.boolean().default(true).volatile(),
|
|
@@ -543,11 +730,13 @@ const Config = Schema.object({
|
|
|
543
730
|
suggest: Schema.boolean().default(true).volatile(),
|
|
544
731
|
stepDuration: Schema.boolean().default(true).volatile(),
|
|
545
732
|
sessionInfo: Schema.boolean().default(true).volatile(),
|
|
733
|
+
toolsManager: Schema.boolean().default(true).volatile(),
|
|
546
734
|
suggestModel: Schema.string().default("").volatile(),
|
|
547
735
|
suggestReasoning: Schema.string().default("").volatile(),
|
|
548
|
-
suggestPrompt: Schema.string().default("").volatile()
|
|
736
|
+
suggestPrompt: Schema.string().default("").volatile(),
|
|
737
|
+
disabledTools: Schema.string().default("").volatile()
|
|
549
738
|
});
|
|
550
|
-
function apply(ctx) {
|
|
739
|
+
function apply(ctx, config) {
|
|
551
740
|
ctx.inject(["connection"], (serviceCtx) => {
|
|
552
741
|
try {
|
|
553
742
|
serviceCtx.effect(() => registerSuggestRoute(serviceCtx), "desktop-enhance: suggest route");
|
|
@@ -559,6 +748,16 @@ function apply(ctx) {
|
|
|
559
748
|
} catch (error) {
|
|
560
749
|
serviceCtx.logger?.warn(`desktop-enhance: session-info route not registered: ${String(error)}`);
|
|
561
750
|
}
|
|
751
|
+
try {
|
|
752
|
+
serviceCtx.effect(() => registerToolsRoute(serviceCtx), "desktop-enhance: tools route");
|
|
753
|
+
} catch (error) {
|
|
754
|
+
serviceCtx.logger?.warn(`desktop-enhance: tools route not registered: ${String(error)}`);
|
|
755
|
+
}
|
|
756
|
+
try {
|
|
757
|
+
serviceCtx.effect(() => installToolsPolicy(serviceCtx, () => readToolsConfig(config)), "desktop-enhance: tools policy");
|
|
758
|
+
} catch (error) {
|
|
759
|
+
serviceCtx.logger?.warn(`desktop-enhance: tools policy not installed: ${String(error)}`);
|
|
760
|
+
}
|
|
562
761
|
});
|
|
563
762
|
}
|
|
564
763
|
const __test = {
|
|
@@ -566,6 +765,7 @@ const __test = {
|
|
|
566
765
|
SUGGEST_MODELS_PATH,
|
|
567
766
|
SUGGEST_EFFORTS_PATH,
|
|
568
767
|
SESSION_INFO_PATH,
|
|
768
|
+
TOOLS_PATH,
|
|
569
769
|
MODEL_TIMEOUT_MS,
|
|
570
770
|
MAX_OUTPUT_TOKENS,
|
|
571
771
|
buildPrompt,
|
|
@@ -574,8 +774,13 @@ const __test = {
|
|
|
574
774
|
knownNamesOf,
|
|
575
775
|
handleSuggest,
|
|
576
776
|
handleSessionInfo,
|
|
777
|
+
handleToolsCatalog,
|
|
778
|
+
collectAllToolSchemas,
|
|
779
|
+
installToolsPolicy,
|
|
780
|
+
readToolsConfig,
|
|
577
781
|
registerSuggestRoute,
|
|
578
782
|
registerSessionInfoRoute,
|
|
783
|
+
registerToolsRoute,
|
|
579
784
|
routeOf,
|
|
580
785
|
quietEffortFor,
|
|
581
786
|
listModels,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-desktop-enhance",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "DSH Desktop 界面增强:页内查找(Cmd+F
|
|
3
|
+
"version": "0.2.6",
|
|
4
|
+
"description": "DSH Desktop 界面增强:页内查找(Cmd+F)、轮次编号、上下文压缩行常显、建议、每步耗时、会话信息、工具管理。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./lib/index.js",
|