dsh-smooth-stream 0.4.3 → 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/README.en.md +13 -0
- package/README.md +13 -0
- package/lib/client.js +962 -1051
- package/lib/client.js.map +1 -1
- package/lib/index.js +22 -6
- package/package.json +11 -5
- package/src/client/AgentRowEntrance.module.css +43 -0
- package/src/client/FollowHost.tsx +18 -1
- package/src/client/SmoothStreamCard.module.css +34 -0
- package/src/client/SmoothStreamCard.tsx +39 -10
- package/src/client/TypewriterAssistantNodeView.tsx +130 -21
- package/src/client/TypewriterToolNodeView.tsx +9 -1
- package/src/client/clientStore.ts +71 -12
- package/src/client/index.ts +15 -29
- package/src/client/locales.ts +25 -5
- package/src/client/smooth-stream-card-controller.ts +10 -6
- package/src/client/smooth-stream-settings-api.ts +6 -4
- package/src/client/teleprompterGlide.ts +1021 -75
- package/src/client/turn-process-face.d.ts +27 -0
- package/src/plugin.ts +30 -6
- package/src/settings-api.ts +4 -2
- package/src/settings.ts +26 -8
- package/src/client/auto-collapse-controller.ts +0 -1072
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turn-process fold face for the DSH 0.1.2 completion-collapse contract.
|
|
3
|
+
*
|
|
4
|
+
* The Host seat hands every keyed Chat renderer a `turnProcess` owner prop
|
|
5
|
+
* when the node belongs to a projected Turn: the fold decision lives in the
|
|
6
|
+
* conversation snapshot (turn closed + compact transcript), and the renderer
|
|
7
|
+
* is expected to hide its answer-inline reasoning while folded. The pinned
|
|
8
|
+
* type-only dependency predates the field, so the face is declared here and
|
|
9
|
+
* merged into the owner-props interface; erases at compile time.
|
|
10
|
+
*/
|
|
11
|
+
export interface TurnProcessOwnerFace {
|
|
12
|
+
/** Answer anchor of the projection; null while the answer has not landed. */
|
|
13
|
+
readonly spec: { readonly answerStep: number | null, readonly inlineReasoning: boolean }
|
|
14
|
+
/** Whether this node's process content may fold (turn closed + compact mode). */
|
|
15
|
+
readonly foldable: boolean
|
|
16
|
+
/** Current fold state, persisted by the Host across sessions. */
|
|
17
|
+
readonly open: boolean
|
|
18
|
+
/** Fold or unfold from the renderer side (summary click, find-in-page reveal). */
|
|
19
|
+
setOpen(open: boolean): void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare module '@deepseek-ai/dsh-client-ui-conversation/client' {
|
|
23
|
+
interface ChatNodeOwnerProps {
|
|
24
|
+
/** Present only when the node belongs to a projected Turn (0.1.2+). */
|
|
25
|
+
turnProcess?: TurnProcessOwnerFace | undefined
|
|
26
|
+
}
|
|
27
|
+
}
|
package/src/plugin.ts
CHANGED
|
@@ -55,8 +55,13 @@ export const Config: Schema<Config> = Schema.object({
|
|
|
55
55
|
*/
|
|
56
56
|
export const StreamSettingsSchema: Schema<StreamSettings> = Schema.object({
|
|
57
57
|
enabled: Schema.boolean().default(DEFAULT_STREAM_SETTINGS.enabled),
|
|
58
|
+
controlScroll: Schema.boolean().default(DEFAULT_STREAM_SETTINGS.controlScroll),
|
|
59
|
+
motionPreference: Schema.union([
|
|
60
|
+
Schema.const('auto'),
|
|
61
|
+
Schema.const('force-smooth'),
|
|
62
|
+
Schema.const('force-reduced'),
|
|
63
|
+
] as const).default(DEFAULT_STREAM_SETTINGS.motionPreference),
|
|
58
64
|
thinkAutoExpand: Schema.boolean().default(DEFAULT_STREAM_SETTINGS.thinkAutoExpand),
|
|
59
|
-
autoCollapse: Schema.boolean().default(DEFAULT_STREAM_SETTINGS.autoCollapse),
|
|
60
65
|
debugEnabled: Schema.boolean().default(DEFAULT_STREAM_SETTINGS.debugEnabled),
|
|
61
66
|
debugTuning: Schema.object({
|
|
62
67
|
revealScale: Schema.number().min(0.25).max(2).default(DEFAULT_STREAM_SETTINGS.debugTuning.revealScale),
|
|
@@ -117,8 +122,9 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
117
122
|
installation: installation.kind,
|
|
118
123
|
writable: connectionCtx.settings.writable,
|
|
119
124
|
enabled: settings.enabled,
|
|
125
|
+
controlScroll: settings.controlScroll,
|
|
126
|
+
motionPreference: settings.motionPreference,
|
|
120
127
|
thinkAutoExpand: settings.thinkAutoExpand,
|
|
121
|
-
autoCollapse: settings.autoCollapse,
|
|
122
128
|
canUpgrade: installation.kind === 'npm',
|
|
123
129
|
}
|
|
124
130
|
}
|
|
@@ -159,13 +165,14 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
159
165
|
if (endpoint === STREAM_SETTINGS_RPC.write) {
|
|
160
166
|
if (typeof payload !== 'object' || payload === null || Array.isArray(payload)
|
|
161
167
|
|| typeof (payload as { enabled?: unknown }).enabled !== 'boolean'
|
|
168
|
+
|| typeof (payload as { controlScroll?: unknown }).controlScroll !== 'boolean'
|
|
162
169
|
|| typeof (payload as { thinkAutoExpand?: unknown }).thinkAutoExpand !== 'boolean'
|
|
163
|
-
|
|
170
|
+
) {
|
|
164
171
|
return {
|
|
165
172
|
ok: false,
|
|
166
173
|
error: {
|
|
167
174
|
code: 'settings-rejected',
|
|
168
|
-
message: 'enabled,
|
|
175
|
+
message: 'enabled, controlScroll and thinkAutoExpand must be booleans',
|
|
169
176
|
details: { ns: STREAM_SETTINGS_NS },
|
|
170
177
|
},
|
|
171
178
|
}
|
|
@@ -183,11 +190,27 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
183
190
|
try {
|
|
184
191
|
const next = payload as {
|
|
185
192
|
enabled: boolean
|
|
193
|
+
controlScroll: boolean
|
|
194
|
+
motionPreference?: unknown
|
|
186
195
|
thinkAutoExpand: boolean
|
|
187
|
-
autoCollapse: boolean
|
|
188
196
|
debugEnabled?: unknown
|
|
189
197
|
debugTuning?: unknown
|
|
190
198
|
}
|
|
199
|
+
if (
|
|
200
|
+
next.motionPreference !== undefined
|
|
201
|
+
&& next.motionPreference !== 'auto'
|
|
202
|
+
&& next.motionPreference !== 'force-smooth'
|
|
203
|
+
&& next.motionPreference !== 'force-reduced'
|
|
204
|
+
) {
|
|
205
|
+
return {
|
|
206
|
+
ok: false,
|
|
207
|
+
error: {
|
|
208
|
+
code: 'settings-rejected',
|
|
209
|
+
message: 'motionPreference must be one of auto | force-smooth | force-reduced',
|
|
210
|
+
details: { ns: STREAM_SETTINGS_NS },
|
|
211
|
+
},
|
|
212
|
+
}
|
|
213
|
+
}
|
|
191
214
|
const hasDebug = next.debugEnabled !== undefined || next.debugTuning !== undefined
|
|
192
215
|
if (hasDebug && (typeof next.debugEnabled !== 'boolean' || !validDebugTuning(next.debugTuning))) {
|
|
193
216
|
return {
|
|
@@ -201,8 +224,9 @@ export function apply(ctx: Context, config: Config): void {
|
|
|
201
224
|
}
|
|
202
225
|
await scope.update({
|
|
203
226
|
enabled: next.enabled,
|
|
227
|
+
controlScroll: next.controlScroll,
|
|
228
|
+
...(next.motionPreference === undefined ? {} : { motionPreference: next.motionPreference }),
|
|
204
229
|
thinkAutoExpand: next.thinkAutoExpand,
|
|
205
|
-
autoCollapse: next.autoCollapse,
|
|
206
230
|
...(hasDebug ? { debugEnabled: next.debugEnabled, debugTuning: next.debugTuning } : {}),
|
|
207
231
|
})
|
|
208
232
|
} catch {
|
package/src/settings-api.ts
CHANGED
|
@@ -25,10 +25,12 @@ export interface StreamSettingsView {
|
|
|
25
25
|
writable: boolean
|
|
26
26
|
/** Whether smooth-stream currently owns conversation rendering. */
|
|
27
27
|
enabled: boolean
|
|
28
|
+
/** Whether smooth-stream also owns conversation bottom-follow. */
|
|
29
|
+
controlScroll: boolean
|
|
30
|
+
/** How the reveal honors the OS reduced-motion preference. */
|
|
31
|
+
motionPreference: import('./settings.ts').StreamMotionPreference
|
|
28
32
|
/** Current resolved preference. */
|
|
29
33
|
thinkAutoExpand: boolean
|
|
30
|
-
/** Whether finished turns fold their work process behind a summary row. */
|
|
31
|
-
autoCollapse: boolean
|
|
32
34
|
/** Whether a fixed npm update command is safe to offer. */
|
|
33
35
|
canUpgrade: boolean
|
|
34
36
|
}
|
package/src/settings.ts
CHANGED
|
@@ -45,6 +45,18 @@ export const DEFAULT_STREAM_DEBUG_TUNING: StreamDebugTuning = {
|
|
|
45
45
|
backpressureMinScale: 0.55,
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* How the typewriter reveal responds to the OS reduced-motion preference.
|
|
50
|
+
* Credit: three-state design proposed by @Zn-Dk in #21/#22.
|
|
51
|
+
*/
|
|
52
|
+
export type StreamMotionPreference =
|
|
53
|
+
/** Follow the OS preference: reduced-motion users get raw text (accessibility first). */
|
|
54
|
+
| 'auto'
|
|
55
|
+
/** Always run the smoothing engine, ignoring the OS preference. */
|
|
56
|
+
| 'force-smooth'
|
|
57
|
+
/** Always render raw text, ignoring the OS preference. */
|
|
58
|
+
| 'force-reduced'
|
|
59
|
+
|
|
48
60
|
/**
|
|
49
61
|
* Preferences a user may set. Deliberately separate from {@link StreamConfig}
|
|
50
62
|
* because the two change at different times: composition-time values go
|
|
@@ -56,19 +68,24 @@ export interface StreamSettings {
|
|
|
56
68
|
* Off returns all rendering ownership to the built-in UI.
|
|
57
69
|
*/
|
|
58
70
|
enabled: boolean
|
|
71
|
+
/**
|
|
72
|
+
* Whether this plugin also takes over conversation bottom-follow. Off leaves
|
|
73
|
+
* scroll ownership to the Harness; text reveal still runs.
|
|
74
|
+
*/
|
|
75
|
+
controlScroll: boolean
|
|
76
|
+
/**
|
|
77
|
+
* How the reveal honors the OS reduced-motion preference. `auto` preserves
|
|
78
|
+
* the accessibility-first default; `force-smooth` keeps the engine on
|
|
79
|
+
* machines where a system-wide reduce-motion switch (performance tooling,
|
|
80
|
+
* RDP sessions, forced browser flags) would otherwise bypass it silently.
|
|
81
|
+
*/
|
|
82
|
+
motionPreference: StreamMotionPreference
|
|
59
83
|
/**
|
|
60
84
|
* Whether a reasoning ("Think") block auto-expands while it is the
|
|
61
85
|
* streaming tail. Off keeps the block collapsed — the user can still open
|
|
62
86
|
* it by hand — and stops the running state from re-owning the disclosure.
|
|
63
87
|
*/
|
|
64
88
|
thinkAutoExpand: boolean
|
|
65
|
-
/**
|
|
66
|
-
* Whether a finished turn folds its work process (thinking, tool calls,
|
|
67
|
-
* context injection, intermediate replies) behind one "已处理" summary row,
|
|
68
|
-
* leaving only the final answer visible. The summary row can always be
|
|
69
|
-
* toggled by hand, and turns still expand live while they stream.
|
|
70
|
-
*/
|
|
71
|
-
autoCollapse: boolean
|
|
72
89
|
/** Whether the live renderer diagnostics panel is enabled. */
|
|
73
90
|
debugEnabled: boolean
|
|
74
91
|
/** Values edited by the diagnostics panel. */
|
|
@@ -78,8 +95,9 @@ export interface StreamSettings {
|
|
|
78
95
|
/** Defaults shared by the Host schema and the client-side fallback. */
|
|
79
96
|
export const DEFAULT_STREAM_SETTINGS: StreamSettings = {
|
|
80
97
|
enabled: true,
|
|
98
|
+
controlScroll: true,
|
|
99
|
+
motionPreference: 'auto',
|
|
81
100
|
thinkAutoExpand: true,
|
|
82
|
-
autoCollapse: true,
|
|
83
101
|
debugEnabled: false,
|
|
84
102
|
debugTuning: DEFAULT_STREAM_DEBUG_TUNING,
|
|
85
103
|
}
|