@michengai/dsh-codex-ui 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -7,6 +7,146 @@ window.__ModuleLoader__.load({
7
7
  let react = require("react");
8
8
  let _deepseek_ai_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
9
9
  let react_jsx_runtime = require("react/jsx-runtime");
10
+ let react_dom = require("react-dom");
11
+ /** 按用户要求用最窄宽度替代宿主自适应默认;已有有效偏好不重置,拖拽起点沿用宿主存储。 */
12
+ function initializeComposerWidth(storage) {
13
+ const key = "dsh.conversation.contentWidth";
14
+ try {
15
+ const saved = Number(storage.getItem(key));
16
+ if (Number.isFinite(saved) && saved > 0) return;
17
+ storage.setItem(key, String(640));
18
+ } catch (error) {
19
+ console.warn("[codex-ui] 无法初始化输入区宽度,将使用宿主默认值。", error);
20
+ }
21
+ }
22
+ /** 新建页没有宿主 WidthHandle,补充同一宽度偏好的拖拽入口。 */
23
+ function observeHeroWidthHandles(label) {
24
+ const mounted = /* @__PURE__ */ new Map();
25
+ const style = document.createElement("style");
26
+ style.textContent = `[data-phase=hero]:has([data-conversation-scroll]){position:relative}[data-dcu-width-handle]{position:absolute;top:0;bottom:0;width:32px;padding:0;border:0;background:transparent;cursor:col-resize;touch-action:none;z-index:8;outline-offset:-5px}[data-dcu-width-handle=left]{right:calc(50% + var(--dsh-chat-content-width) / 2 + 16px)}[data-dcu-width-handle=right]{left:calc(50% + var(--dsh-chat-content-width) / 2 + 16px)}[data-dcu-width-handle]::after{content:'';position:absolute;top:calc(var(--dcu-pointer-y,50%) - 50px);height:100px;width:3px;left:14px;border-radius:3px;background:linear-gradient(transparent,var(--dsw-alias-scrollbar-hover-l1,#888),transparent);opacity:0}[data-dcu-width-handle]:hover::after,[data-dcu-width-handle]:focus-visible::after,[data-dcu-width-handle][data-dragging]::after{opacity:1}[data-phase=hero]:has([data-conversation-composer-overlay]) [data-dcu-width-handle]{display:none}`;
27
+ document.head.append(style);
28
+ const sync = () => {
29
+ for (const [root, dispose] of mounted) if (!root.isConnected || root.dataset.phase !== "hero") {
30
+ dispose();
31
+ mounted.delete(root);
32
+ }
33
+ for (const root of document.querySelectorAll("[data-phase=hero]")) {
34
+ if (mounted.has(root) || !root.querySelector("[data-conversation-scroll]")) continue;
35
+ const clamp = (value) => Math.min(Math.max(640, value), Math.max(640, root.clientWidth - 176));
36
+ const current = () => {
37
+ const raw = getComputedStyle(root).getPropertyValue("--dsh-chat-user-width");
38
+ return clamp(parseFloat(raw) || 640);
39
+ };
40
+ const publish = (width, save) => {
41
+ const value = clamp(width);
42
+ root.style.setProperty("--dsh-chat-user-width", `${value}px`);
43
+ if (save) try {
44
+ localStorage.setItem("dsh.conversation.contentWidth", String(value));
45
+ } catch (error) {
46
+ console.warn("[codex-ui] 无法保存输入区宽度。", error);
47
+ }
48
+ };
49
+ const handles = ["left", "right"].map((side) => {
50
+ const handle = document.createElement("button");
51
+ handle.type = "button";
52
+ handle.dataset.dcuWidthHandle = side;
53
+ handle.setAttribute("aria-label", label);
54
+ let origin = 0;
55
+ let initial = 640;
56
+ let dragging = false;
57
+ handle.addEventListener("pointerdown", (event) => {
58
+ if (event.button !== 0) return;
59
+ event.preventDefault();
60
+ origin = event.clientX;
61
+ initial = current();
62
+ dragging = true;
63
+ handle.dataset.dragging = "";
64
+ handle.setPointerCapture(event.pointerId);
65
+ });
66
+ handle.addEventListener("pointermove", (event) => {
67
+ handle.style.setProperty("--dcu-pointer-y", `${event.clientY - handle.getBoundingClientRect().top}px`);
68
+ if (dragging) publish(initial + (event.clientX - origin) * (side === "right" ? 2 : -2), false);
69
+ });
70
+ handle.addEventListener("pointerup", (event) => {
71
+ if (!dragging) return;
72
+ publish(initial + (event.clientX - origin) * (side === "right" ? 2 : -2), true);
73
+ dragging = false;
74
+ delete handle.dataset.dragging;
75
+ handle.releasePointerCapture(event.pointerId);
76
+ });
77
+ handle.addEventListener("lostpointercapture", () => {
78
+ if (dragging) publish(initial, false);
79
+ dragging = false;
80
+ delete handle.dataset.dragging;
81
+ });
82
+ handle.addEventListener("keydown", (event) => {
83
+ if (![
84
+ "ArrowLeft",
85
+ "ArrowRight",
86
+ "Home"
87
+ ].includes(event.key)) return;
88
+ event.preventDefault();
89
+ const delta = (event.key === "ArrowRight" ? 1 : -1) * (side === "right" ? 1 : -1) * 20;
90
+ publish(event.key === "Home" ? 640 : current() + delta, true);
91
+ });
92
+ root.append(handle);
93
+ return handle;
94
+ });
95
+ mounted.set(root, () => {
96
+ handles.forEach((handle) => handle.remove());
97
+ });
98
+ }
99
+ };
100
+ const observer = new MutationObserver(sync);
101
+ observer.observe(document.body, {
102
+ childList: true,
103
+ subtree: true,
104
+ attributes: true,
105
+ attributeFilter: ["data-phase"]
106
+ });
107
+ sync();
108
+ return () => {
109
+ observer.disconnect();
110
+ mounted.forEach((dispose) => dispose());
111
+ mounted.clear();
112
+ style.remove();
113
+ };
114
+ }
115
+ //#endregion
116
+ //#region src/client/tree-expansion.ts
117
+ const WORKSPACE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.workspace-expansion.v1";
118
+ const CHANNEL_EXPANSION_STORAGE_KEY = "dsh-codex-ui.channel-expansion.v1";
119
+ const SCHEDULE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.schedule-expansion.v1";
120
+ const MAX_EXPANSION_ENTRIES = 500;
121
+ const MAX_EXPANSION_KEY_LENGTH = 512;
122
+ function browserStorage() {
123
+ if (typeof window === "undefined") return void 0;
124
+ try {
125
+ return window.localStorage;
126
+ } catch {
127
+ return;
128
+ }
129
+ }
130
+ function parseTreeExpansionState(value) {
131
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
132
+ const entries = Object.entries(value).filter(([key, expanded]) => key.length > 0 && key.length <= MAX_EXPANSION_KEY_LENGTH && typeof expanded === "boolean").slice(0, MAX_EXPANSION_ENTRIES);
133
+ return Object.fromEntries(entries);
134
+ }
135
+ function readTreeExpansionState(storage, key) {
136
+ if (storage === void 0) return {};
137
+ try {
138
+ return parseTreeExpansionState(JSON.parse(storage.getItem(key) ?? "{}"));
139
+ } catch {
140
+ return {};
141
+ }
142
+ }
143
+ function writeTreeExpansionState(storage, key, state) {
144
+ if (storage === void 0) return;
145
+ try {
146
+ storage.setItem(key, JSON.stringify(parseTreeExpansionState(state)));
147
+ } catch {}
148
+ }
149
+ //#endregion
10
150
  //#region src/client/settings-navigation.ts
11
151
  /**
12
152
  * DSH 设置壳暂未提供按 section id 打开的公开 API。该兼容层只从本插件渲染
@@ -31,6 +171,7 @@ window.__ModuleLoader__.load({
31
171
  let cancelPendingNavigation;
32
172
  const SETTINGS_NAVIGATION_TIMEOUT_MS = 4e3;
33
173
  const SETTINGS_TRIGGER_SELECTOR = "[data-dcu-settings-trigger],[aria-haspopup=\"dialog\"]";
174
+ const SETTINGS_OPEN_SECTION_EVENT = "dcu-settings-open-section";
34
175
  /** 根入口与分区跳转使用同一触发器合约,兼容保留的宿主设置壳。 */
35
176
  function openSettingsRoot(root) {
36
177
  root?.querySelector(SETTINGS_TRIGGER_SELECTOR)?.click();
@@ -44,6 +185,14 @@ window.__ModuleLoader__.load({
44
185
  }
45
186
  const opening = cancelPendingNavigation !== void 0;
46
187
  cancelPendingNavigation?.();
188
+ const request = new CustomEvent(SETTINGS_OPEN_SECTION_EVENT, {
189
+ detail: { labels },
190
+ cancelable: true
191
+ });
192
+ if (!trigger.dispatchEvent(request)) {
193
+ onSelected?.();
194
+ return;
195
+ }
47
196
  const pageSelector = trigger.hasAttribute("data-dcu-settings-trigger") ? "[data-dcu-settings-page]" : "[role=\"dialog\"]";
48
197
  if (!opening && document.querySelector(pageSelector) === null) trigger.click();
49
198
  let frame;
@@ -522,6 +671,82 @@ window.__ModuleLoader__.load({
522
671
  * This source code is licensed under the ISC license.
523
672
  * See the LICENSE file in the root directory of this source tree.
524
673
  */
674
+ const Bug = createLucideIcon("bug", [
675
+ ["path", {
676
+ d: "M12 20v-9",
677
+ key: "1qisl0"
678
+ }],
679
+ ["path", {
680
+ d: "M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z",
681
+ key: "uouzyp"
682
+ }],
683
+ ["path", {
684
+ d: "M14.12 3.88 16 2",
685
+ key: "qol33r"
686
+ }],
687
+ ["path", {
688
+ d: "M21 21a4 4 0 0 0-3.81-4",
689
+ key: "1b0z45"
690
+ }],
691
+ ["path", {
692
+ d: "M21 5a4 4 0 0 1-3.55 3.97",
693
+ key: "5cxbf6"
694
+ }],
695
+ ["path", {
696
+ d: "M22 13h-4",
697
+ key: "1jl80f"
698
+ }],
699
+ ["path", {
700
+ d: "M3 21a4 4 0 0 1 3.81-4",
701
+ key: "1fjd4g"
702
+ }],
703
+ ["path", {
704
+ d: "M3 5a4 4 0 0 0 3.55 3.97",
705
+ key: "1d7oge"
706
+ }],
707
+ ["path", {
708
+ d: "M6 13H2",
709
+ key: "82j7cp"
710
+ }],
711
+ ["path", {
712
+ d: "m8 2 1.88 1.88",
713
+ key: "fmnt4t"
714
+ }],
715
+ ["path", {
716
+ d: "M9 7.13V6a3 3 0 1 1 6 0v1.13",
717
+ key: "1vgav8"
718
+ }]
719
+ ]);
720
+ /**
721
+ * @license lucide-react v1.39.0 - ISC
722
+ *
723
+ * This source code is licensed under the ISC license.
724
+ * See the LICENSE file in the root directory of this source tree.
725
+ */
726
+ const ChartColumn = createLucideIcon("chart-column", [
727
+ ["path", {
728
+ d: "M3 3v16a2 2 0 0 0 2 2h16",
729
+ key: "c24i48"
730
+ }],
731
+ ["path", {
732
+ d: "M18 17V9",
733
+ key: "2bz60n"
734
+ }],
735
+ ["path", {
736
+ d: "M13 17V5",
737
+ key: "1frdt8"
738
+ }],
739
+ ["path", {
740
+ d: "M8 17v-3",
741
+ key: "17ska0"
742
+ }]
743
+ ]);
744
+ /**
745
+ * @license lucide-react v1.39.0 - ISC
746
+ *
747
+ * This source code is licensed under the ISC license.
748
+ * See the LICENSE file in the root directory of this source tree.
749
+ */
525
750
  const CircleQuestionMark = createLucideIcon("circle-question-mark", [
526
751
  ["circle", {
527
752
  cx: "12",
@@ -670,6 +895,26 @@ window.__ModuleLoader__.load({
670
895
  * This source code is licensed under the ISC license.
671
896
  * See the LICENSE file in the root directory of this source tree.
672
897
  */
898
+ const Hammer = createLucideIcon("hammer", [
899
+ ["path", {
900
+ d: "m15 12-9.373 9.373a1 1 0 0 1-3.001-3L12 9",
901
+ key: "1hayfq"
902
+ }],
903
+ ["path", {
904
+ d: "m18 15 4-4",
905
+ key: "16gjal"
906
+ }],
907
+ ["path", {
908
+ d: "m21.5 11.5-1.914-1.914A2 2 0 0 1 19 8.172v-.344a2 2 0 0 0-.586-1.414l-1.657-1.657A6 6 0 0 0 12.516 3H9l1.243 1.243A6 6 0 0 1 12 8.485V10l2 2h1.172a2 2 0 0 1 1.414.586L18.5 14.5",
909
+ key: "15ts47"
910
+ }]
911
+ ]);
912
+ /**
913
+ * @license lucide-react v1.39.0 - ISC
914
+ *
915
+ * This source code is licensed under the ISC license.
916
+ * See the LICENSE file in the root directory of this source tree.
917
+ */
673
918
  const Link = createLucideIcon("link", [["path", {
674
919
  d: "M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71",
675
920
  key: "1cjeqo"
@@ -733,6 +978,34 @@ window.__ModuleLoader__.load({
733
978
  * This source code is licensed under the ISC license.
734
979
  * See the LICENSE file in the root directory of this source tree.
735
980
  */
981
+ const ScanLine = createLucideIcon("scan-line", [
982
+ ["path", {
983
+ d: "M3 7V5a2 2 0 0 1 2-2h2",
984
+ key: "aa7l1z"
985
+ }],
986
+ ["path", {
987
+ d: "M17 3h2a2 2 0 0 1 2 2v2",
988
+ key: "4qcy5o"
989
+ }],
990
+ ["path", {
991
+ d: "M21 17v2a2 2 0 0 1-2 2h-2",
992
+ key: "6vwrx8"
993
+ }],
994
+ ["path", {
995
+ d: "M7 21H5a2 2 0 0 1-2-2v-2",
996
+ key: "ioqczr"
997
+ }],
998
+ ["path", {
999
+ d: "M7 12h10",
1000
+ key: "b7w52i"
1001
+ }]
1002
+ ]);
1003
+ /**
1004
+ * @license lucide-react v1.39.0 - ISC
1005
+ *
1006
+ * This source code is licensed under the ISC license.
1007
+ * See the LICENSE file in the root directory of this source tree.
1008
+ */
736
1009
  const Search = createLucideIcon("search", [["path", {
737
1010
  d: "m21 21-4.34-4.34",
738
1011
  key: "14j7rj"
@@ -866,6 +1139,44 @@ window.__ModuleLoader__.load({
866
1139
  * This source code is licensed under the ISC license.
867
1140
  * See the LICENSE file in the root directory of this source tree.
868
1141
  */
1142
+ const Telescope = createLucideIcon("telescope", [
1143
+ ["path", {
1144
+ d: "m10.065 12.493-6.18 1.318a.934.934 0 0 1-1.108-.702l-.537-2.15a1.07 1.07 0 0 1 .691-1.265l13.504-4.44",
1145
+ key: "k4qptu"
1146
+ }],
1147
+ ["path", {
1148
+ d: "m13.56 11.747 4.332-.924",
1149
+ key: "19l80z"
1150
+ }],
1151
+ ["path", {
1152
+ d: "m16 21-3.105-6.21",
1153
+ key: "7oh9d"
1154
+ }],
1155
+ ["path", {
1156
+ d: "M16.485 5.94a2 2 0 0 1 1.455-2.425l1.09-.272a1 1 0 0 1 1.212.727l1.515 6.06a1 1 0 0 1-.727 1.213l-1.09.272a2 2 0 0 1-2.425-1.455z",
1157
+ key: "m7xp4m"
1158
+ }],
1159
+ ["path", {
1160
+ d: "m6.158 8.633 1.114 4.456",
1161
+ key: "74o979"
1162
+ }],
1163
+ ["path", {
1164
+ d: "m8 21 3.105-6.21",
1165
+ key: "1fvxut"
1166
+ }],
1167
+ ["circle", {
1168
+ cx: "12",
1169
+ cy: "13",
1170
+ r: "2",
1171
+ key: "1c1ljs"
1172
+ }]
1173
+ ]);
1174
+ /**
1175
+ * @license lucide-react v1.39.0 - ISC
1176
+ *
1177
+ * This source code is licensed under the ISC license.
1178
+ * See the LICENSE file in the root directory of this source tree.
1179
+ */
869
1180
  const User = createLucideIcon("user", [["path", {
870
1181
  d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",
871
1182
  key: "975kel"
@@ -2212,40 +2523,6 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
2212
2523
  return fallback !== void 0 && fallback.trim() !== "" ? fallback : void 0;
2213
2524
  }
2214
2525
  //#endregion
2215
- //#region src/client/tree-expansion.ts
2216
- const WORKSPACE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.workspace-expansion.v1";
2217
- const CHANNEL_EXPANSION_STORAGE_KEY = "dsh-codex-ui.channel-expansion.v1";
2218
- const SCHEDULE_EXPANSION_STORAGE_KEY = "dsh-codex-ui.schedule-expansion.v1";
2219
- const MAX_EXPANSION_ENTRIES = 500;
2220
- const MAX_EXPANSION_KEY_LENGTH = 512;
2221
- function browserStorage() {
2222
- if (typeof window === "undefined") return void 0;
2223
- try {
2224
- return window.localStorage;
2225
- } catch {
2226
- return;
2227
- }
2228
- }
2229
- function parseTreeExpansionState(value) {
2230
- if (value === null || typeof value !== "object" || Array.isArray(value)) return {};
2231
- const entries = Object.entries(value).filter(([key, expanded]) => key.length > 0 && key.length <= MAX_EXPANSION_KEY_LENGTH && typeof expanded === "boolean").slice(0, MAX_EXPANSION_ENTRIES);
2232
- return Object.fromEntries(entries);
2233
- }
2234
- function readTreeExpansionState(storage, key) {
2235
- if (storage === void 0) return {};
2236
- try {
2237
- return parseTreeExpansionState(JSON.parse(storage.getItem(key) ?? "{}"));
2238
- } catch {
2239
- return {};
2240
- }
2241
- }
2242
- function writeTreeExpansionState(storage, key, state) {
2243
- if (storage === void 0) return;
2244
- try {
2245
- storage.setItem(key, JSON.stringify(parseTreeExpansionState(state)));
2246
- } catch {}
2247
- }
2248
- //#endregion
2249
2526
  //#region src/client/workspace-compat.ts
2250
2527
  function hasStartSession(value) {
2251
2528
  return value !== null && typeof value === "object" && "startSession" in value && typeof value.startSession === "function";
@@ -2648,7 +2925,8 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
2648
2925
  const stylesheet$4 = `
2649
2926
  .dcu-wb{--dcu-wb-inset:8px;display:flex;flex:1;min-height:0;flex-direction:column;padding:4px var(--dcu-wb-inset) 8px;color:var(--dcu-sidebar-primary)}
2650
2927
  .dcu-wb *{box-sizing:border-box}
2651
- .dcu-wb-tree{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;padding-bottom:16px;scrollbar-gutter:auto;user-select:none;-webkit-user-select:none}
2928
+ .dcu-wb-tree{flex:1;min-height:0;overflow-x:hidden;overflow-y:auto;padding-bottom:16px;scrollbar-gutter:auto;scrollbar-width:none;user-select:none;-webkit-user-select:none}
2929
+ .dcu-wb-tree::-webkit-scrollbar{display:none}
2652
2930
  .dcu-wb-section+.dcu-wb-section{margin-top:12px}
2653
2931
  .dcu-wb-section-head{position:relative;display:flex;align-items:center;min-height:24px;padding:0;border-radius:6px}.dcu-wb-section-head:hover .dcu-wb-actions{display:flex}.dcu-wb-section-label{position:relative;display:flex;align-items:center;gap:4px;flex:1;min-width:0;min-height:24px;border:0;padding:2px 4px 2px 12px;background:transparent;color:var(--dcu-sidebar-tertiary);font:13px/20px var(--dcu-font,inherit);font-weight:400;letter-spacing:0;text-align:left;cursor:pointer}.dcu-wb-section-caret{display:grid;place-items:center;flex:none;width:12px;height:12px;color:currentColor;opacity:0;transform:rotate(0deg);transform-origin:50% 50%;transition:opacity 120ms ease,transform 160ms ease}.dcu-wb-section-head .dcu-wb-section-caret{position:absolute;left:0;top:6px}.dcu-wb-section-caret svg{display:block}.dcu-wb-section-head:hover .dcu-wb-section-caret,.dcu-wb-section-label:focus-visible .dcu-wb-section-caret{opacity:.78}.dcu-wb-section-label[aria-expanded=true] .dcu-wb-section-caret{transform:rotate(90deg)}.dcu-wb-section-body{display:block}.dcu-wb-section-body[data-open=false]{display:none}.dcu-wb-section-body>div{min-height:0}.dcu-wb-section-body[data-open=true]>div{animation:dcu-wb-section-in 140ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-wb-section-in{from{opacity:0;transform:translateY(-3px)}to{opacity:1;transform:none}}@media (prefers-reduced-motion:reduce){.dcu-wb-section-caret{transition:none}.dcu-wb-section-body[data-open=true]>div{animation:none}}
2654
2932
  .dcu-wb-project{position:relative;min-width:0}
@@ -5714,6 +5992,340 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5714
5992
  } catch {}
5715
5993
  }
5716
5994
  //#endregion
5995
+ //#region src/client/new-conversation-style.ts
5996
+ /** 新建页底部输入布局;保留宿主节点、插槽与 active 会话底部信息。 */
5997
+ const NEW_CONVERSATION_STYLE = `
5998
+ [data-phase=hero]:has([data-conversation-scroll]){container:dcu-new-conversation / inline-size}
5999
+ [data-phase=hero] [data-conversation-scroll][class]{--dsh-composer-side-clearance:16px;justify-content:flex-start;scrollbar-gutter:stable both-edges}
6000
+ [data-phase=hero] [data-composer-seat]{flex:1 0 auto;min-height:100%}
6001
+ [data-phase=hero] [data-composer-seat]>:has([class*="_composerHero"]){display:flex;flex:1;flex-direction:column}
6002
+ [data-phase=hero] [class*="_composerHero"]{box-sizing:border-box;flex:1;width:100%;max-width:none;min-width:0;margin-inline:auto;gap:0;padding-bottom:32px}
6003
+ [data-phase=hero] [class*="_composerHero"]>:first-child{box-sizing:border-box;flex:1;width:100%;max-width:768px;align-self:center;height:auto;min-height:340px;align-items:center;padding:32px 28px}
6004
+ [data-phase=hero] [class*="_composerHero"]>:first-child>[class$="_stack"]{width:100%;max-width:none;min-width:0;align-items:center;gap:32px}
6005
+ [data-phase=hero] [class*="_heroWorkspaceRow"]{box-sizing:border-box;flex:none;width:min(calc(var(--dsh-composer-card-max-width) + 2 * var(--dsh-composer-side-clearance) - 56px),calc(100% - 56px));align-self:center;justify-content:flex-start;flex-wrap:wrap;gap:8px;min-height:48px;margin:0 28px -10px;padding:6px 12px 16px;border-radius:18px 18px 0 0;background:color-mix(in srgb,var(--dsw-alias-label-primary) 4%,var(--dsw-alias-bg-base))}
6006
+ [data-phase=hero] [class*="_heroWorkspaceRow"]>[class$="_workspace"]{min-width:0;max-width:100%;font-weight:400}
6007
+ .dcu-home-suggestions{width:100%;color:var(--dsw-alias-label-primary);font:13px/20px var(--dsw-font-family,system-ui)}
6008
+ .dcu-home-cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:10px}
6009
+ .dcu-home-card{appearance:none;display:flex;flex-direction:column;justify-content:space-between;gap:22px;min-width:0;min-height:106px;padding:16px;border:1px solid color-mix(in srgb,var(--dsw-alias-label-primary) 10%,transparent);border-radius:20px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer;transition:background-color 150ms,border-color 150ms}
6010
+ .dcu-home-card:hover,.dcu-home-card[aria-pressed=true]{background:color-mix(in srgb,var(--dsw-alias-label-primary) 5%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-label-primary) 20%,transparent)}
6011
+ .dcu-home-card svg{width:16px;height:16px;flex:none;color:var(--dcu-home-icon)}
6012
+ .dcu-home-card:focus-visible,.dcu-home-task:focus-visible{outline:2px solid var(--dsw-alias-label-primary);outline-offset:3px}
6013
+ .dcu-home-details,.dcu-home-status{display:grid}
6014
+ .dcu-home-suggestions[data-has-draft=true]{visibility:hidden;pointer-events:none}
6015
+ .dcu-home-tasks{grid-area:1/1;display:flex;flex-wrap:wrap;align-content:start;gap:8px;margin-top:16px}
6016
+ .dcu-home-details>[data-active=false],.dcu-home-status>[data-active=false]{visibility:hidden;pointer-events:none}
6017
+ .dcu-home-task{appearance:none;border:1px solid color-mix(in srgb,var(--dsw-alias-label-primary) 12%,transparent);border-radius:10px;padding:8px 12px;background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}
6018
+ .dcu-home-task:hover{background:color-mix(in srgb,var(--dsw-alias-label-primary) 5%,transparent)}
6019
+ .dcu-home-hint{grid-area:1/1;margin:12px 0 0;color:var(--dsw-alias-label-secondary)}
6020
+ @container dcu-new-conversation (width < 640px){
6021
+ .dcu-home-cards{grid-template-columns:repeat(2,minmax(0,1fr))}
6022
+ [data-phase=hero] [class*="_composerHero"]>:first-child{padding:32px 24px;min-height:420px}
6023
+ }
6024
+ @media(prefers-reduced-motion:reduce){.dcu-home-card{transition:none}}
6025
+ `;
6026
+ //#endregion
6027
+ //#region src/client/composer-tool-menus.ts
6028
+ /** 只适配由输入区工具触发的菜单;保留原条目、选择回调及目录创建流程。 */
6029
+ const TOOL = "[class*=\"_heroWorkspaceRow\"] button,[data-composer-card] button[aria-haspopup],[data-composer-card] button[aria-expanded]";
6030
+ const MENU = "[role=\"menu\"],[role=\"listbox\"]";
6031
+ const COMPOSER_TOOL_MENU_STYLE = `
6032
+ [class*="_heroWorkspaceRow"] button{min-height:28px;border-radius:999px;font-size:13px;line-height:20px}
6033
+ [class*="_heroWorkspaceRow"] button:hover,[class*="_heroWorkspaceRow"] button[aria-expanded=true]{background:color-mix(in srgb,var(--dsw-alias-label-primary) 8%,transparent)}
6034
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]){box-sizing:border-box;min-width:0!important;width:262px;max-width:calc(100vw - 24px);max-height:var(--dcu-tool-menu-height,360px)!important;padding:5px!important;border-radius:18px!important;background:#fff!important;color:var(--dsw-alias-label-primary);box-shadow:0 8px 32px #0002,0 0 0 1px #0000000a!important;display:flex;flex-direction:column;gap:0;z-index:1100}
6035
+ [data-dcu-tool-menu=portal]{position:fixed!important;left:var(--dcu-tool-menu-x)!important;top:var(--dcu-tool-menu-y)!important;bottom:auto!important;right:auto!important}
6036
+ :is([data-dcu-tool-menu=inline],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]:not([data-dcu-tool-menu=portal])){width:320px;translate:var(--dcu-tool-menu-shift,0px) 0}
6037
+ [class*="_heroWorkspaceRow"] [data-gitgraph-popover]:not([data-dcu-tool-menu=portal]){top:auto!important;bottom:calc(100% + 4px)!important}
6038
+ body[data-ds-dark-theme] :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]){background:#292929!important;box-shadow:0 8px 32px #0003,0 0 0 1px #ffffff08!important}
6039
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover])>[class*="_viewport"]{min-height:0;max-height:none;overflow-y:auto;scrollbar-width:thin}
6040
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) :is([role=menuitem],[role=menuitemradio],[role=menuitemcheckbox],[role=option]){box-sizing:border-box;min-height:28px;padding:4px 9px;gap:8px;border-radius:8px;font-size:13px;line-height:20px}
6041
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) :is([role=menuitem],[role=menuitemradio],[role=option]):hover:not(:disabled),:is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) [class*="_selected"],:is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) [aria-selected=true],:is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) [aria-checked=true]{background:color-mix(in srgb,var(--dsw-alias-label-primary) 10%,transparent)}
6042
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) [class*="_itemIcon"] svg{width:16px;height:16px}
6043
+ :is([data-dcu-tool-menu],[class*="_heroWorkspaceRow"] [data-gitgraph-popover]) [class*="_footer"]{flex:none;margin-top:5px;padding-top:5px;border-top:1px solid color-mix(in srgb,var(--dsw-alias-label-primary) 10%,transparent)}
6044
+ [data-dcu-tool-filter]{box-sizing:border-box;flex:none;width:100%;height:32px;padding:4px 10px;margin:0 0 1px;border:0;border-radius:8px;outline:none;background:transparent;color:inherit;font:13px/20px var(--dsw-font-family,system-ui)}
6045
+ [data-dcu-tool-filter]:focus-visible{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--dsw-alias-label-primary) 20%,transparent)}
6046
+ [data-dcu-tool-empty]{padding:8px 10px;font-size:13px;color:var(--dsw-alias-label-secondary)}
6047
+ [data-dcu-tool-filtered]{display:none!important}
6048
+ `;
6049
+ function observeComposerToolMenus(copy) {
6050
+ let anchor;
6051
+ let known = /* @__PURE__ */ new Set();
6052
+ let pendingUntil = 0;
6053
+ const mounted = /* @__PURE__ */ new Map();
6054
+ const now = () => Date.now();
6055
+ function capture(event) {
6056
+ const target = event.target instanceof Element ? event.target.closest(TOOL) : null;
6057
+ if (target === null || target.closest("[data-conversation-scroll]") === null) return;
6058
+ anchor = target;
6059
+ known = new Set(document.querySelectorAll(MENU));
6060
+ pendingUntil = now() + 1e3;
6061
+ }
6062
+ function mount(menu, trigger) {
6063
+ const portal = getComputedStyle(menu).position === "fixed";
6064
+ menu.setAttribute("data-dcu-tool-menu", portal ? "portal" : "inline");
6065
+ const isProject = trigger.matches("[class*=\"_heroWorkspaceRow\"]>button:first-child");
6066
+ const viewport = menu.querySelector(":scope>[class*=\"_viewport\"]");
6067
+ let input;
6068
+ let empty;
6069
+ if (isProject && viewport !== null && menu.querySelector("input") === null) {
6070
+ input = document.createElement("input");
6071
+ input.type = "search";
6072
+ input.placeholder = copy.search;
6073
+ input.setAttribute("aria-label", copy.search);
6074
+ input.setAttribute("data-dcu-tool-filter", "");
6075
+ empty = document.createElement("div");
6076
+ empty.setAttribute("data-dcu-tool-empty", "");
6077
+ empty.setAttribute("role", "status");
6078
+ empty.textContent = copy.empty;
6079
+ empty.hidden = true;
6080
+ menu.prepend(input);
6081
+ viewport.after(empty);
6082
+ input.addEventListener("input", () => {
6083
+ const query = input.value.trim().toLocaleLowerCase();
6084
+ let count = 0;
6085
+ for (const row of viewport.children) {
6086
+ const match = (row.textContent ?? "").toLocaleLowerCase().includes(query);
6087
+ row.toggleAttribute("data-dcu-tool-filtered", !match);
6088
+ if (match) count++;
6089
+ }
6090
+ empty.hidden = count > 0;
6091
+ place();
6092
+ });
6093
+ input.addEventListener("keydown", (event) => {
6094
+ if (event.key !== "ArrowDown" && event.key !== "Enter") return;
6095
+ const first = viewport.querySelector(":scope>:not([data-dcu-tool-filtered]) button:not(:disabled)");
6096
+ if (first !== null) {
6097
+ event.preventDefault();
6098
+ event.stopPropagation();
6099
+ first.focus();
6100
+ if (event.key === "Enter") first.click();
6101
+ }
6102
+ });
6103
+ }
6104
+ function place() {
6105
+ if (!trigger.isConnected || !menu.isConnected) return;
6106
+ const rect = trigger.getBoundingClientRect();
6107
+ const above = rect.top - 16;
6108
+ const below = window.innerHeight - rect.bottom - 16;
6109
+ const topSide = above >= Math.min(260, below);
6110
+ menu.style.setProperty("--dcu-tool-menu-height", `${Math.max(60, Math.min(360, topSide ? above : below))}px`);
6111
+ if (!portal) {
6112
+ const previous = parseFloat(menu.style.getPropertyValue("--dcu-tool-menu-shift")) || 0;
6113
+ const bounds = menu.getBoundingClientRect();
6114
+ const naturalLeft = bounds.left - previous;
6115
+ const left = Math.max(12, Math.min(naturalLeft, window.innerWidth - bounds.width - 12));
6116
+ menu.style.setProperty("--dcu-tool-menu-shift", `${left - naturalLeft}px`);
6117
+ return;
6118
+ }
6119
+ const bounds = menu.getBoundingClientRect();
6120
+ const x = Math.max(12, Math.min(rect.left, window.innerWidth - bounds.width - 12));
6121
+ const y = Math.max(12, topSide ? rect.top - bounds.height - 4 : rect.bottom + 4);
6122
+ menu.style.setProperty("--dcu-tool-menu-x", `${x}px`);
6123
+ menu.style.setProperty("--dcu-tool-menu-y", `${y}px`);
6124
+ }
6125
+ const resize = new ResizeObserver(place);
6126
+ resize.observe(menu);
6127
+ resize.observe(trigger);
6128
+ window.addEventListener("resize", place);
6129
+ window.addEventListener("scroll", place, true);
6130
+ place();
6131
+ mounted.set(menu, () => {
6132
+ resize.disconnect();
6133
+ window.removeEventListener("resize", place);
6134
+ window.removeEventListener("scroll", place, true);
6135
+ input?.remove();
6136
+ empty?.remove();
6137
+ menu.querySelectorAll("[data-dcu-tool-filtered]").forEach((row) => row.removeAttribute("data-dcu-tool-filtered"));
6138
+ menu.removeAttribute("data-dcu-tool-menu");
6139
+ for (const property of [
6140
+ "--dcu-tool-menu-x",
6141
+ "--dcu-tool-menu-y",
6142
+ "--dcu-tool-menu-height",
6143
+ "--dcu-tool-menu-shift"
6144
+ ]) menu.style.removeProperty(property);
6145
+ });
6146
+ }
6147
+ function sync() {
6148
+ for (const [menu, dispose] of mounted) if (!menu.isConnected) {
6149
+ dispose();
6150
+ mounted.delete(menu);
6151
+ }
6152
+ if (anchor === void 0 || now() > pendingUntil) return;
6153
+ for (const menu of document.querySelectorAll(MENU)) {
6154
+ if (known.has(menu) || mounted.has(menu) || menu.parentElement?.closest(MENU) !== null) continue;
6155
+ if (menu.getClientRects().length === 0) continue;
6156
+ mount(menu, anchor);
6157
+ pendingUntil = 0;
6158
+ break;
6159
+ }
6160
+ }
6161
+ const observer = new MutationObserver(sync);
6162
+ observer.observe(document.body, {
6163
+ childList: true,
6164
+ subtree: true
6165
+ });
6166
+ document.addEventListener("pointerdown", capture, true);
6167
+ document.addEventListener("keydown", captureKey, true);
6168
+ function captureKey(event) {
6169
+ if ([
6170
+ "Enter",
6171
+ " ",
6172
+ "ArrowDown"
6173
+ ].includes(event.key)) capture(event);
6174
+ }
6175
+ return () => {
6176
+ observer.disconnect();
6177
+ document.removeEventListener("pointerdown", capture, true);
6178
+ document.removeEventListener("keydown", captureKey, true);
6179
+ mounted.forEach((dispose) => dispose());
6180
+ mounted.clear();
6181
+ };
6182
+ }
6183
+ //#endregion
6184
+ //#region src/client/NewConversationSuggestions.tsx
6185
+ const categories = [
6186
+ {
6187
+ id: "explore",
6188
+ label: "home.explore",
6189
+ tasks: [{
6190
+ label: "home.explore.task1",
6191
+ prompt: "home.explore.prompt1"
6192
+ }, {
6193
+ label: "home.explore.task2",
6194
+ prompt: "home.explore.prompt2"
6195
+ }],
6196
+ Icon: Telescope,
6197
+ color: "#27aaff"
6198
+ },
6199
+ {
6200
+ id: "build",
6201
+ label: "home.build",
6202
+ tasks: [{
6203
+ label: "home.build.task1",
6204
+ prompt: "home.build.prompt1"
6205
+ }, {
6206
+ label: "home.build.task2",
6207
+ prompt: "home.build.prompt2"
6208
+ }],
6209
+ Icon: Hammer,
6210
+ color: "#a478e8"
6211
+ },
6212
+ {
6213
+ id: "review",
6214
+ label: "home.review",
6215
+ tasks: [{
6216
+ label: "home.review.task1",
6217
+ prompt: "home.review.prompt1"
6218
+ }, {
6219
+ label: "home.review.task2",
6220
+ prompt: "home.review.prompt2"
6221
+ }],
6222
+ Icon: ScanLine,
6223
+ color: "#44bd83"
6224
+ },
6225
+ {
6226
+ id: "fix",
6227
+ label: "home.fix",
6228
+ tasks: [{
6229
+ label: "home.fix.task1",
6230
+ prompt: "home.fix.prompt1"
6231
+ }, {
6232
+ label: "home.fix.task2",
6233
+ prompt: "home.fix.prompt2"
6234
+ }],
6235
+ Icon: Bug,
6236
+ color: "#f48235"
6237
+ }
6238
+ ];
6239
+ const hints = {
6240
+ workspace: "home.workspace",
6241
+ draft: "home.draft",
6242
+ busy: "home.busy"
6243
+ };
6244
+ const emptyDraft = {
6245
+ getSnapshot: () => false,
6246
+ subscribe: () => () => {}
6247
+ };
6248
+ /** 只向宿主标题容器贡献自己的 React portal,不搬动标题、工具条或编辑器。 */
6249
+ function NewConversationSuggestions({ t, prefill, draftSource = emptyDraft }) {
6250
+ const hasDraft = (0, react.useSyncExternalStore)(draftSource.subscribe, draftSource.getSnapshot, emptyDraft.getSnapshot);
6251
+ const [target, setTarget] = (0, react.useState)(null);
6252
+ (0, react.useEffect)(() => {
6253
+ const sync = () => setTarget(document.querySelector("[data-phase=hero] [class*=\"_composerHero\"]>:first-child>[class$=\"_stack\"]"));
6254
+ sync();
6255
+ const observer = new MutationObserver(sync);
6256
+ observer.observe(document.body, {
6257
+ childList: true,
6258
+ subtree: true,
6259
+ attributes: true,
6260
+ attributeFilter: ["data-phase"]
6261
+ });
6262
+ return () => observer.disconnect();
6263
+ }, []);
6264
+ return target === null ? null : (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SuggestionCards, {
6265
+ t,
6266
+ prefill,
6267
+ hasDraft
6268
+ }), target);
6269
+ }
6270
+ function SuggestionCards({ t, prefill, hasDraft = false }) {
6271
+ const [selected, setSelected] = (0, react.useState)();
6272
+ const [hint, setHint] = (0, react.useState)("ready");
6273
+ function fill(text) {
6274
+ const result = prefill?.(text) ?? "workspace";
6275
+ setHint(result);
6276
+ if (result === "ready") document.querySelector("[data-phase=hero] [data-lexical-editor=true]")?.focus();
6277
+ if (result === "workspace") document.querySelector("[data-phase=hero] [class*=\"_heroWorkspaceRow\"]>button")?.click();
6278
+ }
6279
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
6280
+ className: "dcu-home-suggestions",
6281
+ "data-has-draft": hasDraft,
6282
+ "aria-hidden": hasDraft,
6283
+ "aria-label": t("home.suggestions"),
6284
+ children: [
6285
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6286
+ className: "dcu-home-cards",
6287
+ children: categories.map(({ id, label, Icon, color }) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
6288
+ type: "button",
6289
+ disabled: hasDraft,
6290
+ className: "dcu-home-card",
6291
+ style: { "--dcu-home-icon": color },
6292
+ "aria-pressed": selected === id,
6293
+ onClick: () => {
6294
+ setSelected(selected === id ? void 0 : id);
6295
+ setHint("ready");
6296
+ },
6297
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { "aria-hidden": "true" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t(label) })]
6298
+ }, id))
6299
+ }),
6300
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6301
+ className: "dcu-home-details",
6302
+ children: categories.map((category) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6303
+ className: "dcu-home-tasks",
6304
+ "data-active": selected === category.id,
6305
+ "aria-hidden": selected !== category.id,
6306
+ children: category.tasks.map((task) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
6307
+ type: "button",
6308
+ className: "dcu-home-task",
6309
+ disabled: hasDraft || selected !== category.id,
6310
+ onClick: () => fill(t(task.prompt)),
6311
+ children: t(task.label)
6312
+ }, task.label))
6313
+ }, category.id))
6314
+ }),
6315
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6316
+ className: "dcu-home-status",
6317
+ children: Object.keys(hints).map((key) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
6318
+ className: "dcu-home-hint",
6319
+ "data-active": hint === key,
6320
+ "aria-hidden": hint !== key,
6321
+ role: hint === key ? "status" : void 0,
6322
+ children: t(hints[key])
6323
+ }, key))
6324
+ })
6325
+ ]
6326
+ });
6327
+ }
6328
+ //#endregion
5717
6329
  //#region src/client/CodexSidebar.tsx
5718
6330
  const subscribeEmptyCompanionTabs = () => () => {};
5719
6331
  const getEmptyCompanionTabs = () => EMPTY_COMPANION_TABS;
@@ -5732,7 +6344,7 @@ header [data-dcu-title-folder] svg,header [data-dcu-title-more] svg{display:bloc
5732
6344
  });
5733
6345
  }
5734
6346
  const stylesheet$3 = `
5735
- .dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-primary:#393d3e;--dcu-sidebar-secondary:#676b6c;--dcu-sidebar-tertiary:#9a9f9f;--dcu-sidebar-navigation:#4e5253;--dcu-sidebar-icon:#4e5253;--dcu-sidebar-hover:#dfe8e5;--dcu-sidebar-border:rgba(37,46,41,.10);--dcu-tip-bg:#ffffff;--dcu-tip-shadow:0 10px 32px rgba(31,39,36,.22);width:100%;height:100%;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden;background:#eef7f5;color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font)}body[data-ds-dark-theme] .dcu-root{background:#1d2120;--dcu-sidebar-primary:#b9bab9;--dcu-sidebar-secondary:#909191;--dcu-sidebar-tertiary:#666867;--dcu-sidebar-navigation:#b9bab9;--dcu-sidebar-icon:#afafaf;--dcu-sidebar-hover:#303432;--dcu-sidebar-border:rgba(255,255,255,.08);--dcu-tip-bg:#2a2a2a;--dcu-tip-shadow:0 10px 30px rgba(0,0,0,.28)}
6347
+ .dcu-root{--dcu-font:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI","Microsoft YaHei UI",sans-serif;--dcu-sidebar-background:#eef7f5;--dcu-sidebar-primary:#393d3e;--dcu-sidebar-secondary:#676b6c;--dcu-sidebar-tertiary:#9a9f9f;--dcu-sidebar-navigation:#4e5253;--dcu-sidebar-icon:#4e5253;--dcu-sidebar-hover:#dfe8e5;--dcu-sidebar-border:rgba(37,46,41,.10);--dcu-tip-bg:#ffffff;--dcu-tip-shadow:0 10px 32px rgba(31,39,36,.22);width:100%;height:100%;min-width:0;box-sizing:border-box;display:flex;flex-direction:column;overflow:hidden;background:var(--dcu-sidebar-background);color:var(--dcu-sidebar-primary);font:14px/20px var(--dcu-font)}body[data-ds-dark-theme] .dcu-root{--dcu-sidebar-background:#1d2120;--dcu-sidebar-primary:#b9bab9;--dcu-sidebar-secondary:#909191;--dcu-sidebar-tertiary:#666867;--dcu-sidebar-navigation:#b9bab9;--dcu-sidebar-icon:#afafaf;--dcu-sidebar-hover:#303432;--dcu-sidebar-border:rgba(255,255,255,.08);--dcu-tip-bg:#2a2a2a;--dcu-tip-shadow:0 10px 30px rgba(0,0,0,.28)}
5736
6348
  /* 滤镜只作用于背景,避免为设置和搜索等 fixed 后代创建侧栏包含块。 */
5737
6349
  body[data-we-sidebar-glass] .dcu-root{position:relative;background:transparent}body[data-we-sidebar-glass] .dcu-root::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;background-color:color-mix(in srgb,var(--we-sidebar-color,#fff) calc(var(--we-sidebar-alpha,.15)*.66*100%),transparent);background-image:linear-gradient(180deg,rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.14)),rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.04)) 38%,rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.01)));-webkit-backdrop-filter:blur(var(--we-sidebar-blur,16px)) saturate(var(--we-sidebar-saturate,1.8)) brightness(var(--we-glass-brightness,1.04)) contrast(1.01);backdrop-filter:blur(var(--we-sidebar-blur,16px)) saturate(var(--we-sidebar-saturate,1.8)) brightness(var(--we-glass-brightness,1.04)) contrast(1.01);box-shadow:inset 0 1px 0 rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.32)),inset 0 -1px 0 rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.08)),inset 0 0 0 .5px rgba(255,255,255,calc(var(--we-sidebar-sheen,1)*.06))}body[data-ds-dark-theme][data-we-sidebar-glass] .dcu-root::before{background-color:color-mix(in srgb,var(--we-sidebar-color,#fff) calc(var(--we-sidebar-alpha,.15)*.33*100%),transparent)}body[data-we-appwindow][data-we-sidebar-glass] .dcu-root::before{-webkit-backdrop-filter:none;backdrop-filter:none}@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){body[data-we-sidebar-glass] .dcu-root{background:#eef7f5}body[data-ds-dark-theme][data-we-sidebar-glass] .dcu-root{background:#1d2120}body[data-we-sidebar-glass] .dcu-root::before{display:none}}
5738
6350
  body[data-we-sidebar-glass] .dcu-expanded-shell,body[data-we-sidebar-glass] .dcu-compact-shell,body[data-we-sidebar-glass] .dcu-foot{position:relative}
@@ -5780,7 +6392,23 @@ body[data-we-sidebar-glass] .dcu-expanded-shell,body[data-we-sidebar-glass] .dcu
5780
6392
  .dcu-native-workspaces{flex-direction:column}.dcu-native-workspaces>[data-mcp-connector-top-mount=true]{flex:none}.dcu-root .mcpConnectorLauncher,.dcu-root [data-mcp-connector-top-mount=true]{display:none!important}
5781
6393
  .dcu-dependency-notice{margin:0 10px 8px;border:1px solid var(--dcu-sidebar-border);border-radius:8px;padding:8px;color:var(--dcu-sidebar-secondary);font-size:12px;line-height:18px}
5782
6394
  .dcu-search-scrim{position:fixed;z-index:10020;inset:0;display:flex;justify-content:center;align-items:flex-start;padding:72px 20px;background:color-mix(in srgb,#000 48%,transparent);animation:dcu-search-scrim-in 140ms ease-out}.dcu-search-dialog{width:min(560px,100%);max-height:min(640px,calc(100vh - 120px));overflow:auto;border:1px solid var(--dcu-sidebar-border);border-radius:16px;padding:10px;background:var(--dsw-specific-menu);box-shadow:var(--dsw-shadow-lv4);animation:dcu-search-dialog-in 180ms cubic-bezier(.16,1,.3,1)}@keyframes dcu-search-scrim-in{from{opacity:0}to{opacity:1}}@keyframes dcu-search-dialog-in{from{opacity:0;transform:translateY(-6px) scale(.985)}to{opacity:1}}.dcu-search-input{margin-bottom:8px}.dcu-search-section{padding:6px 0}.dcu-search-title{padding:0 8px 4px;color:var(--dcu-sidebar-tertiary);font-size:12px;font-weight:600}.dcu-search-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:12px;width:100%;min-height:34px;border:0;border-radius:8px;padding:6px 8px;background:transparent;color:var(--dcu-sidebar-primary);font:inherit;text-align:left;cursor:pointer}.dcu-search-row:hover,.dcu-search-row[data-active=true]{background:var(--dcu-sidebar-hover)}.dcu-search-main{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dcu-search-detail{max-width:160px;overflow:hidden;color:var(--dcu-sidebar-tertiary);font-size:12px;text-overflow:ellipsis;white-space:nowrap}.dcu-search-empty{padding:18px 8px;color:var(--dcu-sidebar-tertiary);font-size:13px}@media (prefers-reduced-motion:reduce){.dcu-expanded-shell,.dcu-root.dcu-compact .dcu-compact-shell,.dcu-foot,.dcu-search-scrim,.dcu-search-dialog,.dcu-extension-panel,.dcu-extension-leading svg{animation:none;transition:none}}
5783
- [data-conversation-scroll]{--dsh-composer-card-max-width:calc(var(--dsh-chat-content-width) + 32px);--dsh-composer-side-clearance:24px}[data-conversation-scroll] [data-composer-card]{min-height:96px;padding-top:10px;border-radius:16px;box-shadow:var(--dsw-shadow-lv3);transition:border-color 180ms ease,box-shadow 180ms ease}[data-conversation-scroll] [data-composer-card]:focus-within{border-color:var(--dsw-alias-button-info-fill);box-shadow:0 0 0 2px var(--dsw-static-deepseek-50),var(--dsw-shadow-lv3)}[data-conversation-scroll] [data-input-mirror]{min-height:44px}@media (prefers-reduced-motion:reduce){[data-conversation-scroll] [data-composer-card]{transition:none}}
6395
+ [data-conversation-scroll]{--dsh-composer-card-max-width:calc(var(--dsh-chat-content-width) + 32px);--dsh-composer-side-clearance:24px;--dcu-composer-bg:var(--dsw-specific-input-major,#fff);--dcu-composer-shadow:0 0 0 1px #0000000a,0 2px 8px #0000000a,0 4px 80px 8px #00000006}
6396
+ body[data-ds-dark-theme] [data-conversation-scroll]{--dcu-composer-bg:var(--dsw-alias-bg-layer-2,#242424);--dcu-composer-shadow:inset 0 0 1px #fff3}
6397
+ [data-conversation-scroll] [data-composer-card]{padding-top:8px;gap:4px;border:0;border-radius:20px;background:var(--dcu-composer-bg);box-shadow:var(--dcu-composer-shadow)}
6398
+ [data-conversation-scroll] [data-input-mirror]{min-height:44px}
6399
+ [data-conversation-scroll] [data-composer-card] [data-input-scroll]{margin-right:0}
6400
+ [data-conversation-scroll] [data-input-scroll] [data-lexical-editor=true]{min-height:44px;padding:0 12px}
6401
+ [data-conversation-scroll] [data-composer-placeholder]{inset:0 12px auto}
6402
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div{padding:0 8px 8px;gap:5px}
6403
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div>div{gap:4px}
6404
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div>div>div{gap:4px}
6405
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div :is(button,select):not([role]){min-height:28px;height:28px}
6406
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]{width:28px;transform:none;background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-base)}
6407
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div button[class$=_primary]:hover:not(:disabled){background:var(--dsw-alias-label-secondary)}
6408
+ [data-conversation-scroll] [data-composer-card]>[data-input-scroll]+div :is(button,select):focus-visible{outline:2px solid var(--dsw-alias-label-secondary);outline-offset:2px}
6409
+ @supports(corner-shape:superellipse(1.5)){[data-conversation-scroll] [data-composer-card]{border-radius:25px;corner-shape:superellipse(1.5)}}
6410
+ @media(max-width:639px){[data-conversation-scroll]{--dcu-composer-shadow:0 0 0 1px #0000000a,0 2px 8px #0000000a,0 4px 40px 8px #00000006}}
6411
+ @media(forced-colors:active){[data-conversation-scroll] [data-composer-card]{outline:1px solid CanvasText}}
5784
6412
  html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:has([data-dcu-official-turn-navigator]) .dcu-turn-navigator{display:none}
5785
6413
  [data-dcu-official-turn-navigator]{right:auto!important;left:calc(12px - (var(--dsh-composer-side-clearance) + 16px))!important}
5786
6414
  [data-dcu-official-turn-mark]{inset:0 auto 0 0!important}
@@ -6095,7 +6723,7 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6095
6723
  });
6096
6724
  });
6097
6725
  /** Codex 风格的 DSH 侧栏,只替换导航外观,项目浏览和设置仍由 DSH 官方组件提供。 */
6098
- function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces }) {
6726
+ function CodexSidebar({ collapsed, width, openSession, startSession, toggleSidebar, archiveSession, deleteSession, forkSession, moveSession, renameSession, openPath, companionSlots, renderSlot, t, useSessions, useSessionPendingInteraction, useWorkspaces, prefillNewConversation, newConversationDraft }) {
6099
6727
  const compact = collapsed || width < 80;
6100
6728
  const [visualCompact, setVisualCompact] = (0, react.useState)(compact);
6101
6729
  const [collapsing, setCollapsing] = (0, react.useState)(false);
@@ -6272,6 +6900,13 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
6272
6900
  "aria-label": t("sidebar.label"),
6273
6901
  children: [
6274
6902
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: stylesheet$3 }),
6903
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: NEW_CONVERSATION_STYLE }),
6904
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: COMPOSER_TOOL_MENU_STYLE }),
6905
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(NewConversationSuggestions, {
6906
+ t,
6907
+ prefill: prefillNewConversation,
6908
+ draftSource: newConversationDraft
6909
+ }),
6275
6910
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
6276
6911
  className: "dcu-expanded-shell",
6277
6912
  children: [
@@ -7177,9 +7812,56 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7177
7812
  /** 本插件独占的界面文案命名空间。 */
7178
7813
  const NS = "michengai.codexUi";
7179
7814
  const zh = {
7815
+ "home.resizeInput": "拖动调整输入区宽度",
7816
+ "home.projectSearch": "搜索项目",
7817
+ "home.projectEmpty": "没有匹配的项目",
7818
+ "home.suggestions": "开始一项任务",
7819
+ "home.workspace": "请先选择工作区,再选择任务。",
7820
+ "home.draft": "已保留当前草稿和附件;清空输入后可填入任务建议。",
7821
+ "home.busy": "当前输入正在处理中,请稍后再试。",
7822
+ "home.explore": "探索并理解代码",
7823
+ "home.build": "构建新功能、应用或工具",
7824
+ "home.review": "审查代码并提出修改建议",
7825
+ "home.fix": "修复问题和失败",
7826
+ "home.explore.task1": "了解项目结构",
7827
+ "home.explore.prompt1": "请探索当前工作区的代码,解释项目结构、主要入口和模块之间的关系。",
7828
+ "home.explore.task2": "理解一项功能",
7829
+ "home.explore.prompt2": "我想了解一项功能的实现。先问我具体是哪项功能,再沿调用关系解释。",
7830
+ "home.build.task1": "实现一项新功能",
7831
+ "home.build.prompt1": "我想在当前项目中实现一项新功能。先和我确认需求与验收标准,再实施。",
7832
+ "home.build.task2": "构建一个小工具",
7833
+ "home.build.prompt2": "我想构建一个小工具。先问我目标、输入和输出,再结合当前项目提出方案。",
7834
+ "home.review.task1": "评审当前改动",
7835
+ "home.review.prompt1": "请评审当前工作区的未提交改动,优先指出真实缺陷、回归风险和缺少的测试;先不要修改。",
7836
+ "home.review.task2": "检查代码质量",
7837
+ "home.review.prompt2": "请检查当前项目的代码质量,给出有源码依据的改进建议,先评估不改动。",
7838
+ "home.fix.task1": "排查一个问题",
7839
+ "home.fix.prompt1": "我遇到了一个问题。先问我复现步骤、预期和实际表现,再定位根因并修复。",
7840
+ "home.fix.task2": "修复失败的测试",
7841
+ "home.fix.prompt2": "请运行当前项目适用的测试,定位失败根因并做最小修复,保留有效的回归覆盖。",
7842
+ "host.transcript.normal": "标准",
7843
+ "host.transcript.compact": "紧凑",
7844
+ "host.command.compact": "压缩较早的对话历史",
7845
+ "host.command.export": "将当前会话日志下载为 ZIP 压缩包",
7846
+ "host.command.feedback": "记录对当前会话的反馈",
7847
+ "host.command.goal": "设置或查看长时间任务的目标",
7848
+ "host.command.permission": "切换权限预设(沙箱模式与审批策略)",
7849
+ "host.command.plan": "进入或退出计划模式",
7850
+ "usage.title": "使用统计",
7851
+ "usage.loading": "正在加载费用面板…",
7852
+ "usage.failed": "费用面板暂时无法嵌入,可重试或打开原弹窗。",
7853
+ "usage.closed": "费用面板已关闭。",
7854
+ "usage.reopen": "重新打开费用面板",
7855
+ "usage.retry": "重试",
7856
+ "usage.original": "打开原弹窗",
7180
7857
  "settings.title": "设置",
7181
7858
  "settings.back": "返回应用",
7182
7859
  "settings.openDocument": "打开配置文件",
7860
+ "settings.advanced": "高级",
7861
+ "settings.documentTitle": "配置文件",
7862
+ "settings.documentDescription": "在外部编辑器中查看和编辑配置",
7863
+ "settings.documentOpen": "打开",
7864
+ "settings.documentOpening": "打开中…",
7183
7865
  "settings.openDocumentError": "无法打开配置文件",
7184
7866
  "settings.search": "搜索设置…",
7185
7867
  "settings.personal": "个人",
@@ -7406,9 +8088,56 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7406
8088
  "meta.locale": "zh-CN"
7407
8089
  };
7408
8090
  const en = {
8091
+ "home.resizeInput": "Drag to resize the input area",
8092
+ "home.projectSearch": "Search projects",
8093
+ "home.projectEmpty": "No matching projects",
8094
+ "home.suggestions": "Start a task",
8095
+ "home.workspace": "Choose a workspace first, then select a task.",
8096
+ "home.draft": "Your draft and attachments are preserved. Clear the input to use a suggestion.",
8097
+ "home.busy": "The input is busy. Please try again shortly.",
8098
+ "home.explore": "Explore and understand code",
8099
+ "home.build": "Build features, apps, or tools",
8100
+ "home.review": "Review code and suggest changes",
8101
+ "home.fix": "Fix bugs and failures",
8102
+ "home.explore.task1": "Explain the project structure",
8103
+ "home.explore.prompt1": "Explore this workspace and explain its structure, main entry points, and module relationships.",
8104
+ "home.explore.task2": "Understand a feature",
8105
+ "home.explore.prompt2": "Help me understand a feature. First ask which feature, then explain its implementation and call flow.",
8106
+ "home.build.task1": "Implement a feature",
8107
+ "home.build.prompt1": "Help me implement a feature in this project. First clarify requirements and acceptance criteria.",
8108
+ "home.build.task2": "Build a small tool",
8109
+ "home.build.prompt2": "Help me build a small tool. First ask about its goal, inputs, and outputs, then propose an approach.",
8110
+ "home.review.task1": "Review current changes",
8111
+ "home.review.prompt1": "Review uncommitted changes for bugs, regressions, and missing tests. Do not modify files yet.",
8112
+ "home.review.task2": "Inspect code quality",
8113
+ "home.review.prompt2": "Inspect code quality in this project and suggest improvements grounded in the source. Assess only; do not edit.",
8114
+ "home.fix.task1": "Investigate a bug",
8115
+ "home.fix.prompt1": "Help me fix a bug. First ask for reproduction steps, expected behavior, and actual behavior.",
8116
+ "home.fix.task2": "Fix failing tests",
8117
+ "home.fix.prompt2": "Run the applicable project tests, identify failure causes, and make minimal fixes with meaningful regression coverage.",
8118
+ "host.transcript.normal": "Normal",
8119
+ "host.transcript.compact": "Compact",
8120
+ "host.command.compact": "Compact older conversation history",
8121
+ "host.command.export": "Download this Session log as a ZIP archive",
8122
+ "host.command.feedback": "record feedback about this session",
8123
+ "host.command.goal": "set or view the goal for a long-running task",
8124
+ "host.command.permission": "Switch the permission preset (sandbox mode + approval policy)",
8125
+ "host.command.plan": "Enter or leave plan mode",
8126
+ "usage.title": "Usage statistics",
8127
+ "usage.loading": "Loading billing dashboard…",
8128
+ "usage.failed": "The embedded dashboard is unavailable. Retry or open the original dialog.",
8129
+ "usage.closed": "The billing dashboard is closed.",
8130
+ "usage.reopen": "Reopen billing dashboard",
8131
+ "usage.retry": "Retry",
8132
+ "usage.original": "Open original dialog",
7409
8133
  "settings.title": "Settings",
7410
8134
  "settings.back": "Back to app",
7411
8135
  "settings.openDocument": "Open configuration file",
8136
+ "settings.advanced": "Advanced",
8137
+ "settings.documentTitle": "Configuration file",
8138
+ "settings.documentDescription": "View and edit configuration in an external editor",
8139
+ "settings.documentOpen": "Open",
8140
+ "settings.documentOpening": "Opening…",
7412
8141
  "settings.openDocumentError": "Could not open configuration file",
7413
8142
  "settings.search": "Search settings…",
7414
8143
  "settings.personal": "Personal",
@@ -7769,9 +8498,216 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7769
8498
  };
7770
8499
  }
7771
8500
  //#endregion
8501
+ //#region src/usage-frame/contract.ts
8502
+ /** 同源费用承载页与宿主之间的最小能力桥;不暴露 Context 或远程服务全集。 */
8503
+ const USAGE_FRAME_PATH = "/api/dsh-codex-ui/usage/frame";
8504
+ const BILLING_ENTRY_ID = "usage-billing";
8505
+ //#endregion
8506
+ //#region src/client/UsageStatisticsSection.tsx
8507
+ /** 设置中的费用原面板承载区;不重建图表、计费或原面板的业务逻辑。 */
8508
+ function UsageStatisticsSection({ useStore, actions, billing, close, openOriginal, t }) {
8509
+ const snapshot = useStore((state) => state);
8510
+ const latest = (0, react.useRef)(snapshot);
8511
+ const listeners = (0, react.useRef)(/* @__PURE__ */ new Set());
8512
+ const frame = (0, react.useRef)(null);
8513
+ const [attempt, setAttempt] = (0, react.useState)(0);
8514
+ const [state, setState] = (0, react.useState)("loading");
8515
+ const disposeTheme = (0, react.useRef)(() => {});
8516
+ const timer = (0, react.useRef)(void 0);
8517
+ (0, react.useEffect)(() => {
8518
+ latest.current = snapshot;
8519
+ listeners.current.forEach((listener) => listener());
8520
+ }, [snapshot]);
8521
+ (0, react.useEffect)(() => {
8522
+ setState("loading");
8523
+ timer.current = setTimeout(() => {
8524
+ setState("failed");
8525
+ }, 15e3);
8526
+ return () => {
8527
+ clearTimeout(timer.current);
8528
+ disposeTheme.current();
8529
+ listeners.current.clear();
8530
+ };
8531
+ }, [attempt]);
8532
+ (0, react.useEffect)(() => {
8533
+ if ((state === "closed" || state === "failed") && document.activeElement === frame.current) frame.current?.parentElement?.querySelector("button")?.focus();
8534
+ }, [state]);
8535
+ const connect = () => {
8536
+ const target = frame.current?.contentWindow;
8537
+ if (!target) return;
8538
+ try {
8539
+ if (target.location.origin !== location.origin || target.location.pathname !== "/api/dsh-codex-ui/usage/frame") throw new Error("费用承载页地址不匹配");
8540
+ const document = target.document;
8541
+ if (!target.dcuUsageRuntimeReady || !document.getElementById("billing-root")) throw new Error("费用承载页未正确加载");
8542
+ const sync = () => {
8543
+ document.body.toggleAttribute("data-ds-dark-theme", window.document.body.hasAttribute("data-ds-dark-theme"));
8544
+ document.documentElement.lang = window.document.documentElement.lang;
8545
+ const tokens = getComputedStyle(window.document.body);
8546
+ for (const key of tokens) if (key.startsWith("--dsw-")) document.body.style.setProperty(key, tokens.getPropertyValue(key));
8547
+ };
8548
+ sync();
8549
+ disposeTheme.current();
8550
+ const observer = new MutationObserver(sync);
8551
+ observer.observe(window.document.body, {
8552
+ attributes: true,
8553
+ attributeFilter: [
8554
+ "data-ds-dark-theme",
8555
+ "class",
8556
+ "style"
8557
+ ]
8558
+ });
8559
+ disposeTheme.current = () => observer.disconnect();
8560
+ target.dcuUsageHost = {
8561
+ getSnapshot: () => latest.current,
8562
+ subscribe: (listener) => {
8563
+ listeners.current.add(listener);
8564
+ return () => {
8565
+ listeners.current.delete(listener);
8566
+ };
8567
+ },
8568
+ actions,
8569
+ ...billing,
8570
+ close,
8571
+ dismissed: () => {
8572
+ clearTimeout(timer.current);
8573
+ setState((current) => current === "failed" ? current : "closed");
8574
+ },
8575
+ focusOutside: (backward) => {
8576
+ const page = frame.current?.closest("[data-dcu-settings-page]");
8577
+ if (!page || !frame.current) return;
8578
+ const controls = [...page.querySelectorAll("button,input,select,textarea,a[href],[tabindex]")].filter((element) => element.tabIndex >= 0 && !element.matches(":disabled") && !element.closest("[inert]") && element.getClientRects().length > 0);
8579
+ controls[(controls.indexOf(frame.current) + (backward ? -1 : 1) + controls.length) % controls.length]?.focus();
8580
+ },
8581
+ ready: () => {
8582
+ clearTimeout(timer.current);
8583
+ setState((current) => current === "failed" ? current : "ready");
8584
+ },
8585
+ failed: (message) => {
8586
+ console.warn("[michengai-codex-ui] 费用承载失败:%s", message);
8587
+ clearTimeout(timer.current);
8588
+ setState("failed");
8589
+ }
8590
+ };
8591
+ target.postMessage({ type: "dcu-usage-init" }, location.origin);
8592
+ } catch (error) {
8593
+ console.warn("[michengai-codex-ui] 无法连接费用承载页", error);
8594
+ clearTimeout(timer.current);
8595
+ setState("failed");
8596
+ }
8597
+ };
8598
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
8599
+ className: "dcu-usage-section",
8600
+ "aria-label": t("usage.title"),
8601
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", { children: t("usage.title") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8602
+ className: "dcu-usage-stage",
8603
+ "aria-busy": state === "loading",
8604
+ children: [
8605
+ state === "loading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
8606
+ className: "dcu-usage-loading",
8607
+ role: "status",
8608
+ children: t("usage.loading")
8609
+ }),
8610
+ state === "closed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8611
+ role: "status",
8612
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("usage.closed") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8613
+ onClick: () => setAttempt((value) => value + 1),
8614
+ children: t("usage.reopen")
8615
+ })]
8616
+ }),
8617
+ state === "failed" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8618
+ role: "alert",
8619
+ children: [
8620
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("usage.failed") }),
8621
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8622
+ onClick: () => {
8623
+ setAttempt((value) => value + 1);
8624
+ },
8625
+ children: t("usage.retry")
8626
+ }),
8627
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8628
+ onClick: () => {
8629
+ close();
8630
+ requestAnimationFrame(openOriginal);
8631
+ },
8632
+ children: t("usage.original")
8633
+ })
8634
+ ]
8635
+ }),
8636
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
8637
+ ref: frame,
8638
+ title: t("usage.title"),
8639
+ src: USAGE_FRAME_PATH,
8640
+ onLoad: connect,
8641
+ "aria-hidden": state !== "ready",
8642
+ tabIndex: state === "ready" ? 0 : -1,
8643
+ style: { visibility: state === "ready" ? "visible" : "hidden" },
8644
+ className: "dcu-usage-frame"
8645
+ }, attempt)
8646
+ ]
8647
+ })]
8648
+ });
8649
+ }
8650
+ //#endregion
8651
+ //#region src/client/usage-statistics.ts
8652
+ function registerUsageStatistics(ctx) {
8653
+ const t = ctx.locale.bind(NS);
8654
+ ctx.slots.inject("settings.section", () => {
8655
+ let current;
8656
+ let remove;
8657
+ const refresh = () => {
8658
+ const entry = ctx.slots.entriesOfSlot("sidebar.footer.action").find((item) => item.options.id === BILLING_ENTRY_ID);
8659
+ if (entry === current) return;
8660
+ remove?.();
8661
+ remove = void 0;
8662
+ current = entry;
8663
+ if (!entry?.store || typeof entry.store === "function" || !entry.locale || !entry.inject) return;
8664
+ const face = entry.inject();
8665
+ if (typeof face.checkModels !== "function" || typeof face.publishCosts !== "function") return;
8666
+ const billing = {
8667
+ translate: ctx.locale.bind(entry.locale),
8668
+ checkModels: face.checkModels,
8669
+ publishCosts: face.publishCosts
8670
+ };
8671
+ remove = ctx.slots.register({
8672
+ name: "settings.section",
8673
+ id: "usage-statistics",
8674
+ order: 90,
8675
+ label: () => t("usage.title"),
8676
+ locale: NS,
8677
+ store: entry.store,
8678
+ inject: () => ({
8679
+ billing,
8680
+ openOriginal: () => {
8681
+ ctx.get("billingMetrics")?.openDashboard?.();
8682
+ }
8683
+ })
8684
+ }, UsageStatisticsSection);
8685
+ };
8686
+ const unsubscribe = ctx.slots.subscribe("sidebar.footer.action", refresh);
8687
+ refresh();
8688
+ return () => {
8689
+ unsubscribe();
8690
+ remove?.();
8691
+ };
8692
+ });
8693
+ ctx.effect(() => {
8694
+ const onClick = (event) => {
8695
+ if (!(event.target instanceof Element) || !event.target.closest(".dcu-footer-actions [data-testid=\"billing-trigger\"],.dcu-footer-actions [data-testid=\"billing-rail-button\"]")) return;
8696
+ if (!ctx.slots.entriesOfSlot("settings.section").some((entry) => entry.options.id === "usage-statistics")) return;
8697
+ const seat = document.querySelector(".dcu-settings-seat");
8698
+ if (!seat?.querySelector("[data-dcu-settings-trigger]")) return;
8699
+ event.preventDefault();
8700
+ event.stopPropagation();
8701
+ openSettingsSection(seat, t("usage.title"));
8702
+ };
8703
+ document.addEventListener("click", onClick, true);
8704
+ return () => document.removeEventListener("click", onClick, true);
8705
+ }, "michengai-codex-ui: usage navigation");
8706
+ }
8707
+ //#endregion
7772
8708
  //#region src/client/settings-page-model.ts
