@klarkxy/dsh-session-manager 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/client.js CHANGED
@@ -65,18 +65,20 @@ const text = {
65
65
  settingsMode: "继续灰影",
66
66
  modeFixed: "固定文本",
67
67
  modeAuto: "模型生成",
68
- settingsModeHint: "输入框为空时显示的灰色继续文本:Tab 填入,点击发送。",
68
+ settingsModeHint: "输入框为空时显示建议;按 Tab 填入,点击直接发送。",
69
+ continueSourceLabel: "内容来源",
69
70
  continueTextLabel: "固定文本内容",
70
71
  continueTextPlaceholder: "留空使用默认「继续」",
71
- ghostModelLabel: "灰影模型",
72
- ghostModelHint: "只在上一轮结束后生成一次,并缓存在这个会话中;留空跟随会话或宿主默认。",
73
- welcomeBackGroup: "欢迎回来",
74
- recapEnabledLabel: "欢迎回来摘要",
75
- recapEnabledHint: "回到空闲的会话时,在对话顶部生成回顾卡片。",
76
- recapMinutesLabel: "摘要阈值(分钟)",
77
- compactEnabledLabel: "压缩建议",
78
- compactEnabledHint: "空闲较久时,回到会话会建议先压缩上下文。",
79
- compactMinutesLabel: "建议阈值(分钟)",
72
+ ghostModelLabel: "生成模型",
73
+ ghostModelHint: "每轮结束后生成一次并缓存;不选择时使用当前会话或宿主的默认模型。",
74
+ welcomeBackGroup: "回到会话时",
75
+ recapEnabledLabel: "显示会话摘要",
76
+ recapEnabledHint: "在对话中回顾上次进展。",
77
+ recapMinutesLabel: "离开多久后显示摘要",
78
+ compactEnabledLabel: "建议压缩上下文",
79
+ compactEnabledHint: "长时间离开后,建议先压缩上下文。",
80
+ compactMinutesLabel: "离开多久后显示建议",
81
+ minutesUnit: "分钟",
80
82
  modelLabel: "摘要模型",
81
83
  modelFollowOption: "当前会话 / 宿主默认模型",
82
84
  modelGroupHint: "只用于欢迎回来摘要;留空跟随会话或宿主默认。",
@@ -119,18 +121,20 @@ const text = {
119
121
  settingsMode: "Continue ghost",
120
122
  modeFixed: "Fixed text",
121
123
  modeAuto: "Model-generated",
122
- settingsModeHint: "The grey continuation shown on an empty composer: Tab fills it, clicking sends it.",
124
+ settingsModeHint: "Show a suggestion when the composer is empty. Press Tab to fill it, or click to send.",
125
+ continueSourceLabel: "Source",
123
126
  continueTextLabel: "Fixed text",
124
127
  continueTextPlaceholder: "Empty uses the default \"Continue\"",
125
- ghostModelLabel: "Ghost model",
126
- ghostModelHint: "Generated once after the previous turn ends and cached for this session; empty follows the conversation or host default.",
127
- welcomeBackGroup: "Welcome back",
128
- recapEnabledLabel: "Welcome-back recap",
129
- recapEnabledHint: "Shows a recap card at the top of the conversation when you return to an idle session.",
130
- recapMinutesLabel: "Recap threshold (minutes)",
131
- compactEnabledLabel: "Compaction suggestion",
132
- compactEnabledHint: "Suggests compacting the context when you return after a longer idle stretch.",
133
- compactMinutesLabel: "Suggestion threshold (minutes)",
128
+ ghostModelLabel: "Generation model",
129
+ ghostModelHint: "Generated once after each turn and cached. The default follows the current conversation or host.",
130
+ welcomeBackGroup: "When you return",
131
+ recapEnabledLabel: "Show session recap",
132
+ recapEnabledHint: "Review your previous progress in the conversation.",
133
+ recapMinutesLabel: "Show recap after",
134
+ compactEnabledLabel: "Suggest context compaction",
135
+ compactEnabledHint: "Suggest compacting the context after a long time away.",
136
+ compactMinutesLabel: "Show suggestion after",
137
+ minutesUnit: "minutes",
134
138
  modelLabel: "Recap model",
135
139
  modelFollowOption: "Current conversation / host default",
136
140
  modelGroupHint: "Used only for the welcome-back recap; empty follows the conversation or host default.",
@@ -1660,25 +1664,88 @@ ${modelMenuCss}
1660
1664
  min-width: 0;
1661
1665
  }
1662
1666
  .${FREE_CHAT_ROOT} .dsh-free-alert { margin: 0; }
1663
- /* Settings page: a feature is its toggle row plus the nested well that holds
1664
- * the fields the switch gates. The well reuses the nested-card surface
1665
- * (layer-2 on layer-1) so the grouping reads without another heading. */
1667
+ /* Settings page: one quiet reading surface. Rules, not nested wells, separate
1668
+ * sections; dependent controls align with the feature they belong to. */
1669
+ .${FREE_CHAT_ROOT} .dsm-settings {
1670
+ display: flex;
1671
+ flex-direction: column;
1672
+ gap: 20px;
1673
+ min-width: 0;
1674
+ }
1675
+ .${FREE_CHAT_ROOT} .dsm-setting {
1676
+ display: flex;
1677
+ flex-direction: column;
1678
+ gap: 12px;
1679
+ min-width: 0;
1680
+ }
1681
+ .${FREE_CHAT_ROOT} .dsm-setting + .dsm-setting {
1682
+ padding-top: 20px;
1683
+ border-top: 0.5px solid var(--dsw-alias-border-l2);
1684
+ }
1685
+ .${FREE_CHAT_ROOT} .dsm-setting-header {
1686
+ display: flex;
1687
+ flex-direction: column;
1688
+ gap: 4px;
1689
+ }
1690
+ .${FREE_CHAT_ROOT} .dsm-ghost-controls {
1691
+ display: grid;
1692
+ grid-template-columns: minmax(220px, 0.8fr) minmax(0, 1.2fr);
1693
+ align-items: start;
1694
+ gap: 16px;
1695
+ }
1696
+ /* SegmentedTabs is 42px tall; its adjacent text controls share that baseline. */
1697
+ .${FREE_CHAT_ROOT} .dsm-ghost-controls .dsh-model-menu-trigger,
1698
+ .${FREE_CHAT_ROOT} .dsm-ghost-controls .dsm-ghost-input {
1699
+ height: 42px;
1700
+ }
1666
1701
  .${FREE_CHAT_ROOT} .dsm-feature + .dsm-feature {
1702
+ margin-top: 4px;
1667
1703
  border-top: 0.5px solid var(--dsw-alias-border-l2);
1668
1704
  }
1669
- .${FREE_CHAT_ROOT} .dsm-subs {
1705
+ .${FREE_CHAT_ROOT} .dsm-feature > .dsh-ui-toggle-row { padding: 8px 0; }
1706
+ .${FREE_CHAT_ROOT} .dsm-feature-options {
1670
1707
  display: flex;
1671
1708
  flex-direction: column;
1672
- gap: 12px;
1673
- margin: 0 0 4px;
1674
- padding: 12px;
1675
- border-radius: var(--dsw-radius-md);
1676
- background: var(--dsw-alias-bg-layer-2);
1709
+ gap: 8px;
1710
+ padding: 4px 0 8px;
1677
1711
  }
1678
- .${FREE_CHAT_ROOT} .dsm-subs[data-disabled='true'] .dsh-ui-label {
1712
+ .${FREE_CHAT_ROOT} .dsm-feature-options[data-disabled='true'] .dsh-ui-label,
1713
+ .${FREE_CHAT_ROOT} .dsm-feature-options[data-disabled='true'] .dsh-ui-meta {
1679
1714
  color: var(--dsw-alias-label-tertiary);
1680
1715
  }
1681
- .${FREE_CHAT_ROOT} .dsm-minutes { width: 120px; }
1716
+ .${FREE_CHAT_ROOT} .dsm-compact-options { max-width: calc(50% - 10px); }
1717
+ .${FREE_CHAT_ROOT} .dsm-model-field .dsh-model-menu-root,
1718
+ .${FREE_CHAT_ROOT} .dsm-model-field .dsh-model-menu-trigger {
1719
+ width: 100%;
1720
+ max-width: none;
1721
+ }
1722
+ .${FREE_CHAT_ROOT} .dsm-model-field .dsh-model-menu-trigger {
1723
+ justify-content: space-between;
1724
+ height: 32px;
1725
+ padding: 0 10px;
1726
+ border: 0.5px solid var(--dsw-alias-border-l4);
1727
+ border-radius: var(--dsw-radius-md);
1728
+ background: var(--dsw-alias-bg-layer-3);
1729
+ color: var(--dsw-alias-label-primary);
1730
+ }
1731
+ .${FREE_CHAT_ROOT} .dsm-model-field .dsh-model-menu-triggerLabel {
1732
+ flex: 1;
1733
+ text-align: left;
1734
+ }
1735
+ .${FREE_CHAT_ROOT} .dsm-settings-footer .dsh-ui-notice--error {
1736
+ flex: 0 0 100%;
1737
+ min-width: 0;
1738
+ }
1739
+ .${FREE_CHAT_ROOT} .dsm-minutes-control {
1740
+ display: flex;
1741
+ align-items: center;
1742
+ gap: 8px;
1743
+ }
1744
+ .${FREE_CHAT_ROOT} .dsm-minutes { width: 88px; }
1745
+ @media (max-width: 560px) {
1746
+ .${FREE_CHAT_ROOT} .dsm-ghost-controls { grid-template-columns: minmax(0, 1fr); }
1747
+ .${FREE_CHAT_ROOT} .dsm-compact-options { max-width: none; }
1748
+ }
1682
1749
  /* Welcome-back card: one flat full-width row at the latest turn's tail in the
1683
1750
  * chat flow — a single bordered surface with the recap laid out inline, no
1684
1751
  * nested box. */
@@ -2820,11 +2887,11 @@ function createContinueModel(host) {
2820
2887
  load(sessionId) {
2821
2888
  if (sessionId === "" || lifetime.signal.aborted || inflight.has(sessionId)) return;
2822
2889
  const current = read(sessionId);
2823
- if (current.text !== void 0 && current.seq === void 0) return;
2890
+ if (current.text !== void 0 && current.seq === void 0 && current.pending !== true) return;
2824
2891
  const ticket = new AbortController();
2825
2892
  inflight.set(sessionId, ticket);
2826
2893
  const signal = AbortSignal.any([lifetime.signal, ticket.signal]);
2827
- callContinueSuggest(host, sessionId, current.seq, signal).then((value) => {
2894
+ callContinueSuggest(host, sessionId, current.text ? current.seq : void 0, signal).then((value) => {
2828
2895
  if (signal.aborted || inflight.get(sessionId) !== ticket) return;
2829
2896
  write(sessionId, value);
2830
2897
  }).catch(() => {}).finally(() => {
@@ -2863,7 +2930,9 @@ async function callContinueSuggest(host, sessionId, knownSeq, signal) {
2863
2930
  const seq = typeof value?.seq === "number" && Number.isSafeInteger(value.seq) && value.seq >= 0 ? value.seq : void 0;
2864
2931
  return {
2865
2932
  text,
2866
- ...seq === void 0 ? {} : { seq }
2933
+ ...seq === void 0 ? {} : { seq },
2934
+ ...value?.pending === true ? { pending: true } : {},
2935
+ ...value?.fallback === true ? { fallback: true } : {}
2867
2936
  };
2868
2937
  }
2869
2938
  function createPresenceConfigModel(host, delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))) {
@@ -3320,8 +3389,10 @@ function ContinueGhost(props) {
3320
3389
  const blank = props.useSession?.((state) => state.blank) ?? true;
3321
3390
  const running = props.useSessionStatus?.((state) => state.get(sessionId)?.running === true) ?? false;
3322
3391
  const snapshot = (0, react.useSyncExternalStore)(props.model.subscribe, () => props.model.getSnapshot(sessionId), () => props.model.getSnapshot(sessionId));
3323
- const text = snapshot.text ?? uiText(props.locale, "continueDefault");
3324
- const active = sessionId !== "" && !blank && bare && draft === "" && phase === "plain";
3392
+ const shown = running || snapshot.pending === true || snapshot.text === void 0 ? "" : snapshot.text ?? (snapshot.fallback === true ? uiText(props.locale, "continueDefault") : "");
3393
+ const idle = sessionId !== "" && !blank && bare && draft === "" && phase === "plain" && !running;
3394
+ const active = shown !== "" && idle;
3395
+ const text = shown;
3325
3396
  const latest = (0, react.useRef)({
3326
3397
  active,
3327
3398
  text
@@ -3337,18 +3408,18 @@ function ContinueGhost(props) {
3337
3408
  const finished = wasRunning.current && !running;
3338
3409
  wasRunning.current = running;
3339
3410
  if (finished && sessionId !== "") props.model.invalidate(sessionId);
3340
- if (active && !running) props.model.load(sessionId);
3411
+ if (idle && !running) props.model.load(sessionId);
3341
3412
  }, [
3342
3413
  props.model,
3343
- active,
3414
+ idle,
3344
3415
  running,
3345
3416
  sessionId
3346
3417
  ]);
3347
3418
  (0, react.useEffect)(() => {
3348
- if (active && !running && snapshot.text === void 0) props.model.load(sessionId);
3419
+ if (idle && !running && snapshot.text === void 0) props.model.load(sessionId);
3349
3420
  }, [
3350
3421
  props.model,
3351
- active,
3422
+ idle,
3352
3423
  running,
3353
3424
  sessionId,
3354
3425
  snapshot
@@ -3644,117 +3715,135 @@ function SessionManagerSettings(props) {
3644
3715
  };
3645
3716
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3646
3717
  className: `${FREE_CHAT_ROOT} dsh-ui-page`,
3647
- children: [
3648
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3649
- className: "dsh-ui-card",
3718
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3719
+ className: "dsm-settings",
3720
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3721
+ className: "dsm-setting",
3722
+ "aria-labelledby": `${tabsId}-ghost-heading`,
3650
3723
  children: [
3651
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3652
- className: "dsh-ui-heading",
3653
- children: copy("settingsMode")
3654
- }),
3655
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3656
- className: "dsh-ui-hint",
3657
- children: copy("settingsModeHint")
3658
- }),
3659
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
3660
- label: copy("settingsMode"),
3661
- items: [{
3662
- id: `${tabsId}-fixed`,
3663
- panelId: fixedPanelId,
3664
- value: "fixed",
3665
- label: copy("modeFixed")
3666
- }, {
3667
- id: `${tabsId}-auto`,
3668
- panelId: autoPanelId,
3669
- value: "auto",
3670
- label: copy("modeAuto")
3671
- }],
3672
- value: draft.continueMode,
3673
- onChange: (value) => edit({
3674
- ...draft,
3675
- continueMode: value
3676
- })
3677
- }) }),
3678
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3679
- role: "tabpanel",
3680
- id: fixedPanelId,
3681
- "aria-labelledby": `${tabsId}-fixed`,
3682
- hidden: draft.continueMode !== "fixed",
3683
- children: draft.continueMode === "fixed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3684
- className: "dsh-ui-field",
3685
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3686
- className: "dsh-ui-label",
3687
- children: copy("continueTextLabel")
3688
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3689
- value: draft.continueText,
3690
- placeholder: copy("continueTextPlaceholder"),
3691
- onChange: (event) => edit({
3692
- ...draft,
3693
- continueText: event.target.value
3694
- })
3695
- })]
3696
- }) : null
3724
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
3725
+ className: "dsm-setting-header",
3726
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3727
+ id: `${tabsId}-ghost-heading`,
3728
+ className: "dsh-ui-title",
3729
+ children: copy("settingsMode")
3730
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3731
+ className: "dsh-ui-hint",
3732
+ children: copy("settingsModeHint")
3733
+ })]
3697
3734
  }),
