dsh-ssh-tui 0.1.7 → 0.2.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.
@@ -12,10 +12,13 @@ export type SessionPickerResult = {
12
12
  kind: 'new';
13
13
  } | null;
14
14
  /**
15
- * Show the picker and wait for one digit, Enter (new session), or Esc/Ctrl+C
16
- * (cancel). Restores the terminal before resolving.
15
+ * Show the picker and wait for one digit, Enter (new session), or a lone
16
+ * Esc/Ctrl+C (cancel). Incomplete CSI/SS3 sequences are buffered briefly so
17
+ * arrow keys are ignored instead of cancelling. Restores the terminal before
18
+ * resolving; an AbortSignal cancels and restores as well.
17
19
  * @param ctx - boot context supplying sessionPersistence.
18
20
  * @param color - whether to apply ANSI colors.
21
+ * @param signal - optional abort signal (fiber dispose) to cancel the picker.
19
22
  * @returns the selection, or null when cancelled.
20
23
  */
21
- export declare function showSessionPicker(ctx: Context, color: boolean): Promise<SessionPickerResult>;
24
+ export declare function showSessionPicker(ctx: Context, color: boolean, signal?: AbortSignal): Promise<SessionPickerResult>;
@@ -11,7 +11,11 @@
11
11
  */
12
12
  import type { Agent, ModelSelection, ModelSelectionRef } from '@deepseek-ai/dsh-agent';
13
13
  import type { Context } from '@deepseek-ai/cordis';
14
+ import { type LlmCallConfig } from '@deepseek-ai/dsh-llm';
15
+ import { SessionId, type SessionEvent } from '@deepseek-ai/dsh-session';
16
+ import type { SubagentRunEndInfo, SubagentRunInfo } from '@deepseek-ai/dsh-subagent';
14
17
  import { type SubagentSelectionRef } from './subagent-model.js';
18
+ import { type AskUserQuestionAnswer, type AskUserQuestionRequest } from '@deepseek-ai/dsh-user-questions';
15
19
  /** Presentation configuration for the terminal channel. */
