@antst/dashi 0.1.0-alpha.6 → 0.1.0-alpha.7

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/lib/index.js CHANGED
@@ -19,6 +19,10 @@ function parseArgs(args) {
19
19
  let accessible = false;
20
20
  let inline = true;
21
21
  let name;
22
+ let effort;
23
+ let model;
24
+ let permission;
25
+ let provider;
22
26
  let resume;
23
27
  let resumeAll = false;
24
28
  let resumePicker = false;
@@ -33,14 +37,23 @@ function parseArgs(args) {
33
37
  inline = true;
34
38
  else if (argument === '--fullscreen')
35
39
  inline = false;
36
- else if (argument === '--name' || argument === '--image') {
40
+ else if (argument === '--name' || argument === '--image' || argument === '--effort'
41
+ || argument === '--model' || argument === '--permission' || argument === '--provider') {
37
42
  const value = args[++index];
38
43
  if (value === undefined || value === '')
39
44
  return undefined;
40
45
  if (argument === '--name')
41
46
  name = value;
42
- else
47
+ else if (argument === '--image')
43
48
  images.push(value);
49
+ else if (argument === '--effort')
50
+ effort = value;
51
+ else if (argument === '--model')
52
+ model = value;
53
+ else if (argument === '--permission')
54
+ permission = value;
55
+ else
56
+ provider = value;
44
57
  }
45
58
  else if (argument === '--resume' || argument === '-r') {
46
59
  const value = args[index + 1];
@@ -55,6 +68,9 @@ function parseArgs(args) {
55
68
  resumeAll = true;
56
69
  else if (argument === '--continue' || argument === '-c')
57
70
  useContinue = true;
71
+ else if (argument === '--yolo' || argument === '--dangerously-skip-permissions') {
72
+ permission = 'danger-full-access';
73
+ }
58
74
  else if (argument?.startsWith('-') === true)
59
75
  return undefined;
60
76
  else if (argument !== undefined)
@@ -62,7 +78,8 @@ function parseArgs(args) {
62
78
  }
63
79
  if (resume !== undefined && (resumePicker || useContinue) || resumePicker && useContinue
64
80
  || name !== undefined && (resume !== undefined || resumePicker || useContinue)
65
- || resumeAll && resume === undefined && !resumePicker || resumeAll && useContinue)
81
+ || resumeAll && resume === undefined && !resumePicker || resumeAll && useContinue
82
+ || provider !== undefined && model === undefined)
66
83
  return undefined;
67
84
  return {
68
85
  accessible,
@@ -71,8 +88,12 @@ function parseArgs(args) {
71
88
  resumeAll,
72
89
  resumePicker,
73
90
  ...(images.length === 0 ? {} : { images }),
91
+ ...(effort === undefined ? {} : { effort }),
92
+ ...(model === undefined ? {} : { model }),
74
93
  ...(name === undefined ? {} : { name }),
94
+ ...(permission === undefined ? {} : { permission }),
75
95
  ...(prompt.length === 0 ? {} : { prompt: prompt.join(' ') }),
96
+ ...(provider === undefined ? {} : { provider }),
76
97
  ...(resume === undefined ? {} : { resume }),
77
98
  };
78
99
  }
package/lib/renderer.js CHANGED
@@ -65,7 +65,12 @@ function cellText(cell, toolMode, accessible, now = Date.now()) {
65
65
  : accessible ? '[done]' : '◆';
66
66
  return `${cell.pending === true ? YELLOW : DIM}${marker} ${safe}${elapsed === undefined ? '' : ` · ${duration(elapsed)}`}${RESET}`;
67
67
  }
68
- case 'context': return `${DIM}Context · ${safe}${RESET}`;
68
+ case 'context': {
69
+ if (cell.collapsed !== true || cell.detail === undefined)
70
+ return `${DIM}Context · ${safe}${RESET}`;
71
+ const head = `${DIM}Context · ${plain(cell.detail, true)}${RESET}`;
72
+ return toolMode === 'expanded' ? `${head}\n${safe}` : head;
73
+ }
69
74
  case 'shell': return `${DIM}Shell${RESET}\n${safe}`;
70
75
  case 'compaction': return `${DIM}${accessible ? '[compacted]' : '↻'} ${safe}${RESET}`;
71
76
  case 'reasoning': return cell.collapsed
@@ -4,9 +4,13 @@ import type { TuiRoot } from './tui-root.js';
4
4
  export interface RootLaunchOptions {
5
5
  readonly continue: boolean;
6
6
  readonly cwd: string;
7
+ readonly effort?: string;
7
8
  readonly name?: string;
8
9
  readonly images?: readonly string[];
10
+ readonly model?: string;
11
+ readonly permission?: string;
9
12
  readonly prompt?: string;
13
+ readonly provider?: string;
10
14
  readonly resume?: string;
11
15
  }
12
16
  export interface SessionRuntime {
@@ -775,6 +775,34 @@ export async function createSessionRuntime(ctx, options, tuiRoot, dispatch, deci
775
775
  await bound.controlPump;
776
776
  }
777
777
  await install(binding);
778
+ if (options.model !== undefined || options.effort !== undefined) {
779
+ const catalog = await ctx.sessionController.modelCatalog();
780
+ const currentSelection = currentModel(ctx, binding.agent) ?? catalog.default;
781
+ const model = options.model ?? currentSelection.model;
782
+ const candidates = catalog.groups.filter(group => group.models.some(item => item.id === model));
783
+ if (options.provider === undefined && candidates.length > 1) {
784
+ throw new Error(`model "${model}" is available from multiple providers: ${candidates.map(group => group.id).join(', ')}; pass --provider`);
785
+ }
786
+ const result = await ctx.sessionController.selectModel({
787
+ sessionId: binding.agent.id,
788
+ model,
789
+ provider: options.provider ?? candidates[0]?.id ?? currentSelection.provider,
790
+ ...(options.effort === undefined ? {} : { reasoningEffort: options.effort }),
791
+ });
792
+ const { effort: _previousEffort, ...root } = binding.root;
793
+ binding.root = {
794
+ ...root, model: result.selected.model, provider: result.selected.provider,
795
+ ...(result.selected.reasoningEffort === undefined ? {} : { effort: result.selected.reasoningEffort }),
796
+ };
797
+ }
798
+ if (options.permission !== undefined) {
799
+ const execution = await ctx.commands.execute(binding.agent, `/permission ${options.permission}`, [], lifetime.signal);
800
+ if (execution === undefined)
801
+ throw new Error('DSH supplied no /permission command');
802
+ if (execution.result.kind === 'error')
803
+ throw new Error(execution.result.text ?? 'permission change failed');
804
+ binding.root = { ...binding.root, permission: options.permission };
805
+ }
778
806
  tuiRoot.bind(binding.agent);
779
807
  const activate = async (value) => {
780
808
  try {
package/lib/state.js CHANGED
@@ -39,7 +39,7 @@ function help() {
39
39
  'Ctrl+B activity details for jobs and subagents',
40
40
  '@ paths require DSH file-reference · Ctrl+V pastes an image · Backspace removes it',
41
41
  'Ctrl+S stash · Ctrl+G editor · F1 help · Ctrl+L redraw · Ctrl+Z suspend',
42
- '/new /clear /resume [--all] [NAME|UUID] /fork /rewind /rename /model /permission /agents /queue · launch -r/-c',
42
+ '/new /clear /resume [--all] [NAME|UUID] /fork /rewind /rename /model /permission /agents /queue · launch -r/-c --model/--effort/--permission/--yolo',
43
43
  '/status /context /tasks /history /export /copy /exit',
44
44
  ],
45
45
  };
package/lib/transcript.js CHANGED
@@ -26,6 +26,23 @@ function shellCell(message, pending) {
26
26
  key: `shell:${String(message.id)}`, kind: 'shell', pending, text: messageText(message.content),
27
27
  };
28
28
  }
29
+ function collapsedContextCell(message, key) {
30
+ const source = message.source;
31
+ const form = source.form;
32
+ if (source.kind !== 'plugin' || !['instructions', 'catalog', 'snapshot', 'notice', 'recall'].includes(String(form))) {
33
+ return undefined;
34
+ }
35
+ const text = messageText(message.content);
36
+ const lines = text.split(/\r?\n/u);
37
+ const first = form === 'notice' && typeof source.summary === 'string' ? source.summary : lines[0] ?? '';
38
+ return {
39
+ collapsed: true,
40
+ detail: `${String(form)} · ${first.trim()} · ${String(lines.length)} lines`,
41
+ key,
42
+ kind: 'context',
43
+ text,
44
+ };
45
+ }
29
46
  /** Project DSH-owned pending injections beside the durable transcript. */
30
47
  export function pendingShellCells(messages) {
31
48
  return messages.filter(isDashiShell).map(message => shellCell(message, true));
@@ -132,9 +149,10 @@ export function foldCells(events, presenter = createToolPresenter(() => undefine
132
149
  break;
133
150
  }
134
151
  const text = messageText(event.data.content);
152
+ const context = collapsedContextCell(event.data, `${event.seq}:context`);
135
153
  cells.push(isDashiShell(event.data)
136
154
  ? shellCell(event.data, false)
137
- : {
155
+ : context ?? {
138
156
  key: `${event.seq}:user`,
139
157
  kind: event.data.source.kind === 'user' ? 'user' : 'context',
140
158
  text,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antst/dashi",
3
- "version": "0.1.0-alpha.6",
3
+ "version": "0.1.0-alpha.7",
4
4
  "description": "A terminal UI for DeepSeek Harness",
5
5
  "publishConfig": {
6
6
  "access": "public"