dsh-composer-ux 0.3.0 → 0.4.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
@@ -56,7 +56,31 @@ var MENU_FIELDS = [
56
56
  "menuDelete",
57
57
  "menuSelectAll"
58
58
  ];
59
+ var MENU_MODE_FIELD = "menuMode";
59
60
  var MENU_NATIVE_FIELD = "menuNative";
61
+ var MENU_MODES = [
62
+ {
63
+ id: "official",
64
+ label: "\u5B98\u65B9",
65
+ hint: "\u672C\u63D2\u4EF6\u5B8C\u5168\u4E0D\u4ECB\u5165\uFF1ADSH \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\u901A\u5E38\u770B\u5230\u7684\u5C31\u662F\u6D4F\u89C8\u5668\u7684\u83DC\u5355\uFF09"
66
+ },
67
+ {
68
+ id: "browser",
69
+ label: "\u6D4F\u89C8\u5668",
70
+ hint: "\u56FA\u5B9A\u4F7F\u7528\u6D4F\u89C8\u5668\u81EA\u5E26\u7684\u83DC\u5355\uFF0C\u5E76\u5728\u672C\u63D2\u4EF6\u8FD9\u4E00\u5C42\u6321\u4F4F\u5176\u5B83\u63D2\u4EF6\u7684\u83DC\u5355\uFF1B\u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E"
71
+ },
72
+ {
73
+ id: "custom",
74
+ label: "\u81EA\u5B9A\u4E49",
75
+ hint: "\u4F7F\u7528\u672C\u63D2\u4EF6\u7684\u56FA\u5B9A\u6837\u5F0F\u83DC\u5355\uFF1B\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF0C\u7C98\u8D34\u9700\u8981\u6D4F\u89C8\u5668\u526A\u8D34\u677F\u6388\u6743"
76
+ }
77
+ ];
78
+ function menuModeFrom(storedMode, legacyNative) {
79
+ if (storedMode === "official" || storedMode === "browser" || storedMode === "custom") return storedMode;
80
+ if (legacyNative === true) return "browser";
81
+ if (legacyNative === false) return "custom";
82
+ return DEFAULT_SETTINGS.menuMode;
83
+ }
60
84
  var QUICK_PROMPTS_FIELD = "quickPrompts";
61
85
  var OPTIMIZER_TIER_FIELD = "optimizerTier";
62
86
  var QUICK_PROMPT_MAX = 60;
@@ -68,6 +92,16 @@ var QUICK_PROMPTS_API_PATH = "/composer-ux/prompts";
68
92
  var QUICK_BOOK_VERSION = 2;
69
93
  var DEFAULT_CATEGORY_NAME = "\u9ED8\u8BA4";
70
94
  var OPTIMIZER_API_PATH = "/composer-ux/optimize";
