@antst/dashi 0.1.0-alpha.8 → 0.1.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.md +6 -6
- package/lib/application.d.ts +2 -0
- package/lib/application.js +8 -3
- package/lib/catalogs.d.ts +5 -0
- package/lib/catalogs.js +91 -1
- package/lib/completion-trigger.d.ts +4 -0
- package/lib/completion-trigger.js +13 -1
- package/lib/diff-view.js +11 -4
- package/lib/help.d.ts +1 -1
- package/lib/help.js +1 -1
- package/lib/history-records.d.ts +2 -2
- package/lib/history-records.js +2 -12
- package/lib/index.js +62 -14
- package/lib/input.d.ts +8 -1
- package/lib/input.js +45 -0
- package/lib/renderer.d.ts +2 -0
- package/lib/renderer.js +90 -20
- package/lib/rewind.d.ts +15 -2
- package/lib/rewind.js +46 -16
- package/lib/session-runtime.d.ts +10 -0
- package/lib/session-runtime.js +390 -43
- package/lib/shell-command.d.ts +1 -1
- package/lib/shell-command.js +3 -2
- package/lib/state.d.ts +23 -3
- package/lib/state.js +64 -23
- package/lib/transcript.d.ts +3 -1
- package/lib/transcript.js +57 -44
- package/package.json +38 -33
- package/validated-dsh-versions.json +0 -3
package/lib/shell-command.d.ts
CHANGED
|
@@ -7,4 +7,4 @@ export declare const HUMAN_SHELL_STREAM_BYTES: number;
|
|
|
7
7
|
export declare function shellResultText(command: string, result: ShellRunResult): string;
|
|
8
8
|
export declare function quoteShellWord(value: string): string;
|
|
9
9
|
/** Run an explicit human command through DSH and identify its next-step context. */
|
|
10
|
-
export declare function runHumanShell(ctx: Context, agent: Agent, command: string, signal: AbortSignal, success?: string): Promise<readonly [UserMessage, ShellRunResult]>;
|
|
10
|
+
export declare function runHumanShell(ctx: Context, agent: Agent, command: string, signal: AbortSignal, success?: string, useSessionSandbox?: boolean): Promise<readonly [UserMessage, ShellRunResult]>;
|
package/lib/shell-command.js
CHANGED
|
@@ -45,11 +45,12 @@ export function shellResultText(command, result) {
|
|
|
45
45
|
}
|
|
46
46
|
export function quoteShellWord(value) { return `'${value.replaceAll("'", "'\\''")}'`; }
|
|
47
47
|
/** Run an explicit human command through DSH and identify its next-step context. */
|
|
48
|
-
export async function runHumanShell(ctx, agent, command, signal, success) {
|
|
48
|
+
export async function runHumanShell(ctx, agent, command, signal, success, useSessionSandbox = true) {
|
|
49
49
|
const result = await ctx.shell.run(ctx.shell.resolve({
|
|
50
50
|
command,
|
|
51
51
|
env: { DSH_HOME: resolveDshHome() },
|
|
52
|
-
sandboxPolicy: ctx.sandboxPolicy.resolve(
|
|
52
|
+
sandboxPolicy: ctx.sandboxPolicy.resolve(useSessionSandbox
|
|
53
|
+
? { session: agent.session } : { mode: 'danger-full-access' }),
|
|
53
54
|
signal,
|
|
54
55
|
stdoutMaxBytes: HUMAN_SHELL_STREAM_BYTES,
|
|
55
56
|
timeoutMs: HUMAN_SHELL_TIMEOUT_MS,
|
package/lib/state.d.ts
CHANGED
|
@@ -87,6 +87,7 @@ export interface QuestionOption {
|
|
|
87
87
|
readonly label: string;
|
|
88
88
|
}
|
|
89
89
|
export interface QuestionItem {
|
|
90
|
+
readonly allowCustom?: boolean;
|
|
90
91
|
readonly detail?: string;
|
|
91
92
|
readonly header?: string;
|
|
92
93
|
readonly id: string;
|
|
@@ -97,6 +98,7 @@ export interface QuestionItem {
|
|
|
97
98
|
readonly multiSelect: boolean;
|
|
98
99
|
readonly options: readonly QuestionOption[];
|
|
99
100
|
readonly question: string;
|
|
101
|
+
readonly secret?: boolean;
|
|
100
102
|
}
|
|
101
103
|
export interface QuestionAnswer {
|
|
102
104
|
readonly custom?: string;
|
|
@@ -129,9 +131,15 @@ export type OverlayValue = {
|
|
|
129
131
|
readonly path: string;
|
|
130
132
|
readonly source: string;
|
|
131
133
|
readonly text: string;
|
|
134
|
+
} | {
|
|
135
|
+
readonly kind: 'copy';
|
|
136
|
+
readonly text: string;
|
|
132
137
|
} | {
|
|
133
138
|
readonly kind: 'insert';
|
|
134
139
|
readonly text: string;
|
|
140
|
+
} | {
|
|
141
|
+
readonly jobId: string;
|
|
142
|
+
readonly kind: 'job-output';
|
|
135
143
|
} | {
|
|
136
144
|
readonly kind: 'model';
|
|
137
145
|
readonly effort?: string;
|
|
@@ -182,6 +190,8 @@ export type OverlayValue = {
|
|
|
182
190
|
};
|
|
183
191
|
export type ActivatableOverlayValue = Exclude<OverlayValue, {
|
|
184
192
|
kind: 'attach';
|
|
193
|
+
} | {
|
|
194
|
+
kind: 'copy';
|
|
185
195
|
} | {
|
|
186
196
|
kind: 'insert';
|
|
187
197
|
}>;
|
|
@@ -200,12 +210,13 @@ export type Overlay = {
|
|
|
200
210
|
readonly kind: 'list';
|
|
201
211
|
readonly notice?: string;
|
|
202
212
|
readonly options: readonly OverlayOption[];
|
|
203
|
-
readonly purpose: 'agents' | 'completion' | 'memory' | 'model' | 'permission' | 'resume' | 'rewind' | 'rewind-action' | 'search';
|
|
213
|
+
readonly purpose: 'agents' | 'completion' | 'copy' | 'memory' | 'model' | 'permission' | 'resume' | 'rewind' | 'rewind-action' | 'search' | 'skills';
|
|
204
214
|
readonly title: string;
|
|
205
215
|
} | {
|
|
206
216
|
readonly cells?: readonly TerminalCell[];
|
|
207
217
|
readonly kind: 'info';
|
|
208
218
|
readonly lines: readonly string[];
|
|
219
|
+
readonly scrollOffset?: number;
|
|
209
220
|
readonly title: string;
|
|
210
221
|
} | {
|
|
211
222
|
readonly cursor: number;
|
|
@@ -261,6 +272,9 @@ export type UiAction = {
|
|
|
261
272
|
readonly source?: string;
|
|
262
273
|
readonly text?: string;
|
|
263
274
|
readonly type: 'attachment-added';
|
|
275
|
+
} | {
|
|
276
|
+
readonly path: string;
|
|
277
|
+
readonly type: 'attachment-path';
|
|
264
278
|
} | {
|
|
265
279
|
readonly index: number;
|
|
266
280
|
readonly type: 'attachment-remove';
|
|
@@ -323,6 +337,9 @@ export type UiAction = {
|
|
|
323
337
|
readonly type: 'open-history';
|
|
324
338
|
} | {
|
|
325
339
|
readonly type: 'open-details';
|
|
340
|
+
} | {
|
|
341
|
+
readonly path: string;
|
|
342
|
+
readonly type: 'open-file';
|
|
326
343
|
} | {
|
|
327
344
|
readonly type: 'completion-ready';
|
|
328
345
|
readonly options: readonly OverlayOption[];
|
|
@@ -333,6 +350,7 @@ export type UiAction = {
|
|
|
333
350
|
} | {
|
|
334
351
|
readonly type: 'overlay-close';
|
|
335
352
|
} | {
|
|
353
|
+
readonly limit?: number;
|
|
336
354
|
readonly type: 'overlay-move';
|
|
337
355
|
readonly offset: number;
|
|
338
356
|
} | {
|
|
@@ -428,7 +446,8 @@ export type UiAction = {
|
|
|
428
446
|
readonly hasMore?: boolean;
|
|
429
447
|
readonly rootId?: string;
|
|
430
448
|
} | {
|
|
431
|
-
readonly
|
|
449
|
+
readonly selection: number | 'code';
|
|
450
|
+
readonly type: 'copy-assistant';
|
|
432
451
|
};
|
|
433
452
|
export type UiEffect = {
|
|
434
453
|
readonly type: 'activate-overlay';
|
|
@@ -492,6 +511,7 @@ export type UiEffect = {
|
|
|
492
511
|
} | {
|
|
493
512
|
readonly type: 'suspend';
|
|
494
513
|
};
|
|
495
|
-
export declare function initialViewState(cwd: string, inline: boolean, root?: RootView, cells?: readonly TerminalCell[], prompts?: readonly string[], historyHasMore?: boolean, attachments?: readonly DraftAttachment[]): ViewState;
|
|
514
|
+
export declare function initialViewState(cwd: string, inline: boolean, root?: RootView, cells?: readonly TerminalCell[], prompts?: readonly string[], historyHasMore?: boolean, attachments?: readonly DraftAttachment[], toolMode?: ToolMode): ViewState;
|
|
496
515
|
export declare const TURN_BELL_THRESHOLD_MS = 10000;
|
|
516
|
+
export declare const PAGE_CELLS = 8;
|
|
497
517
|
export declare function reduce(state: ViewState, action: UiAction): readonly [ViewState, readonly UiEffect[]];
|
package/lib/state.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FLAG_HELP, VERSION_LINE } from './help.js';
|
|
2
|
-
export function initialViewState(cwd, inline, root, cells = [], prompts = [], historyHasMore = false, attachments = []) {
|
|
2
|
+
export function initialViewState(cwd, inline, root, cells = [], prompts = [], historyHasMore = false, attachments = [], toolMode = 'collapsed') {
|
|
3
3
|
return {
|
|
4
4
|
attachments, cells, composer: '', cwd, decisions: [], exitArmed: false, historyHasMore, inline,
|
|
5
5
|
newOutput: 0, prompts, rewindArmed: false, scrollOffset: 0,
|
|
6
|
-
sendMode: 'steer', toolMode
|
|
6
|
+
sendMode: 'steer', toolMode,
|
|
7
7
|
...(root === undefined ? {} : { root }),
|
|
8
8
|
};
|
|
9
9
|
}
|
|
@@ -25,7 +25,7 @@ function moveCursor(decision, cursor) {
|
|
|
25
25
|
const question = decision.questions[decision.index];
|
|
26
26
|
if (question === undefined)
|
|
27
27
|
return decision;
|
|
28
|
-
return { ...decision, cursor: Math.max(0, Math.min(question.options.length, cursor)) };
|
|
28
|
+
return { ...decision, cursor: Math.max(0, Math.min(question.options.length - (question.allowCustom === false ? 1 : 0), cursor)) };
|
|
29
29
|
}
|
|
30
30
|
function help() {
|
|
31
31
|
return {
|
|
@@ -41,8 +41,8 @@ function help() {
|
|
|
41
41
|
'Ctrl+B activity details for jobs and subagents',
|
|
42
42
|
'@ paths require DSH file-reference · Ctrl+V pastes an image · Backspace removes it',
|
|
43
43
|
'Ctrl+S stash · Ctrl+G editor · F1 help · Ctrl+L redraw · Ctrl+Z suspend',
|
|
44
|
-
'/new /clear /resume [--all] [NAME|UUID] /fork /rewind /rename /model /permission /agents /queue',
|
|
45
|
-
'/
|
|
44
|
+
'/new /clear /reset /resume /continue [--all] [NAME|UUID] /fork /branch /rewind /rename /model /effort /permission /agents /queue /status /usage /context',
|
|
45
|
+
'/init /memory /skills /config /login /logout /diff /plugins /plugin /tasks /bashes /subtask /loop /btw /recap /history /export /copy /exit /quit',
|
|
46
46
|
...FLAG_HELP,
|
|
47
47
|
],
|
|
48
48
|
};
|
|
@@ -55,7 +55,7 @@ function moveOverlay(overlay, cursor, detailsCount = 0) {
|
|
|
55
55
|
: Math.max(0, overlay.options.length - 1);
|
|
56
56
|
return { ...overlay, cursor: Math.max(0, Math.min(limit, cursor)) };
|
|
57
57
|
}
|
|
58
|
-
const PAGE_CELLS = 8;
|
|
58
|
+
export const PAGE_CELLS = 8;
|
|
59
59
|
function matches(cells, query) {
|
|
60
60
|
const needle = query.trim().toLocaleLowerCase();
|
|
61
61
|
if (needle === '')
|
|
@@ -86,13 +86,31 @@ function refreshSearch(search, cells) {
|
|
|
86
86
|
const found = matches(cells, search.query);
|
|
87
87
|
return { ...search, cursor: Math.min(search.cursor, Math.max(0, found.length - 1)), matches: found };
|
|
88
88
|
}
|
|
89
|
-
function
|
|
89
|
+
function completedAssistant(cells, nth) {
|
|
90
|
+
let seen = 0;
|
|
90
91
|
for (let index = cells.length - 1; index >= 0; index--) {
|
|
91
92
|
const cell = cells[index];
|
|
92
|
-
if (cell?.kind === 'assistant' && cell.pending !== true)
|
|
93
|
+
if (cell?.kind === 'assistant' && cell.pending !== true && ++seen === nth)
|
|
93
94
|
return cell;
|
|
94
95
|
}
|
|
95
96
|
}
|
|
97
|
+
function codeBlockOptions(text) {
|
|
98
|
+
const fence = /(?:^|\r?\n)(`{3,}|~{3,})([^\r\n]*)\r?\n([\s\S]*?)\r?\n\1[ \t]*(?=\r?\n|$)/gu;
|
|
99
|
+
return [...text.matchAll(fence)].map(match => {
|
|
100
|
+
const code = match[3] ?? '';
|
|
101
|
+
return {
|
|
102
|
+
label: `${match[2]?.trim() || 'text'} · ${code.split(/\r?\n/u)[0] ?? ''}`,
|
|
103
|
+
value: { kind: 'copy', text: code },
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function exitChord(state) {
|
|
108
|
+
if (state.exitArmed)
|
|
109
|
+
return reduce(state, { type: 'exit' });
|
|
110
|
+
return [{ ...state, exitArmed: true, rewindArmed: false }, [
|
|
111
|
+
{ type: 'exit-timer', armed: true }, ...redraw(),
|
|
112
|
+
]];
|
|
113
|
+
}
|
|
96
114
|
export function reduce(state, action) {
|
|
97
115
|
const head = state.decisions[0];
|
|
98
116
|
switch (action.type) {
|
|
@@ -103,6 +121,7 @@ export function reduce(state, action) {
|
|
|
103
121
|
...(replace ? { composer: action.text } : {}),
|
|
104
122
|
}, [...(replace ? [{ type: 'set-composer', text: action.text }] : []), ...redraw()]];
|
|
105
123
|
}
|
|
124
|
+
case 'attachment-path': return [state, [{ type: 'attach', path: action.path, source: state.composer, text: state.composer }]];
|
|
106
125
|
case 'attachment-remove': {
|
|
107
126
|
if (action.index < 0 || action.index >= state.attachments.length)
|
|
108
127
|
return [state, []];
|
|
@@ -156,16 +175,12 @@ export function reduce(state, action) {
|
|
|
156
175
|
...state, attachments: [], composer: '', exitArmed: false, recall: undefined, rewindArmed: false,
|
|
157
176
|
}, [{ type: 'set-composer', text: '' }, ...redraw()]];
|
|
158
177
|
}
|
|
159
|
-
|
|
160
|
-
return reduce(state, { type: 'exit' });
|
|
161
|
-
return [{ ...state, exitArmed: true, rewindArmed: false }, [{ type: 'exit-timer', armed: true }, ...redraw()]];
|
|
178
|
+
return exitChord(state);
|
|
162
179
|
}
|
|
163
180
|
case 'ctrl-d':
|
|
164
181
|
if (state.composer !== '')
|
|
165
182
|
return [state, []];
|
|
166
|
-
|
|
167
|
-
return reduce(state, { type: 'exit' });
|
|
168
|
-
return reduce(state, { type: 'ctrl-c' });
|
|
183
|
+
return exitChord(state);
|
|
169
184
|
case 'decision-cancel': {
|
|
170
185
|
if (head === undefined)
|
|
171
186
|
return [state, []];
|
|
@@ -218,7 +233,7 @@ export function reduce(state, action) {
|
|
|
218
233
|
const question = head.questions[head.index];
|
|
219
234
|
if (question === undefined)
|
|
220
235
|
return [state, []];
|
|
221
|
-
const custom = head.cursor === question.options.length ? head.custom.trim() : undefined;
|
|
236
|
+
const custom = question.allowCustom !== false && head.cursor === question.options.length ? question.secret === true ? head.custom : head.custom.trim() : undefined;
|
|
222
237
|
if (custom !== undefined && custom === '')
|
|
223
238
|
return [state, []];
|
|
224
239
|
const option = question.options[head.cursor];
|
|
@@ -355,6 +370,7 @@ export function reduce(state, action) {
|
|
|
355
370
|
return head === undefined
|
|
356
371
|
? [{ ...state, overlay: action.overlay, exitArmed: false, rewindArmed: false }, redraw()]
|
|
357
372
|
: [state, []];
|
|
373
|
+
case 'open-file': return [state, [{ type: 'activate-overlay', value: { kind: 'open-file', path: action.path } }]];
|
|
358
374
|
case 'overlay-close': {
|
|
359
375
|
if (state.overlay === undefined)
|
|
360
376
|
return [state, []];
|
|
@@ -364,8 +380,14 @@ export function reduce(state, action) {
|
|
|
364
380
|
case 'overlay-move': {
|
|
365
381
|
if (state.overlay === undefined)
|
|
366
382
|
return [state, []];
|
|
383
|
+
if (state.overlay.kind === 'info') {
|
|
384
|
+
const current = state.overlay.scrollOffset ?? 0;
|
|
385
|
+
const scrollOffset = Math.max(0, Math.min(action.limit ?? current, current + action.offset));
|
|
386
|
+
return scrollOffset === current ? [state, []]
|
|
387
|
+
: [{ ...state, overlay: { ...state.overlay, scrollOffset } }, redraw()];
|
|
388
|
+
}
|
|
367
389
|
const count = (state.root?.jobs?.length ?? 0) + (state.root?.subagents?.length ?? 0);
|
|
368
|
-
const overlay = moveOverlay(state.overlay, state.overlay.
|
|
390
|
+
const overlay = moveOverlay(state.overlay, state.overlay.cursor + action.offset, count);
|
|
369
391
|
return overlay === state.overlay ? [state, []] : [{ ...state, overlay }, redraw()];
|
|
370
392
|
}
|
|
371
393
|
case 'overlay-number': {
|
|
@@ -382,10 +404,12 @@ export function reduce(state, action) {
|
|
|
382
404
|
return reduce(state, { type: 'history-toggle' });
|
|
383
405
|
if (overlay.kind === 'info')
|
|
384
406
|
return reduce(state, { type: 'overlay-close' });
|
|
385
|
-
if (overlay.kind === 'details')
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
407
|
+
if (overlay.kind === 'details') {
|
|
408
|
+
const job = state.root?.jobs?.[overlay.cursor - (state.root?.subagents?.length ?? 0)];
|
|
409
|
+
if (job !== undefined)
|
|
410
|
+
return [state, [{ type: 'activate-overlay', value: { jobId: job.id, kind: 'job-output' } }]];
|
|
411
|
+
return [{ ...state, overlay: { ...overlay, expanded: !overlay.expanded } }, redraw()];
|
|
412
|
+
}
|
|
389
413
|
if (overlay.kind === 'confirm') {
|
|
390
414
|
if (overlay.cursor !== 0)
|
|
391
415
|
return reduce(state, { type: 'overlay-close' });
|
|
@@ -410,6 +434,10 @@ export function reduce(state, action) {
|
|
|
410
434
|
type: 'attach', path: option.value.path, source: option.value.source, text: option.value.text,
|
|
411
435
|
}, ...redraw()]];
|
|
412
436
|
}
|
|
437
|
+
if (option.value.kind === 'copy') {
|
|
438
|
+
const { overlay: _overlay, ...withoutOverlay } = state;
|
|
439
|
+
return [withoutOverlay, [{ type: 'copy', text: option.value.text }, ...redraw()]];
|
|
440
|
+
}
|
|
413
441
|
if (option.value.kind === 'permission' && option.danger === true) {
|
|
414
442
|
return [{ ...state, overlay: {
|
|
415
443
|
acceptLabel: 'Enable',
|
|
@@ -548,6 +576,13 @@ export function reduce(state, action) {
|
|
|
548
576
|
return reduce(state, { type: 'decision-submit' });
|
|
549
577
|
if (state.root === undefined || state.composer === '' && state.attachments.length === 0)
|
|
550
578
|
return [state, []];
|
|
579
|
+
if (state.root.status === 'running' && /^\/(?:btw|recap)(?:\s|$)/u.test(state.composer)) {
|
|
580
|
+
const cleared = { ...state, attachments: [], composer: '', exitArmed: false, recall: undefined, rewindArmed: false };
|
|
581
|
+
const [reported, effects] = reduce(cleared, {
|
|
582
|
+
type: 'runtime-error', message: 'finish or interrupt the turn first', rootId: state.root.id,
|
|
583
|
+
});
|
|
584
|
+
return [reported, [{ type: 'set-composer', text: '' }, ...effects]];
|
|
585
|
+
}
|
|
551
586
|
const mode = state.root.status === 'running' ? state.sendMode : 'next-turn';
|
|
552
587
|
return [{
|
|
553
588
|
...state, attachments: [], composer: '', exitArmed: false, recall: undefined, rewindArmed: false,
|
|
@@ -636,9 +671,15 @@ export function reduce(state, action) {
|
|
|
636
671
|
}),
|
|
637
672
|
}, redraw()];
|
|
638
673
|
}
|
|
639
|
-
case 'copy-
|
|
640
|
-
const cell =
|
|
641
|
-
|
|
674
|
+
case 'copy-assistant': {
|
|
675
|
+
const cell = completedAssistant(state.cells, action.selection === 'code' ? 1 : action.selection);
|
|
676
|
+
if (cell === undefined)
|
|
677
|
+
return [state, []];
|
|
678
|
+
if (action.selection !== 'code')
|
|
679
|
+
return [state, [{ type: 'copy', text: cell.text }]];
|
|
680
|
+
return [{ ...state, overlay: {
|
|
681
|
+
cursor: 0, kind: 'list', options: codeBlockOptions(cell.text), purpose: 'copy', title: 'Copy code block',
|
|
682
|
+
} }, redraw()];
|
|
642
683
|
}
|
|
643
684
|
}
|
|
644
685
|
}
|
package/lib/transcript.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { UserMessage } from '@deepseek-ai/dsh-llm';
|
|
1
|
+
import type { StreamChunk, UserMessage } from '@deepseek-ai/dsh-llm';
|
|
2
2
|
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
3
3
|
import type { TerminalCell } from './state.js';
|
|
4
4
|
import { type ToolPresenter } from './tool-presentation.js';
|
|
@@ -7,6 +7,8 @@ interface FoldOptions {
|
|
|
7
7
|
}
|
|
8
8
|
/** Project DSH-owned pending injections beside the durable transcript. */
|
|
9
9
|
export declare function pendingShellCells(messages: readonly UserMessage[]): readonly TerminalCell[];
|
|
10
|
+
/** Fold one transient DSH Assistant frame into the current pending cells. */
|
|
11
|
+
export declare function foldAssistantStream(current: readonly TerminalCell[], turn: number, step: number, chunk: StreamChunk): readonly TerminalCell[];
|
|
10
12
|
/** Fold one chronological DSH event slice into terminal-owned presentation cells. */
|
|
11
13
|
export declare function foldCells(events: readonly SessionEvent[], presenter?: ToolPresenter | undefined, options?: FoldOptions): readonly TerminalCell[];
|
|
12
14
|
export {};
|
package/lib/transcript.js
CHANGED
|
@@ -81,6 +81,57 @@ function compactSource(event) {
|
|
|
81
81
|
...(typeof source.sourceCommandId === 'string' ? { sourceCommandId: source.sourceCommandId } : {}),
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
|
+
function putAssistant(cells, assistants, turn, step, kind, text, complete) {
|
|
85
|
+
const key = `${turn}:${step}`;
|
|
86
|
+
const pair = assistants.get(key) ?? {};
|
|
87
|
+
const slot = kind === 'text' ? pair.text : pair.reasoning;
|
|
88
|
+
const cellKind = kind === 'text' ? 'assistant' : 'reasoning';
|
|
89
|
+
if (slot === undefined) {
|
|
90
|
+
const next = cells.length;
|
|
91
|
+
cells.push({
|
|
92
|
+
key: `assistant:${key}:${kind}`,
|
|
93
|
+
kind: cellKind,
|
|
94
|
+
...(!complete && kind === 'text' ? { pending: true } : {}),
|
|
95
|
+
text,
|
|
96
|
+
...(complete && kind === 'reasoning' ? { collapsed: true } : {}),
|
|
97
|
+
});
|
|
98
|
+
if (kind === 'text')
|
|
99
|
+
pair.text = next;
|
|
100
|
+
else
|
|
101
|
+
pair.reasoning = next;
|
|
102
|
+
assistants.set(key, pair);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const previous = cells[slot];
|
|
106
|
+
if (previous === undefined)
|
|
107
|
+
return;
|
|
108
|
+
const { pending: _pending, ...settled } = previous;
|
|
109
|
+
cells[slot] = {
|
|
110
|
+
...(complete ? settled : previous),
|
|
111
|
+
text: complete ? text : previous.text + text,
|
|
112
|
+
...(complete && kind === 'reasoning' ? { collapsed: true } : {}),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
/** Fold one transient DSH Assistant frame into the current pending cells. */
|
|
116
|
+
export function foldAssistantStream(current, turn, step, chunk) {
|
|
117
|
+
const cells = [...current];
|
|
118
|
+
const pair = {};
|
|
119
|
+
cells.forEach((cell, slot) => {
|
|
120
|
+
if (cell.kind === 'assistant')
|
|
121
|
+
pair.text = slot;
|
|
122
|
+
else if (cell.kind === 'reasoning')
|
|
123
|
+
pair.reasoning = slot;
|
|
124
|
+
});
|
|
125
|
+
const assistants = new Map([[`${turn}:${step}`, pair]]);
|
|
126
|
+
if (chunk.type === 'text-delta')
|
|
127
|
+
putAssistant(cells, assistants, turn, step, 'text', chunk.text, false);
|
|
128
|
+
else if (chunk.type === 'reasoning-delta')
|
|
129
|
+
putAssistant(cells, assistants, turn, step, 'reasoning', chunk.text, false);
|
|
130
|
+
else if (chunk.type === 'block-end' && (chunk.block.type === 'text' || chunk.block.type === 'reasoning')) {
|
|
131
|
+
putAssistant(cells, assistants, turn, step, chunk.block.type, chunk.block.text, true);
|
|
132
|
+
}
|
|
133
|
+
return cells;
|
|
134
|
+
}
|
|
84
135
|
/** Fold one chronological DSH event slice into terminal-owned presentation cells. */
|
|
85
136
|
export function foldCells(events, presenter = createToolPresenter(() => undefined), options = {}) {
|
|
86
137
|
const toolPresenter = presenter ?? createToolPresenter(() => undefined);
|
|
@@ -94,39 +145,10 @@ export function foldCells(events, presenter = createToolPresenter(() => undefine
|
|
|
94
145
|
let planSlot;
|
|
95
146
|
let todoSlot;
|
|
96
147
|
let truncatedPrefix = options.truncatedStart === true;
|
|
97
|
-
const putAssistant = (turn, step, kind, text, complete) => {
|
|
98
|
-
const key = `${turn}:${step}`;
|
|
99
|
-
const pair = assistants.get(key) ?? {};
|
|
100
|
-
const slot = kind === 'text' ? pair.text : pair.reasoning;
|
|
101
|
-
const cellKind = kind === 'text' ? 'assistant' : 'reasoning';
|
|
102
|
-
if (slot === undefined) {
|
|
103
|
-
const next = cells.length;
|
|
104
|
-
cells.push({
|
|
105
|
-
key: `assistant:${key}:${kind}`,
|
|
106
|
-
kind: cellKind,
|
|
107
|
-
...(!complete && kind === 'text' ? { pending: true } : {}),
|
|
108
|
-
text,
|
|
109
|
-
...(complete && kind === 'reasoning' ? { collapsed: true } : {}),
|
|
110
|
-
});
|
|
111
|
-
if (kind === 'text')
|
|
112
|
-
pair.text = next;
|
|
113
|
-
else
|
|
114
|
-
pair.reasoning = next;
|
|
115
|
-
assistants.set(key, pair);
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const previous = cells[slot];
|
|
119
|
-
if (previous === undefined)
|
|
120
|
-
return;
|
|
121
|
-
const { pending: _pending, ...settled } = previous;
|
|
122
|
-
cells[slot] = {
|
|
123
|
-
...(complete ? settled : previous),
|
|
124
|
-
text: complete ? text : previous.text + text,
|
|
125
|
-
...(complete && kind === 'reasoning' ? { collapsed: true } : {}),
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
148
|
for (const event of events) {
|
|
129
149
|
switch (event.type) {
|
|
150
|
+
case 'system/message':
|
|
151
|
+
break;
|
|
130
152
|
case 'turn/start':
|
|
131
153
|
truncatedPrefix = false;
|
|
132
154
|
openTurns.add(event.data.turn);
|
|
@@ -160,25 +182,14 @@ export function foldCells(events, presenter = createToolPresenter(() => undefine
|
|
|
160
182
|
});
|
|
161
183
|
break;
|
|
162
184
|
}
|
|
163
|
-
case 'assistant/chunk': {
|
|
164
|
-
const { chunk, step, turn } = event.data;
|
|
165
|
-
if (chunk.type === 'text-delta')
|
|
166
|
-
putAssistant(turn, step, 'text', chunk.text, false);
|
|
167
|
-
else if (chunk.type === 'reasoning-delta')
|
|
168
|
-
putAssistant(turn, step, 'reasoning', chunk.text, false);
|
|
169
|
-
else if (chunk.type === 'block-end' && (chunk.block.type === 'text' || chunk.block.type === 'reasoning')) {
|
|
170
|
-
putAssistant(turn, step, chunk.block.type, chunk.block.text, true);
|
|
171
|
-
}
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
185
|
case 'assistant/message': {
|
|
175
186
|
const { message, step, turn } = event.data;
|
|
176
187
|
const text = blockText(message.content, 'text');
|
|
177
188
|
const reasoning = blockText(message.content, 'reasoning');
|
|
178
189
|
if (reasoning !== '')
|
|
179
|
-
putAssistant(turn, step, 'reasoning', reasoning, true);
|
|
190
|
+
putAssistant(cells, assistants, turn, step, 'reasoning', reasoning, true);
|
|
180
191
|
if (text !== '')
|
|
181
|
-
putAssistant(turn, step, 'text', text, true);
|
|
192
|
+
putAssistant(cells, assistants, turn, step, 'text', text, true);
|
|
182
193
|
break;
|
|
183
194
|
}
|
|
184
195
|
case 'tool/call': {
|
|
@@ -299,6 +310,8 @@ export function foldCells(events, presenter = createToolPresenter(() => undefine
|
|
|
299
310
|
break;
|
|
300
311
|
}
|
|
301
312
|
case 'turn/end':
|
|
313
|
+
if (event.data.reason.kind === 'interrupted')
|
|
314
|
+
break;
|
|
302
315
|
if (!openTurns.delete(event.data.turn)) {
|
|
303
316
|
if (!truncatedPrefix) {
|
|
304
317
|
cells.push({ key: `${event.seq}:error`, kind: 'error', text: `turn ${event.data.turn} ended without starting` });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antst/dashi",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "A terminal UI for DeepSeek Harness",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"lib/**/*.js",
|
|
28
|
-
"lib/**/*.d.ts"
|
|
29
|
-
"validated-dsh-versions.json"
|
|
28
|
+
"lib/**/*.d.ts"
|
|
30
29
|
],
|
|
31
30
|
"license": "MIT",
|
|
32
31
|
"engines": {
|
|
@@ -36,35 +35,41 @@
|
|
|
36
35
|
"@earendil-works/pi-tui": "0.84.4"
|
|
37
36
|
},
|
|
38
37
|
"peerDependencies": {
|
|
39
|
-
"@deepseek-ai/cordis": "4.0.2",
|
|
40
|
-
"@deepseek-ai/cordis-plugin-loader": "1.0.3",
|
|
41
|
-
"@deepseek-ai/dsh-agent": "0.1.
|
|
42
|
-
"@deepseek-ai/dsh-agent-instructions": "0.1.
|
|
43
|
-
"@deepseek-ai/dsh-agent-presets": "0.1.
|
|
44
|
-
"@deepseek-ai/dsh-api-session-controller": "0.1.
|
|
45
|
-
"@deepseek-ai/dsh-attachment": "0.1.
|
|
46
|
-
"@deepseek-ai/dsh-
|
|
47
|
-
"@deepseek-ai/dsh-
|
|
48
|
-
"@deepseek-ai/dsh-
|
|
49
|
-
"@deepseek-ai/dsh-
|
|
50
|
-
"@deepseek-ai/dsh-
|
|
51
|
-
"@deepseek-ai/dsh-
|
|
52
|
-
"@deepseek-ai/dsh-
|
|
53
|
-
"@deepseek-ai/dsh-
|
|
54
|
-
"@deepseek-ai/dsh-
|
|
55
|
-
"@deepseek-ai/dsh-
|
|
56
|
-
"@deepseek-ai/dsh-
|
|
57
|
-
"@deepseek-ai/dsh-
|
|
58
|
-
"@deepseek-ai/dsh-
|
|
59
|
-
"@deepseek-ai/dsh-
|
|
60
|
-
"@deepseek-ai/dsh-
|
|
61
|
-
"@deepseek-ai/dsh-
|
|
62
|
-
"@deepseek-ai/dsh-
|
|
63
|
-
"@deepseek-ai/dsh-
|
|
64
|
-
"@deepseek-ai/dsh-
|
|
65
|
-
"@deepseek-ai/dsh-
|
|
66
|
-
"@deepseek-ai/dsh-
|
|
67
|
-
"@deepseek-ai/dsh-
|
|
68
|
-
"@deepseek-ai/dsh-
|
|
38
|
+
"@deepseek-ai/cordis": "^4.0.2",
|
|
39
|
+
"@deepseek-ai/cordis-plugin-loader": "^1.0.3",
|
|
40
|
+
"@deepseek-ai/dsh-agent": ">=0.1.5-rc.2",
|
|
41
|
+
"@deepseek-ai/dsh-agent-instructions": ">=0.1.5-rc.2",
|
|
42
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.1.5-rc.2",
|
|
43
|
+
"@deepseek-ai/dsh-api-session-controller": ">=0.1.5-rc.2",
|
|
44
|
+
"@deepseek-ai/dsh-attachment": ">=0.1.5-rc.2",
|
|
45
|
+
"@deepseek-ai/dsh-authorization": ">=0.1.5-rc.2",
|
|
46
|
+
"@deepseek-ai/dsh-cmdline": ">=0.1.5-rc.2",
|
|
47
|
+
"@deepseek-ai/dsh-commands": ">=0.1.5-rc.2",
|
|
48
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.5-rc.2",
|
|
49
|
+
"@deepseek-ai/dsh-compaction": ">=0.1.5-rc.2",
|
|
50
|
+
"@deepseek-ai/dsh-file-reference": ">=0.1.5-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-fs": ">=0.1.5-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-home-paths": ">=0.1.5-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-host-plugin-inventory": ">=0.1.5-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-jobs": ">=0.1.5-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-llm": ">=0.1.5-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-permission-presets": ">=0.1.5-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-plan-mode": ">=0.1.5-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-sandbox-policy": ">=0.1.5-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-schedule": ">=0.1.5-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-session": ">=0.1.5-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-session-projection": ">=0.1.5-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-session-query": ">=0.1.5-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-session-stats": ">=0.1.5-rc.2",
|
|
64
|
+
"@deepseek-ai/dsh-settings": ">=0.1.5-rc.2",
|
|
65
|
+
"@deepseek-ai/dsh-shell": ">=0.1.5-rc.2",
|
|
66
|
+
"@deepseek-ai/dsh-skill": ">=0.1.5-rc.2",
|
|
67
|
+
"@deepseek-ai/dsh-subagent": ">=0.1.5-rc.2",
|
|
68
|
+
"@deepseek-ai/dsh-system-prompt": ">=0.1.5-rc.2",
|
|
69
|
+
"@deepseek-ai/dsh-token-meter": ">=0.1.5-rc.2",
|
|
70
|
+
"@deepseek-ai/dsh-tool-todo": ">=0.1.5-rc.2",
|
|
71
|
+
"@deepseek-ai/dsh-tools": ">=0.1.5-rc.2",
|
|
72
|
+
"@deepseek-ai/dsh-user-approval": ">=0.1.5-rc.2",
|
|
73
|
+
"@deepseek-ai/dsh-user-questions": ">=0.1.5-rc.2"
|
|
69
74
|
}
|
|
70
75
|
}
|