dsh-code-server-app 0.3.57 → 0.3.59

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.
@@ -1,380 +0,0 @@
1
- /* dshcs-editor-bridge / webview/src/panel.css —— 「问 DSH」面板自己的样式(0.2.3)
2
- *
3
- * 面板的外壳(标题 / 状态 / 输入框 / 授权卡片)用 VS Code 主题变量,跟编辑器原生面板一致;
4
- * 消息正文**不在这里排版** —— 交给 DSH 官方渲染器的 CSS(MarkdownText.module.css /
5
- * CodeBlock.module.css),它依赖一套设计令牌(--dsw-* / --dsl-* / --shiki-*),
6
- * 由下面这行提供:构建脚本从官方发布物
7
- * (`@deepseek-ai/dsh-client-ui-theme` 的 lib/client.js 里内联的 CSS)原样抽出来,
8
- * 所以与 DSH 界面用的是同一套令牌(见 scripts/build-webview.mjs)。
9
- *
10
- * 顺序要紧:@import 必须在最前(官方令牌先落地),后面的覆盖规则才生效。
11
- */
12
-
13
- @import "./official-tokens.css";
14
-
15
- :root {
16
- color-scheme: light dark;
17
- }
18
-
19
- /* 面板根容器:
20
- * - webview 形态:body 带 .dshcs-panel(见 lib/ask-panel.js 的外壳 HTML);
21
- * - DSH 页面形态(0.2.5):对话框把 .dshcs-panel 放在自己的容器 div 上,
22
- * 所有排版规则都挂在这个类下,**绝不碰 DSH 自己的 body**(注入样式不能改宿主界面)。
23
- */
24
- .dshcs-panel {
25
- height: 100%;
26
- margin: 0;
27
- background: var(--vscode-editor-background, var(--dsw-alias-bg-base, #1e1e1e));
28
- color: var(--vscode-foreground, var(--dsw-alias-label-primary, #ccc));
29
- font-family: var(--vscode-font-family, var(--dsw-font-family, sans-serif));
30
- font-size: var(--vscode-font-size, 13px);
31
- overflow: hidden;
32
- }
33
-
34
- .dshcs-panel #root {
35
- height: 100%;
36
- }
37
-
38
- .dshcs-app {
39
- display: flex;
40
- flex-direction: column;
41
- height: 100%;
42
- /* 对话框形状(0.2.4):面板开在编辑器区、占满工作台宽度,内容居中限宽。 */
43
- width: 100%;
44
- max-width: 900px;
45
- margin: 0 auto;
46
- }
47
-
48
- .dshcs-header {
49
- display: flex;
50
- align-items: baseline;
51
- gap: 8px;
52
- padding: 8px 12px;
53
- border-bottom: 1px solid var(--vscode-panel-border, rgba(128, 128, 128, 0.35));
54
- font-size: 12px;
55
- opacity: 0.9;
56
- }
57
-
58
- .dshcs-header .dshcs-title {
59
- font-weight: 600;
60
- letter-spacing: 0.04em;
61
- }
62
-
63
- .dshcs-header .dshcs-where {
64
- flex: 1;
65
- overflow: hidden;
66
- text-overflow: ellipsis;
67
- white-space: nowrap;
68
- }
69
-
70
- .dshcs-header .dshcs-version {
71
- opacity: 0.7;
72
- font-family: var(--vscode-editor-font-family, monospace);
73
- font-size: 11px;
74
- }
75
-
76
- .dshcs-header .dshcs-close {
77
- border: none;
78
- background: transparent;
79
- color: inherit;
80
- cursor: pointer;
81
- font-size: 13px;
82
- line-height: 1;
83
- padding: 2px 6px;
84
- border-radius: 4px;
85
- opacity: 0.75;
86
- }
87
-
88
- .dshcs-header .dshcs-close:hover {
89
- background: var(--vscode-toolbar-hoverBackground, rgba(128, 128, 128, 0.2));
90
- opacity: 1;
91
- }
92
-
93
- /* ---- 思考行(默认收起;外形照抄官方 ReasoningRow 的排版语言) ---- */
94
-
95
- .dshcs-think {
96
- display: flex;
97
- flex-direction: column;
98
- margin: 2px 0 6px;
99
- }
100
-
101
- .dshcs-think .dshcs-think-separator {
102
- flex: none;
103
- width: 2px;
104
- height: 2px;
105
- margin: 0 8px;
106
- border-radius: 1px;
107
- background: var(--dsw-alias-label-caption, currentColor);
108
- display: inline-block;
109
- }
110
-
111
- .dshcs-think .dshcs-think-summary {
112
- min-width: 0;
113
- overflow: hidden;
114
- flex: 1 1 auto;
115
- color: var(--dsw-alias-label-tertiary, var(--vscode-descriptionForeground));
116
- font-size: var(--dsh-content-font-size-secondary, 13px);
117
- white-space: nowrap;
118
- text-overflow: ellipsis;
119
- }
120
-
121
- .dshcs-think .dshcs-think-body {
122
- padding: 4px 0 4px calc(22px + var(--dsh-content-font-delta, 0px));
123
- color: var(--dsw-alias-label-tertiary, var(--vscode-descriptionForeground));
124
- font-size: var(--dsh-content-font-size-secondary, 13px);
125
- line-height: 1.55;
126
- white-space: pre-wrap;
127
- word-break: break-word;
128
- }
129
-
130
- .dshcs-warn {
131
- margin: 8px 12px 0;
132
- padding: 6px 8px;
133
- border: 1px solid var(--vscode-inputValidation-warningBorder, #b89500);
134
- background: var(--vscode-inputValidation-warningBackground, rgba(184, 149, 0, 0.15));
135
- border-radius: 4px;
136
- font-size: 12px;
137
- white-space: pre-wrap;
138
- }
139
-
140
- .dshcs-log {
141
- flex: 1;
142
- overflow-y: auto;
143
- padding: 12px 14px 4px;
144
- }
145
-
146
- .dshcs-empty {
147
- opacity: 0.6;
148
- font-size: 12px;
149
- padding: 4px 0;
150
- }
151
-
152
- /* ---- 消息条目:排版交给官方渲染器,这里只管气泡与间距 ---- */
153
-
154
- .dshcs-msg {
155
- margin-bottom: 14px;
156
- }
157
-
158
- .dshcs-user {
159
- display: flex;
160
- justify-content: flex-end;
161
- }
162
-
163
- /* 用户消息:注入的上下文(折叠行)+ 问题气泡,右对齐成一组。 */
164
- .dshcs-user-stack {
165
- max-width: 88%;
166
- display: flex;
167
- flex-direction: column;
168
- align-items: stretch;
169
- gap: 2px;
170
- }
171
-
172
- .dshcs-context .dshcs-context-summary {
173
- min-width: 0;
174
- overflow: hidden;
175
- flex: 1 1 auto;
176
- color: var(--dsw-alias-label-tertiary, var(--vscode-descriptionForeground));
177
- font-size: var(--dsh-content-font-size-secondary, 13px);
178
- white-space: nowrap;
179
- text-overflow: ellipsis;
180
- }
181
-
182
- .dshcs-context .dshcs-context-body {
183
- margin: 2px 0 4px;
184
- padding: 4px 0 4px calc(22px + var(--dsh-content-font-delta, 0px));
185
- color: var(--dsw-alias-label-tertiary, var(--vscode-descriptionForeground));
186
- font-size: var(--dsh-content-font-size-secondary, 12px);
187
- font-family: var(--ds-font-family-code, monospace);
188
- line-height: 1.5;
189
- white-space: pre-wrap;
190
- word-break: break-word;
191
- max-height: 40vh;
192
- overflow: auto;
193
- }
194
-
195
- .dshcs-bubble {
196
- padding: 6px 10px;
197
- border-radius: 8px;
198
- background: var(--vscode-input-background, rgba(128, 128, 128, 0.12));
199
- border: 1px solid var(--vscode-input-border, rgba(128, 128, 128, 0.25));
200
- white-space: pre-wrap;
201
- word-break: break-word;
202
- }
203
-
204
- .dshcs-bubble[data-status="sending"] {
205
- opacity: 0.6;
206
- }
207
-
208
- .dshcs-bubble[data-status="error"] {
209
- border-color: var(--vscode-inputValidation-errorBorder, #be1100);
210
- }
211
-
212
- .dshcs-assistant {
213
- word-break: break-word;
214
- }
215
-
216
- .dshcs-tool {
217
- display: flex;
218
- align-items: baseline;
219
- gap: 8px;
220
- margin: 4px 0 10px;
221
- padding: 4px 8px;
222
- border-left: 2px solid var(--vscode-panel-border, rgba(128, 128, 128, 0.4));
223
- font-size: 12px;
224
- opacity: 0.85;
225
- }
226
-
227
- .dshcs-tool .dshcs-tool-name {
228
- font-family: var(--vscode-editor-font-family, monospace);
229
- }
230
-
231
- .dshcs-tool .dshcs-tool-summary {
232
- flex: 1;
233
- overflow: hidden;
234
- text-overflow: ellipsis;
235
- white-space: nowrap;
236
- opacity: 0.8;
237
- }
238
-
239
- .dshcs-tool .dshcs-tool-state[data-state="error"] {
240
- color: var(--vscode-errorForeground, #f48771);
241
- }
242
-
243
- /* ---- 授权卡片:桥里唯一的"非只读"操作,必须一眼看清 ---- */
244
-
245
- .dshcs-approval {
246
- margin: 8px 12px;
247
- padding: 8px 10px;
248
- border: 1px solid var(--vscode-inputValidation-warningBorder, #b89500);
249
- background: var(--vscode-inputValidation-warningBackground, rgba(184, 149, 0, 0.12));
250
- border-radius: 6px;
251
- }
252
-
253
- .dshcs-approval[data-decided] {
254
- opacity: 0.75;
255
- }
256
-
257
- .dshcs-approval-head {
258
- display: flex;
259
- align-items: baseline;
260
- gap: 8px;
261
- font-size: 12px;
262
- margin-bottom: 4px;
263
- }
264
-
265
- .dshcs-approval-title {
266
- font-weight: 600;
267
- }
268
-
269
- .dshcs-approval-timer {
270
- flex: 1;
271
- text-align: right;
272
- opacity: 0.8;
273
- }
274
-
275
- .dshcs-approval-body {
276
- font-size: 12px;
277
- margin-bottom: 6px;
278
- word-break: break-word;
279
- }
280
-
281
- .dshcs-approval-tool {
282
- font-family: var(--vscode-editor-font-family, monospace);
283
- }
284
-
285
- .dshcs-approval-reason {
286
- margin-top: 2px;
287
- opacity: 0.9;
288
- white-space: pre-wrap;
289
- }
290
-
291
- .dshcs-approval-actions {
292
- display: flex;
293
- align-items: center;
294
- gap: 8px;
295
- flex-wrap: wrap;
296
- }
297
-
298
- .dshcs-approval-actions button {
299
- padding: 3px 10px;
300
- border: 1px solid var(--vscode-button-border, transparent);
301
- border-radius: 4px;
302
- cursor: pointer;
303
- color: var(--vscode-button-foreground);
304
- background: var(--vscode-button-background);
305
- font-family: inherit;
306
- font-size: 12px;
307
- }
308
-
309
- .dshcs-approval-actions button + button {
310
- color: var(--vscode-button-secondaryForeground, var(--vscode-foreground));
311
- background: var(--vscode-button-secondaryBackground, rgba(128, 128, 128, 0.2));
312
- }
313
-
314
- .dshcs-approval-actions button:disabled {
315
- opacity: 0.5;
316
- cursor: default;
317
- }
318
-
319
- .dshcs-approval-note {
320
- font-size: 12px;
321
- opacity: 0.85;
322
- }
323
-
324
- /* ---- 状态行 + 输入框 ---- */
325
-
326
- .dshcs-status {
327
- padding: 0 12px 6px;
328
- font-size: 12px;
329
- min-height: 16px;
330
- opacity: 0.85;
331
- }
332
-
333
- .dshcs-status[data-status="error"] {
334
- color: var(--vscode-errorForeground, #f48771);
335
- opacity: 1;
336
- }
337
-
338
- .dshcs-footer {
339
- display: flex;
340
- align-items: flex-end;
341
- gap: 8px;
342
- padding: 8px 12px;
343
- border-top: 1px solid var(--vscode-panel-border, rgba(128, 128, 128, 0.35));
344
- }
345
-
346
- .dshcs-footer textarea {
347
- flex: 1;
348
- min-height: 46px;
349
- max-height: 40vh;
350
- resize: vertical;
351
- box-sizing: border-box;
352
- padding: 6px 8px;
353
- border: 1px solid var(--vscode-input-border, rgba(128, 128, 128, 0.35));
354
- border-radius: 4px;
355
- color: var(--vscode-input-foreground);
356
- background: var(--vscode-input-background);
357
- font-family: inherit;
358
- font-size: inherit;
359
- }
360
-
361
- .dshcs-footer textarea:focus {
362
- outline: 1px solid var(--vscode-focusBorder);
363
- outline-offset: -1px;
364
- }
365
-
366
- .dshcs-footer button {
367
- padding: 6px 14px;
368
- border: none;
369
- border-radius: 4px;
370
- cursor: pointer;
371
- color: var(--vscode-button-foreground);
372
- background: var(--vscode-button-background);
373
- font-family: inherit;
374
- font-size: inherit;
375
- }
376
-
377
- .dshcs-footer button:disabled {
378
- opacity: 0.5;
379
- cursor: default;
380
- }
@@ -1,160 +0,0 @@
1
- // dshcs-editor-bridge / webview/src/thread.jsx —— 一个对话条目的渲染(0.2.3 起;0.2.4 加思考行)
2
- //
3
- // 助手正文**不再自己排版**:直接调用 DSH 官方渲染器
4
- // (`@deepseek-ai/dsh-client-ui-primitives` 的 `MarkdownText` —— 与 DSH 界面同一份代码,
5
- // 同一套 mdast 管线、KaTeX、shiki 高亮、增量流式解析),面板只负责"外壳"。
6
- //
7
- // 思考过程(0.2.4):DSH 界面把它渲染成一行可折叠的「思考」(官方 `ReasoningRow` 用的就是
8
- // `DisclosureRow` + `IconThinkOutline14`,**默认收起**,收起时显示首行 / 流式时的最新一行)。
9
- // 面板用同一套官方部件重现它,差别只在文案与类名。
10
- //
11
- // 用户消息:DSH 界面里用户消息是纯文本气泡,这里保持一致(不渲染 markdown)。
12
- // 工具 / 授权:面板只给一行紧凑摘要(不做逐工具的自定义卡片)。
13
-
14
- import { memo, useState } from 'react';
15
- import {
16
- DisclosureRow,
17
- IconContextInjectionOutline16,
18
- IconThinkOutline14,
19
- MarkdownText,
20
- } from '@deepseek-ai/dsh-client-ui-primitives';
21
-
22
- /** 官方渲染器的界面文案(面板自己给中文;DSH 界面走它自己的 locale)。 */
23
- const LABELS = { code: { copyLabel: '复制', copiedLabel: '已复制' }, footnotes: '脚注' };
24
-
25
- /** 工具状态 → 中文。 */
26
- const TOOL_STATE = { running: '运行中', ok: '完成', error: '失败' };
27
-
28
- /** 授权审计行状态 → 中文。 */
29
- const APPROVAL_STATE = {
30
- asked: '等待授权',
31
- 'allowed-once': '已允许一次',
32
- rejected: '已拒绝',
33
- cancelled: '已取消',
34
- unavailable: '无人处理',
35
- };
36
-
37
- /** 折叠摘要取首行(还在流式时取最新一行)—— 与官方 ReasoningRow 同一规则。 */
38
- function summaryLine(text, running) {
39
- const source = running ? text.trimEnd() : text;
40
- if (source === '') return '';
41
- const index = running ? source.lastIndexOf('\n') : source.indexOf('\n');
42
- const line = index === -1 ? source : (running ? source.slice(index + 1) : source.slice(0, index));
43
- return line.replaceAll('**', '');
44
- }
45
-
46
- /**
47
- * 一行「思考」(默认收起,点行即展开)—— 外形与交互照抄官方 `ReasoningRow`。
48
- * @param {{text: string, running: boolean}} props running = 这一轮的正文还没开始落
49
- */
50
- function ThinkingRow({ text, running }) {
51
- const [expanded, setExpanded] = useState(false);
52
- return (
53
- <div className="dshcs-think" data-state={running ? 'running' : 'ok'} data-expanded={expanded || undefined}>
54
- <DisclosureRow
55
- icon={<IconThinkOutline14 size={14} />}
56
- title={running ? '思考中' : '思考'}
57
- open={expanded}
58
- expandable
59
- expandOnRowClick
60
- onToggle={() => setExpanded((value) => !value)}
61
- collapsedContent={(
62
- <>
63
- <span className="dshcs-think-separator" aria-hidden />
64
- <span className="dshcs-think-summary">{summaryLine(text, running)}</span>
65
- </>
66
- )}
67
- >
68
- <div className="dshcs-think-body">{text}</div>
69
- </DisclosureRow>
70
- </div>
71
- );
72
- }
73
-
74
- /**
75
- * 一行「注入的上下文」(默认收起):桥拼进消息的位置行 + 选区代码块。
76
- *
77
- * 与 DSH 界面对注入上下文的处理一致 —— 默认折叠,只留一行摘要;点开才看得到那段代码。
78
- * 摘要取位置行(第一行),去掉 `From the editor: ` 前缀(标题已经说了"来自编辑器")。
79
- */
80
- function ContextRow({ text, title = '上下文' }) {
81
- const [expanded, setExpanded] = useState(false);
82
- const firstLine = text.split('\n')[0] ?? '';
83
- const summary = firstLine.replace(/^From the editor:\s*/i, '');
84
- return (
85
- <div className="dshcs-context" data-expanded={expanded || undefined}>
86
- <DisclosureRow
87
- icon={<IconContextInjectionOutline16 size={16} />}
88
- title={title}
89
- open={expanded}
90
- expandable
91
- expandOnRowClick
92
- onToggle={() => setExpanded((value) => !value)}
93
- collapsedContent={<span className="dshcs-context-summary">{summary}</span>}
94
- >
95
- <pre className="dshcs-context-body">{text}</pre>
96
- </DisclosureRow>
97
- </div>
98
- );
99
- }
100
-
101
- export const ThreadEntry = memo(function ThreadEntry({ entry }) {
102
- if (entry.role === 'user') {
103
- // **别的工具注入的上下文不是"用户说的"**(0.3.43):DSH 界面按「上下文注入」折叠显示,面板照做 ——
104
- // 否则这些注入会变成一屏用户气泡,把真正的对话挤掉。
105
- if (typeof entry.sourceKind === 'string' && entry.sourceKind !== '') {
106
- return (
107
- <div className="dshcs-msg dshcs-injection">
108
- <ContextRow text={entry.text} title="上下文注入" />
109
- </div>
110
- );
111
- }
112
- const context = typeof entry.context === 'string' ? entry.context : '';
113
- return (
114
- <div className="dshcs-msg dshcs-user">
115
- <div className="dshcs-user-stack">
116
- {context === '' ? null : <ContextRow text={context} />}
117
- <div className="dshcs-bubble" data-status={entry.status ?? undefined}>{entry.text}</div>
118
- </div>
119
- </div>
120
- );
121
- }
122
-
123
- if (entry.role === 'assistant') {
124
- const thinking = typeof entry.thinking === 'string' ? entry.thinking : '';
125
- // 正文还没到(整轮都是思考)→ 思考行标"思考中";正文到了就标"思考"(官方同一判据)。
126
- const running = entry.streaming === true && entry.text === '';
127
- return (
128
- <div className="dshcs-msg dshcs-assistant">
129
- {thinking === '' ? null : <ThinkingRow text={thinking} running={running} />}
130
- {entry.text === ''
131
- ? null
132
- : <MarkdownText text={entry.text} streaming={entry.streaming === true} labels={LABELS} />}
133
- </div>
134
- );
135
- }
136
-
137
- if (entry.role === 'tool') {
138
- return (
139
- <div className="dshcs-tool" data-state={entry.status ?? 'running'}>
140
- <span className="dshcs-tool-name">{entry.name ?? 'tool'}</span>
141
- <span className="dshcs-tool-summary">{entry.summary ?? ''}</span>
142
- <span className="dshcs-tool-state" data-state={entry.status ?? 'running'}>
143
- {TOOL_STATE[entry.status] ?? entry.status ?? ''}
144
- </span>
145
- </div>
146
- );
147
- }
148
-
149
- if (entry.role === 'approval') {
150
- return (
151
- <div className="dshcs-tool dshcs-approval-row" data-state={entry.status ?? 'asked'}>
152
- <span className="dshcs-tool-name">{entry.toolName ?? entry.name ?? 'tool'}</span>
153
- <span className="dshcs-tool-summary">{entry.summary ?? ''}</span>
154
- <span className="dshcs-tool-state">{APPROVAL_STATE[entry.status] ?? entry.status ?? ''}</span>
155
- </div>
156
- );
157
- }
158
-
159
- return null;
160
- });