dsh-composer-ux 0.13.0 → 0.13.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -2770,6 +2770,9 @@ var quickPrimaryButtonDisabled = {
2770
2770
  cursor: "default"
2771
2771
  };
2772
2772
  var quickList = {
2773
+ // `flex: 1 1 auto` + `minHeight: 0`:这一半被压时**自己滚**,而不是把内容顶出去。
2774
+ flex: "1 1 auto",
2775
+ minHeight: 0,
2773
2776
  overflowY: "auto",
2774
2777
  padding: "6px 6px 8px",
2775
2778
  display: "flex",
@@ -2833,6 +2836,32 @@ var quickEmpty = {
2833
2836
  padding: "14px 10px",
2834
2837
  textAlign: "center"
2835
2838
  };
2839
+ var quickSectionBody = {
2840
+ flex: "1 1 auto",
2841
+ minHeight: 0,
2842
+ display: "flex",
2843
+ flexDirection: "column",
2844
+ overflow: "hidden"
2845
+ };
2846
+ var quickSectionToggle = {
2847
+ display: "flex",
2848
+ alignItems: "center",
2849
+ gap: 6,
2850
+ width: "100%",
2851
+ padding: "6px 12px",
2852
+ border: 0,
2853
+ borderTop: "0.5px solid var(--dsw-alias-border-l2)",
2854
+ borderBottom: "0.5px solid var(--dsw-alias-border-l2)",
2855
+ background: "transparent",
2856
+ color: "var(--dsw-alias-label-secondary)",
2857
+ fontSize: 11.5,
2858
+ textAlign: "left",
2859
+ cursor: "pointer"
2860
+ };
2861
+ var quickSectionToggleArrow = {
2862
+ width: 10,
2863
+ flex: "0 0 auto"
2864
+ };
2836
2865
  var quickCategoryRow = {
2837
2866
  display: "flex",
2838
2867
  alignItems: "center",
@@ -2866,13 +2895,44 @@ var quickCategoryAdd = {
2866
2895
  cursor: "pointer"
2867
2896
  };
2868
2897
  var dockBox = {
2898
+ // 撑满中部容器(`minHeight: 0` 是关键:否则弹性子项按内容高度撑,又会被裁)。
2899
+ flex: "1 1 auto",
2900
+ minHeight: 0,
2901
+ overflow: "hidden",
2869
2902
  display: "flex",
2870
2903
  flexDirection: "column",
2871
2904
  gap: 6,
2872
- padding: "8px 10px",
2873
- borderRadius: 10,
2874
- background: "var(--dsw-alias-bg-layer-1)",
2875
- border: "0.5px solid var(--dsw-alias-border-l2)"
2905
+ padding: "8px 12px 8px",
2906
+ // 0.13.2:**不再画成一张独立卡片**(用户原话「提示词优化是悬浮的」)。
2907
+ // 去掉自己的背景与圆角边框,只留一条细分隔线 —— 它就是面板里的一段,而不是浮在上面的小窗。
2908
+ borderTop: "0.5px solid var(--dsw-alias-border-l2)"
2909
+ };
2910
+ var dockBody = {
2911
+ flex: "1 1 auto",
2912
+ minHeight: 0,
2913
+ display: "flex",
2914
+ flexDirection: "column",
2915
+ gap: 6,
2916
+ overflowY: "auto"
2917
+ };
2918
+ var dockButtonsPinned = {
2919
+ flex: "0 0 auto"
2920
+ };
2921
+ var dockButtonGhost = {
2922
+ border: 0,
2923
+ background: "transparent",
2924
+ color: "var(--dsw-alias-label-tertiary)",
2925
+ borderRadius: 999,
2926
+ padding: "3px 8px",
2927
+ fontSize: 11,
2928
+ lineHeight: 1.6,
2929
+ cursor: "pointer",
2930
+ whiteSpace: "nowrap"
2931
+ };
2932
+ var dockButtonWarn = {
2933
+ ...dockButtonGhost,
2934
+ color: "var(--dsw-alias-label-error, #d33)",
2935
+ border: "0.5px solid var(--dsw-alias-label-error, #d33)"
2876
2936
  };
2877
2937
  var dockHead = {
2878
2938
  display: "flex",
@@ -6273,6 +6333,15 @@ function useOptimizeElapsed(startedAt) {
6273
6333
  return running ? seconds : 0;
6274
6334
  }
6275
6335
 
6336
+ // src/client/panel-sections.ts
6337
+ var DEFAULT_PANEL_SECTION = "quick";
6338
+ function toggleSection(current) {
6339
+ return current === "quick" ? "optimize" : "quick";
6340
+ }
6341
+ function sectionForDock(dockPresent, current) {
6342
+ return dockPresent ? "optimize" : current;
6343
+ }
6344
+
6276
6345
  // src/client/OptimizeDock.tsx
6277
6346
  var import_react13 = require("react");
6278
6347
 
@@ -6484,6 +6553,7 @@ async function copyText(text) {
6484
6553
  }
6485
6554
  function OptimizeDock({ state: state2, seconds, actions }) {
6486
6555
  const [copied, setCopied] = (0, import_react13.useState)(false);
6556
+ const [discardArmed, setDiscardArmed] = (0, import_react13.useState)(false);
6487
6557
  const running = state2.phase === "running";
6488
6558
  const hasText = state2.text.trim() !== "";
6489
6559
  const canInsert = state2.phase === "done" && hasText;
@@ -6500,6 +6570,29 @@ function OptimizeDock({ state: state2, seconds, actions }) {
6500
6570
  /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: dockHead, children: [
6501
6571
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockPhase, role: "status", children: dockPhaseText(state2) }),
6502
6572
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockMeta, children: running ? `\u5DF2\u7B49\u5F85 ${String(seconds)}s` : state2.elapsedMs > 0 ? `\u7528\u65F6 ${(state2.elapsedMs / 1e3).toFixed(1)} \u79D2` : "" }),
6573
+ !running && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6574
+ "button",
6575
+ {
6576
+ type: "button",
6577
+ style: discardArmed ? dockButtonWarn : dockButtonGhost,
6578
+ title: discardArmed ? "\u518D\u70B9\u4E00\u6B21\u5C31\u771F\u7684\u4E22\u6389\u8FD9\u4EFD\u7ED3\u679C\uFF08\u4E0D\u53EF\u6062\u590D\uFF09" : "\u4E22\u5F03\u8FD9\u4EFD\u7ED3\u679C\uFF08\u4E0D\u53EF\u6062\u590D\uFF1B\u53EA\u60F3\u6536\u8D77\u6765\u5C31\u70B9\u53F3\u8FB9\u7684 \u2715\uFF09",
6579
+ onMouseDown: (event) => {
6580
+ event.preventDefault();
6581
+ },
6582
+ onClick: () => {
6583
+ if (!discardArmed) {
6584
+ setDiscardArmed(true);
6585
+ setTimeout(() => {
6586
+ setDiscardArmed(false);
6587
+ }, 4e3);
6588
+ return;
6589
+ }
6590
+ setDiscardArmed(false);
6591
+ actions.discard();
6592
+ },
6593
+ children: discardArmed ? "\u70B9\u7B2C\u4E8C\u6B21\u4E22\u5F03" : "\u4E22\u5F03"
6594
+ }
6595
+ ),
6503
6596
  running ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6504
6597
  "button",
6505
6598
  {
@@ -6517,8 +6610,8 @@ function OptimizeDock({ state: state2, seconds, actions }) {
6517
6610
  {
6518
6611
  type: "button",
6519
6612
  style: dockButton,
6520
- "aria-label": "\u5173\u95ED\u7ED3\u679C\u6846",
6521
- title: "\u6536\u8D77\u7ED3\u679C\u6846\uFF08\u4E22\u5F03\u6846\u91CC\u7684\u5185\u5BB9\uFF1B\u8F93\u5165\u6846\u91CC\u5DF2\u7ECF\u63D2\u5165\u7684\u5185\u5BB9\u4E0D\u53D7\u5F71\u54CD\uFF09",
6613
+ "aria-label": "\u6536\u8D77\u7ED3\u679C\u6846",
6614
+ title: "\u6536\u8D77\u7ED3\u679C\u6846\uFF080.13.2 \u8D77\u53EA\u662F\u6536\u8D77\uFF1A\u7ED3\u679C\u7559\u7740\uFF0C\u70B9\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u90A3\u4E00\u534A\u5C31\u80FD\u518D\u770B\u5230\uFF1B\u60F3\u5220\u6389\u7528\u65C1\u8FB9\u7684\u300C\u4E22\u5F03\u300D\uFF09",
6522
6615
  onMouseDown: (event) => {
6523
6616
  event.preventDefault();
6524
6617
  },
@@ -6527,28 +6620,30 @@ function OptimizeDock({ state: state2, seconds, actions }) {
6527
6620
  }
6528
6621
  )
6529
6622
  ] }),