7773
8709
  function settingsGroup(id) {
7774
- if (/archive|about/.test(id)) return "records";
8710
+ if (/archive|about|^usage-statistics$/.test(id)) return "records";
7775
8711
  if (/^(general|appearance|theme|language|shortcuts|voice|account)$/.test(id)) return "personal";
7776
8712
  return "integrations";
7777
8713
  }
@@ -7788,14 +8724,15 @@ html[data-dcu-official-turn-navigator-supported=true] .dcu-turn-navigator,html:h
7788
8724
  //#region src/client/settings-page-styles.ts
7789
8725
  /** Codex 设置页的局部 tokens 与布局,不覆盖宿主其他弹窗。 */
7790
8726
  const settingsPageStyles = `
7791
- .dcu-settings-page{--sp-bg:#fff;--sp-nav:#f5f5f5;--sp-card:#fafafa;--sp-border:#e5e5e5;--sp-text:#303030;--sp-muted:#737373;--sp-hover:#e9e9e9;--sp-active:#e4e4e4;position:fixed;inset:0;z-index:1000;display:grid;grid-template-columns:240px minmax(0,1fr);background:var(--sp-bg);color:var(--sp-text);font:14px/1.5 var(--dcu-font,system-ui);text-align:left;isolation:isolate}
7792
- body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--sp-card:#232323;--sp-border:#333;--sp-text:#dedede;--sp-muted:#a1a1a1;--sp-hover:#292c2b;--sp-active:#303332;color-scheme:dark}
8727
+ .dcu-settings-page{--sp-bg:#fff;--sp-nav:var(--dcu-sidebar-background,#eef7f5);--sp-card:#fafafa;--sp-border:#e5e5e5;--sp-text:#303030;--sp-muted:#737373;--sp-hover:#e9e9e9;--sp-active:#e4e4e4;position:fixed;inset:0;z-index:1000;display:grid;grid-template-columns:clamp(240px,var(--dcu-sidebar-expanded-width,275px),min(520px,calc(100vw - 320px))) minmax(0,1fr);background:var(--sp-bg);color:var(--sp-text);font:14px/1.5 var(--dcu-font,system-ui);text-align:left;isolation:isolate}
8728
+ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:var(--dcu-sidebar-background,#1d2120);--sp-card:#232323;--sp-border:#333;--sp-text:#dedede;--sp-muted:#a1a1a1;--sp-hover:#292c2b;--sp-active:#303332;color-scheme:dark}
7793
8729
  .dcu-settings-page *{box-sizing:border-box}
7794
8730
  .dcu-settings-page button,.dcu-settings-page input{font:inherit}
7795
8731
  .dcu-settings-page button{cursor:pointer}
7796
8732
  .dcu-settings-page :focus-visible{outline:2px solid #459cff;outline-offset:3px}
7797
- .dcu-settings-nav{display:flex;flex-direction:column;min-height:0;padding:18px 8px;background:var(--sp-nav);border-right:1px solid var(--sp-border);overflow-y:auto}
7798
- .dcu-settings-back{display:flex;align-items:center;gap:8px;width:100%;padding:8px;border:0;border-radius:7px;background:transparent;color:var(--sp-text);text-align:left}
8733
+ .dcu-settings-nav{--sp-text:var(--dcu-sidebar-navigation,#4e5253);--sp-muted:var(--dcu-sidebar-secondary,#676b6c);--sp-hover:var(--dcu-sidebar-hover,#dfe8e5);--sp-active:var(--dcu-sidebar-hover,#dfe8e5);--sp-border:var(--dcu-sidebar-border,rgba(37,46,41,.10));display:flex;flex-direction:column;min-height:0;padding:18px 8px;background:var(--sp-nav);box-shadow:inset -1px 0 var(--sp-border);overflow-y:auto}
8734
+ body[data-ds-dark-theme] .dcu-settings-nav{--sp-text:var(--dcu-sidebar-navigation,#b9bab9);--sp-muted:var(--dcu-sidebar-secondary,#909191);--sp-hover:var(--dcu-sidebar-hover,#303432);--sp-active:var(--dcu-sidebar-hover,#303432);--sp-border:var(--dcu-sidebar-border,rgba(255,255,255,.08))}
8735
+ .dcu-settings-back{display:flex;align-items:center;flex-shrink:0;gap:8px;width:100%;height:30px;padding:5px 8px;border:0;border-radius:10px;background:transparent;color:var(--sp-text);text-align:left}
7799
8736
  .dcu-settings-back:hover,.dcu-settings-link:hover{background:var(--sp-hover)}
7800
8737
  .dcu-settings-search{display:flex;align-items:center;gap:8px;padding:5px 9px;margin:12px 0 18px;background:var(--sp-hover);border:1px solid transparent;border-radius:8px;color:var(--sp-muted)}
7801
8738
  .dcu-settings-search:focus-within{border-color:#459cff}
@@ -7803,17 +8740,22 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7803
8740
  .dcu-settings-search input[type=search]{appearance:none;padding:0;border-radius:0;box-shadow:none;line-height:20px}
7804
8741
  .dcu-settings-search input:focus,.dcu-settings-search input:focus-visible{outline:none;box-shadow:none}
7805
8742
  .dcu-settings-search input::placeholder{color:var(--sp-muted)}
7806
- .dcu-settings-group{margin:0 0 22px}
7807
- .dcu-settings-group-label{margin:0 8px 6px;color:var(--sp-muted);font-size:12px;font-weight:500}
7808
- .dcu-settings-link{display:flex;align-items:center;gap:9px;min-height:32px;width:100%;padding:5px 9px;border:0;border-radius:8px;background:transparent;color:var(--sp-text);text-align:left;font-size:14px!important}
8743
+ .dcu-settings-group{flex-shrink:0;margin:0 0 16px}
8744
+ .dcu-settings-group-label{margin:0 8px 4px;color:var(--sp-muted);font-size:12px;font-weight:500}
8745
+ .dcu-settings-link{display:flex;align-items:center;gap:8px;height:30px;min-height:30px;min-width:0;width:100%;padding:5px 8px;border:0;border-radius:10px;overflow:hidden;background:transparent;color:var(--sp-text);text-align:left;font-size:14px!important}
8746
+ /* Codex Desktop SidebarItem / SidebarSection:30px 行高、1px 行距、内收焦点圈。 */
8747
+ .dcu-settings-link+.dcu-settings-link{margin-top:1px}
8748
+ .dcu-settings-back:focus-visible,.dcu-settings-link:focus-visible{outline-offset:-2px}
8749
+ @supports(corner-shape:superellipse(1.5)){.dcu-settings-back,.dcu-settings-link{border-radius:12.5px;corner-shape:superellipse(1.5)}}
7809
8750
  .dcu-settings-link[aria-current=page]{background:var(--sp-active)}
7810
- .dcu-settings-link svg{flex:none;opacity:.9}
8751
+ .dcu-settings-link svg{flex:none;color:var(--dcu-sidebar-icon,var(--sp-text));opacity:1}
7811
8752
  .dcu-settings-link span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
7812
8753
  .dcu-settings-empty{padding:8px;color:var(--sp-muted);font-size:13px}
7813
8754
  .dcu-settings-main{min-width:0;min-height:0;overflow:auto;overscroll-behavior:contain;background:var(--sp-bg);scrollbar-width:thin;scrollbar-color:var(--sp-border) transparent}
7814
- .dcu-settings-inner{width:min(100%,864px);margin:0 auto;padding:32px 48px}
8755
+ .dcu-settings-inner{width:min(100%,864px);margin:0 auto;padding:48px 48px}
7815
8756
  .dcu-settings-heading{display:flex;align-items:center;justify-content:space-between;gap:24px;margin-bottom:24px}
7816
- .dcu-settings-heading h1{margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px}
8757
+ .dcu-settings-heading h1,.dcu-settings-inner:is([data-settings-section=models],[data-settings-section=plugins],[data-settings-section=agent-presets]) [class$="_section"]>h2:is([class$="_title"],[class$="_heading"]){margin:0;font-size:24px;line-height:32px;font-weight:600;letter-spacing:-.4px}
8758
+ .dcu-settings-inner:is([data-settings-section=models],[data-settings-section=plugins],[data-settings-section=agent-presets]) [class$="_section"]>p[class$="_intro"]{margin:0;font-size:14px;line-height:22px}
7817
8759
  .dcu-settings-heading[data-own-title=false]{justify-content:flex-end;margin-bottom:16px}
7818
8760
  .dcu-settings-heading:not(:has(h1,button,a,[role=button])){display:none}
7819
8761
  .dcu-settings-actions{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-end;color:var(--sp-muted)}
@@ -7826,6 +8768,13 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7826
8768
  .dcu-settings-row>[data-slot]>*{padding:12px 0!important;border-bottom:0!important;margin:0!important;min-width:0}
7827
8769
  .dcu-settings-row button{font-size:13px;border-radius:8px}
7828
8770
  .dcu-settings-row input{max-width:100%}
8771
+ .dcu-settings-document{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:16px 0;font-size:14px;line-height:20px}
8772
+ .dcu-settings-document-copy{min-width:0}
8773
+ .dcu-settings-document p{margin:4px 0 0;font-size:12px;color:var(--sp-muted);overflow-wrap:anywhere}
8774
+ .dcu-settings-document button{flex:none;min-height:36px;padding:8px 16px;border:0;border-radius:8px;background:var(--sp-hover);color:var(--sp-text);font:inherit;font-size:13px;cursor:pointer;transition:background .15s}
8775
+ .dcu-settings-document button:hover:not(:disabled){background:color-mix(in srgb,var(--sp-text) 14%,transparent)}
8776
+ .dcu-settings-document button:focus-visible{outline:2px solid var(--sp-muted);outline-offset:3px}
8777
+ .dcu-settings-document button:disabled{opacity:.55;cursor:wait}
7829
8778
  .dcu-settings-trigger{appearance:none;box-sizing:border-box;display:flex;align-items:center;border:0;border-radius:8px;background:transparent;color:var(--dcu-sidebar-navigation,inherit);height:36px;min-height:36px;padding:0 4px;width:100%;font:400 14px/20px var(--dcu-font,system-ui);text-align:left;cursor:pointer;transition:background-color 160ms ease,color 160ms ease,transform 120ms ease}
7830
8779
  .dcu-settings-trigger-content{display:grid;grid-template-columns:20px minmax(0,1fr);column-gap:8px;align-items:center;width:100%;min-width:0}
7831
8780
  .dcu-settings-trigger-content svg{display:block;width:16px;height:16px;color:var(--dcu-sidebar-icon,currentColor);transition:transform 220ms cubic-bezier(.16,1,.3,1)}
@@ -7842,6 +8791,24 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7842
8791
  @keyframes dcu-settings-enter{from{opacity:0}to{opacity:1}}
7843
8792
  @keyframes dcu-settings-nav-enter{from{opacity:0;transform:translateX(-6px)}to{opacity:1;transform:none}}
7844
8793
  @keyframes dcu-settings-content-enter{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
8794
+ /* 只有 Desktop 明确提供系统背景材质时才贯通透明层,普通浏览器保持实色。 */
8795
+ html[data-dsh-native-backdrop=mica]:has(.dcu-root),html[data-dsh-native-backdrop=mica]:has(.dcu-root) body,html[data-dsh-native-backdrop=mica] #root,html[data-dsh-native-backdrop=mica] #root>[data-slot=root],html[data-dsh-native-backdrop=mica] #root>[data-slot=root]>div{background:transparent!important}
8796
+ html[data-dsh-native-backdrop=mica] #root>[data-slot=root]>div>div:has(>[data-slot=sidebar]){background:transparent!important}
8797
+ html[data-dsh-native-backdrop=mica] #root :is([class$="_centerCol"],[class$="_detailsCol"]){background:var(--dsw-alias-bg-base,#fff)}
8798
+ html[data-dsh-native-backdrop=mica] :is(.dcu-root,.dcu-settings-nav){background:rgba(255,255,255,.18)}
8799
+ html[data-dsh-native-backdrop=mica] body[data-ds-dark-theme] :is(.dcu-root,.dcu-settings-nav){background:rgba(20,23,22,.18)}
8800
+ html[data-dsh-native-backdrop=mica] .dcu-root:has(.dcu-settings-page) [inert]{visibility:hidden}
8801
+ html[data-dsh-native-backdrop=mica] .dcu-settings-page,html[data-dsh-native-backdrop=mica] .dcu-root:has(.dcu-settings-page){background:transparent}
8802
+
8803
+ .dcu-settings-inner:has(.dcu-usage-section){width:100%;height:100%;max-width:1280px;display:flex;flex-direction:column;padding-bottom:0}
8804
+ .dcu-settings-inner:has(.dcu-usage-section)>.dcu-settings-heading{display:none}
8805
+ .dcu-settings-inner:has(.dcu-usage-section)>[data-slot="settings.section"]{display:flex;flex:1;min-height:0;flex-direction:column}
8806
+ .dcu-usage-section{display:flex;flex-direction:column;flex:1;min-height:0;gap:16px}
8807
+ .dcu-usage-section h1{font-size:24px;font-weight:500;margin:0}
8808
+ .dcu-usage-section p{color:var(--sp-muted)}
8809
+ .dcu-usage-stage{position:relative;flex:1;min-height:420px;background:var(--sp-bg)}
8810
+ .dcu-usage-loading{position:absolute;inset:0;display:grid;place-items:center;margin:0}
8811
+ .dcu-usage-frame{position:absolute;inset:0;display:block;width:100%;height:100%;border:0;background:var(--sp-bg)}
7845
8812
  @media(prefers-reduced-motion:reduce){.dcu-settings-trigger,.dcu-settings-trigger-content svg,.dcu-settings-back,.dcu-settings-link{transition:none}.dcu-settings-trigger:hover svg,.dcu-settings-trigger:active{transform:none}.dcu-settings-page,.dcu-settings-nav,.dcu-settings-inner{animation:none}}
7846
8813
  .dcu-settings-page [data-slot="settings.section"]{min-width:0}
7847
8814
  .dcu-settings-inner:has(.dcu-connector-frame){height:100%;display:flex;flex-direction:column}
@@ -7849,8 +8816,8 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7849
8816
  .dcu-settings-page .dcu-connectors:has(>.dcu-connector-frame){display:flex;flex-direction:column;flex:1 1 0;min-height:0}
7850
8817
  .dcu-settings-page .dcu-connector-frame{flex:1 1 0;min-height:0;height:100%}
7851
8818
 
7852
- @media(max-width:900px){.dcu-settings-page{grid-template-columns:200px minmax(0,1fr)}.dcu-settings-inner{padding:24px 28px}.dcu-settings-heading{align-items:flex-start;flex-direction:column;gap:12px}}
7853
- @media(max-width:600px){.dcu-settings-page{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr)}.dcu-settings-nav{padding:8px 12px;max-height:220px;border-right:0;border-bottom:1px solid var(--sp-border)}.dcu-settings-search{margin:6px 0}.dcu-settings-groups{display:flex;gap:8px;overflow-x:auto;flex:none}.dcu-settings-group{display:flex;gap:4px;margin:0;flex:none}.dcu-settings-group-label{display:none}.dcu-settings-link{width:auto;min-height:40px;flex:none}.dcu-settings-inner{padding:24px 16px}.dcu-settings-heading{margin-bottom:28px}.dcu-settings-heading h1{font-size:22px}.dcu-settings-card{padding:0 12px}.dcu-settings-row>[data-slot]>*{flex-wrap:wrap;gap:12px!important}.dcu-settings-general-group{margin-bottom:32px}}
8819
+ @media(max-width:900px){.dcu-settings-inner{padding:32px 28px}.dcu-settings-heading{align-items:flex-start;flex-direction:column;gap:12px}}
8820
+ @media(max-width:600px){.dcu-settings-page{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr)}.dcu-settings-nav{padding:8px 12px;max-height:220px;border-right:0;border-bottom:1px solid var(--sp-border)}.dcu-settings-search{margin:6px 0}.dcu-settings-groups{display:flex;gap:8px;overflow-x:auto;flex:none}.dcu-settings-group{display:flex;gap:4px;margin:0;flex:none}.dcu-settings-group-label{display:none}.dcu-settings-link{width:auto;min-height:40px;flex:none}.dcu-settings-link+.dcu-settings-link{margin-top:0}.dcu-settings-inner{padding:32px 16px}.dcu-settings-heading{margin-bottom:28px}.dcu-settings-heading h1,.dcu-settings-inner:is([data-settings-section=models],[data-settings-section=plugins],[data-settings-section=agent-presets]) [class$="_section"]>h2:is([class$="_title"],[class$="_heading"]){font-size:22px}.dcu-settings-card{padding:0 12px}.dcu-settings-row>[data-slot]>*{flex-wrap:wrap;gap:12px!important}.dcu-settings-general-group{margin-bottom:32px}}
7854
8821
  `;
