dsh-composer-ux 0.4.0 → 0.5.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
@@ -38,9 +38,71 @@ __export(client_exports, {
38
38
  module.exports = __toCommonJS(client_exports);
39
39
  var import_dsh_client_store = require("@deepseek-ai/dsh-client-store");
40
40
 
41
+ // src/terminal/discover.ts
42
+ function normalizePath(value) {
43
+ const trimmed = value.trim().replace(/^"|"$/g, "");
44
+ const slashed = trimmed.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
45
+ return slashed.length > 1 ? slashed.replace(/\/+$/, "") : slashed;
46
+ }
47
+
48
+ // src/terminal/contracts.ts
49
+ var TERMINAL_MODE_FIELD = "terminalMode";
50
+ var TERMINAL_BASH_PATH_FIELD = "terminalBashPath";
51
+ var TERMINAL_CANDIDATES_FIELD = "terminalCandidates";
52
+ var TERMINAL_STATUS_FIELD = "terminalStatus";
53
+ var TERMINAL_EFFECTIVE_FIELD = "terminalEffective";
54
+ var TERMINAL_API_PATH = "/composer-ux/terminal";
55
+ var TERMINAL_MODES = [
56
+ {
57
+ id: "auto",
58
+ label: "\u81EA\u52A8",
59
+ hint: "\u63A2\u6D4B\u5230 Git Bash \u5C31\u7528\u5B83\uFF08\u627E\u4E0D\u5230\u5219\u4FDD\u6301 PowerShell\uFF09\uFF1B\u5F00\u7BB1\u5373\u7528\uFF0C\u4E0D\u7528\u624B\u586B\u8DEF\u5F84"
60
+ },
61
+ {
62
+ id: "gitbash",
63
+ label: "Git Bash",
64
+ hint: "\u5F3A\u5236\u6362\u6210 Git Bash\uFF1B\u6CA1\u63A2\u6D4B\u5230\u5C31\u56DE\u843D PowerShell\uFF0C\u5E76\u5728\u72B6\u6001\u884C\u5199\u660E\u539F\u56E0"
65
+ },
66
+ {
67
+ id: "pwsh",
68
+ label: "PowerShell",
69
+ hint: "\u4FDD\u6301 DSH \u9ED8\u8BA4\uFF08\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u78B0\u7EC8\u7AEF\u5DE5\u5177\u9762\uFF09"
70
+ }
71
+ ];
72
+ var DEFAULT_TERMINAL_MODE = "auto";
73
+ function terminalModeFrom(value) {
74
+ return value === "auto" || value === "gitbash" || value === "pwsh" ? value : DEFAULT_TERMINAL_MODE;
75
+ }
76
+ function sanitizeTerminalCandidates(value) {
77
+ if (!Array.isArray(value)) return [];
78
+ const out = [];
79
+ const seen = /* @__PURE__ */ new Set();
80
+ for (const item of value) {
81
+ if (out.length >= 20) break;
82
+ if (typeof item !== "object" || item === null) continue;
83
+ const row2 = item;
84
+ const path = typeof row2.path === "string" ? normalizePath(row2.path).slice(0, 400) : "";
85
+ if (path === "") continue;
86
+ const key = path.toLowerCase();
87
+ if (seen.has(key)) continue;
88
+ seen.add(key);
89
+ const label = typeof row2.label === "string" ? row2.label.slice(0, 40) : "";
90
+ const kind = row2.kind === "git" || row2.kind === "msys2" || row2.kind === "cygwin" || row2.kind === "niubash" || row2.kind === "path" ? row2.kind : "path";
91
+ out.push({ path, label: label === "" ? "PATH" : label, kind, explicit: row2.explicit === true });
92
+ }
93
+ return out;
94
+ }
95
+
41
96
  // src/settings-contract.ts
42
97
  var NAMESPACE = "composer-ux";
98
+ var REPO_URL = "https://github.com/fangwen9527/dsh-composer-ux";
99
+ var RESTART_API_PATH = "/composer-ux/restart";
43
100
  var ENABLED_FIELD = "enabled";
101
+ var KEYS_ENABLED_FIELD = "keysEnabled";
102
+ var MENU_ENABLED_FIELD = "menuEnabled";
103
+ var QUICK_ENABLED_FIELD = "quickEnabled";
104
+ var PANEL_ENABLED_FIELD = "panelEnabled";
105
+ var TERMINAL_ENABLED_FIELD = "terminalEnabled";
44
106
  var SEND_KEY_FIELD = "sendKey";
45
107
  var NEWLINE_KEY_FIELD = "newlineKey";
46
108
  var PANEL_SCROLL_FIELD = "panelScroll";
@@ -227,7 +289,14 @@ var DEFAULT_HEADER_NAME = "x-opencode-session";
227
289
  var HEADER_VALUE_MAX = 200;
228
290
  var HEADER_NAME_MAX = 64;
229
291
  var DEFAULT_SETTINGS = {
292
+ // 总开关默认开:它只是总闸,真正"要不要用这一栏"由下面五个开关决定(默认关)。
230
293
  enabled: true,
294
+ // 五栏默认关(老文档由 sectionEnabledOf 迁移成"碰过就开")。
295
+ keysEnabled: false,
296
+ menuEnabled: false,
297
+ quickEnabled: false,
298
+ panelEnabled: false,
299
+ terminalEnabled: false,
231
300
  sendKey: "Enter",
232
301
  newlineKey: "Shift+Enter",
233
302
  menuUndo: true,
@@ -248,8 +317,24 @@ var DEFAULT_SETTINGS = {
248
317
  headerAppliedValue: "",
249
318
  headerStatus: "",
250
319
  quickPrompts: DEFAULT_QUICK_PROMPTS,
251
- optimizerTier: DEFAULT_OPTIMIZER_TIER
320
+ optimizerTier: DEFAULT_OPTIMIZER_TIER,
321
+ terminalMode: DEFAULT_TERMINAL_MODE,
322
+ terminalBashPath: "",
323
+ terminalCandidates: [],
324
+ terminalStatus: "",
325
+ terminalEffective: ""
252
326
  };
327
+ function activeSections(settings) {
328
+ const on = settings.enabled;
329
+ return {
330
+ keys: on && settings.keysEnabled,
331
+ menu: on && settings.menuEnabled,
332
+ quick: on && settings.quickEnabled,
333
+ panel: on && settings.panelEnabled,
334
+ header: on && settings.headerEnabled,
335
+ terminal: on && settings.terminalEnabled
336
+ };
337
+ }
253
338
  var SEND_PRESETS = ["Enter", "Ctrl+Enter", "Alt+Enter", "Shift+Enter"];
254
339
  var NEWLINE_PRESETS = ["Shift+Enter", "Enter", "Ctrl+Enter", "Alt+Enter"];
255
340
  var MENU_ITEMS = [
@@ -270,6 +355,25 @@ function newSessionId() {
270
355
  ).join("");
271
356
  return `${hex(8)}-${hex(4)}-4${hex(3)}-a${hex(3)}-${hex(12)}`;
272
357
  }
358
+ var SECTION_SIGNALS = {
359
+ [KEYS_ENABLED_FIELD]: (source) => touched(source, SEND_KEY_FIELD, DEFAULT_SETTINGS.sendKey) || touched(source, NEWLINE_KEY_FIELD, DEFAULT_SETTINGS.newlineKey),
360
+ // 「官方」=本插件不介入,等价于关;所以只有选过另外两档才算"碰过"。
361
+ // (`menuModeFrom` 对"两个键都没有"给的就是 'official',天然满足"缺省 = 默认"。)
362
+ [MENU_ENABLED_FIELD]: (source) => menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]) !== "official",
363
+ [QUICK_ENABLED_FIELD]: (source) => Array.isArray(source[QUICK_PROMPTS_FIELD]) && source[QUICK_PROMPTS_FIELD].length !== DEFAULT_QUICK_PROMPTS.length || touched(source, OPTIMIZER_TIER_FIELD, DEFAULT_OPTIMIZER_TIER),
364
+ [PANEL_ENABLED_FIELD]: (source) => touched(source, PANEL_SCROLL_FIELD, true) || touched(source, PANEL_RESIZE_FIELD, true) || source[PANEL_WIDTH_FIELD] !== void 0 || source[PANEL_HEIGHT_FIELD] !== void 0,
365
+ [TERMINAL_ENABLED_FIELD]: (source) => touched(source, TERMINAL_MODE_FIELD, DEFAULT_TERMINAL_MODE) || touched(source, TERMINAL_BASH_PATH_FIELD, "")
366
+ };
367
+ function touched(source, field, untouched) {
368
+ const value = source[field];
369
+ return value !== void 0 && value !== untouched;
370
+ }
371
+ function sectionEnabledOf(field, source) {
372
+ const explicit = source[field];
373
+ if (typeof explicit === "boolean") return explicit;
374
+ const signal = SECTION_SIGNALS[field];
375
+ return signal === void 0 ? false : signal(source);
376
+ }
273
377
  function sanitizeSettings(value) {
274
378
  const source = typeof value === "object" && value !== null ? value : {};
275
379
  const asString = (field) => {
@@ -319,6 +423,12 @@ function sanitizeSettings(value) {
319
423
  };
320
424
  return {
321
425
  enabled: asBool(ENABLED_FIELD),
426
+ // 五栏开关:显式写过听它的,否则按"用户碰过没"迁移(见 sectionEnabledOf)。
427
+ keysEnabled: sectionEnabledOf(KEYS_ENABLED_FIELD, source),
428
+ menuEnabled: sectionEnabledOf(MENU_ENABLED_FIELD, source),
429
+ quickEnabled: sectionEnabledOf(QUICK_ENABLED_FIELD, source),
430
+ panelEnabled: sectionEnabledOf(PANEL_ENABLED_FIELD, source),
431
+ terminalEnabled: sectionEnabledOf(TERMINAL_ENABLED_FIELD, source),
322
432
  sendKey: asString(SEND_KEY_FIELD),
323
433
  newlineKey: asString(NEWLINE_KEY_FIELD),
324
434
  menuUndo: asBool("menuUndo"),
@@ -343,7 +453,14 @@ function sanitizeSettings(value) {
343
453
  headerAppliedValue: asText(HEADER_APPLIED_VALUE_FIELD, HEADER_VALUE_MAX),
344
454
  headerStatus: asText(HEADER_STATUS_FIELD, HEADER_VALUE_MAX),
345
455
  quickPrompts: asQuickPrompts(),
346
- optimizerTier: asTier()
456
+ optimizerTier: asTier(),
457
+ terminalMode: terminalModeFrom(source[TERMINAL_MODE_FIELD]),
458
+ // 路径只做长度与归一化收窄,不在这里判"存不存在"——那是宿主半的探测结论,
459
+ // 由状态行告诉用户(用户看得见自己填了什么,比悄悄清空好)。
460
+ terminalBashPath: asText(TERMINAL_BASH_PATH_FIELD, 400),
461
+ terminalCandidates: sanitizeTerminalCandidates(source[TERMINAL_CANDIDATES_FIELD]),
462
+ terminalStatus: asText(TERMINAL_STATUS_FIELD, 400),
463
+ terminalEffective: asText(TERMINAL_EFFECTIVE_FIELD, 16)
347
464
  };
348
465
  }
349
466
 
@@ -765,6 +882,7 @@ function composing(event) {
765
882
  function installInterceptors(deps) {
766
883
  const onKeyDown = (event) => {
767
884
  if (replaying) return;
885
+ if (!activeSections(deps.settings()).keys) return;
768
886
  const root = findComposerRoot(event.target);
769
887
  if (root === null) return;
770
888
  if (composing(event)) return;
@@ -788,7 +906,9 @@ function installInterceptors(deps) {
788
906
  const onContextMenu = (event) => {
789
907
  const root = findComposerRoot(event.target);
790
908
  if (root === null) return;
791
- const mode = deps.settings().menuMode;
909
+ const settings = deps.settings();
910
+ if (!activeSections(settings).menu) return;
911
+ const mode = settings.menuMode;
792
912
  if (mode === "official") return;
793
913
  if (mode === "browser") {
794
914
  if (deps.menuOpen()) deps.setMenu(null);
@@ -1053,7 +1173,8 @@ var CARD_CSS = `
1053
1173
  .dsh-ux-cardHeader {
1054
1174
  appearance: none;
1055
1175
  box-sizing: border-box;
1056
- width: 100%;
1176
+ flex: 1;
1177
+ min-width: 0;
1057
1178
  font: inherit;
1058
1179
  color: inherit;
1059
1180
  text-align: left;
@@ -1070,6 +1191,35 @@ var CARD_CSS = `
1070
1191
  outline: 2px solid var(--dsw-alias-brand-primary);
1071
1192
  outline-offset: -2px;
1072
1193
  }
1194
+ /* \u6807\u9898\u884C = \u5DE6\u8FB9"\u5C55\u5F00"\u6309\u94AE\uFF08\u5360\u6EE1\u5269\u4F59\u5BBD\u5EA6\uFF09+ \u53F3\u8FB9\u4ECE\u5C5E\u63A7\u4EF6\u4E0E\u672C\u680F\u5F00\u5173\u3002
1195
+ \u4E0D\u80FD\u5728 <button> \u91CC\u585E\u6309\u94AE\uFF0C\u6240\u4EE5\u4E24\u8005\u662F\u5144\u5F1F\u8282\u70B9\u3002 */
1196
+ .dsh-ux-cardHeaderRow {
1197
+ display: flex;
1198
+ align-items: center;
1199
+ flex-wrap: wrap;
1200
+ gap: 6px;
1201
+ padding-right: 12px;
1202
+ }
1203
+ .dsh-ux-cardControls {
1204
+ align-items: center;
1205
+ display: inline-flex;
1206
+ flex: none;
1207
+ flex-wrap: wrap;
1208
+ gap: 8px;
1209
+ }
1210
+ /* \u6807\u9898\u884C\u91CC\u7684"\u6587\u5B57 + \u5C0F\u5F00\u5173"\uFF08\u5BFC\u822A\u6EDA\u52A8 / \u8FB9\u7F18\u7F29\u653E\uFF09\u3002 */
1211
+ .dsh-ux-miniToggle {
1212
+ align-items: center;
1213
+ color: var(--dsw-alias-label-secondary);
1214
+ display: inline-flex;
1215
+ flex: none;
1216
+ font-size: 11px;
1217
+ gap: 5px;
1218
+ white-space: nowrap;
1219
+ }
1220
+ /* \u672A\u542F\u7528\uFF1A\u6807\u9898\u884C\u91CC\u8BF4\u6E05\u695A\uFF0C\u6B63\u6587\u538B\u6697\uFF0C\u8BA9\u4EBA\u4E00\u773C\u770B\u51FA"\u8FD9\u4E00\u680F\u73B0\u5728\u4E0D\u751F\u6548"\u3002 */
1221
+ .dsh-ux-cardOff { border-style: dashed; }
1222
+ .dsh-ux-cardOff .dsh-ux-cardBody { opacity: .6; }
1073
1223
  .dsh-ux-cardHeaderStatic {
1074
1224
  box-sizing: border-box;
1075
1225
  display: flex;
@@ -1097,6 +1247,109 @@ var CARD_CSS = `
1097
1247
  line-height: 1.5;
1098
1248
  margin: 0;
1099
1249
  }
1250
+ .dsh-ux-cardLink {
1251
+ align-items: center;
1252
+ color: var(--dsw-alias-label-secondary);
1253
+ display: inline-flex;
1254
+ flex: none;
1255
+ font-size: 12px;
1256
+ gap: 4px;
1257
+ text-decoration: none;
1258
+ white-space: nowrap;
1259
+ }
1260
+ .dsh-ux-cardLink:hover {
1261
+ color: var(--dsw-alias-brand-primary);
1262
+ text-decoration: underline;
1263
+ }
1264
+ /* \u62AC\u5934\u53F3\u7AEF\u90A3\u4E00\u7EC4\uFF1A\u91CD\u542F\u6309\u94AE + GitHub \u94FE\u63A5\uFF0C\u4E24\u679A\u90FD\u4E0D\u53C2\u4E0E\u6536\u7F29\u3002 */
1265
+ .dsh-ux-cardActions {
1266
+ align-items: center;
1267
+ display: inline-flex;
1268
+ flex: none;
1269
+ gap: 10px;
1270
+ }
1271
+ .dsh-ux-restartButton {
1272
+ appearance: none;
1273
+ background: 0 0;
1274
+ border: 1px solid var(--dsw-alias-border-l2);
1275
+ border-radius: 999px;
1276
+ color: var(--dsw-alias-label-primary);
1277
+ cursor: pointer;
1278
+ flex: none;
1279
+ font: inherit;
1280
+ font-size: 12px;
1281
+ line-height: 1;
1282
+ padding: 6px 12px;
1283
+ transition: border-color .16s, color .16s, background .16s;
1284
+ white-space: nowrap;
1285
+ }
1286
+ .dsh-ux-restartButton:hover:not(:disabled) {
1287
+ background: var(--dsw-alias-interactive-bg-hover);
1288
+ border-color: var(--dsw-alias-brand-primary);
1289
+ color: var(--dsw-alias-brand-primary);
1290
+ }
1291
+ .dsh-ux-restartButton:disabled {
1292
+ color: var(--dsw-alias-label-tertiary);
1293
+ cursor: default;
1294
+ opacity: .7;
1295
+ }
1296
+ /* \u786E\u8BA4\u6761\uFF1A\u62AC\u5934\u6B63\u4E0B\u65B9\u7684\u4E00\u6761\uFF0C\u4F4D\u7F6E\u5BF9\u9F50\u5E02\u573A\u7684\u300CN \u9879\u53D8\u66F4\u9700\u91CD\u542F\u300D\u6A2A\u5E45\u3002 */
1297
+ .dsh-ux-restartBanner {
1298
+ align-items: center;
1299
+ background: var(--dsw-alias-bg-layer-2);
1300
+ border: 1px solid var(--dsw-alias-border-l2);
1301
+ border-radius: 10px;
1302
+ display: flex;
1303
+ gap: 10px;
1304
+ margin: 0 16px 12px;
1305
+ padding: 10px 12px;
1306
+ }
1307
+ .dsh-ux-restartBannerFailed { border-color: var(--dsw-alias-state-error-primary); }
1308
+ .dsh-ux-restartBannerText {
1309
+ color: var(--dsw-alias-label-secondary);
1310
+ flex: 1;
1311
+ font-size: 12px;
1312
+ line-height: 1.5;
1313
+ min-width: 0;
1314
+ }
1315
+ .dsh-ux-restartBannerFailed .dsh-ux-restartBannerText { color: var(--dsw-alias-state-error-primary); }
1316
+ .dsh-ux-restartBannerActions {
1317
+ align-items: center;
1318
+ display: inline-flex;
1319
+ flex: none;
1320
+ gap: 8px;
1321
+ }
1322
+ .dsh-ux-restartGo {
1323
+ appearance: none;
1324
+ background: var(--dsw-alias-button-primary-fill);
1325
+ border: 0;
1326
+ border-radius: 999px;
1327
+ color: var(--dsw-alias-label-primary-foreground);
1328
+ cursor: pointer;
1329
+ font: inherit;
1330
+ font-size: 12px;
1331
+ line-height: 1;
1332
+ padding: 7px 14px;
1333
+ white-space: nowrap;
1334
+ }
1335
+ .dsh-ux-restartGo:hover { background: var(--dsw-alias-brand-primary); }
1336
+ .dsh-ux-restartCancel {
1337
+ appearance: none;
1338
+ background: 0 0;
1339
+ border: 1px solid var(--dsw-alias-border-l2);
1340
+ border-radius: 999px;
1341
+ color: var(--dsw-alias-label-secondary);
1342
+ cursor: pointer;
1343
+ font: inherit;
1344
+ font-size: 12px;
1345
+ line-height: 1;
1346
+ padding: 7px 14px;
1347
+ white-space: nowrap;
1348
+ }
1349
+ .dsh-ux-restartCancel:hover {
1350
+ border-color: var(--dsw-alias-label-dimmed);
1351
+ color: var(--dsw-alias-label-primary);
1352
+ }
1100
1353
  .dsh-ux-cardChevron {
1101
1354
  color: var(--dsw-alias-label-tertiary);
1102
1355
  flex: none;
@@ -1603,12 +1856,13 @@ var import_jsx_runtime2 = require("react/jsx-runtime");
1603
1856
  var EDGES = ["left", "right", "top", "bottom", "br"];
1604
1857
  function PanelResizeHandles({ useLive, actions }) {
1605
1858
  const settings = useLive((value) => ({
1606
- enabled: value.enabled,
1859
+ // 「设置面板」栏(或总开关)关着时整块停用 —— 与导航滚动那处用同一个判据。
1860
+ sectionOn: activeSections(value).panel,
1607
1861
  panelResize: value.panelResize,
1608
1862
  panelWidth: value.panelWidth,
1609
1863
  panelHeight: value.panelHeight
1610
1864
  }));
1611
- const enabled = settings.enabled === true && settings.panelResize === true;
1865
+ const enabled = settings.sectionOn === true && settings.panelResize === true;
1612
1866
  const [panel, setPanel] = (0, import_react2.useState)(null);
1613
1867
  const [active2, setActive] = (0, import_react2.useState)(null);
1614
1868
  const dragRef = (0, import_react2.useRef)(null);
@@ -1998,25 +2252,44 @@ function Chevron() {
1998
2252
  }
1999
2253
  function FoldCard(props) {
2000
2254
  const [open, setOpen] = (0, import_react4.useState)(false);
2001
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: open ? "dsh-ux-card dsh-ux-cardOpen" : "dsh-ux-card", children: [
2002
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2003
- "button",
2004
- {
2005
- type: "button",
2006
- className: "dsh-ux-cardHeader",
2007
- "aria-expanded": open,
2008
- onClick: () => {
2009
- setOpen((current) => !current);
2010
- },
2011
- children: [
2012
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
2013
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-cardName", children: props.name }),
2014
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-cardDescription", children: props.summary })
2015
- ] }),
2016
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: open ? "dsh-ux-cardChevron dsh-ux-cardChevronOpen" : "dsh-ux-cardChevron", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Chevron, {}) })
2017
- ]
2018
- }
2019
- ),
2255
+ const off = props.toggle !== void 0 && props.toggle.checked === false;
2256
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: [
2257
+ "dsh-ux-card",
2258
+ open ? "dsh-ux-cardOpen" : "",
2259
+ off ? "dsh-ux-cardOff" : ""
2260
+ ].filter((part) => part !== "").join(" "), children: [
2261
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-ux-cardHeaderRow", children: [
2262
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2263
+ "button",
2264
+ {
2265
+ type: "button",
2266
+ className: "dsh-ux-cardHeader",
2267
+ "aria-expanded": open,
2268
+ onClick: () => {
2269
+ setOpen((current) => !current);
2270
+ },
2271
+ children: [
2272
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
2273
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-cardName", children: props.name }),
2274
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-cardDescription", children: off ? `\u672A\u542F\u7528 \xB7 ${props.summary}` : props.summary })
2275
+ ] }),
2276
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: open ? "dsh-ux-cardChevron dsh-ux-cardChevronOpen" : "dsh-ux-cardChevron", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Chevron, {}) })
2277
+ ]
2278
+ }
2279
+ ),
2280
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardControls", children: [
2281
+ props.controls,
2282
+ props.toggle !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2283
+ Switch,
2284
+ {
2285
+ small: true,
2286
+ label: `${props.name}\uFF1A\u542F\u7528\u8FD9\u4E00\u680F`,
2287
+ checked: props.toggle.checked,
2288
+ onChange: props.toggle.onChange
2289
+ }
2290
+ )
2291
+ ] })
2292
+ ] }),
2020
2293
  open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-ux-cardBody", children: props.children })
2021
2294
  ] });
2022
2295
  }
@@ -2106,6 +2379,57 @@ function KeyRow(props) {
2106
2379
  ] })
2107
2380
  ] });
2108
2381
  }
2382
+ function Switch(props) {
2383
+ const { checked, onChange, label, small = false } = props;
2384
+ const width = small ? 30 : 36;
2385
+ const height = small ? 16 : 20;
2386
+ const knob = small ? 12 : 14;
2387
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2388
+ "button",
2389
+ {
2390
+ type: "button",
2391
+ role: "switch",
2392
+ "aria-checked": checked,
2393
+ "aria-label": label,
2394
+ title: label,
2395
+ onClick: () => {
2396
+ onChange(!checked);
2397
+ },
2398
+ style: {
2399
+ width,
2400
+ height,
2401
+ borderRadius: 999,
2402
+ border: "0.5px solid var(--dsw-alias-border-l2)",
2403
+ cursor: "pointer",
2404
+ background: checked ? "var(--dsw-alias-button-primary-fill)" : "var(--dsw-alias-interactive-bg-hover)",
2405
+ position: "relative",
2406
+ flex: "0 0 auto",
2407
+ padding: 0
2408
+ },
2409
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2410
+ "span",
2411
+ {
2412
+ style: {
2413
+ position: "absolute",
2414
+ top: small ? 1 : 2,
2415
+ left: checked ? width - knob - (small ? 1 : 2) : small ? 1 : 2,
2416
+ width: knob,
2417
+ height: knob,
2418
+ borderRadius: "50%",
2419
+ background: checked ? "var(--dsw-alias-label-primary-foreground)" : "var(--dsw-alias-label-secondary)",
2420
+ transition: "left 0.12s ease"
2421
+ }
2422
+ }
2423
+ )
2424
+ }
2425
+ );
2426
+ }
2427
+ function MiniToggle(props) {
2428
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-miniToggle", children: [
2429
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-miniToggleLabel", children: props.label }),
2430
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Switch, { small: true, label: props.label, checked: props.checked, onChange: props.onChange })
2431
+ ] });
2432
+ }
2109
2433
  function ToggleRow(props) {
2110
2434
  const { label, desc, checked, onChange, first } = props;
2111
2435
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: first === true ? { ...row, borderTop: "none" } : row, children: [
@@ -2113,43 +2437,7 @@ function ToggleRow(props) {
2113
2437
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: label }),
2114
2438
  desc !== void 0 && desc !== "" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: desc })
2115
2439
  ] }),
2116
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2117
- "button",
2118
- {
2119
- type: "button",
2120
- role: "switch",
2121
- "aria-checked": checked,
2122
- onClick: () => {
2123
- onChange(!checked);
2124
- },
2125
- style: {
2126
- width: 36,
2127
- height: 20,
2128
- borderRadius: 999,
2129
- border: "0.5px solid var(--dsw-alias-border-l2)",
2130
- cursor: "pointer",
2131
- background: checked ? "var(--dsw-alias-button-primary-fill)" : "var(--dsw-alias-interactive-bg-hover)",
2132
- position: "relative",
2133
- flex: "0 0 auto",
2134
- padding: 0
2135
- },
2136
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2137
- "span",
2138
- {
2139
- style: {
2140
- position: "absolute",
2141
- top: 2,
2142
- left: checked ? 18 : 2,
2143
- width: 14,
2144
- height: 14,
2145
- borderRadius: "50%",
2146
- background: checked ? "var(--dsw-alias-label-primary-foreground)" : "var(--dsw-alias-label-secondary)",
2147
- transition: "left 0.12s ease"
2148
- }
2149
- }
2150
- )
2151
- }
2152
- )
2440
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Switch, { label, checked, onChange })
2153
2441
  ] });
2154
2442
  }
2155
2443
  function TextFieldRow(props) {
@@ -2438,11 +2726,249 @@ function QuickPromptsEditor(props) {
2438
2726
  ] })
2439
2727
  ] });
2440
2728
  }
2729
+ var candidatePill = {
2730
+ ...pill,
2731
+ textAlign: "left",
2732
+ maxWidth: "100%",
2733
+ overflowWrap: "anywhere",
2734
+ lineHeight: 1.4
2735
+ };
2736
+ function DefaultTerminalBody(props) {
2737
+ const { settings, setField, hideMode = false } = props;
2738
+ const [note, setNote] = (0, import_react4.useState)("");
2739
+ const [busy, setBusy] = (0, import_react4.useState)(false);
2740
+ const candidates = settings.terminalCandidates;
2741
+ if (settings.terminalEffective === "unsupported") {
2742
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u672C\u63D2\u4EF6\u53EA\u5728 Windows \u4E0A\u63A5\u7BA1\u7EC8\u7AEF\uFF08Windows \u4E0A DSH \u9ED8\u8BA4\u7ED9\u6A21\u578B\u7684\u662F PowerShell\uFF09\u3002\u5F53\u524D\u5E73\u53F0\u4E0D\u9700\u8981\u5B83\uFF0C \u8FD9\u91CC\u7684\u8BBE\u7F6E\u4E0D\u4F1A\u751F\u6548\u3002" });
2743
+ }
2744
+ const discover = async () => {
2745
+ setBusy(true);
2746
+ setNote("");
2747
+ try {
2748
+ const response = await fetch(TERMINAL_API_PATH, { method: "POST" });
2749
+ const parsed = await response.json();
2750
+ const found = sanitizeTerminalCandidates(parsed.candidates);
2751
+ setNote(found.length === 0 ? "\u6CA1\u6709\u627E\u5230\u53EF\u7528\u7684 bash\uFF08WSL \u7684 bash.exe \u4F1A\u88AB\u5FFD\u7565\uFF0C\u5B83\u6309 Linux \u89C4\u5219\u89E3\u91CA\u8DEF\u5F84\uFF09" : `\u627E\u5230 ${String(found.length)} \u4E2A\u5019\u9009\uFF0C\u5DF2\u5217\u5728\u4E0B\u65B9`);
2752
+ } catch (error) {
2753
+ setNote(`\u81EA\u52A8\u53D1\u73B0\u5931\u8D25\uFF1A${error instanceof Error ? error.message : String(error)}`);
2754
+ } finally {
2755
+ setBusy(false);
2756
+ }
2757
+ };
2758
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2759
+ !hideMode && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2760
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2761
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u7EC8\u7AEF\u5DE5\u5177" }),
2762
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: TERMINAL_MODES.find((item) => item.id === settings.terminalMode)?.hint ?? "" })
2763
+ ] }),
2764
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2765
+ PillChoice,
2766
+ {
2767
+ items: TERMINAL_MODES,
2768
+ value: settings.terminalMode,
2769
+ onChange: (mode) => {
2770
+ setField(TERMINAL_MODE_FIELD, mode);
2771
+ },
2772
+ ariaLabel: "\u7EC8\u7AEF\u5DE5\u5177"
2773
+ }
2774
+ )
2775
+ ] }),
2776
+ settings.terminalMode !== "pwsh" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2777
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2778
+ TextFieldRow,
2779
+ {
2780
+ title: "Git Bash \u8DEF\u5F84",
2781
+ desc: "\u7559\u7A7A = \u7528\u81EA\u52A8\u63A2\u6D4B\u5230\u7684\u90A3\u4E00\u4E2A\uFF08\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\uFF09",
2782
+ value: settings.terminalBashPath,
2783
+ placeholder: "\u7559\u7A7A = \u81EA\u52A8",
2784
+ maxLength: 400,
2785
+ onChange: (next) => {
2786
+ setField(TERMINAL_BASH_PATH_FIELD, next);
2787
+ },
2788
+ action: { label: busy ? "\u63A2\u6D4B\u4E2D\u2026" : "\u81EA\u52A8\u53D1\u73B0", onClick: () => {
2789
+ void discover();
2790
+ } }
2791
+ }
2792
+ ),
2793
+ candidates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 6, marginTop: 2 }, children: candidates.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2794
+ "button",
2795
+ {
2796
+ type: "button",
2797
+ title: candidate.path,
2798
+ style: candidate.path === settings.terminalBashPath ? { ...candidatePill, ...pillActive } : candidatePill,
2799
+ onClick: () => {
2800
+ setField(TERMINAL_BASH_PATH_FIELD, candidate.path);
2801
+ },
2802
+ children: [
2803
+ candidate.label,
2804
+ "\uFF1A",
2805
+ candidate.path,
2806
+ candidate.explicit ? "\uFF08\u4F60\u586B\u7684\uFF09" : ""
2807
+ ]
2808
+ },
2809
+ candidate.path
2810
+ )) }),
2811
+ note !== "" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: note })
2812
+ ] }),
2813
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
2814
+ "\u72B6\u6001\uFF1A",
2815
+ settings.terminalStatus === "" ? "\u7B49\u5F85\u5BBF\u4E3B\u534A\u63A2\u6D4B\u2026" : settings.terminalStatus
2816
+ ] }),
2817
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 \u6362\u6210 Git Bash \u540E\uFF0C\u6A21\u578B\u770B\u5230\u7684\u7EC8\u7AEF\u5DE5\u5177\u5C31\u53EB bash\uFF08\u547D\u4EE4\u6309 bash/POSIX \u5199\uFF09\uFF0CPowerShell \u90A3\u4E2A\u5DE5\u5177 \u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931 \u2014\u2014 \u4E00\u4E2A\u4F1A\u8BDD\u53EA\u9762\u5BF9\u4E00\u4E2A\u7EC8\u7AEF\u5DE5\u5177\u3002" }),
2818
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 \u6539\u6863\u4F4D\u4F1A\u7ACB\u523B\u91CD\u65B0\u4E0B\u53D1\u7ED9\u6B63\u5728\u8DD1\u7684\u4F1A\u8BDD\u3002\u4F46\u4F1A\u8BDD\u5386\u53F2\u91CC\u53EF\u80FD\u8FD8\u7559\u7740\u65E7\u5DE5\u5177\u540D\uFF1A\u5982\u679C\u54EA\u513F\u62A5\u4E86 unknown tool \u4E4B\u7C7B\u7684\u9519\uFF0C\u8BA9\u6A21\u578B\u6539\u7528 bash \u91CD\u8BD5\u5373\u53EF\uFF0C\u4E0D\u5F71\u54CD\u4F1A\u8BDD\u672C\u8EAB\u3002" }),
2819
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 \u53EA\u5BF9 Windows \u751F\u6548\uFF1BWSL \u7684 bash.exe \u4F1A\u88AB\u4E3B\u52A8\u6392\u9664\uFF08\u5B83\u628A D:\\ \u8FD9\u7C7B\u8DEF\u5F84\u89E3\u91CA\u6210 /mnt/d\uFF0C\u4E0E\u6A21\u578B\u624B\u91CC\u7684 Windows \u5DE5\u4F5C\u76EE\u5F55\u4E0D\u517C\u5BB9\uFF09\u3002\u6C99\u7BB1\u3001\u5BA1\u6279\u3001\u8D85\u65F6\u4E0E\u8F93\u51FA\u622A\u65AD\u7684\u884C\u4E3A\u4E0E DSH \u81EA\u5E26\u7EC8\u7AEF\u4E00\u81F4\u3002" })
2820
+ ] });
2821
+ }
2822
+ var RESTART_WAIT_MS = 6e4;
2823
+ var RESTART_POLL_MS = 1500;
2824
+ function blockedText(blocked) {
2825
+ if (blocked === "debugger") {
2826
+ return "\u8FD9\u4E2A\u5BBF\u4E3B\u6B63\u88AB\u8C03\u8BD5\u5668\u9644\u7740\uFF1A\u4ECE\u754C\u9762\u91CC\u6740\u6389\u5B83\u53EA\u4F1A\u8FDE\u8C03\u8BD5\u4F1A\u8BDD\u4E00\u8D77\u4E22\u6389\uFF0C\u8BF7\u4ECE IDE \u6216\u7EC8\u7AEF\u505C\u6B62\u5B83\u518D\u542F\u52A8\u3002";
2827
+ }
2828
+ if (blocked.startsWith("supervised:")) {
2829
+ return `\u8FD9\u4E2A\u5BBF\u4E3B\u7531 ${blocked.slice("supervised:".length)} \u5F53\u670D\u52A1\u5728\u8DD1\uFF0C\u91CD\u542F\u8BE5\u5F52\u5B83\u7BA1\uFF08\u5B83\u4F1A\u8FDE\u540C\u6574\u4E2A cgroup \u4E00\u8D77\u6536\u6389\uFF0C\u63D2\u4EF6\u81EA\u5DF1\u91CD\u542F\u53EA\u4F1A\u8BA9\u670D\u52A1\u518D\u4E5F\u8D77\u4E0D\u6765\uFF09\u3002`;
2830
+ }
2831
+ return `\u8FD9\u4E2A\u5BBF\u4E3B\u5F53\u524D\u4E0D\u5141\u8BB8\u4ECE\u754C\u9762\u91CD\u542F\uFF08${blocked}\uFF09\u3002`;
2832
+ }
2833
+ function useRestart() {
2834
+ const [stage, setStage] = (0, import_react4.useState)("idle");
2835
+ const [detail, setDetail] = (0, import_react4.useState)("");
2836
+ const [blocked, setBlocked] = (0, import_react4.useState)(null);
2837
+ const readFacts = async () => {
2838
+ const response = await fetch(RESTART_API_PATH, { cache: "no-store" });
2839
+ if (!response.ok) return { error: `HTTP ${String(response.status)}` };
2840
+ const parsed = await response.json();
2841
+ return {
2842
+ running: typeof parsed.running === "number" ? parsed.running : 0,
2843
+ command: typeof parsed.command === "string" ? parsed.command : "",
2844
+ logHint: typeof parsed.logHint === "string" ? parsed.logHint : "",
2845
+ blocked: typeof parsed.blocked === "string" ? parsed.blocked : null,
2846
+ boot: typeof parsed.boot === "string" ? parsed.boot : null
2847
+ };
2848
+ };
2849
+ const awaitNewBoot = async (previousBoot, logHint) => {
2850
+ const deadline = Date.now() + RESTART_WAIT_MS;
2851
+ while (Date.now() < deadline) {
2852
+ await new Promise((done) => {
2853
+ setTimeout(done, RESTART_POLL_MS);
2854
+ });
2855
+ try {
2856
+ const facts = await readFacts();
2857
+ if ("error" in facts) continue;
2858
+ if (facts.boot !== null && facts.boot !== previousBoot) {
2859
+ location.reload();
2860
+ return;
2861
+ }
2862
+ } catch {
2863
+ }
2864
+ }
2865
+ setStage("failed");
2866
+ setDetail("\u7B49\u4E86 60 \u79D2\u4E5F\u6CA1\u7B49\u5230\u65B0\u8FDB\u7A0B\u3002\u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat \u91CD\u542F\u4E00\u6B21\u3002" + (logHint === "" ? "" : `\u5BBF\u4E3B\u534A\u7684\u8BCA\u65AD\u65E5\u5FD7\u5728 ${logHint}\u3002`));
2867
+ };
2868
+ const ask = () => {
2869
+ setStage("asking");
2870
+ setDetail("\u6B63\u5728\u8BFB\u53D6\u91CD\u542F\u65B9\u5F0F\u2026");
2871
+ void (async () => {
2872
+ try {
2873
+ const facts = await readFacts();
2874
+ if ("error" in facts) {
2875
+ setStage("failed");
2876
+ setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF08${facts.error}\uFF09\u2014\u2014 \u5BBF\u4E3B\u534A\u53EF\u80FD\u8FD8\u6CA1\u6362\u5230\u5E26\u8FD9\u6761\u8DEF\u7531\u7684\u7248\u672C\uFF0C\u8BF7\u5148\u624B\u52A8\u8FD0\u884C\u4E00\u6B21 restart-webui.bat\u3002`);
2877
+ return;
2878
+ }
2879
+ setBlocked(facts.blocked);
2880
+ if (facts.blocked !== null) {
2881
+ setStage("failed");
2882
+ setDetail(blockedText(facts.blocked));
2883
+ return;
2884
+ }
2885
+ setStage("asking");
2886
+ setDetail((facts.boot === null ? "\u5BBF\u4E3B\u534A\u8FD8\u662F\u4E0A\u4E00\u7248\uFF1A\u8FD9\u6B21\u91CD\u542F\u4F1A\u8D70\u65E7\u673A\u5236\uFF08\u5199\u811A\u672C + \u81EA\u5DF1\u9000\u51FA\uFF09\uFF0C\u91CD\u542F\u4E4B\u540E\u6309\u94AE\u5C31\u662F\u65B0\u7248\u4E86\u3002" : `\u91CD\u542F\u65B9\u5F0F\uFF1A${facts.command}\u3002`) + `\u5F53\u524D\u6709 ${String(facts.running)} \u4E2A\u4F1A\u8BDD\u5728\u8DD1 \u2014\u2014 \u91CD\u542F\u4F1A\u6253\u65AD\u5B83\u4EEC\uFF08\u5305\u62EC\u6B63\u5728\u751F\u6210\u7684\u90A3\u4E00\u8F6E\uFF09\u3002`);
2887
+ } catch (error) {
2888
+ setStage("failed");
2889
+ setDetail(`\u8BFB\u4E0D\u5230\u91CD\u542F\u72B6\u6001\uFF1A${error instanceof Error ? error.message : String(error)}`);
2890
+ }
2891
+ })();
2892
+ };
2893
+ const confirm = () => {
2894
+ setStage("restarting");
2895
+ setDetail("\u5DF2\u53D1\u51FA\u91CD\u542F\u8BF7\u6C42 \u2014\u2014 \u6B63\u5728\u7B49\u65B0\u8FDB\u7A0B\u8D77\u6765\uFF08\u8FD9\u4E2A\u9875\u9762\u4F1A\u81EA\u5DF1\u56DE\u6765\uFF09\u2026");
2896
+ void (async () => {
2897
+ let previousBoot = null;
2898
+ let logHint = "";
2899
+ try {
2900
+ const before = await readFacts();
2901
+ if (!("error" in before)) {
2902
+ previousBoot = before.boot;
2903
+ logHint = before.logHint;
2904
+ }
2905
+ } catch {
2906
+ }
2907
+ try {
2908
+ const response = await fetch(RESTART_API_PATH, {
2909
+ method: "POST",
2910
+ headers: { "content-type": "application/json" },
2911
+ body: "{}"
2912
+ });
2913
+ const parsed = await response.json();
2914
+ if (response.status !== 202 && parsed.ok !== true) {
2915
+ setStage("failed");
2916
+ setDetail(`\u91CD\u542F\u6CA1\u6210\u529F\uFF1A${parsed.error ?? `HTTP ${String(response.status)}`} \u2014\u2014 \u8BF7\u624B\u52A8\u8FD0\u884C restart-webui.bat\u3002`);
2917
+ return;
2918
+ }
2919
+ } catch {
2920
+ }
2921
+ await awaitNewBoot(previousBoot, logHint);
2922
+ })();
2923
+ };
2924
+ const cancel = () => {
2925
+ setStage("idle");
2926
+ setDetail("");
2927
+ };
2928
+ return { stage, detail, blocked, ask, confirm, cancel };
2929
+ }
2930
+ function RestartButton({ restart }) {
2931
+ const busy = restart.stage === "restarting" || restart.stage === "asking";
2932
+ const blocked = restart.blocked;
2933
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2934
+ "button",
2935
+ {
2936
+ type: "button",
2937
+ className: "dsh-ux-restartButton",
2938
+ disabled: busy || blocked !== null,
2939
+ title: blocked === null ? "\u91CD\u542F DSH\uFF1A\u8BA9\u5BBF\u4E3B\u534A\u7684\u65B0\u4EE3\u7801\uFF08\u9ED8\u8BA4\u7EC8\u7AEF\u3001\u952E\u4F4D schema\uFF09\u751F\u6548\u3002\u70B9\u4E00\u4E0B\u4F1A\u5148\u8BA9\u4F60\u786E\u8BA4\u4E00\u6B21\u3002" : blockedText(blocked),
2940
+ onClick: () => {
2941
+ restart.ask();
2942
+ },
2943
+ children: restart.stage === "restarting" ? "\u91CD\u542F\u4E2D\u2026" : "\u91CD\u542F DSH"
2944
+ }
2945
+ );
2946
+ }
2947
+ function RestartBanner({ restart }) {
2948
+ if (restart.stage === "idle") return null;
2949
+ const failed = restart.stage === "failed";
2950
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: failed ? "dsh-ux-restartBanner dsh-ux-restartBannerFailed" : "dsh-ux-restartBanner", children: [
2951
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-restartBannerText", children: restart.detail }),
2952
+ restart.stage === "asking" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-restartBannerActions", children: [
2953
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-ux-restartGo", onClick: () => {
2954
+ restart.confirm();
2955
+ }, children: "\u786E\u8BA4\u91CD\u542F" }),
2956
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-ux-restartCancel", onClick: () => {
2957
+ restart.cancel();
2958
+ }, children: "\u53D6\u6D88" })
2959
+ ] }),
2960
+ failed && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "dsh-ux-restartBannerActions", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "dsh-ux-restartCancel", onClick: () => {
2961
+ restart.cancel();
2962
+ }, children: "\u77E5\u9053\u4E86" }) })
2963
+ ] });
2964
+ }
2441
2965
  function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2442