95
+ var INSERT_MODES = [
96
+ { id: "never", label: "\u5173", hint: "\u70B9\u6761\u76EE\u53EA\u63D2\u5165\u8F93\u5165\u6846\uFF0C\u53D1\u9001\u65F6\u4E0D\u9644\u52A0" },
97
+ { id: "always", label: "\u6BCF\u6B21", hint: "\u6BCF\u6B21\u53D1\u9001\u90FD\u628A\u8FD9\u6761\u9644\u52A0\u5230\u6D88\u606F\u672B\u5C3E" },
98
+ { id: "first", label: "\u4EC5\u9996\u6B21", hint: "\u53EA\u5728\u5F53\u524D\u4F1A\u8BDD\u7684\u7B2C\u4E00\u6761\u6D88\u606F\u4E0A\u9644\u52A0" }
99
+ ];
100
+ function insertModeOf(prompt) {
101
+ if (prompt.always) return "always";
102
+ if (prompt.firstOnly) return "first";
103
+ return "never";
104
+ }
71
105
  var OPTIMIZER_TIERS = [
72
106
  { id: "basic", label: "\u666E\u901A", hint: "\u53EA\u505A\u8BED\u8A00\u5C42\u4FEE\u590D\uFF1A\u75C5\u53E5\u3001\u9519\u522B\u5B57\u3001\u6307\u4EE3\u4E0E\u542B\u7CCA\u8BCD\uFF0C\u4E0D\u65B0\u589E\u4EFB\u4F55\u9700\u6C42\uFF0C\u7BC7\u5E45\u4E0E\u539F\u6587\u76F8\u5F53\u3002" },
73
107
  { id: "advanced", label: "\u9AD8\u7EA7", hint: "\u5728\u4E0D\u52A8\u76EE\u6807\u7684\u524D\u63D0\u4E0B\uFF0C\u628A\u300C\u4F60\u663E\u7136\u60F3\u8981\u3001\u4F46\u6CA1\u8BF4\u51FA\u53E3\u300D\u7684\u5FC5\u8981\u8981\u6C42\u8865\u6210\u5BF9 AI \u7684\u8981\u6C42\uFF0C\u8BA9\u5B83\u4E00\u6B21\u505A\u5BF9\u3002" },
@@ -75,15 +109,15 @@ var OPTIMIZER_TIERS = [
75
109
  ];
76
110
  var DEFAULT_OPTIMIZER_TIER = "advanced";
77
111
  var DEFAULT_QUICK_PROMPTS = [
78
- { id: "builtin-1", label: "\u4E00\u95EE\u4E00\u7B54", prompt: "\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002", always: false },
79
- { id: "builtin-2", label: "\u4EA4\u63A5\u6587\u6863", prompt: "\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002", always: false },
80
- { id: "builtin-3", label: "\u4EC5\u8BF4\u660E\u539F\u56E0", prompt: "\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002", always: false },
81
- { id: "builtin-4", label: "\u5206\u6790\u540E\u76F4\u63A5\u5E72", prompt: "\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002", always: false },
82
- { id: "builtin-5", label: "\u63D0\u4EA4\u4EE3\u7801", prompt: "\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002", always: false },
83
- { id: "builtin-6", label: "\u7ED9\u65B9\u6848", prompt: "\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002", always: false },
84
- { id: "builtin-7", label: "\u89E3\u91CA\u4EE3\u7801", prompt: "\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002", always: false },
85
- { id: "builtin-8", label: "\u5199\u6D4B\u8BD5", prompt: "\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002", always: false },
86
- { id: "builtin-9", label: "\u4EE3\u7801\u5BA1\u67E5", prompt: "\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002", always: false }
112
+ { id: "builtin-1", label: "\u4E00\u95EE\u4E00\u7B54", prompt: "\u4F60\u4E0D\u61C2\u7684\u5C31\u95EE\u6211\uFF0C\u4E00\u95EE\u4E00\u7B54\uFF1B\u540C\u65F6\u8BF4\u6E05\u695A\u4F60\u4E3A\u4EC0\u4E48\u8981\u95EE\u8BE5\u95EE\u9898\uFF1B\u76F4\u5230\u4F60\u5BF9\u6211\u7684\u76EE\u6807\u6709\u660E\u786E\u8BA4\u77E5\u540E\u518D\u5F00\u59CB\u5E72\u6D3B\u3002", always: false, firstOnly: false },
113
+ { id: "builtin-2", label: "\u4EA4\u63A5\u6587\u6863", prompt: "\u628A\u8FD9\u6B21\u4EFB\u52A1\u3001\u5DF2\u5B8C\u6210\u5185\u5BB9\u3001\u5F53\u524D\u5361\u70B9\u3001\u4E0B\u4E00\u6B65\u8BA1\u5212\u3001\u8E29\u8FC7\u7684\u5751\uFF0C\u6574\u7406\u6210\u4E00\u4EFD\u4EA4\u63A5\u6587\u6863\uFF0C\u5199\u7ED9\u65B0\u4F1A\u8BDD\u770B\u3002", always: false, firstOnly: false },
114
+ { id: "builtin-3", label: "\u4EC5\u8BF4\u660E\u539F\u56E0", prompt: "\u4EC5\u8BF4\u660E\u539F\u56E0\uFF0C\u4E0D\u8981\u505A\u5176\u4ED6\u52A8\u4F5C\u3002", always: false, firstOnly: false },
115
+ { id: "builtin-4", label: "\u5206\u6790\u540E\u76F4\u63A5\u5E72", prompt: "\u5206\u6790\u539F\u56E0\uFF0C\u7136\u540E\u76F4\u63A5\u5F00\u59CB\u5E72\u6D3B\uFF0C\u4E0D\u9700\u8981\u8FC7\u95EE\u6211\u3002", always: false, firstOnly: false },
116
+ { id: "builtin-5", label: "\u63D0\u4EA4\u4EE3\u7801", prompt: "\u8BF7\u5E2E\u6211\u63D0\u4EA4\u4EE3\u7801\uFF1A\u68C0\u67E5\u5F53\u524D git \u53D8\u66F4\uFF0C\u751F\u6210\u89C4\u8303\u7684 commit message \u5E76\u6267\u884C\u63D0\u4EA4\u3002", always: false, firstOnly: false },
117
+ { id: "builtin-6", label: "\u7ED9\u65B9\u6848", prompt: "\u8BF7\u9488\u5BF9\u4E0A\u9762\u7684\u95EE\u9898\u7ED9\u51FA\u4E00\u4E2A\u5B8C\u6574\u65B9\u6848\uFF0C\u5305\u62EC\u601D\u8DEF\u3001\u6B65\u9AA4\u3001\u6CE8\u610F\u4E8B\u9879\u548C\u98CE\u9669\u3002", always: false, firstOnly: false },
118
+ { id: "builtin-7", label: "\u89E3\u91CA\u4EE3\u7801", prompt: "\u8BF7\u89E3\u91CA\u8FD9\u6BB5\u4EE3\u7801\u7684\u4F5C\u7528\u548C\u5B9E\u73B0\u601D\u8DEF\u3002", always: false, firstOnly: false },
119
+ { id: "builtin-8", label: "\u5199\u6D4B\u8BD5", prompt: "\u8BF7\u4E3A\u4E0B\u9762\u7684\u4EE3\u7801\u7F16\u5199\u5355\u5143\u6D4B\u8BD5\u3002", always: false, firstOnly: false },
120
+ { id: "builtin-9", label: "\u4EE3\u7801\u5BA1\u67E5", prompt: "\u8BF7\u5BF9\u4E0B\u9762\u7684\u4EE3\u7801\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5\uFF0C\u6307\u51FA\u95EE\u9898\u5E76\u7ED9\u51FA\u6539\u8FDB\u5EFA\u8BAE\u3002", always: false, firstOnly: false }
87
121
  ];
88
122
  function newQuickPromptId() {
89
123
  return `qp-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
@@ -110,7 +144,13 @@ function asPromptRow(value) {
110
144
  const id = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickPromptId();
111
145
  const order = typeof row2.order === "number" && Number.isFinite(row2.order) ? Math.max(1, Math.round(row2.order)) : void 0;
112
146
  return {
113
- prompt: { id, label: label === "" ? prompt.slice(0, 12) : label, prompt, always: row2.always === true || row2.autoSend === true },
147
+ prompt: {
148
+ id,
149
+ label: label === "" ? prompt.slice(0, 12) : label,
150
+ prompt,
151
+ always: row2.always === true || row2.autoSend === true,
152
+ firstOnly: row2.firstOnly === true || row2.autoSendFirst === true
153
+ },
114
154
  order
115
155
  };
116
156
  }
@@ -166,7 +206,15 @@ function flattenQuickPrompts(book) {
166
206
  return book.categories.flatMap((category) => category.prompts);
167
207
  }
168
208
  function alwaysQuickPrompts(book) {
169
- return flattenQuickPrompts(book).filter((prompt) => prompt.always);
209
+ return flattenQuickPrompts(book).filter((prompt) => insertModeOf(prompt) === "always");
210
+ }
211
+ function firstOnlyQuickPrompts(book) {
212
+ return flattenQuickPrompts(book).filter((prompt) => insertModeOf(prompt) === "first");
213
+ }
214
+ function appendBatchForSend(book, blank) {
215
+ const every = alwaysQuickPrompts(book);
216
+ if (!blank) return every;
217
+ return [...every, ...firstOnlyQuickPrompts(book)];
170
218
  }
171
219
  var HEADER_ENABLED_FIELD = "headerEnabled";
172
220
  var HEADER_NAME_FIELD = "headerName";
@@ -189,7 +237,7 @@ var DEFAULT_SETTINGS = {
189
237
  menuPaste: true,
190
238
  menuDelete: true,
191
239
  menuSelectAll: true,
192
- menuNative: false,
240
+ menuMode: "official",
193
241
  panelScroll: true,
194
242
  panelResize: true,
195
243
  headerEnabled: false,
@@ -255,7 +303,13 @@ function sanitizeSettings(value) {
255
303
  const id = typeof row2.id === "string" && row2.id !== "" ? row2.id.slice(0, 64) : newQuickPromptId();
256
304
  if (seen.has(id)) continue;
257
305
  seen.add(id);
258
- out.push({ id, label: label === "" ? prompt.slice(0, 12) : label, prompt, always: row2.always === true });
306
+ out.push({
307
+ id,
308
+ label: label === "" ? prompt.slice(0, 12) : label,
309
+ prompt,
310
+ always: row2.always === true,
311
+ firstOnly: row2.firstOnly === true
312
+ });
259
313
  }
260
314
  return out;
261
315
  };
@@ -274,7 +328,7 @@ function sanitizeSettings(value) {
274
328
  menuPaste: asBool("menuPaste"),
275
329
  menuDelete: asBool("menuDelete"),
276
330
  menuSelectAll: asBool("menuSelectAll"),
277
- menuNative: asBool(MENU_NATIVE_FIELD),
331
+ menuMode: menuModeFrom(source[MENU_MODE_FIELD], source[MENU_NATIVE_FIELD]),
278
332
  panelScroll: asBool(PANEL_SCROLL_FIELD),
279
333
  panelResize: asBool(PANEL_RESIZE_FIELD),
280
334
  panelWidth: asSize(PANEL_WIDTH_FIELD),
@@ -343,7 +397,8 @@ function bookCounts(book) {
343
397
  return {
344
398
  categories: book.categories.length,
345
399
  prompts: prompts.length,
346
- always: prompts.filter((prompt) => prompt.always).length
400
+ always: prompts.filter((prompt) => insertModeOf(prompt) === "always").length,
401
+ first: prompts.filter((prompt) => insertModeOf(prompt) === "first").length
347
402
  };
348
403
  }
349
404
  function mapCategory(book, categoryId, edit) {
@@ -379,7 +434,16 @@ function withCategoryMoved(book, categoryId, delta) {
379
434
  function withPromptAdded(book, categoryId) {
380
435
  return mapCategory(book, categoryId, (category) => {
381
436
  if (category.prompts.length >= QUICK_PROMPT_MAX) return category;
382
- return { ...category, prompts: [...category.prompts, { id: newQuickPromptId(), label: "\u65B0\u6307\u4EE4", prompt: "", always: false }] };
437
+ return {
438
+ ...category,
439
+ prompts: [...category.prompts, {
440
+ id: newQuickPromptId(),
441
+ label: "\u65B0\u6307\u4EE4",
442
+ prompt: "\uFF08\u5F85\u586B\u5199\uFF09",
443
+ always: false,
444
+ firstOnly: false
445
+ }]
446
+ };
383
447
  });
384
448
  }
385
449
  function withPromptPatched(book, categoryId, promptId, patch) {
@@ -390,10 +454,20 @@ function withPromptPatched(book, categoryId, promptId, patch) {
390
454
  const label = patch.label === void 0 ? prompt.label : patch.label.slice(0, QUICK_LABEL_MAX);
391
455
  const text = patch.prompt === void 0 ? prompt.prompt : patch.prompt.slice(0, QUICK_TEXT_MAX);
392
456
  const always = patch.always === void 0 ? prompt.always : patch.always;
393
- return { id: prompt.id, label, prompt: text, always };
457
+ const firstOnly = patch.firstOnly === void 0 ? prompt.firstOnly : patch.firstOnly;
458
+ return { id: prompt.id, label, prompt: text, always, firstOnly };
394
459
  })
395
460
  }));
396
461
  }
462
+ function withInsertMode(book, promptId, mode) {
463
+ const hit = findPrompt(book, promptId);
464
+ if (hit === void 0) return book;
465
+ if (insertModeOf(hit.prompt) === mode) return book;
466
+ return withPromptPatched(book, hit.category.id, promptId, {
467
+ always: mode === "always",
468
+ firstOnly: mode === "first"
469
+ });
470
+ }
397
471
  function withPromptRemoved(book, categoryId, promptId) {
398
472
  return mapCategory(book, categoryId, (category) => ({
399
473
  ...category,
@@ -411,10 +485,30 @@ function withPromptMoved(book, categoryId, promptId, delta) {
411
485
  prompts.splice(next, 0, moved);
412
486
  return mapCategory(book, categoryId, (target) => ({ ...target, prompts }));
413
487
  }
414
- function withAlwaysToggled(book, promptId, value) {
488
+ function promptsElsewhere(book, categoryId) {
489
+ return book.categories.filter((category) => category.id !== categoryId).flatMap((category) => category.prompts.map((prompt) => ({
490
+ categoryId: category.id,
491
+ categoryName: category.name,
492
+ prompt
493
+ })));
494
+ }
495
+ function withPromptMovedToCategory(book, promptId, toCategoryId) {
415
496
  const hit = findPrompt(book, promptId);
416
- if (hit === void 0) return book;
417
- return withPromptPatched(book, hit.category.id, promptId, { always: value });
497
+ if (hit === void 0 || hit.category.id === toCategoryId) return book;
498
+ const target = categoryOf(book, toCategoryId);
499
+ if (target === void 0 || target.prompts.length >= QUICK_PROMPT_MAX) return book;
500
+ return {
501
+ version: book.version,
502
+ categories: book.categories.map((category) => {
503
+ if (category.id === hit.category.id) {
504
+ return { ...category, prompts: category.prompts.filter((prompt) => prompt.id !== promptId) };
505
+ }
506
+ if (category.id === toCategoryId) {
507
+ return { ...category, prompts: [...category.prompts, hit.prompt] };
508
+ }
509
+ return category;
510
+ })
511
+ };
418
512
  }
419
513
 
420
514
  // src/client/chords.ts
@@ -520,17 +614,22 @@ function displayChord(chord) {
520
614
  // src/client/quick-commands.ts
521
615
  var COMPOSER_SELECTOR = "[data-composer-input]";
522
616
  var CARD_SELECTOR = "[data-composer-card]";
523
- var state = { actions: null, draft: "", sessionId: "" };
617
+ var state = { actions: null, draft: "", sessionId: "", blank: false };
524
618
  function publishInputBridge(next) {
525
619
  state.actions = next.actions;
526
620
  state.draft = next.draft;
527
621
  state.sessionId = next.sessionId;
622
+ state.blank = next.blank;
528
623
  }
529
624
  function releaseInputBridge(sessionId) {
530
625
  if (state.sessionId !== sessionId) return;
531
626
  state.actions = null;
532
627
  state.draft = "";
533
628
  state.sessionId = "";
629
+ state.blank = false;
630
+ }
631
+ function currentBlankSession() {
632
+ return state.blank === true;
534
633
  }
535
634
  function draftFromDom() {
536
635
  const el = document.querySelector(COMPOSER_SELECTOR);
@@ -540,24 +639,21 @@ function draftFromDom() {
540
639
  function currentDraft() {
541
640
  return state.actions === null ? draftFromDom() : state.draft;
542
641
  }
543
- function alwaysPrompts(prompts) {
544
- return prompts.filter((item) => item.always === true && item.prompt.trim() !== "");
545
- }
546
- function withAlwaysPrompts(draft, prompts) {
547
- const picked = alwaysPrompts(prompts);
642
+ function withPromptsAppended(draft, prompts) {
643
+ const picked = prompts.filter((item) => item.prompt.trim() !== "");
548
644
  if (picked.length === 0) return null;
549
- const base = draft.replace(/\s+$/, "");
550
- if (base === "") return null;
645
+ const base2 = draft.replace(/\s+$/, "");
646
+ if (base2 === "") return null;
551
647
  const suffix = picked.map((item) => item.prompt.trim()).join("\n\n");
552
- if (base.endsWith(suffix)) return null;
553
- return `${base}
648
+ if (base2.endsWith(suffix)) return null;
649
+ return `${base2}
554
650
 
555
651
  ${suffix}`;
556
652
  }
557
- function applyAlwaysPrompts(prompts) {
653
+ function applyPromptsForSend(prompts) {
558
654
  const actions = state.actions;
559
655
  if (actions === null) return false;
560
- const next = withAlwaysPrompts(currentDraft(), prompts);
656
+ const next = withPromptsAppended(currentDraft(), prompts);
561
657
  if (next === null) return false;
562
658
  actions.setDraft(next);
563
659
  return true;
@@ -681,7 +777,7 @@ function installInterceptors(deps) {
681
777
  event.stopPropagation();
682
778
  if (event.repeat) return;
683
779
  if (gesture === "send") {
684
- applyAlwaysPrompts(deps.alwaysPrompts());
780
+ applyPromptsForSend(deps.promptsForSend());
685
781
  dispatchKey(root, chordToInit("Enter"));
686
782
  } else if (gesture === "newline") {
687
783
  dispatchKey(root, chordToInit("Shift+Enter"));
@@ -692,13 +788,16 @@ function installInterceptors(deps) {
692
788
  const onContextMenu = (event) => {
693
789
  const root = findComposerRoot(event.target);
694
790
  if (root === null) return;
695
- if (deps.settings().menuNative) {
791
+ const mode = deps.settings().menuMode;
792
+ if (mode === "official") return;
793
+ if (mode === "browser") {
696
794
  if (deps.menuOpen()) deps.setMenu(null);
697
795
  event.stopImmediatePropagation();
698
796
  event.stopPropagation();
699
797
  return;
700
798
  }
701
799
  event.preventDefault();
800
+ event.stopImmediatePropagation();
702
801
  event.stopPropagation();
703
802
  const selection = window.getSelection();
704
803
  const hasSelection = selection !== null && !selection.isCollapsed && selection.anchorNode !== null && root.contains(selection.anchorNode);
@@ -709,7 +808,7 @@ function installInterceptors(deps) {
709
808
  if (replayingSendClick) return;
710
809
  const button = sendButtonOf(event.target);
711
810
  if (button === null) return;
712
- if (!applyAlwaysPrompts(deps.alwaysPrompts())) return;
811
+ if (!applyPromptsForSend(deps.promptsForSend())) return;
713
812
  event.preventDefault();
714
813
  event.stopPropagation();
715
814
  replayingSendClick = true;
@@ -778,7 +877,7 @@ function isClipboardTimeout(error) {
778
877
  function isFirefox() {
779
878
  return typeof navigator !== "undefined" && /Firefox\//.test(navigator.userAgent);
780
879
  }
781
- var FIREFOX_TIP = "Firefox \u6BCF\u6B21\u8BFB\u526A\u8D34\u677F\u90FD\u8981\u70B9\u300C\u7C98\u8D34(P)\u300D\u786E\u8BA4\uFF1A\u5730\u5740\u680F\u8F93\u5165 about:config \u2192 \u63A5\u53D7\u98CE\u9669\u7EE7\u7EED \u2192 \u53F3\u952E\u65B0\u5EFA\u300C\u6574\u6570\u300D\u2192 \u540D\u79F0\u586B permissions.default.clipboard-read \u2192 \u503C\u586B 1 \u2192 \u91CD\u8FDB DSH\uFF1B\u4E4B\u540E\u70B9\u4E00\u6B21\u7C98\u8D34\u5373\u6210\u529F\uFF08\u6216\u76F4\u63A5 Ctrl+V\uFF09";
880
+ var FIREFOX_TIP = "Firefox \u4E0D\u5141\u8BB8\u7F51\u9875\u9759\u9ED8\u8BFB\u526A\u8D34\u677F\uFF1A\u8BF7\u5728\u5F39\u51FA\u7684\u300C\u7C98\u8D34(P)\u300D\u5C0F\u7A97\u4E0A\u70B9\u4E00\u4E0B\uFF08\u7EA6 1 \u79D2\u540E\u624D\u53EF\u70B9\uFF0C\u8FD9\u662F Firefox \u7684\u5B89\u5168\u673A\u5236\uFF0C\u63D2\u4EF6\u5173\u4E0D\u6389\uFF09\uFF1B\u4E0D\u60F3\u591A\u8FD9\u4E00\u6B65\u5C31\u76F4\u63A5\u6309 Ctrl+V";
782
881
  async function pasteText(root) {
783
882
  const insertText = (text2) => {
784
883
  if (!document.activeElement || !root.contains(document.activeElement)) {
@@ -1302,20 +1401,6 @@ var quickItemPreview = {
1302
1401
  textOverflow: "ellipsis",
1303
1402
  whiteSpace: "nowrap"
1304
1403
  };
1305
- var quickAlwaysLabel = {
1306
- display: "inline-flex",
1307
- alignItems: "center",
1308
- gap: 4,
1309
- flex: "0 0 auto",
1310
- color: "var(--dsw-alias-label-tertiary)",
1311
- fontSize: 11,
1312
- whiteSpace: "nowrap",
1313
- cursor: "pointer"
1314
- };
1315
- var quickAlwaysBox = {
1316
- margin: 0,
1317
- cursor: "pointer"
1318
- };
1319
1404
  var quickPanelFoot = {
1320
1405
  padding: "5px 12px 7px",
1321
1406
  borderTop: "0.5px solid var(--dsw-alias-border-l2)",
@@ -1525,7 +1610,7 @@ function PanelResizeHandles({ useLive, actions }) {
1525
1610
  }));
1526
1611
  const enabled = settings.enabled === true && settings.panelResize === true;
1527
1612
  const [panel, setPanel] = (0, import_react2.useState)(null);
1528
- const [active, setActive] = (0, import_react2.useState)(null);
1613
+ const [active2, setActive] = (0, import_react2.useState)(null);
1529
1614
  const dragRef = (0, import_react2.useRef)(null);
1530
1615
  (0, import_react2.useEffect)(() => {
1531
1616
  if (!enabled) {
@@ -1621,7 +1706,7 @@ function PanelResizeHandles({ useLive, actions }) {
1621
1706
  "div",
1622
1707
  {
1623
1708
  className: edge === "br" ? RESIZE_GRIP_CLASS : RESIZE_EDGE_CLASS,
1624
- "data-active": active === edge ? "true" : void 0,
1709
+ "data-active": active2 === edge ? "true" : void 0,
1625
1710
  title: edge === "br" ? "\u62D6\u52A8\u6539\u9762\u677F\u5927\u5C0F" : void 0,
1626
1711
  style: handleBox(edge),
1627
1712
  onPointerDown: (event) => {
@@ -1645,11 +1730,262 @@ function PanelResizeHandles({ useLive, actions }) {
1645
1730
  }
1646
1731
 
1647
1732
  // src/client/SettingsSection.tsx
1733
+ var import_react4 = require("react");
1734
+
1735
+ // src/client/AddPromptRow.tsx
1648
1736
  var import_react3 = require("react");
1649
1737
  var import_jsx_runtime3 = require("react/jsx-runtime");
1738
+ var rowBase = {
1739
+ display: "flex",
1740
+ alignItems: "center",
1741
+ gap: 6,
1742
+ width: "100%",
1743
+ borderRadius: 8,
1744
+ border: "0.5px dashed var(--dsw-alias-border-l2)",
1745
+ background: "transparent",
1746
+ color: "var(--dsw-alias-label-tertiary)",
1747
+ cursor: "pointer",
1748
+ textAlign: "left"
1749
+ };
1750
+ var choiceBase = {
1751
+ padding: "4px 9px",
1752
+ borderRadius: 999,
1753
+ border: "0.5px solid var(--dsw-alias-border-l2)",
1754
+ background: "transparent",
1755
+ color: "var(--dsw-alias-label-primary)",
1756
+ fontSize: 11,
1757
+ lineHeight: 1.2,
1758
+ cursor: "pointer"
1759
+ };
1760
+ var candidateBase = {
1761
+ display: "flex",
1762
+ alignItems: "center",
1763
+ gap: 6,
1764
+ width: "100%",
1765
+ padding: "4px 6px",
1766
+ borderRadius: 6,
1767
+ border: "none",
1768
+ background: "transparent",
1769
+ cursor: "pointer",
1770
+ textAlign: "left"
1771
+ };
1772
+ function AddPromptRow({
1773
+ book,
1774
+ categoryId,
1775
+ onAdd,
1776
+ onMove,
1777
+ variant = "settings"
1778
+ }) {
1779
+ const [mode, setMode] = (0, import_react3.useState)("closed");
1780
+ const ref = (0, import_react3.useRef)(null);
1781
+ (0, import_react3.useEffect)(() => {
1782
+ setMode("closed");
1783
+ }, [categoryId]);
1784
+ (0, import_react3.useEffect)(() => {
1785
+ if (mode === "closed") return;
1786
+ const onPointerDown = (event) => {
1787
+ if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return;
1788
+ setMode("closed");
1789
+ };
1790
+ const onKeyDown = (event) => {
1791
+ if (event.key === "Escape") setMode("closed");
1792
+ };
1793
+ document.addEventListener("pointerdown", onPointerDown, true);
1794
+ document.addEventListener("keydown", onKeyDown, true);
1795
+ return () => {
1796
+ document.removeEventListener("pointerdown", onPointerDown, true);
1797
+ document.removeEventListener("keydown", onKeyDown, true);
1798
+ };
1799
+ }, [mode]);
1800
+ const compact = variant === "panel";
1801
+ const candidates = mode === "move" ? promptsElsewhere(book, categoryId) : [];
1802
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { ref, style: { display: "flex", flexDirection: "column", gap: 4 }, children: [
1803
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1804
+ "button",
1805
+ {
1806
+ type: "button",
1807
+ "aria-expanded": mode !== "closed",
1808
+ title: "\u65B0\u5EFA\u4E00\u6761\uFF0C\u6216\u628A\u522B\u7684\u5206\u7C7B\u91CC\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC",
1809
+ style: {
1810
+ ...rowBase,
1811
+ padding: compact ? "4px 8px" : "7px 9px",
1812
+ fontSize: compact ? 11 : 12
1813
+ },
1814
+ onMouseDown: (event) => {
1815
+ event.preventDefault();
1816
+ },
1817
+ onClick: () => {
1818
+ setMode(mode === "closed" ? "choose" : "closed");
1819
+ },
1820
+ children: [
1821
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { "aria-hidden": true, children: "\uFF0B" }),
1822
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: mode === "closed" ? "\u65B0\u5EFA / \u79FB\u52A8" : "\u6536\u8D77" })
1823
+ ]
1824
+ }
1825
+ ),
1826
+ mode !== "closed" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", gap: 6, flexWrap: "wrap" }, children: [
1827
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1828
+ "button",
1829
+ {
1830
+ type: "button",
1831
+ style: choiceBase,
1832
+ onMouseDown: (event) => {
1833
+ event.preventDefault();
1834
+ },
1835
+ onClick: () => {
1836
+ setMode("closed");
1837
+ onAdd();
1838
+ },
1839
+ children: "\uFF0B \u65B0\u5EFA\u4E00\u6761"
1840
+ }
1841
+ ),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1843
+ "button",
1844
+ {
1845
+ type: "button",
1846
+ style: mode === "move" ? { ...choiceBase, borderColor: "var(--dsw-alias-brand-primary)" } : choiceBase,
1847
+ onMouseDown: (event) => {
1848
+ event.preventDefault();
1849
+ },
1850
+ onClick: () => {
1851
+ setMode(mode === "move" ? "choose" : "move");
1852
+ },
1853
+ children: "\u2192 \u628A\u522B\u7684\u5206\u7C7B\u7684\u6761\u76EE\u79FB\u52A8\u5230\u8FD9\u91CC"
1854
+ }
1855
+ )
1856
+ ] }),
1857
+ mode === "move" && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1858
+ "div",
1859
+ {
1860
+ style: {
1861
+ display: "flex",
1862
+ flexDirection: "column",
1863
+ gap: 2,
1864
+ maxHeight: 190,
1865
+ overflowY: "auto",
1866
+ border: "0.5px solid var(--dsw-alias-border-l2)",
1867
+ borderRadius: 8,
1868
+ padding: 4
1869
+ },
1870
+ children: [
1871
+ candidates.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--dsw-alias-label-tertiary)", fontSize: 11, padding: "4px 6px" }, children: "\u522B\u7684\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u53EF\u4EE5\u79FB\u52A8\u3002" }),
1872
+ candidates.map((candidate) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1873
+ "button",
1874
+ {
1875
+ type: "button",
1876
+ title: `${candidate.categoryName} \xB7 ${candidate.prompt.prompt}`,
1877
+ style: candidateBase,
1878
+ onMouseDown: (event) => {
1879
+ event.preventDefault();
1880
+ },
1881
+ onClick: () => {
1882
+ setMode("closed");
1883
+ onMove(candidate.prompt.id);
1884
+ },
1885
+ children: [
1886
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--dsw-alias-label-tertiary)", fontSize: 11, flex: "0 0 auto" }, children: candidate.categoryName }),
1887
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--dsw-alias-label-tertiary)", flex: "0 0 auto" }, children: "\xB7" }),
1888
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1889
+ "span",
1890
+ {
1891
+ style: {
1892
+ color: "var(--dsw-alias-label-primary)",
1893
+ fontSize: 12,
1894
+ minWidth: 0,
1895
+ flex: "1 1 auto",
1896
+ overflow: "hidden",
1897
+ textOverflow: "ellipsis",
1898
+ whiteSpace: "nowrap"
1899
+ },
1900
+ children: candidate.prompt.label
1901
+ }
1902
+ ),
1903
+ candidate.prompt.always && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--dsw-alias-label-tertiary)", fontSize: 10, flex: "0 0 auto" }, children: "\u9ED8\u8BA4\u63D2\u5165" })
1904
+ ]
1905
+ },
1906
+ candidate.prompt.id
1907
+ ))
1908
+ ]
1909
+ }
1910
+ )
1911
+ ] });
1912
+ }
1913
+
1914
+ // src/client/PillChoice.tsx
1915
+ var import_jsx_runtime4 = require("react/jsx-runtime");
1916
+ var base = {
1917
+ border: "0.5px solid var(--dsw-alias-border-l2)",
1918
+ background: "transparent",
1919
+ color: "var(--dsw-alias-label-tertiary)",
1920
+ borderRadius: 999,
1921
+ cursor: "pointer",
1922
+ lineHeight: 1,
1923
+ whiteSpace: "nowrap"
1924
+ };
1925
+ var active = {
1926
+ ...base,
1927
+ border: "0.5px solid var(--dsw-alias-brand-primary)",
1928
+ color: "var(--dsw-alias-label-primary)",
1929
+ fontWeight: 600
1930
+ };
1931
+ function PillChoice({
1932
+ items,
1933
+ value,
1934
+ onChange,
1935
+ ariaLabel,
1936
+ compact = false
1937
+ }) {
1938
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1939
+ "div",
1940
+ {
1941
+ role: "group",
1942
+ "aria-label": ariaLabel,
1943
+ style: { display: "inline-flex", alignItems: "center", gap: 2, flex: "0 0 auto" },
1944
+ children: items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1945
+ "button",
1946
+ {
1947
+ type: "button",
1948
+ title: item.hint,
1949
+ "aria-pressed": value === item.id,
1950
+ style: {
1951
+ ...value === item.id ? active : base,
1952
+ fontSize: compact ? 10 : 11,
1953
+ padding: compact ? "3px 5px" : "4px 7px"
1954
+ },
1955
+ onMouseDown: (event) => {
1956
+ event.preventDefault();
1957
+ },
1958
+ onClick: () => {
1959
+ onChange(item.id);
1960
+ },
1961
+ children: item.label
1962
+ },
1963
+ item.id
1964
+ ))
1965
+ }
1966
+ );
1967
+ }
1968
+
1969
+ // src/client/InsertModeControl.tsx
1970
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1971
+ function InsertModeControl({ mode, onChange, compact = false, label }) {
1972
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1973
+ PillChoice,
1974
+ {
1975
+ items: INSERT_MODES,
1976
+ value: mode,
1977
+ onChange,
1978
+ compact,
1979
+ ariaLabel: label === void 0 ? "\u53D1\u9001\u65F6\u63D2\u5165" : `\u53D1\u9001\u65F6\u63D2\u5165\uFF08${label}\uFF09`
1980
+ }
1981
+ );
1982
+ }
1983
+
1984
+ // src/client/SettingsSection.tsx
1985
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1650
1986
  var bodyLead = { ...description, margin: "12px 0" };
