@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.
@@ -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]>;
@@ -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({ session: agent.session }),
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 type: 'copy-latest';
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: 'collapsed',
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
- '/status /context /memory /config /diff /plugins /plugin /tasks /history /export /copy /exit',
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 latestCompletedAssistant(cells) {
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
- if (state.exitArmed)
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
- if (state.root?.status !== 'idle' || state.attachments.length > 0)
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.kind === 'info' ? 0 : state.overlay.cursor + action.offset, count);
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
- return [{
387
- ...state, overlay: { ...overlay, expanded: !overlay.expanded },
388
- }, redraw()];
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-latest': {
640
- const cell = latestCompletedAssistant(state.cells);
641
- return cell === undefined ? [state, []] : [state, [{ type: 'copy', text: cell.text }]];
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
  }
@@ -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-alpha.8",
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.2-rc.1",
42
- "@deepseek-ai/dsh-agent-instructions": "0.1.2-rc.1",
43
- "@deepseek-ai/dsh-agent-presets": "0.1.2-rc.1",
44
- "@deepseek-ai/dsh-api-session-controller": "0.1.2-rc.1",
45
- "@deepseek-ai/dsh-attachment": "0.1.2-rc.1",
46
- "@deepseek-ai/dsh-cmdline": "0.1.2-rc.1",
47
- "@deepseek-ai/dsh-commands": "0.1.2-rc.1",
48
- "@deepseek-ai/dsh-compaction": "0.1.2-rc.1",
49
- "@deepseek-ai/dsh-file-reference": "0.1.2-rc.1",
50
- "@deepseek-ai/dsh-fs": "0.1.2-rc.1",
51
- "@deepseek-ai/dsh-home-paths": "0.1.2-rc.1",
52
- "@deepseek-ai/dsh-host-plugin-inventory": "0.1.2-rc.1",
53
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1",
54
- "@deepseek-ai/dsh-permission-presets": "0.1.2-rc.1",
55
- "@deepseek-ai/dsh-plan-mode": "0.1.2-rc.1",
56
- "@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
57
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
58
- "@deepseek-ai/dsh-session-projection": "0.1.2-rc.1",
59
- "@deepseek-ai/dsh-session-query": "0.1.2-rc.1",
60
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1",
61
- "@deepseek-ai/dsh-shell": "0.1.2-rc.1",
62
- "@deepseek-ai/dsh-skill": "0.1.2-rc.1",
63
- "@deepseek-ai/dsh-subagent": "0.1.2-rc.1",
64
- "@deepseek-ai/dsh-token-meter": "0.1.2-rc.1",
65
- "@deepseek-ai/dsh-tool-todo": "0.1.2-rc.1",
66
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
67
- "@deepseek-ai/dsh-user-approval": "0.1.2-rc.1",
68
- "@deepseek-ai/dsh-user-questions": "0.1.2-rc.1"
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
  }
@@ -1,3 +0,0 @@
1
- [
2
- "0.1.2-rc.1"
3
- ]