3698
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3699
- role: "tabpanel",
3700
- id: autoPanelId,
3701
- "aria-labelledby": `${tabsId}-auto`,
3702
- hidden: draft.continueMode !== "auto",
3703
- children: draft.continueMode === "auto" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3704
- className: "dsh-ui-field",
3705
- children: [
3706
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3735
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3736
+ className: "dsm-ghost-controls",
3737
+ children: [
3738
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3739
+ className: "dsh-ui-field",
3740
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3707
3741
  className: "dsh-ui-label",
3708
- children: copy("ghostModelLabel")
3709
- }),
3710
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
3711
- locale: props.locale,
3712
- open: ghostMenuOpen,
3713
- onOpenChange: setGhostMenuOpen,
3714
- listClassName: FREE_CHAT_ROOT,
3715
- anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3716
- type: "button",
3717
- className: "dsh-model-menu-trigger",
3718
- "aria-label": `${copy("ghostModelLabel")}: ${ghostLabel}`,
3719
- "aria-haspopup": "menu",
3720
- "aria-expanded": ghostMenuOpen,
3721
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3722
- className: "dsh-model-menu-triggerLabel",
3723
- children: ghostLabel
3724
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `dsh-model-menu-chevron${ghostMenuOpen ? " dsh-model-menu-chevronOpen" : ""}` })]
3725
- }),
3726
- choices: selectableChoices,
3727
- selected: ghostRoute,
3728
- onPick: (route) => edit({
3729
- ...draft,
3730
- ghostModel: modelRouteKey(route.provider, route.model)
3731
- }),
3732
- leading: [{
3733
- id: "follow",
3734
- label: copy("modelFollowOption"),
3735
- selected: !ghostRoute
3742
+ children: copy("continueSourceLabel")
3743
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.SegmentedTabs, {
3744
+ label: copy("continueSourceLabel"),
3745
+ items: [{
3746
+ id: `${tabsId}-fixed`,
3747
+ panelId: fixedPanelId,
3748
+ value: "fixed",
3749
+ label: copy("modeFixed")
3750
+ }, {
3751
+ id: `${tabsId}-auto`,
3752
+ panelId: autoPanelId,
3753
+ value: "auto",
3754
+ label: copy("modeAuto")
3736
3755
  }],
3737
- onPickLeading: () => edit({
3756
+ value: draft.continueMode,
3757
+ onChange: (value) => edit({
3738
3758
  ...draft,
3739
- ghostModel: ""
3740
- }),
3741
- modelValue: ghostLabel
3742
- }) }),
3743
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3744
- className: "dsh-ui-hint",
3745
- children: copy("ghostModelHint")
3746
- })
3747
- ]
3748
- }) : null
3749
- })
3759
+ continueMode: value
3760
+ })
3761
+ })]
3762
+ }),
3763
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3764
+ role: "tabpanel",
3765
+ id: fixedPanelId,
3766
+ "aria-labelledby": `${tabsId}-fixed`,
3767
+ hidden: draft.continueMode !== "fixed",
3768
+ children: draft.continueMode === "fixed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3769
+ className: "dsh-ui-field",
3770
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3771
+ className: "dsh-ui-label",
3772
+ children: copy("continueTextLabel")
3773
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3774
+ className: "dsm-ghost-input",
3775
+ value: draft.continueText,
3776
+ placeholder: copy("continueTextPlaceholder"),
3777
+ onChange: (event) => edit({
3778
+ ...draft,
3779
+ continueText: event.target.value
3780
+ })
3781
+ })]
3782
+ }) : null
3783
+ }),
3784
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3785
+ role: "tabpanel",
3786
+ id: autoPanelId,
3787
+ "aria-labelledby": `${tabsId}-auto`,
3788
+ hidden: draft.continueMode !== "auto",
3789
+ children: draft.continueMode === "auto" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3790
+ className: "dsh-ui-field dsm-model-field",
3791
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3792
+ className: "dsh-ui-label",
3793
+ children: copy("ghostModelLabel")
3794
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
3795
+ locale: props.locale,
3796
+ open: ghostMenuOpen,
3797
+ onOpenChange: setGhostMenuOpen,
3798
+ listClassName: FREE_CHAT_ROOT,
3799
+ anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3800
+ type: "button",
3801
+ className: "dsh-model-menu-trigger",
3802
+ "aria-label": `${copy("ghostModelLabel")}: ${ghostLabel}`,
3803
+ "aria-haspopup": "menu",
3804
+ "aria-expanded": ghostMenuOpen,
3805
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3806
+ className: "dsh-model-menu-triggerLabel",
3807
+ children: ghostLabel
3808
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `dsh-model-menu-chevron${ghostMenuOpen ? " dsh-model-menu-chevronOpen" : ""}` })]
3809
+ }),
3810
+ choices: selectableChoices,
3811
+ selected: ghostRoute,
3812
+ onPick: (route) => edit({
3813
+ ...draft,
3814
+ ghostModel: modelRouteKey(route.provider, route.model)
3815
+ }),
3816
+ leading: [{
3817
+ id: "follow",
3818
+ label: copy("modelFollowOption"),
3819
+ selected: !ghostRoute
3820
+ }],
3821
+ onPickLeading: () => edit({
3822
+ ...draft,
3823
+ ghostModel: ""
3824
+ }),
3825
+ modelValue: ghostLabel
3826
+ })]
3827
+ }) : null
3828
+ })
3829
+ ]
3830
+ }),
3831
+ draft.continueMode === "auto" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3832
+ className: "dsh-ui-hint",
3833
+ children: copy("ghostModelHint")
3834
+ }) : null
3750
3835
  ]