16
20
  export interface TuiConfig {
17
21
  /** Exact shared agent/session identity driven by this terminal. */
@@ -47,6 +51,17 @@ export interface TuiConfig {
47
51
  /** Open the history-session picker immediately after mounting (--resume). */
48
52
  resumePicker?: boolean;
49
53
  }
54
+ type SubagentLogKind = 'user' | 'assistant' | 'tool' | 'result' | 'turn' | 'approval' | 'team' | 'system';
55
+ /** One child-session event folded into a parent-side subagent card. */
56
+ export interface SubagentLogEntry {
57
+ kind: SubagentLogKind;
58
+ text: string;
59
+ }
60
+ /** One todo-list item as the plan card renders it. */
61
+ export interface PlanTodoItem {
62
+ content: string;
63
+ status: 'pending' | 'in_progress' | 'completed';
64
+ }
50
65
  type Row = {
51
66
  kind: 'user';
52
67
  text: string;
@@ -77,6 +92,42 @@ type Row = {
77
92
  exitCode?: number;
78
93
  signal?: string;
79
94
  expanded: boolean;
95
+ } | {
96
+ kind: 'subagent';
97
+ sessionId: string;
98
+ runId: string;
99
+ provider: string;
100
+ local: boolean;
101
+ label: string;
102
+ status: 'running' | 'ok' | 'error' | 'aborted';
103
+ startedAt: number;
104
+ endedAt?: number;
105
+ stopReason?: string;
106
+ lastActivity: string;
107
+ logs: SubagentLogEntry[];
108
+ expanded: boolean;
109
+ } | {
110
+ kind: 'plan';
111
+ active: boolean;
112
+ pending: boolean;
113
+ todos: PlanTodoItem[];
114
+ expanded: boolean;
115
+ } | {
116
+ kind: 'question';
117
+ questionId: string;
118
+ title: string;
119
+ header?: string;
120
+ detail?: string;
121
+ intent: 'ask' | 'plan-review';
122
+ status: 'waiting' | 'answered' | 'cancelled';
123
+ summary: string;
124
+ expanded: boolean;
125
+ } | {
126
+ kind: 'goal';
127
+ objective: string;
128
+ phase: 'active' | 'paused' | 'blocked' | 'complete' | 'cleared';
129
+ blockedReason?: string;
130
+ expanded: boolean;
80
131
  } | {
81
132
  kind: 'system';
82
133
  text: string;
@@ -132,6 +183,18 @@ export interface OpenCodeSource {
132
183
  export declare function openCodeSourceFor(provider: string, llmPiAiSection: unknown): OpenCodeSource | null;
133
184
  /** Render the OpenCode Go quota payload as a transcript block. */
134
185
  export declare function formatOpenCodeGoUsage(payload: unknown, source: OpenCodeSource): string;
186
+ /** Whether `text` could still grow into a recognized escape sequence. */
187
+ export declare function isEscapePrefix(text: string): boolean;
188
+ /** Parse a todo_write payload into displayable plan items. */
189
+ export declare function parsePlanTodos(value: unknown): PlanTodoItem[];
190
+ /** Compact todo-list summary: done/total plus the first in-progress task. */
191
+ export declare function todoSummary(value: unknown): string;
192
+ /** Compact ask_user_question summary from tool arguments. */
193
+ export declare function askSummary(value: unknown): string;
194
+ /** One-line subagent card header used while collapsed. */
195
+ export declare function subagentHeaderText(row: Extract<Row, {
196
+ kind: 'subagent';
197
+ }>, now?: number): string;
135
198
  /** One-line friendly tool-call presentation (command / path / arg summary). */
136
199
  export declare function presentToolCall(name: string, args: string): {
137
200
  title: string;
@@ -263,6 +326,11 @@ export declare class SshTui {
263
326
  private pushRow;
264
327
  /** The transcript rows that support per-row expand/collapse. */
265
328
  private collapsibleRows;
329
+ private spinnerFrame;
330
+ private findSubagentRow;
331
+ private findLivePlanRow;
332
+ private upsertPlanRow;
333
+ private paintCollapsibleHeader;
266
334
  /** Move the expand/collapse focus among reasoning and tool rows. */
267
335
  private moveCollapsibleFocus;
268
336
  /** Toggle the focused block; without focus, toggle the most recent one. */
@@ -289,19 +357,27 @@ export declare class SshTui {
289
357
  * owns the route); direct children created by tool-subagent inherit the
290
358
  * parent provider unless `/submodel` stored an explicit subagent provider.
291
359
  */
292
- private readonly handleAgentRequest;
293
- private readonly handleSessionEvent;
360
+ readonly handleAgentRequest: ({ agent }: {
361
+ agent: Agent;
362
+ }, next: () => Promise<LlmCallConfig>) => Promise<LlmCallConfig>;
363
+ readonly handleSessionEvent: (session: {
364
+ id: SessionId;
365
+ }, event: SessionEvent) => void;
294
366
  private readonly handleStatus;
295
367
  private readonly handleError;
296
368
  private readonly handleInboxClaimed;
297
369
  private readonly handleInboxDiscarded;
298
370
  private readonly handleDisposed;
299
- /** Render a live subagent's own session events so its progress is visible. */
300
- private readonly handleSubagentSessionEvent;
301
- private readonly handleSubagentStart;
302
- private readonly handleSubagentEnd;
371
+ /** Plan-mode / command / team events that plugins merge into SessionEventMap. */
372
+ private handleExtensionEvent;
373
+ private handleGoalChange;
374
+ private handleSubagentExtensionEvent;
375
+ /** Fold a live subagent's own session events into that child's card. */
376
+ readonly handleSubagentSessionEvent: (sessionId: SessionId, event: SessionEvent) => void;
377
+ readonly handleSubagentStart: (info: SubagentRunInfo) => void;
378
+ readonly handleSubagentEnd: (info: SubagentRunEndInfo) => void;
303
379
  private readonly handleApproval;
304
- private readonly handleUserQuestions;
380
+ readonly handleUserQuestions: (request: AskUserQuestionRequest) => Promise<AskUserQuestionAnswer>;
305
381
  /** Queue one dialog behind an already-open one instead of overwriting it. */
306
382
  private openDialog;
307
383
  private showNextDialog;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ssh-tui",
3
- "version": "0.1.7",
3
+ "version": "0.2.0",
4
4
  "description": "SSH-friendly interactive terminal TUI plugin for DeepSeek Harness",
5
5
  "keywords": [
6
6
  "deepseek-harness",
@@ -72,19 +72,20 @@
72
72
  },
73
73
  "peerDependencies": {
74
74
  "@deepseek-ai/cordis": "^4.0.1",
75
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
76
- "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6",
77
- "@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.6",
78
- "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6",
79
- "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6",
80
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
81
- "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
82
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
83
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
84
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
85
- "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6",
86
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
87
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6"
75
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
76
+ "@deepseek-ai/dsh-agent-default-model": "^0.1.1-rc.2",
77
+ "@deepseek-ai/dsh-agent-loop": "^0.1.1-rc.2",
78
+ "@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.2",
79
+ "@deepseek-ai/dsh-cmdline": "^0.1.1-rc.2",
80
+ "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
81
+ "@deepseek-ai/dsh-credentials": "^0.1.1-rc.2",
82
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
83
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
84
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
85
+ "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
86
+ "@deepseek-ai/dsh-user-approval": "^0.1.1-rc.2",
87
+ "@deepseek-ai/dsh-user-questions": "^0.1.1-rc.2",
88
+ "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2"
88
89
  },
89
90
  "peerDependenciesMeta": {
90
91
  "@deepseek-ai/dsh-user-approval": {
@@ -102,20 +103,21 @@
102
103
  },
103
104
  "devDependencies": {
104
105
  "@deepseek-ai/cordis": "^4.0.1",
105
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
106
- "@deepseek-ai/dsh-agent-default-model": "^0.1.0-rc.6",
107
- "@deepseek-ai/dsh-agent-loop": "^0.1.0-rc.6",
108
- "@deepseek-ai/dsh-agent-presets": "^0.1.0-rc.6",
109
- "@deepseek-ai/dsh-cmdline": "^0.1.0-rc.6",
110
- "@deepseek-ai/dsh-commands": "^0.1.0-rc.6",
111
- "@deepseek-ai/dsh-credentials": "^0.1.0-rc.6",
112
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
113
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
114
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
115
- "@deepseek-ai/dsh-subagent": "^0.1.0-rc.6",
116
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
117
- "@deepseek-ai/dsh-user-questions": "^0.1.0-rc.6",
106
+ "@deepseek-ai/dsh-agent": "^0.1.1-rc.2",
107
+ "@deepseek-ai/dsh-agent-default-model": "^0.1.1-rc.2",
108
+ "@deepseek-ai/dsh-agent-loop": "^0.1.1-rc.2",
109
+ "@deepseek-ai/dsh-agent-presets": "^0.1.1-rc.2",
110
+ "@deepseek-ai/dsh-cmdline": "^0.1.1-rc.2",
111
+ "@deepseek-ai/dsh-commands": "^0.1.1-rc.2",
112
+ "@deepseek-ai/dsh-credentials": "^0.1.1-rc.2",
113
+ "@deepseek-ai/dsh-llm": "^0.1.1-rc.2",
114
+ "@deepseek-ai/dsh-session": "^0.1.1-rc.2",
115
+ "@deepseek-ai/dsh-settings": "^0.1.1-rc.2",
116
+ "@deepseek-ai/dsh-subagent": "^0.1.1-rc.2",
117
+ "@deepseek-ai/dsh-user-approval": "^0.1.1-rc.2",
118
+ "@deepseek-ai/dsh-user-questions": "^0.1.1-rc.2",
118
119
  "@types/node": "^24.0.0",
119
- "typescript": "^5.9.0"
120
+ "typescript": "^5.9.0",
121
+ "@deepseek-ai/dsh-session-persistence": "^0.1.1-rc.2"
120
122
  }
121
123
  }