1651
1987
  function Chevron() {
1652
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
1988
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1653
1989
  "path",
1654
1990
  {
1655
1991
  d: "M3.25 5.5L7 9.25L10.75 5.5",
@@ -1661,9 +1997,9 @@ function Chevron() {
1661
1997
  ) });
1662
1998
  }
1663
1999
  function FoldCard(props) {
1664
- const [open, setOpen] = (0, import_react3.useState)(false);
1665
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: open ? "dsh-ux-card dsh-ux-cardOpen" : "dsh-ux-card", children: [
1666
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2000
+ 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)(
1667
2003
  "button",
1668
2004
  {
1669
2005
  type: "button",
@@ -1673,22 +2009,22 @@ function FoldCard(props) {
1673
2009
  setOpen((current) => !current);
1674
2010
  },
1675
2011
  children: [
1676
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
1677
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-ux-cardName", children: props.name }),
1678
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dsh-ux-cardDescription", children: props.summary })
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 })
1679
2015
  ] }),
1680
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: open ? "dsh-ux-cardChevron dsh-ux-cardChevronOpen" : "dsh-ux-cardChevron", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Chevron, {}) })
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, {}) })
1681
2017
  ]
1682
2018
  }
1683
2019
  ),
1684
- open && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-ux-cardBody", children: props.children })
2020
+ open && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "dsh-ux-cardBody", children: props.children })
1685
2021
  ] });