3751
- }),
3752
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3753
- className: "dsh-ui-card",
3836
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
3837
+ className: "dsm-setting",
3838
+ "aria-labelledby": `${tabsId}-return-heading`,
3754
3839
  children: [
3755
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3756
- className: "dsh-ui-heading",
3757
- children: copy("welcomeBackGroup")
3840
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
3841
+ className: "dsm-setting-header",
3842
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
3843
+ id: `${tabsId}-return-heading`,
3844
+ className: "dsh-ui-title",
3845
+ children: copy("welcomeBackGroup")
3846
+ })
3758
3847
  }),
3759
3848
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3760
3849
  className: "dsm-feature",
@@ -3778,84 +3867,82 @@ function SessionManagerSettings(props) {
3778
3867
  })
3779
3868
  })]
3780
3869
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3781
- className: "dsm-subs",
3870
+ className: "dsm-feature-options",
3782
3871
  "data-disabled": draft.recapEnabled ? void 0 : "true",
3783
- children: [
3784
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3872
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3873
+ className: "dsh-ui-fields-grid",
3874
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3785
3875
  className: "dsh-ui-field",
3786
3876
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3787
3877
  className: "dsh-ui-label",
3788
3878
  children: copy("recapMinutesLabel")
3789
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3790
- className: "dsm-minutes",
3791
- value: draft.recapMinutes,
3792
- inputMode: "numeric",
3793
- disabled: !draft.recapEnabled,
3794
- "aria-invalid": recapInvalid || void 0,
3795
- "aria-describedby": recapInvalid ? `${tabsId}-recap-error` : void 0,
3796
- onChange: (event) => edit({
3797
- ...draft,
3798
- recapMinutes: event.target.value
3799
- })
3879
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3880
+ className: "dsm-minutes-control",
3881
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3882
+ className: "dsm-minutes",
3883
+ value: draft.recapMinutes,
3884
+ inputMode: "numeric",
3885
+ disabled: !draft.recapEnabled,
3886
+ "aria-invalid": recapInvalid || void 0,
3887
+ "aria-describedby": recapInvalid ? `${tabsId}-recap-error` : void 0,
3888
+ onChange: (event) => edit({
3889
+ ...draft,
3890
+ recapMinutes: event.target.value
3891
+ })
3892
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3893
+ className: "dsh-ui-meta",
3894
+ children: copy("minutesUnit")
3895
+ })]
3800
3896
  })]