2966
  const settings = useLive((item) => item);
2443
2967
  const book = useBook((item) => item);
2444
2968
  const bookStatus = useBookStatus((item) => item);
2445
2969
  const [conflict, setConflict] = (0, import_react4.useState)(null);
2970
+ const restart = useRestart();
2971
+ const sections = activeSections(settings);
2446
2972
  const setKey = (side, chord) => {
2447
2973
  const other = side === "send" ? settings.newlineKey : settings.sendKey;
2448
2974
  if (chord !== "" && chord === other) {
@@ -2461,12 +2987,33 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2461
2987
  const quickCounts = bookCounts(book);
2462
2988
  const quickSummary = `${quickCounts.categories} \u4E2A\u5206\u7C7B \xB7 ${quickCounts.prompts} \u6761 \xB7 \u6BCF\u6B21 ${quickCounts.always} \xB7 \u4EC5\u9996\u6B21 ${quickCounts.first} \xB7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.label ?? "\u9AD8\u7EA7"}`;
2463
2989
  const headerStatusText = settings.headerEnabled ? settings.headerStatus === "" ? "\u7B49\u5F85\u9996\u6B21\u5199\u5165\u2026" : settings.headerStatus : "\u672A\u542F\u7528\uFF08\u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u5199\u5165\uFF09";
2990
+ const terminalSummary = sections.terminal === false ? settings.terminalMode === "pwsh" ? "\u4FDD\u6301 PowerShell" : "\u6253\u5F00\u540E\u63A5\u7BA1\u7EC8\u7AEF" : settings.terminalEffective === "unsupported" ? "\u975E Windows\uFF1A\u4E0D\u9700\u8981" : settings.terminalMode === "pwsh" ? "\u5F53\u524D\uFF1A\u4FDD\u6301 PowerShell" : settings.terminalEffective === "bash" ? "\u5F53\u524D\uFF1AGit Bash" : "\u5F53\u524D\uFF1APowerShell\uFF08\u672A\u63A5\u7BA1\uFF09";
2464
2991
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "4px 2px" }, children: [
2465
2992
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "dsh-ux-card", children: [
2466
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-ux-cardHeaderStatic", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
2467
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "dsh-ux-cardName", children: "\u8F93\u5165\u4F53\u9A8C" }),
2468
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dsh-ux-cardDescription", children: "dsh-composer-ux \xB7 \u4E3B\u804A\u5929\u8F93\u5165\u6846\u7684\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\uFF1B\u8BBE\u7F6E\u5373\u65F6\u751F\u6548\u5E76\u6301\u4E45\u4FDD\u5B58\u3002" })
2469
- ] }) }),
2993
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-ux-cardHeaderStatic", children: [
2994
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
2995
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "dsh-ux-cardName", children: "\u8F93\u5165\u4F53\u9A8C" }),
2996
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "dsh-ux-cardDescription", children: "dsh-composer-ux \xB7 \u4E3B\u804A\u5929\u8F93\u5165\u6846\u7684\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u4E0E\u8BBE\u7F6E\u9762\u677F\uFF1B\u8BBE\u7F6E\u5373\u65F6\u751F\u6548\u5E76\u6301\u4E45\u4FDD\u5B58\u3002" })
2997
+ ] }),
2998
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "dsh-ux-cardActions", children: [
2999
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RestartButton, { restart }),
3000
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3001
+ "a",
3002
+ {
3003
+ className: "dsh-ux-cardLink",
3004
+ href: REPO_URL,
3005
+ target: "_blank",
3006
+ rel: "noreferrer noopener",
3007
+ title: "\u5728 GitHub \u4E0A\u67E5\u770B\u8FD9\u4E2A\u63D2\u4EF6\uFF08\u65B0\u6807\u7B7E\u6253\u5F00\uFF09",
3008
+ children: [
3009
+ "GitHub ",
3010
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { "aria-hidden": "true", children: "\u2197" })
3011
+ ]
3012
+ }
3013
+ )
3014
+ ] })
3015
+ ] }),
3016
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RestartBanner, { restart }),
2470
3017
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-ux-cardBody", children: [
2471
3018
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2472
3019
  ToggleRow,
