@ahggg/dsh-side-chat 0.7.3 → 1.0.1
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.md +52 -20
- package/README.zh-CN.md +52 -20
- package/lib/client/apply.js +48 -32
- package/lib/client/contracts.d.ts +3 -58
- package/lib/client/dsh/ReadOnlyConversation.d.ts +10 -0
- package/lib/client/dsh/ReadOnlyConversation.js +99 -0
- package/lib/client/dsh/SideChatOverlay.d.ts +7 -0
- package/lib/client/{rc6/Rc6SideChatOverlay.js → dsh/SideChatOverlay.js} +26 -56
- package/lib/client/{rc6 → dsh}/context.d.ts +4 -6
- package/lib/client/dsh/conversation-store.d.ts +22 -0
- package/lib/client/dsh/conversation-store.js +19 -0
- package/lib/client/dsh/primitive-labels.d.ts +2 -0
- package/lib/client/dsh/primitive-labels.js +4 -0
- package/lib/client/{rc6 → dsh}/remote-adapter.d.ts +2 -2
- package/lib/client/dsh/remote-adapter.js +22 -0
- package/lib/client/dsh/sessions-adapter.d.ts +56 -0
- package/lib/client/dsh/sessions-adapter.js +185 -0
- package/lib/client/index.d.ts +2 -2
- package/lib/client/panel/SelectionQuote.js +8 -1
- package/lib/client/panel/SideChatErrorState.js +1 -1
- package/lib/client/panel/SideChatModelSelect.d.ts +2 -1
- package/lib/client/panel/SideChatModelSelect.js +43 -24
- package/lib/client/panel/SideChatPanel.js +12 -5
- package/lib/client/panel/messages.d.ts +1 -1
- package/lib/client/panel/messages.js +8 -8
- package/lib/client/parent-composer/ParentConversationAnnotations.d.ts +3 -2
- package/lib/client/parent-composer/ParentConversationAnnotations.js +50 -30
- package/lib/client/parent-composer/add-to-conversation.d.ts +14 -28
- package/lib/client/parent-composer/add-to-conversation.js +131 -545
- package/lib/client/parent-composer/annotation-persistence.d.ts +8 -8
- package/lib/client/parent-composer/annotation-persistence.js +106 -102
- package/lib/client/parent-composer/composer-reference.d.ts +17 -55
- package/lib/client/parent-composer/composer-reference.js +20 -72
- package/lib/client/parent-composer/referenced-conversation.d.ts +5 -7
- package/lib/client/parent-composer/referenced-conversation.js +21 -73
- package/lib/client/selection/ConversationAnnotationMarkers.js +5 -1
- package/lib/client/selection/SelectionActions.js +2 -1
- package/lib/client/selection/conversation-dom.d.ts +5 -0
- package/lib/client/selection/conversation-dom.js +24 -0
- package/lib/client/selection/selection-controller.d.ts +1 -1
- package/lib/client/selection/selection-controller.js +7 -3
- package/lib/client/selection/selection-normalizer.js +1 -1
- package/lib/client/side-chat-controller.d.ts +28 -41
- package/lib/client/side-chat-controller.js +247 -337
- package/lib/client.js +84 -54
- package/lib/host/index.d.ts +1 -1
- package/lib/host/index.js +1 -1
- package/lib/host/read-only-chat-service.d.ts +30 -0
- package/lib/host/read-only-chat-service.js +315 -0
- package/lib/index.d.ts +16 -8
- package/lib/index.js +34 -13
- package/lib/remote.d.ts +23 -14
- package/lib/remote.js +2 -5
- package/lib/shared/constants.d.ts +0 -13
- package/lib/shared/constants.js +0 -13
- package/lib/shared/contracts.d.ts +52 -19
- package/lib/shared/contracts.js +2 -3
- package/lib/shared/error-codes.d.ts +1 -1
- package/lib/shared/error-codes.js +2 -2
- package/lib/shared/{archived-wire.d.ts → side-chat-wire.d.ts} +109 -20
- package/lib/shared/side-chat-wire.js +34 -0
- package/lib/typert.d.ts +3 -68
- package/lib/typert.js +60 -4
- package/package.json +76 -56
- package/lib/client/rc6/ArchivedConversation.d.ts +0 -14
- package/lib/client/rc6/ArchivedConversation.js +0 -231
- package/lib/client/rc6/Rc6SideChatOverlay.d.ts +0 -7
- package/lib/client/rc6/SideChatTool.d.ts +0 -22
- package/lib/client/rc6/SideChatTool.js +0 -404
- package/lib/client/rc6/primitive-labels.d.ts +0 -7
- package/lib/client/rc6/primitive-labels.js +0 -60
- package/lib/client/rc6/remote-adapter.js +0 -34
- package/lib/client/rc6/runtime-compat.d.ts +0 -120
- package/lib/client/rc6/runtime-compat.js +0 -187
- package/lib/client/rc6/sessions-adapter.d.ts +0 -64
- package/lib/client/rc6/sessions-adapter.js +0 -387
- package/lib/host/archived-fork-service.d.ts +0 -28
- package/lib/host/archived-fork-service.js +0 -309
- package/lib/shared/archived-wire.js +0 -47
- /package/lib/client/{rc6 → dsh}/context.js +0 -0
|
@@ -1,404 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from 'react';
|
|
3
|
-
import { CodeBlock, DiffBlock, DisclosureRow, IconApiOutline14, IconBrowseOutline16, IconCodeOutline16, IconEditOutline16, IconSearchOutline16, IconSparkle16, ReadBlock, SearchBlock, StateDot, TerminalBlock, WebBlock, } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
4
|
-
import { DIFF_LABELS, READ_LABELS, SEARCH_LABELS, TERMINAL_LABELS, WEB_LABELS, } from './primitive-labels.js';
|
|
5
|
-
const TOOL_VARIANTS = {
|
|
6
|
-
bash: 'bash',
|
|
7
|
-
pwsh: 'bash',
|
|
8
|
-
read: 'read',
|
|
9
|
-
web_fetch: 'read',
|
|
10
|
-
web_search: 'search',
|
|
11
|
-
grep: 'search',
|
|
12
|
-
glob: 'search',
|
|
13
|
-
write: 'write',
|
|
14
|
-
edit: 'edit',
|
|
15
|
-
run_code: 'code',
|
|
16
|
-
};
|
|
17
|
-
const VARIANT_TITLES = {
|
|
18
|
-
search: 'Search',
|
|
19
|
-
read: 'Read',
|
|
20
|
-
bash: 'Bash',
|
|
21
|
-
write: 'Write',
|
|
22
|
-
edit: 'Edit',
|
|
23
|
-
code: 'Code',
|
|
24
|
-
others: 'Tool call',
|
|
25
|
-
};
|
|
26
|
-
const SUMMARY_KEYS = {
|
|
27
|
-
bash: ['description', 'command'],
|
|
28
|
-
read: ['path', 'file_path', 'url'],
|
|
29
|
-
search: ['query', 'pattern', 'url'],
|
|
30
|
-
write: ['path', 'file_path'],
|
|
31
|
-
edit: ['path', 'file_path'],
|
|
32
|
-
code: ['description'],
|
|
33
|
-
others: [],
|
|
34
|
-
};
|
|
35
|
-
function record(value) {
|
|
36
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
37
|
-
? value
|
|
38
|
-
: null;
|
|
39
|
-
}
|
|
40
|
-
function stringValue(value) {
|
|
41
|
-
return typeof value === 'string' && value !== '' ? value : undefined;
|
|
42
|
-
}
|
|
43
|
-
function numberValue(value) {
|
|
44
|
-
return typeof value === 'number' && Number.isFinite(value) ? value : undefined;
|
|
45
|
-
}
|
|
46
|
-
function booleanValue(value) {
|
|
47
|
-
return typeof value === 'boolean' ? value : undefined;
|
|
48
|
-
}
|
|
49
|
-
function firstLine(text) {
|
|
50
|
-
const newline = text.indexOf('\n');
|
|
51
|
-
return newline === -1 ? text : text.slice(0, newline);
|
|
52
|
-
}
|
|
53
|
-
function stringify(value) {
|
|
54
|
-
if (typeof value === 'string')
|
|
55
|
-
return value;
|
|
56
|
-
try {
|
|
57
|
-
return JSON.stringify(value, null, 2);
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
return String(value);
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function contentText(content) {
|
|
64
|
-
return content.map((block) => {
|
|
65
|
-
if (block.type === 'text' || block.type === 'reasoning')
|
|
66
|
-
return block.text;
|
|
67
|
-
if (block.type === 'image')
|
|
68
|
-
return '[Image]';
|
|
69
|
-
if (block.type === 'tool-call')
|
|
70
|
-
return `${block.name}(${block.arguments})`;
|
|
71
|
-
if (block.type === 'tool-result')
|
|
72
|
-
return contentText(block.content);
|
|
73
|
-
return stringify(block);
|
|
74
|
-
}).filter(Boolean).join('\n');
|
|
75
|
-
}
|
|
76
|
-
export function toolOutputText(content) {
|
|
77
|
-
const text = contentText(content);
|
|
78
|
-
const fileEnvelope = /^<path>[\s\S]*?<\/path>\s*<type>[\s\S]*?<\/type>\s*<content>\s*\n?([\s\S]*?)\n?<\/content>\s*$/u.exec(text);
|
|
79
|
-
return fileEnvelope?.[1]?.trimEnd() ?? text;
|
|
80
|
-
}
|
|
81
|
-
function parseArguments(argsRaw) {
|
|
82
|
-
try {
|
|
83
|
-
return record(JSON.parse(argsRaw));
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
return null;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function formattedArguments(argsRaw) {
|
|
90
|
-
try {
|
|
91
|
-
return JSON.stringify(JSON.parse(argsRaw), null, 2);
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
return argsRaw;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
function classifyTool(name) {
|
|
98
|
-
return TOOL_VARIANTS[name.toLowerCase()] ?? 'others';
|
|
99
|
-
}
|
|
100
|
-
function toolTitle(name, variant) {
|
|
101
|
-
if (name.toLowerCase() === 'pwsh')
|
|
102
|
-
return 'Pwsh';
|
|
103
|
-
return VARIANT_TITLES[variant];
|
|
104
|
-
}
|
|
105
|
-
function pickArgument(args, keys) {
|
|
106
|
-
for (const key of keys) {
|
|
107
|
-
const value = stringValue(args[key]);
|
|
108
|
-
if (value !== undefined)
|
|
109
|
-
return value;
|
|
110
|
-
}
|
|
111
|
-
return Object.values(args).find((value) => typeof value === 'string' && value !== '');
|
|
112
|
-
}
|
|
113
|
-
function relativizeToCwd(path, cwd) {
|
|
114
|
-
if (cwd === undefined || cwd === '')
|
|
115
|
-
return path;
|
|
116
|
-
const root = cwd.replace(/[/\\]+$/u, '');
|
|
117
|
-
const lowerPath = path.toLowerCase();
|
|
118
|
-
const lowerRoot = root.toLowerCase();
|
|
119
|
-
return lowerPath.startsWith(`${lowerRoot}/`) || lowerPath.startsWith(`${lowerRoot}\\`)
|
|
120
|
-
? path.slice(root.length + 1)
|
|
121
|
-
: path;
|
|
122
|
-
}
|
|
123
|
-
function summaryFromArguments(name, variant, argsRaw, callId, cwd) {
|
|
124
|
-
const args = parseArguments(argsRaw);
|
|
125
|
-
const picked = args === null ? undefined : pickArgument(args, SUMMARY_KEYS[variant]);
|
|
126
|
-
const base = relativizeToCwd(firstLine(picked ?? (argsRaw === '' || argsRaw === '{}' ? callId : argsRaw)), cwd);
|
|
127
|
-
return variant === 'others' && name !== '' ? `${name} · ${base}` : base;
|
|
128
|
-
}
|
|
129
|
-
function filePathFromArguments(variant, argsRaw) {
|
|
130
|
-
if (variant !== 'read' && variant !== 'write' && variant !== 'edit')
|
|
131
|
-
return undefined;
|
|
132
|
-
const args = parseArguments(argsRaw);
|
|
133
|
-
if (args === null)
|
|
134
|
-
return undefined;
|
|
135
|
-
return stringValue(args['path']) ?? stringValue(args['file_path']);
|
|
136
|
-
}
|
|
137
|
-
function variantIcon(variant) {
|
|
138
|
-
switch (variant) {
|
|
139
|
-
case 'search': return _jsx(IconSearchOutline16, { size: 14 });
|
|
140
|
-
case 'read': return _jsx(IconBrowseOutline16, { size: 14 });
|
|
141
|
-
case 'bash': return _jsx(IconApiOutline14, { size: 14 });
|
|
142
|
-
case 'write':
|
|
143
|
-
case 'edit': return _jsx(IconEditOutline16, { size: 14 });
|
|
144
|
-
case 'code': return _jsx(IconCodeOutline16, { size: 14 });
|
|
145
|
-
case 'others': return _jsx(IconSparkle16, { size: 14 });
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
function resolveTerminalCwd(viewCwd, cwd) {
|
|
149
|
-
if (viewCwd === undefined || viewCwd === '')
|
|
150
|
-
return cwd;
|
|
151
|
-
if (cwd === undefined || cwd === '' || /^(?:[A-Za-z]:[/\\]|[/\\]{1,2})/u.test(viewCwd))
|
|
152
|
-
return viewCwd;
|
|
153
|
-
return `${cwd.replace(/[/\\]+$/u, '')}\\${viewCwd}`;
|
|
154
|
-
}
|
|
155
|
-
function terminalCard(variant, argsRaw, state, output, callView, resultView, cwd) {
|
|
156
|
-
const call = record(callView);
|
|
157
|
-
const result = record(resultView);
|
|
158
|
-
const callIsTerminal = call?.['card'] === 'terminal';
|
|
159
|
-
const resultIsTerminal = result?.['card'] === 'terminal';
|
|
160
|
-
if (variant !== 'bash' && !callIsTerminal && !resultIsTerminal)
|
|
161
|
-
return null;
|
|
162
|
-
const args = parseArguments(argsRaw);
|
|
163
|
-
const command = stringValue(result?.['title'])
|
|
164
|
-
?? stringValue(call?.['title'])
|
|
165
|
-
?? (args === null ? undefined : stringValue(args['command']))
|
|
166
|
-
?? '';
|
|
167
|
-
return {
|
|
168
|
-
command,
|
|
169
|
-
cwd: resolveTerminalCwd(stringValue(call?.['cwd']), cwd),
|
|
170
|
-
output: stringValue(result?.['output']) ?? output,
|
|
171
|
-
exitCode: numberValue(result?.['exitCode']),
|
|
172
|
-
signal: stringValue(result?.['signal']),
|
|
173
|
-
running: state === 'running' || state === 'pending',
|
|
174
|
-
description: stringValue(call?.['description']),
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
function languageForPath(path) {
|
|
178
|
-
if (path === undefined)
|
|
179
|
-
return undefined;
|
|
180
|
-
const extension = /\.([^.\\/]+)$/u.exec(path)?.[1]?.toLowerCase();
|
|
181
|
-
const aliases = {
|
|
182
|
-
js: 'javascript', jsx: 'jsx', ts: 'typescript', tsx: 'tsx',
|
|
183
|
-
json: 'json', css: 'css', html: 'html', md: 'markdown',
|
|
184
|
-
yml: 'yaml', yaml: 'yaml', py: 'python', ps1: 'powershell',
|
|
185
|
-
sh: 'bash', toml: 'toml', xml: 'xml',
|
|
186
|
-
};
|
|
187
|
-
return extension === undefined ? undefined : aliases[extension];
|
|
188
|
-
}
|
|
189
|
-
function validReadLines(value) {
|
|
190
|
-
if (!Array.isArray(value))
|
|
191
|
-
return null;
|
|
192
|
-
const lines = [];
|
|
193
|
-
for (const item of value) {
|
|
194
|
-
const line = record(item);
|
|
195
|
-
const number = numberValue(line?.['number']);
|
|
196
|
-
const text = stringValue(line?.['text']) ?? (line?.['text'] === '' ? '' : undefined);
|
|
197
|
-
if (number === undefined || text === undefined)
|
|
198
|
-
return null;
|
|
199
|
-
lines.push({ number, text });
|
|
200
|
-
}
|
|
201
|
-
return lines;
|
|
202
|
-
}
|
|
203
|
-
function readCard(name, argsRaw, state, output, resultView, cwd) {
|
|
204
|
-
if (state === 'running' || state === 'pending' || state === 'error' || state === 'interrupted')
|
|
205
|
-
return null;
|
|
206
|
-
const result = record(resultView);
|
|
207
|
-
if (result?.['card'] === 'read') {
|
|
208
|
-
const lines = validReadLines(result['lines']);
|
|
209
|
-
const totalLines = numberValue(result['totalLines']);
|
|
210
|
-
const path = stringValue(result['path']);
|
|
211
|
-
if (lines === null || totalLines === undefined)
|
|
212
|
-
return null;
|
|
213
|
-
return {
|
|
214
|
-
label: stringValue(result['title']) ?? (path === undefined ? undefined : relativizeToCwd(path, cwd)),
|
|
215
|
-
lines,
|
|
216
|
-
totalLines,
|
|
217
|
-
lang: stringValue(result['lang']),
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
if (name.toLowerCase() !== 'read' || output === undefined)
|
|
221
|
-
return null;
|
|
222
|
-
const path = filePathFromArguments('read', argsRaw);
|
|
223
|
-
const texts = output.split('\n');
|
|
224
|
-
return {
|
|
225
|
-
label: path === undefined ? undefined : relativizeToCwd(path, cwd),
|
|
226
|
-
lines: texts.map((text, index) => ({ number: index + 1, text })),
|
|
227
|
-
totalLines: texts.length,
|
|
228
|
-
lang: languageForPath(path),
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
function validSearchCard(resultView) {
|
|
232
|
-
const result = record(resultView);
|
|
233
|
-
if (result?.['card'] !== 'search')
|
|
234
|
-
return null;
|
|
235
|
-
const truncated = booleanValue(result['truncated']);
|
|
236
|
-
const total = numberValue(result['total']);
|
|
237
|
-
if (truncated === undefined || total === undefined)
|
|
238
|
-
return null;
|
|
239
|
-
if (result['shape'] === 'paths') {
|
|
240
|
-
const paths = result['paths'];
|
|
241
|
-
return Array.isArray(paths) && paths.every((path) => typeof path === 'string')
|
|
242
|
-
? { kind: 'paths', paths, truncated, total, labels: SEARCH_LABELS }
|
|
243
|
-
: null;
|
|
244
|
-
}
|
|
245
|
-
if (result['shape'] !== 'matches' || !Array.isArray(result['files']))
|
|
246
|
-
return null;
|
|
247
|
-
const files = [];
|
|
248
|
-
for (const item of result['files']) {
|
|
249
|
-
const file = record(item);
|
|
250
|
-
const path = stringValue(file?.['path']);
|
|
251
|
-
const matchesValue = file?.['matches'];
|
|
252
|
-
if (path === undefined || !Array.isArray(matchesValue))
|
|
253
|
-
return null;
|
|
254
|
-
const matches = [];
|
|
255
|
-
for (const matchValue of matchesValue) {
|
|
256
|
-
const match = record(matchValue);
|
|
257
|
-
const lineNumber = numberValue(match?.['lineNumber']);
|
|
258
|
-
const line = stringValue(match?.['line']) ?? (match?.['line'] === '' ? '' : undefined);
|
|
259
|
-
if (lineNumber === undefined || line === undefined)
|
|
260
|
-
return null;
|
|
261
|
-
matches.push({ lineNumber, line });
|
|
262
|
-
}
|
|
263
|
-
files.push({ path, matches });
|
|
264
|
-
}
|
|
265
|
-
return { kind: 'matches', files, truncated, total, labels: SEARCH_LABELS };
|
|
266
|
-
}
|
|
267
|
-
function validDiffs(view) {
|
|
268
|
-
const value = record(view);
|
|
269
|
-
if (value?.['card'] !== 'diff' || !Array.isArray(value['diffs']) || value['diffs'].length === 0)
|
|
270
|
-
return null;
|
|
271
|
-
const diffs = [];
|
|
272
|
-
for (const item of value['diffs']) {
|
|
273
|
-
const hunk = record(item);
|
|
274
|
-
const path = stringValue(hunk?.['path']);
|
|
275
|
-
const oldText = hunk?.['oldText'];
|
|
276
|
-
const newText = stringValue(hunk?.['newText']) ?? (hunk?.['newText'] === '' ? '' : undefined);
|
|
277
|
-
if (path === undefined || (oldText !== null && typeof oldText !== 'string') || newText === undefined)
|
|
278
|
-
return null;
|
|
279
|
-
diffs.push({ path, oldText, newText });
|
|
280
|
-
}
|
|
281
|
-
return diffs;
|
|
282
|
-
}
|
|
283
|
-
function validWebCard(view) {
|
|
284
|
-
const result = record(view);
|
|
285
|
-
if (result?.['card'] !== 'web')
|
|
286
|
-
return null;
|
|
287
|
-
const truncated = booleanValue(result['truncated']);
|
|
288
|
-
if (truncated === undefined)
|
|
289
|
-
return null;
|
|
290
|
-
if (result['kind'] === 'fetch') {
|
|
291
|
-
const url = stringValue(result['url']);
|
|
292
|
-
const statusCode = numberValue(result['statusCode']);
|
|
293
|
-
return url === undefined || statusCode === undefined
|
|
294
|
-
? null
|
|
295
|
-
: { kind: 'fetch', url, statusCode, truncated, labels: WEB_LABELS };
|
|
296
|
-
}
|
|
297
|
-
if (result['kind'] !== 'search' || !Array.isArray(result['sources']))
|
|
298
|
-
return null;
|
|
299
|
-
const sources = [];
|
|
300
|
-
for (const item of result['sources']) {
|
|
301
|
-
const source = record(item);
|
|
302
|
-
const url = stringValue(source?.['url']);
|
|
303
|
-
if (url === undefined)
|
|
304
|
-
return null;
|
|
305
|
-
const title = stringValue(source?.['title']);
|
|
306
|
-
const snippet = stringValue(source?.['snippet']);
|
|
307
|
-
const publishedAt = stringValue(source?.['publishedAt']);
|
|
308
|
-
sources.push({
|
|
309
|
-
url,
|
|
310
|
-
...(title === undefined ? {} : { title }),
|
|
311
|
-
...(snippet === undefined ? {} : { snippet }),
|
|
312
|
-
...(publishedAt === undefined ? {} : { publishedAt }),
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
const answer = stringValue(result['answer']);
|
|
316
|
-
return {
|
|
317
|
-
kind: 'search',
|
|
318
|
-
sources,
|
|
319
|
-
truncated,
|
|
320
|
-
labels: WEB_LABELS,
|
|
321
|
-
...(answer === undefined ? {} : { answer }),
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
function genericBody(variant, argsRaw) {
|
|
325
|
-
if (argsRaw === '' || argsRaw === '{}')
|
|
326
|
-
return null;
|
|
327
|
-
if (variant === 'read' || variant === 'write' || variant === 'edit')
|
|
328
|
-
return null;
|
|
329
|
-
return formattedArguments(argsRaw);
|
|
330
|
-
}
|
|
331
|
-
function leadingFor(state, icon) {
|
|
332
|
-
if (state === 'error')
|
|
333
|
-
return _jsx(StateDot, { state: "error" });
|
|
334
|
-
if (state === 'interrupted')
|
|
335
|
-
return _jsx(StateDot, { state: "warning" });
|
|
336
|
-
return icon;
|
|
337
|
-
}
|
|
338
|
-
function toolStatus(state) {
|
|
339
|
-
if (state === 'running' || state === 'pending')
|
|
340
|
-
return 'Running';
|
|
341
|
-
if (state === 'error')
|
|
342
|
-
return 'Failed';
|
|
343
|
-
if (state === 'interrupted')
|
|
344
|
-
return 'Stopped';
|
|
345
|
-
return null;
|
|
346
|
-
}
|
|
347
|
-
export function ToolCard({ callId, name, argsRaw, state, output, callView, resultView, cwd, }) {
|
|
348
|
-
const [expanded, setExpanded] = useState(false);
|
|
349
|
-
const variant = classifyTool(name);
|
|
350
|
-
const terminal = terminalCard(variant, argsRaw, state, output, callView, resultView, cwd);
|
|
351
|
-
const terminalFailed = terminal !== null
|
|
352
|
-
&& !terminal.running
|
|
353
|
-
&& ((terminal.exitCode !== undefined && terminal.exitCode !== 0) || terminal.signal !== undefined);
|
|
354
|
-
const visualState = state === 'success' && terminalFailed ? 'error' : state;
|
|
355
|
-
const read = readCard(name, argsRaw, visualState, output, resultView, cwd);
|
|
356
|
-
const search = validSearchCard(resultView);
|
|
357
|
-
const diffs = validDiffs(resultView) ?? validDiffs(callView);
|
|
358
|
-
const web = validWebCard(resultView);
|
|
359
|
-
const args = parseArguments(argsRaw);
|
|
360
|
-
const code = variant === 'code' && args !== null ? stringValue(args['code']) : undefined;
|
|
361
|
-
const body = genericBody(variant, argsRaw);
|
|
362
|
-
const summary = terminal?.description
|
|
363
|
-
?? stringValue(record(resultView)?.['title'])
|
|
364
|
-
?? summaryFromArguments(name, variant, argsRaw, callId, cwd);
|
|
365
|
-
const failureLine = visualState === 'error' && output !== undefined ? firstLine(output) : null;
|
|
366
|
-
const summaryText = failureLine ?? summary;
|
|
367
|
-
const hasSpecialCard = terminal !== null || read !== null || search !== null || diffs !== null || web !== null || code !== undefined;
|
|
368
|
-
const expandable = hasSpecialCard || body !== null || output !== undefined;
|
|
369
|
-
const open = expanded && expandable;
|
|
370
|
-
const status = toolStatus(visualState);
|
|
371
|
-
return (_jsxs("section", { className: "dsh-side-chat-tool", "data-call-id": callId, "data-state": visualState, "data-expanded": open || undefined, children: [status !== null && _jsx("span", { className: "dsh-side-chat-tool-visually-hidden", children: status }), _jsx(DisclosureRow, { rowClassName: "dsh-side-chat-tool-row", leadingClassName: "dsh-side-chat-tool-leading", titleClassName: "dsh-side-chat-tool-title", chevronClassName: "dsh-side-chat-tool-chevron", icon: leadingFor(visualState, variantIcon(variant)), title: toolTitle(name, variant), open: open, expandable: expandable, expandOnRowClick: true, keepContentWhenOpen: true, onToggle: () => { setExpanded(current => !current); }, collapsedContent: summaryText !== '' && (_jsxs(_Fragment, { children: [_jsx("span", { className: "dsh-side-chat-tool-separator", "aria-hidden": "true" }), _jsx("span", { className: failureLine === null
|
|
372
|
-
? 'dsh-side-chat-tool-summary'
|
|
373
|
-
: 'dsh-side-chat-tool-summary dsh-side-chat-tool-error-summary', children: summaryText })] })), children: _jsx("div", { className: "dsh-side-chat-tool-body-wrap", children: terminal !== null
|
|
374
|
-
? (_jsx(TerminalBlock, { command: terminal.command, cwd: terminal.cwd, output: terminal.output, exitCode: terminal.exitCode, signal: terminal.signal, running: terminal.running, maxLines: Infinity, className: "dsh-side-chat-tool-terminal", labels: TERMINAL_LABELS }))
|
|
375
|
-
: read !== null
|
|
376
|
-
? _jsx(ReadBlock, { ...read, labels: READ_LABELS, maxLines: 8, className: "dsh-side-chat-tool-read" })
|
|
377
|
-
: search !== null
|
|
378
|
-
? _jsx(SearchBlock, { ...search, maxLines: 8, className: "dsh-side-chat-tool-search" })
|
|
379
|
-
: diffs !== null
|
|
380
|
-
? _jsx(DiffBlock, { diffs: diffs, labels: DIFF_LABELS, maxLines: 8, className: "dsh-side-chat-tool-diff" })
|
|
381
|
-
: web !== null
|
|
382
|
-
? _jsx(WebBlock, { ...web, className: "dsh-side-chat-tool-web" })
|
|
383
|
-
: code !== undefined
|
|
384
|
-
? _jsx(CodeBlock, { code: code, lang: "typescript", copyLabel: "Copy", copiedLabel: "Copied", className: "dsh-side-chat-tool-code" })
|
|
385
|
-
: (body !== null || output !== undefined) && (_jsxs("div", { className: "dsh-side-chat-tool-io-card", children: [body !== null && (_jsxs("div", { className: "dsh-side-chat-tool-io-section", children: [_jsx("span", { className: "dsh-side-chat-tool-io-label", children: "IN" }), _jsx("span", { className: "dsh-side-chat-tool-io-text", children: body })] })), body !== null && output !== undefined && _jsx("span", { className: "dsh-side-chat-tool-io-divider", "aria-hidden": "true" }), output !== undefined && (_jsxs("div", { className: "dsh-side-chat-tool-io-section", children: [_jsx("span", { className: "dsh-side-chat-tool-io-label", children: "OUT" }), _jsx("span", { className: "dsh-side-chat-tool-io-text", "data-error": visualState === 'error' || undefined, children: output })] }))] })) }) })] }));
|
|
386
|
-
}
|
|
387
|
-
function resultState(node, output) {
|
|
388
|
-
if (!node.isError)
|
|
389
|
-
return 'success';
|
|
390
|
-
const identity = `${node.error?.name ?? ''} ${node.error?.code ?? ''} ${output}`;
|
|
391
|
-
return /\b(?:aborted|cancelled|canceled)\b/iu.test(identity) ? 'interrupted' : 'error';
|
|
392
|
-
}
|
|
393
|
-
export function ToolBlockCard({ block, cwd }) {
|
|
394
|
-
const presentation = block;
|
|
395
|
-
const settled = 'kind' in block;
|
|
396
|
-
const output = settled ? toolOutputText(block.content) : undefined;
|
|
397
|
-
const state = settled ? resultState(block, output ?? '') : 'running';
|
|
398
|
-
const name = settled ? block.call?.name ?? block.callId : block.name;
|
|
399
|
-
const argsRaw = settled ? block.call?.argsRaw ?? '{}' : block.argsRaw;
|
|
400
|
-
return (_jsxs("div", { className: "dsh-side-chat-tool-branch", children: [_jsx(ToolCard, { callId: block.callId, name: name, argsRaw: argsRaw, state: state, output: output, callView: presentation.callView, resultView: settled ? presentation.resultView : null, cwd: cwd }), block.subCalls.length > 0 && (_jsx("div", { className: "dsh-side-chat-tool-subcalls", "data-subcalls": true, children: block.subCalls.map(child => _jsx(ToolBlockCard, { block: child, cwd: cwd }, child.callId)) }))] }));
|
|
401
|
-
}
|
|
402
|
-
export function RunningToolCard({ call, cwd }) {
|
|
403
|
-
return _jsx(ToolBlockCard, { block: call, cwd: cwd });
|
|
404
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { DiffBlockLabels, MarkdownLabels, ReadBlockLabels, SearchBlockLabels, TerminalBlockLabels, WebBlockLabels } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
2
|
-
export declare const MARKDOWN_LABELS: MarkdownLabels;
|
|
3
|
-
export declare const TERMINAL_LABELS: TerminalBlockLabels;
|
|
4
|
-
export declare const READ_LABELS: ReadBlockLabels;
|
|
5
|
-
export declare const DIFF_LABELS: DiffBlockLabels;
|
|
6
|
-
export declare const SEARCH_LABELS: SearchBlockLabels;
|
|
7
|
-
export declare const WEB_LABELS: WebBlockLabels;
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
const hiddenLines = (hidden) => `Show ${String(hidden)} hidden line${hidden === 1 ? '' : 's'}`;
|
|
2
|
-
export const MARKDOWN_LABELS = {
|
|
3
|
-
code: { copyLabel: 'Copy', copiedLabel: 'Copied' },
|
|
4
|
-
footnotes: 'Footnotes',
|
|
5
|
-
};
|
|
6
|
-
export const TERMINAL_LABELS = {
|
|
7
|
-
signal: signal => `Signal ${signal}`,
|
|
8
|
-
exitCode: code => `Exit ${String(code)}`,
|
|
9
|
-
running: 'Running',
|
|
10
|
-
failed: 'Failed',
|
|
11
|
-
done: 'Done',
|
|
12
|
-
copy: 'Copy',
|
|
13
|
-
copied: 'Copied',
|
|
14
|
-
noOutput: 'No output',
|
|
15
|
-
collapseAria: 'Collapse command output',
|
|
16
|
-
collapse: 'Collapse',
|
|
17
|
-
expandAria: hiddenLines,
|
|
18
|
-
expand: hiddenLines,
|
|
19
|
-
};
|
|
20
|
-
export const READ_LABELS = {
|
|
21
|
-
window: (shown, total) => `Showing ${String(shown)} of ${String(total)} lines`,
|
|
22
|
-
copy: 'Copy',
|
|
23
|
-
copied: 'Copied',
|
|
24
|
-
collapseAria: 'Collapse file content',
|
|
25
|
-
expandAria: hiddenLines,
|
|
26
|
-
collapse: 'Collapse',
|
|
27
|
-
expand: hiddenLines,
|
|
28
|
-
};
|
|
29
|
-
export const DIFF_LABELS = {
|
|
30
|
-
copy: 'Copy',
|
|
31
|
-
copied: 'Copied',
|
|
32
|
-
collapseAria: 'Collapse diff',
|
|
33
|
-
expandAria: hiddenLines,
|
|
34
|
-
collapse: 'Collapse',
|
|
35
|
-
expand: hiddenLines,
|
|
36
|
-
files: count => `${String(count)} file${count === 1 ? '' : 's'}`,
|
|
37
|
-
};
|
|
38
|
-
export const SEARCH_LABELS = {
|
|
39
|
-
pathsSummary: (shown, total, truncated) => truncated
|
|
40
|
-
? `Showing ${String(shown)} of ${String(total)} paths`
|
|
41
|
-
: `${String(total)} path${total === 1 ? '' : 's'}`,
|
|
42
|
-
matchesSummary: (shown, total, files, truncated) => {
|
|
43
|
-
const summary = `${String(shown)} match${shown === 1 ? '' : 'es'} in ${String(files)} file${files === 1 ? '' : 's'}`;
|
|
44
|
-
return truncated ? `${summary} (${String(total)} total)` : summary;
|
|
45
|
-
},
|
|
46
|
-
copy: 'Copy',
|
|
47
|
-
copied: 'Copied',
|
|
48
|
-
noResults: 'No results',
|
|
49
|
-
collapseAria: 'Collapse search results',
|
|
50
|
-
expandAria: hiddenLines,
|
|
51
|
-
collapse: 'Collapse',
|
|
52
|
-
expand: hiddenLines,
|
|
53
|
-
};
|
|
54
|
-
export const WEB_LABELS = {
|
|
55
|
-
noResults: 'No results',
|
|
56
|
-
sourcesTruncated: 'Sources truncated',
|
|
57
|
-
http: 'HTTP',
|
|
58
|
-
contentTruncated: 'Content truncated',
|
|
59
|
-
markdown: MARKDOWN_LABELS,
|
|
60
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import TYPERT_REMOTE from '../../remote.js';
|
|
2
|
-
function remoteFailure(error) {
|
|
3
|
-
const code = error.code;
|
|
4
|
-
const badRequest = code === 'bad-request' || code === 'gateway/bad-request';
|
|
5
|
-
return {
|
|
6
|
-
code: badRequest ? 'invalid_request' : 'transport_error',
|
|
7
|
-
message: error.message || 'The Side Chat RPC failed.',
|
|
8
|
-
recoverable: !badRequest,
|
|
9
|
-
};
|
|
10
|
-
}
|
|
11
|
-
export async function mountArchivedRemote(ctx) {
|
|
12
|
-
const dispose = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
13
|
-
const archived = ctx.get('remote.sideChatArchived');
|
|
14
|
-
return {
|
|
15
|
-
remote: {
|
|
16
|
-
create: async (request) => {
|
|
17
|
-
const result = await archived.create({
|
|
18
|
-
...request,
|
|
19
|
-
atSeq: Math.floor(request.atSeq),
|
|
20
|
-
});
|
|
21
|
-
return result.ok ? result.value : { ok: false, error: remoteFailure(result.error) };
|
|
22
|
-
},
|
|
23
|
-
selectModel: async (request) => {
|
|
24
|
-
const result = await archived.selectModel(request);
|
|
25
|
-
return result.ok ? result.value : { ok: false, error: remoteFailure(result.error) };
|
|
26
|
-
},
|
|
27
|
-
close: async (request) => {
|
|
28
|
-
const result = await archived.close(request);
|
|
29
|
-
return result.ok ? result.value : { ok: false, error: remoteFailure(result.error) };
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
dispose,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import type { SessionFace as CurrentSessionFace } from '@deepseek-ai/dsh-api-session-controller/client';
|
|
2
|
-
import type { ChatSnapshot } from '@deepseek-ai/dsh-client-ui-chat/client';
|
|
3
|
-
import type { AssistantBlock, ConversationNode, PartialAssistant, RunningToolCall, ToolCallBlock } from '@deepseek-ai/dsh-client-ui-conversation/client';
|
|
4
|
-
import type { SessionId } from '@deepseek-ai/dsh-session/types';
|
|
5
|
-
import type { AskUserQuestionAnswer, AskUserQuestionItem } from '@deepseek-ai/dsh-user-questions/types';
|
|
6
|
-
export type { AssistantBlock, ConversationNode, RunningToolCall, ToolCallBlock, };
|
|
7
|
-
interface RuntimeFailure {
|
|
8
|
-
readonly code: string;
|
|
9
|
-
readonly message: string;
|
|
10
|
-
}
|
|
11
|
-
export type RuntimeResult<T = unknown> = {
|
|
12
|
-
readonly ok: true;
|
|
13
|
-
readonly value: T;
|
|
14
|
-
} | {
|
|
15
|
-
readonly ok: false;
|
|
16
|
-
readonly error: RuntimeFailure;
|
|
17
|
-
};
|
|
18
|
-
interface ObservableSnapshot<T> {
|
|
19
|
-
readonly getSnapshot: () => T;
|
|
20
|
-
readonly subscribe: (listener: () => void) => () => void;
|
|
21
|
-
}
|
|
22
|
-
export interface SideChatNodeStore {
|
|
23
|
-
get(key: string): {
|
|
24
|
-
readonly key: string;
|
|
25
|
-
readonly kind: string;
|
|
26
|
-
readonly anchorSeq: number;
|
|
27
|
-
readonly visibility: 'visible' | 'hidden';
|
|
28
|
-
readonly location: {
|
|
29
|
-
readonly kind: 'session' | 'unresolved';
|
|
30
|
-
} | {
|
|
31
|
-
readonly kind: 'turn';
|
|
32
|
-
readonly turn: {
|
|
33
|
-
readonly turn: number;
|
|
34
|
-
readonly status: 'open' | 'closed' | 'unknown';
|
|
35
|
-
};
|
|
36
|
-
} | {
|
|
37
|
-
readonly kind: 'step';
|
|
38
|
-
readonly turn: {
|
|
39
|
-
readonly turn: number;
|
|
40
|
-
readonly status: 'open' | 'closed' | 'unknown';
|
|
41
|
-
};
|
|
42
|
-
readonly step: {
|
|
43
|
-
readonly status: 'open' | 'closed' | 'unknown';
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
} | undefined;
|
|
47
|
-
}
|
|
48
|
-
export interface SideChatApprovalInteraction {
|
|
49
|
-
readonly kind: 'approval';
|
|
50
|
-
readonly key: string;
|
|
51
|
-
readonly toolName: string;
|
|
52
|
-
readonly reason?: string;
|
|
53
|
-
respond(decision: 'approve' | 'decline'): Promise<boolean>;
|
|
54
|
-
}
|
|
55
|
-
export interface SideChatQuestionInteraction {
|
|
56
|
-
readonly kind: 'question';
|
|
57
|
-
readonly key: string;
|
|
58
|
-
readonly questions: readonly AskUserQuestionItem[];
|
|
59
|
-
respond(answer: AskUserQuestionAnswer | null): Promise<boolean>;
|
|
60
|
-
}
|
|
61
|
-
export type SideChatPendingInteraction = SideChatApprovalInteraction | SideChatQuestionInteraction;
|
|
62
|
-
export interface SideChatQueuedMessage {
|
|
63
|
-
readonly id: string;
|
|
64
|
-
readonly placement: 'queued' | 'steering' | 'context';
|
|
65
|
-
readonly preview: string;
|
|
66
|
-
}
|
|
67
|
-
export interface SideChatConversationSnapshot {
|
|
68
|
-
readonly nodes: readonly ConversationNode[];
|
|
69
|
-
readonly turnEnds: ReadonlyMap<number, number>;
|
|
70
|
-
readonly partial: PartialAssistant | null;
|
|
71
|
-
readonly runningCalls: readonly RunningToolCall[];
|
|
72
|
-
readonly pending: readonly SideChatPendingInteraction[];
|
|
73
|
-
readonly queue: readonly SideChatQueuedMessage[];
|
|
74
|
-
readonly running: boolean;
|
|
75
|
-
readonly openState: 'cold' | 'loading' | 'open' | 'error';
|
|
76
|
-
readonly promptError: {
|
|
77
|
-
readonly error: RuntimeFailure;
|
|
78
|
-
} | null;
|
|
79
|
-
readonly lastAgentError: string | null;
|
|
80
|
-
readonly chatNodes: SideChatNodeStore;
|
|
81
|
-
}
|
|
82
|
-
/** Stable surface consumed by Side Chat on both the monolithic and split DSH clients. */
|
|
83
|
-
export interface SideChatConversationFace extends ObservableSnapshot<SideChatConversationSnapshot> {
|
|
84
|
-
readonly sessionId: SessionId;
|
|
85
|
-
prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
|
|
86
|
-
updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
|
|
87
|
-
cancel(): Promise<RuntimeResult>;
|
|
88
|
-
rename(title: string): Promise<RuntimeResult>;
|
|
89
|
-
open(): Promise<void>;
|
|
90
|
-
}
|
|
91
|
-
interface RuntimeSessionFace {
|
|
92
|
-
readonly sessionId: SessionId;
|
|
93
|
-
getSnapshot(): unknown;
|
|
94
|
-
subscribe(listener: () => void): () => void;
|
|
95
|
-
prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
|
|
96
|
-
updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
|
|
97
|
-
cancel(): Promise<RuntimeResult>;
|
|
98
|
-
rename(title: string): Promise<RuntimeResult>;
|
|
99
|
-
open?: () => Promise<void>;
|
|
100
|
-
}
|
|
101
|
-
/** Bridge DSH <=0.1.1's combined Session snapshot and 0.1.2's split stores. */
|
|
102
|
-
export declare class CompatibleConversationFace implements SideChatConversationFace {
|
|
103
|
-
private readonly session;
|
|
104
|
-
private readonly chat?;
|
|
105
|
-
private readonly pending?;
|
|
106
|
-
readonly sessionId: SessionId;
|
|
107
|
-
private cache;
|
|
108
|
-
constructor(session: RuntimeSessionFace, chat?: ObservableSnapshot<ChatSnapshot | undefined> | undefined, pending?: ObservableSnapshot<ReadonlyMap<SessionId, unknown>> | undefined);
|
|
109
|
-
readonly subscribe: (listener: () => void) => (() => void);
|
|
110
|
-
readonly getSnapshot: () => SideChatConversationSnapshot;
|
|
111
|
-
prompt(content: unknown[], mode: 'queue' | 'steer'): Promise<RuntimeResult>;
|
|
112
|
-
updateQueue(itemId: string, action: unknown): Promise<RuntimeResult>;
|
|
113
|
-
cancel(): Promise<RuntimeResult>;
|
|
114
|
-
rename(title: string): Promise<RuntimeResult>;
|
|
115
|
-
open(): Promise<void>;
|
|
116
|
-
}
|
|
117
|
-
export declare function compatibleConversationFace(session: CurrentSessionFace, sources?: {
|
|
118
|
-
readonly chat?: ObservableSnapshot<ChatSnapshot | undefined>;
|
|
119
|
-
readonly pending?: ObservableSnapshot<ReadonlyMap<SessionId, unknown>>;
|
|
120
|
-
}): CompatibleConversationFace;
|