7855
8822
  //#endregion
7856
8823
  //#region src/client/settings-focus.ts
@@ -7876,6 +8843,7 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7876
8843
  editor: "settings.editor"
7877
8844
  };
7878
8845
  function sectionIcon(id) {
8846
+ if (id === "usage-statistics") return ChartColumn;
7879
8847
  if (id === "market" || id === "plugin-marketplace") return Store;
7880
8848
  if (id === "better-sidebar" || id === "sidebar-cards") return PanelRight;
7881
8849
  if (/model/.test(id)) return Cpu;
@@ -7937,6 +8905,24 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
7937
8905
  setActiveId(id);
7938
8906
  setOpen(true);
7939
8907
  }, []);
8908
+ (0, react.useEffect)(() => {
8909
+ const element = trigger.current;
8910
+ const navigate = (event) => {
8911
+ const labels = event.detail?.labels;
8912
+ if (!Array.isArray(labels)) return;
8913
+ const row = labels.flatMap((label) => rows.filter((item) => (item.id === "general" ? t("settings.general") : item.label) === label))[0];
8914
+ if (!row) return;
8915
+ event.preventDefault();
8916
+ setQuery("");
8917
+ openSection(row.id);
8918
+ };
8919
+ element?.addEventListener(SETTINGS_OPEN_SECTION_EVENT, navigate);
8920
+ return () => element?.removeEventListener(SETTINGS_OPEN_SECTION_EVENT, navigate);
8921
+ }, [
8922
+ rows,
8923
+ t,
8924
+ openSection
8925
+ ]);
7940
8926
  (0, react.useEffect)(() => () => {
7941
8927
  exitAnimation.current?.cancel();
7942
8928
  }, []);