@@ -2484,282 +3031,374 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2484
3031
  ] })
2485
3032
  ] }),
2486
3033
  settings.enabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2487
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(FoldCard, { name: "\u952E\u4F4D", summary: keySummary, children: [
2488
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u652F\u6301\u5E38\u7528\u9884\u8BBE\uFF0C\u4E5F\u53EF\u4EE5\u70B9\u51FB\u300C\u81EA\u5B9A\u4E49\u2026\u300D\u540E\u76F4\u63A5\u6309\u4E0B\u4EFB\u610F\u7EC4\u5408\u952E\u5F55\u5236\uFF08Esc \u53D6\u6D88\uFF0CBackspace \u6E05\u9664\uFF09\u3002 \u672A\u7ED1\u5B9A\u7684 Enter \u7CFB\u6309\u952E\u4E0D\u4F1A\u89E6\u53D1\u53D1\u9001\u6216\u6362\u884C\uFF1BCtrl+Enter / \u2318+Enter \u672A\u88AB\u7ED1\u5B9A\u65F6\u4FDD\u7559\u539F\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B \u4E2D\u6587\u8F93\u5165\u6CD5\u7EC4\u5408\u671F\u95F4\u4E0D\u53D7\u5F71\u54CD\u3002" }),
2489
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2490
- KeyRow,
2491
- {
2492
- first: true,
2493
- title: "\u53D1\u9001\u952E",
2494
- desc: "\u6309\u4E0B\u540E\u53D1\u9001\u5F53\u524D\u8F93\u5165",
2495
- value: settings.sendKey,
2496
- presets: SEND_PRESETS,
2497
- conflict: (chord) => chord !== "" && chord === settings.newlineKey,
2498
- onChange: (chord) => {
2499
- setKey("send", chord);
2500
- }
2501
- }
2502
- ),
2503
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2504
- KeyRow,
2505
- {
2506
- title: "\u6362\u884C\u952E",
2507
- desc: "\u6309\u4E0B\u540E\u5728\u8F93\u5165\u5185\u6362\u884C",
2508
- value: settings.newlineKey,
2509
- presets: NEWLINE_PRESETS,
2510
- conflict: (chord) => chord !== "" && chord === settings.sendKey,
2511
- onChange: (chord) => {
2512
- setKey("newline", chord);
2513
- }
2514
- }
2515
- ),
2516
- conflictHint !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintError, children: conflictHint }),
2517
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2518
- "button",
2519
- {
2520
- type: "button",
2521
- style: pill,
2522
- onClick: () => {
2523
- setConflict(null);
2524
- actions.resetAll();
2525
- },
2526
- children: "\u6062\u590D\u9ED8\u8BA4"
2527
- }
2528
- ) })
2529
- ] }),
2530
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(FoldCard, { name: "\u53F3\u952E\u83DC\u5355", summary: menuSummary, children: [
2531
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u53F3\u952E\u70B9\u51FB\u8F93\u5165\u6846\u65F6\u5F39\u51FA\u54EA\u4E00\u79CD\u83DC\u5355\u3002\u53EA\u5F71\u54CD\u53F3\u952E\uFF0C\u4E0D\u5F71\u54CD\u952E\u4F4D\u4E0E\u5176\u5B83\u529F\u80FD\u3002" }),
2532
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2533
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2534
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u83DC\u5355\u6765\u6E90" }),
2535
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: MENU_MODES.find((item) => item.id === settings.menuMode)?.hint ?? "" })
2536
- ] }),
2537
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2538
- PillChoice,
2539
- {
2540
- items: MENU_MODES,
2541
- value: settings.menuMode,
2542
- onChange: (mode) => {
2543
- actions.setField(MENU_MODE_FIELD, mode);
2544
- },
2545
- ariaLabel: "\u53F3\u952E\u83DC\u5355\u6765\u6E90"
3034
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3035
+ FoldCard,
3036
+ {
3037
+ name: "\u952E\u4F4D",
3038
+ summary: keySummary,
3039
+ toggle: {
3040
+ checked: sections.keys,
3041
+ onChange: (next) => {
3042
+ actions.setField(KEYS_ENABLED_FIELD, next);
2546
3043
  }
2547
- )
2548
- ] }),
2549
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u5B98\u65B9\uFF1A\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF0CDSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548\uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709 \u53F3\u952E\u83DC\u5355\uFF0C\u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09\u3002" }),
2550
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u6D4F\u89C8\u5668\uFF1A\u56FA\u5B9A\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF08\u6837\u5B50\u968F\u6D4F\u89C8\u5668\u800C\u53D8\uFF09\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B \u597D\u5904\u662F\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E\u3002" }),
2551
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u81EA\u5B9A\u4E49\uFF1A\u7528\u672C\u63D2\u4EF6\u56FA\u5B9A\u6837\u5F0F\u7684\u83DC\u5355\uFF08\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF09\u3002\u8FD9\u4E00\u6863\u7684\u300C\u7C98\u8D34\u300D \u8981\u8BFB\u526A\u8D34\u677F\uFF0C\u6D4F\u89C8\u5668\u4F1A\u5148\u8981\u4E00\u6B21\u6388\u6743\u2014\u2014\u4E09\u5BB6\u6D4F\u89C8\u5668\u7684\u5904\u7406\u4E0D\u4E00\u6837\uFF1A" }),
2552
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 Chrome / Edge\uFF08\u8C37\u6B4C / \u5FAE\u8F6F\u6D4F\u89C8\u5668\uFF09\uFF1A\u5F39\u51FA\u540E\u70B9\u300C\u5141\u8BB8\u300D\u5373\u53EF\uFF0C\u4E4B\u540E\u4F1A\u8BB0\u4F4F\u8FD9\u4E2A\u7AD9\u70B9\u3001\u4E0D\u518D\u95EE\u3002 \u8981\u6539\u6216\u64A4\u9500\u6388\u6743\uFF1A\u70B9\u5730\u5740\u680F\u6700\u5DE6\u8FB9\u7684\u7F51\u7AD9\u56FE\u6807 \u2192 \u7F51\u7AD9\u8BBE\u7F6E\uFF08Edge \u53EB\u300C\u6B64\u7AD9\u70B9\u7684\u6743\u9650\u300D\uFF09\u2192 \u526A\u8D34\u677F\uFF1B \u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728\u5730\u5740\u680F\u8F93\u5165 chrome://settings/content/clipboard\uFF08Edge \u8F93\u5165 edge://settings/content/clipboard\uFF09\u3002" }),
2553
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 Firefox\uFF1A\u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\u2014\u2014\u4F60\u70B9\u672C\u63D2\u4EF6\u7684\u300C\u7C98\u8D34\u300D\u540E\uFF0C\u5B83\u4F1A\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\u300C\u7C98\u8D34(P)\u300D \u4E00\u9879\u7684\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u70B9\u5B83\u624D\u5B8C\u6210\u8FD9\u6B21\u7C98\u8D34\u3002\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389 \uFF08\u5B9E\u6D4B\uFF1Aabout:config \u91CC\u7684\u526A\u8D34\u677F\u9996\u9009\u9879\u5BF9\u5B83\u65E0\u6548\uFF09\u3002\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V\uFF0C \u6216\u628A\u4E0A\u9762\u7684\u300C\u83DC\u5355\u6765\u6E90\u300D\u6362\u6210\u300C\u6D4F\u89C8\u5668 / \u5B98\u65B9\u300D\u6863\u2014\u2014\u90A3\u4E24\u6863\u7528\u7684\u662F\u6D4F\u89C8\u5668\u81EA\u5DF1\u7684\u7C98\u8D34\u3002" }),
2554
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u6CE8\u610F\uFF1Achrome://\u3001edge:// \u8FD9\u4E9B\u5730\u5740\u6D4F\u89C8\u5668\u4E0D\u5141\u8BB8\u505A\u6210\u7F51\u9875\u91CC\u7684\u94FE\u63A5\uFF0C\u53EA\u80FD\u624B\u8F93\uFF0C \u6216\u590D\u5236\u4E0A\u9762\u90A3\u4E32\u7C98\u8D34\u5230\u5730\u5740\u680F\u3002" }),
2555
- settings.menuMode === "custom" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2556
- MENU_ITEMS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2557
- ToggleRow,
2558
- {
2559
- label: item.label,
2560
- desc: item.shortcut !== "" ? `\u5FEB\u6377\u952E ${item.shortcut}` : "",
2561
- checked: settings[item.field],
2562
- onChange: (next) => {
2563
- actions.setField(item.field, next);
3044
+ },
3045
+ children: [
3046
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u652F\u6301\u5E38\u7528\u9884\u8BBE\uFF0C\u4E5F\u53EF\u4EE5\u70B9\u51FB\u300C\u81EA\u5B9A\u4E49\u2026\u300D\u540E\u76F4\u63A5\u6309\u4E0B\u4EFB\u610F\u7EC4\u5408\u952E\u5F55\u5236\uFF08Esc \u53D6\u6D88\uFF0CBackspace \u6E05\u9664\uFF09\u3002 \u672A\u7ED1\u5B9A\u7684 Enter \u7CFB\u6309\u952E\u4E0D\u4F1A\u89E6\u53D1\u53D1\u9001\u6216\u6362\u884C\uFF1BCtrl+Enter / \u2318+Enter \u672A\u88AB\u7ED1\u5B9A\u65F6\u4FDD\u7559\u539F\u300C\u52A0\u901F\u63D0\u4EA4\u300D\u884C\u4E3A\uFF1B \u4E2D\u6587\u8F93\u5165\u6CD5\u7EC4\u5408\u671F\u95F4\u4E0D\u53D7\u5F71\u54CD\u3002" }),
3047
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3048
+ KeyRow,
3049
+ {
3050
+ first: true,
3051
+ title: "\u53D1\u9001\u952E",
3052
+ desc: "\u6309\u4E0B\u540E\u53D1\u9001\u5F53\u524D\u8F93\u5165",
3053
+ value: settings.sendKey,
3054
+ presets: SEND_PRESETS,
3055
+ conflict: (chord) => chord !== "" && chord === settings.newlineKey,
3056
+ onChange: (chord) => {
3057
+ setKey("send", chord);
3058
+ }
2564
3059
  }
2565
- },
2566
- item.field
2567
- )),
2568
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2569
- "button",
2570
- {
2571
- type: "button",
2572
- style: pill,
2573
- onClick: () => {
2574
- for (const item of MENU_ITEMS) actions.setField(item.field, true);
2575
- },
2576
- children: "\u5168\u90E8\u5F00\u542F"
2577
- }
2578
- ) })
2579
- ] })
2580
- ] }),
2581
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(FoldCard, { name: "\u5FEB\u6377\u6307\u4EE4", summary: quickSummary, children: [
2582
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: bodyLead, children: [
2583
- "\u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\u3002 \u6BCF\u6761\u53F3\u4FA7\u7684\u4E09\u9009\u4E00\u51B3\u5B9A",
2584
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u53D1\u9001\u65F6\u600E\u4E48\u9644\u52A0" }),
2585
- "\uFF1A \u300C\u5173\u300D= \u53EA\u63D2\u5165\u4E0D\u9644\u52A0\uFF1B\u300C\u6BCF\u6B21\u300D= \u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\u5230\u6D88\u606F",
2586
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u672B\u5C3E" }),
2587
- "\uFF1B \u300C\u4EC5\u9996\u6B21\u300D= \u53EA\u5728",
2588
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F" }),
2589
- "\u4E0A\u9644\u52A0\uFF08\u4E4B\u540E\u4E0D\u518D\u9644\u52A0\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF09\u3002 \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\u3002 \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002"
2590
- ] }),
2591
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2592
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2593
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u4F18\u5316\u5F3A\u5EA6" }),
2594
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.hint ?? "" })
2595
- ] }),
2596
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2597
- "button",
2598
- {
2599
- type: "button",
2600
- title: item.hint,
2601
- style: settings.optimizerTier === item.id ? pillActive : pill,
2602
- onClick: () => {
2603
- actions.setField(OPTIMIZER_TIER_FIELD, item.id);
2604
- },
2605
- children: item.label
2606
- },
2607
- item.id
2608
- )) })
2609
- ] }),
2610
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2611
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2612
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
2613
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: "\u5206\u7C7B\u5728\u8FD9\u91CC\u7BA1\u7406\uFF08\u9762\u677F\u91CC\u53EA\u505A\u5207\u6362\uFF09\uFF1B\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF0C\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002" })
2614
- ] }),
2615
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2616
- QuickPromptsEditor,
2617
- {
2618
- book,
2619
- status: bookStatus,
2620
- onSave: (next) => {
2621
- actions.saveBook(next);
2622
- },
2623
- onReload: () => {
2624
- actions.reloadBook();
2625
- },
2626
- onReset: () => {
2627
- actions.resetBook();
3060
+ ),
3061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3062
+ KeyRow,
3063
+ {
3064
+ title: "\u6362\u884C\u952E",
3065
+ desc: "\u6309\u4E0B\u540E\u5728\u8F93\u5165\u5185\u6362\u884C",
3066
+ value: settings.newlineKey,
3067
+ presets: NEWLINE_PRESETS,
3068
+ conflict: (chord) => chord !== "" && chord === settings.sendKey,
3069
+ onChange: (chord) => {
3070
+ setKey("newline", chord);
3071
+ }
2628
3072
  }
2629
- }
2630
- )
2631
- ] })
2632
- ] }),
2633
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(FoldCard, { name: "\u8BBE\u7F6E\u9762\u677F", summary: panelSummary, children: [
2634
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u63D2\u4EF6\u88C5\u5F97\u591A\u65F6\u8BBE\u7F6E\u6761\u76EE\u5F88\u957F\uFF1A\u5F00\u542F\u300C\u5BFC\u822A\u53EF\u6EDA\u52A8\u300D\u540E\uFF0C\u5DE6\u4FA7\u5BFC\u822A\u5728\u6EA2\u51FA\u65F6\u4F1A\u51FA\u73B0\u6EDA\u52A8\u6761\u3002 \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002" }),
2635
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2636
- ToggleRow,
2637
- {
2638
- first: true,
2639
- label: "\u5BFC\u822A\u53EF\u6EDA\u52A8",
2640
- desc: "\u8BBE\u7F6E\u6761\u76EE\u8D85\u51FA\u9762\u677F\u9AD8\u5EA6\u65F6\u663E\u793A\u6EDA\u52A8\u6761",
2641
- checked: settings.panelScroll,
3073
+ ),
3074
+ conflictHint !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintError, children: conflictHint }),
3075
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3076
+ "button",
3077
+ {
3078
+ type: "button",
3079
+ style: pill,
3080
+ onClick: () => {
3081
+ setConflict(null);
3082
+ actions.resetAll();
3083
+ },
3084
+ children: "\u6062\u590D\u9ED8\u8BA4"
3085
+ }
3086
+ ) })
3087
+ ]
3088
+ }
3089
+ ),
3090
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3091
+ FoldCard,
3092
+ {
3093
+ name: "\u53F3\u952E\u83DC\u5355",
3094
+ summary: menuSummary,
3095
+ toggle: {
3096
+ checked: sections.menu,
2642
3097
  onChange: (next) => {
2643
- actions.setField(PANEL_SCROLL_FIELD, next);
3098
+ actions.setField(MENU_ENABLED_FIELD, next);
2644
3099
  }
2645
- }
2646
- ),
2647
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2648
- ToggleRow,
2649
- {
2650
- label: "\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F",
2651
- desc: "\u62D6\u52A8\u9762\u677F\u56DB\u8FB9 / \u56DB\u89D2\u6539\u53D8\u9762\u677F\u5C3A\u5BF8",
2652
- checked: settings.panelResize,
3100
+ },
3101
+ children: [
3102
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u53F3\u952E\u70B9\u51FB\u8F93\u5165\u6846\u65F6\u5F39\u51FA\u54EA\u4E00\u79CD\u83DC\u5355\u3002\u53EA\u5F71\u54CD\u53F3\u952E\uFF0C\u4E0D\u5F71\u54CD\u952E\u4F4D\u4E0E\u5176\u5B83\u529F\u80FD\u3002" }),
3103
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
3104
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowText, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u83DC\u5355\u6765\u6E90" }) }),
3105
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3106
+ PillChoice,
3107
+ {
3108
+ items: MENU_MODES,
3109
+ value: settings.menuMode,
3110
+ onChange: (mode) => {
3111
+ actions.setField(MENU_MODE_FIELD, mode);
3112
+ },
3113
+ ariaLabel: "\u53F3\u952E\u83DC\u5355\u6765\u6E90"
3114
+ }
3115
+ )
3116
+ ] }),
3117
+ settings.menuMode === "official" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
3118
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u5B98\u65B9" }),
3119
+ "\uFF1A\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF0CDSH \u4E0E\u5176\u5B83\u63D2\u4EF6\u81EA\u5DF1\u7684\u53F3\u952E\u5904\u7406\u539F\u6837\u751F\u6548 \uFF08DSH \u5B98\u65B9\u8F93\u5165\u6846\u672C\u8EAB\u6CA1\u6709\u53F3\u952E\u83DC\u5355\uFF0C\u6240\u4EE5\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09\u3002"
3120
+ ] }),
3121
+ settings.menuMode === "browser" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
3122
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u6D4F\u89C8\u5668" }),
3123
+ "\uFF1A\u56FA\u5B9A\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF08\u6837\u5B50\u968F\u6D4F\u89C8\u5668\u800C\u53D8\uFF09\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42 \u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u597D\u5904\u662F\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E\u3002"
3124
+ ] }),
3125
+ settings.menuMode === "custom" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3126
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
3127
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u81EA\u5B9A\u4E49" }),
3128
+ "\uFF1A\u7528\u672C\u63D2\u4EF6\u56FA\u5B9A\u6837\u5F0F\u7684\u83DC\u5355\uFF08\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF09\u3002 \u8FD9\u4E00\u6863\u7684\u300C\u7C98\u8D34\u300D\u8981\u8BFB\u526A\u8D34\u677F\uFF0C\u6D4F\u89C8\u5668\u4F1A\u5148\u8981\u4E00\u6B21\u6388\u6743\u2014\u2014\u4E09\u5BB6\u6D4F\u89C8\u5668\u7684\u5904\u7406\u4E0D\u4E00\u6837\uFF1A"
3129
+ ] }),
3130
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 Chrome / Edge\uFF08\u8C37\u6B4C / \u5FAE\u8F6F\u6D4F\u89C8\u5668\uFF09\uFF1A\u5F39\u51FA\u540E\u70B9\u300C\u5141\u8BB8\u300D\u5373\u53EF\uFF0C\u4E4B\u540E\u4F1A\u8BB0\u4F4F\u8FD9\u4E2A\u7AD9\u70B9\u3001\u4E0D\u518D\u95EE\u3002 \u8981\u6539\u6216\u64A4\u9500\u6388\u6743\uFF1A\u70B9\u5730\u5740\u680F\u6700\u5DE6\u8FB9\u7684\u7F51\u7AD9\u56FE\u6807 \u2192 \u7F51\u7AD9\u8BBE\u7F6E\uFF08Edge \u53EB\u300C\u6B64\u7AD9\u70B9\u7684\u6743\u9650\u300D\uFF09\u2192 \u526A\u8D34\u677F\uFF1B \u4E5F\u53EF\u4EE5\u76F4\u63A5\u5728\u5730\u5740\u680F\u8F93\u5165 chrome://settings/content/clipboard\uFF08Edge \u8F93\u5165 edge://settings/content/clipboard\uFF09\u3002" }),
3131
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\xB7 Firefox\uFF1A\u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\u2014\u2014\u4F60\u70B9\u672C\u63D2\u4EF6\u7684\u300C\u7C98\u8D34\u300D\u540E\uFF0C\u5B83\u4F1A\u5148\u5F39\u4E00\u4E2A\u53EA\u6709\u300C\u7C98\u8D34(P)\u300D \u4E00\u9879\u7684\u5C0F\u7A97\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF09\uFF0C\u70B9\u5B83\u624D\u5B8C\u6210\u8FD9\u6B21\u7C98\u8D34\u3002\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389 \uFF08\u5B9E\u6D4B\uFF1Aabout:config \u91CC\u7684\u526A\u8D34\u677F\u9996\u9009\u9879\u5BF9\u5B83\u65E0\u6548\uFF09\u3002\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V\uFF0C \u6216\u628A\u4E0A\u9762\u7684\u300C\u83DC\u5355\u6765\u6E90\u300D\u6362\u6210\u300C\u6D4F\u89C8\u5668 / \u5B98\u65B9\u300D\u6863\u2014\u2014\u90A3\u4E24\u6863\u7528\u7684\u662F\u6D4F\u89C8\u5668\u81EA\u5DF1\u7684\u7C98\u8D34\u3002" }),
3132
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u6CE8\u610F\uFF1Achrome://\u3001edge:// \u8FD9\u4E9B\u5730\u5740\u6D4F\u89C8\u5668\u4E0D\u5141\u8BB8\u505A\u6210\u7F51\u9875\u91CC\u7684\u94FE\u63A5\uFF0C\u53EA\u80FD\u624B\u8F93\uFF0C \u6216\u590D\u5236\u4E0A\u9762\u90A3\u4E32\u7C98\u8D34\u5230\u5730\u5740\u680F\u3002" }),
3133
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { ...row, flexDirection: "column", alignItems: "stretch", gap: 8 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
3134
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u83DC\u5355\u6761\u76EE" }),
3135
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: "\u8FD9 7 \u4E2A\u5F00\u5173\u51B3\u5B9A\u81EA\u5B9A\u4E49\u83DC\u5355\u91CC\u51FA\u73B0\u54EA\u4E9B\u6761\u76EE\uFF0C\u5173\u6389\u7684\u4E0D\u663E\u793A\u3002" })
3136
+ ] }) }),
3137
+ MENU_ITEMS.map((item, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3138
+ ToggleRow,
3139
+ {
3140
+ first: index === 0,
3141
+ label: item.label,
3142
+ desc: item.shortcut !== "" ? `\u5FEB\u6377\u952E ${item.shortcut}` : "",
3143
+ checked: settings[item.field],
3144
+ onChange: (next) => {
3145
+ actions.setField(item.field, next);
3146
+ }
3147
+ },
3148
+ item.field
3149
+ )),
3150
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { padding: "8px 0 2px" }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3151
+ "button",
3152
+ {
3153
+ type: "button",
3154
+ style: pill,
3155
+ onClick: () => {
3156
+ for (const item of MENU_ITEMS) actions.setField(item.field, true);
3157
+ },
3158
+ children: "\u5168\u90E8\u5F00\u542F"
3159
+ }
3160
+ ) })
3161
+ ] })
3162
+ ]
3163
+ }
3164
+ ),
3165
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3166
+ FoldCard,
3167
+ {
3168
+ name: "\u5FEB\u6377\u6307\u4EE4",
3169
+ summary: quickSummary,
3170
+ toggle: {
3171
+ checked: sections.quick,
2653
3172
  onChange: (next) => {
2654
- actions.setField(PANEL_RESIZE_FIELD, next);
2655
- }
2656
- }
2657
- ),
2658
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginTop: 10 }, children: [
2659
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: rowDesc, children: "\u5C3A\u5BF8\u9884\u8BBE\uFF1A" }),
2660
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2661
- "button",
2662
- {
2663
- type: "button",
2664
- style: pill,
2665
- onClick: () => {
2666
- actions.clearField(PANEL_WIDTH_FIELD);
2667
- actions.clearField(PANEL_HEIGHT_FIELD);
2668
- },
2669
- children: "\u9ED8\u8BA4\uFF08800\uFF09"
2670
- }
2671
- ),
2672
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2673
- "button",
2674
- {
2675
- type: "button",
2676
- style: settings.panelWidth === 640 && settings.panelHeight === 600 ? pillActive : pill,
2677
- onClick: () => {
2678
- actions.setField(PANEL_WIDTH_FIELD, 640);
2679
- actions.setField(PANEL_HEIGHT_FIELD, 600);
2680
- },
2681
- children: "\u7D27\u51D1\uFF08640\xD7600\uFF09"
2682
- }
2683
- ),
2684
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2685
- "button",
2686
- {
2687
- type: "button",
2688
- style: settings.panelWidth === 1040 && settings.panelHeight === 760 ? pillActive : pill,
2689
- onClick: () => {
2690
- actions.setField(PANEL_WIDTH_FIELD, 1040);
2691
- actions.setField(PANEL_HEIGHT_FIELD, 760);
2692
- },
2693
- children: "\u5BBD\u655E\uFF081040\xD7760\uFF09"
3173
+ actions.setField(QUICK_ENABLED_FIELD, next);
2694
3174
  }