6530
- state2.items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ol", { style: dockList, children: state2.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("li", { style: dockItemRow, children: [
6531
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockKind, children: KIND_LABEL[item.kind] ?? item.kind }),
6532
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockItemText, children: item.text }),
6533
- item.quote !== "" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockMeta, children: item.quoteSource === "none" ? `\uFF08\u6A21\u578B\u81EA\u5DF1\u8865\u7684\uFF0C\u4F9D\u636E\u4E0D\u662F\u4F60\u539F\u8BDD\uFF1A\u300C${item.quote}\u300D\uFF09` : `\uFF08\u4F9D\u636E\uFF1A"${item.quote}"\uFF09` })
6534
- ] }, item.id)) }),
6535
- state2.dropped.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockDropped, children: `\u4E22\u5F03 ${String(state2.dropped.length)} \u6761\uFF1A${state2.dropped.map((row2) => row2.reason).join("\uFF1B")}` }),
6536
- state2.phase === "error" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockError, role: "alert", children: state2.error === "" ? "\u4F18\u5316\u5931\u8D25" : state2.error }),
6537
- (state2.phase === "done" || state2.phase === "cancelled") && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6538
- "textarea",
6539
- {
6540
- value: state2.text,
6541
- onChange: (event) => {
6542
- actions.edit(event.target.value);
6543
- },
6544
- spellCheck: false,
6545
- "aria-label": "\u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\uFF08\u53EF\u7F16\u8F91\uFF09",
6546
- placeholder: state2.phase === "cancelled" ? "\u53D6\u6D88\u65F6\u8FD8\u6CA1\u6709\u6210\u54C1\uFF1A\u4E0A\u9762\u662F\u5DF2\u751F\u6210\u7684\u90E8\u5206\u3002\u70B9\u300C\u91CD\u65B0\u4F18\u5316\u300D\u8DD1\u5B8C\u4E00\u8F6E\u5C31\u80FD\u62FF\u5230\u6210\u54C1\u3002" : "\uFF08\u6210\u54C1\u4E3A\u7A7A\uFF09",
6547
- style: dockEditor
6548
- }
6549
- ),
6550
- state2.phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockSummaryLine, children: state2.route === "" ? dockSummary(state2) : `${dockSummary(state2)} \xB7 ${state2.route}` }),
6551
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: dockButtons, children: [
6623
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: dockBody, children: [
6624
+ state2.items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("ol", { style: dockList, children: state2.items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("li", { style: dockItemRow, children: [
6625
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockKind, children: KIND_LABEL[item.kind] ?? item.kind }),
6626
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockItemText, children: item.text }),
6627
+ item.quote !== "" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { style: dockMeta, children: item.quoteSource === "none" ? `\uFF08\u6A21\u578B\u81EA\u5DF1\u8865\u7684\uFF0C\u4F9D\u636E\u4E0D\u662F\u4F60\u539F\u8BDD\uFF1A\u300C${item.quote}\u300D\uFF09` : `\uFF08\u4F9D\u636E\uFF1A"${item.quote}"\uFF09` })
6628
+ ] }, item.id)) }),
6629
+ state2.dropped.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockDropped, children: `\u4E22\u5F03 ${String(state2.dropped.length)} \u6761\uFF1A${state2.dropped.map((row2) => row2.reason).join("\uFF1B")}` }),
6630
+ state2.phase === "error" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockError, role: "alert", children: state2.error === "" ? "\u4F18\u5316\u5931\u8D25" : state2.error }),
6631
+ (state2.phase === "done" || state2.phase === "cancelled") && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6632
+ "textarea",
6633
+ {
6634
+ value: state2.text,
6635
+ onChange: (event) => {
6636
+ actions.edit(event.target.value);
6637
+ },
6638
+ spellCheck: false,
6639
+ "aria-label": "\u4F18\u5316\u540E\u7684\u63D0\u793A\u8BCD\uFF08\u53EF\u7F16\u8F91\uFF09",
6640
+ placeholder: state2.phase === "cancelled" ? "\u53D6\u6D88\u65F6\u8FD8\u6CA1\u6709\u6210\u54C1\uFF1A\u4E0A\u9762\u662F\u5DF2\u751F\u6210\u7684\u90E8\u5206\u3002\u70B9\u300C\u91CD\u65B0\u4F18\u5316\u300D\u8DD1\u5B8C\u4E00\u8F6E\u5C31\u80FD\u62FF\u5230\u6210\u54C1\u3002" : "\uFF08\u6210\u54C1\u4E3A\u7A7A\uFF09",
6641
+ style: dockEditor
6642
+ }
6643
+ ),
6644
+ state2.phase === "done" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: dockSummaryLine, children: state2.route === "" ? dockSummary(state2) : `${dockSummary(state2)} \xB7 ${state2.route}` })
6645
+ ] }),
6646
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { style: { ...dockButtons, ...dockButtonsPinned }, children: [
6552
6647
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
6553
6648
  "button",
6554
6649
  {
@@ -6608,6 +6703,7 @@ function QuickCommandsPanel({
6608
6703
  useBook,
6609
6704
  useBookStatus,
6610
6705
  useDock,
6706
+ useDockHidden,
6611
6707
  actions
6612
6708
  }) {
6613
6709
  const settings = useLive((item) => item);
@@ -6618,9 +6714,12 @@ function QuickCommandsPanel({
6618
6714
  const book = useBook((item) => item);
6619
6715
  const status = useBookStatus((item) => item);
6620
6716
  const dock = useDock((item) => item);
6717
+ const dockHidden = useDockHidden((item) => item);
6621
6718
  const ref = (0, import_react14.useRef)(null);
6622
6719
  const [position, setPosition] = (0, import_react14.useState)(null);
6623
6720
  const [activeId, setActiveId] = (0, import_react14.useState)("");
6721
+ const [section, setSection] = (0, import_react14.useState)(DEFAULT_PANEL_SECTION);
6722
+ const dockPresent = dock !== null;
6624
6723
  const seconds = useOptimizeElapsed(busy ? startedAt : 0);
6625
6724
  const dockRunning = dock !== null && dock.phase === "running";
6626
6725
  const dockSeconds = useOptimizeElapsed(dockRunning && dock !== null ? dock.startedAt : 0);
@@ -6639,7 +6738,7 @@ function QuickCommandsPanel({
6639
6738
  const above = anchor.bottom - height - GAP;
6640
6739
  const top = above >= MARGIN ? above : Math.min(anchor.bottom + GAP, window.innerHeight - height - MARGIN);
6641
6740
  setPosition({ left, top: Math.max(MARGIN, top) });
6642
- }, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy]);
6741
+ }, [anchor?.left, anchor?.bottom, counts.prompts, categories.length, busy, section, dock !== null]);
6643
6742
  (0, import_react14.useEffect)(() => {
6644
6743
  if (anchor === null) return;
6645
6744
  const onPointerDown = (event) => {
@@ -6666,6 +6765,13 @@ function QuickCommandsPanel({
6666
6765
  window.removeEventListener("resize", actions.close);
6667
6766
  };
6668
6767
  }, [anchor === null, actions, dockRunning]);
6768
+ const dockVisible = dockPresent && !dockHidden;
6769
+ const prevDockPresent = (0, import_react14.useRef)(false);
6770
+ if (prevDockPresent.current !== dockVisible) {
6771
+ prevDockPresent.current = dockVisible;
6772
+ const next = sectionForDock(dockVisible, section);
6773
+ if (next !== section) setSection(next);
6774
+ }
6669
6775
  if (anchor === null) return null;
6670
6776
  const tier = settings.optimizerTier;
6671
6777
  const items = active2?.prompts ?? [];
@@ -6717,108 +6823,149 @@ function QuickCommandsPanel({
6717
6823
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: busy ? `\u4F18\u5316\u4E2D\u2026\uFF08${String(seconds)}s\uFF09` : "\u4F18\u5316\u63D0\u793A\u8BCD" })
6718
6824
  ]
6719
6825
  }
6720
- ),
6721
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickCategoryRow, children: [
6722
- categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6723
- "button",
6724
- {
6725
- type: "button",
6726
- title: `${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`,
6727
- "aria-pressed": category.id === active2?.id,
6728
- style: category.id === active2?.id ? quickCategoryTabActive : quickCategoryTab,
6729
- onMouseDown: (event) => {
6730
- event.preventDefault();
6731
- },
6732
- onClick: () => {
6733
- setActiveId(category.id);
6734
- },
6735
- children: category.name
6736
- },
6737
- category.id
6738
- )),
6739
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6740
- "button",
6741
- {
6742
- type: "button",
6743
- style: quickCategoryAdd,
6744
- disabled: categories.length >= QUICK_CATEGORY_MAX,
6745
- title: "\u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u5230\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C\u300D\u91CC\u6539\uFF09",
6746
- onMouseDown: (event) => {
6747
- event.preventDefault();
6826
+ )
6827
+ ] }),
6828
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6829
+ "button",
6830
+ {
6831
+ type: "button",
6832
+ style: quickSectionToggle,
6833
+ "aria-expanded": section === "optimize",
6834
+ title: section === "optimize" ? "\u6536\u8D77\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\uFF0C\u56DE\u5230\u300C\u5FEB\u6377\u6307\u4EE4\u300D" : "\u5C55\u5F00\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\uFF08\u7ED3\u679C\u6846\u5C31\u5728\u91CC\u9762\uFF1B\u4E0A\u9762\u70B9 \u2728 \u4E5F\u4F1A\u81EA\u52A8\u5C55\u5F00\uFF09",
6835
+ onMouseDown: (event) => {
6836
+ event.preventDefault();
6837
+ },
6838
+ onClick: () => {
6839
+ const next = toggleSection(section);
6840
+ if (next === "optimize") actions.dockShow();
6841
+ setSection(next);
6842
+ },
6843
+ children: [
6844
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickSectionToggleArrow, "aria-hidden": true, children: section === "optimize" ? "\u25BE" : "\u25B8" }),
6845
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "\u4F18\u5316\u63D0\u793A\u8BCD" }),
6846
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { marginLeft: "auto", color: "var(--dsw-alias-label-tertiary)" }, children: section === "optimize" ? "\u70B9\u6B64\u56DE\u5230\u5FEB\u6377\u6307\u4EE4" : dockPresent ? "\u4E0A\u6B21\u7684\u7ED3\u679C\u5728\u8FD9\u513F" : "\u8FD8\u6CA1\u6709\u7ED3\u679C" })
6847
+ ]
6848
+ }
6849
+ ),
6850
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickSectionBody, children: [
6851
+ dock !== null && section === "optimize" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { padding: "8px 12px 8px", flex: "1 1 auto", minHeight: 0, display: "flex", flexDirection: "column" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6852
+ OptimizeDock,
6853
+ {
6854
+ state: dock,
6855
+ seconds: dockSeconds,
6856
+ actions: {
6857
+ insert: actions.dockInsert,
6858
+ retry: actions.dockRetry,
6859
+ cancel: actions.dockCancel,
6860
+ // 关掉结果框顺手切回快捷指令那半:此时优化半已经没内容了。
6861
+ close: () => {
6862
+ actions.dockClose();
6863
+ setSection(DEFAULT_PANEL_SECTION);
6748
6864
  },
6749
- onClick: () => {
6750
- actions.addCategory(DEFAULT_CATEGORY_NAME);
6865
+ discard: () => {
6866
+ actions.dockDiscard();
6867
+ setSection(DEFAULT_PANEL_SECTION);
6751
6868
  },
6752
- children: "\uFF0B"
6869
+ edit: actions.dockEdit
6753
6870
  }
6754
- )
6755
- ] })
6756
- ] }),
6757
- dock !== null && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { padding: "8px 12px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6758
- OptimizeDock,
6759
- {
6760
- state: dock,
6761
- seconds: dockSeconds,
6762
- actions: {
6763
- insert: actions.dockInsert,
6764
- retry: actions.dockRetry,
6765
- cancel: actions.dockCancel,
6766
- close: actions.dockClose,
6767
- edit: actions.dockEdit
6768
6871
  }
6769
- }
6770
- ) }),
6771
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickList, children: [
6772
- items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickEmpty, children: [
6773
- "\u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002",
6872
+ ) }),
6873
+ section === "optimize" && dock === null && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickEmpty, children: [
6874
+ "\u8FD8\u6CA1\u8DD1\u8FC7\u4F18\u5316\u3002",
6875
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
6876
+ "\u70B9\u4E0A\u9762\u7684\u300C\u2728 \u4F18\u5316\u63D0\u793A\u8BCD\u300D\u628A\u8F93\u5165\u6846\u91CC\u7684\u8BDD\u4EA4\u7ED9\u53E6\u4E00\u4E2A AI \u6574\u7406\u6210\u4E00\u6761\u80FD\u76F4\u63A5\u53D1\u7684\u6E05\u6670\u6307\u4EE4 \u2014\u2014 \u7ED3\u679C\u4F1A\u51FA\u73B0\u5728\u8FD9\u91CC\uFF08\u53EF\u7F16\u8F91\u3001\u53EF\u63D2\u5165\u8F93\u5165\u6846\u3001\u53EF\u590D\u5236\uFF09\u3002",
6774
6877
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
6775
- "\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002"
6878
+ "\u5F3A\u5EA6\u7528\u6807\u9898\u884C\u90A3\u4E09\u4E2A\u6863\u4F4D\uFF08\u666E\u901A / \u9AD8\u7EA7 / \u6781\u7AEF\uFF09\u3002"
6776
6879
  ] }),