@@ -8031,7 +9017,7 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8031
9017
  "aria-expanded": open,
8032
9018
  "aria-label": t("settings.title"),
8033
9019
  onClick: () => {
8034
- setOpen(true);
9020
+ openSection("general");
8035
9021
  },
8036
9022
  children: renderSlot("settings.trigger", { wide })
8037
9023
  }),
@@ -8126,6 +9112,7 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8126
9112
  className: "dcu-settings-main",
8127
9113
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8128
9114
  className: "dcu-settings-inner",
9115
+ "data-settings-section": active?.id,
8129
9116
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
8130
9117
  className: "dcu-settings-heading",
8131
9118
  "data-own-title": active?.id === "general",
@@ -8153,9 +9140,9 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8153
9140
  /** 每条偏好仍由原插件渲染和保存,只为公共条目添加可扩展的分组容器。 */
8154
9141
  function CodexGeneralSettings({ items, renderSlot, t }) {
8155
9142
  const rows = (0, react.useSyncExternalStore)(items.subscribe, items.getSnapshot);
8156
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9143
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
8157
9144
  className: "dcu-settings-general",
8158
- children: [
9145
+ children: [[
8159
9146
  "permissions",
8160
9147
  "general",
8161
9148
  "editor"
@@ -8167,11 +9154,12 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8167
9154
  className: "dcu-settings-card",
8168
9155
  children: entries.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
8169
9156
  className: "dcu-settings-row",
9157
+ "data-dcu-settings-item": row.id,
8170
9158
  children: renderSlot("settings.general.item", {}, { only: row.id })
8171
9159
  }, row.id))
8172
9160
  })]