3801
3897
  }), recapInvalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3802
3898
  id: `${tabsId}-recap-error`,
3803
3899
  className: "dsh-ui-error",
3804
3900
  role: "alert",
3805
3901
  children: copy("minutesInvalid")
3806
- }) : null] }),
3807
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3808
- className: "dsh-ui-field",
3809
- children: [
3810
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3811
- className: "dsh-ui-label",
3812
- children: copy("modelLabel")
3902
+ }) : null] }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3903
+ className: "dsh-ui-field dsm-model-field",
3904
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3905
+ className: "dsh-ui-label",
3906
+ children: copy("modelLabel")
3907
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
3908
+ locale: props.locale,
3909
+ open: menuOpen,
3910
+ onOpenChange: setMenuOpen,
3911
+ listClassName: FREE_CHAT_ROOT,
3912
+ anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3913
+ type: "button",
3914
+ className: "dsh-model-menu-trigger",
3915
+ disabled: !draft.recapEnabled,
3916
+ "aria-label": `${copy("modelLabel")}: ${selectedLabel}`,
3917
+ "aria-haspopup": "menu",
3918
+ "aria-expanded": menuOpen,
3919
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3920
+ className: "dsh-model-menu-triggerLabel",
3921
+ children: selectedLabel
3922
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `dsh-model-menu-chevron${menuOpen ? " dsh-model-menu-chevronOpen" : ""}` })]
3813
3923
  }),