6777
- items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
6778
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6779
- "button",
6780
- {
6781
- type: "button",
6782
- title: item.prompt,
6783
- style: quickItem,
6784
- onMouseDown: (event) => {
6785
- event.preventDefault();
6786
- },
6787
- onClick: () => {
6788
- actions.insert(item.prompt);
6880
+ section === "quick" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
6881
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { style: { padding: "8px 12px 0" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickCategoryRow, children: [
6882
+ categories.map((category) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6883
+ "button",
6884
+ {
6885
+ type: "button",
6886
+ title: `${category.name}\uFF08${String(category.prompts.length)} \u6761\uFF09`,
6887
+ "aria-pressed": category.id === active2?.id,
6888
+ style: category.id === active2?.id ? quickCategoryTabActive : quickCategoryTab,
6889
+ onMouseDown: (event) => {
6890
+ event.preventDefault();
6891
+ },
6892
+ onClick: () => {
6893
+ setActiveId(category.id);
6894
+ },
6895
+ children: category.name
6789
6896
  },
6790
- children: [
6791
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickItemLabel, children: item.label }),
6792
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
6793
- ]
6794
- }
6795
- ),
6796
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6797
- InsertModeControl,
6798
- {
6799
- compact: true,
6800
- label: item.label,
6801
- mode: insertModeOf(item),
6802
- onChange: (mode) => {
6803
- actions.setInsertMode(item.id, mode);
6897
+ category.id
6898
+ )),
6899
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6900
+ "button",
6901
+ {
6902
+ type: "button",
6903
+ style: quickCategoryAdd,
6904
+ disabled: categories.length >= QUICK_CATEGORY_MAX,
6905
+ title: "\u65B0\u589E\u4E00\u4E2A\u5206\u7C7B\uFF08\u540D\u5B57\u5230\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C\u300D\u91CC\u6539\uFF09",
6906
+ onMouseDown: (event) => {
6907
+ event.preventDefault();
6908
+ },
6909
+ onClick: () => {
6910
+ actions.addCategory(DEFAULT_CATEGORY_NAME);
6911
+ },
6912
+ children: "\uFF0B"
6804
6913
  }
6805
- }
6806
- )
6807
- ] }, item.id)),
6808
- active2 !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6809
- AddPromptRow,
6810
- {
6811
- variant: "panel",
6812
- book,
6813
- categoryId: active2.id,
6814
- onAdd: () => {
6815
- actions.addPrompt(active2.id);
6816
- },
6817
- onMove: (promptId) => {
6818
- actions.movePrompt(promptId, active2.id);
6819
- }
6820
- }
6821
- )
6914
+ )
6915
+ ] }) }),
6916
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickList, children: [
6917
+ items.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickEmpty, children: [
6918
+ "\u8FD9\u4E2A\u5206\u7C7B\u91CC\u8FD8\u6CA1\u6709\u6761\u76EE\u3002",
6919
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("br", {}),
6920
+ "\u5728\u300C\u8BBE\u7F6E \u2192 \u8F93\u5165\u4F53\u9A8C \u2192 \u5FEB\u6377\u6307\u4EE4\u6E05\u5355\u300D\u91CC\u6DFB\u52A0\u3002"
6921
+ ] }),
6922
+ items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 4 }, children: [
6923
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6924
+ "button",
6925
+ {
6926
+ type: "button",
6927
+ title: item.prompt,
6928
+ style: quickItem,
6929
+ onMouseDown: (event) => {
6930
+ event.preventDefault();
6931
+ },
6932
+ onClick: () => {
6933
+ actions.insert(item.prompt);
6934
+ },
6935
+ children: [
6936
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickItemLabel, children: item.label }),
6937
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickItemPreview, children: item.prompt.replace(/\s+/g, " ") })
6938
+ ]
6939
+ }
6940
+ ),
6941
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6942
+ InsertModeControl,
6943
+ {
6944
+ compact: true,
6945
+ label: item.label,
6946
+ mode: insertModeOf(item),
6947
+ onChange: (mode) => {
6948
+ actions.setInsertMode(item.id, mode);
6949
+ }
6950
+ }
6951
+ )
6952
+ ] }, item.id)),
6953
+ active2 !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6954
+ AddPromptRow,
6955
+ {
6956
+ variant: "panel",
6957
+ book,
6958
+ categoryId: active2.id,
6959
+ onAdd: () => {
6960
+ actions.addPrompt(active2.id);
6961
+ },
6962
+ onMove: (promptId) => {
6963
+ actions.movePrompt(promptId, active2.id);
6964
+ }
6965
+ }
6966
+ )
6967
+ ] })
6968
+ ] })
6822
6969
  ] }),