8173
9161
  }, group);
8174
- })
9162
+ }), renderSlot("settings.general.footer", {})]
8175
9163
  });
8176
9164
  }
8177
9165
  //#endregion
@@ -8210,17 +9198,35 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8210
9198
  setOpening(false);
8211
9199
  }
8212
9200
  };
8213
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
8214
- role: "alert",
8215
- children: t("settings.openDocumentError")
8216
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
8217
- type: "button",
8218
- disabled: opening,
8219
- onClick: () => {
8220
- open();
8221
- },
8222
- children: t("settings.openDocument")
8223
- })] });
9201
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
9202
+ className: "dcu-settings-general-group",
9203
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", { children: t("settings.advanced") }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
9204
+ className: "dcu-settings-card",
9205
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9206
+ className: "dcu-settings-document",
9207
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
9208
+ className: "dcu-settings-document-copy",
9209
+ children: [
9210
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: t("settings.documentTitle") }),
9211
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: t("settings.documentDescription") }),
9212
+ error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
9213
+ role: "alert",
9214
+ children: t("settings.openDocumentError")
9215
+ })
9216
+ ]
9217
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
9218
+ type: "button",
9219
+ "aria-label": t("settings.openDocument"),
9220
+ "aria-busy": opening,
9221
+ disabled: opening,
9222
+ onClick: () => {
9223
+ open();
9224
+ },
9225
+ children: t(opening ? "settings.documentOpening" : "settings.documentOpen")
9226
+ })]
9227
+ })
9228
+ })]
9229
+ });
8224
9230
  }