3814
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelMenu, {
3815
- locale: props.locale,
3816
- open: menuOpen,
3817
- onOpenChange: setMenuOpen,
3818
- listClassName: FREE_CHAT_ROOT,
3819
- anchor: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3820
- type: "button",
3821
- className: "dsh-model-menu-trigger",
3822
- disabled: !draft.recapEnabled,
3823
- "aria-label": `${copy("modelLabel")}: ${selectedLabel}`,
3824
- "aria-haspopup": "menu",
3825
- "aria-expanded": menuOpen,
3826
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3827
- className: "dsh-model-menu-triggerLabel",
3828
- children: selectedLabel
3829
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineRegular, { className: `dsh-model-menu-chevron${menuOpen ? " dsh-model-menu-chevronOpen" : ""}` })]
3830
- }),
3831
- choices: selectableChoices,
3832
- selected: selectedRoute,
3833
- onPick: (route) => edit({
3834
- ...draft,
3835
- model: modelRouteKey(route.provider, route.model)
3836
- }),
3837
- leading: [{
3838
- id: "follow",
3839
- label: copy("modelFollowOption"),
3840
- selected: !selectedRoute
3841
- }],
3842
- onPickLeading: () => edit({
3843
- ...draft,
3844
- model: ""
3845
- }),
3846
- modelValue: selectedLabel
3847
- }) }),
3848
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3849
- className: "dsh-ui-hint",
3850
- children: copy("modelGroupHint")
3851
- })
3852
- ]
3853
- }),
3854
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
3855
- state: catalog,
3856
- locale: props.locale
3857
- })
3858
- ]
3924
+ choices: selectableChoices,
3925
+ selected: selectedRoute,
3926
+ onPick: (route) => edit({
3927
+ ...draft,
3928
+ model: modelRouteKey(route.provider, route.model)
3929
+ }),
3930
+ leading: [{
3931
+ id: "follow",
3932
+ label: copy("modelFollowOption"),
3933
+ selected: !selectedRoute
3934
+ }],
3935
+ onPickLeading: () => edit({
3936
+ ...draft,
3937
+ model: ""
3938
+ }),
3939
+ modelValue: selectedLabel
3940
+ })]
3941
+ })]
3942
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModelCatalogStatus, {
3943
+ state: catalog,
3944
+ locale: props.locale
3945
+ })]
3859
3946
  })]
