dsh-desktop-enhance 0.3.0 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -25,6 +25,12 @@ window.__ModuleLoader__.load({
25
25
  "sessionInfo.skills.title": "已注入 Skill",
26
26
  "sessionInfo.skills.short": "Skill",
27
27
  "sessionInfo.skills.empty": "暂无已注入 Skill",
28
+ "sessionInfo.skills.available": "可用 Skill",
29
+ "sessionInfo.skills.manage": "管理 ↗",
30
+ "sessionInfo.skills.close": "收起 ✕",
31
+ "sessionInfo.skills.disabledPrefix": "已禁用:",
32
+ "sessionInfo.skills.popoverTitle": "当前会话 Skill 管理",
33
+ "sessionInfo.skills.popoverHint": "默认继承全局设置;在此修改仅作用于当前会话,并自动触发 DSH 更新技能目录",
28
34
  "sessionInfo.trigger.user": "用户触发",
29
35
  "sessionInfo.trigger.agent": "Agent触发",
30
36
  "sessionInfo.tools.title": "可用工具",
@@ -32,8 +38,11 @@ window.__ModuleLoader__.load({
32
38
  "sessionInfo.tools.manage": "管理 ↗",
33
39
  "sessionInfo.tools.close": "收起 ✕",
34
40
  "sessionInfo.tools.disabledPrefix": "已禁用:",
35
- "sessionInfo.tools.popoverTitle": "全局工具管理",
36
- "sessionInfo.tools.popoverHint": "隐藏禁用工具的 Prompt Schema 并拒绝执行(跨会话生效)",
41
+ "sessionInfo.tools.popoverTitle": "当前会话工具管理",
42
+ "sessionInfo.tools.popoverHint": "默认继承全局设置;在此修改仅作用于当前会话(隐藏 Schema 并拒绝执行)",
43
+ "sessionInfo.override.badge": "已自定义",
44
+ "sessionInfo.override.banner": "当前会话已自定义(偏离全局默认设置)",
45
+ "sessionInfo.override.reset": "重置为全局默认",
37
46
  "settings.title": "UI 增强",
38
47
  "settings.description": "逐项开关本插件添加的界面增强。关闭后恢复 DSH 原生外观。",
39
48
  "settings.findBar": "页内查找",
@@ -49,8 +58,18 @@ window.__ModuleLoader__.load({
49
58
  "settings.sessionInfo": "会话信息",
50
59
  "settings.sessionInfo.hint": "在主对话区右上角悬浮展示当前会话的信息看板(如已注入的 Skill、触发方式与轮次),点击条目可打开 Skill 预览",
51
60
  "settings.toolsManager": "工具管理",
52
- "settings.toolsManager.hint": "在右上角「会话信息」看板中展示可用工具计数,点击「管理 ↗」弹出工具前缀树大浮层(支持搜索、单点与按前缀批量启停;禁用的工具对模型不可见且拒绝执行)",
53
- "settings.tools.search": "搜索工具名或描述…",
61
+ "settings.toolsManager.hint": "管理模型可用的工具(设置页配置跨会话全局默认,会话右上角「会话信息」可按单会话临时覆盖;被禁用的工具隐藏 Schema 且拒绝执行)",
62
+ "settings.skillsManager": "Skill 管理",
63
+ "settings.skillsManager.hint": "按项目级、全局级、插件注入三类来源查看并管理 Skill(设置页管理全局与插件 Skill 默认状态,会话右上角「会话信息」额外包含当前项目级 Skill 并支持单会话覆盖与预览)",
64
+ "settings.defaults.toolsTitle": "全局默认可用工具",
65
+ "settings.defaults.toolsHint": "所有项目与会话默认继承此配置;可在单个会话右上角临时覆盖",
66
+ "settings.defaults.skillsTitle": "全局默认可用 Skill",
67
+ "settings.defaults.skillsHint": "管理跨项目共享的全局级与插件注入 Skill(项目级 Skill 请在对应会话右上角管理)",
68
+ "settings.defaults.manage": "管理全局默认 ↗",
69
+ "settings.defaults.close": "收起面板 ✕",
70
+ "settings.defaults.allEnabled": "默认全部启用",
71
+ "settings.defaults.enabledPrefix": "默认启用 ",
72
+ "settings.tools.search": "搜索工具名、描述或插件来源…",
54
73
  "settings.tools.refresh": "刷新列表",
55
74
  "settings.tools.enableAll": "全部启用",
56
75
  "settings.tools.disableAll": "全部禁用",
@@ -60,6 +79,15 @@ window.__ModuleLoader__.load({
60
79
  "settings.tools.disabled": "已禁用",
61
80
  "settings.tools.allDisabled": "全部已禁用",
62
81
  "settings.tools.empty": "没有匹配的工具。",
82
+ "settings.tools.scope.builtin": "内置工具",
83
+ "settings.tools.scope.plugin": "插件与 MCP 工具",
84
+ "settings.skills.search": "搜索 Skill 名称、描述或来源…",
85
+ "settings.skills.empty": "没有匹配的 Skill。",
86
+ "settings.skills.scope.project": "项目级 Skill",
87
+ "settings.skills.scope.global": "全局级 Skill",
88
+ "settings.skills.scope.plugin": "插件与内置 Skill",
89
+ "settings.skills.userOnly": "仅手动 /",
90
+ "settings.skills.preview": "预览 ↗",
63
91
  "settings.suggestModel": "建议用哪个模型",
64
92
  "settings.suggestModel.hint": "留空则跟随当前会话的模型;建议选一个非推理的轻量模型,否则每条建议都要等它想完",
65
93
  "settings.suggestModel.follow": "跟随当前会话",
@@ -100,6 +128,12 @@ window.__ModuleLoader__.load({
100
128
  "sessionInfo.skills.title": "Active skills",
101
129
  "sessionInfo.skills.short": "Skill",
102
130
  "sessionInfo.skills.empty": "No active skills",
131
+ "sessionInfo.skills.available": "Available skills",
132
+ "sessionInfo.skills.manage": "Manage ↗",
133
+ "sessionInfo.skills.close": "Close ✕",
134
+ "sessionInfo.skills.disabledPrefix": "Disabled: ",
135
+ "sessionInfo.skills.popoverTitle": "Session skills manager",
136
+ "sessionInfo.skills.popoverHint": "Inherits global defaults; changes here apply only to this session and refresh the DSH skill catalog",
103
137
  "sessionInfo.trigger.user": "User",
104
138
  "sessionInfo.trigger.agent": "Agent",
105
139
  "sessionInfo.tools.title": "Available tools",
@@ -107,8 +141,11 @@ window.__ModuleLoader__.load({
107
141
  "sessionInfo.tools.manage": "Manage ↗",
108
142
  "sessionInfo.tools.close": "Close ✕",
109
143
  "sessionInfo.tools.disabledPrefix": "Disabled: ",
110
- "sessionInfo.tools.popoverTitle": "Global tools manager",
111
- "sessionInfo.tools.popoverHint": "Hides disabled tools from the model prompt schema and denies execution across sessions",
144
+ "sessionInfo.tools.popoverTitle": "Session tools manager",
145
+ "sessionInfo.tools.popoverHint": "Inherits global defaults; changes here apply only to this session (hides schema and denies execution)",
146
+ "sessionInfo.override.badge": "Customized",
147
+ "sessionInfo.override.banner": "Customized for this session (differs from global default)",
148
+ "sessionInfo.override.reset": "Reset to global default",
112
149
  "settings.title": "UI enhancements",
113
150
  "settings.description": "Switch each interface enhancement this plugin adds. Turning one off restores the native DSH look.",
114
151
  "settings.findBar": "Find in conversation",
@@ -124,8 +161,18 @@ window.__ModuleLoader__.load({
124
161
  "settings.sessionInfo": "Session info",
125
162
  "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",
126
163
  "settings.toolsManager": "Tools manager",
127
- "settings.toolsManager.hint": "Shows an available-tools summary row inside the top-right Session Info card; click \"Manage ↗\" to open the prefix-tree popover for individual and batch tool toggling",
128
- "settings.tools.search": "Search tool name or description…",
164
+ "settings.toolsManager.hint": "Manage model-visible tools (configure global defaults here and per-session overrides in the top-right Session Info card; disabled tools are hidden from the prompt schema and blocked at execution)",
165
+ "settings.skillsManager": "Skills manager",
166
+ "settings.skillsManager.hint": "Inspect and toggle skills grouped by Project, Global, and Plugin sources (configure global defaults here and per-session overrides with SKILL.md preview in the top-right Session Info card)",
167
+ "settings.defaults.toolsTitle": "Global default tools",
168
+ "settings.defaults.toolsHint": "Inherited by all projects and sessions by default; can be overridden per session in the top-right Session Info card",
169
+ "settings.defaults.skillsTitle": "Global default skills",
170
+ "settings.defaults.skillsHint": "Manage global and plugin-injected skills shared across projects (project-level skills are managed inside each session)",
171
+ "settings.defaults.manage": "Manage defaults ↗",
172
+ "settings.defaults.close": "Close panel ✕",
173
+ "settings.defaults.allEnabled": "All enabled by default",
174
+ "settings.defaults.enabledPrefix": "Enabled ",
175
+ "settings.tools.search": "Search tool name, description, or plugin…",
129
176
  "settings.tools.refresh": "Refresh",
130
177
  "settings.tools.enableAll": "Enable all",
131
178
  "settings.tools.disableAll": "Disable all",
@@ -135,6 +182,15 @@ window.__ModuleLoader__.load({
135
182
  "settings.tools.disabled": "Disabled",
136
183
  "settings.tools.allDisabled": "All disabled",
137
184
  "settings.tools.empty": "No matching tools.",
185
+ "settings.tools.scope.builtin": "Built-in tools",
186
+ "settings.tools.scope.plugin": "Plugin & MCP tools",
187
+ "settings.skills.search": "Search skill name, description, or source…",
188
+ "settings.skills.empty": "No matching skills.",
189
+ "settings.skills.scope.project": "Project skills",
190
+ "settings.skills.scope.global": "Global skills",
191
+ "settings.skills.scope.plugin": "Plugin & bundled skills",
192
+ "settings.skills.userOnly": "Manual / only",
193
+ "settings.skills.preview": "Preview ↗",
138
194
  "settings.suggestModel": "Model for suggestions",
139
195
  "settings.suggestModel.hint": "Empty follows the current session model. Prefer a lightweight non-reasoning model, or every suggestion waits for it to finish thinking",
140
196
  "settings.suggestModel.follow": "Follow the current session",
@@ -421,7 +477,8 @@ window.__ModuleLoader__.load({
421
477
  suggest: "data-desktop-enhance-off-suggest",
422
478
  stepDuration: "data-desktop-enhance-off-step-duration",
423
479
  sessionInfo: "data-desktop-enhance-off-session-info",
424
- toolsManager: "data-desktop-enhance-off-tools-manager"
480
+ toolsManager: "data-desktop-enhance-off-tools-manager",
481
+ skillsManager: "data-desktop-enhance-off-skills-manager"
425
482
  };
426
483
  const FIELDS = [
427
484
  "findBar",
@@ -430,7 +487,8 @@ window.__ModuleLoader__.load({
430
487
  "suggest",
431
488
  "stepDuration",
432
489
  "sessionInfo",
433
- "toolsManager"
490
+ "toolsManager",
491
+ "skillsManager"
434
492
  ];
435
493
  const ALL_FIELDS = [...FIELDS, ...TEXT_FIELDS];
436
494
  function flagOn(value, field) {
@@ -498,6 +556,7 @@ window.__ModuleLoader__.load({
498
556
  const SUGGEST_MODELS_ROUTE = "/api/desktop-enhance/suggest-models";
499
557
  const SESSION_INFO_ROUTE = "/api/desktop-enhance/session-info";
500
558
  const TOOLS_ROUTE = "/api/desktop-enhance/tools";
559
+ const SKILLS_ROUTE = "/api/desktop-enhance/skills";
501
560
  //#endregion
502
561
  //#region src/client/settings/catalog.ts
503
562
  function parseModelCatalog(body) {
@@ -555,6 +614,7 @@ window.__ModuleLoader__.load({
555
614
  const CACHE_MS = 3e4;
556
615
  const SUGGEST_MODELS_URL = SUGGEST_MODELS_ROUTE;
557
616
  const TOOLS_URL = TOOLS_ROUTE;
617
+ const SKILLS_URL = SKILLS_ROUTE;
558
618
  function createCatalogCache(now = () => Date.now()) {
559
619
  const hits = new Map();
560
620
  const pending = new Map();
@@ -679,6 +739,1094 @@ window.__ModuleLoader__.load({
679
739
  };
680
740
  }
681
741
  //#endregion
742
+ //#region src/shared/tools-manager.ts
743
+ const TOOL_SCOPE_ORDER = ["builtin", "plugin"];
744
+ const DISABLED_TOOL_PREFIX = "tool is disabled by desktop-enhance:";
745
+ function compareCodeUnits(a, b) {
746
+ return a < b ? -1 : a > b ? 1 : 0;
747
+ }
748
+ function parseDisabledTools(raw) {
749
+ const out = new Set();
750
+ if (typeof raw !== "string" || raw.length === 0) return out;
751
+ for (const piece of raw.split(/[\s,]+/)) {
752
+ const trimmed = piece.trim();
753
+ if (trimmed !== "") out.add(trimmed);
754
+ }
755
+ return out;
756
+ }
757
+ function formatDisabledTools(names) {
758
+ const unique = new Set();
759
+ for (const name of names) if (typeof name === "string") {
760
+ const trimmed = name.trim();
761
+ if (trimmed !== "") unique.add(trimmed);
762
+ }
763
+ return [...unique].sort(compareCodeUnits).join(",");
764
+ }
765
+ const ACTION_VERB_PREFIXES = new Set([
766
+ "add",
767
+ "call",
768
+ "check",
769
+ "clear",
770
+ "close",
771
+ "create",
772
+ "delete",
773
+ "edit",
774
+ "enable",
775
+ "disable",
776
+ "enter",
777
+ "exit",
778
+ "fetch",
779
+ "find",
780
+ "generate",
781
+ "get",
782
+ "interrupt",
783
+ "kill",
784
+ "list",
785
+ "load",
786
+ "open",
787
+ "query",
788
+ "remove",
789
+ "reset",
790
+ "resolve",
791
+ "run",
792
+ "save",
793
+ "search",
794
+ "select",
795
+ "send",
796
+ "set",
797
+ "show",
798
+ "spawn",
799
+ "start",
800
+ "stop",
801
+ "trigger",
802
+ "update",
803
+ "verify",
804
+ "view",
805
+ "wait",
806
+ "write"
807
+ ]);
808
+ const OPTIONAL_OFFICIAL_TOOL_PACKAGES = new Set([
809
+ "@deepseek-ai/dsh-tool-terminal",
810
+ "@deepseek-ai/dsh-tool-session-query",
811
+ "@deepseek-ai/dsh-tool-ralph",
812
+ "@deepseek-ai/dsh-mcp-resources",
813
+ "@deepseek-ai/dsh-mcp-client"
814
+ ]);
815
+ function isPluginToolPackage(pkg) {
816
+ if (pkg.startsWith("mcp:")) return true;
817
+ if (!pkg.startsWith("@deepseek-ai/")) return true;
818
+ if (pkg.startsWith("@deepseek-ai/dsh-experimental-")) return true;
819
+ return OPTIONAL_OFFICIAL_TOOL_PACKAGES.has(pkg);
820
+ }
821
+ const BUILTIN_TOOL_PACKAGES = new Map([
822
+ ["@deepseek-ai/dsh-tool-bash", "bash"],
823
+ ["@deepseek-ai/dsh-tool-bash-persistent", "bash"],
824
+ ["@deepseek-ai/dsh-tool-pwsh", "pwsh"],
825
+ ["@deepseek-ai/dsh-tool-pwsh-persistent", "pwsh"],
826
+ ["@deepseek-ai/dsh-tool-fs", "fs"],
827
+ ["@deepseek-ai/dsh-tool-fs-search", "fs_search"],
828
+ ["@deepseek-ai/dsh-tool-str-replace-editor", "str_replace_editor"],
829
+ ["@deepseek-ai/dsh-tool-working-directory", "working_directory"],
830
+ ["@deepseek-ai/dsh-tool-workspace-dependencies", "workspace_dependencies"],
831
+ ["@deepseek-ai/dsh-tool-jobs", "job"],
832
+ ["@deepseek-ai/dsh-tool-schedule", "schedule"],
833
+ ["@deepseek-ai/dsh-schedule", "schedule"],
834
+ ["@deepseek-ai/dsh-tool-goal", "goal"],
835
+ ["@deepseek-ai/dsh-plan-mode", "plan"],
836
+ ["@deepseek-ai/dsh-tool-todo", "todo"],
837
+ ["@deepseek-ai/dsh-tool-ask-user", "ask_user"],
838
+ ["@deepseek-ai/dsh-tool-skill", "skill"],
839
+ ["@deepseek-ai/dsh-tool-present", "present"],
840
+ ["@deepseek-ai/dsh-tool-web", "web"],
841
+ ["@deepseek-ai/dsh-tool-subagent", "subagent"],
842
+ ["@deepseek-ai/dsh-tool-subagent-control", "subagent"],
843
+ ["@deepseek-ai/dsh-subagent", "subagent"],
844
+ ["@deepseek-ai/dsh-tool-workflow", "workflow"],
845
+ ["@deepseek-ai/dsh-tool-cordis", "cordis_inspect"],
846
+ ["@deepseek-ai/dsh-cordis-host-runner", "cordis_inspect"],
847
+ ["@deepseek-ai/dsh-plugin-manager", "plugin_manager"],
848
+ ["@deepseek-ai/dsh-plugin-market", "plugin_manager"],
849
+ ["@deepseek-ai/dsh-tools", "builtin"]
850
+ ]);
851
+ const KNOWN_TOOL_SPECS = {
852
+ bash: {
853
+ scope: "builtin",
854
+ pluginName: "@deepseek-ai/dsh-tool-bash",
855
+ groupKey: "bash"
856
+ },
857
+ pwsh: {
858
+ scope: "builtin",
859
+ pluginName: "@deepseek-ai/dsh-tool-pwsh",
860
+ groupKey: "pwsh"
861
+ },
862
+ read: {
863
+ scope: "builtin",
864
+ pluginName: "@deepseek-ai/dsh-tool-fs",
865
+ groupKey: "read"
866
+ },
867
+ read_image: {
868
+ scope: "builtin",
869
+ pluginName: "@deepseek-ai/dsh-tool-fs",
870
+ groupKey: "read"
871
+ },
872
+ write: {
873
+ scope: "builtin",
874
+ pluginName: "@deepseek-ai/dsh-tool-fs",
875
+ groupKey: "write"
876
+ },
877
+ edit: {
878
+ scope: "builtin",
879
+ pluginName: "@deepseek-ai/dsh-tool-fs",
880
+ groupKey: "edit"
881
+ },
882
+ str_replace_editor: {
883
+ scope: "builtin",
884
+ pluginName: "@deepseek-ai/dsh-tool-str-replace-editor",
885
+ groupKey: "str_replace_editor"
886
+ },
887
+ glob: {
888
+ scope: "builtin",
889
+ pluginName: "@deepseek-ai/dsh-tool-fs-search",
890
+ groupKey: "glob"
891
+ },
892
+ grep: {
893
+ scope: "builtin",
894
+ pluginName: "@deepseek-ai/dsh-tool-fs-search",
895
+ groupKey: "grep"
896
+ },
897
+ working_directory: {
898
+ scope: "builtin",
899
+ pluginName: "@deepseek-ai/dsh-tool-working-directory",
900
+ groupKey: "working_directory"
901
+ },
902
+ load_workspace_dependencies: {
903
+ scope: "builtin",
904
+ pluginName: "@deepseek-ai/dsh-tool-workspace-dependencies",
905
+ groupKey: "load_workspace_dependencies"
906
+ },
907
+ job_output: {
908
+ scope: "builtin",
909
+ pluginName: "@deepseek-ai/dsh-tool-jobs",
910
+ groupKey: "job"
911
+ },
912
+ job_list: {
913
+ scope: "builtin",
914
+ pluginName: "@deepseek-ai/dsh-tool-jobs",
915
+ groupKey: "job"
916
+ },
917
+ job_kill: {
918
+ scope: "builtin",
919
+ pluginName: "@deepseek-ai/dsh-tool-jobs",
920
+ groupKey: "job"
921
+ },
922
+ schedule_create: {
923
+ scope: "builtin",
924
+ pluginName: "@deepseek-ai/dsh-tool-schedule",
925
+ groupKey: "schedule"
926
+ },
927
+ schedule_list: {
928
+ scope: "builtin",
929
+ pluginName: "@deepseek-ai/dsh-tool-schedule",
930
+ groupKey: "schedule"
931
+ },
932
+ schedule_update: {
933
+ scope: "builtin",
934
+ pluginName: "@deepseek-ai/dsh-tool-schedule",
935
+ groupKey: "schedule"
936
+ },
937
+ schedule_delete: {
938
+ scope: "builtin",
939
+ pluginName: "@deepseek-ai/dsh-tool-schedule",
940
+ groupKey: "schedule"
941
+ },
942
+ create_goal: {
943
+ scope: "builtin",
944
+ pluginName: "@deepseek-ai/dsh-tool-goal",
945
+ groupKey: "goal"
946
+ },
947
+ get_goal: {
948
+ scope: "builtin",
949
+ pluginName: "@deepseek-ai/dsh-tool-goal",
950
+ groupKey: "goal"
951
+ },
952
+ update_goal: {
953
+ scope: "builtin",
954
+ pluginName: "@deepseek-ai/dsh-tool-goal",
955
+ groupKey: "goal"
956
+ },
957
+ plan: {
958
+ scope: "builtin",
959
+ pluginName: "@deepseek-ai/dsh-plan-mode",
960
+ groupKey: "plan"
961
+ },
962
+ exit_plan_mode: {
963
+ scope: "builtin",
964
+ pluginName: "@deepseek-ai/dsh-plan-mode",
965
+ groupKey: "plan"
966
+ },
967
+ todo_write: {
968
+ scope: "builtin",
969
+ pluginName: "@deepseek-ai/dsh-tool-todo",
970
+ groupKey: "todo_write"
971
+ },
972
+ ask_user_question: {
973
+ scope: "builtin",
974
+ pluginName: "@deepseek-ai/dsh-tool-ask-user",
975
+ groupKey: "ask_user_question"
976
+ },
977
+ skill: {
978
+ scope: "builtin",
979
+ pluginName: "@deepseek-ai/dsh-tool-skill",
980
+ groupKey: "skill"
981
+ },
982
+ present: {
983
+ scope: "builtin",
984
+ pluginName: "@deepseek-ai/dsh-tool-present",
985
+ groupKey: "present"
986
+ },
987
+ web_search: {
988
+ scope: "builtin",
989
+ pluginName: "@deepseek-ai/dsh-tool-web",
990
+ groupKey: "web"
991
+ },
992
+ web_fetch: {
993
+ scope: "builtin",
994
+ pluginName: "@deepseek-ai/dsh-tool-web",
995
+ groupKey: "web"
996
+ },
997
+ subagent: {
998
+ scope: "builtin",
999
+ pluginName: "@deepseek-ai/dsh-tool-subagent",
1000
+ groupKey: "subagent"
1001
+ },
1002
+ subagent_fork: {
1003
+ scope: "builtin",
1004
+ pluginName: "@deepseek-ai/dsh-tool-subagent",
1005
+ groupKey: "subagent"
1006
+ },
1007
+ list_subagent_models: {
1008
+ scope: "builtin",
1009
+ pluginName: "@deepseek-ai/dsh-tool-subagent",
1010
+ groupKey: "subagent"
1011
+ },
1012
+ send_message: {
1013
+ scope: "builtin",
1014
+ pluginName: "@deepseek-ai/dsh-tool-subagent-control",
1015
+ groupKey: "subagent"
1016
+ },
1017
+ interrupt_agent: {
1018
+ scope: "builtin",
1019
+ pluginName: "@deepseek-ai/dsh-tool-subagent-control",
1020
+ groupKey: "subagent"
1021
+ },
1022
+ list_agents: {
1023
+ scope: "builtin",
1024
+ pluginName: "@deepseek-ai/dsh-tool-subagent-control",
1025
+ groupKey: "subagent"
1026
+ },
1027
+ workflow: {
1028
+ scope: "builtin",
1029
+ pluginName: "@deepseek-ai/dsh-tool-workflow",
1030
+ groupKey: "workflow"
1031
+ },
1032
+ cordis_inspect_list: {
1033
+ scope: "builtin",
1034
+ pluginName: "@deepseek-ai/dsh-tool-cordis",
1035
+ groupKey: "cordis_inspect"
1036
+ },
1037
+ cordis_inspect_query: {
1038
+ scope: "builtin",
1039
+ pluginName: "@deepseek-ai/dsh-tool-cordis",
1040
+ groupKey: "cordis_inspect"
1041
+ },
1042
+ cordis_dynamic: {
1043
+ scope: "builtin",
1044
+ pluginName: "@deepseek-ai/dsh-cordis-host-runner",
1045
+ groupKey: "cordis_inspect"
1046
+ },
1047
+ plugin_manager: {
1048
+ scope: "builtin",
1049
+ pluginName: "@deepseek-ai/dsh-plugin-manager",
1050
+ groupKey: "plugin_manager"
1051
+ },
1052
+ plugin_market: {
1053
+ scope: "builtin",
1054
+ pluginName: "@deepseek-ai/dsh-plugin-market",
1055
+ groupKey: "plugin_manager"
1056
+ },
1057
+ create_worktree: {
1058
+ scope: "plugin",
1059
+ pluginName: "@deepseek-ai/dsh-experimental-tool-worktree",
1060
+ groupKey: "dsh-experimental-tool-worktree"
1061
+ },
1062
+ spawn_teammate: {
1063
+ scope: "plugin",
1064
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1065
+ groupKey: "dsh-experimental-tool-agent-team"
1066
+ },
1067
+ wait_agent: {
1068
+ scope: "plugin",
1069
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1070
+ groupKey: "dsh-experimental-tool-agent-team"
1071
+ },
1072
+ team_task_create: {
1073
+ scope: "plugin",
1074
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1075
+ groupKey: "dsh-experimental-tool-agent-team"
1076
+ },
1077
+ team_task_list: {
1078
+ scope: "plugin",
1079
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1080
+ groupKey: "dsh-experimental-tool-agent-team"
1081
+ },
1082
+ team_task_get: {
1083
+ scope: "plugin",
1084
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1085
+ groupKey: "dsh-experimental-tool-agent-team"
1086
+ },
1087
+ team_task_update: {
1088
+ scope: "plugin",
1089
+ pluginName: "@deepseek-ai/dsh-experimental-tool-agent-team",
1090
+ groupKey: "dsh-experimental-tool-agent-team"
1091
+ },
1092
+ terminal_open: {
1093
+ scope: "plugin",
1094
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1095
+ groupKey: "dsh-tool-terminal"
1096
+ },
1097
+ terminal_send: {
1098
+ scope: "plugin",
1099
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1100
+ groupKey: "dsh-tool-terminal"
1101
+ },
1102
+ terminal_read: {
1103
+ scope: "plugin",
1104
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1105
+ groupKey: "dsh-tool-terminal"
1106
+ },
1107
+ terminal_signal: {
1108
+ scope: "plugin",
1109
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1110
+ groupKey: "dsh-tool-terminal"
1111
+ },
1112
+ terminal_close: {
1113
+ scope: "plugin",
1114
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1115
+ groupKey: "dsh-tool-terminal"
1116
+ },
1117
+ terminal_list: {
1118
+ scope: "plugin",
1119
+ pluginName: "@deepseek-ai/dsh-tool-terminal",
1120
+ groupKey: "dsh-tool-terminal"
1121
+ },
1122
+ session_search: {
1123
+ scope: "plugin",
1124
+ pluginName: "@deepseek-ai/dsh-tool-session-query",
1125
+ groupKey: "dsh-tool-session-query"
1126
+ },
1127
+ session_event_search: {
1128
+ scope: "plugin",
1129
+ pluginName: "@deepseek-ai/dsh-tool-session-query",
1130
+ groupKey: "dsh-tool-session-query"
1131
+ },
1132
+ session_trace: {
1133
+ scope: "plugin",
1134
+ pluginName: "@deepseek-ai/dsh-tool-session-query",
1135
+ groupKey: "dsh-tool-session-query"
1136
+ },
1137
+ session_event_trace: {
1138
+ scope: "plugin",
1139
+ pluginName: "@deepseek-ai/dsh-tool-session-query",
1140
+ groupKey: "dsh-tool-session-query"
1141
+ },
1142
+ session_event_read: {
1143
+ scope: "plugin",
1144
+ pluginName: "@deepseek-ai/dsh-tool-session-query",
1145
+ groupKey: "dsh-tool-session-query"
1146
+ },
1147
+ ralph: {
1148
+ scope: "plugin",
1149
+ pluginName: "@deepseek-ai/dsh-tool-ralph",
1150
+ groupKey: "dsh-tool-ralph"
1151
+ },
1152
+ list_mcp_resources: {
1153
+ scope: "plugin",
1154
+ pluginName: "@deepseek-ai/dsh-mcp-resources",
1155
+ groupKey: "dsh-mcp-resources"
1156
+ },
1157
+ list_mcp_resource_templates: {
1158
+ scope: "plugin",
1159
+ pluginName: "@deepseek-ai/dsh-mcp-resources",
1160
+ groupKey: "dsh-mcp-resources"
1161
+ },
1162
+ read_mcp_resource: {
1163
+ scope: "plugin",
1164
+ pluginName: "@deepseek-ai/dsh-mcp-resources",
1165
+ groupKey: "dsh-mcp-resources"
1166
+ },
1167
+ sidebar_open: {
1168
+ scope: "plugin",
1169
+ pluginName: "dsh-better-sidebar",
1170
+ groupKey: "dsh-better-sidebar"
1171
+ },
1172
+ task_memory_write: {
1173
+ scope: "plugin",
1174
+ pluginName: "dsh-expedition-memory",
1175
+ groupKey: "dsh-expedition-memory"
1176
+ },
1177
+ task_memory_write_document: {
1178
+ scope: "plugin",
1179
+ pluginName: "dsh-expedition-memory",
1180
+ groupKey: "dsh-expedition-memory"
1181
+ },
1182
+ task_memory_update: {
1183
+ scope: "plugin",
1184
+ pluginName: "dsh-expedition-memory",
1185
+ groupKey: "dsh-expedition-memory"
1186
+ },
1187
+ task_memory_retire: {
1188
+ scope: "plugin",
1189
+ pluginName: "dsh-expedition-memory",
1190
+ groupKey: "dsh-expedition-memory"
1191
+ },
1192
+ canvas_state: {
1193
+ scope: "plugin",
1194
+ pluginName: "dsh-image-gen",
1195
+ groupKey: "dsh-image-gen"
1196
+ },
1197
+ view_canvas: {
1198
+ scope: "plugin",
1199
+ pluginName: "dsh-image-gen",
1200
+ groupKey: "dsh-image-gen"
1201
+ },
1202
+ generate_image: {
1203
+ scope: "plugin",
1204
+ pluginName: "dsh-image-gen",
1205
+ groupKey: "dsh-image-gen"
1206
+ },
1207
+ generate_images: {
1208
+ scope: "plugin",
1209
+ pluginName: "dsh-image-gen",
1210
+ groupKey: "dsh-image-gen"
1211
+ },
1212
+ edit_image: {
1213
+ scope: "plugin",
1214
+ pluginName: "dsh-image-gen",
1215
+ groupKey: "dsh-image-gen"
1216
+ },
1217
+ find_inspiration: {
1218
+ scope: "plugin",
1219
+ pluginName: "dsh-image-gen",
1220
+ groupKey: "dsh-image-gen"
1221
+ }
1222
+ };
1223
+ function normalizeBarePackageName(raw) {
1224
+ const trimmed = raw.trim();
1225
+ if (trimmed === "" || trimmed.startsWith("mcp:")) return trimmed;
1226
+ const parts = trimmed.split("/");
1227
+ if (trimmed.startsWith("@") && parts.length >= 2) return `${parts[0]}/${parts[1]}`;
1228
+ return parts[0] ?? trimmed;
1229
+ }
1230
+ function shortBadgeOfPackage(pkgName) {
1231
+ return pkgName.startsWith("@deepseek-ai/") ? pkgName.slice(13) : pkgName;
1232
+ }
1233
+ function makeMcpOrigin(rawServer) {
1234
+ const server = rawServer.trim() || "mcp";
1235
+ return {
1236
+ scope: "plugin",
1237
+ pluginName: `mcp:${server}`,
1238
+ sourceBadge: `mcp:${server}`,
1239
+ groupKey: `mcp__${server}`
1240
+ };
1241
+ }
1242
+ function makeKnownOrigin(spec) {
1243
+ const badge = shortBadgeOfPackage(spec.pluginName);
1244
+ return {
1245
+ scope: spec.scope,
1246
+ pluginName: spec.pluginName,
1247
+ sourceBadge: badge,
1248
+ groupKey: spec.groupKey ?? badge
1249
+ };
1250
+ }
1251
+ function splitToolName(name) {
1252
+ const parts = name.split("__");
1253
+ if (parts.length > 1) {
1254
+ const result = [];
1255
+ for (let i = 0; i < parts.length; i++) {
1256
+ const part = parts[i];
1257
+ if (part === void 0 || part === "") continue;
1258
+ if (i === 0 || i === parts.length - 1) result.push(part);
1259
+ else {
1260
+ const sub = part.split("_").filter((s) => s !== "");
1261
+ result.push(...sub);
1262
+ }
1263
+ }
1264
+ return result.length > 0 ? result : [name];
1265
+ }
1266
+ const sub = name.split("_").filter((s) => s !== "");
1267
+ if (sub.length <= 1) return [name];
1268
+ const firstWord = sub[0]?.toLowerCase() ?? "";
1269
+ if (ACTION_VERB_PREFIXES.has(firstWord)) return [name];
1270
+ return sub;
1271
+ }
1272
+ function classifyToolOrigin(toolName, rawPluginName) {
1273
+ const name = typeof toolName === "string" ? toolName.trim() : "";
1274
+ if (name.startsWith("mcp__")) return makeMcpOrigin(name.split("__").filter((s) => s !== "")[1] ?? "mcp");
1275
+ const explicitPkg = typeof rawPluginName === "string" ? normalizeBarePackageName(rawPluginName) : "";
1276
+ const known = KNOWN_TOOL_SPECS[name];
1277
+ if (explicitPkg !== "" && explicitPkg !== "root" && explicitPkg !== "builtin") {
1278
+ if (explicitPkg.startsWith("mcp:")) return makeMcpOrigin(explicitPkg.slice(4));
1279
+ if (isPluginToolPackage(explicitPkg)) {
1280
+ const badge = shortBadgeOfPackage(explicitPkg);
1281
+ return {
1282
+ scope: "plugin",
1283
+ pluginName: explicitPkg,
1284
+ sourceBadge: badge,
1285
+ groupKey: badge
1286
+ };
1287
+ }
1288
+ if (known !== void 0 && known.scope === "builtin") return makeKnownOrigin(known);
1289
+ const builtinGroup = BUILTIN_TOOL_PACKAGES.get(explicitPkg);
1290
+ const groupKey = builtinGroup === void 0 || builtinGroup === "builtin" ? splitToolName(name)[0] ?? name : builtinGroup === "fs" ? name === "read" || name === "read_image" ? "read" : name : builtinGroup === "fs_search" ? name : builtinGroup;
1291
+ return {
1292
+ scope: "builtin",
1293
+ pluginName: explicitPkg,
1294
+ sourceBadge: shortBadgeOfPackage(explicitPkg),
1295
+ groupKey
1296
+ };
1297
+ }
1298
+ if (known !== void 0) return makeKnownOrigin(known);
1299
+ const segments = splitToolName(name);
1300
+ return {
1301
+ scope: "builtin",
1302
+ pluginName: "builtin",
1303
+ sourceBadge: "builtin",
1304
+ groupKey: segments.length > 1 ? segments[0] ?? name : name
1305
+ };
1306
+ }
1307
+ function resolveToolMeta(tool) {
1308
+ if ((tool.scope === "builtin" || tool.scope === "plugin") && typeof tool.pluginName === "string" && tool.pluginName !== "" && typeof tool.sourceBadge === "string" && tool.sourceBadge !== "" && typeof tool.groupKey === "string" && tool.groupKey !== "") return {
1309
+ scope: tool.scope,
1310
+ pluginName: tool.pluginName,
1311
+ sourceBadge: tool.sourceBadge,
1312
+ groupKey: tool.groupKey
1313
+ };
1314
+ return classifyToolOrigin(tool.name, tool.pluginName);
1315
+ }
1316
+ function segmentsForTool(tool, meta) {
1317
+ if (tool.name.startsWith("mcp__")) {
1318
+ const leafLabel = splitToolName(tool.name).at(-1) ?? tool.name;
1319
+ return [meta.groupKey, leafLabel];
1320
+ }
1321
+ if (meta.groupKey !== "" && meta.groupKey !== tool.name) return [meta.groupKey, tool.name];
1322
+ return splitToolName(tool.name);
1323
+ }
1324
+ function finalizeBranch(branch) {
1325
+ const nodes = [];
1326
+ for (const [, child] of branch.children) if (child.kind === "leaf") nodes.push(child);
1327
+ else {
1328
+ const children = finalizeBranch(child.branch);
1329
+ const firstChild = children[0];
1330
+ if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "leaf" && !child.prefix.startsWith("mcp")) {
1331
+ nodes.push(firstChild);
1332
+ continue;
1333
+ }
1334
+ if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "node") {
1335
+ const sep = child.prefix === "mcp" ? "__" : "_";
1336
+ nodes.push({
1337
+ kind: "node",
1338
+ prefix: firstChild.prefix,
1339
+ label: `${child.label}${sep}${firstChild.label}`,
1340
+ children: firstChild.children,
1341
+ total: firstChild.total,
1342
+ disabled: firstChild.disabled,
1343
+ ...firstChild.scope !== void 0 ? { scope: firstChild.scope } : {},
1344
+ ...firstChild.sourceBadge !== void 0 ? { sourceBadge: firstChild.sourceBadge } : {}
1345
+ });
1346
+ continue;
1347
+ }
1348
+ let total = 0;
1349
+ let disabled = 0;
1350
+ for (const c of children) {
1351
+ total += c.total;
1352
+ disabled += c.kind === "leaf" ? c.disabledCount : c.disabled;
1353
+ }
1354
+ nodes.push({
1355
+ kind: "node",
1356
+ prefix: child.prefix,
1357
+ label: child.label,
1358
+ children,
1359
+ total,
1360
+ disabled,
1361
+ ...child.scope !== void 0 ? { scope: child.scope } : {},
1362
+ ...child.sourceBadge !== void 0 ? { sourceBadge: child.sourceBadge } : {}
1363
+ });
1364
+ }
1365
+ nodes.sort((a, b) => {
1366
+ if (a.kind !== b.kind) return a.kind === "node" ? -1 : 1;
1367
+ return compareCodeUnits(a.kind === "node" ? a.label : a.name, b.kind === "node" ? b.label : b.name);
1368
+ });
1369
+ return nodes;
1370
+ }
1371
+ function buildToolPrefixTree(tools, disabled, query = "") {
1372
+ const needle = typeof query === "string" ? query.trim().toLowerCase() : "";
1373
+ const filtered = needle === "" ? tools : tools.filter((t) => {
1374
+ const meta = resolveToolMeta(t);
1375
+ return t.name.toLowerCase().includes(needle) || t.description.toLowerCase().includes(needle) || meta.sourceBadge.toLowerCase().includes(needle) || meta.pluginName.toLowerCase().includes(needle) || meta.groupKey.toLowerCase().includes(needle);
1376
+ });
1377
+ const root = { children: new Map() };
1378
+ for (const tool of filtered) {
1379
+ const meta = resolveToolMeta(tool);
1380
+ const segments = segmentsForTool(tool, meta);
1381
+ let current = root;
1382
+ for (let i = 0; i < segments.length; i++) {
1383
+ const seg = segments[i];
1384
+ if (seg === void 0) continue;
1385
+ if (i === segments.length - 1) {
1386
+ const isOff = disabled.has(tool.name);
1387
+ const leaf = {
1388
+ kind: "leaf",
1389
+ name: tool.name,
1390
+ label: seg,
1391
+ description: tool.description,
1392
+ disabled: isOff,
1393
+ total: 1,
1394
+ disabledCount: isOff ? 1 : 0,
1395
+ scope: meta.scope,
1396
+ pluginName: meta.pluginName,
1397
+ sourceBadge: meta.sourceBadge
1398
+ };
1399
+ const existing = current.children.get(seg);
1400
+ if (existing !== void 0 && existing.kind === "branch") existing.branch.children.set(`__self__:${tool.name}`, leaf);
1401
+ else current.children.set(seg, leaf);
1402
+ } else {
1403
+ let next = current.children.get(seg);
1404
+ const prefixKey = segments[0] === "mcp" ? segments.slice(0, i + 1).join("__") : segments.slice(0, i + 1).join("_");
1405
+ if (next === void 0) {
1406
+ next = {
1407
+ kind: "branch",
1408
+ prefix: prefixKey,
1409
+ label: seg,
1410
+ scope: meta.scope,
1411
+ sourceBadge: meta.sourceBadge,
1412
+ branch: { children: new Map() }
1413
+ };
1414
+ current.children.set(seg, next);
1415
+ } else if (next.kind === "leaf") {
1416
+ const branch = { children: new Map() };
1417
+ branch.children.set(`__self__:${next.name}`, next);
1418
+ next = {
1419
+ kind: "branch",
1420
+ prefix: prefixKey,
1421
+ label: seg,
1422
+ scope: meta.scope,
1423
+ sourceBadge: meta.sourceBadge,
1424
+ branch
1425
+ };
1426
+ current.children.set(seg, next);
1427
+ }
1428
+ current = next.branch;
1429
+ }
1430
+ }
1431
+ }
1432
+ return finalizeBranch(root);
1433
+ }
1434
+ function buildToolScopeGroups(tools, disabled, query = "") {
1435
+ const buckets = new Map();
1436
+ for (const scope of TOOL_SCOPE_ORDER) buckets.set(scope, []);
1437
+ for (const tool of tools) {
1438
+ const meta = resolveToolMeta(tool);
1439
+ const bucket = buckets.get(meta.scope);
1440
+ if (bucket !== void 0) bucket.push({
1441
+ ...tool,
1442
+ scope: meta.scope,
1443
+ pluginName: meta.pluginName,
1444
+ sourceBadge: meta.sourceBadge,
1445
+ groupKey: meta.groupKey
1446
+ });
1447
+ }
1448
+ const groups = [];
1449
+ for (const scope of TOOL_SCOPE_ORDER) {
1450
+ const bucketTools = buckets.get(scope) ?? [];
1451
+ if (bucketTools.length === 0) continue;
1452
+ const children = buildToolPrefixTree(bucketTools, disabled, query);
1453
+ if (children.length === 0) continue;
1454
+ let total = 0;
1455
+ let disabledCount = 0;
1456
+ for (const child of children) {
1457
+ total += child.total;
1458
+ disabledCount += child.kind === "leaf" ? child.disabledCount : child.disabled;
1459
+ }
1460
+ groups.push({
1461
+ scope,
1462
+ children,
1463
+ total,
1464
+ disabled: disabledCount
1465
+ });
1466
+ }
1467
+ return groups;
1468
+ }
1469
+ function toggleNamesInSet(current, names) {
1470
+ const next = new Set(current);
1471
+ if (names.some((name) => !current.has(name))) for (const name of names) next.add(name);
1472
+ else for (const name of names) next.delete(name);
1473
+ return next;
1474
+ }
1475
+ function toggleToolScopeGroupInSet(current, group) {
1476
+ const names = [];
1477
+ for (const child of group.children) names.push(...collectNodeLeafNames(child));
1478
+ return toggleNamesInSet(current, names);
1479
+ }
1480
+ function collectNodeLeafNames(node) {
1481
+ if (node.kind === "leaf") return [node.name];
1482
+ const out = [];
1483
+ for (const child of node.children) out.push(...collectNodeLeafNames(child));
1484
+ return out;
1485
+ }
1486
+ function toggleToolInSet(current, toolName, nextDisabled) {
1487
+ const next = new Set(current);
1488
+ if (nextDisabled) next.add(toolName);
1489
+ else next.delete(toolName);
1490
+ return next;
1491
+ }
1492
+ function toggleNodeInSet(current, node) {
1493
+ return toggleNamesInSet(current, collectNodeLeafNames(node));
1494
+ }
1495
+ function disabledToolReason(toolName, enabled, disabled) {
1496
+ if (!enabled || disabled.size === 0) return void 0;
1497
+ if (disabled.has(toolName)) return `${DISABLED_TOOL_PREFIX} ${JSON.stringify(toolName)}`;
1498
+ }
1499
+ function filterToolSchemas(tools, enabled, disabled) {
1500
+ if (!enabled || disabled.size === 0) return [...tools];
1501
+ return tools.filter((tool) => !disabled.has(tool.name));
1502
+ }
1503
+ function normalizeToolSummaries(list, excludedNames) {
1504
+ const byName = new Map();
1505
+ for (const item of list) {
1506
+ if (item === null || item === void 0 || typeof item !== "object") continue;
1507
+ const rec = item;
1508
+ const name = rec.name;
1509
+ if (typeof name !== "string" || name.trim() === "") continue;
1510
+ const trimmed = name.trim();
1511
+ if (excludedNames?.has(trimmed)) continue;
1512
+ const desc = typeof rec.description === "string" ? rec.description.trim() : "";
1513
+ const origin = classifyToolOrigin(trimmed, rec.pluginName);
1514
+ const existing = byName.get(trimmed);
1515
+ if (existing !== void 0) {
1516
+ if (typeof rec.pluginName === "string" && rec.pluginName.trim() !== "" && existing.pluginName !== origin.pluginName) byName.set(trimmed, {
1517
+ name: trimmed,
1518
+ description: existing.description !== "" ? existing.description : desc,
1519
+ scope: origin.scope,
1520
+ pluginName: origin.pluginName,
1521
+ sourceBadge: origin.sourceBadge,
1522
+ groupKey: origin.groupKey
1523
+ });
1524
+ continue;
1525
+ }
1526
+ byName.set(trimmed, {
1527
+ name: trimmed,
1528
+ description: desc,
1529
+ scope: origin.scope,
1530
+ pluginName: origin.pluginName,
1531
+ sourceBadge: origin.sourceBadge,
1532
+ groupKey: origin.groupKey
1533
+ });
1534
+ }
1535
+ return [...byName.values()].sort((a, b) => compareCodeUnits(a.name, b.name));
1536
+ }
1537
+ function parseToolCatalog(raw) {
1538
+ if (raw === null || raw === void 0 || typeof raw !== "object") return {
1539
+ tools: [],
1540
+ available: false
1541
+ };
1542
+ const list = raw.tools;
1543
+ if (!Array.isArray(list)) return {
1544
+ tools: [],
1545
+ available: false
1546
+ };
1547
+ return {
1548
+ tools: normalizeToolSummaries(list),
1549
+ available: true
1550
+ };
1551
+ }
1552
+ function isValidOverrideKey(value) {
1553
+ return value !== "" && !/[\s;:+,]/.test(value);
1554
+ }
1555
+ function parseSessionOverrides(raw) {
1556
+ const out = new Map();
1557
+ if (typeof raw !== "string" || raw.trim() === "") return out;
1558
+ for (const entry of raw.split(";")) {
1559
+ const trimmedEntry = entry.trim();
1560
+ if (trimmedEntry === "") continue;
1561
+ const colonIdx = trimmedEntry.indexOf(":");
1562
+ if (colonIdx <= 0) continue;
1563
+ const sessionId = trimmedEntry.slice(0, colonIdx).trim();
1564
+ if (!isValidOverrideKey(sessionId)) continue;
1565
+ const tokensRaw = trimmedEntry.slice(colonIdx + 1);
1566
+ const allow = new Set();
1567
+ const deny = new Set();
1568
+ for (const token of tokensRaw.split(",")) {
1569
+ const t = token.trim();
1570
+ if (t.length < 2) continue;
1571
+ const op = t[0];
1572
+ const name = t.slice(1).trim();
1573
+ if (!isValidOverrideKey(name)) continue;
1574
+ if (op === "+") {
1575
+ deny.delete(name);
1576
+ allow.add(name);
1577
+ } else if (op === "-") {
1578
+ allow.delete(name);
1579
+ deny.add(name);
1580
+ }
1581
+ }
1582
+ if (allow.size > 0 || deny.size > 0) {
1583
+ out.delete(sessionId);
1584
+ out.set(sessionId, {
1585
+ allow,
1586
+ deny
1587
+ });
1588
+ }
1589
+ }
1590
+ return out;
1591
+ }
1592
+ function formatSessionOverrides(map) {
1593
+ const entries = [];
1594
+ for (const [rawSessionId, delta] of map.entries()) {
1595
+ const sessionId = typeof rawSessionId === "string" ? rawSessionId.trim() : "";
1596
+ if (!isValidOverrideKey(sessionId)) continue;
1597
+ const allow = new Set();
1598
+ const deny = new Set();
1599
+ for (const name of delta.allow) {
1600
+ const n = typeof name === "string" ? name.trim() : "";
1601
+ if (isValidOverrideKey(n)) allow.add(n);
1602
+ }
1603
+ for (const name of delta.deny) {
1604
+ const n = typeof name === "string" ? name.trim() : "";
1605
+ if (isValidOverrideKey(n) && !allow.has(n)) deny.add(n);
1606
+ }
1607
+ const tokens = [...[...allow].sort(compareCodeUnits).map((n) => `+${n}`), ...[...deny].sort(compareCodeUnits).map((n) => `-${n}`)];
1608
+ if (tokens.length > 0) entries.push([sessionId, `${sessionId}:${tokens.join(",")}`]);
1609
+ }
1610
+ return (entries.length > 32 ? entries.slice(entries.length - 32) : entries).map(([, encoded]) => encoded).join(";");
1611
+ }
1612
+ function resolveEffectiveDisabled(globalRaw, overridesRaw, sessionId) {
1613
+ const globalSet = parseDisabledTools(globalRaw);
1614
+ const sid = typeof sessionId === "string" ? sessionId.trim() : "";
1615
+ if (sid === "") return globalSet;
1616
+ const delta = parseSessionOverrides(overridesRaw).get(sid);
1617
+ if (delta === void 0) return globalSet;
1618
+ const effective = new Set(globalSet);
1619
+ for (const name of delta.deny) effective.add(name);
1620
+ for (const name of delta.allow) effective.delete(name);
1621
+ return effective;
1622
+ }
1623
+ function hasSessionOverride(globalRaw, overridesRaw, sessionId) {
1624
+ const sid = typeof sessionId === "string" ? sessionId.trim() : "";
1625
+ if (sid === "") return false;
1626
+ const globalSet = parseDisabledTools(globalRaw);
1627
+ const effectiveSet = resolveEffectiveDisabled(globalRaw, overridesRaw, sid);
1628
+ if (globalSet.size !== effectiveSet.size) return true;
1629
+ for (const name of globalSet) if (!effectiveSet.has(name)) return true;
1630
+ return false;
1631
+ }
1632
+ function updateSessionOverride(globalRaw, overridesRaw, sessionId, nextEffectiveDisabled) {
1633
+ const sid = typeof sessionId === "string" ? sessionId.trim() : "";
1634
+ const map = parseSessionOverrides(overridesRaw);
1635
+ if (!isValidOverrideKey(sid)) return formatSessionOverrides(map);
1636
+ const globalSet = parseDisabledTools(globalRaw);
1637
+ const targetSet = parseDisabledTools(formatDisabledTools(nextEffectiveDisabled));
1638
+ const allow = new Set();
1639
+ const deny = new Set();
1640
+ for (const name of globalSet) if (!targetSet.has(name)) allow.add(name);
1641
+ for (const name of targetSet) if (!globalSet.has(name)) deny.add(name);
1642
+ map.delete(sid);
1643
+ if (allow.size > 0 || deny.size > 0) map.set(sid, {
1644
+ allow,
1645
+ deny
1646
+ });
1647
+ return formatSessionOverrides(map);
1648
+ }
1649
+ function clearSessionOverride(overridesRaw, sessionId) {
1650
+ const sid = typeof sessionId === "string" ? sessionId.trim() : "";
1651
+ const map = parseSessionOverrides(overridesRaw);
1652
+ if (sid !== "") map.delete(sid);
1653
+ return formatSessionOverrides(map);
1654
+ }
1655
+ //#endregion
1656
+ //#region src/shared/skills-manager.ts
1657
+ const SKILL_SCOPE_ORDER = [
1658
+ "project",
1659
+ "global",
1660
+ "plugin"
1661
+ ];
1662
+ function extractPackageBadgeFromPath(rawPath) {
1663
+ const normalized = rawPath.replaceAll("\\", "/");
1664
+ const nmMatch = /\/node_modules\/((?:@[^/]+\/[^/]+)|(?:[^/]+))\//.exec(normalized);
1665
+ if (nmMatch?.[1] !== void 0) {
1666
+ const pkg = nmMatch[1];
1667
+ return pkg.startsWith("@deepseek-ai/") ? pkg.slice(13) : pkg;
1668
+ }
1669
+ if (normalized.includes("/app.asar/") || normalized.includes("/office-skills/")) return "bundled";
1670
+ }
1671
+ function classifySkillScope(rawSource, rawProvider, rawPath) {
1672
+ const source = typeof rawSource === "string" ? rawSource.trim() : "";
1673
+ const provider = typeof rawProvider === "string" ? rawProvider.trim() : "";
1674
+ const path = typeof rawPath === "string" ? rawPath.trim() : "";
1675
+ if (source === "project-dsh") return {
1676
+ scope: "project",
1677
+ sourceBadge: ".dsh/skills"
1678
+ };
1679
+ if (source === "project-agents") return {
1680
+ scope: "project",
1681
+ sourceBadge: ".agents/skills"
1682
+ };
1683
+ if (source.startsWith("project")) return {
1684
+ scope: "project",
1685
+ sourceBadge: source
1686
+ };
1687
+ if (source === "user-dsh") return {
1688
+ scope: "global",
1689
+ sourceBadge: "~/.dsh/skills"
1690
+ };
1691
+ if (source === "user-agents") return {
1692
+ scope: "global",
1693
+ sourceBadge: "~/.agents/skills"
1694
+ };
1695
+ if (source.startsWith("user")) return {
1696
+ scope: "global",
1697
+ sourceBadge: source
1698
+ };
1699
+ if (source === "custom") {
1700
+ const pkgBadge = path !== "" ? extractPackageBadgeFromPath(path) : void 0;
1701
+ if (pkgBadge !== void 0) return {
1702
+ scope: "plugin",
1703
+ sourceBadge: pkgBadge
1704
+ };
1705
+ return {
1706
+ scope: "global",
1707
+ sourceBadge: "custom"
1708
+ };
1709
+ }
1710
+ if (source === "bundled") return {
1711
+ scope: "plugin",
1712
+ sourceBadge: provider !== "" && provider !== "filesystem" ? provider : (path !== "" ? extractPackageBadgeFromPath(path) : void 0) ?? "bundled"
1713
+ };
1714
+ if (provider !== "" && provider !== "filesystem") return {
1715
+ scope: "plugin",
1716
+ sourceBadge: provider
1717
+ };
1718
+ if (provider === "filesystem") {
1719
+ const pkgBadge = path !== "" ? extractPackageBadgeFromPath(path) : void 0;
1720
+ if (pkgBadge !== void 0) return {
1721
+ scope: "plugin",
1722
+ sourceBadge: pkgBadge
1723
+ };
1724
+ return {
1725
+ scope: "global",
1726
+ sourceBadge: source !== "" ? source : "filesystem"
1727
+ };
1728
+ }
1729
+ return {
1730
+ scope: "plugin",
1731
+ sourceBadge: provider || source || "plugin"
1732
+ };
1733
+ }
1734
+ function normalizeSkillCatalogItems(list, options) {
1735
+ const includeProject = options?.includeProject ?? true;
1736
+ const byName = new Map();
1737
+ for (const raw of list) {
1738
+ if (raw === null || raw === void 0 || typeof raw !== "object") continue;
1739
+ const row = raw;
1740
+ const name = typeof row.name === "string" ? row.name.trim() : "";
1741
+ if (name === "" || byName.has(name)) continue;
1742
+ const description = typeof row.description === "string" ? row.description.trim() : "";
1743
+ const source = typeof row.source === "string" ? row.source.trim() : "";
1744
+ const provider = typeof row.provider === "string" ? row.provider.trim() : "";
1745
+ const path = typeof row.path === "string" && row.path.trim() !== "" ? row.path.trim() : void 0;
1746
+ const { scope, sourceBadge } = classifySkillScope(source, provider, path);
1747
+ if (!includeProject && scope === "project") continue;
1748
+ const invocation = typeof row.invocation === "object" && row.invocation !== null ? row.invocation : null;
1749
+ const modelInvocable = typeof row.modelInvocable === "boolean" ? row.modelInvocable : typeof invocation?.modelInvocable === "boolean" ? invocation.modelInvocable : true;
1750
+ const userInvocable = typeof row.userInvocable === "boolean" ? row.userInvocable : typeof invocation?.userInvocable === "boolean" ? invocation.userInvocable : true;
1751
+ const whenToUse = typeof row.whenToUse === "string" && row.whenToUse.trim() !== "" ? row.whenToUse.trim() : void 0;
1752
+ byName.set(name, {
1753
+ name,
1754
+ description,
1755
+ source,
1756
+ provider,
1757
+ scope,
1758
+ sourceBadge,
1759
+ ...path === void 0 ? {} : { path },
1760
+ ...whenToUse === void 0 ? {} : { whenToUse },
1761
+ modelInvocable,
1762
+ userInvocable
1763
+ });
1764
+ }
1765
+ return [...byName.values()].sort((a, b) => compareCodeUnits(a.name, b.name));
1766
+ }
1767
+ function parseSkillCatalog(raw, options) {
1768
+ if (raw === null || raw === void 0 || typeof raw !== "object") return {
1769
+ skills: [],
1770
+ available: false
1771
+ };
1772
+ const list = raw.skills;
1773
+ if (!Array.isArray(list)) return {
1774
+ skills: [],
1775
+ available: false
1776
+ };
1777
+ return {
1778
+ skills: normalizeSkillCatalogItems(list, options),
1779
+ available: true
1780
+ };
1781
+ }
1782
+ function buildSkillScopeGroups(skills, disabled, query = "", options) {
1783
+ const includeProject = options?.includeProject ?? true;
1784
+ const needle = typeof query === "string" ? query.trim().toLowerCase() : "";
1785
+ const buckets = new Map();
1786
+ for (const scope of SKILL_SCOPE_ORDER) buckets.set(scope, []);
1787
+ for (const skill of skills) {
1788
+ if (!includeProject && skill.scope === "project") continue;
1789
+ if (needle !== "") {
1790
+ if (!(skill.name.toLowerCase().includes(needle) || skill.description.toLowerCase().includes(needle) || skill.sourceBadge.toLowerCase().includes(needle) || skill.provider.toLowerCase().includes(needle))) continue;
1791
+ }
1792
+ const bucket = buckets.get(skill.scope);
1793
+ if (bucket !== void 0) bucket.push({
1794
+ ...skill,
1795
+ disabled: disabled.has(skill.name)
1796
+ });
1797
+ }
1798
+ const groups = [];
1799
+ for (const scope of SKILL_SCOPE_ORDER) {
1800
+ if (!includeProject && scope === "project") continue;
1801
+ const items = buckets.get(scope) ?? [];
1802
+ if (items.length === 0) continue;
1803
+ items.sort((a, b) => compareCodeUnits(a.name, b.name));
1804
+ const disabledCount = items.reduce((sum, item) => sum + (item.disabled ? 1 : 0), 0);
1805
+ groups.push({
1806
+ scope,
1807
+ items,
1808
+ total: items.length,
1809
+ disabled: disabledCount
1810
+ });
1811
+ }
1812
+ return groups;
1813
+ }
1814
+ function toggleSkillGroupInSet(current, group) {
1815
+ const next = new Set(current);
1816
+ if (group.items.some((item) => !current.has(item.name))) for (const item of group.items) next.add(item.name);
1817
+ else for (const item of group.items) next.delete(item.name);
1818
+ return next;
1819
+ }
1820
+ function isSkillDisabled(skillName, enabled, disabled) {
1821
+ if (!enabled || disabled.size === 0 || typeof skillName !== "string") return false;
1822
+ const trimmed = skillName.trim();
1823
+ return trimmed !== "" && disabled.has(trimmed);
1824
+ }
1825
+ function filterSkillsList(skills, enabled, disabled) {
1826
+ if (!enabled || disabled.size === 0) return [...skills];
1827
+ return skills.filter((skill) => !disabled.has(skill.name));
1828
+ }
1829
+ //#endregion
682
1830
  //#region src/client/settings/card.ts
683
1831
  function withField(list, field) {
684
1832
  return list.includes(field) ? list : [...list, field];
@@ -686,11 +1834,24 @@ window.__ModuleLoader__.load({
686
1834
  function withoutField(list, field) {
687
1835
  return list.includes(field) ? list.filter((item) => item !== field) : list;
688
1836
  }
1837
+ const RAW_STRING_FIELDS = [
1838
+ "disabledTools",
1839
+ "sessionToolOverrides",
1840
+ "disabledSkills",
1841
+ "sessionSkillOverrides"
1842
+ ];
689
1843
  function readField(value, field) {
1844
+ if (RAW_STRING_FIELDS.includes(field)) {
1845
+ if (value === null || value === void 0 || typeof value !== "object") return "";
1846
+ const raw = value[field];
1847
+ return typeof raw === "string" ? raw.trim() : "";
1848
+ }
690
1849
  if (TEXT_FIELDS.includes(field)) return textOf(value, field);
691
1850
  return flagOn(value, field);
692
1851
  }
693
1852
  function labelOf(t, field) {
1853
+ if (field === "disabledTools" || field === "sessionToolOverrides") return t("settings.toolsManager");
1854
+ if (field === "disabledSkills" || field === "sessionSkillOverrides") return t("settings.skillsManager");
694
1855
  return t("settings." + field);
695
1856
  }
696
1857
  function SettingsRow({ store, t, getForm }) {
@@ -714,9 +1875,10 @@ window.__ModuleLoader__.load({
714
1875
  const value = snapshot === null || snapshot === void 0 ? void 0 : snapshot.value;
715
1876
  const ready = snapshot !== null && snapshot !== void 0 && snapshot.status === "ready" && snapshot.value !== void 0;
716
1877
  const readOnly = form === null || form === void 0 || !ready || snapshot.writable !== true || typeof form.set !== "function";
1878
+ const isUndeclared = (field) => ready && !readOnly && (value === null || value === void 0 || typeof value !== "object" || !(field in value));
717
1879
  const write = (field, wanted) => {
718
1880
  if (readOnly) return;
719
- if (drifted.includes(field)) return;
1881
+ if (isUndeclared(field)) return;
720
1882
  const mine = gen.current + 1;
721
1883
  gen.current = mine;
722
1884
  owner.current.set(field, mine);
@@ -821,7 +1983,21 @@ window.__ModuleLoader__.load({
821
1983
  role: "alert"
822
1984
  }, t("settings.staleHost") + "(" + drifted.map((field) => labelOf(t, field)).join("、") + ")") : null;
823
1985
  const showSuggest = flagOn(value, "suggest") || readOnly;
824
- 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, {
1986
+ const showDefaultTools = flagOn(value, "toolsManager") || readOnly;
1987
+ const showDefaultSkills = flagOn(value, "skillsManager") || readOnly;
1988
+ 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, showDefaultTools ? h(DefaultToolsManager, {
1989
+ key: "default-tools",
1990
+ t,
1991
+ disabledRaw: String(readField(value, "disabledTools")),
1992
+ disabled: readOnly || busy.includes("disabledTools") || isUndeclared("disabledTools"),
1993
+ onSave: (nextCanonical) => write("disabledTools", nextCanonical)
1994
+ }) : null, showDefaultSkills ? h(DefaultSkillsManager, {
1995
+ key: "default-skills",
1996
+ t,
1997
+ disabledRaw: String(readField(value, "disabledSkills")),
1998
+ disabled: readOnly || busy.includes("disabledSkills") || isUndeclared("disabledSkills"),
1999
+ onSave: (nextCanonical) => write("disabledSkills", nextCanonical)
2000
+ }) : null, showSuggest ? h(SuggestSettings, {
825
2001
  key: "suggest",
826
2002
  t,
827
2003
  value,
@@ -1056,6 +2232,423 @@ window.__ModuleLoader__.load({
1056
2232
  }, t("settings.suggestPrompt.reset"))])
1057
2233
  ]);
1058
2234
  }
2235
+ function renderDefaultSummaryTags(disabledNames, t, prefixKey, tagAttr) {
2236
+ if (disabledNames.length === 0) return h("div", {
2237
+ key: "status",
2238
+ className: "de-defaults-status"
2239
+ }, t("settings.defaults.allEnabled"));
2240
+ return h("div", {
2241
+ key: "tags",
2242
+ className: "de-defaults-tags"
2243
+ }, [
2244
+ h("span", {
2245
+ key: "prefix",
2246
+ className: "de-defaults-muted"
2247
+ }, t(prefixKey)),
2248
+ ...disabledNames.slice(0, 6).map((name) => h("span", {
2249
+ key: name,
2250
+ className: "de-defaults-tag",
2251
+ [tagAttr]: name
2252
+ }, name)),
2253
+ disabledNames.length > 6 ? h("span", {
2254
+ key: "more",
2255
+ className: "de-defaults-muted"
2256
+ }, `+${String(disabledNames.length - 6)}`) : null
2257
+ ]);
2258
+ }
2259
+ function renderDefaultLeafControls(opts) {
2260
+ const { t, itemDisabled, toggleAttr, itemName, controlDisabled, onToggle } = opts;
2261
+ return h("div", {
2262
+ key: "ctrls",
2263
+ className: "de-defaults-controls"
2264
+ }, [h("span", {
2265
+ key: "pill",
2266
+ className: "de-defaults-pill",
2267
+ "data-disabled": itemDisabled ? "true" : "false"
2268
+ }, itemDisabled ? t("settings.tools.disabled") : t("settings.tools.enabled")), h("button", {
2269
+ key: "btn",
2270
+ type: "button",
2271
+ className: "de-button",
2272
+ [toggleAttr]: itemName,
2273
+ disabled: controlDisabled,
2274
+ onClick: onToggle
2275
+ }, itemDisabled ? t("settings.tools.enable") : t("settings.tools.disable"))]);
2276
+ }
2277
+ function renderDefaultGroupHeader(opts) {
2278
+ const { t, headerAttr, batchAttr, groupKey, label, isOpen, total, disabledCount, controlDisabled, depth = 0, onToggleOpen, onBatchToggle } = opts;
2279
+ const enabledInGroup = total - disabledCount;
2280
+ return h("div", {
2281
+ key: "head",
2282
+ className: "de-defaults-group-head",
2283
+ [headerAttr]: groupKey,
2284
+ style: depth > 0 ? { paddingLeft: `${String(depth * 16 + 8)}px` } : void 0,
2285
+ onClick: onToggleOpen
2286
+ }, [h("span", {
2287
+ key: "title",
2288
+ className: "de-defaults-group-title"
2289
+ }, `${isOpen ? "▾" : "▸"} ${label}`), h("div", {
2290
+ key: "ctrls",
2291
+ className: "de-defaults-controls"
2292
+ }, [h("span", {
2293
+ key: "pill",
2294
+ className: "de-defaults-pill",
2295
+ "data-disabled": enabledInGroup === 0 ? "true" : "false"
2296
+ }, enabledInGroup === 0 ? t("settings.tools.allDisabled") : `${String(enabledInGroup)}/${String(total)}`), h("button", {
2297
+ key: "batch",
2298
+ type: "button",
2299
+ className: "de-button",
2300
+ [batchAttr]: groupKey,
2301
+ disabled: controlDisabled,
2302
+ onClick: (e) => {
2303
+ e?.stopPropagation?.();
2304
+ onBatchToggle();
2305
+ }
2306
+ }, enabledInGroup > 0 ? t("settings.tools.disableAll") : t("settings.tools.enableAll"))])]);
2307
+ }
2308
+ function renderDefaultsManagerBox(opts) {
2309
+ const { kind, t, titleKey, hintKey, disabledPrefixKey, tagAttr, searchPlaceholderKey, emptyKey, totalCount, enabledCount, disabledInCatalogCount, hasAnyDisabled, displayDisabledNames, open, query, controlDisabled, onToggleOpen, onQueryChange, onEnableAll, onRefresh, treeElements } = opts;
2310
+ return h("div", {
2311
+ className: "de-defaults-box",
2312
+ "data-desktop-enhance-defaults": kind
2313
+ }, [h("div", {
2314
+ key: "summary",
2315
+ className: "de-defaults-summary"
2316
+ }, [h("div", {
2317
+ key: "left",
2318
+ className: "de-text"
2319
+ }, [
2320
+ h("div", {
2321
+ key: "title-row",
2322
+ className: "de-defaults-title-row"
2323
+ }, [h("span", {
2324
+ key: "title",
2325
+ className: "de-title"
2326
+ }, t(titleKey)), totalCount > 0 ? h("span", {
2327
+ key: "count",
2328
+ className: "de-defaults-pill",
2329
+ "data-desktop-enhance-default-count": kind,
2330
+ "data-disabled": disabledInCatalogCount > 0 ? "true" : "false"
2331
+ }, `${t("settings.defaults.enabledPrefix")}${String(enabledCount)}/${String(totalCount)}`) : null]),
2332
+ h("div", {
2333
+ key: "desc",
2334
+ className: "de-desc"
2335
+ }, t(hintKey)),
2336
+ renderDefaultSummaryTags(displayDisabledNames, t, disabledPrefixKey, tagAttr)
2337
+ ]), h("button", {
2338
+ key: "manage",
2339
+ type: "button",
2340
+ className: "de-button",
2341
+ "data-desktop-enhance-action": `manage-default-${kind}`,
2342
+ "aria-expanded": open ? "true" : "false",
2343
+ onClick: onToggleOpen
2344
+ }, open ? t("settings.defaults.close") : t("settings.defaults.manage"))]), open ? h("div", {
2345
+ key: "panel",
2346
+ className: "de-defaults-panel",
2347
+ "data-desktop-enhance-default-panel": kind
2348
+ }, [h("div", {
2349
+ key: "toolbar",
2350
+ className: "de-defaults-toolbar"
2351
+ }, [h("input", {
2352
+ key: "search",
2353
+ type: "search",
2354
+ className: "de-text-input",
2355
+ "data-desktop-enhance-default-search": kind,
2356
+ placeholder: t(searchPlaceholderKey),
2357
+ value: query,
2358
+ onInput: (e) => {
2359
+ const v = e?.target?.value;
2360
+ if (typeof v === "string") onQueryChange(v);
2361
+ }
2362
+ }), h("div", {
2363
+ key: "actions",
2364
+ className: "de-prompt-actions"
2365
+ }, [h("button", {
2366
+ key: "enable-all",
2367
+ type: "button",
2368
+ className: "de-button",
2369
+ "data-desktop-enhance-action": `enable-all-default-${kind}`,
2370
+ disabled: controlDisabled || !hasAnyDisabled,
2371
+ onClick: onEnableAll
2372
+ }, `${t("settings.tools.enableAll")} (${String(enabledCount)}/${String(totalCount)})`), h("button", {
2373
+ key: "refresh",
2374
+ type: "button",
2375
+ className: "de-button",
2376
+ "data-desktop-enhance-action": `refresh-default-${kind}`,
2377
+ onClick: onRefresh
2378
+ }, t("settings.tools.refresh"))])]), h("div", {
2379
+ key: "tree",
2380
+ className: "de-defaults-tree"
2381
+ }, treeElements.length === 0 ? h("div", {
2382
+ key: "empty",
2383
+ className: "de-defaults-muted"
2384
+ }, t(emptyKey)) : treeElements)]) : null]);
2385
+ }
2386
+ function DefaultToolsManager({ t, disabledRaw, disabled, onSave }) {
2387
+ const [catalog, setCatalog] = React.useState(null);
2388
+ const [open, setOpen] = React.useState(false);
2389
+ const [query, setQuery] = React.useState("");
2390
+ const [collapsedNodes, setCollapsedNodes] = React.useState([]);
2391
+ React.useEffect(() => {
2392
+ if (typeof globalThis.fetch !== "function") return void 0;
2393
+ let live = true;
2394
+ catalogCache.get(TOOLS_URL, globalThis.fetch).then((body) => {
2395
+ if (live) setCatalog(parseToolCatalog(body));
2396
+ }).catch(() => {
2397
+ if (live) setCatalog({
2398
+ tools: [],
2399
+ available: false
2400
+ });
2401
+ });
2402
+ return () => {
2403
+ live = false;
2404
+ };
2405
+ }, []);
2406
+ const disabledSet = parseDisabledTools(disabledRaw);
2407
+ const tools = catalog?.available ? catalog.tools : [];
2408
+ const disabledInCatalog = tools.filter((tool) => disabledSet.has(tool.name));
2409
+ const enabledCount = tools.length - disabledInCatalog.length;
2410
+ const displayDisabledNames = tools.length > 0 ? disabledInCatalog.map((tool) => tool.name) : [...disabledSet];
2411
+ const commitSet = (nextSet) => {
2412
+ onSave(formatDisabledTools(nextSet));
2413
+ };
2414
+ const refreshCatalog = () => {
2415
+ if (typeof globalThis.fetch !== "function") return;
2416
+ catalogCache.invalidate?.(TOOLS_URL);
2417
+ catalogCache.get(TOOLS_URL, globalThis.fetch).then((body) => setCatalog(parseToolCatalog(body))).catch(() => setCatalog({
2418
+ tools: [],
2419
+ available: false
2420
+ }));
2421
+ };
2422
+ const renderTreeNode = (node, depth) => {
2423
+ if (node.kind === "leaf") return h("div", {
2424
+ key: `leaf:${node.name}`,
2425
+ className: "de-defaults-leaf",
2426
+ "data-default-tool-leaf": node.name,
2427
+ "data-tool-scope": node.scope,
2428
+ "data-disabled": node.disabled ? "true" : "false",
2429
+ style: depth > 0 ? { paddingLeft: `${String(depth * 16 + 8)}px` } : void 0
2430
+ }, [h("div", {
2431
+ key: "info",
2432
+ className: "de-defaults-leaf-info"
2433
+ }, [h("div", {
2434
+ key: "head",
2435
+ className: "de-defaults-leaf-head"
2436
+ }, [h("span", {
2437
+ key: "name",
2438
+ className: "de-defaults-leaf-name"
2439
+ }, node.name), node.scope === "plugin" && node.sourceBadge !== "" ? h("span", {
2440
+ key: "badge",
2441
+ className: "de-defaults-source-badge",
2442
+ "data-tool-scope": node.scope
2443
+ }, node.sourceBadge) : null]), node.description !== "" ? h("div", {
2444
+ key: "desc",
2445
+ className: "de-defaults-leaf-desc"
2446
+ }, node.description) : null]), renderDefaultLeafControls({
2447
+ t,
2448
+ itemDisabled: node.disabled,
2449
+ toggleAttr: "data-default-tool-toggle",
2450
+ itemName: node.name,
2451
+ controlDisabled: disabled,
2452
+ onToggle: () => commitSet(toggleToolInSet(disabledSet, node.name, !node.disabled))
2453
+ })]);
2454
+ const isOpen = query.trim() !== "" || !collapsedNodes.includes(node.prefix);
2455
+ return h("div", {
2456
+ key: `node:${node.prefix}`,
2457
+ className: "de-defaults-group",
2458
+ "data-default-tool-node": node.prefix
2459
+ }, [renderDefaultGroupHeader({
2460
+ t,
2461
+ headerAttr: "data-default-tool-node-header",
2462
+ batchAttr: "data-default-tool-batch",
2463
+ groupKey: node.prefix,
2464
+ label: node.label,
2465
+ isOpen,
2466
+ total: node.total,
2467
+ disabledCount: node.disabled,
2468
+ controlDisabled: disabled,
2469
+ depth,
2470
+ onToggleOpen: () => {
2471
+ setCollapsedNodes((curr) => curr.includes(node.prefix) ? curr.filter((p) => p !== node.prefix) : [...curr, node.prefix]);
2472
+ },
2473
+ onBatchToggle: () => commitSet(toggleNodeInSet(disabledSet, node))
2474
+ }), isOpen ? h("div", {
2475
+ key: "children",
2476
+ className: "de-defaults-group-children"
2477
+ }, node.children.map((child) => renderTreeNode(child, depth + 1))) : null]);
2478
+ };
2479
+ const scopeGroups = open ? buildToolScopeGroups(tools, disabledSet, query) : [];
2480
+ return renderDefaultsManagerBox({
2481
+ kind: "tools",
2482
+ t,
2483
+ titleKey: "settings.defaults.toolsTitle",
2484
+ hintKey: "settings.defaults.toolsHint",
2485
+ disabledPrefixKey: "sessionInfo.tools.disabledPrefix",
2486
+ tagAttr: "data-default-tool-tag",
2487
+ searchPlaceholderKey: "settings.tools.search",
2488
+ emptyKey: "settings.tools.empty",
2489
+ totalCount: tools.length,
2490
+ enabledCount,
2491
+ disabledInCatalogCount: disabledInCatalog.length,
2492
+ hasAnyDisabled: disabledSet.size > 0,
2493
+ displayDisabledNames,
2494
+ open,
2495
+ query,
2496
+ controlDisabled: disabled,
2497
+ onToggleOpen: () => setOpen((v) => !v),
2498
+ onQueryChange: setQuery,
2499
+ onEnableAll: () => commitSet(new Set()),
2500
+ onRefresh: refreshCatalog,
2501
+ treeElements: scopeGroups.map((group) => {
2502
+ const scopeKey = `scope:${group.scope}`;
2503
+ const isOpen = query.trim() !== "" || !collapsedNodes.includes(scopeKey);
2504
+ return h("div", {
2505
+ key: `scope:${group.scope}`,
2506
+ className: "de-defaults-group",
2507
+ "data-default-tool-scope": group.scope
2508
+ }, [renderDefaultGroupHeader({
2509
+ t,
2510
+ headerAttr: "data-default-tool-scope-header",
2511
+ batchAttr: "data-default-tool-scope-batch",
2512
+ groupKey: group.scope,
2513
+ label: t("settings.tools.scope." + group.scope),
2514
+ isOpen,
2515
+ total: group.total,
2516
+ disabledCount: group.disabled,
2517
+ controlDisabled: disabled,
2518
+ depth: 0,
2519
+ onToggleOpen: () => {
2520
+ setCollapsedNodes((curr) => curr.includes(scopeKey) ? curr.filter((p) => p !== scopeKey) : [...curr, scopeKey]);
2521
+ },
2522
+ onBatchToggle: () => commitSet(toggleToolScopeGroupInSet(disabledSet, group))
2523
+ }), isOpen ? h("div", {
2524
+ key: "children",
2525
+ className: "de-defaults-group-children"
2526
+ }, group.children.map((n) => renderTreeNode(n, 1))) : null]);
2527
+ })
2528
+ });
2529
+ }
2530
+ function DefaultSkillsManager({ t, disabledRaw, disabled, onSave }) {
2531
+ const [catalog, setCatalog] = React.useState(null);
2532
+ const [open, setOpen] = React.useState(false);
2533
+ const [query, setQuery] = React.useState("");
2534
+ const [collapsedScopes, setCollapsedScopes] = React.useState([]);
2535
+ React.useEffect(() => {
2536
+ if (typeof globalThis.fetch !== "function") return void 0;
2537
+ let live = true;
2538
+ catalogCache.get(SKILLS_URL, globalThis.fetch).then((body) => {
2539
+ if (live) setCatalog(parseSkillCatalog(body, { includeProject: false }));
2540
+ }).catch(() => {
2541
+ if (live) setCatalog({
2542
+ skills: [],
2543
+ available: false
2544
+ });
2545
+ });
2546
+ return () => {
2547
+ live = false;
2548
+ };
2549
+ }, []);
2550
+ const disabledSet = parseDisabledTools(disabledRaw);
2551
+ const skills = catalog?.available ? catalog.skills : [];
2552
+ const disabledInCatalog = skills.filter((skill) => disabledSet.has(skill.name));
2553
+ const enabledCount = skills.length - disabledInCatalog.length;
2554
+ const displayDisabledNames = skills.length > 0 ? disabledInCatalog.map((skill) => skill.name) : [...disabledSet];
2555
+ const commitSet = (nextSet) => {
2556
+ onSave(formatDisabledTools(nextSet));
2557
+ };
2558
+ const refreshCatalog = () => {
2559
+ if (typeof globalThis.fetch !== "function") return;
2560
+ catalogCache.invalidate?.(SKILLS_URL);
2561
+ catalogCache.get(SKILLS_URL, globalThis.fetch).then((body) => setCatalog(parseSkillCatalog(body, { includeProject: false }))).catch(() => setCatalog({
2562
+ skills: [],
2563
+ available: false
2564
+ }));
2565
+ };
2566
+ const groups = open ? buildSkillScopeGroups(skills, disabledSet, query, { includeProject: false }) : [];
2567
+ return renderDefaultsManagerBox({
2568
+ kind: "skills",
2569
+ t,
2570
+ titleKey: "settings.defaults.skillsTitle",
2571
+ hintKey: "settings.defaults.skillsHint",
2572
+ disabledPrefixKey: "sessionInfo.skills.disabledPrefix",
2573
+ tagAttr: "data-default-skill-tag",
2574
+ searchPlaceholderKey: "settings.skills.search",
2575
+ emptyKey: "settings.skills.empty",
2576
+ totalCount: skills.length,
2577
+ enabledCount,
2578
+ disabledInCatalogCount: disabledInCatalog.length,
2579
+ hasAnyDisabled: disabledSet.size > 0,
2580
+ displayDisabledNames,
2581
+ open,
2582
+ query,
2583
+ controlDisabled: disabled,
2584
+ onToggleOpen: () => setOpen((v) => !v),
2585
+ onQueryChange: setQuery,
2586
+ onEnableAll: () => commitSet(new Set()),
2587
+ onRefresh: refreshCatalog,
2588
+ treeElements: groups.map((group) => {
2589
+ const isOpen = query.trim() !== "" || !collapsedScopes.includes(group.scope);
2590
+ return h("div", {
2591
+ key: `group:${group.scope}`,
2592
+ className: "de-defaults-group",
2593
+ "data-default-skill-group": group.scope
2594
+ }, [renderDefaultGroupHeader({
2595
+ t,
2596
+ headerAttr: "data-default-skill-group-header",
2597
+ batchAttr: "data-default-skill-batch",
2598
+ groupKey: group.scope,
2599
+ label: t("settings.skills.scope." + group.scope),
2600
+ isOpen,
2601
+ total: group.total,
2602
+ disabledCount: group.disabled,
2603
+ controlDisabled: disabled,
2604
+ onToggleOpen: () => {
2605
+ setCollapsedScopes((curr) => curr.includes(group.scope) ? curr.filter((s) => s !== group.scope) : [...curr, group.scope]);
2606
+ },
2607
+ onBatchToggle: () => commitSet(toggleSkillGroupInSet(disabledSet, group))
2608
+ }), isOpen ? h("div", {
2609
+ key: "items",
2610
+ className: "de-defaults-group-children"
2611
+ }, group.items.map((item) => h("div", {
2612
+ key: `skill:${item.name}`,
2613
+ className: "de-defaults-leaf",
2614
+ "data-default-skill-leaf": item.name,
2615
+ "data-skill-scope": item.scope,
2616
+ "data-disabled": item.disabled ? "true" : "false",
2617
+ style: { paddingLeft: "24px" }
2618
+ }, [h("div", {
2619
+ key: "info",
2620
+ className: "de-defaults-leaf-info"
2621
+ }, [h("div", {
2622
+ key: "head",
2623
+ className: "de-defaults-leaf-head"
2624
+ }, [
2625
+ h("span", {
2626
+ key: "name",
2627
+ className: "de-defaults-leaf-name"
2628
+ }, item.name),
2629
+ h("span", {
2630
+ key: "badge",
2631
+ className: "de-defaults-source-badge",
2632
+ "data-skill-scope": item.scope
2633
+ }, item.sourceBadge),
2634
+ !item.modelInvocable ? h("span", {
2635
+ key: "user-only",
2636
+ className: "de-defaults-source-badge"
2637
+ }, t("settings.skills.userOnly")) : null
2638
+ ]), item.description !== "" ? h("div", {
2639
+ key: "desc",
2640
+ className: "de-defaults-leaf-desc"
2641
+ }, item.description) : null]), renderDefaultLeafControls({
2642
+ t,
2643
+ itemDisabled: item.disabled,
2644
+ toggleAttr: "data-default-skill-toggle",
2645
+ itemName: item.name,
2646
+ controlDisabled: disabled,
2647
+ onToggle: () => commitSet(toggleToolInSet(disabledSet, item.name, !item.disabled))
2648
+ })]))) : null]);
2649
+ })
2650
+ });
2651
+ }
1059
2652
  //#endregion
1060
2653
  //#region src/client/timing/index.ts
1061
2654
  function finite(value) {
@@ -2062,477 +3655,330 @@ window.__ModuleLoader__.load({
2062
3655
  for (const node of nodes) byName.set(node.name, node);
2063
3656
  return [...byName.values()];
2064
3657
  }
2065
- function projectSkills(events) {
2066
- let windowStartSeq = null;
2067
- let currentTurn;
2068
- const rawNodes = [];
2069
- const replacedRanges = [];
2070
- const shadowedSeqs = [];
2071
- const shadowedSet = new Set();
2072
- for (const raw of events) {
2073
- const ev = asRecord(raw);
2074
- if (ev === null) continue;
2075
- const seq = nonNegativeInt(ev.seq);
2076
- if (seq !== void 0 && (windowStartSeq === null || seq < windowStartSeq)) windowStartSeq = seq;
2077
- const range = replaceRangeOf(ev.surfaceOp);
2078
- if (range !== null) replacedRanges.push(range);
2079
- const data = asRecord(ev.data);
2080
- const turnInEvent = positiveInt(data?.turn);
2081
- if (range === null && turnInEvent !== void 0) currentTurn = turnInEvent;
2082
- const effectiveTurn = turnInEvent ?? currentTurn;
2083
- const type = nonEmptyString(ev.type);
2084
- if (type === "compaction/summary" || type === "compaction/prune") {
2085
- const list = data?.shadowedSeqs;
2086
- if (Array.isArray(list)) for (const item of list) {
2087
- const s = nonNegativeInt(item);
2088
- if (s !== void 0 && !shadowedSet.has(s)) {
2089
- shadowedSet.add(s);
2090
- shadowedSeqs.push(s);
2091
- }
2092
- }
2093
- continue;
2094
- }
2095
- if (seq === void 0) continue;
2096
- if (type === "user/message" || type === "developer/message") {
2097
- const name = invokedSkillName(type, data);
2098
- if (name !== void 0) rawNodes.push({
2099
- name,
2100
- trigger: "user",
2101
- seq,
2102
- ...effectiveTurn === void 0 ? {} : { turn: effectiveTurn }
2103
- });
2104
- continue;
2105
- }
2106
- if (type === "tool/result") {
2107
- const name = toolSkillName(asRecord(data?.message));
2108
- if (name !== void 0) rawNodes.push({
2109
- name,
2110
- trigger: "agent",
2111
- seq,
2112
- ...effectiveTurn === void 0 ? {} : { turn: effectiveTurn }
2113
- });
2114
- }
2115
- }
2116
- const surviving = rawNodes.filter((node) => !isSeqShadowed(node.seq, replacedRanges, shadowedSet));
2117
- return {
2118
- skills: deduplicateSkills(surviving),
2119
- nodes: surviving,
2120
- windowStartSeq,
2121
- replacedRanges,
2122
- shadowedSeqs
2123
- };
2124
- }
2125
- function mergeSkillProjections(host, client) {
2126
- if (host === null) return client.skills;
2127
- if (client.windowStartSeq === null) return host.skills;
2128
- if (client.windowStartSeq === 0) return client.skills;
2129
- const windowStart = client.windowStartSeq;
2130
- const clientShadowed = new Set(client.shadowedSeqs);
2131
- const hostNodes = host.nodes ?? host.skills;
2132
- const clientNodes = client.nodes ?? client.skills;
2133
- return deduplicateSkills([...hostNodes.filter((skill) => skill.seq < windowStart && !isSeqShadowed(skill.seq, client.replacedRanges, clientShadowed)), ...clientNodes]);
2134
- }
2135
- function parseSkillArray(list) {
2136
- const out = [];
2137
- for (const item of list) {
2138
- const row = asRecord(item);
2139
- if (row === null) continue;
2140
- const name = nonEmptyString(row.name);
2141
- const trigger = row.trigger === "user" || row.trigger === "agent" ? row.trigger : void 0;
2142
- const seq = nonNegativeInt(row.seq);
2143
- const turn = positiveInt(row.turn);
2144
- if (name !== void 0 && trigger !== void 0 && seq !== void 0) out.push({
2145
- name,
2146
- trigger,
2147
- seq,
2148
- ...turn === void 0 ? {} : { turn }
2149
- });
2150
- }
2151
- return out;
2152
- }
2153
- function normalizeSkillProjection(raw) {
2154
- const rec = asRecord(raw);
2155
- if (rec === null || !Array.isArray(rec.skills)) return null;
2156
- const skills = parseSkillArray(rec.skills);
2157
- const nodes = Array.isArray(rec.nodes) ? parseSkillArray(rec.nodes) : skills;
2158
- const windowStartSeq = nonNegativeInt(rec.windowStartSeq) ?? null;
2159
- const replacedRanges = [];
2160
- if (Array.isArray(rec.replacedRanges)) for (const item of rec.replacedRanges) {
2161
- const r = asRecord(item);
2162
- const startSeq = nonNegativeInt(r?.startSeq);
2163
- const endSeq = nonNegativeInt(r?.endSeq);
2164
- if (startSeq !== void 0 && endSeq !== void 0 && endSeq >= startSeq) replacedRanges.push({
2165
- startSeq,
2166
- endSeq
2167
- });
2168
- }
2169
- const shadowedSeqs = [];
2170
- if (Array.isArray(rec.shadowedSeqs)) for (const item of rec.shadowedSeqs) {
2171
- const s = nonNegativeInt(item);
2172
- if (s !== void 0) shadowedSeqs.push(s);
2173
- }
2174
- return {
2175
- skills,
2176
- nodes,
2177
- windowStartSeq,
2178
- replacedRanges,
2179
- shadowedSeqs
2180
- };
2181
- }
2182
- function buildSessionInfoSections(skills, t) {
2183
- return [{
2184
- id: "skills",
2185
- title: t("sessionInfo.skills.title"),
2186
- shortLabel: t("sessionInfo.skills.short"),
2187
- emptyText: t("sessionInfo.skills.empty"),
2188
- items: skills.map((skill) => ({
2189
- name: skill.name,
2190
- badge: skill.trigger === "user" ? t("sessionInfo.trigger.user") : t("sessionInfo.trigger.agent"),
2191
- ...skill.turn === void 0 ? {} : { turnLabel: `#${String(skill.turn)}` }
2192
- }))
2193
- }];
2194
- }
2195
- //#endregion
2196
- //#region src/shared/tools-manager.ts
2197
- const DISABLED_TOOL_PREFIX = "tool is disabled by desktop-enhance:";
2198
- function compareCodeUnits(a, b) {
2199
- return a < b ? -1 : a > b ? 1 : 0;
2200
- }
2201
- function parseDisabledTools(raw) {
2202
- const out = new Set();
2203
- if (typeof raw !== "string" || raw.length === 0) return out;
2204
- for (const piece of raw.split(/[\s,]+/)) {
2205
- const trimmed = piece.trim();
2206
- if (trimmed !== "") out.add(trimmed);
2207
- }
2208
- return out;
2209
- }
2210
- function formatDisabledTools(names) {
2211
- const unique = new Set();
2212
- for (const name of names) if (typeof name === "string") {
2213
- const trimmed = name.trim();
2214
- if (trimmed !== "") unique.add(trimmed);
2215
- }
2216
- return [...unique].sort(compareCodeUnits).join(",");
2217
- }
2218
- function splitToolName(name) {
2219
- const parts = name.split("__");
2220
- if (parts.length > 1) {
2221
- const result = [];
2222
- for (let i = 0; i < parts.length; i++) {
2223
- const part = parts[i];
2224
- if (part === void 0 || part === "") continue;
2225
- if (i === 0 || i === parts.length - 1) result.push(part);
2226
- else {
2227
- const sub = part.split("_").filter((s) => s !== "");
2228
- result.push(...sub);
2229
- }
2230
- }
2231
- return result.length > 0 ? result : [name];
2232
- }
2233
- const sub = name.split("_").filter((s) => s !== "");
2234
- return sub.length > 0 ? sub : [name];
2235
- }
2236
- function finalizeBranch(branch) {
2237
- const nodes = [];
2238
- for (const [, child] of branch.children) if (child.kind === "leaf") nodes.push(child);
2239
- else {
2240
- const children = finalizeBranch(child.branch);
2241
- const firstChild = children[0];
2242
- if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "leaf" && !child.prefix.startsWith("mcp")) {
2243
- nodes.push(firstChild);
2244
- continue;
2245
- }
2246
- if (children.length === 1 && firstChild !== void 0 && firstChild.kind === "node") {
2247
- const sep = child.prefix === "mcp" ? "__" : "_";
2248
- nodes.push({
2249
- kind: "node",
2250
- prefix: firstChild.prefix,
2251
- label: `${child.label}${sep}${firstChild.label}`,
2252
- children: firstChild.children,
2253
- total: firstChild.total,
2254
- disabled: firstChild.disabled
2255
- });
2256
- continue;
2257
- }
2258
- let total = 0;
2259
- let disabled = 0;
2260
- for (const c of children) {
2261
- total += c.total;
2262
- disabled += c.kind === "leaf" ? c.disabledCount : c.disabled;
2263
- }
2264
- nodes.push({
2265
- kind: "node",
2266
- prefix: child.prefix,
2267
- label: child.label,
2268
- children,
2269
- total,
2270
- disabled
2271
- });
2272
- }
2273
- nodes.sort((a, b) => {
2274
- if (a.kind !== b.kind) return a.kind === "node" ? -1 : 1;
2275
- return compareCodeUnits(a.kind === "node" ? a.label : a.name, b.kind === "node" ? b.label : b.name);
2276
- });
2277
- return nodes;
2278
- }
2279
- function buildToolPrefixTree(tools, disabled, query = "") {
2280
- const needle = typeof query === "string" ? query.trim().toLowerCase() : "";
2281
- const filtered = needle === "" ? tools : tools.filter((t) => t.name.toLowerCase().includes(needle) || t.description.toLowerCase().includes(needle));
2282
- const root = { children: new Map() };
2283
- for (const tool of filtered) {
2284
- const segments = splitToolName(tool.name);
2285
- let current = root;
2286
- for (let i = 0; i < segments.length; i++) {
2287
- const seg = segments[i];
2288
- if (seg === void 0) continue;
2289
- if (i === segments.length - 1) {
2290
- const isOff = disabled.has(tool.name);
2291
- const leaf = {
2292
- kind: "leaf",
2293
- name: tool.name,
2294
- label: seg,
2295
- description: tool.description,
2296
- disabled: isOff,
2297
- total: 1,
2298
- disabledCount: isOff ? 1 : 0
2299
- };
2300
- const existing = current.children.get(seg);
2301
- if (existing !== void 0 && existing.kind === "branch") existing.branch.children.set(`__self__:${tool.name}`, leaf);
2302
- else current.children.set(seg, leaf);
2303
- } else {
2304
- let next = current.children.get(seg);
2305
- if (next === void 0) {
2306
- next = {
2307
- kind: "branch",
2308
- prefix: segments.slice(0, i + 1).join("_"),
2309
- label: seg,
2310
- branch: { children: new Map() }
2311
- };
2312
- current.children.set(seg, next);
2313
- } else if (next.kind === "leaf") {
2314
- const branch = { children: new Map() };
2315
- branch.children.set(`__self__:${next.name}`, next);
2316
- next = {
2317
- kind: "branch",
2318
- prefix: segments.slice(0, i + 1).join("_"),
2319
- label: seg,
2320
- branch
2321
- };
2322
- current.children.set(seg, next);
3658
+ function projectSkills(events) {
3659
+ let windowStartSeq = null;
3660
+ let currentTurn;
3661
+ const rawNodes = [];
3662
+ const replacedRanges = [];
3663
+ const shadowedSeqs = [];
3664
+ const shadowedSet = new Set();
3665
+ for (const raw of events) {
3666
+ const ev = asRecord(raw);
3667
+ if (ev === null) continue;
3668
+ const seq = nonNegativeInt(ev.seq);
3669
+ if (seq !== void 0 && (windowStartSeq === null || seq < windowStartSeq)) windowStartSeq = seq;
3670
+ const range = replaceRangeOf(ev.surfaceOp);
3671
+ if (range !== null) replacedRanges.push(range);
3672
+ const data = asRecord(ev.data);
3673
+ const turnInEvent = positiveInt(data?.turn);
3674
+ if (range === null && turnInEvent !== void 0) currentTurn = turnInEvent;
3675
+ const effectiveTurn = turnInEvent ?? currentTurn;
3676
+ const type = nonEmptyString(ev.type);
3677
+ if (type === "compaction/summary" || type === "compaction/prune") {
3678
+ const list = data?.shadowedSeqs;
3679
+ if (Array.isArray(list)) for (const item of list) {
3680
+ const s = nonNegativeInt(item);
3681
+ if (s !== void 0 && !shadowedSet.has(s)) {
3682
+ shadowedSet.add(s);
3683
+ shadowedSeqs.push(s);
2323
3684
  }
2324
- current = next.branch;
2325
3685
  }
3686
+ continue;
3687
+ }
3688
+ if (seq === void 0) continue;
3689
+ if (type === "user/message" || type === "developer/message") {
3690
+ const name = invokedSkillName(type, data);
3691
+ if (name !== void 0) rawNodes.push({
3692
+ name,
3693
+ trigger: "user",
3694
+ seq,
3695
+ ...effectiveTurn === void 0 ? {} : { turn: effectiveTurn }
3696
+ });
3697
+ continue;
3698
+ }
3699
+ if (type === "tool/result") {
3700
+ const name = toolSkillName(asRecord(data?.message));
3701
+ if (name !== void 0) rawNodes.push({
3702
+ name,
3703
+ trigger: "agent",
3704
+ seq,
3705
+ ...effectiveTurn === void 0 ? {} : { turn: effectiveTurn }
3706
+ });
2326
3707
  }
2327
3708
  }
2328
- return finalizeBranch(root);
2329
- }
2330
- function collectNodeLeafNames(node) {
2331
- if (node.kind === "leaf") return [node.name];
2332
- const out = [];
2333
- for (const child of node.children) out.push(...collectNodeLeafNames(child));
2334
- return out;
2335
- }
2336
- function toggleToolInSet(current, toolName, nextDisabled) {
2337
- const next = new Set(current);
2338
- if (nextDisabled) next.add(toolName);
2339
- else next.delete(toolName);
2340
- return next;
2341
- }
2342
- function toggleNodeInSet(current, node) {
2343
- const names = collectNodeLeafNames(node);
2344
- const next = new Set(current);
2345
- if (names.some((name) => !current.has(name))) for (const name of names) next.add(name);
2346
- else for (const name of names) next.delete(name);
2347
- return next;
2348
- }
2349
- function disabledToolReason(toolName, enabled, disabled) {
2350
- if (!enabled || disabled.size === 0) return void 0;
2351
- if (disabled.has(toolName)) return `${DISABLED_TOOL_PREFIX} ${JSON.stringify(toolName)}`;
3709
+ const surviving = rawNodes.filter((node) => !isSeqShadowed(node.seq, replacedRanges, shadowedSet));
3710
+ return {
3711
+ skills: deduplicateSkills(surviving),
3712
+ nodes: surviving,
3713
+ windowStartSeq,
3714
+ replacedRanges,
3715
+ shadowedSeqs
3716
+ };
2352
3717
  }
2353
- function filterToolSchemas(tools, enabled, disabled) {
2354
- if (!enabled || disabled.size === 0) return [...tools];
2355
- return tools.filter((tool) => !disabled.has(tool.name));
3718
+ function mergeSkillProjections(host, client) {
3719
+ if (host === null) return client.skills;
3720
+ if (client.windowStartSeq === null) return host.skills;
3721
+ if (client.windowStartSeq === 0) return client.skills;
3722
+ const windowStart = client.windowStartSeq;
3723
+ const clientShadowed = new Set(client.shadowedSeqs);
3724
+ const hostNodes = host.nodes ?? host.skills;
3725
+ const clientNodes = client.nodes ?? client.skills;
3726
+ return deduplicateSkills([...hostNodes.filter((skill) => skill.seq < windowStart && !isSeqShadowed(skill.seq, client.replacedRanges, clientShadowed)), ...clientNodes]);
2356
3727
  }
2357
- function normalizeToolSummaries(list, excludedNames) {
2358
- const byName = new Map();
3728
+ function parseSkillArray(list) {
3729
+ const out = [];
2359
3730
  for (const item of list) {
2360
- if (item === null || item === void 0 || typeof item !== "object") continue;
2361
- const name = item.name;
2362
- if (typeof name !== "string" || name.trim() === "") continue;
2363
- const trimmed = name.trim();
2364
- if (excludedNames?.has(trimmed) || byName.has(trimmed)) continue;
2365
- const desc = item.description;
2366
- byName.set(trimmed, {
2367
- name: trimmed,
2368
- description: typeof desc === "string" ? desc.trim() : ""
3731
+ const row = asRecord(item);
3732
+ if (row === null) continue;
3733
+ const name = nonEmptyString(row.name);
3734
+ const trigger = row.trigger === "user" || row.trigger === "agent" ? row.trigger : void 0;
3735
+ const seq = nonNegativeInt(row.seq);
3736
+ const turn = positiveInt(row.turn);
3737
+ if (name !== void 0 && trigger !== void 0 && seq !== void 0) out.push({
3738
+ name,
3739
+ trigger,
3740
+ seq,
3741
+ ...turn === void 0 ? {} : { turn }
2369
3742
  });
2370
3743
  }
2371
- return [...byName.values()].sort((a, b) => compareCodeUnits(a.name, b.name));
3744
+ return out;
2372
3745
  }
2373
- function parseToolCatalog(raw) {
2374
- if (raw === null || raw === void 0 || typeof raw !== "object") return {
2375
- tools: [],
2376
- available: false
2377
- };
2378
- const list = raw.tools;
2379
- if (!Array.isArray(list)) return {
2380
- tools: [],
2381
- available: false
2382
- };
3746
+ function normalizeSkillProjection(raw) {
3747
+ const rec = asRecord(raw);
3748
+ if (rec === null || !Array.isArray(rec.skills)) return null;
3749
+ const skills = parseSkillArray(rec.skills);
3750
+ const nodes = Array.isArray(rec.nodes) ? parseSkillArray(rec.nodes) : skills;
3751
+ const windowStartSeq = nonNegativeInt(rec.windowStartSeq) ?? null;
3752
+ const replacedRanges = [];
3753
+ if (Array.isArray(rec.replacedRanges)) for (const item of rec.replacedRanges) {
3754
+ const r = asRecord(item);
3755
+ const startSeq = nonNegativeInt(r?.startSeq);
3756
+ const endSeq = nonNegativeInt(r?.endSeq);
3757
+ if (startSeq !== void 0 && endSeq !== void 0 && endSeq >= startSeq) replacedRanges.push({
3758
+ startSeq,
3759
+ endSeq
3760
+ });
3761
+ }
3762
+ const shadowedSeqs = [];
3763
+ if (Array.isArray(rec.shadowedSeqs)) for (const item of rec.shadowedSeqs) {
3764
+ const s = nonNegativeInt(item);
3765
+ if (s !== void 0) shadowedSeqs.push(s);
3766
+ }
2383
3767
  return {
2384
- tools: normalizeToolSummaries(list),
2385
- available: true
3768
+ skills,
3769
+ nodes,
3770
+ windowStartSeq,
3771
+ replacedRanges,
3772
+ shadowedSeqs
2386
3773
  };
2387
3774
  }
2388
- //#endregion
2389
- //#region src/client/session-info/tools-popover.ts
2390
- const TOOLS_POPOVER_ATTR = "data-desktop-enhance-tools-popover";
2391
- function buildToolsSummarySection(opts) {
2392
- const { t, enabledToolsCount, totalToolsCount, disabledInCatalog, popoverOpen, onTogglePopover } = opts;
2393
- const toolSec = globalThis.document.createElement("section");
2394
- toolSec.setAttribute("data-session-info-section", "tools");
2395
- const toolRow = globalThis.document.createElement("div");
2396
- toolRow.setAttribute("data-session-info-tools-row", "");
2397
- const left = globalThis.document.createElement("span");
2398
- left.setAttribute("data-session-info-tools-left", "");
2399
- const titleSpan = globalThis.document.createElement("span");
2400
- titleSpan.setAttribute("data-session-info-tools-title", "");
2401
- titleSpan.textContent = t("sessionInfo.tools.title");
2402
- left.appendChild(titleSpan);
2403
- const countSpan = globalThis.document.createElement("span");
2404
- countSpan.setAttribute("data-session-info-tools-count", "");
2405
- countSpan.setAttribute("data-has-disabled", disabledInCatalog.length > 0 ? "true" : "false");
2406
- countSpan.textContent = `${String(enabledToolsCount)}/${String(totalToolsCount)}`;
2407
- left.appendChild(countSpan);
2408
- toolRow.appendChild(left);
2409
- const manageBtn = globalThis.document.createElement("button");
2410
- manageBtn.setAttribute("type", "button");
2411
- manageBtn.setAttribute("data-session-info-tools-manage", "");
2412
- manageBtn.setAttribute("aria-expanded", popoverOpen ? "true" : "false");
2413
- manageBtn.textContent = popoverOpen ? t("sessionInfo.tools.close") : t("sessionInfo.tools.manage");
2414
- manageBtn.addEventListener("click", (e) => {
2415
- e?.stopPropagation?.();
2416
- onTogglePopover();
2417
- });
2418
- toolRow.appendChild(manageBtn);
2419
- toolSec.appendChild(toolRow);
2420
- if (disabledInCatalog.length > 0) {
2421
- const disabledWrap = globalThis.document.createElement("div");
2422
- disabledWrap.setAttribute("data-session-info-tools-disabled", "");
2423
- const prefixSpan = globalThis.document.createElement("span");
2424
- prefixSpan.setAttribute("data-session-info-tools-muted", "");
2425
- prefixSpan.textContent = t("sessionInfo.tools.disabledPrefix");
2426
- disabledWrap.appendChild(prefixSpan);
2427
- for (const item of disabledInCatalog.slice(0, 3)) {
2428
- const tag = globalThis.document.createElement("span");
2429
- tag.setAttribute("data-session-info-tools-tag", item.name);
2430
- tag.textContent = item.name;
2431
- disabledWrap.appendChild(tag);
2432
- }
2433
- if (disabledInCatalog.length > 3) {
2434
- const more = globalThis.document.createElement("span");
2435
- more.setAttribute("data-session-info-tools-muted", "");
2436
- more.textContent = `+${String(disabledInCatalog.length - 3)}`;
2437
- disabledWrap.appendChild(more);
2438
- }
2439
- toolSec.appendChild(disabledWrap);
2440
- }
2441
- return toolSec;
2442
- }
2443
- function syncToolsPopover(props) {
2444
- const { root, t, toolsCatalog, disabledSet, disabledInCatalog, searchQuery, expandedToolNodes, writable, onSearchChange, onToggleNodeExpand, onCommitSet, onRefreshCatalog, onClose } = props;
2445
- let pop = root.querySelector(`[${TOOLS_POPOVER_ATTR}]`);
2446
- if (pop === null) {
2447
- pop = globalThis.document.createElement("aside");
2448
- pop.setAttribute(TOOLS_POPOVER_ATTR, "");
2449
- const head = globalThis.document.createElement("div");
2450
- head.setAttribute("data-tools-popover-header", "");
2451
- const titleWrap = globalThis.document.createElement("div");
2452
- titleWrap.setAttribute("data-tools-popover-title-wrap", "");
2453
- const titleEl = globalThis.document.createElement("span");
2454
- titleEl.setAttribute("data-tools-popover-title", "");
2455
- titleEl.textContent = t("sessionInfo.tools.popoverTitle");
2456
- const hintEl = globalThis.document.createElement("span");
2457
- hintEl.setAttribute("data-session-info-tools-muted", "");
2458
- hintEl.textContent = t("sessionInfo.tools.popoverHint");
2459
- titleWrap.appendChild(titleEl);
2460
- titleWrap.appendChild(hintEl);
2461
- head.appendChild(titleWrap);
2462
- const closeBtn = globalThis.document.createElement("button");
2463
- closeBtn.setAttribute("type", "button");
2464
- closeBtn.setAttribute("data-tools-popover-close", "");
2465
- closeBtn.textContent = "✕";
2466
- closeBtn.addEventListener("click", onClose);
2467
- head.appendChild(closeBtn);
2468
- pop.appendChild(head);
2469
- const body = globalThis.document.createElement("div");
2470
- body.setAttribute("data-tools-popover-body", "");
2471
- const toolbar = globalThis.document.createElement("div");
2472
- toolbar.setAttribute("data-tools-popover-toolbar", "");
2473
- const searchInput = globalThis.document.createElement("input");
2474
- searchInput.setAttribute("type", "search");
2475
- searchInput.setAttribute("data-tools-popover-search", "");
2476
- searchInput.setAttribute("placeholder", t("settings.tools.search"));
2477
- searchInput.value = searchQuery;
2478
- searchInput.addEventListener("input", () => {
2479
- onSearchChange(searchInput.value);
2480
- });
2481
- toolbar.appendChild(searchInput);
2482
- const actions = globalThis.document.createElement("div");
2483
- actions.setAttribute("data-tools-popover-actions", "");
2484
- const enableAllBtn = globalThis.document.createElement("button");
2485
- enableAllBtn.setAttribute("type", "button");
2486
- enableAllBtn.setAttribute("data-tools-btn", "");
2487
- enableAllBtn.setAttribute("data-tools-popover-enable-all", "");
2488
- enableAllBtn.addEventListener("click", () => {
2489
- onCommitSet(new Set());
2490
- });
2491
- actions.appendChild(enableAllBtn);
2492
- const refreshBtn = globalThis.document.createElement("button");
2493
- refreshBtn.setAttribute("type", "button");
2494
- refreshBtn.setAttribute("data-tools-btn", "");
2495
- refreshBtn.setAttribute("data-tools-popover-refresh", "");
2496
- refreshBtn.textContent = t("settings.tools.refresh");
2497
- refreshBtn.addEventListener("click", onRefreshCatalog);
2498
- actions.appendChild(refreshBtn);
2499
- toolbar.appendChild(actions);
2500
- body.appendChild(toolbar);
2501
- const treeContainer = globalThis.document.createElement("div");
2502
- treeContainer.setAttribute("data-tools-popover-tree", "");
2503
- body.appendChild(treeContainer);
2504
- pop.appendChild(body);
2505
- root.appendChild(pop);
3775
+ function buildSessionInfoSections(skills, t) {
3776
+ return [{
3777
+ id: "skills",
3778
+ title: t("sessionInfo.skills.title"),
3779
+ shortLabel: t("sessionInfo.skills.short"),
3780
+ emptyText: t("sessionInfo.skills.empty"),
3781
+ items: skills.map((skill) => ({
3782
+ name: skill.name,
3783
+ badge: skill.trigger === "user" ? t("sessionInfo.trigger.user") : t("sessionInfo.trigger.agent"),
3784
+ ...skill.turn === void 0 ? {} : { turnLabel: `#${String(skill.turn)}` }
3785
+ }))
3786
+ }];
3787
+ }
3788
+ //#endregion
3789
+ //#region src/client/session-info/tools-popover.ts
3790
+ const TOOLS_POPOVER_ATTR = "data-desktop-enhance-tools-popover";
3791
+ const SKILLS_POPOVER_ATTR = "data-desktop-enhance-skills-popover";
3792
+ function populateSummaryContainer(container, opts) {
3793
+ const { kind, t, titleKey, manageKey, closeKey, disabledPrefixKey, enabledCount, totalCount, disabledInCatalog, customized, popoverOpen, onTogglePopover } = opts;
3794
+ const row = globalThis.document.createElement("div");
3795
+ row.setAttribute("data-session-info-tools-row", "");
3796
+ if (kind === "skills") row.setAttribute("data-session-info-skills-row", "");
3797
+ const left = globalThis.document.createElement("span");
3798
+ left.setAttribute("data-session-info-tools-left", "");
3799
+ const titleSpan = globalThis.document.createElement("span");
3800
+ titleSpan.setAttribute("data-session-info-tools-title", "");
3801
+ titleSpan.textContent = t(titleKey);
3802
+ left.appendChild(titleSpan);
3803
+ const countSpan = globalThis.document.createElement("span");
3804
+ countSpan.setAttribute("data-session-info-tools-count", "");
3805
+ if (kind === "skills") countSpan.setAttribute("data-session-info-skills-count", "");
3806
+ countSpan.setAttribute("data-has-disabled", disabledInCatalog.length > 0 ? "true" : "false");
3807
+ countSpan.textContent = `${String(enabledCount)}/${String(totalCount)}`;
3808
+ left.appendChild(countSpan);
3809
+ if (customized) {
3810
+ const badge = globalThis.document.createElement("span");
3811
+ badge.setAttribute("data-session-info-override-badge", kind);
3812
+ badge.textContent = t("sessionInfo.override.badge");
3813
+ left.appendChild(badge);
2506
3814
  }
2507
- const enableAllBtn = pop.querySelector("[data-tools-popover-enable-all]");
2508
- if (enableAllBtn !== null) {
2509
- const enabledCount = toolsCatalog.length - disabledInCatalog.length;
2510
- enableAllBtn.textContent = `${t("settings.tools.enableAll")} (${String(enabledCount)}/${String(toolsCatalog.length)})`;
2511
- if (!writable || disabledSet.size === 0) enableAllBtn.setAttribute("disabled", "");
2512
- else enableAllBtn.removeAttribute("disabled");
3815
+ row.appendChild(left);
3816
+ const manageBtn = globalThis.document.createElement("button");
3817
+ manageBtn.setAttribute("type", "button");
3818
+ manageBtn.setAttribute("data-session-info-tools-manage", "");
3819
+ if (kind === "skills") manageBtn.setAttribute("data-session-info-skills-manage", "");
3820
+ manageBtn.setAttribute("aria-expanded", popoverOpen ? "true" : "false");
3821
+ manageBtn.textContent = popoverOpen ? t(closeKey) : t(manageKey);
3822
+ manageBtn.addEventListener("click", (e) => {
3823
+ e?.stopPropagation?.();
3824
+ onTogglePopover();
3825
+ });
3826
+ row.appendChild(manageBtn);
3827
+ container.appendChild(row);
3828
+ if (disabledInCatalog.length > 0) {
3829
+ const disabledWrap = globalThis.document.createElement("div");
3830
+ disabledWrap.setAttribute(`data-session-info-${kind}-disabled`, "");
3831
+ const prefixSpan = globalThis.document.createElement("span");
3832
+ prefixSpan.setAttribute("data-session-info-tools-muted", "");
3833
+ prefixSpan.textContent = t(disabledPrefixKey);
3834
+ disabledWrap.appendChild(prefixSpan);
3835
+ for (const item of disabledInCatalog.slice(0, 3)) {
3836
+ const tag = globalThis.document.createElement("span");
3837
+ tag.setAttribute(`data-session-info-${kind}-tag`, item.name);
3838
+ tag.textContent = item.name;
3839
+ disabledWrap.appendChild(tag);
3840
+ }
3841
+ if (disabledInCatalog.length > 3) {
3842
+ const more = globalThis.document.createElement("span");
3843
+ more.setAttribute("data-session-info-tools-muted", "");
3844
+ more.textContent = `+${String(disabledInCatalog.length - 3)}`;
3845
+ disabledWrap.appendChild(more);
3846
+ }
3847
+ container.appendChild(disabledWrap);
2513
3848
  }
2514
- const treeContainer = pop.querySelector("[data-tools-popover-tree]");
2515
- if (treeContainer === null) return pop;
2516
- const treeNodes = buildToolPrefixTree(toolsCatalog, disabledSet, searchQuery);
2517
- if (treeNodes.length === 0) {
3849
+ return container;
3850
+ }
3851
+ function buildToolsSummarySection(opts) {
3852
+ const toolSec = globalThis.document.createElement("section");
3853
+ toolSec.setAttribute("data-session-info-section", "tools");
3854
+ return populateSummaryContainer(toolSec, {
3855
+ kind: "tools",
3856
+ t: opts.t,
3857
+ titleKey: "sessionInfo.tools.title",
3858
+ manageKey: "sessionInfo.tools.manage",
3859
+ closeKey: "sessionInfo.tools.close",
3860
+ disabledPrefixKey: "sessionInfo.tools.disabledPrefix",
3861
+ enabledCount: opts.enabledToolsCount,
3862
+ totalCount: opts.totalToolsCount,
3863
+ disabledInCatalog: opts.disabledInCatalog,
3864
+ customized: opts.customized ?? false,
3865
+ popoverOpen: opts.popoverOpen,
3866
+ onTogglePopover: opts.onTogglePopover
3867
+ });
3868
+ }
3869
+ function buildSkillsSummaryControls(opts) {
3870
+ const wrap = globalThis.document.createElement("div");
3871
+ wrap.setAttribute("data-session-info-skills-summary", "");
3872
+ return populateSummaryContainer(wrap, {
3873
+ kind: "skills",
3874
+ t: opts.t,
3875
+ titleKey: "sessionInfo.skills.available",
3876
+ manageKey: "sessionInfo.skills.manage",
3877
+ closeKey: "sessionInfo.skills.close",
3878
+ disabledPrefixKey: "sessionInfo.skills.disabledPrefix",
3879
+ enabledCount: opts.enabledSkillsCount,
3880
+ totalCount: opts.totalSkillsCount,
3881
+ disabledInCatalog: opts.disabledInCatalog,
3882
+ customized: opts.customized ?? false,
3883
+ popoverOpen: opts.popoverOpen,
3884
+ onTogglePopover: opts.onTogglePopover
3885
+ });
3886
+ }
3887
+ function syncOverrideBanner(pop, t, customized, writable, onResetOverride) {
3888
+ const slot = pop.querySelector("[data-popover-override-slot]");
3889
+ if (slot === null) return;
3890
+ if (!customized || onResetOverride === void 0) {
3891
+ slot.replaceChildren();
3892
+ return;
3893
+ }
3894
+ const banner = globalThis.document.createElement("div");
3895
+ banner.setAttribute("data-popover-override-banner", "");
3896
+ const text = globalThis.document.createElement("span");
3897
+ text.setAttribute("data-popover-override-text", "");
3898
+ text.textContent = t("sessionInfo.override.banner");
3899
+ banner.appendChild(text);
3900
+ const resetBtn = globalThis.document.createElement("button");
3901
+ resetBtn.setAttribute("type", "button");
3902
+ resetBtn.setAttribute("data-tools-btn", "");
3903
+ resetBtn.setAttribute("data-popover-override-reset", "");
3904
+ resetBtn.textContent = t("sessionInfo.override.reset");
3905
+ if (!writable) resetBtn.setAttribute("disabled", "");
3906
+ resetBtn.addEventListener("click", () => {
3907
+ onResetOverride();
3908
+ });
3909
+ banner.appendChild(resetBtn);
3910
+ slot.replaceChildren(banner);
3911
+ }
3912
+ function buildCollapsibleGroupHeaderDom(opts) {
3913
+ const { t, headerAttr, headerValue, extraHeaderAttr, batchAttr, batchValue, labelText, isOpen, total, disabledCount, writable, depth = 0, onToggleOpen, onBatchToggle } = opts;
3914
+ const head = globalThis.document.createElement("div");
3915
+ head.setAttribute(headerAttr, headerValue);
3916
+ if (extraHeaderAttr !== void 0) head.setAttribute(extraHeaderAttr.name, extraHeaderAttr.value);
3917
+ if (depth > 0) head.setAttribute("style", `padding-left: ${String(depth * 18 + 8)}px;`);
3918
+ const title = globalThis.document.createElement("span");
3919
+ title.setAttribute("data-tools-node-title", "");
3920
+ const arrow = globalThis.document.createElement("span");
3921
+ arrow.setAttribute("data-session-info-arrow", "");
3922
+ arrow.textContent = isOpen ? "▾" : "▸";
3923
+ const label = globalThis.document.createElement("span");
3924
+ label.textContent = labelText;
3925
+ title.appendChild(arrow);
3926
+ title.appendChild(label);
3927
+ head.appendChild(title);
3928
+ const ctrls = globalThis.document.createElement("div");
3929
+ ctrls.setAttribute("data-tools-controls", "");
3930
+ const enabledInGroup = total - disabledCount;
3931
+ const pill = globalThis.document.createElement("span");
3932
+ pill.setAttribute("data-tools-pill", "");
3933
+ pill.setAttribute("data-disabled", enabledInGroup === 0 ? "true" : "false");
3934
+ pill.textContent = enabledInGroup === 0 ? t("settings.tools.allDisabled") : `${String(enabledInGroup)}/${String(total)}`;
3935
+ ctrls.appendChild(pill);
3936
+ const batchBtn = globalThis.document.createElement("button");
3937
+ batchBtn.setAttribute("type", "button");
3938
+ batchBtn.setAttribute("data-tools-btn", "");
3939
+ batchBtn.setAttribute(batchAttr, batchValue);
3940
+ batchBtn.textContent = enabledInGroup > 0 ? t("settings.tools.disableAll") : t("settings.tools.enableAll");
3941
+ if (!writable) batchBtn.setAttribute("disabled", "");
3942
+ batchBtn.addEventListener("click", (e) => {
3943
+ e?.stopPropagation?.();
3944
+ onBatchToggle();
3945
+ });
3946
+ ctrls.appendChild(batchBtn);
3947
+ head.appendChild(ctrls);
3948
+ head.addEventListener("click", onToggleOpen);
3949
+ return head;
3950
+ }
3951
+ function buildToolTreeDomNodes(opts) {
3952
+ const { t, toolsCatalog, disabledSet, searchQuery, expandedToolNodes, writable, onToggleNodeExpand, onCommitSet } = opts;
3953
+ const scopeGroups = buildToolScopeGroups(toolsCatalog, disabledSet, searchQuery);
3954
+ if (scopeGroups.length === 0) {
2518
3955
  const empty = globalThis.document.createElement("div");
2519
3956
  empty.setAttribute("data-tools-empty", "");
2520
3957
  empty.textContent = t("settings.tools.empty");
2521
- treeContainer.replaceChildren(empty);
2522
- return pop;
3958
+ return [empty];
2523
3959
  }
2524
3960
  const buildNodeDom = (node, depth) => {
2525
3961
  if (node.kind === "leaf") {
2526
3962
  const row = globalThis.document.createElement("div");
2527
3963
  row.setAttribute("data-tools-leaf", node.name);
3964
+ row.setAttribute("data-tool-scope", node.scope);
2528
3965
  row.setAttribute("data-disabled", node.disabled ? "true" : "false");
2529
3966
  if (depth > 0) row.setAttribute("style", `padding-left: ${String(depth * 18 + 8)}px;`);
2530
3967
  const info = globalThis.document.createElement("div");
2531
3968
  info.setAttribute("data-tools-leaf-info", "");
2532
- const nameEl = globalThis.document.createElement("div");
3969
+ const nameRow = globalThis.document.createElement("div");
3970
+ nameRow.setAttribute("data-tools-leaf-header", "");
3971
+ const nameEl = globalThis.document.createElement("span");
2533
3972
  nameEl.setAttribute("data-tools-leaf-name", "");
2534
3973
  nameEl.textContent = node.name;
2535
- info.appendChild(nameEl);
3974
+ nameRow.appendChild(nameEl);
3975
+ if (node.scope === "plugin" && node.sourceBadge !== "") {
3976
+ const badgeEl = globalThis.document.createElement("span");
3977
+ badgeEl.setAttribute("data-tools-source-badge", node.scope);
3978
+ badgeEl.textContent = node.sourceBadge;
3979
+ nameRow.appendChild(badgeEl);
3980
+ }
3981
+ info.appendChild(nameRow);
2536
3982
  if (node.description !== "") {
2537
3983
  const descEl = globalThis.document.createElement("div");
2538
3984
  descEl.setAttribute("data-tools-leaf-desc", "");
@@ -2563,50 +4009,324 @@ window.__ModuleLoader__.load({
2563
4009
  const isOpen = searchQuery.trim() !== "" || expandedToolNodes.has(node.prefix);
2564
4010
  const groupEl = globalThis.document.createElement("div");
2565
4011
  groupEl.setAttribute("data-tools-node", node.prefix);
4012
+ groupEl.appendChild(buildCollapsibleGroupHeaderDom({
4013
+ t,
4014
+ headerAttr: "data-tools-node-header",
4015
+ headerValue: node.prefix,
4016
+ batchAttr: "data-tools-batch",
4017
+ batchValue: node.prefix,
4018
+ labelText: node.label,
4019
+ isOpen,
4020
+ total: node.total,
4021
+ disabledCount: node.disabled,
4022
+ writable,
4023
+ depth,
4024
+ onToggleOpen: () => onToggleNodeExpand(node.prefix),
4025
+ onBatchToggle: () => onCommitSet(toggleNodeInSet(disabledSet, node))
4026
+ }));
4027
+ if (isOpen) for (const child of node.children) groupEl.appendChild(buildNodeDom(child, depth + 1));
4028
+ return groupEl;
4029
+ };
4030
+ const buildScopeGroupDom = (group) => {
4031
+ const scopeNodeKey = `scope:${group.scope}`;
4032
+ const isOpen = searchQuery.trim() !== "" || expandedToolNodes.has(scopeNodeKey);
4033
+ const groupEl = globalThis.document.createElement("div");
4034
+ groupEl.setAttribute("data-tools-scope-group", group.scope);
4035
+ groupEl.appendChild(buildCollapsibleGroupHeaderDom({
4036
+ t,
4037
+ headerAttr: "data-tools-node-header",
4038
+ headerValue: scopeNodeKey,
4039
+ extraHeaderAttr: {
4040
+ name: "data-tools-scope-header",
4041
+ value: group.scope
4042
+ },
4043
+ batchAttr: "data-tools-scope-batch",
4044
+ batchValue: group.scope,
4045
+ labelText: t(`settings.tools.scope.${group.scope}`),
4046
+ isOpen,
4047
+ total: group.total,
4048
+ disabledCount: group.disabled,
4049
+ writable,
4050
+ depth: 0,
4051
+ onToggleOpen: () => onToggleNodeExpand(scopeNodeKey),
4052
+ onBatchToggle: () => onCommitSet(toggleToolScopeGroupInSet(disabledSet, group))
4053
+ }));
4054
+ if (isOpen) for (const child of group.children) groupEl.appendChild(buildNodeDom(child, 1));
4055
+ return groupEl;
4056
+ };
4057
+ return scopeGroups.map(buildScopeGroupDom);
4058
+ }
4059
+ function buildSkillGroupDomNodes(opts) {
4060
+ const { t, skillsCatalog, disabledSet, searchQuery, expandedSkillScopes, includeProject, writable, onToggleScopeExpand, onCommitSet, onPreviewSkill } = opts;
4061
+ const groups = buildSkillScopeGroups(skillsCatalog, disabledSet, searchQuery, { includeProject });
4062
+ if (groups.length === 0) {
4063
+ const empty = globalThis.document.createElement("div");
4064
+ empty.setAttribute("data-tools-empty", "");
4065
+ empty.setAttribute("data-skills-empty", "");
4066
+ empty.textContent = t("settings.skills.empty");
4067
+ return [empty];
4068
+ }
4069
+ const buildGroupDom = (group) => {
4070
+ const isOpen = searchQuery.trim() !== "" || expandedSkillScopes.has(group.scope);
4071
+ const groupEl = globalThis.document.createElement("div");
4072
+ groupEl.setAttribute("data-tools-node", group.scope);
4073
+ groupEl.setAttribute("data-skills-group", group.scope);
2566
4074
  const head = globalThis.document.createElement("div");
2567
- head.setAttribute("data-tools-node-header", node.prefix);
2568
- if (depth > 0) head.setAttribute("style", `padding-left: ${String(depth * 18 + 8)}px;`);
4075
+ head.setAttribute("data-tools-node-header", group.scope);
4076
+ head.setAttribute("data-skills-group-header", group.scope);
2569
4077
  const title = globalThis.document.createElement("span");
2570
4078
  title.setAttribute("data-tools-node-title", "");
2571
4079
  const arrow = globalThis.document.createElement("span");
2572
4080
  arrow.setAttribute("data-session-info-arrow", "");
2573
4081
  arrow.textContent = isOpen ? "▾" : "▸";
2574
4082
  const label = globalThis.document.createElement("span");
2575
- label.textContent = node.label;
4083
+ label.textContent = t(`settings.skills.scope.${group.scope}`);
2576
4084
  title.appendChild(arrow);
2577
4085
  title.appendChild(label);
2578
4086
  head.appendChild(title);
2579
4087
  const ctrls = globalThis.document.createElement("div");
2580
4088
  ctrls.setAttribute("data-tools-controls", "");
2581
- const enabledInNode = node.total - node.disabled;
4089
+ const enabledInGroup = group.total - group.disabled;
2582
4090
  const pill = globalThis.document.createElement("span");
2583
4091
  pill.setAttribute("data-tools-pill", "");
2584
- pill.setAttribute("data-disabled", enabledInNode === 0 ? "true" : "false");
2585
- pill.textContent = enabledInNode === 0 ? t("settings.tools.allDisabled") : `${String(enabledInNode)}/${String(node.total)}`;
4092
+ pill.setAttribute("data-disabled", enabledInGroup === 0 ? "true" : "false");
4093
+ pill.textContent = enabledInGroup === 0 ? t("settings.tools.allDisabled") : `${String(enabledInGroup)}/${String(group.total)}`;
2586
4094
  ctrls.appendChild(pill);
2587
4095
  const batchBtn = globalThis.document.createElement("button");
2588
4096
  batchBtn.setAttribute("type", "button");
2589
4097
  batchBtn.setAttribute("data-tools-btn", "");
2590
- batchBtn.setAttribute("data-tools-batch", node.prefix);
2591
- batchBtn.textContent = enabledInNode > 0 ? t("settings.tools.disableAll") : t("settings.tools.enableAll");
4098
+ batchBtn.setAttribute("data-skills-batch", group.scope);
4099
+ batchBtn.textContent = enabledInGroup > 0 ? t("settings.tools.disableAll") : t("settings.tools.enableAll");
2592
4100
  if (!writable) batchBtn.setAttribute("disabled", "");
2593
4101
  batchBtn.addEventListener("click", (e) => {
2594
4102
  e?.stopPropagation?.();
2595
- onCommitSet(toggleNodeInSet(disabledSet, node));
4103
+ onCommitSet(toggleSkillGroupInSet(disabledSet, group));
2596
4104
  });
2597
4105
  ctrls.appendChild(batchBtn);
2598
4106
  head.appendChild(ctrls);
2599
4107
  head.addEventListener("click", () => {
2600
- onToggleNodeExpand(node.prefix);
4108
+ onToggleScopeExpand(group.scope);
2601
4109
  });
2602
4110
  groupEl.appendChild(head);
2603
- if (isOpen) for (const child of node.children) groupEl.appendChild(buildNodeDom(child, depth + 1));
4111
+ if (isOpen) for (const item of group.items) {
4112
+ const row = globalThis.document.createElement("div");
4113
+ row.setAttribute("data-tools-leaf", item.name);
4114
+ row.setAttribute("data-skills-leaf", item.name);
4115
+ row.setAttribute("data-skill-scope", item.scope);
4116
+ row.setAttribute("data-disabled", item.disabled ? "true" : "false");
4117
+ row.setAttribute("style", "padding-left: 26px;");
4118
+ const info = globalThis.document.createElement("div");
4119
+ info.setAttribute("data-tools-leaf-info", "");
4120
+ const nameRow = globalThis.document.createElement("div");
4121
+ nameRow.setAttribute("data-skills-leaf-header", "");
4122
+ const nameEl = globalThis.document.createElement("span");
4123
+ nameEl.setAttribute("data-tools-leaf-name", "");
4124
+ nameEl.setAttribute("data-skills-leaf-name", "");
4125
+ nameEl.textContent = item.name;
4126
+ nameRow.appendChild(nameEl);
4127
+ const sourceBadge = globalThis.document.createElement("span");
4128
+ sourceBadge.setAttribute("data-skills-source-badge", item.scope);
4129
+ sourceBadge.textContent = item.sourceBadge;
4130
+ nameRow.appendChild(sourceBadge);
4131
+ if (!item.modelInvocable) {
4132
+ const userOnly = globalThis.document.createElement("span");
4133
+ userOnly.setAttribute("data-skills-user-only", "");
4134
+ userOnly.textContent = t("settings.skills.userOnly");
4135
+ nameRow.appendChild(userOnly);
4136
+ }
4137
+ if (onPreviewSkill !== void 0) {
4138
+ const previewBtn = globalThis.document.createElement("button");
4139
+ previewBtn.setAttribute("type", "button");
4140
+ previewBtn.setAttribute("data-skills-preview", item.name);
4141
+ previewBtn.textContent = t("settings.skills.preview");
4142
+ previewBtn.addEventListener("click", (e) => {
4143
+ e?.stopPropagation?.();
4144
+ onPreviewSkill(item.name);
4145
+ });
4146
+ nameRow.appendChild(previewBtn);
4147
+ }
4148
+ info.appendChild(nameRow);
4149
+ if (item.description !== "") {
4150
+ const descEl = globalThis.document.createElement("div");
4151
+ descEl.setAttribute("data-tools-leaf-desc", "");
4152
+ descEl.textContent = item.description;
4153
+ info.appendChild(descEl);
4154
+ }
4155
+ row.appendChild(info);
4156
+ const itemCtrls = globalThis.document.createElement("div");
4157
+ itemCtrls.setAttribute("data-tools-controls", "");
4158
+ const itemPill = globalThis.document.createElement("span");
4159
+ itemPill.setAttribute("data-tools-pill", "");
4160
+ itemPill.setAttribute("data-disabled", item.disabled ? "true" : "false");
4161
+ itemPill.textContent = item.disabled ? t("settings.tools.disabled") : t("settings.tools.enabled");
4162
+ itemCtrls.appendChild(itemPill);
4163
+ const toggleBtn = globalThis.document.createElement("button");
4164
+ toggleBtn.setAttribute("type", "button");
4165
+ toggleBtn.setAttribute("data-tools-btn", "");
4166
+ toggleBtn.setAttribute("data-skills-toggle", item.name);
4167
+ toggleBtn.textContent = item.disabled ? t("settings.tools.enable") : t("settings.tools.disable");
4168
+ if (!writable) toggleBtn.setAttribute("disabled", "");
4169
+ toggleBtn.addEventListener("click", () => {
4170
+ onCommitSet(toggleToolInSet(disabledSet, item.name, !item.disabled));
4171
+ });
4172
+ itemCtrls.appendChild(toggleBtn);
4173
+ row.appendChild(itemCtrls);
4174
+ groupEl.appendChild(row);
4175
+ }
2604
4176
  return groupEl;
2605
4177
  };
2606
- const renderedNodes = treeNodes.map((n) => buildNodeDom(n, 0));
2607
- treeContainer.replaceChildren(...renderedNodes);
4178
+ return groups.map(buildGroupDom);
4179
+ }
4180
+ function syncAnchoredPopoverShell(opts) {
4181
+ const { root, popoverAttr, kind, t, titleKey, hintKey, searchPlaceholderKey, searchQuery, totalCount, disabledInCatalogCount, hasAnyDisabled, customized, writable, onSearchChange, onEnableAll, onResetOverride, onRefreshCatalog, onClose, renderTreeNodes } = opts;
4182
+ const enableAllAttr = `data-${kind}-popover-enable-all`;
4183
+ const refreshAttr = `data-${kind}-popover-refresh`;
4184
+ let pop = root.querySelector(`[${popoverAttr}]`);
4185
+ if (pop === null) {
4186
+ pop = globalThis.document.createElement("aside");
4187
+ pop.setAttribute(popoverAttr, "");
4188
+ const head = globalThis.document.createElement("div");
4189
+ head.setAttribute("data-tools-popover-header", "");
4190
+ const titleWrap = globalThis.document.createElement("div");
4191
+ titleWrap.setAttribute("data-tools-popover-title-wrap", "");
4192
+ const titleEl = globalThis.document.createElement("span");
4193
+ titleEl.setAttribute("data-tools-popover-title", "");
4194
+ titleEl.textContent = t(titleKey);
4195
+ const hintEl = globalThis.document.createElement("span");
4196
+ hintEl.setAttribute("data-session-info-tools-muted", "");
4197
+ hintEl.textContent = t(hintKey);
4198
+ titleWrap.appendChild(titleEl);
4199
+ titleWrap.appendChild(hintEl);
4200
+ head.appendChild(titleWrap);
4201
+ const closeBtn = globalThis.document.createElement("button");
4202
+ closeBtn.setAttribute("type", "button");
4203
+ closeBtn.setAttribute("data-tools-popover-close", "");
4204
+ if (kind === "skills") closeBtn.setAttribute("data-skills-popover-close", "");
4205
+ closeBtn.textContent = "✕";
4206
+ closeBtn.addEventListener("click", onClose);
4207
+ head.appendChild(closeBtn);
4208
+ pop.appendChild(head);
4209
+ const body = globalThis.document.createElement("div");
4210
+ body.setAttribute("data-tools-popover-body", "");
4211
+ const overrideSlot = globalThis.document.createElement("div");
4212
+ overrideSlot.setAttribute("data-popover-override-slot", "");
4213
+ body.appendChild(overrideSlot);
4214
+ const toolbar = globalThis.document.createElement("div");
4215
+ toolbar.setAttribute("data-tools-popover-toolbar", "");
4216
+ const searchInput = globalThis.document.createElement("input");
4217
+ searchInput.setAttribute("type", "search");
4218
+ searchInput.setAttribute("data-tools-popover-search", "");
4219
+ if (kind === "skills") searchInput.setAttribute("data-skills-popover-search", "");
4220
+ searchInput.setAttribute("placeholder", t(searchPlaceholderKey));
4221
+ searchInput.value = searchQuery;
4222
+ searchInput.addEventListener("input", () => {
4223
+ onSearchChange(searchInput.value);
4224
+ });
4225
+ toolbar.appendChild(searchInput);
4226
+ const actions = globalThis.document.createElement("div");
4227
+ actions.setAttribute("data-tools-popover-actions", "");
4228
+ const enableAllBtn = globalThis.document.createElement("button");
4229
+ enableAllBtn.setAttribute("type", "button");
4230
+ enableAllBtn.setAttribute("data-tools-btn", "");
4231
+ enableAllBtn.setAttribute(enableAllAttr, "");
4232
+ enableAllBtn.addEventListener("click", onEnableAll);
4233
+ actions.appendChild(enableAllBtn);
4234
+ const refreshBtn = globalThis.document.createElement("button");
4235
+ refreshBtn.setAttribute("type", "button");
4236
+ refreshBtn.setAttribute("data-tools-btn", "");
4237
+ refreshBtn.setAttribute(refreshAttr, "");
4238
+ refreshBtn.textContent = t("settings.tools.refresh");
4239
+ refreshBtn.addEventListener("click", onRefreshCatalog);
4240
+ actions.appendChild(refreshBtn);
4241
+ toolbar.appendChild(actions);
4242
+ body.appendChild(toolbar);
4243
+ const treeContainer = globalThis.document.createElement("div");
4244
+ treeContainer.setAttribute("data-tools-popover-tree", "");
4245
+ if (kind === "skills") treeContainer.setAttribute("data-skills-popover-tree", "");
4246
+ body.appendChild(treeContainer);
4247
+ pop.appendChild(body);
4248
+ root.appendChild(pop);
4249
+ }
4250
+ syncOverrideBanner(pop, t, customized, writable, onResetOverride);
4251
+ const enableAllBtn = pop.querySelector(`[${enableAllAttr}]`);
4252
+ if (enableAllBtn !== null) {
4253
+ const enabledCount = totalCount - disabledInCatalogCount;
4254
+ enableAllBtn.textContent = `${t("settings.tools.enableAll")} (${String(enabledCount)}/${String(totalCount)})`;
4255
+ if (!writable || !hasAnyDisabled) enableAllBtn.setAttribute("disabled", "");
4256
+ else enableAllBtn.removeAttribute("disabled");
4257
+ }
4258
+ const treeContainer = pop.querySelector("[data-tools-popover-tree]");
4259
+ if (treeContainer !== null) treeContainer.replaceChildren(...renderTreeNodes());
2608
4260
  return pop;
2609
4261
  }
4262
+ function syncToolsPopover(props) {
4263
+ const { root, t, toolsCatalog, disabledSet, disabledInCatalog, customized = false, searchQuery, expandedToolNodes, writable, onSearchChange, onToggleNodeExpand, onCommitSet, onResetOverride, onRefreshCatalog, onClose } = props;
4264
+ return syncAnchoredPopoverShell({
4265
+ root,
4266
+ popoverAttr: TOOLS_POPOVER_ATTR,
4267
+ kind: "tools",
4268
+ t,
4269
+ titleKey: "sessionInfo.tools.popoverTitle",
4270
+ hintKey: "sessionInfo.tools.popoverHint",
4271
+ searchPlaceholderKey: "settings.tools.search",
4272
+ searchQuery,
4273
+ totalCount: toolsCatalog.length,
4274
+ disabledInCatalogCount: disabledInCatalog.length,
4275
+ hasAnyDisabled: disabledSet.size > 0,
4276
+ customized,
4277
+ writable,
4278
+ onSearchChange,
4279
+ onEnableAll: () => onCommitSet(new Set()),
4280
+ onResetOverride,
4281
+ onRefreshCatalog,
4282
+ onClose,
4283
+ renderTreeNodes: () => buildToolTreeDomNodes({
4284
+ t,
4285
+ toolsCatalog,
4286
+ disabledSet,
4287
+ searchQuery,
4288
+ expandedToolNodes,
4289
+ writable,
4290
+ onToggleNodeExpand,
4291
+ onCommitSet
4292
+ })
4293
+ });
4294
+ }
4295
+ function syncSkillsPopover(props) {
4296
+ const { root, t, skillsCatalog, disabledSet, disabledInCatalog, customized = false, searchQuery, expandedSkillScopes, writable, onSearchChange, onToggleScopeExpand, onCommitSet, onResetOverride, onRefreshCatalog, onPreviewSkill, onClose } = props;
4297
+ return syncAnchoredPopoverShell({
4298
+ root,
4299
+ popoverAttr: SKILLS_POPOVER_ATTR,
4300
+ kind: "skills",
4301
+ t,
4302
+ titleKey: "sessionInfo.skills.popoverTitle",
4303
+ hintKey: "sessionInfo.skills.popoverHint",
4304
+ searchPlaceholderKey: "settings.skills.search",
4305
+ searchQuery,
4306
+ totalCount: skillsCatalog.length,
4307
+ disabledInCatalogCount: disabledInCatalog.length,
4308
+ hasAnyDisabled: disabledSet.size > 0,
4309
+ customized,
4310
+ writable,
4311
+ onSearchChange,
4312
+ onEnableAll: () => onCommitSet(new Set()),
4313
+ onResetOverride,
4314
+ onRefreshCatalog,
4315
+ onClose,
4316
+ renderTreeNodes: () => buildSkillGroupDomNodes({
4317
+ t,
4318
+ skillsCatalog,
4319
+ disabledSet,
4320
+ searchQuery,
4321
+ expandedSkillScopes,
4322
+ includeProject: true,
4323
+ writable,
4324
+ onToggleScopeExpand,
4325
+ onCommitSet,
4326
+ onPreviewSkill
4327
+ })
4328
+ });
4329
+ }
2610
4330
  //#endregion
2611
4331
  //#region src/client/session-info/panel.ts
2612
4332
  const SESSION_INFO_ATTR = "data-desktop-enhance-session-info";
@@ -2666,13 +4386,105 @@ window.__ModuleLoader__.load({
2666
4386
  toolsEnabled: state.toolsEnabled,
2667
4387
  toolsWritable: state.toolsWritable,
2668
4388
  toolsCount: state.toolsCount,
2669
- disabledCanonical: state.disabledCanonical,
2670
- popoverOpen: state.popoverOpen,
2671
- searchQuery: state.searchQuery,
2672
- expandedTools: [...state.expandedToolNodes].sort()
4389
+ toolsDisabledCanonical: state.toolsDisabledCanonical,
4390
+ toolsCustomized: state.toolsCustomized,
4391
+ toolsSearchQuery: state.toolsSearchQuery,
4392
+ expandedTools: [...state.expandedToolNodes].sort(),
4393
+ skillsEnabled: state.skillsEnabled,
4394
+ skillsWritable: state.skillsWritable,
4395
+ skillsCount: state.skillsCount,
4396
+ skillsDisabledCanonical: state.skillsDisabledCanonical,
4397
+ skillsCustomized: state.skillsCustomized,
4398
+ skillsSearchQuery: state.skillsSearchQuery,
4399
+ expandedSkills: [...state.expandedSkillScopes].sort(),
4400
+ activePopover: state.activePopover
2673
4401
  });
2674
4402
  }
2675
- function installSessionInfo(ctx, isOn, getSessions, t, fetchImpl = globalThis.fetch, toolsBridge) {
4403
+ function createPolicyChannel(bridge) {
4404
+ let optimisticRaw = null;
4405
+ let lastObservedRaw = "";
4406
+ let reconcileTimer = null;
4407
+ const hasSessionScope = () => bridge !== void 0 && typeof bridge.getSessionOverridesRaw === "function" && typeof bridge.setSessionOverridesRaw === "function";
4408
+ const readHostRaw = () => {
4409
+ if (bridge === void 0) return "";
4410
+ if (hasSessionScope()) return formatSessionOverrides(parseSessionOverrides(bridge.getSessionOverridesRaw?.() ?? ""));
4411
+ return formatDisabledTools(parseDisabledTools(bridge.getDisabledRaw()));
4412
+ };
4413
+ const writeHostRaw = (nextCanonical) => {
4414
+ if (bridge === void 0) return;
4415
+ if (hasSessionScope()) bridge.setSessionOverridesRaw?.(nextCanonical);
4416
+ else bridge.setDisabledRaw(nextCanonical);
4417
+ };
4418
+ const clearTimer = () => {
4419
+ if (reconcileTimer !== null) {
4420
+ globalThis.clearTimeout(reconcileTimer);
4421
+ reconcileTimer = null;
4422
+ }
4423
+ };
4424
+ const isOn = () => bridge !== void 0 && bridge.isOn();
4425
+ const isWritable = () => {
4426
+ if (bridge === void 0) return false;
4427
+ return bridge.canWrite ? bridge.canWrite() : true;
4428
+ };
4429
+ const currentRaw = () => {
4430
+ const hostRaw = readHostRaw();
4431
+ if (hostRaw !== lastObservedRaw) {
4432
+ lastObservedRaw = hostRaw;
4433
+ if (optimisticRaw === hostRaw) {
4434
+ optimisticRaw = null;
4435
+ clearTimer();
4436
+ }
4437
+ }
4438
+ return optimisticRaw ?? hostRaw;
4439
+ };
4440
+ const effectiveSet = (sessionId) => {
4441
+ const raw = currentRaw();
4442
+ if (hasSessionScope()) return resolveEffectiveDisabled(bridge?.getDisabledRaw() ?? "", raw, sessionId);
4443
+ return parseDisabledTools(raw);
4444
+ };
4445
+ const isCustomized = (sessionId) => {
4446
+ if (!hasSessionScope()) return false;
4447
+ return hasSessionOverride(bridge?.getDisabledRaw() ?? "", currentRaw(), sessionId);
4448
+ };
4449
+ const scheduleReconcile = (onMismatch) => {
4450
+ clearTimer();
4451
+ reconcileTimer = globalThis.setTimeout(() => {
4452
+ reconcileTimer = null;
4453
+ const currentHost = readHostRaw();
4454
+ lastObservedRaw = currentHost;
4455
+ if (optimisticRaw !== null && optimisticRaw !== currentHost) {
4456
+ optimisticRaw = null;
4457
+ onMismatch();
4458
+ } else optimisticRaw = null;
4459
+ }, RECONCILE_MS);
4460
+ };
4461
+ const commitSet = (nextSet, sessionId, onUpdated, onReconcileRollback) => {
4462
+ if (!isWritable()) return;
4463
+ const nextCanonical = hasSessionScope() ? updateSessionOverride(bridge?.getDisabledRaw() ?? "", currentRaw(), sessionId, nextSet) : formatDisabledTools(nextSet);
4464
+ optimisticRaw = nextCanonical;
4465
+ writeHostRaw(nextCanonical);
4466
+ scheduleReconcile(onReconcileRollback);
4467
+ onUpdated();
4468
+ };
4469
+ const resetSession = (sessionId, onUpdated, onReconcileRollback) => {
4470
+ if (!isWritable() || !hasSessionScope()) return;
4471
+ const nextCanonical = clearSessionOverride(currentRaw(), sessionId);
4472
+ optimisticRaw = nextCanonical;
4473
+ writeHostRaw(nextCanonical);
4474
+ scheduleReconcile(onReconcileRollback);
4475
+ onUpdated();
4476
+ };
4477
+ return {
4478
+ isOn,
4479
+ isWritable,
4480
+ effectiveSet,
4481
+ isCustomized,
4482
+ commitSet,
4483
+ resetSession,
4484
+ clearTimer
4485
+ };
4486
+ }
4487
+ function installSessionInfo(ctx, isOn, getSessions, t, fetchImpl = globalThis.fetch, toolsBridge, skillsBridge) {
2676
4488
  let activeSessionId = null;
2677
4489
  let retained = null;
2678
4490
  let unsubscribeSource = null;
@@ -2681,64 +4493,35 @@ window.__ModuleLoader__.load({
2681
4493
  let minimized = false;
2682
4494
  const collapsedSections = new Set();
2683
4495
  let mountedPanel = null;
2684
- let mountedPopover = null;
4496
+ let mountedToolsPopover = null;
4497
+ let mountedSkillsPopover = null;
2685
4498
  let lastSignature = "";
4499
+ let activePopover = null;
4500
+ const toolsChannel = createPolicyChannel(toolsBridge);
2686
4501
  let toolsCatalog = [];
2687
4502
  let toolsCatalogLoaded = false;
2688
4503
  let toolsCatalogAttempted = false;
2689
4504
  let toolsLoading = false;
2690
- let popoverOpen = false;
2691
- let searchQuery = "";
2692
- const expandedToolNodes = new Set();
2693
- let defaultExpandedSeeded = false;
2694
- let optimisticDisabledRaw = null;
2695
- let lastObservedBridgeRaw = "";
2696
- let reconcileTimer = null;
2697
- function clearReconcileTimer() {
2698
- if (reconcileTimer !== null) {
2699
- globalThis.clearTimeout(reconcileTimer);
2700
- reconcileTimer = null;
2701
- }
2702
- }
2703
- function isToolsWritable() {
2704
- if (toolsBridge === void 0) return false;
2705
- return toolsBridge.canWrite ? toolsBridge.canWrite() : true;
2706
- }
2707
- function effectiveDisabledSet() {
2708
- const bridgeRaw = formatDisabledTools(parseDisabledTools(toolsBridge?.getDisabledRaw() ?? ""));
2709
- if (bridgeRaw !== lastObservedBridgeRaw) {
2710
- lastObservedBridgeRaw = bridgeRaw;
2711
- if (optimisticDisabledRaw === bridgeRaw) {
2712
- optimisticDisabledRaw = null;
2713
- clearReconcileTimer();
2714
- }
4505
+ let toolsSearchQuery = "";
4506
+ const expandedToolNodes = new Set(TOOL_SCOPE_ORDER.map((s) => `scope:${s}`));
4507
+ let defaultExpandedToolsSeeded = false;
4508
+ const skillsChannel = createPolicyChannel(skillsBridge);
4509
+ let skillsCatalog = [];
4510
+ let skillsCatalogSessionId = null;
4511
+ let skillsCatalogAttemptedFor = null;
4512
+ let skillsLoading = false;
4513
+ let skillsSearchQuery = "";
4514
+ const expandedSkillScopes = new Set(SKILL_SCOPE_ORDER);
4515
+ function removeToolsPopover() {
4516
+ if (mountedToolsPopover !== null) {
4517
+ mountedToolsPopover.remove();
4518
+ mountedToolsPopover = null;
2715
4519
  }
2716
- return parseDisabledTools(optimisticDisabledRaw ?? bridgeRaw);
2717
- }
2718
- function commitDisabledSet(nextSet, root, sessionId) {
2719
- if (!isToolsWritable()) return;
2720
- const canonical = formatDisabledTools(nextSet);
2721
- optimisticDisabledRaw = canonical;
2722
- toolsBridge?.setDisabledRaw(canonical);
2723
- clearReconcileTimer();
2724
- reconcileTimer = globalThis.setTimeout(() => {
2725
- reconcileTimer = null;
2726
- const currentHostRaw = formatDisabledTools(parseDisabledTools(toolsBridge?.getDisabledRaw() ?? ""));
2727
- lastObservedBridgeRaw = currentHostRaw;
2728
- if (optimisticDisabledRaw !== null && optimisticDisabledRaw !== currentHostRaw) {
2729
- optimisticDisabledRaw = null;
2730
- lastSignature = "";
2731
- const current = findActiveChatConversation();
2732
- paint(current?.sessionId === sessionId ? current.root : root, sessionId);
2733
- } else optimisticDisabledRaw = null;
2734
- }, RECONCILE_MS);
2735
- lastSignature = "";
2736
- paint(root, sessionId);
2737
4520
  }
2738
- function removePopover() {
2739
- if (mountedPopover !== null) {
2740
- mountedPopover.remove();
2741
- mountedPopover = null;
4521
+ function removeSkillsPopover() {
4522
+ if (mountedSkillsPopover !== null) {
4523
+ mountedSkillsPopover.remove();
4524
+ mountedSkillsPopover = null;
2742
4525
  }
2743
4526
  }
2744
4527
  function removePanel() {
@@ -2746,12 +4529,14 @@ window.__ModuleLoader__.load({
2746
4529
  mountedPanel.remove();
2747
4530
  mountedPanel = null;
2748
4531
  }
2749
- removePopover();
4532
+ removeToolsPopover();
4533
+ removeSkillsPopover();
2750
4534
  lastSignature = "";
2751
4535
  }
2752
4536
  function detach() {
2753
4537
  fetchToken += 1;
2754
- clearReconcileTimer();
4538
+ toolsChannel.clearTimer();
4539
+ skillsChannel.clearTimer();
2755
4540
  if (unsubscribeSource !== null) {
2756
4541
  unsubscribeSource();
2757
4542
  unsubscribeSource = null;
@@ -2762,11 +4547,11 @@ window.__ModuleLoader__.load({
2762
4547
  }
2763
4548
  activeSessionId = null;
2764
4549
  hostProjection = null;
2765
- popoverOpen = false;
4550
+ activePopover = null;
2766
4551
  removePanel();
2767
4552
  }
2768
4553
  function ensureToolsCatalog(root, sessionId, force = false) {
2769
- if (toolsBridge === void 0 || !toolsBridge.isOn()) return;
4554
+ if (!toolsChannel.isOn()) return;
2770
4555
  if (toolsLoading && !force) return;
2771
4556
  if ((toolsCatalogLoaded || toolsCatalogAttempted) && !force) return;
2772
4557
  if (typeof fetchImpl !== "function") return;
@@ -2779,10 +4564,13 @@ window.__ModuleLoader__.load({
2779
4564
  if (parsed.available) {
2780
4565
  toolsCatalog = parsed.tools;
2781
4566
  toolsCatalogLoaded = true;
2782
- if (!defaultExpandedSeeded) {
2783
- defaultExpandedSeeded = true;
2784
- const initialTree = buildToolPrefixTree(toolsCatalog, effectiveDisabledSet(), "");
2785
- for (const node of initialTree) if (node.kind === "node") expandedToolNodes.add(node.prefix);
4567
+ if (!defaultExpandedToolsSeeded) {
4568
+ defaultExpandedToolsSeeded = true;
4569
+ const initialGroups = buildToolScopeGroups(toolsCatalog, toolsChannel.effectiveSet(sessionId), "");
4570
+ for (const group of initialGroups) {
4571
+ expandedToolNodes.add(`scope:${group.scope}`);
4572
+ for (const node of group.children) if (node.kind === "node") expandedToolNodes.add(node.prefix);
4573
+ }
2786
4574
  }
2787
4575
  lastSignature = "";
2788
4576
  const current = findActiveChatConversation();
@@ -2792,18 +4580,56 @@ window.__ModuleLoader__.load({
2792
4580
  toolsLoading = false;
2793
4581
  });
2794
4582
  }
4583
+ function ensureSkillsCatalog(root, sessionId, force = false) {
4584
+ if (!skillsChannel.isOn()) return;
4585
+ if (skillsLoading && !force) return;
4586
+ if ((skillsCatalogSessionId === sessionId || skillsCatalogAttemptedFor === sessionId) && !force) return;
4587
+ if (typeof fetchImpl !== "function") return;
4588
+ const url = `${SKILLS_URL}?sessionId=${globalThis.encodeURIComponent(sessionId)}`;
4589
+ if (force) catalogCache.invalidate?.(url);
4590
+ skillsCatalogAttemptedFor = sessionId;
4591
+ skillsLoading = true;
4592
+ catalogCache.get(url, fetchImpl).then((body) => {
4593
+ skillsLoading = false;
4594
+ const parsed = parseSkillCatalog(body, { includeProject: true });
4595
+ if (parsed.available) {
4596
+ skillsCatalog = parsed.skills;
4597
+ skillsCatalogSessionId = sessionId;
4598
+ lastSignature = "";
4599
+ const current = findActiveChatConversation();
4600
+ paint(current?.sessionId === sessionId ? current.root : root, sessionId);
4601
+ }
4602
+ }).catch(() => {
4603
+ skillsLoading = false;
4604
+ });
4605
+ }
2795
4606
  function currentClientProjection() {
2796
4607
  return projectSkills(eventsOf(retained?.binding.eventSource.getSnapshot().entries ?? []));
2797
4608
  }
4609
+ function repaintCurrent(fallbackRoot, sessionId) {
4610
+ lastSignature = "";
4611
+ const current = findActiveChatConversation();
4612
+ paint(current?.sessionId === sessionId ? current.root : fallbackRoot, sessionId);
4613
+ }
2798
4614
  function paint(root, sessionId) {
2799
- const toolsEnabled = toolsBridge !== void 0 && toolsBridge.isOn();
2800
- const toolsWritable = toolsEnabled && isToolsWritable();
4615
+ const toolsEnabled = toolsChannel.isOn();
4616
+ const toolsWritable = toolsEnabled && toolsChannel.isWritable();
2801
4617
  if (toolsEnabled && !toolsCatalogLoaded && !toolsCatalogAttempted && !toolsLoading) ensureToolsCatalog(root, sessionId);
2802
- if (!toolsEnabled && popoverOpen) popoverOpen = false;
2803
- const disabledSet = toolsEnabled ? effectiveDisabledSet() : new Set();
2804
- const disabledCanonical = toolsEnabled ? formatDisabledTools(disabledSet) : "";
2805
- const disabledInCatalog = toolsEnabled ? toolsCatalog.filter((tool) => disabledSet.has(tool.name)) : [];
2806
- const enabledToolsCount = toolsEnabled ? toolsCatalog.length - disabledInCatalog.length : 0;
4618
+ if (!toolsEnabled && activePopover === "tools") activePopover = null;
4619
+ const skillsEnabled = skillsChannel.isOn();
4620
+ const skillsWritable = skillsEnabled && skillsChannel.isWritable();
4621
+ if (skillsEnabled && skillsCatalogSessionId !== sessionId && skillsCatalogAttemptedFor !== sessionId && !skillsLoading) ensureSkillsCatalog(root, sessionId);
4622
+ if (!skillsEnabled && activePopover === "skills") activePopover = null;
4623
+ const toolsDisabledSet = toolsEnabled ? toolsChannel.effectiveSet(sessionId) : new Set();
4624
+ const toolsDisabledCanonical = toolsEnabled ? formatDisabledTools(toolsDisabledSet) : "";
4625
+ const toolsCustomized = toolsEnabled && toolsChannel.isCustomized(sessionId);
4626
+ const disabledToolsInCatalog = toolsEnabled ? toolsCatalog.filter((tool) => toolsDisabledSet.has(tool.name)) : [];
4627
+ const enabledToolsCount = toolsEnabled ? toolsCatalog.length - disabledToolsInCatalog.length : 0;
4628
+ const skillsDisabledSet = skillsEnabled ? skillsChannel.effectiveSet(sessionId) : new Set();
4629
+ const skillsDisabledCanonical = skillsEnabled ? formatDisabledTools(skillsDisabledSet) : "";
4630
+ const skillsCustomized = skillsEnabled && skillsChannel.isCustomized(sessionId);
4631
+ const disabledSkillsInCatalog = skillsEnabled ? skillsCatalog.filter((skill) => skillsDisabledSet.has(skill.name)) : [];
4632
+ const enabledSkillsCount = skillsEnabled ? skillsCatalog.length - disabledSkillsInCatalog.length : 0;
2807
4633
  const clientProjection = currentClientProjection();
2808
4634
  const sections = buildSessionInfoSections(mergeSkillProjections(hostProjection, clientProjection), t);
2809
4635
  const totalItems = sections.reduce((sum, sec) => sum + sec.items.length, 0);
@@ -2814,10 +4640,18 @@ window.__ModuleLoader__.load({
2814
4640
  toolsEnabled,
2815
4641
  toolsWritable,
2816
4642
  toolsCount: toolsCatalog.length,
2817
- disabledCanonical,
2818
- popoverOpen,
2819
- searchQuery,
2820
- expandedToolNodes
4643
+ toolsDisabledCanonical,
4644
+ toolsCustomized,
4645
+ toolsSearchQuery,
4646
+ expandedToolNodes,
4647
+ skillsEnabled,
4648
+ skillsWritable,
4649
+ skillsCount: skillsCatalog.length,
4650
+ skillsDisabledCanonical,
4651
+ skillsCustomized,
4652
+ skillsSearchQuery,
4653
+ expandedSkillScopes,
4654
+ activePopover
2821
4655
  });
2822
4656
  let panel = root.querySelector(`[${SESSION_INFO_ATTR}]`);
2823
4657
  if (panel === null) {
@@ -2839,11 +4673,11 @@ window.__ModuleLoader__.load({
2839
4673
  const titleWrap = globalThis.document.createElement("span");
2840
4674
  titleWrap.setAttribute("data-session-info-title", "");
2841
4675
  const dot = globalThis.document.createElement("span");
2842
- dot.setAttribute("data-session-info-dot", totalItems === 0 && enabledToolsCount === 0 ? "idle" : "active");
4676
+ dot.setAttribute("data-session-info-dot", totalItems === 0 && enabledToolsCount === 0 && enabledSkillsCount === 0 ? "idle" : "active");
2843
4677
  titleWrap.appendChild(dot);
2844
4678
  const titleText = globalThis.document.createElement("span");
2845
4679
  if (minimized) {
2846
- const parts = sections.map((sec) => `${sec.shortLabel} ${String(sec.items.length)}`);
4680
+ const parts = sections.map((sec) => sec.id === "skills" && skillsEnabled && skillsCatalog.length > 0 ? `${sec.shortLabel} ${String(sec.items.length)} (${String(enabledSkillsCount)}/${String(skillsCatalog.length)})` : `${sec.shortLabel} ${String(sec.items.length)}`);
2847
4681
  if (toolsEnabled && toolsCatalog.length > 0) parts.push(`${t("sessionInfo.tools.short")} ${String(enabledToolsCount)}/${String(toolsCatalog.length)}`);
2848
4682
  titleText.textContent = `${t("sessionInfo.title")} · ${parts.join(" · ")}`;
2849
4683
  } else titleText.textContent = t("sessionInfo.title");
@@ -2855,7 +4689,7 @@ window.__ModuleLoader__.load({
2855
4689
  header.appendChild(toggleIcon);
2856
4690
  header.addEventListener("click", () => {
2857
4691
  minimized = !minimized;
2858
- if (minimized) popoverOpen = false;
4692
+ if (minimized) activePopover = null;
2859
4693
  paint(root, sessionId);
2860
4694
  });
2861
4695
  const children = [header];
@@ -2925,55 +4759,131 @@ window.__ModuleLoader__.load({
2925
4759
  }
2926
4760
  secEl.appendChild(body);
2927
4761
  }
4762
+ if (sec.id === "skills" && skillsEnabled) secEl.appendChild(buildSkillsSummaryControls({
4763
+ t,
4764
+ enabledSkillsCount,
4765
+ totalSkillsCount: skillsCatalog.length,
4766
+ disabledInCatalog: disabledSkillsInCatalog,
4767
+ customized: skillsCustomized,
4768
+ popoverOpen: activePopover === "skills",
4769
+ onTogglePopover: () => {
4770
+ activePopover = activePopover === "skills" ? null : "skills";
4771
+ if (activePopover === "skills" && skillsCatalogSessionId !== sessionId) ensureSkillsCatalog(root, sessionId, true);
4772
+ paint(root, sessionId);
4773
+ }
4774
+ }));
2928
4775
  children.push(secEl);
2929
4776
  }
2930
4777
  if (toolsEnabled) children.push(buildToolsSummarySection({
2931
4778
  t,
2932
4779
  enabledToolsCount,
2933
4780
  totalToolsCount: toolsCatalog.length,
2934
- disabledInCatalog,
2935
- popoverOpen,
4781
+ disabledInCatalog: disabledToolsInCatalog,
4782
+ customized: toolsCustomized,
4783
+ popoverOpen: activePopover === "tools",
2936
4784
  onTogglePopover: () => {
2937
- popoverOpen = !popoverOpen;
2938
- if (popoverOpen && !toolsCatalogLoaded) ensureToolsCatalog(root, sessionId, true);
4785
+ activePopover = activePopover === "tools" ? null : "tools";
4786
+ if (activePopover === "tools" && !toolsCatalogLoaded) ensureToolsCatalog(root, sessionId, true);
2939
4787
  paint(root, sessionId);
2940
4788
  }
2941
4789
  }));
2942
4790
  }
2943
4791
  panel.replaceChildren(...children);
2944
- if (popoverOpen && !minimized) mountedPopover = syncToolsPopover({
2945
- root,
2946
- t,
2947
- toolsCatalog,
2948
- disabledSet,
2949
- disabledInCatalog,
2950
- searchQuery,
2951
- expandedToolNodes,
2952
- writable: toolsWritable,
2953
- onSearchChange: (nextQuery) => {
2954
- searchQuery = nextQuery;
2955
- lastSignature = "";
2956
- paint(root, sessionId);
2957
- },
2958
- onToggleNodeExpand: (prefix) => {
2959
- if (expandedToolNodes.has(prefix)) expandedToolNodes.delete(prefix);
2960
- else expandedToolNodes.add(prefix);
2961
- lastSignature = "";
2962
- paint(root, sessionId);
2963
- },
2964
- onCommitSet: (nextSet) => {
2965
- commitDisabledSet(nextSet, root, sessionId);
2966
- },
2967
- onRefreshCatalog: () => {
2968
- ensureToolsCatalog(root, sessionId, true);
2969
- },
2970
- onClose: () => {
2971
- popoverOpen = false;
2972
- lastSignature = "";
2973
- paint(root, sessionId);
2974
- }
2975
- });
2976
- else removePopover();
4792
+ if (activePopover === "tools" && !minimized) {
4793
+ removeSkillsPopover();
4794
+ mountedToolsPopover = syncToolsPopover({
4795
+ root,
4796
+ t,
4797
+ toolsCatalog,
4798
+ disabledSet: toolsDisabledSet,
4799
+ disabledInCatalog: disabledToolsInCatalog,
4800
+ customized: toolsCustomized,
4801
+ searchQuery: toolsSearchQuery,
4802
+ expandedToolNodes,
4803
+ writable: toolsWritable,
4804
+ onSearchChange: (nextQuery) => {
4805
+ toolsSearchQuery = nextQuery;
4806
+ lastSignature = "";
4807
+ paint(root, sessionId);
4808
+ },
4809
+ onToggleNodeExpand: (prefix) => {
4810
+ if (expandedToolNodes.has(prefix)) expandedToolNodes.delete(prefix);
4811
+ else expandedToolNodes.add(prefix);
4812
+ lastSignature = "";
4813
+ paint(root, sessionId);
4814
+ },
4815
+ onCommitSet: (nextSet) => {
4816
+ toolsChannel.commitSet(nextSet, sessionId, () => {
4817
+ lastSignature = "";
4818
+ paint(root, sessionId);
4819
+ }, () => repaintCurrent(root, sessionId));
4820
+ },
4821
+ onResetOverride: () => {
4822
+ toolsChannel.resetSession(sessionId, () => {
4823
+ lastSignature = "";
4824
+ paint(root, sessionId);
4825
+ }, () => repaintCurrent(root, sessionId));
4826
+ },
4827
+ onRefreshCatalog: () => {
4828
+ ensureToolsCatalog(root, sessionId, true);
4829
+ },
4830
+ onClose: () => {
4831
+ activePopover = null;
4832
+ lastSignature = "";
4833
+ paint(root, sessionId);
4834
+ }
4835
+ });
4836
+ } else if (activePopover === "skills" && !minimized) {
4837
+ removeToolsPopover();
4838
+ mountedSkillsPopover = syncSkillsPopover({
4839
+ root,
4840
+ t,
4841
+ skillsCatalog,
4842
+ disabledSet: skillsDisabledSet,
4843
+ disabledInCatalog: disabledSkillsInCatalog,
4844
+ customized: skillsCustomized,
4845
+ searchQuery: skillsSearchQuery,
4846
+ expandedSkillScopes,
4847
+ writable: skillsWritable,
4848
+ onSearchChange: (nextQuery) => {
4849
+ skillsSearchQuery = nextQuery;
4850
+ lastSignature = "";
4851
+ paint(root, sessionId);
4852
+ },
4853
+ onToggleScopeExpand: (scope) => {
4854
+ if (expandedSkillScopes.has(scope)) expandedSkillScopes.delete(scope);
4855
+ else expandedSkillScopes.add(scope);
4856
+ lastSignature = "";
4857
+ paint(root, sessionId);
4858
+ },
4859
+ onCommitSet: (nextSet) => {
4860
+ skillsChannel.commitSet(nextSet, sessionId, () => {
4861
+ lastSignature = "";
4862
+ paint(root, sessionId);
4863
+ }, () => repaintCurrent(root, sessionId));
4864
+ },
4865
+ onResetOverride: () => {
4866
+ skillsChannel.resetSession(sessionId, () => {
4867
+ lastSignature = "";
4868
+ paint(root, sessionId);
4869
+ }, () => repaintCurrent(root, sessionId));
4870
+ },
4871
+ onRefreshCatalog: () => {
4872
+ ensureSkillsCatalog(root, sessionId, true);
4873
+ },
4874
+ onPreviewSkill: (skillName) => {
4875
+ openSkillInHost(ctx, sessionId, skillName);
4876
+ },
4877
+ onClose: () => {
4878
+ activePopover = null;
4879
+ lastSignature = "";
4880
+ paint(root, sessionId);
4881
+ }
4882
+ });
4883
+ } else {
4884
+ removeToolsPopover();
4885
+ removeSkillsPopover();
4886
+ }
2977
4887
  }
2978
4888
  function triggerHostRefresh(sessionId, root) {
2979
4889
  const token = ++fetchToken;
@@ -3049,7 +4959,7 @@ window.__ModuleLoader__.load({
3049
4959
  }
3050
4960
  //#endregion
3051
4961
  //#region \0dsh-desktop-enhance-css:/Users/lijiechengbj/projects/AI-agents/dsh-desktop-enhance/src/client/styles/enhance.css.mjs
3052
- 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-session-info-section=\"tools\"],\n:root[data-desktop-enhance-off-tools-manager] [data-desktop-enhance-tools-popover] {\n display: none !important;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-row] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n gap: 8px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-left] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-width: 0;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-title] {\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n color: var(--dsw-alias-label-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-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:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-count][data-has-disabled=\"true\"] {\n background: var(--dsw-alias-state-warn-tertiary);\n color: var(--dsw-alias-state-warn-label);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-manage] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);\n border-radius: var(--dsw-radius-xs);\n padding: 2px 8px;\n font: var(--dsw-font-xxs-strong-12, 600 11px/16px sans-serif);\n cursor: pointer;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-manage]:hover {\n background: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-bg-layer-1);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-disabled] {\n padding: 0 10px 7px;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-muted] {\n font: var(--dsw-font-xxs-12);\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-session-info-tools-tag] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10.5px;\n padding: 1px 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 text-decoration: line-through;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-desktop-enhance-tools-popover] {\n position: absolute;\n top: 12px;\n right: 292px;\n width: 520px;\n max-width: calc(100% - 308px);\n z-index: 20;\n background: var(--dsw-alias-bg-layer-2);\n border: 0.5px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n box-shadow: var(--dsw-alias-shadow-l2, 0 8px 24px color-mix(in srgb, var(--dsw-alias-label-primary) 12%, transparent));\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font: var(--dsw-font-xxs-12);\n color: var(--dsw-alias-label-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-header] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-title-wrap] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-title] {\n font: var(--dsw-font-xs-strong-13, 600 13px/18px sans-serif);\n color: var(--dsw-alias-label-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-close] {\n background: transparent;\n border: none;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: var(--dsw-font-xs-13);\n padding: 4px 6px;\n border-radius: var(--dsw-radius-xs);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-close]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-body] {\n display: flex;\n flex-direction: column;\n padding: 10px 12px;\n gap: 8px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-toolbar] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-search] {\n flex: 1 1 auto;\n min-width: 0;\n background: var(--dsw-alias-bg-layer-1);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-sm);\n padding: 5px 9px;\n font: var(--dsw-font-xxs-12);\n color: var(--dsw-alias-label-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-actions] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-popover-tree] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 380px;\n overflow-y: auto;\n padding-right: 2px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-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]) [data-tools-node-header]:hover,\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-leaf]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-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: 12px;\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]) [data-tools-leaf] {\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]) [data-tools-leaf-info] {\n flex: 1 1 auto;\n min-width: 0;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-leaf-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 word-break: break-all;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-leaf][data-disabled=\"true\"] [data-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]) [data-tools-leaf-desc] {\n font-size: 11px;\n line-height: 16px;\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]) [data-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]) [data-tools-pill] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10.5px;\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]) [data-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]) [data-tools-btn] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-xs);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: var(--dsw-font-xxs-12);\n font-size: 11px;\n padding: 2px 8px;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-btn]:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-state-business-primary);\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-btn]:disabled {\n cursor: default;\n opacity: .5;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-tools-empty] {\n padding: 8px;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n\n\n";
4962
+ 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-session-info-section=\"tools\"],\n:root[data-desktop-enhance-off-tools-manager] [data-desktop-enhance-tools-popover],\n:root[data-desktop-enhance-off-tools-manager] [data-desktop-enhance-defaults=\"tools\"] {\n display: none !important;\n}\n:root[data-desktop-enhance-off-skills-manager] [data-session-info-skills-summary],\n:root[data-desktop-enhance-off-skills-manager] [data-desktop-enhance-skills-popover],\n:root[data-desktop-enhance-off-skills-manager] [data-desktop-enhance-defaults=\"skills\"] {\n display: none !important;\n}\n[data-desktop-enhance-session-info] [data-session-info-skills-summary] {\n border-top: 0.5px dashed var(--dsw-alias-border-l2);\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-row] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 6px 10px;\n gap: 8px;\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-left] {\n display: inline-flex;\n align-items: center;\n gap: 5px;\n min-width: 0;\n flex-wrap: wrap;\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-title] {\n font: var(--dsw-font-xxs-strong-12, 600 12px/18px sans-serif);\n color: var(--dsw-alias-label-primary);\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-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-session-info-tools-count][data-has-disabled=\"true\"] {\n background: var(--dsw-alias-state-warn-tertiary);\n color: var(--dsw-alias-state-warn-label);\n}\n[data-desktop-enhance-session-info] [data-session-info-override-badge] {\n font-size: 10px;\n padding: 0 5px;\n line-height: 15px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-state-business-primary);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 25%, transparent);\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-manage] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 30%, transparent);\n border-radius: var(--dsw-radius-xs);\n padding: 2px 8px;\n font: var(--dsw-font-xxs-strong-12, 600 11px/16px sans-serif);\n cursor: pointer;\n flex: none;\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-manage]:hover {\n background: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-bg-layer-1);\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-disabled],\n[data-desktop-enhance-session-info] [data-session-info-skills-disabled] {\n padding: 0 10px 7px;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-muted],\n[data-desktop-enhance-tools-popover] [data-session-info-tools-muted],\n[data-desktop-enhance-skills-popover] [data-session-info-tools-muted] {\n font: var(--dsw-font-xxs-12);\n font-size: 11px;\n color: var(--dsw-alias-label-tertiary);\n}\n[data-desktop-enhance-session-info] [data-session-info-tools-tag],\n[data-desktop-enhance-session-info] [data-session-info-skills-tag] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10.5px;\n padding: 1px 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 text-decoration: line-through;\n}\n:root:not([data-desktop-enhance-off-tools-manager]) [data-desktop-enhance-tools-popover],\n:root:not([data-desktop-enhance-off-skills-manager]) [data-desktop-enhance-skills-popover] {\n position: absolute;\n top: 12px;\n right: 292px;\n width: 520px;\n max-width: calc(100% - 308px);\n z-index: 20;\n background: var(--dsw-alias-bg-layer-2);\n border: 0.5px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-md);\n box-shadow: var(--dsw-alias-shadow-l2, 0 8px 24px color-mix(in srgb, var(--dsw-alias-label-primary) 12%, transparent));\n display: flex;\n flex-direction: column;\n overflow: hidden;\n font: var(--dsw-font-xxs-12);\n color: var(--dsw-alias-label-primary);\n}\n[data-tools-popover-header] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 10px 14px;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n background: var(--dsw-alias-bg-layer-3);\n}\n[data-tools-popover-title-wrap] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n}\n[data-tools-popover-title] {\n font: var(--dsw-font-xs-strong-13, 600 13px/18px sans-serif);\n color: var(--dsw-alias-label-primary);\n}\n[data-tools-popover-close] {\n background: transparent;\n border: none;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: var(--dsw-font-xs-13);\n padding: 4px 6px;\n border-radius: var(--dsw-radius-xs);\n}\n[data-tools-popover-close]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-primary);\n}\n[data-tools-popover-body] {\n display: flex;\n flex-direction: column;\n padding: 10px 12px;\n gap: 8px;\n}\n[data-popover-override-banner] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n padding: 6px 10px;\n border-radius: var(--dsw-radius-sm);\n background: color-mix(in srgb, var(--dsw-alias-state-business-tertiary) 45%, transparent);\n border: 1px solid color-mix(in srgb, var(--dsw-alias-state-business-primary) 25%, transparent);\n font-size: 11.5px;\n color: var(--dsw-alias-label-primary);\n}\n[data-tools-popover-toolbar] {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n[data-tools-popover-search] {\n flex: 1 1 auto;\n min-width: 0;\n background: var(--dsw-alias-bg-layer-1);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-sm);\n padding: 5px 9px;\n font: var(--dsw-font-xxs-12);\n color: var(--dsw-alias-label-primary);\n}\n[data-tools-popover-actions] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n[data-tools-popover-tree] {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 380px;\n overflow-y: auto;\n padding-right: 2px;\n}\n[data-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[data-tools-node-header]:hover,\n[data-tools-leaf]:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n[data-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: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n min-width: 0;\n}\n[data-tools-leaf] {\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[data-tools-leaf-info] {\n flex: 1 1 auto;\n min-width: 0;\n}\n[data-tools-leaf-header],\n[data-skills-leaf-header] {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n[data-tools-leaf-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 word-break: break-all;\n}\n[data-tools-leaf][data-disabled=\"true\"] [data-tools-leaf-name] {\n color: var(--dsw-alias-label-tertiary);\n text-decoration: line-through;\n}\n[data-tools-source-badge],\n[data-skills-source-badge],\n[data-skills-user-only] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10px;\n padding: 0 5px;\n line-height: 15px;\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[data-tools-source-badge=\"plugin\"],\n[data-skills-source-badge=\"project\"] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n}\n[data-skills-preview] {\n background: transparent;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-xs);\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font-size: 10px;\n padding: 0 5px;\n line-height: 15px;\n}\n[data-skills-preview]:hover {\n border-color: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-state-business-primary);\n}\n[data-tools-leaf-desc] {\n font-size: 11px;\n line-height: 16px;\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[data-tools-controls] {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n[data-tools-pill] {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10.5px;\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[data-tools-pill][data-disabled=\"true\"] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-tertiary);\n}\n[data-tools-btn] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: var(--dsw-radius-xs);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: var(--dsw-font-xxs-12);\n font-size: 11px;\n padding: 2px 8px;\n}\n[data-tools-btn]:hover:not(:disabled) {\n border-color: var(--dsw-alias-state-business-primary);\n color: var(--dsw-alias-state-business-primary);\n}\n[data-tools-btn]:disabled {\n cursor: default;\n opacity: .5;\n}\n[data-tools-empty] {\n padding: 8px;\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n}\n\n\n[data-desktop-enhance-settings] .de-defaults-box {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 12px;\n border-radius: var(--dsw-radius-sm);\n border: 1px solid var(--dsw-alias-border-l1);\n background: color-mix(in srgb, var(--dsw-alias-bg-layer-2) 60%, transparent);\n}\n[data-desktop-enhance-settings] .de-defaults-summary {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n}\n[data-desktop-enhance-settings] .de-defaults-title-row {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n[data-desktop-enhance-settings] .de-defaults-tags {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px;\n margin-top: 2px;\n}\n[data-desktop-enhance-settings] .de-defaults-status,\n[data-desktop-enhance-settings] .de-defaults-muted {\n color: var(--dsw-alias-label-tertiary);\n font: var(--dsw-font-xxs-12);\n font-size: 11px;\n}\n[data-desktop-enhance-settings] .de-defaults-tag {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 11px;\n padding: 1px 6px;\n border-radius: var(--dsw-radius-xs);\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-secondary);\n text-decoration: line-through;\n}\n[data-desktop-enhance-settings] .de-defaults-panel {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding-top: 8px;\n border-top: 1px solid var(--dsw-alias-border-l1);\n}\n[data-desktop-enhance-settings] .de-defaults-toolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n}\n[data-desktop-enhance-settings] .de-defaults-tree {\n display: flex;\n flex-direction: column;\n gap: 2px;\n max-height: 320px;\n overflow-y: auto;\n}\n[data-desktop-enhance-settings] .de-defaults-group-head,\n[data-desktop-enhance-settings] .de-defaults-leaf {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 10px;\n padding: 5px 8px;\n border-radius: var(--dsw-radius-xs);\n}\n[data-desktop-enhance-settings] .de-defaults-group-head {\n cursor: pointer;\n user-select: none;\n}\n[data-desktop-enhance-settings] .de-defaults-group-head:hover,\n[data-desktop-enhance-settings] .de-defaults-leaf:hover {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n}\n[data-desktop-enhance-settings] .de-defaults-group-title {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 12px;\n font-weight: 600;\n color: var(--dsw-alias-label-primary);\n}\n[data-desktop-enhance-settings] .de-defaults-leaf-info {\n flex: 1 1 auto;\n min-width: 0;\n}\n[data-desktop-enhance-settings] .de-defaults-leaf-head {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n}\n[data-desktop-enhance-settings] .de-defaults-leaf-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}\n[data-desktop-enhance-settings] .de-defaults-leaf[data-disabled=\"true\"] .de-defaults-leaf-name {\n color: var(--dsw-alias-label-tertiary);\n text-decoration: line-through;\n}\n[data-desktop-enhance-settings] .de-defaults-leaf-desc {\n font-size: 11px;\n line-height: 16px;\n color: var(--dsw-alias-label-tertiary);\n margin-top: 2px;\n}\n[data-desktop-enhance-settings] .de-defaults-source-badge {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10px;\n padding: 0 5px;\n line-height: 15px;\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[data-desktop-enhance-settings] .de-defaults-source-badge[data-tool-scope=\"plugin\"] {\n background: var(--dsw-alias-state-business-tertiary);\n color: var(--dsw-alias-label-primary-bluish);\n}\n[data-desktop-enhance-settings] .de-defaults-controls {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: none;\n}\n[data-desktop-enhance-settings] .de-defaults-pill {\n font-family: var(--dsw-font-family-mono, ui-monospace, SFMono-Regular, Menlo, monospace);\n font-size: 10.5px;\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[data-desktop-enhance-settings] .de-defaults-pill[data-disabled=\"true\"] {\n background: var(--dsw-alias-interactive-bg-hover-solid);\n color: var(--dsw-alias-label-tertiary);\n}\n\n\n\n";
3053
4963
  //#endregion
3054
4964
  //#region src/client/index.tsx
3055
4965
  const inject = [
@@ -3123,22 +5033,32 @@ window.__ModuleLoader__.load({
3123
5033
  });
3124
5034
  installTurnPrefix(ctx);
3125
5035
  const timings = installTimings(ctx, () => flagOn(settings.get().value, "stepDuration"), () => ctx.get("sessions"));
3126
- const sessionInfo = installSessionInfo(ctx, () => flagOn(settings.get().value, "sessionInfo"), () => ctx.get("sessions"), t, globalThis.fetch, {
3127
- isOn: () => flagOn(settings.get().value, "toolsManager"),
5036
+ const makePolicyBridge = (featureField, globalField, overridesField) => ({
5037
+ isOn: () => flagOn(settings.get().value, featureField),
3128
5038
  canWrite: () => {
3129
5039
  const snap = settings.get();
3130
- return form !== null && typeof form.set === "function" && snap.writable === true && snap.value !== void 0 && Object.hasOwn(snap.value, "disabledTools");
5040
+ return form !== null && typeof form.set === "function" && snap.writable === true && snap.value !== void 0 && Object.hasOwn(snap.value, globalField) && Object.hasOwn(snap.value, overridesField);
3131
5041
  },
3132
5042
  getDisabledRaw: () => {
3133
- const raw = settings.get().value?.disabledTools;
5043
+ const raw = settings.get().value?.[globalField];
3134
5044
  return typeof raw === "string" ? raw : "";
3135
5045
  },
3136
5046
  setDisabledRaw: (nextCanonical) => {
3137
5047
  try {
3138
- Promise.resolve(form?.set?.("disabledTools", nextCanonical)).catch(() => {});
5048
+ Promise.resolve(form?.set?.(globalField, nextCanonical)).catch(() => {});
5049
+ } catch {}
5050
+ },
5051
+ getSessionOverridesRaw: () => {
5052
+ const raw = settings.get().value?.[overridesField];
5053
+ return typeof raw === "string" ? raw : "";
5054
+ },
5055
+ setSessionOverridesRaw: (nextCanonical) => {
5056
+ try {
5057
+ Promise.resolve(form?.set?.(overridesField, nextCanonical)).catch(() => {});
3139
5058
  } catch {}
3140
5059
  }
3141
5060
  });
5061
+ const sessionInfo = installSessionInfo(ctx, () => flagOn(settings.get().value, "sessionInfo"), () => ctx.get("sessions"), t, globalThis.fetch, makePolicyBridge("toolsManager", "disabledTools", "sessionToolOverrides"), makePolicyBridge("skillsManager", "disabledSkills", "sessionSkillOverrides"));
3142
5062
  const suggestStore = createSuggestStore();
3143
5063
  const suggestWatcher = createSuggestWatcher(() => ctx.get("sessions"), suggestStore, {
3144
5064
  fetchImpl: globalThis.fetch,
@@ -3277,8 +5197,11 @@ window.__ModuleLoader__.load({
3277
5197
  catalogCache,
3278
5198
  CACHE_MS,
3279
5199
  TOOLS_URL,
5200
+ SKILLS_URL,
3280
5201
  SuggestSettings,
3281
5202
  ModelPicker,
5203
+ DefaultToolsManager,
5204
+ DefaultSkillsManager,
3282
5205
  zh,
3283
5206
  en,
3284
5207
  css: enhance_css_default,
@@ -3303,21 +5226,41 @@ window.__ModuleLoader__.load({
3303
5226
  buildSessionInfoSections,
3304
5227
  SESSION_INFO_ATTR,
3305
5228
  TOOLS_POPOVER_ATTR,
5229
+ SKILLS_POPOVER_ATTR,
3306
5230
  SESSION_INFO_URL,
3307
5231
  requestSessionInfo,
3308
5232
  openSkillInHost,
3309
5233
  installSessionInfo,
3310
5234
  DISABLED_TOOL_PREFIX,
5235
+ MAX_SESSION_OVERRIDES: 32,
5236
+ TOOL_SCOPE_ORDER,
3311
5237
  buildToolPrefixTree,
5238
+ buildToolScopeGroups,
5239
+ classifyToolOrigin,
5240
+ clearSessionOverride,
3312
5241
  collectNodeLeafNames,
3313
5242
  disabledToolReason,
3314
5243
  filterToolSchemas,
3315
5244
  formatDisabledTools,
5245
+ formatSessionOverrides,
5246
+ hasSessionOverride,
3316
5247
  parseDisabledTools,
5248
+ parseSessionOverrides,
3317
5249
  parseToolCatalog,
5250
+ resolveEffectiveDisabled,
3318
5251
  splitToolName,
3319
5252
  toggleNodeInSet,
3320
- toggleToolInSet
5253
+ toggleToolInSet,
5254
+ toggleToolScopeGroupInSet,
5255
+ updateSessionOverride,
5256
+ SKILL_SCOPE_ORDER,
5257
+ buildSkillScopeGroups,
5258
+ classifySkillScope,
5259
+ filterSkillsList,
5260
+ isSkillDisabled,
5261
+ normalizeSkillCatalogItems,
5262
+ parseSkillCatalog,
5263
+ toggleSkillGroupInSet
3321
5264
  };
3322
5265
  exports.apply = apply;
3323
5266
  exports.inject = inject;