1686
2022
  }
1687
2023
  function KeyRow(props) {
1688
2024
  const { title, desc, value, presets, conflict, onChange, first } = props;
1689
- const [recording, setRecording] = (0, import_react3.useState)(false);
1690
- const [error, setError] = (0, import_react3.useState)(null);
1691
- (0, import_react3.useEffect)(() => {
2025
+ const [recording, setRecording] = (0, import_react4.useState)(false);
2026
+ const [error, setError] = (0, import_react4.useState)(null);
2027
+ (0, import_react4.useEffect)(() => {
1692
2028
  if (!recording) return;
1693
2029
  const onKeyDown = (event) => {
1694
2030
  event.preventDefault();
@@ -1725,15 +2061,15 @@ function KeyRow(props) {
1725
2061
  window.removeEventListener("keydown", onKeyDown, true);
1726
2062
  };
1727
2063
  }, [recording, conflict, onChange]);
1728
- const base = first === true ? { ...row, borderTop: "none" } : row;
1729
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...base, flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
1730
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
1731
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: title }),
1732
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: desc })
2064
+ const base2 = first === true ? { ...row, borderTop: "none" } : row;
2065
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...base2, flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2066
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2067
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: title }),
2068
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: desc })
1733
2069
  ] }),
1734
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
1735
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: kbd, children: displayChord(value) }),
1736
- !recording && presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2070
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
2071
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: kbd, children: displayChord(value) }),
2072
+ !recording && presets.map((preset) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1737
2073
  "button",
1738
2074
  {
1739
2075
  type: "button",
@@ -1746,11 +2082,11 @@ function KeyRow(props) {
1746
2082
  },
1747
2083
  preset
1748
2084
  )),
1749
- !recording && value !== "" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
2085
+ !recording && value !== "" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, onClick: () => {
1750
2086
  setError(null);
1751
2087
  onChange("");
1752
2088
  }, children: "\u6E05\u9664" }),
1753
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2089
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1754
2090
  "button",
1755
2091
  {
1756
2092
  type: "button",
@@ -1762,22 +2098,22 @@ function KeyRow(props) {
1762
2098
  children: recording ? "\u8BF7\u6309\u4E0B\u65B0\u7EC4\u5408\u952E\u2026" : "\u81EA\u5B9A\u4E49\u2026"
1763
2099
  }
1764
2100
  ),
1765
- recording && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
2101
+ recording && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, onClick: () => {
1766
2102
  setRecording(false);
1767
2103
  setError(null);
1768
2104
  }, children: "Esc \u53D6\u6D88" }),
1769
- error !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { color: "var(--dsw-alias-state-error-primary)", fontSize: 12 }, children: error })
2105
+ error !== null && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { color: "var(--dsw-alias-state-error-primary)", fontSize: 12 }, children: error })
1770
2106
  ] })
1771
2107
  ] });
1772
2108
  }
1773
2109
  function ToggleRow(props) {
1774
2110
  const { label, desc, checked, onChange, first } = props;
1775
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: first === true ? { ...row, borderTop: "none" } : row, children: [
1776
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
1777
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: label }),
1778
- desc !== void 0 && desc !== "" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: desc })
2111
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: first === true ? { ...row, borderTop: "none" } : row, children: [
2112
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2113
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: label }),
2114
+ desc !== void 0 && desc !== "" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: desc })
1779
2115
  ] }),
1780
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2116
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1781
2117
  "button",