2695
- )
2696
- ] })
2697
- ] }),
2698
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(FoldCard, { name: "OpenCode \u8BF7\u6C42\u5934", summary: headerSummary, children: [
2699
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintError, children: "\u26A0\uFE0F \u8BF7\u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 OpenCode API \u5730\u5740\uFF0C\u4E0D\u8981\u7528 DSH \u81EA\u5E26\u7684 API \u5730\u5740\u914D\u7F6E\uFF1A \u7528\u81EA\u5E26\u7684\u914D\u7F6E\u65E0\u6CD5\u4E0A\u4F20\u56FE\u7247\uFF0C\u4E00\u65E6\u53D1\u9001\u56FE\u7247\u5C31\u4F1A\u62A5\u9519\u3002" }),
2700
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E0A\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\uFF08\u5B98\u65B9 Go \u6587\u6863 \u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF1A\u4E3A\u6BCF\u6BB5\u5BF9\u8BDD\u5728 x-opencode-session \u4E2D\u53D1\u9001\u4F1A\u8BDD ID\uFF0C \u4EE5\u4FBF\u5176\u4F18\u5316\u8DEF\u7531\u4E0E\u63D0\u793A\u8BCD\u7F13\u5B58\uFF09\u3002DSH \u7684\u8BBE\u7F6E\u9875\u4E0D\u63D0\u4F9B\u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u8FD9\u91CC\u76F4\u63A5\u628A\u5B83\u5199\u8FDB llm-pi-ai \u7684 provider \u914D\u7F6E\u2014\u2014\u4E0B\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u5C31\u751F\u6548\uFF0C\u4E0D\u7528\u91CD\u542F\uFF0C\u4E5F\u4E0D\u7528\u624B\u5DE5\u6539 settings.yaml\u3002 \u53EA\u5BF9 llm-pi-ai \u91CC\u300C\u5DF2\u5B58\u5728\u300D\u7684 opencode \u7CFB\u8DEF\u7531\u751F\u6548\uFF0C\u4E0D\u4F1A\u51ED\u7A7A\u65B0\u5EFA provider\uFF1B \u603B\u5F00\u5173\u5173\u95ED\u6216\u672C\u680F\u76EE\u505C\u7528\u65F6\uFF0C\u5199\u5165\u7684\u5934\u4F1A\u81EA\u52A8\u64A4\u9500\u3002" }),
2701
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2702
- ToggleRow,
2703
- {
2704
- first: true,
2705
- label: "\u9644\u52A0\u8BF7\u6C42\u5934",
2706
- desc: "\u6253\u5F00\u5373\u5199\u5165\uFF0C\u5E76\u5728\u6BCF\u6B21\u542F\u52A8\u65F6\u8865\u9F50\uFF1B\u5173\u95ED\u5373\u64A4\u9500",
2707
- checked: settings.headerEnabled,
3175
+ },
3176
+ children: [
3177
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: bodyLead, children: [
3178
+ "\u8F93\u5165\u6846\u5DE5\u5177\u884C\u91CC\u90A3\u4E2A\u300C\u5FEB\u6377\u6307\u4EE4\u300D\u6309\u94AE\u70B9\u5F00\u5C31\u662F\u8FD9\u5F20\u6E05\u5355\uFF1A\u70B9\u6761\u76EE\u628A\u5185\u5BB9\u63D2\u5165\u8F93\u5165\u6846\u3002 \u6BCF\u6761\u53F3\u4FA7\u7684\u4E09\u9009\u4E00\u51B3\u5B9A",
3179
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u53D1\u9001\u65F6\u600E\u4E48\u9644\u52A0" }),
3180
+ "\uFF1A \u300C\u5173\u300D= \u53EA\u63D2\u5165\u4E0D\u9644\u52A0\uFF1B\u300C\u6BCF\u6B21\u300D= \u6BCF\u6B21\u53D1\u9001\u90FD\u9644\u52A0\u5230\u6D88\u606F",
3181
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u672B\u5C3E" }),
3182
+ "\uFF1B \u300C\u4EC5\u9996\u6B21\u300D= \u53EA\u5728",
3183
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: "\u8FD9\u4E2A\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F" }),
3184
+ "\u4E0A\u9644\u52A0\uFF08\u4E4B\u540E\u4E0D\u518D\u9644\u52A0\uFF0C\u5237\u65B0\u9875\u9762\u4E5F\u4E0D\u4F1A\u91CD\u590D\uFF09\u3002 \u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\u3002 \u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u4F1A\u7528\u53E6\u4E00\u4E2A AI \u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u51FA\u53BB\u7684\u6E05\u6670\u6307\u4EE4\uFF0C \u7ED3\u679C\u76F4\u63A5\u5199\u56DE\u8F93\u5165\u6846\uFF08Ctrl+Z \u53EF\u8FD8\u539F\uFF09\u2014\u2014\u4E0D\u4F1A\u6C61\u67D3\u5F53\u524D\u5BF9\u8BDD\uFF0C\u4E5F\u4E0D\u5360\u4F60\u7684\u5BF9\u8BDD\u8F6E\u6B21\u3002"
3185
+ ] }),
3186
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
3187
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
3188
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u4F18\u5316\u5F3A\u5EA6" }),
3189
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.hint ?? "" })
3190
+ ] }),
3191
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3192
+ "button",
3193
+ {
3194
+ type: "button",
3195
+ title: item.hint,
3196
+ style: settings.optimizerTier === item.id ? pillActive : pill,
3197
+ onClick: () => {
3198
+ actions.setField(OPTIMIZER_TIER_FIELD, item.id);
3199
+ },
3200
+ children: item.label
3201
+ },
3202
+ item.id
3203
+ )) })
3204
+ ] }),
3205
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
3206
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
3207
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
3208
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: "\u5206\u7C7B\u5728\u8FD9\u91CC\u7BA1\u7406\uFF08\u9762\u677F\u91CC\u53EA\u505A\u5207\u6362\uFF09\uFF1B\u5185\u7F6E 9 \u6761\u53EF\u4EE5\u76F4\u63A5\u7528\uFF0C\u6539\u5B8C\u8BB0\u5F97\u70B9\u300C\u4FDD\u5B58\u4FEE\u6539\u300D\u3002" })
3209
+ ] }),
3210
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3211
+ QuickPromptsEditor,
3212
+ {
3213
+ book,
3214
+ status: bookStatus,
3215
+ onSave: (next) => {
3216
+ actions.saveBook(next);
3217
+ },
3218
+ onReload: () => {
3219
+ actions.reloadBook();
3220
+ },
3221
+ onReset: () => {
3222
+ actions.resetBook();
3223
+ }
3224
+ }
3225
+ )
3226
+ ] })
3227
+ ]
3228
+ }
3229
+ ),
3230
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3231
+ FoldCard,
3232
+ {
3233
+ name: "\u8BBE\u7F6E\u9762\u677F",
3234
+ summary: panelSummary,
3235
+ toggle: {
3236
+ checked: sections.panel,
2708
3237
  onChange: (next) => {
2709
- actions.setField(HEADER_ENABLED_FIELD, next);
3238
+ actions.setField(PANEL_ENABLED_FIELD, next);
2710
3239
  }
2711
- }
2712
- ),
2713
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2714
- TextFieldRow,
2715
- {
2716
- title: "\u5934\u540D",
2717
- desc: `\u9ED8\u8BA4 ${DEFAULT_HEADER_NAME}\uFF08OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\uFF09`,
2718
- value: settings.headerName,
2719
- placeholder: DEFAULT_HEADER_NAME,
2720
- maxLength: HEADER_NAME_MAX,
3240
+ },
3241
+ controls: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
3242
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3243
+ MiniToggle,
3244
+ {
3245
+ label: "\u5BFC\u822A\u6EDA\u52A8",
3246
+ checked: settings.panelScroll,
3247
+ onChange: (next) => {
3248
+ actions.setField(PANEL_SCROLL_FIELD, next);
3249
+ }
3250
+ }
3251
+ ),
3252
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3253
+ MiniToggle,
3254
+ {
3255
+ label: "\u8FB9\u7F18\u7F29\u653E",
3256
+ checked: settings.panelResize,
3257
+ onChange: (next) => {
3258
+ actions.setField(PANEL_RESIZE_FIELD, next);
3259
+ }
3260
+ }
3261
+ )
3262
+ ] }),
3263
+ children: [
3264
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "\u63D2\u4EF6\u88C5\u5F97\u591A\u65F6\u8BBE\u7F6E\u6761\u76EE\u5F88\u957F\uFF1A\u5F00\u542F\u300C\u5BFC\u822A\u53EF\u6EDA\u52A8\u300D\u540E\uFF0C\u5DE6\u4FA7\u5BFC\u822A\u5728\u6EA2\u51FA\u65F6\u4F1A\u51FA\u73B0\u6EDA\u52A8\u6761\u3002 \u5F00\u542F\u300C\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F\u300D\u540E\uFF0C\u628A\u9F20\u6807\u79FB\u5230\u8BBE\u7F6E\u9762\u677F\u7684\u8FB9\u6216\u89D2\u4E0A\uFF08\u51FA\u73B0\u9AD8\u4EAE\u6216\u5149\u6807\u53D8\u5316\uFF09\u62D6\u52A8\u5373\u53EF\u6539\u53D8\u9762\u677F\u5927\u5C0F\uFF0C \u5C3A\u5BF8\u4F1A\u8BB0\u4F4F\uFF0C\u4E0B\u6B21\u6253\u5F00\u4FDD\u6301\u3002\uFF08\u8FD9\u4E24\u4E2A\u5F00\u5173\u5728\u6807\u9898\u884C\u4E0A\u3002\uFF09" }),
3265
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginTop: 10 }, children: [
3266
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: rowDesc, children: "\u5C3A\u5BF8\u9884\u8BBE\uFF1A" }),
3267
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3268
+ "button",
3269
+ {
3270
+ type: "button",
3271
+ style: pill,
3272
+ onClick: () => {
3273
+ actions.clearField(PANEL_WIDTH_FIELD);
3274
+ actions.clearField(PANEL_HEIGHT_FIELD);
3275
+ },
3276
+ children: "\u9ED8\u8BA4\uFF08800\uFF09"
3277
+ }
3278
+ ),
3279
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3280
+ "button",
3281
+ {
3282
+ type: "button",
3283
+ style: settings.panelWidth === 640 && settings.panelHeight === 600 ? pillActive : pill,
3284
+ onClick: () => {
3285
+ actions.setField(PANEL_WIDTH_FIELD, 640);
3286
+ actions.setField(PANEL_HEIGHT_FIELD, 600);
3287
+ },
3288
+ children: "\u7D27\u51D1\uFF08640\xD7600\uFF09"
3289
+ }
3290
+ ),
3291
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3292
+ "button",
3293
+ {
3294
+ type: "button",
3295
+ style: settings.panelWidth === 1040 && settings.panelHeight === 760 ? pillActive : pill,
3296
+ onClick: () => {
3297
+ actions.setField(PANEL_WIDTH_FIELD, 1040);
3298
+ actions.setField(PANEL_HEIGHT_FIELD, 760);
3299
+ },
3300
+ children: "\u5BBD\u655E\uFF081040\xD7760\uFF09"
3301
+ }
3302
+ )
3303
+ ] })
3304
+ ]
3305
+ }
3306
+ ),
3307
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3308
+ FoldCard,
3309
+ {
3310
+ name: "OpenCode \u8BF7\u6C42\u5934",
3311
+ summary: headerSummary,
3312
+ toggle: {
3313
+ checked: sections.header,
2721
3314
  onChange: (next) => {
2722
- actions.setField(HEADER_NAME_FIELD, next);
3315
+ actions.setField(HEADER_ENABLED_FIELD, next);
2723
3316
  }
2724
- }
2725
- ),
2726
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2727
- TextFieldRow,
2728
- {
2729
- title: "\u503C",
2730
- desc: "\u6240\u6709\u5BF9\u8BDD\u5171\u7528\u8FD9\u4E00\u4E2A\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u4F1A\u81EA\u52A8\u751F\u6210\u4E00\u4E2A UUID \u5E76\u4FDD\u5B58\u6CBF\u7528",
2731
- value: settings.headerValue,
2732
- placeholder: "\u7559\u7A7A = \u81EA\u52A8\u751F\u6210",
2733
- maxLength: HEADER_VALUE_MAX,
2734
- onChange: (next) => {
2735
- actions.setField(HEADER_VALUE_FIELD, next);
2736
- },
2737
- action: {
2738
- label: "\u91CD\u65B0\u751F\u6210",
2739
- onClick: () => {
2740
- actions.setField(HEADER_VALUE_FIELD, newSessionId());
3317
+ },
3318
+ children: [
3319
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintError, children: "\u26A0\uFE0F \u8BF7\u4F7F\u7528\u81EA\u5B9A\u4E49\u7684 OpenCode API \u5730\u5740\uFF0C\u4E0D\u8981\u7528 DSH \u81EA\u5E26\u7684 API \u5730\u5740\u914D\u7F6E\uFF1A \u7528\u81EA\u5E26\u7684\u914D\u7F6E\u65E0\u6CD5\u4E0A\u4F20\u56FE\u7247\uFF0C\u4E00\u65E6\u53D1\u9001\u56FE\u7247\u5C31\u4F1A\u62A5\u9519\u3002" }),
3320
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "OpenCode \u7684\u63A5\u53E3\u8981\u6C42\u5BA2\u6237\u7AEF\u6BCF\u6B21\u8BF7\u6C42\u90FD\u5E26\u4E0A\u4E00\u4E2A\u7A33\u5B9A\u7684\u4F1A\u8BDD ID \u8BF7\u6C42\u5934\uFF08\u5B98\u65B9 Go \u6587\u6863 \u300C\u53EF\u4EE5\u5728\u54EA\u91CC\u4F7F\u7528\uFF1F\u300D\u7B2C 3 \u6761\uFF1A\u4E3A\u6BCF\u6BB5\u5BF9\u8BDD\u5728 x-opencode-session \u4E2D\u53D1\u9001\u4F1A\u8BDD ID\uFF0C \u4EE5\u4FBF\u5176\u4F18\u5316\u8DEF\u7531\u4E0E\u63D0\u793A\u8BCD\u7F13\u5B58\uFF09\u3002DSH \u7684\u8BBE\u7F6E\u9875\u4E0D\u63D0\u4F9B\u8BF7\u6C42\u5934\u7F16\u8F91\u5668\uFF0C\u6240\u4EE5\u8FD9\u91CC\u76F4\u63A5\u628A\u5B83\u5199\u8FDB llm-pi-ai \u7684 provider \u914D\u7F6E\u2014\u2014\u4E0B\u4E00\u6B21\u6A21\u578B\u8BF7\u6C42\u5C31\u751F\u6548\uFF0C\u4E0D\u7528\u91CD\u542F\uFF0C\u4E5F\u4E0D\u7528\u624B\u5DE5\u6539 settings.yaml\u3002 \u53EA\u5BF9 llm-pi-ai \u91CC\u300C\u5DF2\u5B58\u5728\u300D\u7684 opencode \u7CFB\u8DEF\u7531\u751F\u6548\uFF0C\u4E0D\u4F1A\u51ED\u7A7A\u65B0\u5EFA provider\uFF1B \u603B\u5F00\u5173\u5173\u95ED\u6216\u672C\u680F\u76EE\u505C\u7528\u65F6\uFF0C\u5199\u5165\u7684\u5934\u4F1A\u81EA\u52A8\u64A4\u9500\u3002" }),
3321
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3322
+ TextFieldRow,
3323
+ {
3324
+ title: "\u5934\u540D",
3325
+ desc: `\u9ED8\u8BA4 ${DEFAULT_HEADER_NAME}\uFF08OpenCode \u5B98\u65B9\u8981\u6C42\u7684\u90A3\u4E00\u4E2A\uFF09`,
3326
+ value: settings.headerName,
3327
+ placeholder: DEFAULT_HEADER_NAME,
3328
+ maxLength: HEADER_NAME_MAX,
3329
+ onChange: (next) => {
3330
+ actions.setField(HEADER_NAME_FIELD, next);
3331
+ }
2741
3332
  }