3860
3947
  }),
3861
3948
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -3880,24 +3967,30 @@ function SessionManagerSettings(props) {
3880
3967
  })
3881
3968
  })]
3882
3969
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3883
- className: "dsm-subs",
3970
+ className: "dsm-feature-options dsm-compact-options",
3884
3971
  "data-disabled": draft.compactEnabled ? void 0 : "true",
3885
3972
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
3886
3973
  className: "dsh-ui-field",
3887
3974
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3888
3975
  className: "dsh-ui-label",
3889
3976
  children: copy("compactMinutesLabel")
3890
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3891
- className: "dsm-minutes",
3892
- value: draft.compactMinutes,
3893
- inputMode: "numeric",
3894
- disabled: !draft.compactEnabled,
3895
- "aria-invalid": compactInvalid || void 0,
3896
- "aria-describedby": compactInvalid ? `${tabsId}-compact-error` : void 0,
3897
- onChange: (event) => edit({
3898
- ...draft,
3899
- compactMinutes: event.target.value
3900
- })
3977
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
3978
+ className: "dsm-minutes-control",
3979
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Input, {
3980
+ className: "dsm-minutes",
3981
+ value: draft.compactMinutes,
3982
+ inputMode: "numeric",
3983
+ disabled: !draft.compactEnabled,
3984
+ "aria-invalid": compactInvalid || void 0,
3985
+ "aria-describedby": compactInvalid ? `${tabsId}-compact-error` : void 0,
3986
+ onChange: (event) => edit({
3987
+ ...draft,
3988
+ compactMinutes: event.target.value
3989
+ })
3990
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3991
+ className: "dsh-ui-meta",
3992
+ children: copy("minutesUnit")
3993
+ })]
3901
3994
  })]