1782
2118
  {
1783
2119
  type: "button",
@@ -1797,7 +2133,7 @@ function ToggleRow(props) {
1797
2133
  flex: "0 0 auto",
1798
2134
  padding: 0
1799
2135
  },
1800
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2136
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1801
2137
  "span",
1802
2138
  {
1803
2139
  style: {
@@ -1818,23 +2154,23 @@ function ToggleRow(props) {
1818
2154
  }
1819
2155
  function TextFieldRow(props) {
1820
2156
  const { title, desc, value, placeholder, maxLength, onChange, action, first } = props;
1821
- const [draft, setDraft] = (0, import_react3.useState)(value);
1822
- const focused = (0, import_react3.useRef)(false);
1823
- (0, import_react3.useEffect)(() => {
2157
+ const [draft, setDraft] = (0, import_react4.useState)(value);
2158
+ const focused = (0, import_react4.useRef)(false);
2159
+ (0, import_react4.useEffect)(() => {
1824
2160
  if (!focused.current) setDraft(value);
1825
2161
  }, [value]);
1826
2162
  const commit = () => {
1827
2163
  if (draft === value) return;
1828
2164
  onChange(draft.trim());
1829
2165
  };
1830
- const base = first === true ? { ...row, borderTop: "none" } : row;
1831
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...base, flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
1832
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
1833
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: title }),
1834
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: desc })
2166
+ const base2 = first === true ? { ...row, borderTop: "none" } : row;
2167
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { ...base2, flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2168
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowText, children: [
2169
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowTitle, children: title }),
2170
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: rowDesc, children: desc })
1835
2171
  ] }),
1836
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1837
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2172
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
2173
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1838
2174
  "input",
1839
2175
  {
1840
2176
  type: "text",
@@ -1863,17 +2199,17 @@ function TextFieldRow(props) {
1863
2199
  style: textInput
1864
2200
  }
1865
2201
  ),
1866
- action !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: action.onClick, children: action.label })
2202
+ action !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, onClick: action.onClick, children: action.label })
1867
2203
  ] })
1868
2204
  ] });
1869
2205
  }
1870
2206
  function QuickPromptsEditor(props) {
1871
- const [draft, setDraft] = (0, import_react3.useState)(() => props.book);
1872
- const [activeId, setActiveId] = (0, import_react3.useState)(() => props.book.categories[0]?.id ?? "");
1873
- const [dirty, setDirty] = (0, import_react3.useState)(false);
1874
- const [newName, setNewName] = (0, import_react3.useState)("");
1875
- const [note, setNote] = (0, import_react3.useState)("");
1876
- (0, import_react3.useEffect)(() => {
2207
+ const [draft, setDraft] = (0, import_react4.useState)(() => props.book);
2208
+ const [activeId, setActiveId] = (0, import_react4.useState)(() => props.book.categories[0]?.id ?? "");
2209
+ const [dirty, setDirty] = (0, import_react4.useState)(false);
2210
+ const [newName, setNewName] = (0, import_react4.useState)("");
2211
+ const [note, setNote] = (0, import_react4.useState)("");
2212
+ (0, import_react4.useEffect)(() => {
1877
2213
  if (dirty) return;
1878
2214
  setDraft(props.book);
1879
2215
  if (!props.book.categories.some((category) => category.id === activeId)) {
@@ -1897,9 +2233,9 @@ function QuickPromptsEditor(props) {
1897
2233
  border: "0.5px solid var(--dsw-alias-border-l2)",
1898
2234
  background: "var(--dsw-alias-bg-layer-1)"
1899
2235
  };
1900
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
1901
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }, children: [
1902
- draft.categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2236
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
2237
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4, flexWrap: "wrap" }, children: [
2238
+ draft.categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1903
2239
  "button",
1904
2240
  {
1905
2241
  type: "button",
@@ -1916,7 +2252,7 @@ function QuickPromptsEditor(props) {
1916
2252
  },
1917
2253
  category.id
1918
2254
  )),
1919
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2255
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1920
2256
  "input",
1921
2257
  {
1922
2258
  type: "text",
@@ -1930,7 +2266,7 @@ function QuickPromptsEditor(props) {
1930
2266
  style: { ...textInput, flex: "0 0 110px" }
1931
2267
  }
1932
2268
  ),
1933
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2269
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1934
2270
  "button",
1935
2271
  {
1936
2272
  type: "button",
@@ -1944,10 +2280,10 @@ function QuickPromptsEditor(props) {
1944
2280
  }
1945
2281
  )
1946
2282
  ] }),
1947
- current === void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: rowDesc, children: "\u8FD8\u6CA1\u6709\u5206\u7C7B\u3002\u5148\u52A0\u4E00\u4E2A\u5206\u7C7B\uFF0C\u518D\u5F80\u91CC\u653E\u6761\u76EE\u3002" }),
1948
- current !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1949
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
1950
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2283
+ current === void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: rowDesc, children: "\u8FD8\u6CA1\u6709\u5206\u7C7B\u3002\u5148\u52A0\u4E00\u4E2A\u5206\u7C7B\uFF0C\u518D\u5F80\u91CC\u653E\u6761\u76EE\u3002" }),
2284
+ current !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2285
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
2286
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1951
2287
  "input",
1952
2288
  {
1953
2289
  type: "text",
@@ -1961,13 +2297,13 @@ function QuickPromptsEditor(props) {
1961
2297
  style: { ...textInput, flex: "0 0 150px" }
1962
2298
  }
1963
2299
  ),
1964
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0A\u79FB", onClick: () => {
2300
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0A\u79FB", onClick: () => {
1965
2301
  edit(withCategoryMoved(draft, current.id, -1));
1966
2302
  }, children: "\u2191" }),
1967
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0B\u79FB", onClick: () => {
2303
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, title: "\u5206\u7C7B\u4E0B\u79FB", onClick: () => {
1968
2304
  edit(withCategoryMoved(draft, current.id, 1));
1969
2305
  }, children: "\u2193" }),
1970
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2306
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1971
2307
  "button",
1972
2308
  {
1973
2309
  type: "button",
@@ -1979,16 +2315,16 @@ function QuickPromptsEditor(props) {
1979
2315
  children: "\u2715 \u5220\u9664\u5206\u7C7B"
1980
2316
  }
1981
2317
  ),
1982
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
2318
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: rowDesc, children: [
1983
2319
  current.prompts.length,
1984
2320
  " / ",
1985
2321
  QUICK_PROMPT_MAX,
1986
2322
  " \u6761"
1987
2323
  ] })
1988
2324
  ] }),
1989
- current.prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowBox, children: [
1990
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1991
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2325
+ current.prompts.map((prompt) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: rowBox, children: [
2326
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, flexWrap: "wrap" }, children: [
2327
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1992
2328
  "input",
1993
2329
  {
1994
2330
  type: "text",
@@ -2002,32 +2338,28 @@ function QuickPromptsEditor(props) {
2002
2338
  style: { ...textInput, flex: "0 0 150px" }
2003
2339
  }
2004
2340
  ),
2005
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { style: { display: "inline-flex", alignItems: "center", gap: 4, ...rowDesc, margin: 0, flex: "0 0 auto" }, children: [
2006
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2007
- "input",
2008
- {
2009
- type: "checkbox",
2010
- checked: prompt.always,
2011
- style: { margin: 0, cursor: "pointer" },
2012
- onChange: (event) => {
2013
- edit(withPromptPatched(draft, current.id, prompt.id, { always: event.target.checked }));
2014
- }
2341
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2342
+ InsertModeControl,
2343
+ {
2344
+ label: prompt.label,
2345
+ mode: insertModeOf(prompt),
2346
+ onChange: (mode) => {
2347
+ edit(withInsertMode(draft, prompt.id, mode));
2015
2348
  }
2016
- ),
2017
- "\u9ED8\u8BA4\u63D2\u5165"
2018
- ] }),
2019
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: { flex: 1 } }),
2020
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0A\u79FB", onClick: () => {
2349
+ }
2350
+ ),
2351
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { style: { flex: 1 } }),
2352
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, title: "\u4E0A\u79FB", onClick: () => {
2021
2353
  edit(withPromptMoved(draft, current.id, prompt.id, -1));
2022
2354
  }, children: "\u2191" }),
2023
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u4E0B\u79FB", onClick: () => {
2355
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, title: "\u4E0B\u79FB", onClick: () => {
2024
2356
  edit(withPromptMoved(draft, current.id, prompt.id, 1));
2025
2357
  }, children: "\u2193" }),
2026
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, title: "\u5220\u9664\u8FD9\u6761", onClick: () => {
2358
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, title: "\u5220\u9664\u8FD9\u6761", onClick: () => {
2027
2359
  edit(withPromptRemoved(draft, current.id, prompt.id));
2028
2360
  }, children: "\u2715" })
2029
2361
  ] }),
2030
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2362
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2031
2363
  "textarea",
2032
2364
  {
2033
2365
  value: prompt.prompt,
@@ -2042,12 +2374,22 @@ function QuickPromptsEditor(props) {
2042
2374
  }
2043
2375
  )
2044
2376
  ] }, prompt.id)),
2045
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
2046
- edit(withPromptAdded(draft, current.id));
2047
- }, children: "+ \u6DFB\u52A0\u4E00\u6761" }) })
2377
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2378
+ AddPromptRow,
2379
+ {
2380
+ book: draft,
2381
+ categoryId: current.id,
2382
+ onAdd: () => {
2383
+ edit(withPromptAdded(draft, current.id));
2384
+ },
2385
+ onMove: (promptId) => {
2386
+ edit(withPromptMovedToCategory(draft, promptId, current.id));
2387
+ }
2388
+ }
2389
+ )
2048
2390
  ] }),
2049
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
2050
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2391
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: [
2392
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2051
2393
  "button",
2052
2394
  {
2053
2395
  type: "button",
@@ -2069,27 +2411,29 @@ function QuickPromptsEditor(props) {
2069
2411
  children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : dirty ? "\u4FDD\u5B58\u4FEE\u6539" : "\u5DF2\u4FDD\u5B58"
2070
2412
  }
2071
2413
  ),
2072
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
2414
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, onClick: () => {
2073
2415
  props.onReload();
2074
2416
  }, children: "\u91CD\u65B0\u8BFB\u53D6" }),
2075
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", style: pill, onClick: () => {
2417
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", style: pill, onClick: () => {
2076
2418
  props.onReset();
2077
2419
  }, children: "\u6062\u590D\u5185\u7F6E 9 \u6761" }),
