@antst/dashi 0.1.0-alpha.17 → 0.1.0-alpha.18

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 CHANGED
@@ -6,7 +6,7 @@ via `@antst/dashi-app`, not as a standalone dependency:
6
6
  Install the exact validated DSH release and start dashi:
7
7
 
8
8
  ```sh
9
- pnpm install @deepseek-ai/dsh@0.1.2-rc.1
9
+ pnpm install @deepseek-ai/dsh@0.1.5-rc.2
10
10
  dsh plugin --profile dashi add @antst/dashi-app
11
11
  dsh --profile dashi
12
12
  ```
@@ -19,7 +19,7 @@ dashi validates each DSH release before adopting it, and its packages pin DSH
19
19
  dependencies exactly.
20
20
 
21
21
  Status: pre-release alpha. Interfaces and behavior may change between
22
- alpha versions; the validated DSH version is `0.1.2-rc.1`.
22
+ alpha versions; the validated DSH version is `0.1.5-rc.2`.
23
23
 
24
24
  Full documentation, source, and issue tracker:
25
25
  https://forgejo.antst.net/ai/dashi
package/lib/diff-view.js CHANGED
@@ -1,12 +1,18 @@
1
1
  import { HUMAN_SHELL_STREAM_BYTES } from './shell-command.js';
2
2
  import { boundedBody } from './tool-presentation.js';
3
3
  import { foldCells } from './transcript.js';