8225
9231
  //#endregion
8226
9232
  //#region src/client/settings-page-registration.ts
@@ -8288,8 +9294,8 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8288
9294
  const remote = settingsCtx.get("remote");
8289
9295
  if (!remote.$host.isLoopback) return;
8290
9296
  const describe = settingsCtx.settingsScope.describe();
8291
- settingsCtx.slots.inject("settings.action", () => !owned ? () => {} : settingsCtx.slots.register({
8292
- name: "settings.action",
9297
+ settingsCtx.slots.inject("settings.general.footer", () => !owned ? () => {} : settingsCtx.slots.register({
9298
+ name: "settings.general.footer",
8293
9299
  id: "open-document",
8294
9300
  locale: NS,
8295
9301
  inject: () => ({
@@ -8355,10 +9361,16 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8355
9361
  order: 0,
8356
9362
  locale: NS,
8357
9363
  label: () => t("settings.general"),
8358
- children: { "settings.general.item": {
8359
- kind: "list",
8360
- scope: "root"
8361
- } },
9364
+ children: {
9365
+ "settings.general.item": {
9366
+ kind: "list",
9367
+ scope: "root"
9368
+ },
9369
+ "settings.general.footer": {
9370
+ kind: "list",
9371
+ scope: "root"
9372
+ }
9373
+ },
8362
9374
  inject: () => ({ items })
8363
9375
  }, CodexGeneralSettings));
8364
9376
  }
@@ -8482,6 +9494,105 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
8482
9494
  };
8483
9495
  }
8484
9496
  //#endregion
9497
+ //#region src/client/host-copy.ts
9498
+ const commands = {
9499
+ compact: ["Compact older conversation history", "host.command.compact"],
9500
+ export: ["Download this Session log as a ZIP archive", "host.command.export"],
9501
+ feedback: ["record feedback about this session", "host.command.feedback"],
9502
+ goal: ["set or view the goal for a long-running task", "host.command.goal"],
9503
+ permission: ["Switch the permission preset (sandbox mode + approval policy)", "host.command.permission"],
9504
+ plan: ["Enter or leave plan mode", "host.command.plan"]
9505
+ };
9506
+ const transcript = {
9507
+ Normal: "host.transcript.normal",
9508
+ Compact: "host.transcript.compact"
9509
+ };
9510
+ /** 只补译已核对的宿主控件文本;保留原 Text 节点、事件和业务状态。 */
9511
+ function observeHostCopy(locale, t) {
9512
+ const owned = /* @__PURE__ */ new Map();
9513
+ const replace = (element, original, key) => {
9514
+ const walker = document.createTreeWalker(element, NodeFilter.SHOW_TEXT);
9515
+ let node;
9516
+ while ((node = walker.nextNode()) !== null) {
9517
+ if (node.nodeValue?.trim() !== original) continue;
9518
+ const text = node;
9519
+ const rendered = text.data.replace(original, t(key));
9520
+ owned.set(text, {
9521
+ original: text.data,
9522
+ rendered,
9523
+ key
9524
+ });
9525
+ if (text.data !== rendered) text.data = rendered;
9526
+ }
9527
+ };
9528
+ const apply = () => {
9529
+ for (const [node, state] of owned) {
9530
+ if (!node.isConnected || node.data !== state.rendered) {
9531
+ owned.delete(node);
9532
+ continue;
9533
+ }
9534
+ const next = state.original.replace(state.original.trim(), t(state.key));
9535
+ if (node.data !== next) node.data = next;
9536
+ state.rendered = next;
9537
+ }
9538
+ const selector = document.querySelector("[data-dcu-settings-item=\"transcript-view\"] button[aria-haspopup=\"menu\"]");
9539
+ if (selector) {
9540
+ for (const [original, key] of Object.entries(transcript)) replace(selector, original, key);
9541
+ if (selector.getAttribute("aria-expanded") === "true") for (const menu of document.querySelectorAll("[role=\"menu\"]")) {
9542
+ const items = [...menu.querySelectorAll("[role=\"menuitem\"],[role=\"menuitemradio\"]")];
9543
+ const labels = items.map((item) => item.textContent?.trim());
9544
+ if (items.length !== 2 || !["Normal", t("host.transcript.normal")].some((label) => labels.includes(label)) || !["Compact", t("host.transcript.compact")].some((label) => labels.includes(label))) continue;
9545
+ for (const item of items) for (const [original, key] of Object.entries(transcript)) replace(item, original, key);
9546
+ }
9547
+ }
9548
+ for (const option of document.querySelectorAll("[data-trigger-menu] button[role=\"option\"]")) {
9549
+ const spans = [...option.children].filter((child) => child.tagName === "SPAN" && child.getAttribute("aria-hidden") !== "true");
9550
+ const name = spans[0]?.textContent?.trim();
9551
+ if (!name || !Object.hasOwn(commands, name) || !spans[1]) continue;
9552
+ const [original, key] = commands[name];
9553
+ replace(spans[1], original, key);
9554
+ }
9555
+ };
9556
+ const scope = "[data-trigger-menu],[data-dcu-settings-item=\"transcript-view\"],[role=\"menu\"]";
9557
+ const roots = /* @__PURE__ */ new Map();
9558
+ const discover = () => {
9559
+ for (const [element, observer] of roots) if (!element.isConnected) {
9560
+ observer.disconnect();
9561
+ roots.delete(element);
9562
+ }
9563
+ for (const element of document.querySelectorAll(scope)) {
9564
+ if (roots.has(element)) continue;
9565
+ const observer = new MutationObserver(apply);
9566
+ observer.observe(element, {
9567
+ subtree: true,
9568
+ childList: true,
9569
+ characterData: true,
9570
+ attributes: true,
9571
+ attributeFilter: ["aria-expanded"]
9572
+ });
9573
+ roots.set(element, observer);
9574
+ }
9575
+ apply();
9576
+ };
9577
+ const observer = new MutationObserver((records) => {
9578
+ if (records.some((record) => [...record.addedNodes, ...record.removedNodes].some((node) => node instanceof Element && (node.matches(scope) || node.querySelector(scope) !== null)))) discover();
9579
+ });
9580
+ discover();
9581
+ observer.observe(document.body, {
9582
+ subtree: true,
9583
+ childList: true
9584
+ });
9585
+ const unsubscribe = locale.subscribe(apply);
9586
+ return () => {
9587
+ observer.disconnect();
9588
+ roots.forEach((observer) => observer.disconnect());
9589
+ roots.clear();
9590
+ unsubscribe();
9591
+ for (const [node, state] of owned) if (node.data === state.rendered) node.data = state.original;
9592
+ owned.clear();
9593
+ };
9594
+ }
9595
+ //#endregion
8485
9596
  //#region src/client/official-turn-navigator.ts
8486
9597
  const OFFICIAL_TURN_NAVIGATOR_ATTRIBUTE = "data-dcu-official-turn-navigator";
8487
9598
  const OFFICIAL_TURN_MARK_ATTRIBUTE = "data-dcu-official-turn-mark";
@@ -9089,6 +10200,42 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
9089
10200
  }, InputHistoryHint));