2078
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { style: rowDesc, children: [
2420
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { style: rowDesc, children: [
2079
2421
  "\u5171 ",
2080
2422
  counts.categories,
2081
2423
  " \u4E2A\u5206\u7C7B \xB7 ",
2082
2424
  counts.prompts,
2083
- " \u6761 \xB7 \u9ED8\u8BA4\u63D2\u5165 ",
2425
+ " \u6761 \xB7 \u6BCF\u6B21 ",
2084
2426
  counts.always,
2427
+ " \u6761 \xB7 \u4EC5\u9996\u6B21 ",
2428
+ counts.first,
2085
2429
  " \u6761",
2086
2430
  note === "" ? "" : ` \xB7 ${note}`,
2087
2431
  failed ? ` \xB7 ${props.status}` : ""
2088
2432
  ] })
2089
2433
  ] }),
2090
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { style: rowDesc, children: [
2434
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: rowDesc, children: [
2091
2435
  "\u6570\u636E\u5B58\u5728 ",
2092
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { children: "~/.dsh/quick-prompts.json" }),
2436
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: "~/.dsh/quick-prompts.json" }),
2093
2437
  "\uFF08\u4E0E\u4F1A\u8BDD\u3001\u9879\u76EE\u65E0\u5173\uFF0C\u53EF\u5355\u72EC\u5907\u4EFD\u6216\u624B\u5DE5\u7F16\u8F91\uFF0C \u6539\u5B8C\u70B9\u300C\u91CD\u65B0\u8BFB\u53D6\u300D\u5373\u53EF\u52A0\u8F7D\uFF09\u3002"
2094
2438
  ] })
2095
2439
  ] });
@@ -2098,7 +2442,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2098
2442
  const settings = useLive((item) => item);
2099
2443
  const book = useBook((item) => item);
2100
2444
  const bookStatus = useBookStatus((item) => item);
2101
- const [conflict, setConflict] = (0, import_react3.useState)(null);
2445
+ const [conflict, setConflict] = (0, import_react4.useState)(null);
2102
2446
  const setKey = (side, chord) => {
2103
2447
  const other = side === "send" ? settings.newlineKey : settings.sendKey;
2104
2448
  if (chord !== "" && chord === other) {
@@ -2111,20 +2455,20 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2111
2455
  const conflictHint = conflict !== null ? `\u300C${displayChord(conflict)}\u300D\u5DF2\u88AB\u53E6\u4E00\u4FA7\u5360\u7528\uFF0C\u8BF7\u5148\u4E3A\u53E6\u4E00\u4FA7\u9009\u62E9\u5176\u5B83\u6309\u952E\u3002` : null;
2112
2456
  const menuEnabled = MENU_ITEMS.filter((item) => settings[item.field]).length;
2113
2457
  const keySummary = `\u53D1\u9001 ${displayChord(settings.sendKey)} \xB7 \u6362\u884C ${displayChord(settings.newlineKey)}`;
2114
- const menuSummary = settings.menuNative ? "\u5F53\u524D\uFF1A\u7CFB\u7EDF\u539F\u751F\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09" : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \xB7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`;
2458
+ const menuSummary = settings.menuMode === "official" ? "\u5F53\u524D\uFF1A\u5B98\u65B9\u4E0D\u4ECB\u5165" : settings.menuMode === "browser" ? "\u5F53\u524D\uFF1A\u6D4F\u89C8\u5668\u83DC\u5355\uFF08\u7C98\u8D34\u514D\u6388\u6743\uFF09" : `\u5F53\u524D\uFF1A\u81EA\u5B9A\u4E49\u83DC\u5355 \xB7 ${menuEnabled} / ${MENU_ITEMS.length} \u9879\u5F00\u542F`;
2115
2459
  const panelSummary = `\u5BFC\u822A\u6EDA\u52A8 ${settings.panelScroll ? "\u5F00" : "\u5173"} \xB7 \u8FB9\u7F18\u7F29\u653E ${settings.panelResize ? "\u5F00" : "\u5173"} \xB7 ${settings.panelWidth}\xD7${settings.panelHeight}`;
2116
2460
  const headerSummary = settings.headerEnabled ? settings.headerStatus === "" ? "\u5DF2\u542F\u7528" : settings.headerStatus : "\u672A\u542F\u7528";
2117
2461
  const quickCounts = bookCounts(book);
2118
- const quickSummary = `${quickCounts.categories} \u4E2A\u5206\u7C7B \xB7 ${quickCounts.prompts} \u6761 \xB7 \u9ED8\u8BA4\u63D2\u5165 ${quickCounts.always} \u6761 \xB7 \u4F18\u5316\u6863\u4F4D ${OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.label ?? "\u9AD8\u7EA7"}`;
2462
+ 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"}`;
2119
2463
  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";
2120
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { padding: "4px 2px" }, children: [
2121
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dsh-ux-card", children: [
2122
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dsh-ux-cardHeaderStatic", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dsh-ux-cardHeadText", children: [
2123
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "dsh-ux-cardName", children: "\u8F93\u5165\u4F53\u9A8C" }),
2124
- /* @__PURE__ */ (0, import_jsx_runtime3.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" })
2464
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { style: { padding: "4px 2px" }, children: [
2465
+ /* @__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" })
2125
2469
  ] }) }),
2126
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dsh-ux-cardBody", children: [
2127
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2470
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "dsh-ux-cardBody", children: [
2471
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2128
2472
  ToggleRow,
2129
2473
  {
2130
2474
  first: true,
@@ -2136,13 +2480,13 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2136
2480
  }
2137
2481
  }
2138
2482
  ),
2139
- !settings.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: hintInfo, children: "\u5DF2\u505C\u7528\uFF1A\u53D1\u9001/\u6362\u884C\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8\u4E0E\u8FB9\u7F18\u7F29\u653E\u5747\u4E0D\u518D\u751F\u6548\uFF0C\u8F93\u5165\u6846\u6062\u590D DSH \u539F\u751F\u884C\u4E3A\u3002 \u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u53EF\u4E00\u952E\u6062\u590D\uFF1B\u6240\u6709\u8BBE\u7F6E\u503C\u4ECD\u4FDD\u7559\u3002" })
2483
+ !settings.enabled && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: hintInfo, children: "\u5DF2\u505C\u7528\uFF1A\u53D1\u9001/\u6362\u884C\u952E\u4F4D\u3001\u53F3\u952E\u83DC\u5355\u3001\u8BBE\u7F6E\u9762\u677F\u6EDA\u52A8\u4E0E\u8FB9\u7F18\u7F29\u653E\u5747\u4E0D\u518D\u751F\u6548\uFF0C\u8F93\u5165\u6846\u6062\u590D DSH \u539F\u751F\u884C\u4E3A\u3002 \u6253\u5F00\u4E0A\u65B9\u5F00\u5173\u5373\u53EF\u4E00\u952E\u6062\u590D\uFF1B\u6240\u6709\u8BBE\u7F6E\u503C\u4ECD\u4FDD\u7559\u3002" })
2140
2484
  ] })
2141
2485
  ] }),
2142
- settings.enabled && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2143
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u952E\u4F4D", summary: keySummary, children: [
2144
- /* @__PURE__ */ (0, import_jsx_runtime3.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" }),
2145
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2486
+ 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)(
2146
2490
  KeyRow,
2147
2491
  {
2148
2492
  first: true,
@@ -2156,7 +2500,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2156
2500
  }
2157
2501
  }
2158
2502
  ),
2159
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2503
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2160
2504
  KeyRow,
2161
2505
  {
2162
2506
  title: "\u6362\u884C\u952E",
@@ -2169,8 +2513,8 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2169
2513
  }
2170
2514
  }
2171
2515
  ),
2172
- conflictHint !== null && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: hintError, children: conflictHint }),
2173
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2174
2518
  "button",
2175
2519
  {
2176
2520
  type: "button",
@@ -2183,22 +2527,33 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2183
2527
  }
2184
2528
  ) })
2185
2529
  ] }),
2186
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u53F3\u952E\u83DC\u5355", summary: menuSummary, children: [
2187
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\u53F3\u952E\u70B9\u51FB\u8F93\u5165\u6846\u65F6\u7684\u884C\u4E3A\u3002\u7CFB\u7EDF\u539F\u751F\u6A21\u5F0F\u4E0B\u7531\u6D4F\u89C8\u5668\u5F39\u51FA\u81EA\u5DF1\u7684\u83DC\u5355\uFF08\u6837\u5F0F\u968F\u6D4F\u89C8\u5668\u800C\u53D8\u5316\uFF0C \u7C98\u8D34\u514D\u6388\u6743\u3001\u96F6\u914D\u7F6E\uFF09\uFF1B\u81EA\u5B9A\u4E49\u6A21\u5F0F\u4F7F\u7528\u56FA\u5B9A\u6837\u5F0F\u83DC\u5355\uFF08\u672A\u9009\u4E2D\u6587\u672C\u65F6\u300C\u526A\u5207 / \u590D\u5236 / \u5220\u9664\u300D\u7F6E\u7070\uFF0C \u7C98\u8D34\u9700\u8981\u6D4F\u89C8\u5668\u526A\u8D34\u677F\u6388\u6743\uFF0CFirefox \u8981\u5728 about:config \u4E2D\u8BBE\u7F6E permissions.default.clipboard-read = 1 \u624D\u80FD\u514D\u5F39\u7A97\uFF09\u3002" }),
2188
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2189
- ToggleRow,
2190
- {
2191
- first: true,
2192
- label: "\u4F7F\u7528\u7CFB\u7EDF\u539F\u751F\u83DC\u5355",
2193
- desc: "\u6253\u5F00\u540E\u53F3\u952E\u7C98\u8D34\u514D\u6388\u6743\uFF08\u70B9\u51FB\u6D4F\u89C8\u5668\u83DC\u5355\u7684\u7C98\u8D34\u76F4\u63A5\u6210\u529F\uFF09\uFF1B\u5173\u95ED\u540E\u6062\u590D\u81EA\u5B9A\u4E49\u83DC\u5355",
2194
- checked: settings.menuNative,
2195
- onChange: (next) => {
2196
- actions.setField(MENU_NATIVE_FIELD, next);
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"
2197
2546
  }
2198
- }
2199
- ),
2200
- !settings.menuNative && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
2201
- MENU_ITEMS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2202
2557
  ToggleRow,
2203
2558
  {
2204
2559
  label: item.label,
@@ -2210,7 +2565,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2210
2565
  },