4
+ import { latestCompletedTurn } from './rewind.js';
4
5
  export async function diffOverlay(ctx, agent, presenter, mode, signal) {
5
6
  if (mode === 'turn') {
6
7
  const events = agent.session.snapshotEvents();
7
- const start = events.map(event => event.type).lastIndexOf('turn/start');
8
- const cells = (start < 0 ? [] : foldCells(events.slice(start), presenter)).filter(cell => cell.pending !== true && cell.tool?.card === 'diff' && (cell.tool.diffs?.length ?? 0) > 0);
9
- return { cells, kind: 'info', lines: cells.length === 0 ? ['No write/edit changes in the last turn.'] : [], title: 'Last turn diff' };
8
+ const boundary = latestCompletedTurn(events);
9
+ const end = boundary.atSeq === undefined ? -1 : events.findIndex(event => event.seq === boundary.atSeq);
10
+ let start = end;
11
+ while (start >= 0 && events[start]?.type !== 'turn/start')
12
+ start--;
13
+ const cells = (start < 0 ? [] : foldCells(events.slice(start, end + 1), presenter)).filter(cell => cell.pending !== true && cell.tool?.card === 'diff' && (cell.tool.diffs?.length ?? 0) > 0);
14
+ return { cells, kind: 'info', lines: cells.length === 0 ? ['No write/edit changes in the last completed turn.'] : [],
15
+ title: `Last completed turn diff${boundary.open ? ' · trailing turn open' : ''}` };
10
16
  }
11
17
  const command = 'git diff --no-ext-diff --no-color HEAD --';
12
18
  const result = await ctx.shell.run(ctx.shell.resolve({
@@ -1,4 +1,4 @@
1
1
  import type { SessionHistoryRecord } from '@deepseek-ai/dsh-api-session-controller';
2
- import { type SessionEvent } from '@deepseek-ai/dsh-session';
3
- /** Expand the Controller's compact history wire records to canonical Session events. */
2
+ import type { SessionEvent } from '@deepseek-ai/dsh-session';
3
+ /** Read the Controller's canonical Session event history. */
4
4
  export declare function eventsFromRecords(records: readonly SessionHistoryRecord[]): SessionEvent[];
@@ -1,14 +1,4 @@
1
- import { decodeStorageRecord } from '@deepseek-ai/dsh-session';
2
- /** Expand the Controller's compact history wire records to canonical Session events. */
1
+ /** Read the Controller's canonical Session event history. */
3
2
  export function eventsFromRecords(records) {
4
- return records.flatMap((record) => {
5
- if (record.type === 'event')
6
- return [record.event];
7
- const encoded = record.event.type === 'chunkrow/text-chunks'
8
- ? { type: 'text-chunks', seq0: record.event.seq, time0: record.event.time, data: record.event.data }
9
- : record.event.type === 'chunkrow/reasoning-chunks'
10
- ? { type: 'reasoning-chunks', seq0: record.event.seq, time0: record.event.time, data: record.event.data }
11
- : { type: 'tool-call-chunks', seq0: record.event.seq, time0: record.event.time, data: record.event.data };
12
- return decodeStorageRecord(encoded);
13
- });
3
+ return records.map(record => record.event);
14
4
  }
package/lib/rewind.d.ts CHANGED
@@ -6,6 +6,11 @@ export interface RewindBoundary {
6
6
  readonly label: string;
7
7
  readonly prompt: string;
8
8
  }
9
+ export declare function latestCompletedTurn(events: readonly SessionEvent[]): {
10
+ readonly atSeq?: number;
11
+ readonly open: boolean;
12
+ readonly turn?: number;
13
+ };
9
14
  /** Return only a selection that DSH recorded for the source session. */
10
15
  export declare function rewindModelSelection(projection: {
11
16
  readonly lastUsed: ModelSelection | null;
package/lib/rewind.js CHANGED
@@ -1,3 +1,9 @@
1
+ export function latestCompletedTurn(events) {
2
+ const end = events.filter((event) => event.type === 'turn/end' && event.data.reason.kind !== 'interrupted').at(-1);
3
+ const start = events.filter((event) => event.type === 'turn/start').at(-1);
4
+ return { open: start !== undefined && (end === undefined || start.seq > end.seq),
5
+ ...(end === undefined ? {} : { atSeq: end.seq, turn: end.data.turn }) };
6
+ }
1
7
  /** Return only a selection that DSH recorded for the source session. */
2
8
  export function rewindModelSelection(projection) {
3
9
  return projection?.next ?? projection?.lastUsed ?? undefined;
@@ -44,7 +50,7 @@ export function rewindBoundaries(events) {
44
50
  openTurn = event.data.turn;
45
51
  prompted = false;
46
52
  }
47
- else if (event.type === 'turn/end') {
53
+ else if (event.type === 'turn/end' && event.data.reason.kind !== 'interrupted') {
48
54
  previousEnd = event;
49
55
  openTurn = undefined;
50
56
  prompted = false;
@@ -65,6 +71,7 @@ export function rewindBoundaries(events) {
65
71
  }
66
72
  export function rewindOverlay(events, roller) {
67
73
  const boundaries = rewindBoundaries(events);
74
+ const trailing = latestCompletedTurn(events);
68
75
  return {
69
76
  cursor: Math.max(0, boundaries.length - 1),
70
77
  kind: 'list',
@@ -76,7 +83,7 @@ export function rewindOverlay(events, roller) {
76
83
  },
77
84
  })),
78
85
  purpose: 'rewind',
79
- title: 'Rewind to a prompt',
86
+ title: `Rewind to a prompt${trailing.open ? ' · trailing turn open; completed boundaries only' : ''}`,
80
87
  };
81
88
  }
82
89
  export function rewindActionOverlay(boundary) {
@@ -3,19 +3,20 @@ import { AuthorizationDeclinedError } from '@deepseek-ai/dsh-authorization';
3
3
  import { parseCredentialKey } from '@deepseek-ai/dsh-credentials';
4
4
  import { JobId } from '@deepseek-ai/dsh-jobs';
5
5
  import { createUserMessage, ToolCallId } from '@deepseek-ai/dsh-llm';
6
+ import { expandAssistantStream } from '@deepseek-ai/dsh-llm/assistant-stream';
6
7
  import { SessionId, SessionSeq } from '@deepseek-ai/dsh-session';
7
8
  import { agentPresetOverlay, completionOptions, contextOverlay, currentModel, modelOverlay, permissionOverlay, searchOverlay, sessionStatusLine, sessionOverlay, skillOverlay, statusOverlay, usageOverlay, } from './catalogs.js';
8
9
  import { diffOverlay } from './diff-view.js';
9
10
  import { eventsFromRecords } from './history-records.js';
10
11
  import { admitDraftImages, encodeDraftImages, readDraftImages } from './image-input.js';
11
12
  import { contextPercent, jobViews, subagentViews } from './presentation.js';
12
- import { historyInput, historyInputs, humanPrompt, inheritedTurn, rewindActionOverlay, rewindOverlay, rewindModelSelection, } from './rewind.js';
13
+ import { historyInput, historyInputs, humanPrompt, inheritedTurn, latestCompletedTurn, rewindActionOverlay, rewindOverlay, rewindModelSelection, } from './rewind.js';
13
14
  import { createToolPresenter } from './tool-presentation.js';
14
15
  import { quoteShellWord, runHumanShell } from './shell-command.js';
15
16
  import { markdownTranscript } from './session-export.js';
16
17
  import { isSessionId, sessionMatches, sessionNotFound } from './session-list.js';
17
18
  import { memoryOverlay } from './memory.js';
18
- import { foldCells, pendingShellCells } from './transcript.js';
19
+ import { foldAssistantStream, foldCells, pendingShellCells } from './transcript.js';
19
20
  export class LaunchArgumentError extends Error {
20
21
  }
21
22
  function starterAgents(cwd) {
@@ -60,6 +61,20 @@ function turnStartTime(events, turn) {
60
61
  return event.time;
61
62
  }
62
63
  }
64
+ function latestStep(events) {
65
+ for (let index = events.length - 1; index >= 0; index--) {
66
+ const event = events[index];
67
+ if (event?.type === 'step/start')
68
+ return event;
69
+ }
70
+ }
71
+ function openingStream(baseline) {
72
+ const attempt = baseline?.activeAttempt;
73
+ if (attempt === undefined)
74
+ return [];
75
+ return expandAssistantStream(attempt.stream).slice(0, attempt.nextIndex)
76
+ .reduce((cells, member) => foldAssistantStream(cells, attempt.turn, attempt.step, member.chunk), []);
77
+ }
63
78
  function titleFromEvent(event) {
64
79
  if (String(event.type) !== 'session/title')
65
80
  return undefined;
@@ -164,7 +179,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
164
179
  title = (await ctx.sessionController.rename({ sessionId, title: name })).title;
165
180
  await ctx.sessions.flush(agent.session);
166
181
  const iterator = ctx.sessionController.follow({
167
- address: { kind: 'session', sessionId }, maxMessages: 50,
182
+ address: { kind: 'session', sessionId }, assistantStream: true, maxMessages: 50,
168
183
  }, abort.signal)[Symbol.asyncIterator]();
169
184
  const controlIterator = ctx.sessionController.control(abort.signal)[Symbol.asyncIterator]();
170
185
  const [opening, controlOpening, subagents, repo] = await Promise.all([
@@ -190,6 +205,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
190
205
  iterator,
191
206
  presenter: createToolPresenter(tool => ctx.tools.get(tool, agent)),
192
207
  presentationTimer: undefined,
208
+ streamCells: openingStream(opening.assistantStream),
193
209
  root: {
194
210
  ...(initialContextPercent === undefined ? {} : { contextPercent: initialContextPercent }),
195
211
  cwd: opening.header.cwd ?? options.cwd,
@@ -222,7 +238,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
222
238
  };
223
239
  const executeAccepted = async (bound, line, images, onSettled) => {
224
240
  const from = bound.agent.session.seq;
225
- const execution = ctx.commands.execute(bound.agent, line, images, lifetime.signal);
241
+ const execution = ctx.commands.execute(bound.agent, line, images.map(image => ({ type: 'image', ...image })), lifetime.signal);
226
242
  const accepted = bound.agent.session.snapshotEvents(from).some(event => event.type === 'command/run');
227
243
  if (!accepted) {
228
244
  const result = await execution;
@@ -260,6 +276,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
260
276
  });
261
277
  const transcriptCells = (bound) => [
262
278
  ...foldCells(bound.events, bound.presenter, { truncatedStart: bound.hasMore }),
279
+ ...bound.streamCells,
263
280
  ...pendingShellCells(bound.agent.inbox.nextStep),
264
281
  ];
265
282
  const publish = (bound) => {
@@ -299,10 +316,25 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
299
316
  dispatch({ type: 'redraw' });
300
317
  };
301
318
  const consume = (bound, frame) => {
319
+ if (frame.type === 'assistant-stream') {
320
+ if (frame.frame.type !== 'chunk') {
321
+ bound.streamCells = [];
322
+ schedule(bound);
323
+ return;
324
+ }
325
+ const step = latestStep(bound.events);
326
+ if (step === undefined)
327
+ return;
328
+ bound.streamCells = foldAssistantStream(bound.streamCells, step.data.turn, step.data.step, frame.frame.chunk);
329
+ schedule(bound);
330
+ return;
331
+ }
302
332
  const [event] = eventsFromRecords([frame]);
303
333
  if (event === undefined)
304
334
  return;
305
335
  bound.events.push(event);
336
+ if (event.type === 'assistant/message' || event.type === 'assistant/attempt')
337
+ bound.streamCells = [];
306
338
  if (event.type === 'turn/end') {
307
339
  void refreshRepo(bound);
308
340
  const startedAt = turnStartTime(bound.events, event.data.turn);
@@ -589,7 +621,12 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
589
621
  return stale;
590
622
  if (prompt === '')
591
623
  return { kind: 'error', text: 'usage: /btw TEXT' };
592
- const forked = await ctx.sessionController.fork({ sessionId: bound.agent.id });
624
+ if (bound.agent.status !== 'idle')
625
+ return { kind: 'error', text: 'finish or interrupt the turn first' };
626
+ const boundary = latestCompletedTurn(bound.agent.session.snapshotEvents());
627
+ if (boundary.atSeq === undefined)
628
+ throw new Error('the current session has no completed turn to fork');
629
+ const forked = await ctx.sessionController.fork({ atSeq: boundary.atSeq, sessionId: bound.agent.id });
593
630
  const resolved = await ctx.sessionController.resolveAgent(forked.sessionId);
594
631
  if ('error' in resolved)
595
632
  throw resolved.error;
@@ -611,7 +648,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
611
648
  const next = await iterator.next();
612
649
  if (next.done === true)
613
650
  throw new Error('DSH session follow ended before the side turn completed');
614
- if (next.value.type !== 'snapshot' && eventsFromRecords([next.value])[0]?.type === 'turn/end')
651
+ if (next.value.type === 'event' && eventsFromRecords([next.value])[0]?.type === 'turn/end')
615
652
  break;
616
653
  }
617
654
  }
@@ -622,7 +659,7 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
622
659
  const cells = foldCells(child.session.snapshotEvents(from), createToolPresenter(tool => ctx.tools.get(tool, child)))
623
660
  .filter(cell => cell.kind !== 'user');
624
661
  dispatch({ type: 'open-overlay', overlay: {
625
- cells, kind: 'info', lines: [], title: `Btw · turn ${String(turn)}`,
662
+ cells, kind: 'info', lines: [], title: `Btw · turn ${String(turn)}${boundary.open ? ' · trailing turn open' : ''}`,
626
663
  } });
627
664
  return { kind: 'success' };
628
665
  };
package/lib/state.js CHANGED
@@ -576,6 +576,13 @@ export function reduce(state, action) {
576
576
  return reduce(state, { type: 'decision-submit' });
577
577
  if (state.root === undefined || state.composer === '' && state.attachments.length === 0)
578
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
+ }
579
586
  const mode = state.root.status === 'running' ? state.sendMode : 'next-turn';
580
587
  return [{
581
588
  ...state, attachments: [], composer: '', exitArmed: false, recall: undefined, rewindArmed: false,
@@ -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.17",
3
+ "version": "0.1.0-alpha.18",
4
4
  "description": "A terminal UI for DeepSeek Harness",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -38,39 +38,39 @@
38
38
  "peerDependencies": {
39
39
  "@deepseek-ai/cordis": "4.0.2",
40
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-authorization": "0.1.2-rc.1",
47
- "@deepseek-ai/dsh-cmdline": "0.1.2-rc.1",
48
- "@deepseek-ai/dsh-commands": "0.1.2-rc.1",
49
- "@deepseek-ai/dsh-credentials": "0.1.2-rc.1",
50
- "@deepseek-ai/dsh-compaction": "0.1.2-rc.1",
51
- "@deepseek-ai/dsh-file-reference": "0.1.2-rc.1",
52
- "@deepseek-ai/dsh-fs": "0.1.2-rc.1",
53
- "@deepseek-ai/dsh-home-paths": "0.1.2-rc.1",
54
- "@deepseek-ai/dsh-host-plugin-inventory": "0.1.2-rc.1",
55
- "@deepseek-ai/dsh-jobs": "0.1.2-rc.1",
56
- "@deepseek-ai/dsh-llm": "0.1.2-rc.1",
57
- "@deepseek-ai/dsh-permission-presets": "0.1.2-rc.1",
58
- "@deepseek-ai/dsh-plan-mode": "0.1.2-rc.1",
59
- "@deepseek-ai/dsh-sandbox-policy": "0.1.2-rc.1",
60
- "@deepseek-ai/dsh-schedule": "0.1.2-rc.1",
61
- "@deepseek-ai/dsh-session": "0.1.2-rc.1",
62
- "@deepseek-ai/dsh-session-projection": "0.1.2-rc.1",
63
- "@deepseek-ai/dsh-session-query": "0.1.2-rc.1",
64
- "@deepseek-ai/dsh-session-stats": "0.1.2-rc.1",
65
- "@deepseek-ai/dsh-settings": "0.1.2-rc.1",
66
- "@deepseek-ai/dsh-shell": "0.1.2-rc.1",
67
- "@deepseek-ai/dsh-skill": "0.1.2-rc.1",
68
- "@deepseek-ai/dsh-subagent": "0.1.2-rc.1",
69
- "@deepseek-ai/dsh-system-prompt": "0.1.2-rc.1",
70
- "@deepseek-ai/dsh-token-meter": "0.1.2-rc.1",
71
- "@deepseek-ai/dsh-tool-todo": "0.1.2-rc.1",
72
- "@deepseek-ai/dsh-tools": "0.1.2-rc.1",
73
- "@deepseek-ai/dsh-user-approval": "0.1.2-rc.1",
74
- "@deepseek-ai/dsh-user-questions": "0.1.2-rc.1"
41
+ "@deepseek-ai/dsh-agent": "0.1.5-rc.2",
42
+ "@deepseek-ai/dsh-agent-instructions": "0.1.5-rc.2",
43
+ "@deepseek-ai/dsh-agent-presets": "0.1.5-rc.2",
44
+ "@deepseek-ai/dsh-api-session-controller": "0.1.5-rc.2",
45
+ "@deepseek-ai/dsh-attachment": "0.1.5-rc.2",
46
+ "@deepseek-ai/dsh-authorization": "0.1.5-rc.2",
47
+ "@deepseek-ai/dsh-cmdline": "0.1.5-rc.2",
48
+ "@deepseek-ai/dsh-commands": "0.1.5-rc.2",
49
+ "@deepseek-ai/dsh-credentials": "0.1.5-rc.2",
50
+ "@deepseek-ai/dsh-compaction": "0.1.5-rc.2",
51
+ "@deepseek-ai/dsh-file-reference": "0.1.5-rc.2",
52
+ "@deepseek-ai/dsh-fs": "0.1.5-rc.2",
53
+ "@deepseek-ai/dsh-home-paths": "0.1.5-rc.2",
54
+ "@deepseek-ai/dsh-host-plugin-inventory": "0.1.5-rc.2",
55
+ "@deepseek-ai/dsh-jobs": "0.1.5-rc.2",
56
+ "@deepseek-ai/dsh-llm": "0.1.5-rc.2",
57
+ "@deepseek-ai/dsh-permission-presets": "0.1.5-rc.2",
58
+ "@deepseek-ai/dsh-plan-mode": "0.1.5-rc.2",
59
+ "@deepseek-ai/dsh-sandbox-policy": "0.1.5-rc.2",
60
+ "@deepseek-ai/dsh-schedule": "0.1.5-rc.2",
61
+ "@deepseek-ai/dsh-session": "0.1.5-rc.2",
62
+ "@deepseek-ai/dsh-session-projection": "0.1.5-rc.2",
63
+ "@deepseek-ai/dsh-session-query": "0.1.5-rc.2",
64
+ "@deepseek-ai/dsh-session-stats": "0.1.5-rc.2",
65
+ "@deepseek-ai/dsh-settings": "0.1.5-rc.2",
66
+ "@deepseek-ai/dsh-shell": "0.1.5-rc.2",
67
+ "@deepseek-ai/dsh-skill": "0.1.5-rc.2",
68
+ "@deepseek-ai/dsh-subagent": "0.1.5-rc.2",
69
+ "@deepseek-ai/dsh-system-prompt": "0.1.5-rc.2",
70
+ "@deepseek-ai/dsh-token-meter": "0.1.5-rc.2",
71
+ "@deepseek-ai/dsh-tool-todo": "0.1.5-rc.2",
72
+ "@deepseek-ai/dsh-tools": "0.1.5-rc.2",
73
+ "@deepseek-ai/dsh-user-approval": "0.1.5-rc.2",
74
+ "@deepseek-ai/dsh-user-questions": "0.1.5-rc.2"
75
75
  }
76
76
  }
@@ -1,3 +1,3 @@
1
1
  [
2
- "0.1.2-rc.1"
2
+ "0.1.5-rc.2"
3
3
  ]