9090
10201
  }
9091
10202
  //#endregion
10203
+ //#region src/client/new-conversation-draft.ts
10204
+ /** 跟随当前会话的原草稿状态,覆盖输入、粘贴、历史召回和任务预填。 */
10205
+ function createDraftPresenceSource(selection, resolve) {
10206
+ return {
10207
+ getSnapshot: () => (resolve()?.getSnapshot().draft.length ?? 0) > 0,
10208
+ subscribe: (listener) => {
10209
+ let current;
10210
+ let offInput = () => {};
10211
+ const bind = () => {
10212
+ const next = resolve();
10213
+ if (next !== current) {
10214
+ offInput();
10215
+ current = next;
10216
+ offInput = next?.subscribe(listener) ?? (() => {});
10217
+ }
10218
+ listener();
10219
+ };
10220
+ const offSelection = selection.subscribe(bind);
10221
+ bind();
10222
+ return () => {
10223
+ offSelection();
10224
+ offInput();
10225
+ };
10226
+ }
10227
+ };
10228
+ }
10229
+ /** 任务建议只能填入空闲且空白的草稿,不覆盖附件、提及或正在提交的内容。 */
10230
+ function prefillNewConversation(input, text) {
10231
+ if (input === void 0) return "workspace";
10232
+ const state = input.state.getSnapshot();
10233
+ if (state.phase !== "plain") return "busy";
10234
+ if (state.draft.trim() !== "" || state.imageIds.length > 0 || state.occurrences.length > 0) return "draft";
10235
+ input.setDraft(text);
10236
+ return "ready";
10237
+ }
10238
+ //#endregion
9092
10239
  //#region src/client/index.ts