2211
2566
  item.field
2212
2567
  )),
2213
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2568
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { marginTop: 10 }, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2214
2569
  "button",
2215
2570
  {
2216
2571
  type: "button",
@@ -2223,14 +2578,22 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2223
2578
  ) })
2224
2579
  ] })
2225
2580
  ] }),
2226
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u5FEB\u6377\u6307\u4EE4", summary: quickSummary, children: [
2227
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { style: bodyLead, children: "\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\uFF1B \u6761\u76EE\u53F3\u4FA7\u52FE\u4E0A\u300C\u9ED8\u8BA4\u63D2\u5165\u300D\uFF0C\u5219\u5728\u4F60**\u70B9\u53D1\u9001\u65F6**\u628A\u8FD9\u6761\u63D0\u793A\u8BCD\u81EA\u52A8\u9644\u52A0\u5230\u6D88\u606F**\u672B\u5C3E** \u4E00\u8D77\u53D1\u51FA\u53BB\uFF08\u591A\u6761\u6309\u5217\u8868\u987A\u5E8F\u62FC\u63A5\uFF0C\u8F93\u5165\u6846\u91CC\u4E0D\u63D0\u524D\u663E\u793A\uFF09\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" }),
2228
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2229
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
2230
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u4F18\u5316\u5F3A\u5EA6" }),
2231
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowDesc, children: OPTIMIZER_TIERS.find((item) => item.id === settings.optimizerTier)?.hint ?? "" })
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 ?? "" })
2232
2595
  ] }),
2233
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap" }, children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2234
2597
  "button",
2235
2598
  {
2236
2599
  type: "button",
@@ -2244,12 +2607,12 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2244
2607
  item.id
2245
2608
  )) })
2246
2609
  ] }),
2247
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { ...row, borderTop: "none", flexDirection: "column", alignItems: "stretch", gap: 8 }, children: [
2248
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: rowText, children: [
2249
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { style: rowTitle, children: "\u5FEB\u6377\u6307\u4EE4\u6E05\u5355" }),
2250
- /* @__PURE__ */ (0, import_jsx_runtime3.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" })
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" })
2251
2614
  ] }),
2252
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2615
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2253
2616
  QuickPromptsEditor,
2254
2617
  {
2255
2618
  book,
@@ -2267,9 +2630,9 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2267
2630
  )
2268
2631
  ] })
2269
2632
  ] }),
2270
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "\u8BBE\u7F6E\u9762\u677F", summary: panelSummary, children: [
2271
- /* @__PURE__ */ (0, import_jsx_runtime3.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" }),
2272
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2273
2636
  ToggleRow,
2274
2637
  {
2275
2638
  first: true,
@@ -2281,7 +2644,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2281
2644
  }
2282
2645
  }
2283
2646
  ),
2284
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2647
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2285
2648
  ToggleRow,
2286
2649
  {
2287
2650
  label: "\u8FB9\u7F18\u8C03\u6574\u5927\u5C0F",
@@ -2292,9 +2655,9 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2292
2655
  }
2293
2656
  }
2294
2657
  ),
2295
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", marginTop: 10 }, children: [
2296
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { style: rowDesc, children: "\u5C3A\u5BF8\u9884\u8BBE\uFF1A" }),
2297
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2298
2661
  "button",
2299
2662
  {
2300
2663
  type: "button",
@@ -2306,7 +2669,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2306
2669
  children: "\u9ED8\u8BA4\uFF08800\uFF09"
2307
2670
  }
2308
2671
  ),
2309
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2672
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2310
2673
  "button",
2311
2674
  {
2312
2675
  type: "button",
@@ -2318,7 +2681,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2318
2681
  children: "\u7D27\u51D1\uFF08640\xD7600\uFF09"
2319
2682
  }
2320
2683
  ),
2321
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2684
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2322
2685
  "button",
2323
2686
  {
2324
2687
  type: "button",
@@ -2332,9 +2695,10 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2332
2695
  )
2333
2696
  ] })
2334
2697
  ] }),
2335
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(FoldCard, { name: "OpenCode \u8BF7\u6C42\u5934", summary: headerSummary, children: [
2336
- /* @__PURE__ */ (0, import_jsx_runtime3.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" }),
2337
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
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)(
2338
2702
  ToggleRow,
2339
2703
  {
2340
2704
  first: true,
@@ -2346,7 +2710,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2346
2710
  }
2347
2711
  }
2348
2712
  ),
2349
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2713
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2350
2714
  TextFieldRow,
2351
2715
  {
2352
2716
  title: "\u5934\u540D",
@@ -2359,7 +2723,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2359
2723
  }
2360
2724
  }
2361
2725
  ),
2362
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2726
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2363
2727
  TextFieldRow,
2364
2728
  {
2365
2729
  title: "\u503C",
@@ -2378,7 +2742,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2378
2742
  }
2379
2743
  }
2380
2744
  ),
2381
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2745
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2382
2746
  TextFieldRow,
2383
2747
  {
2384
2748
  title: "\u4F5C\u7528\u8DEF\u7531",
@@ -2391,7 +2755,7 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2391
2755
  }
2392
2756
  }
2393
2757
  ),
