dsh-smooth-stream 0.5.0 → 0.6.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 +226 -76
- package/lib/client.js.map +1 -1
- package/lib/index.js +16 -0
- package/package.json +1 -1
- package/src/client/SmoothStreamCard.module.css +34 -0
- package/src/client/SmoothStreamCard.tsx +29 -0
- package/src/client/TypewriterAssistantNodeView.tsx +115 -16
- package/src/client/index.ts +2 -0
- package/src/client/locales.ts +20 -0
- package/src/client/smooth-stream-card-controller.ts +7 -3
- package/src/client/smooth-stream-settings-api.ts +4 -2
- package/src/client/turn-process-face.d.ts +27 -0
- package/src/plugin.ts +23 -0
- package/src/settings-api.ts +2 -0
- package/src/settings.ts +20 -0
package/lib/client.js
CHANGED
|
@@ -23,27 +23,27 @@ window.__ModuleLoader__.load({
|
|
|
23
23
|
tag.textContent = css$3;
|
|
24
24
|
}
|
|
25
25
|
var TypewriterAssistantNodeView_module_css_default = {
|
|
26
|
-
"
|
|
27
|
-
"disclosureTitle": "I17U7q_disclosureTitle",
|
|
28
|
-
"thinkRow": "I17U7q_thinkRow",
|
|
26
|
+
"stopped": "I17U7q_stopped",
|
|
29
27
|
"thinkChevron": "I17U7q_thinkChevron",
|
|
30
|
-
"
|
|
28
|
+
"thinkTitle": "I17U7q_thinkTitle",
|
|
29
|
+
"thinkLeading": "I17U7q_thinkLeading",
|
|
30
|
+
"thinkSeparator": "I17U7q_thinkSeparator",
|
|
31
31
|
"body": "I17U7q_body",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"thinkBody": "I17U7q_thinkBody",
|
|
33
|
+
"disclosureContent": "I17U7q_disclosureContent",
|
|
34
34
|
"visuallyHidden": "I17U7q_visuallyHidden",
|
|
35
|
-
"
|
|
36
|
-
"thinkSummary": "I17U7q_thinkSummary",
|
|
37
|
-
"think": "I17U7q_think",
|
|
35
|
+
"disclosureTitle": "I17U7q_disclosureTitle",
|
|
38
36
|
"dsh-smooth-stream-think-sweep": "I17U7q_dsh-smooth-stream-think-sweep",
|
|
39
|
-
"
|
|
40
|
-
"thinkLeading": "I17U7q_thinkLeading",
|
|
41
|
-
"disclosureContent": "I17U7q_disclosureContent",
|
|
37
|
+
"disclosureIconIdle": "I17U7q_disclosureIconIdle",
|
|
42
38
|
"follow": "I17U7q_follow",
|
|
39
|
+
"think": "I17U7q_think",
|
|
40
|
+
"thinkSummary": "I17U7q_thinkSummary",
|
|
41
|
+
"disclosureRow": "I17U7q_disclosureRow",
|
|
42
|
+
"root": "I17U7q_root",
|
|
43
43
|
"disclosureLeading": "I17U7q_disclosureLeading",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
44
|
+
"thinkRow": "I17U7q_thinkRow",
|
|
45
|
+
"disclosureChevronHover": "I17U7q_disclosureChevronHover",
|
|
46
|
+
"disclosureRoot": "I17U7q_disclosureRoot"
|
|
47
47
|
};
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/client/AnimatedDisclosure.tsx
|
|
@@ -126,6 +126,7 @@ window.__ModuleLoader__.load({
|
|
|
126
126
|
const DEFAULT_STREAM_SETTINGS = {
|
|
127
127
|
enabled: true,
|
|
128
128
|
controlScroll: true,
|
|
129
|
+
motionPreference: "auto",
|
|
129
130
|
thinkAutoExpand: true,
|
|
130
131
|
debugEnabled: false,
|
|
131
132
|
debugTuning: DEFAULT_STREAM_DEBUG_TUNING
|
|
@@ -2681,6 +2682,20 @@ window.__ModuleLoader__.load({
|
|
|
2681
2682
|
}, []);
|
|
2682
2683
|
return reduced;
|
|
2683
2684
|
}
|
|
2685
|
+
/**
|
|
2686
|
+
* Resolve whether the reveal engine should stay off for this view. The OS
|
|
2687
|
+
* preference wins only in `auto` mode: `force-smooth` keeps the engine on
|
|
2688
|
+
* machines where a system-wide reduce-motion switch (or a forced browser
|
|
2689
|
+
* flag) would otherwise silently bypass smoothing, and `force-reduced`
|
|
2690
|
+
* disables it even when the OS asks for motion. Credit: three-state design
|
|
2691
|
+
* proposed by @Zn-Dk in #21/#22.
|
|
2692
|
+
*/
|
|
2693
|
+
function useMotionReduced(preference) {
|
|
2694
|
+
const system = usePrefersReducedMotion();
|
|
2695
|
+
if (preference === "force-smooth") return false;
|
|
2696
|
+
if (preference === "force-reduced") return true;
|
|
2697
|
+
return system;
|
|
2698
|
+
}
|
|
2684
2699
|
/** Conservative fallback before the streaming Markdown tail has geometry. */
|
|
2685
2700
|
const PREDICTIVE_WRAP_FALLBACK_CHARS = 32;
|
|
2686
2701
|
const STREAM_ANNOUNCEMENT_INTERVAL_MS = 800;
|
|
@@ -2886,8 +2901,8 @@ window.__ModuleLoader__.load({
|
|
|
2886
2901
|
* drains, the settled full parse (KaTeX math, fence highlighting, file
|
|
2887
2902
|
* mentions) swaps in exactly once.
|
|
2888
2903
|
*/
|
|
2889
|
-
function AnimatedMarkdownText({ text, labels, fileMentions, streaming, ownFollow, followSpeedCpsRef, followRevealedCharsRef, followRevealScaleRef, onPredictiveChange, preset, shouldHoldBack, controlScroll = true }) {
|
|
2890
|
-
const reduced =
|
|
2904
|
+
function AnimatedMarkdownText({ text, labels, fileMentions, streaming, motionReduced, ownFollow, followSpeedCpsRef, followRevealedCharsRef, followRevealScaleRef, onPredictiveChange, preset, shouldHoldBack, controlScroll = true }) {
|
|
2905
|
+
const reduced = motionReduced;
|
|
2891
2906
|
const [typing, setTyping] = (0, react.useState)(streaming);
|
|
2892
2907
|
const localSpeedCpsRef = (0, react.useRef)(35);
|
|
2893
2908
|
const followRootRef = (0, react.useRef)(null);
|
|
@@ -2943,6 +2958,9 @@ window.__ModuleLoader__.load({
|
|
|
2943
2958
|
text,
|
|
2944
2959
|
typing
|
|
2945
2960
|
]);
|
|
2961
|
+
(0, react.useEffect)(() => {
|
|
2962
|
+
if (streaming) setTyping(true);
|
|
2963
|
+
}, [streaming]);
|
|
2946
2964
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FollowHost, {
|
|
2947
2965
|
active: live && ownFollow,
|
|
2948
2966
|
speedCpsRef,
|
|
@@ -2972,6 +2990,50 @@ window.__ModuleLoader__.load({
|
|
|
2972
2990
|
}
|
|
2973
2991
|
};
|
|
2974
2992
|
}
|
|
2993
|
+
/**
|
|
2994
|
+
* Apply searchable hidden state without unmounting a stable subtree — the
|
|
2995
|
+
* Host's completion fold hides the answer-inline reasoning this way, so the
|
|
2996
|
+
* takeover renderer must reproduce it to stay inside the contract: the row
|
|
2997
|
+
* disappears into the Host's process summary and comes back on find-in-page.
|
|
2998
|
+
* (Mirrors the Harness chat kit's `useSearchableHidden`.)
|
|
2999
|
+
*/
|
|
3000
|
+
function useSearchableHidden(hidden, reveal) {
|
|
3001
|
+
const ref = (0, react.useRef)(null);
|
|
3002
|
+
(0, react.useLayoutEffect)(() => {
|
|
3003
|
+
const element = ref.current;
|
|
3004
|
+
if (element === null) return;
|
|
3005
|
+
if (hidden && element.contains(element.ownerDocument.activeElement)) {
|
|
3006
|
+
reveal();
|
|
3007
|
+
return;
|
|
3008
|
+
}
|
|
3009
|
+
if (hidden) element.setAttribute("hidden", "until-found");
|
|
3010
|
+
else element.removeAttribute("hidden");
|
|
3011
|
+
}, [hidden, reveal]);
|
|
3012
|
+
(0, react.useEffect)(() => {
|
|
3013
|
+
const element = ref.current;
|
|
3014
|
+
if (element === null) return;
|
|
3015
|
+
element.addEventListener("beforematch", reveal);
|
|
3016
|
+
return () => {
|
|
3017
|
+
element.removeEventListener("beforematch", reveal);
|
|
3018
|
+
};
|
|
3019
|
+
}, [reveal]);
|
|
3020
|
+
return ref;
|
|
3021
|
+
}
|
|
3022
|
+
/**
|
|
3023
|
+
* One answer-inline reasoning block wrapped in the Host's fold contract. The
|
|
3024
|
+
* Host computes the fold decision (turn closed, compact transcript, this node
|
|
3025
|
+
* is the answer) and delivers it through the `turnProcess` owner prop; when
|
|
3026
|
+
* folded the block hides into the Host's "thought" summary row instead of
|
|
3027
|
+
* staying mounted above the answer.
|
|
3028
|
+
*/
|
|
3029
|
+
function FoldableReasoning({ hidden, reveal, children }) {
|
|
3030
|
+
const ref = useSearchableHidden(hidden, reveal);
|
|
3031
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3032
|
+
ref,
|
|
3033
|
+
"data-turn-process-inline": hidden || void 0,
|
|
3034
|
+
children
|
|
3035
|
+
});
|
|
3036
|
+
}
|
|
2975
3037
|
function firstLine(text) {
|
|
2976
3038
|
const newline = text.indexOf("\n");
|
|
2977
3039
|
return newline === -1 ? text : text.slice(0, newline);
|
|
@@ -2990,8 +3052,8 @@ window.__ModuleLoader__.load({
|
|
|
2990
3052
|
* or the assistant node settling — not when the rest of the reply is
|
|
2991
3053
|
* still streaming.
|
|
2992
3054
|
*/
|
|
2993
|
-
function AnimatedReasoning({ text, running, preset, thinkAutoExpand, shouldHoldBack, followSpeedCpsRef, followRevealScaleRef, t }) {
|
|
2994
|
-
const reduced =
|
|
3055
|
+
function AnimatedReasoning({ text, running, preset, thinkAutoExpand, motionReduced, shouldHoldBack, followSpeedCpsRef, followRevealScaleRef, t }) {
|
|
3056
|
+
const reduced = motionReduced;
|
|
2995
3057
|
const [expanded, setExpanded] = (0, react.useState)(running && thinkAutoExpand);
|
|
2996
3058
|
const [autoClosed, setAutoClosed] = (0, react.useState)(false);
|
|
2997
3059
|
const summaryRef = (0, react.useRef)(null);
|
|
@@ -3070,10 +3132,14 @@ window.__ModuleLoader__.load({
|
|
|
3070
3132
|
* holds offscreen reveals when the frame rate is degraded. Settled text
|
|
3071
3133
|
* renders with the full Markdown pipeline.
|
|
3072
3134
|
*/
|
|
3073
|
-
const TypewriterAssistantNodeView = (0, react.memo)(function TypewriterAssistantNodeView({ mode: _mode = DEFAULT_STREAM_CONFIG.mode, preset = DEFAULT_STREAM_CONFIG.preset, revealCharsPerSec: _revealCharsPerSec = DEFAULT_STREAM_CONFIG.revealCharsPerSec, scrollSpeedPxPerSec: _scrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.scrollSpeedPxPerSec, maxScrollSpeedPxPerSec: _maxScrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.maxScrollSpeedPxPerSec, thinkAutoExpand = DEFAULT_STREAM_SETTINGS.thinkAutoExpand, controlScroll = true, node, useTurnData, openFile, loadImage, fileMentions, t }) {
|
|
3135
|
+
const TypewriterAssistantNodeView = (0, react.memo)(function TypewriterAssistantNodeView({ mode: _mode = DEFAULT_STREAM_CONFIG.mode, preset = DEFAULT_STREAM_CONFIG.preset, revealCharsPerSec: _revealCharsPerSec = DEFAULT_STREAM_CONFIG.revealCharsPerSec, scrollSpeedPxPerSec: _scrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.scrollSpeedPxPerSec, maxScrollSpeedPxPerSec: _maxScrollSpeedPxPerSec = DEFAULT_STREAM_CONFIG.maxScrollSpeedPxPerSec, thinkAutoExpand = DEFAULT_STREAM_SETTINGS.thinkAutoExpand, controlScroll = true, motionPreference = DEFAULT_STREAM_SETTINGS.motionPreference, node, useTurnData, openFile, loadImage, fileMentions, turnProcess, t }) {
|
|
3074
3136
|
const data = node.data;
|
|
3075
3137
|
const streaming = data.status === "running";
|
|
3076
|
-
const reduced =
|
|
3138
|
+
const reduced = useMotionReduced(motionPreference);
|
|
3139
|
+
const reasoningHidden = turnProcess !== void 0 && turnProcess.foldable && turnProcess.spec.answerStep === data.step && turnProcess.spec.inlineReasoning && !turnProcess.open;
|
|
3140
|
+
const revealProcess = (0, react.useCallback)(() => {
|
|
3141
|
+
turnProcess?.setOpen(true);
|
|
3142
|
+
}, [turnProcess]);
|
|
3077
3143
|
const { ref: guardRef, shouldHoldBack } = useFpsGuard(streaming);
|
|
3078
3144
|
const rootSpeedRef = (0, react.useRef)(35);
|
|
3079
3145
|
const rootRevealedCharsRef = (0, react.useRef)(0);
|
|
@@ -3136,6 +3202,7 @@ window.__ModuleLoader__.load({
|
|
|
3136
3202
|
labels: markdownLabels,
|
|
3137
3203
|
fileMentions: mentions,
|
|
3138
3204
|
streaming,
|
|
3205
|
+
motionReduced: reduced,
|
|
3139
3206
|
ownFollow: !streaming && index === lastFollow,
|
|
3140
3207
|
followSpeedCpsRef: index === lastFollow ? rootSpeedRef : void 0,
|
|
3141
3208
|
followRevealedCharsRef: index === lastFollow ? rootRevealedCharsRef : void 0,
|
|
@@ -3147,15 +3214,20 @@ window.__ModuleLoader__.load({
|
|
|
3147
3214
|
}, index));
|
|
3148
3215
|
break;
|
|
3149
3216
|
case "reasoning":
|
|
3150
|
-
rendered.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3217
|
+
rendered.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FoldableReasoning, {
|
|
3218
|
+
hidden: reasoningHidden,
|
|
3219
|
+
reveal: revealProcess,
|
|
3220
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AnimatedReasoning, {
|
|
3221
|
+
text: block.text,
|
|
3222
|
+
running: streaming && index === last,
|
|
3223
|
+
preset,
|
|
3224
|
+
thinkAutoExpand,
|
|
3225
|
+
motionReduced: reduced,
|
|
3226
|
+
shouldHoldBack,
|
|
3227
|
+
followSpeedCpsRef: reasoningOwnsSpeed && index === last ? rootSpeedRef : void 0,
|
|
3228
|
+
followRevealScaleRef: reasoningOwnsSpeed && index === last ? rootRevealScaleRef : void 0,
|
|
3229
|
+
t
|
|
3230
|
+
})
|
|
3159
3231
|
}, index));
|
|
3160
3232
|
break;
|
|
3161
3233
|
case "image": {
|
|
@@ -3482,8 +3554,8 @@ window.__ModuleLoader__.load({
|
|
|
3482
3554
|
tag.textContent = css$2;
|
|
3483
3555
|
}
|
|
3484
3556
|
var AgentRowEntrance_module_css_default = {
|
|
3485
|
-
"
|
|
3486
|
-
"
|
|
3557
|
+
"dsh-smooth-stream-agent-row-in": "_7P9_Ta_dsh-smooth-stream-agent-row-in",
|
|
3558
|
+
"surface": "_7P9_Ta_surface"
|
|
3487
3559
|
};
|
|
3488
3560
|
//#endregion
|
|
3489
3561
|
//#region src/client/TypewriterToolNodeView.tsx
|
|
@@ -3662,7 +3734,7 @@ window.__ModuleLoader__.load({
|
|
|
3662
3734
|
}
|
|
3663
3735
|
//#endregion
|
|
3664
3736
|
//#region \0dsh-css:/Users/dzlin/work/project/dsh-smooth-stream/src/client/SmoothStreamCard.module.css.mjs
|
|
3665
|
-
const css$1 = ".XNGeRG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;list-style:none;transition:border-color .16s,background .16s;display:flex}.XNGeRG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.XNGeRG_cardOpen{border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-bg-layer-2)}.XNGeRG_header{appearance:none;cursor:pointer;text-align:left;width:100%;font:inherit;color:inherit;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.XNGeRG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.XNGeRG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.XNGeRG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.XNGeRG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.XNGeRG_version{text-overflow:ellipsis;white-space:nowrap;max-width:16rem;color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:1.5;overflow:hidden}.XNGeRG_pending{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.XNGeRG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.XNGeRG_chevronOpen{transform:rotate(180deg)}.XNGeRG_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;margin:0 16px;padding-bottom:8px;display:flex}.XNGeRG_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.XNGeRG_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.XNGeRG_field+.XNGeRG_field{border-top:1px solid var(--dsw-alias-border-l2)}.XNGeRG_fieldDisabled{opacity:.5}.XNGeRG_fieldHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.XNGeRG_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.XNGeRG_toggle{width:16px;height:16px;accent-color:var(--dsw-alias-brand-primary);cursor:pointer}.XNGeRG_toggle:disabled{cursor:default}.XNGeRG_toggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.XNGeRG_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.XNGeRG_failure{justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}.XNGeRG_updateRow{border-top:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}.XNGeRG_updateCopy{flex-direction:column;gap:4px;min-width:0;display:flex}.XNGeRG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.XNGeRG_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.XNGeRG_save,.XNGeRG_discard,.XNGeRG_update{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.XNGeRG_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.XNGeRG_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.XNGeRG_discard:hover:not(:disabled),.XNGeRG_update:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}.XNGeRG_update{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0;flex:none;align-items:center;gap:6px;display:inline-flex}.XNGeRG_discard:disabled,.XNGeRG_save:disabled,.XNGeRG_update:disabled{opacity:.4;cursor:default}.XNGeRG_discard:focus-visible,.XNGeRG_save:focus-visible,.XNGeRG_update:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}";
|
|
3737
|
+
const css$1 = ".XNGeRG_card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;flex-direction:column;list-style:none;transition:border-color .16s,background .16s;display:flex}.XNGeRG_card:hover{border-color:var(--dsw-alias-label-dimmed)}.XNGeRG_cardOpen{border-color:var(--dsw-alias-label-dimmed);background:var(--dsw-alias-bg-layer-2)}.XNGeRG_header{appearance:none;cursor:pointer;text-align:left;width:100%;font:inherit;color:inherit;background:0 0;border:0;border-radius:12px;align-items:center;gap:12px;padding:14px 16px;display:flex}.XNGeRG_header:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:-2px}.XNGeRG_headText{flex-direction:column;flex:1;gap:4px;min-width:0;display:flex}.XNGeRG_name{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}.XNGeRG_description{color:var(--dsw-alias-label-tertiary);font-size:13px;line-height:1.5}.XNGeRG_version{text-overflow:ellipsis;white-space:nowrap;max-width:16rem;color:var(--dsw-alias-label-tertiary);flex:none;font-size:12px;line-height:1.5;overflow:hidden}.XNGeRG_pending{background:var(--dsw-alias-bg-module-platform);color:var(--dsw-alias-label-secondary);white-space:nowrap;border-radius:999px;flex:none;padding:1px 8px;font-size:11px;font-weight:500;line-height:17px}.XNGeRG_chevron{color:var(--dsw-alias-label-tertiary);flex:none;transition:transform .16s}.XNGeRG_chevronOpen{transform:rotate(180deg)}.XNGeRG_body{border-top:1px solid var(--dsw-alias-border-l2);flex-direction:column;margin:0 16px;padding-bottom:8px;display:flex}.XNGeRG_readOnly{color:var(--dsw-alias-label-tertiary);margin:12px 0 0;font-size:12px;line-height:1.5}.XNGeRG_field{flex-direction:column;gap:6px;padding:12px 0;display:flex}.XNGeRG_field+.XNGeRG_field{border-top:1px solid var(--dsw-alias-border-l2)}.XNGeRG_fieldDisabled{opacity:.5}.XNGeRG_fieldHead{justify-content:space-between;align-items:center;gap:8px;display:flex}.XNGeRG_label{min-width:0;color:var(--dsw-alias-label-primary);flex:1;font-size:13px;font-weight:500;line-height:1.5}.XNGeRG_toggle{width:16px;height:16px;accent-color:var(--dsw-alias-brand-primary);cursor:pointer}.XNGeRG_toggle:disabled{cursor:default}.XNGeRG_toggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.XNGeRG_choiceRow{flex-wrap:wrap;gap:6px 14px;margin:2px 0 0;padding:0;display:flex}.XNGeRG_choice{color:var(--dsw-alias-label-secondary);cursor:pointer;align-items:center;gap:5px;font-size:12px;line-height:1.5;display:flex}.XNGeRG_choiceInput{width:14px;height:14px;accent-color:var(--dsw-alias-brand-primary);cursor:pointer}.XNGeRG_choice:has(.XNGeRG_choiceInput:disabled){cursor:default;opacity:.55}.XNGeRG_choiceInput:disabled{cursor:default}.XNGeRG_hint{color:var(--dsw-alias-label-tertiary);margin:0;font-size:12px;line-height:1.5}.XNGeRG_failure{justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}.XNGeRG_updateRow{border-top:1px solid var(--dsw-alias-border-l2);justify-content:space-between;align-items:center;gap:12px;padding:12px 0;display:flex}.XNGeRG_updateCopy{flex-direction:column;gap:4px;min-width:0;display:flex}.XNGeRG_footer{border-top:1px solid var(--dsw-alias-border-l2);justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px;display:flex}.XNGeRG_failed{min-width:0;color:var(--dsw-alias-label-error);flex:1;margin:0;font-size:12px;line-height:1.5}.XNGeRG_save,.XNGeRG_discard,.XNGeRG_update{appearance:none;font:inherit;cursor:pointer;border:1px solid #0000;border-radius:8px;padding:5px 14px;font-size:13px;line-height:1.5}.XNGeRG_save{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3)}.XNGeRG_discard{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0}.XNGeRG_discard:hover:not(:disabled),.XNGeRG_update:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}.XNGeRG_update{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:0 0;flex:none;align-items:center;gap:6px;display:inline-flex}.XNGeRG_discard:disabled,.XNGeRG_save:disabled,.XNGeRG_update:disabled{opacity:.4;cursor:default}.XNGeRG_discard:focus-visible,.XNGeRG_save:focus-visible,.XNGeRG_update:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:1px}";
|
|
3666
3738
|
const tagId$1 = "dsh-smooth-stream/SmoothStreamCard.module.css";
|
|
3667
3739
|
if (typeof document !== "undefined") {
|
|
3668
3740
|
let tag = document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]");
|
|
@@ -3675,32 +3747,35 @@ window.__ModuleLoader__.load({
|
|
|
3675
3747
|
tag.textContent = css$1;
|
|
3676
3748
|
}
|
|
3677
3749
|
var SmoothStreamCard_module_css_default = {
|
|
3678
|
-
"
|
|
3679
|
-
"
|
|
3680
|
-
"
|
|
3681
|
-
"
|
|
3682
|
-
"
|
|
3750
|
+
"body": "XNGeRG_body",
|
|
3751
|
+
"fieldDisabled": "XNGeRG_fieldDisabled",
|
|
3752
|
+
"readOnly": "XNGeRG_readOnly",
|
|
3753
|
+
"field": "XNGeRG_field",
|
|
3754
|
+
"choiceInput": "XNGeRG_choiceInput",
|
|
3683
3755
|
"headText": "XNGeRG_headText",
|
|
3684
|
-
"
|
|
3756
|
+
"version": "XNGeRG_version",
|
|
3757
|
+
"choice": "XNGeRG_choice",
|
|
3685
3758
|
"description": "XNGeRG_description",
|
|
3686
|
-
"
|
|
3687
|
-
"save": "XNGeRG_save",
|
|
3688
|
-
"cardOpen": "XNGeRG_cardOpen",
|
|
3689
|
-
"failed": "XNGeRG_failed",
|
|
3759
|
+
"pending": "XNGeRG_pending",
|
|
3690
3760
|
"fieldHead": "XNGeRG_fieldHead",
|
|
3761
|
+
"label": "XNGeRG_label",
|
|
3691
3762
|
"toggle": "XNGeRG_toggle",
|
|
3692
|
-
"chevron": "XNGeRG_chevron",
|
|
3693
3763
|
"hint": "XNGeRG_hint",
|
|
3764
|
+
"save": "XNGeRG_save",
|
|
3765
|
+
"updateRow": "XNGeRG_updateRow",
|
|
3766
|
+
"chevron": "XNGeRG_chevron",
|
|
3767
|
+
"cardOpen": "XNGeRG_cardOpen",
|
|
3694
3768
|
"card": "XNGeRG_card",
|
|
3695
3769
|
"header": "XNGeRG_header",
|
|
3696
|
-
"pending": "XNGeRG_pending",
|
|
3697
|
-
"chevronOpen": "XNGeRG_chevronOpen",
|
|
3698
|
-
"readOnly": "XNGeRG_readOnly",
|
|
3699
|
-
"field": "XNGeRG_field",
|
|
3700
|
-
"version": "XNGeRG_version",
|
|
3701
3770
|
"failure": "XNGeRG_failure",
|
|
3702
|
-
"
|
|
3703
|
-
"
|
|
3771
|
+
"failed": "XNGeRG_failed",
|
|
3772
|
+
"chevronOpen": "XNGeRG_chevronOpen",
|
|
3773
|
+
"discard": "XNGeRG_discard",
|
|
3774
|
+
"updateCopy": "XNGeRG_updateCopy",
|
|
3775
|
+
"update": "XNGeRG_update",
|
|
3776
|
+
"footer": "XNGeRG_footer",
|
|
3777
|
+
"name": "XNGeRG_name",
|
|
3778
|
+
"choiceRow": "XNGeRG_choiceRow"
|
|
3704
3779
|
};
|
|
3705
3780
|
//#endregion
|
|
3706
3781
|
//#region src/client/SmoothStreamCard.tsx
|
|
@@ -3816,6 +3891,57 @@ window.__ModuleLoader__.load({
|
|
|
3816
3891
|
children: t("controlScrollHint")
|
|
3817
3892
|
})]
|
|
3818
3893
|
}),
|
|
3894
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3895
|
+
className: state.enabled ? SmoothStreamCard_module_css_default.field : `${SmoothStreamCard_module_css_default.field} ${SmoothStreamCard_module_css_default.fieldDisabled}`,
|
|
3896
|
+
children: [
|
|
3897
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3898
|
+
className: SmoothStreamCard_module_css_default.fieldHead,
|
|
3899
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3900
|
+
className: SmoothStreamCard_module_css_default.label,
|
|
3901
|
+
children: t("motionPreference")
|
|
3902
|
+
})
|
|
3903
|
+
}),
|
|
3904
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3905
|
+
className: SmoothStreamCard_module_css_default.hint,
|
|
3906
|
+
children: t("motionPreferenceHint")
|
|
3907
|
+
}),
|
|
3908
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3909
|
+
className: SmoothStreamCard_module_css_default.choiceRow,
|
|
3910
|
+
role: "radiogroup",
|
|
3911
|
+
"aria-label": t("motionPreference"),
|
|
3912
|
+
children: [
|
|
3913
|
+
[
|
|
3914
|
+
"auto",
|
|
3915
|
+
"motionAuto",
|
|
3916
|
+
"motionAutoHint"
|
|
3917
|
+
],
|
|
3918
|
+
[
|
|
3919
|
+
"force-smooth",
|
|
3920
|
+
"motionForceSmooth",
|
|
3921
|
+
"motionForceSmoothHint"
|
|
3922
|
+
],
|
|
3923
|
+
[
|
|
3924
|
+
"force-reduced",
|
|
3925
|
+
"motionForceReduced",
|
|
3926
|
+
"motionForceReducedHint"
|
|
3927
|
+
]
|
|
3928
|
+
].map(([value, label, hint]) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3929
|
+
className: SmoothStreamCard_module_css_default.choice,
|
|
3930
|
+
title: t(hint),
|
|
3931
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3932
|
+
type: "radio",
|
|
3933
|
+
className: SmoothStreamCard_module_css_default.choiceInput,
|
|
3934
|
+
name: "smooth-stream-motion",
|
|
3935
|
+
checked: state.motionPreference === value,
|
|
3936
|
+
disabled: !state.writable || state.saving || !state.enabled,
|
|
3937
|
+
onChange: () => {
|
|
3938
|
+
props.edit({ motionPreference: value });
|
|
3939
|
+
}
|
|
3940
|
+
}), t(label)]
|
|
3941
|
+
}, value))
|
|
3942
|
+
})
|
|
3943
|
+
]
|
|
3944
|
+
}),
|
|
3819
3945
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3820
3946
|
className: state.enabled ? SmoothStreamCard_module_css_default.field : `${SmoothStreamCard_module_css_default.field} ${SmoothStreamCard_module_css_default.fieldDisabled}`,
|
|
3821
3947
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
@@ -3958,10 +4084,11 @@ window.__ModuleLoader__.load({
|
|
|
3958
4084
|
hooks: { smoothStreamCard: this.store },
|
|
3959
4085
|
edit: (patch) => {
|
|
3960
4086
|
if (this.saving) return;
|
|
3961
|
-
if (patch.enabled !== void 0 || patch.controlScroll !== void 0 || patch.thinkAutoExpand !== void 0) this.stagedBase = {
|
|
4087
|
+
if (patch.enabled !== void 0 || patch.controlScroll !== void 0 || patch.motionPreference !== void 0 || patch.thinkAutoExpand !== void 0) this.stagedBase = {
|
|
3962
4088
|
...this.baseValues(),
|
|
3963
4089
|
...patch.enabled === void 0 ? {} : { enabled: patch.enabled },
|
|
3964
4090
|
...patch.controlScroll === void 0 ? {} : { controlScroll: patch.controlScroll },
|
|
4091
|
+
...patch.motionPreference === void 0 ? {} : { motionPreference: patch.motionPreference },
|
|
3965
4092
|
...patch.thinkAutoExpand === void 0 ? {} : { thinkAutoExpand: patch.thinkAutoExpand }
|
|
3966
4093
|
};
|
|
3967
4094
|
if (this.loadedDebug !== void 0 && (patch.debugEnabled !== void 0 || patch.debugTuning !== void 0)) this.stagedDebug = {
|
|
@@ -4015,6 +4142,7 @@ window.__ModuleLoader__.load({
|
|
|
4015
4142
|
return this.stagedBase ?? {
|
|
4016
4143
|
enabled: this.loaded?.enabled ?? DEFAULT_STREAM_SETTINGS.enabled,
|
|
4017
4144
|
controlScroll: this.loaded?.controlScroll ?? DEFAULT_STREAM_SETTINGS.controlScroll,
|
|
4145
|
+
motionPreference: this.loaded?.motionPreference ?? DEFAULT_STREAM_SETTINGS.motionPreference,
|
|
4018
4146
|
thinkAutoExpand: this.loaded?.thinkAutoExpand ?? DEFAULT_STREAM_SETTINGS.thinkAutoExpand
|
|
4019
4147
|
};
|
|
4020
4148
|
}
|
|
@@ -4135,7 +4263,11 @@ window.__ModuleLoader__.load({
|
|
|
4135
4263
|
"npm",
|
|
4136
4264
|
"development",
|
|
4137
4265
|
"unmanaged"
|
|
4138
|
-
].includes(data.installation) || typeof data.writable !== "boolean" || typeof data.enabled !== "boolean" || typeof data.controlScroll !== "boolean" ||
|
|
4266
|
+
].includes(data.installation) || typeof data.writable !== "boolean" || typeof data.enabled !== "boolean" || typeof data.controlScroll !== "boolean" || ![
|
|
4267
|
+
"auto",
|
|
4268
|
+
"force-smooth",
|
|
4269
|
+
"force-reduced"
|
|
4270
|
+
].includes(data.motionPreference) || typeof data.thinkAutoExpand !== "boolean" || typeof data.canUpgrade !== "boolean") throw new Error("dsh-smooth-stream: malformed settings response");
|
|
4139
4271
|
return data;
|
|
4140
4272
|
}
|
|
4141
4273
|
function upgradeView(value) {
|
|
@@ -4165,6 +4297,7 @@ window.__ModuleLoader__.load({
|
|
|
4165
4297
|
return settingsView(accepted(await connection.rpc.call(STREAM_SETTINGS_RPC_CHANNEL, STREAM_SETTINGS_RPC.write, {
|
|
4166
4298
|
enabled: settings.enabled,
|
|
4167
4299
|
controlScroll: settings.controlScroll,
|
|
4300
|
+
motionPreference: settings.motionPreference,
|
|
4168
4301
|
thinkAutoExpand: settings.thinkAutoExpand,
|
|
4169
4302
|
...settings.debugEnabled === void 0 || settings.debugTuning === void 0 ? {} : {
|
|
4170
4303
|
debugEnabled: settings.debugEnabled,
|
|
@@ -4201,34 +4334,34 @@ window.__ModuleLoader__.load({
|
|
|
4201
4334
|
tag.textContent = css;
|
|
4202
4335
|
}
|
|
4203
4336
|
var DebugPanel_module_css_default = {
|
|
4204
|
-
"
|
|
4205
|
-
"trigger": "m4_tdG_trigger",
|
|
4206
|
-
"panel": "m4_tdG_panel",
|
|
4207
|
-
"statusLive": "m4_tdG_statusLive",
|
|
4208
|
-
"guide": "m4_tdG_guide",
|
|
4337
|
+
"iconButton": "m4_tdG_iconButton",
|
|
4209
4338
|
"triggerActive": "m4_tdG_triggerActive",
|
|
4210
|
-
"secondaryButton": "m4_tdG_secondaryButton",
|
|
4211
|
-
"number": "m4_tdG_number",
|
|
4212
|
-
"title": "m4_tdG_title",
|
|
4213
4339
|
"controlHead": "m4_tdG_controlHead",
|
|
4214
|
-
"
|
|
4215
|
-
"visuallyHidden": "m4_tdG_visuallyHidden",
|
|
4216
|
-
"panelHeader": "m4_tdG_panelHeader",
|
|
4217
|
-
"section": "m4_tdG_section",
|
|
4340
|
+
"number": "m4_tdG_number",
|
|
4218
4341
|
"range": "m4_tdG_range",
|
|
4219
|
-
"
|
|
4220
|
-
"
|
|
4221
|
-
"
|
|
4342
|
+
"statusLive": "m4_tdG_statusLive",
|
|
4343
|
+
"title": "m4_tdG_title",
|
|
4344
|
+
"controlLabel": "m4_tdG_controlLabel",
|
|
4345
|
+
"guide": "m4_tdG_guide",
|
|
4346
|
+
"infoButton": "m4_tdG_infoButton",
|
|
4222
4347
|
"numberWrap": "m4_tdG_numberWrap",
|
|
4348
|
+
"footer": "m4_tdG_footer",
|
|
4349
|
+
"control": "m4_tdG_control",
|
|
4350
|
+
"secondaryButton": "m4_tdG_secondaryButton",
|
|
4351
|
+
"unsaved": "m4_tdG_unsaved",
|
|
4223
4352
|
"metrics": "m4_tdG_metrics",
|
|
4224
|
-
"
|
|
4353
|
+
"scrollArea": "m4_tdG_scrollArea",
|
|
4354
|
+
"state": "m4_tdG_state",
|
|
4355
|
+
"metric": "m4_tdG_metric",
|
|
4356
|
+
"panel": "m4_tdG_panel",
|
|
4357
|
+
"trigger": "m4_tdG_trigger",
|
|
4225
4358
|
"statusDot": "m4_tdG_statusDot",
|
|
4226
|
-
"
|
|
4227
|
-
"
|
|
4228
|
-
"
|
|
4229
|
-
"
|
|
4359
|
+
"section": "m4_tdG_section",
|
|
4360
|
+
"unit": "m4_tdG_unit",
|
|
4361
|
+
"footerSpacer": "m4_tdG_footerSpacer",
|
|
4362
|
+
"visuallyHidden": "m4_tdG_visuallyHidden",
|
|
4230
4363
|
"primaryButton": "m4_tdG_primaryButton",
|
|
4231
|
-
"
|
|
4364
|
+
"panelHeader": "m4_tdG_panelHeader"
|
|
4232
4365
|
};
|
|
4233
4366
|
//#endregion
|
|
4234
4367
|
//#region src/client/DebugPanel.tsx
|
|
@@ -4626,6 +4759,14 @@ window.__ModuleLoader__.load({
|
|
|
4626
4759
|
enabledHint: "Let this plugin render and follow streaming replies. Turn off to use the built-in Harness renderer.",
|
|
4627
4760
|
controlScroll: "Take over scrolling",
|
|
4628
4761
|
controlScrollHint: "On by default; smooth-stream writes the conversation scroll position. Turn off to leave bottom-follow to Harness.",
|
|
4762
|
+
motionPreference: "Motion",
|
|
4763
|
+
motionPreferenceHint: "How streaming responds to the system reduce-motion setting.",
|
|
4764
|
+
motionAuto: "Follow system",
|
|
4765
|
+
motionAutoHint: "Reduced-motion systems get raw text (accessibility first).",
|
|
4766
|
+
motionForceSmooth: "Always smooth",
|
|
4767
|
+
motionForceSmoothHint: "Keep the smoothing engine even when the system asks for reduced motion.",
|
|
4768
|
+
motionForceReduced: "Always raw",
|
|
4769
|
+
motionForceReducedHint: "Render raw text even when the system allows motion.",
|
|
4629
4770
|
thinkAutoExpand: "Auto-expand thinking",
|
|
4630
4771
|
thinkAutoExpandHint: "Open the thinking block while it streams. Turn off to keep it collapsed.",
|
|
4631
4772
|
debugEnabled: "Show render diagnostics",
|
|
@@ -4705,6 +4846,14 @@ window.__ModuleLoader__.load({
|
|
|
4705
4846
|
enabledHint: "由本插件渲染并跟随流式回复;关闭后使用 Harness 内置渲染。",
|
|
4706
4847
|
controlScroll: "接管滚动",
|
|
4707
4848
|
controlScrollHint: "默认开启,由丝滑流式写入会话滚动位置;关闭后贴底滚动交给 Harness。",
|
|
4849
|
+
motionPreference: "动效偏好",
|
|
4850
|
+
motionPreferenceHint: "流式渲染如何响应系统的「减少动态效果」设置。",
|
|
4851
|
+
motionAuto: "跟随系统",
|
|
4852
|
+
motionAutoHint: "系统开启减少动态效果时直接呈现原始文本(优先无障碍)。",
|
|
4853
|
+
motionForceSmooth: "始终平滑",
|
|
4854
|
+
motionForceSmoothHint: "即使系统要求减少动态效果,仍保持平滑流式渲染。",
|
|
4855
|
+
motionForceReduced: "始终原始",
|
|
4856
|
+
motionForceReducedHint: "即使系统允许动效,也直接呈现原始文本。",
|
|
4708
4857
|
thinkAutoExpand: "自动展开思考",
|
|
4709
4858
|
thinkAutoExpandHint: "思考块在流式时自动展开;关闭后保持折叠,可手动展开。",
|
|
4710
4859
|
debugEnabled: "显示渲染调试面板",
|
|
@@ -4899,7 +5048,7 @@ window.__ModuleLoader__.load({
|
|
|
4899
5048
|
refresh() {
|
|
4900
5049
|
const next = this.read();
|
|
4901
5050
|
const pending = this.card?.getSnapshot().status === "loading";
|
|
4902
|
-
if (pending === this.pending && next.enabled === this.value.enabled && next.controlScroll === this.value.controlScroll && next.thinkAutoExpand === this.value.thinkAutoExpand && next.debugEnabled === this.value.debugEnabled && next.debugTuning === this.value.debugTuning) return;
|
|
5051
|
+
if (pending === this.pending && next.enabled === this.value.enabled && next.controlScroll === this.value.controlScroll && next.motionPreference === this.value.motionPreference && next.thinkAutoExpand === this.value.thinkAutoExpand && next.debugEnabled === this.value.debugEnabled && next.debugTuning === this.value.debugTuning) return;
|
|
4903
5052
|
this.pending = pending;
|
|
4904
5053
|
this.value = next;
|
|
4905
5054
|
for (const listener of this.listeners) listener();
|
|
@@ -4999,7 +5148,8 @@ window.__ModuleLoader__.load({
|
|
|
4999
5148
|
scrollSpeedPxPerSec: config.scrollSpeedPxPerSec,
|
|
5000
5149
|
maxScrollSpeedPxPerSec: config.maxScrollSpeedPxPerSec,
|
|
5001
5150
|
thinkAutoExpand: preferences.thinkAutoExpand,
|
|
5002
|
-
controlScroll: preferences.controlScroll
|
|
5151
|
+
controlScroll: preferences.controlScroll,
|
|
5152
|
+
motionPreference: preferences.motionPreference
|
|
5003
5153
|
});
|
|
5004
5154
|
};
|
|
5005
5155
|
ctx.slots.inject("conversation.chat.node", () => {
|