9093
10240
  const inject = [
9094
10241
  "slots",
@@ -9126,20 +10273,34 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
9126
10273
  }
9127
10274
  /** 替换 DSH 的官方 sidebar 插槽,不修改 DSH 源码或会话数据。 */
9128
10275
  function apply(ctx) {
10276
+ const widthStorage = browserStorage();
10277
+ if (widthStorage) initializeComposerWidth(widthStorage);
9129
10278
  ctx.effect(() => ctx.locale.register(NS, {
9130
10279
  zh,
9131
10280
  en
9132
10281
  }), "michengai-codex-ui: dictionaries");
9133
10282
  const t = ctx.locale.bind(NS);
10283
+ ctx.effect(() => observeHeroWidthHandles(t("home.resizeInput")), "michengai-codex-ui: hero width handles");
9134
10284
  registerInputHistory(ctx);
9135
10285
  registerSettingsPage(ctx);
10286
+ registerUsageStatistics(ctx);
9136
10287
  const connection = ctx.get("connection");
9137
10288
  const openPath = (path) => openPathInHost(connection, path);
9138
10289
  ctx.effect(() => observeSlimSidebar(), "michengai-codex-ui: slim sidebar");
9139
10290
  ctx.effect(() => observeSettingsNavIcons(), "michengai-codex-ui: settings nav icons");
9140
10291
  ctx.effect(() => observePermissionLabels(ctx.locale), "michengai-codex-ui: permission labels");
10292
+ ctx.effect(() => observeComposerToolMenus({
10293
+ search: t("home.projectSearch"),
10294
+ empty: t("home.projectEmpty")
10295
+ }), "michengai-codex-ui: composer tool menus");
10296
+ ctx.effect(() => observeHostCopy(ctx.locale, t), "michengai-codex-ui: host copy");
9141
10297
  ctx.effect(() => observeConversationHeader(), "michengai-codex-ui: conversation header");
9142
10298
  ctx.effect(() => observeOfficialTurnNavigators(), "michengai-codex-ui: official turn navigator");
10299
+ const newConversationDraft = createDraftPresenceSource(ctx.sessions.list, () => {
10300
+ const id = ctx.sessions.list.getSnapshot().current;
10301
+ const binding = id === void 0 ? void 0 : ctx.sessions.binding(id);
10302
+ return binding === void 0 ? void 0 : ctx.conversation.input.for(binding.ctx).state;
10303
+ });
9143
10304
  const companionSlots = createCompanionTabSource(ctx.slots);
9144
10305
  ctx.slots.inject("sidebar", () => ctx.slots.register({
9145
10306
  name: "sidebar",
@@ -9168,6 +10329,12 @@ body[data-ds-dark-theme] .dcu-settings-page{--sp-bg:#181818;--sp-nav:#202322;--s
9168
10329
  }
9169
10330
  },
9170
10331
  inject: () => ({
10332
+ newConversationDraft,
10333
+ prefillNewConversation: (text) => {
10334
+ const id = ctx.sessions.list.getSnapshot().current;
10335
+ const binding = id === void 0 ? void 0 : ctx.sessions.binding(id);
10336
+ return prefillNewConversation(binding === void 0 ? void 0 : ctx.conversation.input.for(binding.ctx), text);
10337
+ },
9171
10338
  openSession: (sessionId) => {
9172
10339
  ctx.sessions.open(sessionId);
9173
10340
  },