3902
3995
  }), compactInvalid ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
3903
3996
  id: `${tabsId}-compact-error`,
@@ -3908,34 +4001,33 @@ function SessionManagerSettings(props) {
3908
4001
  })]
3909
4002
  })
3910
4003
  ]
3911
- }),
3912
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3913
- className: "dsh-ui-form-footer",
3914
- children: [
3915
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
3916
- variant: "primary",
3917
- disabled: invalid || snapshot.saving,
3918
- onClick: save,
3919
- children: snapshot.saving ? copy("settingsSaving") : copy("saveSettings")
3920
- }),
3921
- snapshot.saved ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3922
- className: "dsh-ui-notice",
3923
- role: "status",
3924
- children: copy("settingsSaved")
3925
- }) : null,
3926
- externalChange ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3927
- className: "dsh-ui-notice dsh-ui-notice--error",
3928
- role: "alert",
3929
- children: copy("externalChange")
3930
- }) : null,
3931
- snapshot.failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3932
- className: "dsh-ui-notice dsh-ui-notice--error",
3933
- role: "alert",
3934
- children: failureText(props.locale, snapshot.failure)
3935
- }) : null
3936
- ]
3937
- })
3938
- ]
4004
+ })]
4005
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4006
+ className: "dsh-ui-form-footer dsm-settings-footer",
4007
+ children: [
4008
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
4009
+ variant: "primary",
4010
+ disabled: invalid || snapshot.saving,
4011
+ onClick: save,
4012
+ children: snapshot.saving ? copy("settingsSaving") : copy("saveSettings")
4013
+ }),
4014
+ snapshot.saved ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4015
+ className: "dsh-ui-notice",
4016
+ role: "status",
4017
+ children: copy("settingsSaved")
4018
+ }) : null,
4019
+ externalChange ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4020
+ className: "dsh-ui-notice dsh-ui-notice--error",
4021
+ role: "alert",
4022
+ children: copy("externalChange")
4023
+ }) : null,
4024
+ snapshot.failure ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4025
+ className: "dsh-ui-notice dsh-ui-notice--error",
4026
+ role: "alert",
4027
+ children: failureText(props.locale, snapshot.failure)
4028
+ }) : null
4029
+ ]
4030
+ })]
3939
4031
  });
3940
4032
  }
3941
4033
  //#endregion