6823
6970
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { style: quickPanelFoot, children: [
6824
6971
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: quickNotice, role: "status", children: notice !== "" ? notice : failure }),
@@ -6855,12 +7002,13 @@ async function request(method, body) {
6855
7002
  try {
6856
7003
  parsed = JSON.parse(raw);
6857
7004
  } catch {
6858
- return { ok: false, state: null, keep: true, error: `\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684\u4E0D\u662F JSON\uFF08HTTP ${String(response.status)}\uFF09` };
7005
+ return { ok: false, state: null, hidden: false, keep: true, error: `\u670D\u52A1\u7AEF\u8FD4\u56DE\u7684\u4E0D\u662F JSON\uFF08HTTP ${String(response.status)}\uFF09` };
6859
7006
  }
6860
7007
  const row2 = typeof parsed === "object" && parsed !== null ? parsed : {};
6861
7008
  return {
6862
7009
  ok: row2.ok === true,
6863
7010
  state: sanitizeDockSnapshot(row2.state),
7011
+ hidden: row2.hidden === true,
6864
7012
  keep: row2.keep !== false,
6865
7013
  ...textOf(row2.file) === void 0 ? {} : { file: textOf(row2.file) },
6866
7014
  ...textOf(row2.error) === void 0 ? {} : { error: textOf(row2.error) },
@@ -6868,14 +7016,14 @@ async function request(method, body) {
6868
7016
  ...row2.tooBig === true ? { tooBig: true } : {}
6869
7017
  };
6870
7018
  } catch (error) {
6871
- return { ok: false, state: null, keep: true, error: error instanceof Error ? error.message : String(error) };
7019
+ return { ok: false, state: null, hidden: false, keep: true, error: error instanceof Error ? error.message : String(error) };
6872
7020
  }
6873
7021
  }