2742
- }
2743
- }
2744
- ),
2745
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2746
- TextFieldRow,
2747
- {
2748
- title: "\u4F5C\u7528\u8DEF\u7531",
2749
- desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09",
2750
- value: settings.headerRoutes,
2751
- placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09",
2752
- maxLength: HEADER_VALUE_MAX,
3333
+ ),
3334
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3335
+ TextFieldRow,
3336
+ {
3337
+ title: "\u503C",
3338
+ desc: "\u6240\u6709\u5BF9\u8BDD\u5171\u7528\u8FD9\u4E00\u4E2A\u503C\uFF1B\u7559\u7A7A\u65F6\u9996\u6B21\u542F\u7528\u4F1A\u81EA\u52A8\u751F\u6210\u4E00\u4E2A UUID \u5E76\u4FDD\u5B58\u6CBF\u7528",
3339
+ value: settings.headerValue,
3340
+ placeholder: "\u7559\u7A7A = \u81EA\u52A8\u751F\u6210",
3341
+ maxLength: HEADER_VALUE_MAX,
3342
+ onChange: (next) => {
3343
+ actions.setField(HEADER_VALUE_FIELD, next);
3344
+ },
3345
+ action: {
3346
+ label: "\u91CD\u65B0\u751F\u6210",
3347
+ onClick: () => {
3348
+ actions.setField(HEADER_VALUE_FIELD, newSessionId());
3349
+ }
3350
+ }
3351
+ }
3352
+ ),
3353
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3354
+ TextFieldRow,
3355
+ {
3356
+ title: "\u4F5C\u7528\u8DEF\u7531",
3357
+ desc: "\u9017\u53F7\u6216\u7A7A\u683C\u5206\u9694\uFF1B\u7559\u7A7A = \u81EA\u52A8\u5339\u914D OpenCode \u8DEF\u7531\uFF08\u540D\u5B57\u4EE5 opencode \u5F00\u5934\uFF0C\u6216 baseURL \u6307\u5411 opencode.ai\uFF09",
3358
+ value: settings.headerRoutes,
3359
+ placeholder: "\u7559\u7A7A = \u81EA\u52A8\uFF08opencode* \u6216 opencode.ai \u7AEF\u70B9\uFF09",
3360
+ maxLength: HEADER_VALUE_MAX,
3361
+ onChange: (next) => {
3362
+ actions.setField(HEADER_ROUTES_FIELD, next);
3363
+ }
3364
+ }
3365
+ ),
3366
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
3367
+ "\u72B6\u6001\uFF1A",
3368
+ headerStatusText
3369
+ ] })
3370
+ ]
3371
+ }
3372
+ ),
3373
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
3374
+ FoldCard,
3375
+ {
3376
+ name: "\u9ED8\u8BA4\u7EC8\u7AEF",
3377
+ summary: terminalSummary,
3378
+ toggle: {
3379
+ checked: sections.terminal,
2753
3380
  onChange: (next) => {
2754
- actions.setField(HEADER_ROUTES_FIELD, next);
3381
+ actions.setField(TERMINAL_ENABLED_FIELD, next);
2755
3382
  }
2756
- }
2757
- ),
2758
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
2759
- "\u72B6\u6001\uFF1A",
2760
- headerStatusText
2761
- ] })
2762
- ] })
3383
+ },
3384
+ controls: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
3385
+ PillChoice,
3386
+ {
3387
+ compact: true,
3388
+ items: TERMINAL_MODES,
3389
+ value: settings.terminalMode,
3390
+ onChange: (mode) => {
3391
+ actions.setField(TERMINAL_MODE_FIELD, mode);
3392
+ },
3393
+ ariaLabel: "\u7EC8\u7AEF\u5DE5\u5177"
3394
+ }
3395
+ ),
3396
+ children: [
3397
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: bodyLead, children: "Windows \u4E0A DSH \u7ED9\u6A21\u578B\u7684\u7EC8\u7AEF\u5DE5\u5177\u662F PowerShell\uFF0C\u800C\u6A21\u578B\u5BF9 bash \u8BED\u6CD5\u7684\u628A\u63E1\u660E\u663E\u66F4\u597D\u3002\u8FD9\u4E00\u680F\u628A\u7EC8\u7AEF \u6362\u6210 Git Bash\uFF1A\u6A21\u578B\u770B\u5230\u7684\u5DE5\u5177\u5C31\u53EB bash\u3001PowerShell \u90A3\u4E2A\u5DE5\u5177\u4F1A\u4ECE\u5B83\u7684\u5DE5\u5177\u5217\u8868\u91CC\u6D88\u5931\uFF0C \u547D\u4EE4\u91CC\u7684\u8DEF\u5F84\u4E0E\u5F15\u53F7\u6309 bash \u89C4\u5219\u5199\u3002\u672C\u673A\u4E0D\u9700\u8981\u88C5 Git for Windows \u5230\u9ED8\u8BA4\u76EE\u5F55\u2014\u2014\u63A2\u6D4B\u4F1A\u5148\u627E git\uFF0C\u518D\u7531\u540C\u4E00\u4E2A\u5B89\u88C5\u53CD\u63A8 bash\u3002\uFF08\u6863\u4F4D\u5728\u6807\u9898\u884C\u4E0A\uFF1A\u81EA\u52A8 / Git Bash / PowerShell\u3002\uFF09" }),
3398
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(DefaultTerminalBody, { settings, setField: actions.setField, hideMode: true })
3399
+ ]
3400
+ }
3401
+ )
2763
3402
  ] })