2394
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { style: hintInfo, children: [
2758
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { style: hintInfo, children: [
2395
2759
  "\u72B6\u6001\uFF1A",
2396
2760
  headerStatusText
2397
2761
  ] })
@@ -2401,12 +2765,13 @@ function SettingsSection({ useLive, useBook, useBookStatus, actions }) {
2401
2765
  }
2402
2766
 
2403
2767
  // src/client/QuickCommandsButton.tsx
2404
- var import_react4 = require("react");
2405
- var import_jsx_runtime4 = require("react/jsx-runtime");
2768
+ var import_react5 = require("react");
2769
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2406
2770
  function QuickCommandsButton({
2407
2771
  useInput,
2408
2772
  inputActions,
2409
2773
  sessionId,
2774
+ useSession,
2410
2775
  useLive,
2411
2776
  usePanel,
2412
2777
  actions
@@ -2414,21 +2779,23 @@ function QuickCommandsButton({
2414
2779
  const settings = useLive((item) => item);
2415
2780
  const anchor = usePanel((item) => item);
2416
2781
  const draft = useInput((state2) => state2.draft);
2417
- const ref = (0, import_react4.useRef)(null);
2418
- (0, import_react4.useEffect)(() => {
2782
+ const blank = useSession((state2) => state2?.blank === true);
2783
+ const ref = (0, import_react5.useRef)(null);
2784
+ (0, import_react5.useEffect)(() => {
2419
2785
  const sid = typeof sessionId === "string" ? sessionId : "";
2420
2786
  publishInputBridge({
2421
2787
  actions: inputActions ?? null,
2422
2788
  draft: typeof draft === "string" ? draft : "",
2423
- sessionId: sid
2789
+ sessionId: sid,
2790
+ blank: blank === true
2424
2791
  });
2425
2792
  return () => {
2426
2793
  releaseInputBridge(sid);
2427
2794
  };
2428
- }, [inputActions, draft, sessionId]);
2795
+ }, [inputActions, draft, sessionId, blank]);
2429
2796
  if (settings.enabled !== true) return null;
2430
2797
  const open = anchor !== null;
2431
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2798
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2432
2799
  "button",
2433
2800
  {
2434
2801
  ref,
@@ -2449,14 +2816,14 @@ function QuickCommandsButton({
2449
2816
  });
2450
2817
  },
2451
2818
  children: [
2452
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2819
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2453
2820
  "svg",
2454
2821
  {
2455
2822
  viewBox: "0 0 16 16",
2456
2823
  width: "12",
2457
2824
  height: "12",
2458
2825
  "aria-hidden": true,
2459
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2826
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2460
2827
  "path",
2461
2828
  {
2462
2829
  d: "M9.2 1.2 3.4 9.1h3.5l-0.9 5.7 6-8.1H8.4l0.8-5.5Z",
@@ -2465,15 +2832,15 @@ function QuickCommandsButton({
2465
2832
  )
2466
2833
  }
2467
2834
  ),
2468
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u5FEB\u6377\u6307\u4EE4" })
2835
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "\u5FEB\u6377\u6307\u4EE4" })
2469
2836
  ]
2470
2837
  }
2471
2838
  );
2472
2839
  }
2473
2840
 
2474
2841
  // src/client/QuickCommandsPanel.tsx
2475
- var import_react5 = require("react");
2476
- var import_jsx_runtime5 = require("react/jsx-runtime");
2842
+ var import_react6 = require("react");
2843
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2477
2844
  var MARGIN = 8;
2478
2845
  var GAP = 8;
2479
2846
  function QuickCommandsPanel({
@@ -2491,13 +2858,13 @@ function QuickCommandsPanel({
2491
2858
  const notice = useNotice((item) => item);
2492
2859
  const book = useBook((item) => item);
2493
2860
  const status = useBookStatus((item) => item);
2494
- const ref = (0, import_react5.useRef)(null);
2495
- const [position, setPosition] = (0, import_react5.useState)(null);
2496
- const [activeId, setActiveId] = (0, import_react5.useState)("");
2861
+ const ref = (0, import_react6.useRef)(null);
2862
+ const [position, setPosition] = (0, import_react6.useState)(null);
2863
+ const [activeId, setActiveId] = (0, import_react6.useState)("");
2497
2864
  const counts = bookCounts(book);
2498
2865
  const categories = book.categories;
2499
- const active = categories.find((category) => category.id === activeId) ?? categories[0];
2500
- (0, import_react5.useLayoutEffect)(() => {
2866
+ const active2 = categories.find((category) => category.id === activeId) ?? categories[0];
2867
+ (0, import_react6.useLayoutEffect)(() => {
2501
2868
  if (anchor === null) {
2502
2869
  setPosition(null);
2503
2870
  return;
@@ -2510,7 +2877,7 @@ function QuickCommandsPanel({
2510
2877
  const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN);
2511
2878
  setPosition({ left, top: Math.max(MARGIN, top) });
2512
2879
  }, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy]);
2513
- (0, import_react5.useEffect)(() => {
2880
+ (0, import_react6.useEffect)(() => {
2514
2881
  if (anchor === null) return;
2515
2882
  const onPointerDown = (event) => {
2516
2883
  if (ref.current !== null && event.target instanceof Node && ref.current.contains(event.target)) return;
@@ -2534,9 +2901,9 @@ function QuickCommandsPanel({
2534
2901
  }, [anchor === null, actions]);
2535
2902
  if (anchor === null) return null;
2536
2903
  const tier = settings.optimizerTier;
2537
- const items = active?.prompts ?? [];
2904
+ const items = active2?.prompts ?? [];
2538
2905
  const failure = status !== "" && status !== "saving" ? status : "";
2539
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2906
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2540
2907
  "div",
2541
2908
  {
2542
2909
  ref,
@@ -2544,10 +2911,10 @@ function QuickCommandsPanel({
2544
2911
  "aria-label": "\u5FEB\u6377\u6307\u4EE4",
2545
2912
  style: { ...quickPanel, left: position?.left ?? anchor.left, top: position?.top ?? anchor.bottom },
2546
2913
  children: [
2547
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelHead, children: [
2548
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelTitleRow, children: [
2549
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickPanelTitle, children: "\u5FEB\u6377\u6307\u4EE4" }),
2550
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { style: quickTierRow, role: "group", "aria-label": "\u4F18\u5316\u5F3A\u5EA6", children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2914
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickPanelHead, children: [
2915
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickPanelTitleRow, children: [
2916
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: quickPanelTitle, children: "\u5FEB\u6377\u6307\u4EE4" }),
2917
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: quickTierRow, role: "group", "aria-label": "\u4F18\u5316\u5F3A\u5EA6", children: OPTIMIZER_TIERS.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2551
2918
  "button",
2552
2919
  {
2553
2920
  type: "button",
@@ -2565,7 +2932,7 @@ function QuickCommandsPanel({
2565
2932
  item.id
2566
2933
  )) })
2567
2934
  ] }),
2568
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2935
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2569
2936
  "button",
2570
2937
  {
2571
2938
  type: "button",
@@ -2579,19 +2946,19 @@ function QuickCommandsPanel({
2579
2946
  actions.optimize();
2580
2947
  },
2581
2948
  children: [
2582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { "aria-hidden": true, children: "\u2728" }),
2583
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: busy ? "\u4F18\u5316\u4E2D\u2026" : "\u4F18\u5316\u63D0\u793A\u8BCD" })
2949
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { "aria-hidden": true, children: "\u2728" }),
2950
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: busy ? "\u4F18\u5316\u4E2D\u2026" : "\u4F18\u5316\u63D0\u793A\u8BCD" })
2584
2951
  ]
2585
2952
  }
2586
2953
  ),
2587
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickCategoryRow, children: [
2588
- categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2954
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickCategoryRow, children: [
2955
+ categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2589
2956
  "button",
2590
2957
  {
2591
2958
  type: "button",
2592
2959
  title: `${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`,
2593
- "aria-pressed": category.id === active?.id,
2594
- style: category.id === active?.id ? quickCategoryTabActive : quickCategoryTab,
2960
+ "aria-pressed": category.id === active2?.id,
2961
+ style: category.id === active2?.id ? quickCategoryTabActive : quickCategoryTab,
2595
2962
  onMouseDown: (event) => {
2596
2963
  event.preventDefault();
2597
2964
  },
@@ -2602,7 +2969,7 @@ function QuickCommandsPanel({
2602
2969
  },
2603
2970
  category.id
2604
2971
  )),
2605
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2972
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2606
2973
  "button",
2607
2974
  {
2608
2975
  type: "button",
@@ -2620,14 +2987,14 @@ function QuickCommandsPanel({
2620
2987
  )
2621
2988
  ] })
2622
2989
  ] }),
2623
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickList, children: [
2624
- items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickEmpty, children: [
2990
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickList, children: [
2991
+ items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickEmpty, children: [
2625
2992
  "\u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002",
2626
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("br", {}),
2993
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("br", {}),
2627
2994
  "\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002"
2628
2995
  ] }),
2629
- items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2630
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2996
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
2997
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2631
2998
  "button",
2632
2999
  {
2633
3000
  type: "button",
@@ -2640,30 +3007,41 @@ function QuickCommandsPanel({
2640
3007
  actions.insert(item.prompt);
2641
3008
  },
2642
3009
  children: [
2643
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemLabel, children: item.label }),
2644
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
3010
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: quickItemLabel, children: item.label }),
3011
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
2645
3012
  ]
2646
3013
  }
2647
3014
  ),
2648
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { style: quickAlwaysLabel, title: "\u52FE\u4E0A\u540E\uFF0C\u70B9\u53D1\u9001\u65F6\u8FD9\u6761\u63D0\u793A\u8BCD\u4F1A\u81EA\u52A8\u9644\u52A0\u5230\u4F60\u7684\u6D88\u606F\u672B\u5C3E\uFF08\u5BF9\u6240\u6709\u5206\u7C7B\u751F\u6548\uFF09", children: [
2649
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2650
- "input",
2651
- {
2652
- type: "checkbox",
2653
- style: quickAlwaysBox,
2654
- checked: item.always,
2655
- onChange: (event) => {
2656
- actions.setAlways(item.id, event.target.checked);
2657
- }
3015
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3016
+ InsertModeControl,
3017
+ {
3018
+ compact: true,
3019
+ label: item.label,
3020
+ mode: insertModeOf(item),
3021
+ onChange: (mode) => {
3022
+ actions.setInsertMode(item.id, mode);
2658
3023
  }
2659
- ),
2660
- "\u9ED8\u8BA4\u63D2\u5165"
2661
- ] })
2662
- ] }, item.id))
3024
+ }
3025
+ )
3026
+ ] }, item.id)),
3027
+ active2 !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
3028
+ AddPromptRow,
3029
+ {
3030
+ variant: "panel",
3031
+ book,
3032
+ categoryId: active2.id,
3033
+ onAdd: () => {
3034
+ actions.addPrompt(active2.id);
3035
+ },
3036
+ onMove: (promptId) => {
3037
+ actions.movePrompt(promptId, active2.id);
3038
+ }
3039
+ }
3040
+ )
2663
3041
  ] }),
2664
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: quickPanelFoot, children: [
2665
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { style: quickNotice, role: "status", children: notice !== "" ? notice : failure }),
2666
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
3042
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: quickPanelFoot, children: [
3043
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: quickNotice, role: "status", children: notice !== "" ? notice : failure }),
3044
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2667
3045
  "span",
2668
3046
  {
2669
3047
  style: quickFootHint,
@@ -2771,6 +3149,10 @@ function apply(ctx) {
2771
3149
  resetBook: () => {
2772
3150
  commitBook(defaultQuickBook());
2773
3151
  },
3152
+ /** 把某条从它所在分类移到目标分类(「移动到这里」:追加到目标末尾)。 */
3153
+ movePromptToCategory: (promptId, toCategoryId) => {
3154
+ commitBook(withPromptMovedToCategory(book.getSnapshot(), promptId, toCategoryId));
3155
+ },
2774
3156
  /** 设置页「保存」:把编辑器里的整本一次写回(而不是每敲一个字就写盘)。 */
2775
3157
  saveBook: (next) => {
2776
3158
  commitBook(next);
@@ -2783,6 +3165,8 @@ function apply(ctx) {
2783
3165
  SEND_KEY_FIELD,
2784
3166
  NEWLINE_KEY_FIELD,
2785
3167
  ...MENU_FIELDS,
3168
+ MENU_MODE_FIELD,
3169
+ // 旧的布尔字段也一并清掉:它只是迁移线索,留着会把「恢复默认」后的档位又拉回旧值。
2786
3170
  MENU_NATIVE_FIELD,
2787
3171
  PANEL_SCROLL_FIELD,
2788
3172
  PANEL_RESIZE_FIELD,
@@ -2858,11 +3242,13 @@ function apply(ctx) {
2858
3242
  setField(OPTIMIZER_TIER_FIELD, tier);
2859
3243
  },
2860
3244
  /**
2861
- * 「默认插入」勾选:按 id 跨分类找那一条,直接写盘。
2862
- * 这个标记就是「点发送时自动附加到消息末尾」的依据(见 interceptors.ts)。
3245
+ * 设置某条的插入模式(关 / 每次 / 仅首次)。
3246
+ *
3247
+ * 界面上只有这一个入口:两个互斥标志由 `withInsertMode` **一次写对**,
3248
+ * 不给「又每次又仅首次」留缝。
2863
3249
  */
2864
- setAlways: (id, value) => {
2865
- commitBook(withAlwaysToggled(book.getSnapshot(), id, value));
3250
+ setInsertMode: (promptId, mode) => {
3251
+ commitBook(withInsertMode(book.getSnapshot(), promptId, mode));
2866
3252
  }
2867
3253
  };
2868
3254
  slots.inject("settings.section", () => slots.register({
@@ -2926,12 +3312,13 @@ function apply(ctx) {
2926
3312
  insert: quickActions.insert,
2927
3313
  optimize: quickActions.optimize,
2928
3314
  setTier: quickActions.setTier,
2929
- setAlways: quickActions.setAlways,
2930
- toggleAlways: quickActions.setAlways,
3315
+ setInsertMode: quickActions.setInsertMode,
2931
3316
  addCategory: bookActions.addCategory,
2932
3317
  renameCategory: bookActions.renameCategory,
2933
3318
  removeCategory: bookActions.removeCategory,
2934
3319
  moveCategory: bookActions.moveCategory,
3320
+ addPrompt: bookActions.addPrompt,
3321
+ movePrompt: bookActions.movePromptToCategory,
2935
3322
  reloadBook: bookActions.reload
2936
3323
  }
2937
3324
  })
@@ -2955,7 +3342,8 @@ function apply(ctx) {
2955
3342
  if (enabled && dispose === null) {
2956
3343
  dispose = installInterceptors({
2957
3344
  settings: () => live.getSnapshot(),
2958
- alwaysPrompts: () => alwaysQuickPrompts(book.getSnapshot()),
3345
+ // 「仅首次」由这里决定是否算进这一批:会话还是空的(blank)才带上。
3346
+ promptsForSend: () => appendBatchForSend(book.getSnapshot(), currentBlankSession()),
2959
3347
  setMenu: (state2) => {
2960
3348
  menu2.set(state2);
2961
3349
  },
@@ -2967,7 +3355,7 @@ function apply(ctx) {
2967
3355
  menu2.set(null);
2968
3356
  panel.set(null);
2969
3357
  }
2970
- if (live.getSnapshot().menuNative) menu2.set(null);
3358
+ if (live.getSnapshot().menuMode !== "custom") menu2.set(null);
2971
3359
  if (!live.getSnapshot().enabled) panel.set(null);
2972
3360
  };
2973
3361
  syncInterceptors();