6874
7022
  function loadDockState() {
6875
7023
  return request("GET");
6876
7024
  }
6877
- function saveDockState(state2) {
6878
- return request("POST", { state: state2 });
7025
+ function saveDockState(state2, hidden = false) {
7026
+ return request("POST", { state: state2, hidden: hidden === true });
6879
7027
  }
6880
7028
  function clearDockStateOnHost() {
6881
7029
  return saveDockState(null);
@@ -6900,11 +7048,12 @@ function apply(ctx) {
6900
7048
  const optimizing = (0, import_dsh_client_store.createSnapshotStore)(false);
6901
7049
  const optimizeStartedAt = (0, import_dsh_client_store.createSnapshotStore)(0);
6902
7050
  const dock = (0, import_dsh_client_store.createSnapshotStore)(null);
7051
+ const dockHidden = (0, import_dsh_client_store.createSnapshotStore)(false);
6903
7052
  const keepDockOn = () => live.getSnapshot().optimizeKeepDock === true;
6904
7053
  const DOCK_SAVE_DEBOUNCE_MS = 1200;
6905
7054
  const persistDock = () => {
6906
7055
  if (!keepDockOn()) return;
6907
- void saveDockState(dock.getSnapshot());
7056
+ void saveDockState(dock.getSnapshot(), dockHidden.getSnapshot());
6908
7057
  };
6909
7058
  const clearPersistedDock = () => {
6910
7059
  void clearDockStateOnHost();
@@ -6932,6 +7081,7 @@ function apply(ctx) {
6932
7081
  let alive = true;
6933
7082
  void loadDockState().then((reply) => {
6934
7083
  if (!alive || !reply.ok || reply.state === null) return;
7084
+ dockHidden.set(reply.hidden === true);
6935
7085
  if (dock.getSnapshot() === null) dock.set(dockReducer(null, { type: "restore", snapshot: reply.state }));
6936
7086
  });
6937
7087
  return () => {
@@ -6940,16 +7090,19 @@ function apply(ctx) {
6940
7090
  }, "composer-ux: restore optimize dock");
6941
7091
  ctx.effect(() => {
6942
7092
  let timer = null;
6943
- const unsubscribe = dock.subscribe(() => {
7093
+ const schedule = () => {
6944
7094
  if (timer !== null) clearTimeout(timer);
6945
7095
  timer = setTimeout(() => {
6946
7096
  timer = null;
6947
7097
  persistDock();
6948
7098
  }, DOCK_SAVE_DEBOUNCE_MS);
6949
- });
7099
+ };
7100
+ const unsubscribe = dock.subscribe(schedule);
7101
+ const unsubscribeHidden = dockHidden.subscribe(schedule);
6950
7102
  return () => {
6951
7103
  if (timer !== null) clearTimeout(timer);
6952
7104
  unsubscribe();
7105
+ unsubscribeHidden();
6953
7106
  };
6954
7107
  }, "composer-ux: persist optimize dock");
6955
7108
  };
@@ -7158,6 +7311,7 @@ function apply(ctx) {
7158
7311
  optimizeAbort?.abort();
7159
7312
  const controller = new AbortController();
7160
7313
  optimizeAbort = controller;
7314
+ dockHidden.set(false);
7161
7315
  dock.set(dockReducer(dock.getSnapshot(), {
7162
7316
  type: "start",
7163
7317
  source: input.source,
@@ -7284,9 +7438,25 @@ function apply(ctx) {
7284
7438
  dock.set(dockReducer(state2, { type: "cancel", at: Date.now() }));
7285
7439
  note2("\u5DF2\u53D6\u6D88\u8FD9\u4E00\u8F6E\uFF1A\u4E0A\u9762\u662F\u5DF2\u7ECF\u751F\u6210\u7684\u90E8\u5206");
7286
7440
  },
7287
- /** 收起结果框(丢弃框里的内容;输入框里已插入的内容不受影响)。 */
7441
+ /**
7442
+ * 收起结果框(0.13.2 起**不再丢内容**)。
7443
+ *
7444
+ * 内容一直在 dock 里(也一直在盘上),只是标记成「先别显示」;面板那一半的切换按钮会写
7445
+ * 「上次的结果在这儿」,点它就能再展开。想真丢掉用 `dockDiscard`。
7446
+ */
7288
7447
  dockClose: () => {
7448
+ dockHidden.set(true);
7449
+ note2("\u5DF2\u6536\u8D77\u7ED3\u679C\u6846 \u2014\u2014 \u7ED3\u679C\u7559\u7740\uFF0C\u70B9\u300C\u4F18\u5316\u63D0\u793A\u8BCD\u300D\u90A3\u4E00\u534A\u5C31\u80FD\u518D\u770B\u5230");
7450
+ },
7451
+ /** 丢弃结果框(真的清掉,磁盘那份也删)。 */
7452
+ dockDiscard: () => {
7289
7453
  dock.set(dockReducer(dock.getSnapshot(), { type: "clear" }));
7454
+ dockHidden.set(false);
7455
+ note2("\u5DF2\u4E22\u5F03\u8FD9\u4EFD\u7ED3\u679C");
7456
+ },
7457
+ /** 展开结果框(收起状态的对面)。 */
7458
+ dockShow: () => {
7459
+ dockHidden.set(false);
7290
7460
  },
7291
7461
  /** 用户在框里手改了成品。 */
7292
7462
  dockEdit: (text) => {
@@ -7325,6 +7495,7 @@ function apply(ctx) {
7325
7495
  clearDockState: () => {
7326
7496
  clearPersistedDock();
7327
7497
  dock.set(null);
7498
+ dockHidden.set(false);
7328
7499
  }
7329
7500
  }
7330
7501
  })
@@ -7366,7 +7537,7 @@ function apply(ctx) {
7366
7537
  name: "shell.overlay",
7367
7538
  id: "composer-ux-quick-panel",
7368
7539
  inject: () => ({
7369
- hooks: { live, panel, busy: optimizing, startedAt: optimizeStartedAt, notice: panelNotice, book, bookStatus, dock },
7540
+ hooks: { live, panel, busy: optimizing, startedAt: optimizeStartedAt, notice: panelNotice, book, bookStatus, dock, dockHidden },
7370
7541
  actions: {
7371
7542
  toggle: quickActions.toggle,
7372
7543
  close: quickActions.close,
@@ -7376,6 +7547,8 @@ function apply(ctx) {
7376
7547
  dockRetry: quickActions.dockRetry,
7377
7548
  dockCancel: quickActions.dockCancel,
7378
7549
  dockClose: quickActions.dockClose,
7550
+ dockDiscard: quickActions.dockDiscard,
7551
+ dockShow: quickActions.dockShow,
7379
7552
  dockEdit: quickActions.dockEdit,
7380
7553
  setTier: quickActions.setTier,
7381
7554
  setInsertMode: quickActions.setInsertMode,