2764
3403
  ] });
2765
3404
  }
@@ -2793,7 +3432,7 @@ function QuickCommandsButton({
2793
3432
  releaseInputBridge(sid);
2794
3433
  };
2795
3434
  }, [inputActions, draft, sessionId, blank]);
2796
- if (settings.enabled !== true) return null;
3435
+ if (!activeSections(settings).quick) return null;
2797
3436
  const open = anchor !== null;
2798
3437
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2799
3438
  "button",
@@ -3176,7 +3815,20 @@ function apply(ctx) {
3176
3815
  HEADER_NAME_FIELD,
3177
3816
  HEADER_VALUE_FIELD,
3178
3817
  HEADER_ROUTES_FIELD,
3179
- OPTIMIZER_TIER_FIELD
3818
+ OPTIMIZER_TIER_FIELD,
3819
+ // 0.5.0 新增的用户配置:终端档位/路径(「恢复默认」也该把它们恢复)。
3820
+ TERMINAL_MODE_FIELD,
3821
+ TERMINAL_BASH_PATH_FIELD,
3822
+ // 五栏开关也清掉:清掉 = 回到"从没碰过这一栏"⇒ 全关(新装默认的样子)。
3823
+ // 若不清,恢复默认之后六栏还会保持之前打开的状态,与"默认关"的语义不符。
3824
+ KEYS_ENABLED_FIELD,
3825
+ MENU_ENABLED_FIELD,
3826
+ QUICK_ENABLED_FIELD,
3827
+ PANEL_ENABLED_FIELD,
3828
+ TERMINAL_ENABLED_FIELD,
3829
+ // 0.5.0 里那个「可选重启命令」字段已经删掉,但老文档里可能还留着值:
3830
+ // 顺手清掉,免得它永远躺在设置文件里没人认识。
3831
+ "restartCommand"
3180
3832
  ].map((field) => ({ op: "unset", path: [field] }))
3181
3833
  ).catch((error) => {
3182
3834
  console.error("[composer-ux] settings reset failed", error);
@@ -3329,7 +3981,7 @@ function apply(ctx) {
3329
3981
  () => installPanelStyle(
3330
3982
  () => {
3331
3983
  const settings = live.getSnapshot();
3332
- return settings.enabled && settings.panelScroll;
3984
+ return activeSections(settings).panel && settings.panelScroll;
3333
3985
  },
3334
3986
  (listener) => live.subscribe(listener)
3335
3987
  ),
@@ -3338,25 +3990,27 @@ function apply(ctx) {
3338
3990
  ctx.effect(() => {
3339
3991
  let dispose = null;
3340
3992
  const syncInterceptors = () => {
3341
- const enabled = live.getSnapshot().enabled;
3342
- if (enabled && dispose === null) {
3993
+ const settings = live.getSnapshot();
3994
+ const sections = activeSections(settings);
3995
+ const wanted = sections.keys || sections.menu || sections.quick;
3996
+ if (wanted && dispose === null) {
3343
3997
  dispose = installInterceptors({
3344
3998
  settings: () => live.getSnapshot(),
3345
3999
  // 「仅首次」由这里决定是否算进这一批:会话还是空的(blank)才带上。
3346
- promptsForSend: () => appendBatchForSend(book.getSnapshot(), currentBlankSession()),
4000
+ // 「快捷指令」栏关掉时这里直接给空批次 —— 这是唯一一处"关掉就不附加"的闸,
4001
+ // 键位发送与官方按钮两条路都从这里取批次,不需要各写一遍。
4002
+ promptsForSend: () => activeSections(live.getSnapshot()).quick ? appendBatchForSend(book.getSnapshot(), currentBlankSession()) : [],
3347
4003
  setMenu: (state2) => {
3348
4004
  menu2.set(state2);
3349
4005
  },
3350
4006
  menuOpen: () => menu2.getSnapshot() !== null
3351
4007
  });
3352
- } else if (!enabled) {
4008
+ } else if (!wanted) {
3353
4009
  dispose?.();
3354
4010
  dispose = null;
3355
- menu2.set(null);
3356
- panel.set(null);
3357
4011
  }
3358
- if (live.getSnapshot().menuMode !== "custom") menu2.set(null);
3359
- if (!live.getSnapshot().enabled) panel.set(null);
4012
+ if (settings.menuMode !== "custom" || !sections.menu) menu2.set(null);
4013
+ if (!sections.quick) panel.set(null);
3360
4014
  };
3361
4015
  syncInterceptors();
3362
4016
  const unsubscribe = live.subscribe(syncInterceptors);