dsh-ssh-tui 0.3.1 → 0.3.3
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.en.md +45 -19
- package/README.md +37 -16
- package/cordis.patch.yml +1 -1
- package/docs/screenshots/slow-link.gif +0 -0
- package/lib/tui.js +276 -64
- package/lib/tui.js.map +1 -1
- package/lib/types/tui.d.ts +57 -6
- package/package.json +7 -3
- package/docs/screenshots/headless-labeled.png +0 -0
- package/docs/screenshots/workspace-labeled.png +0 -0
package/lib/types/tui.d.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* The renderer uses plain ANSI and coalesces each frame into one stdout
|
|
9
9
|
* write of dirty rows only — jump-host / proxied SSH should see one packet
|
|
10
|
-
* per paint, not one per line. Cadence is DSH_TUI_PAINT_MS
|
|
10
|
+
* per paint, not one per line. Cadence is DSH_TUI_PAINT_MS, else local 80 ms
|
|
11
|
+
* or an SSH tier from a CSI 6n round-trip (default 160 ms).
|
|
11
12
|
*/
|
|
12
13
|
import type { Agent, ModelSelection, ModelSelectionRef } from '@deepseek-ai/dsh-agent';
|
|
13
14
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -53,7 +54,7 @@ export interface TuiConfig {
|
|
|
53
54
|
/**
|
|
54
55
|
* Minimum milliseconds between paints while a turn is streaming.
|
|
55
56
|
* Jump-host / proxied SSH can raise this so token ticks do not flood the
|
|
56
|
-
* link. Defaults from `DSH_TUI_PAINT_MS` (
|
|
57
|
+
* link. Defaults from `DSH_TUI_PAINT_MS` (160).
|
|
57
58
|
*/
|
|
58
59
|
paintIntervalMs?: number;
|
|
59
60
|
}
|
|
@@ -121,6 +122,11 @@ type Row = {
|
|
|
121
122
|
expanded: boolean;
|
|
122
123
|
/** When true the plan stays in the scrolling transcript, not the dock. */
|
|
123
124
|
archived?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Display-only: the last turn ended while todos were still open.
|
|
127
|
+
* Does not rewrite the session log.
|
|
128
|
+
*/
|
|
129
|
+
turnLeftOpen?: boolean;
|
|
124
130
|
} | {
|
|
125
131
|
kind: 'question';
|
|
126
132
|
questionId: string;
|
|
@@ -155,11 +161,21 @@ interface ToolDiffHunk {
|
|
|
155
161
|
export interface TuiController {
|
|
156
162
|
dispose(): Promise<void>;
|
|
157
163
|
}
|
|
164
|
+
export type PaintLinkKind = 'local' | 'ssh';
|
|
158
165
|
/**
|
|
159
|
-
*
|
|
160
|
-
*
|
|
166
|
+
* Explicit env/config always wins. Otherwise local TTYs stay snappy and SSH
|
|
167
|
+
* sessions pick a tier from a measured round-trip (CSI 6n), falling back to
|
|
168
|
+
* 160 ms when the probe is missing.
|
|
161
169
|
*/
|
|
162
|
-
export declare function resolvePaintIntervalMs(configured?: number, env?: NodeJS.ProcessEnv
|
|
170
|
+
export declare function resolvePaintIntervalMs(configured?: number, env?: NodeJS.ProcessEnv, options?: {
|
|
171
|
+
ssh?: boolean;
|
|
172
|
+
rttMs?: number;
|
|
173
|
+
}): number;
|
|
174
|
+
/** True when this process is attached to an SSH session (jump host / proxy). */
|
|
175
|
+
export declare function detectSshSession(env?: NodeJS.ProcessEnv): boolean;
|
|
176
|
+
/** Map a CSI-6n round-trip to a paint cadence. Unknown RTT uses the SSH default. */
|
|
177
|
+
export declare function paintIntervalForRtt(rttMs: number | undefined): number;
|
|
178
|
+
export declare function paintLinkLabel(kind: PaintLinkKind, intervalMs: number, probed: boolean): string;
|
|
163
179
|
/** One incremental paint as a single stdout write (one SSH packet when corked). */
|
|
164
180
|
export declare function composePaintOutput(options: {
|
|
165
181
|
width: number;
|
|
@@ -249,6 +265,17 @@ export declare function openCodeSourceFor(provider: string, llmPiAiSection: unkn
|
|
|
249
265
|
export declare function formatOpenCodeGoUsage(payload: unknown, source: OpenCodeSource): string;
|
|
250
266
|
/** Whether `text` could still grow into a recognized escape sequence. */
|
|
251
267
|
export declare function isEscapePrefix(text: string): boolean;
|
|
268
|
+
/** Parse a Device Status Report cursor reply (`CSI row;col R`). */
|
|
269
|
+
export declare function parseCursorPositionReply(text: string): {
|
|
270
|
+
row: number;
|
|
271
|
+
column: number;
|
|
272
|
+
} | undefined;
|
|
273
|
+
/**
|
|
274
|
+
* Round-trip to the attached terminal via CSI 6n. Returns undefined when the
|
|
275
|
+
* reply never arrives (dumb pipe, blocked DSR). Does not interpret the
|
|
276
|
+
* coordinates — only the elapsed milliseconds matter.
|
|
277
|
+
*/
|
|
278
|
+
export declare function probeTerminalRttMs(stdin?: NodeJS.ReadStream, stdout?: NodeJS.WriteStream, timeoutMs?: number): Promise<number | undefined>;
|
|
252
279
|
/** True while a plan still belongs in the dock (latest incomplete work). */
|
|
253
280
|
export declare function planIsLive(plan: {
|
|
254
281
|
active: boolean;
|
|
@@ -257,6 +284,19 @@ export declare function planIsLive(plan: {
|
|
|
257
284
|
planMarkdown?: string;
|
|
258
285
|
archived?: boolean;
|
|
259
286
|
}): boolean;
|
|
287
|
+
/** Open todos left behind when a turn ends without a completing todo_write. */
|
|
288
|
+
export declare function planTurnLeftOpen(plan: {
|
|
289
|
+
todos: readonly PlanTodoItem[];
|
|
290
|
+
}): boolean;
|
|
291
|
+
/** Mark leftover in-progress/pending todos as display-stale after turn/end. */
|
|
292
|
+
export declare function applyTurnEndToPlan<T extends {
|
|
293
|
+
todos: PlanTodoItem[];
|
|
294
|
+
turnLeftOpen?: boolean;
|
|
295
|
+
}>(plan: T): T;
|
|
296
|
+
/** Follow-up that asks the model to close leftover todos. One per open list. */
|
|
297
|
+
export declare function planCloseNudgeText(plan: {
|
|
298
|
+
todos: readonly PlanTodoItem[];
|
|
299
|
+
}): string;
|
|
260
300
|
export type CardCategory = 'thinking' | 'plan' | 'subagent' | 'reply' | 'tool' | 'question' | 'goal';
|
|
261
301
|
/** Category for jump / search. Assistant replies are not collapsible cards. */
|
|
262
302
|
export declare function cardCategoryOf(row: {
|
|
@@ -275,6 +315,7 @@ export declare function planDockNote(plan: {
|
|
|
275
315
|
pending: boolean;
|
|
276
316
|
todos: readonly PlanTodoItem[];
|
|
277
317
|
planMarkdown?: string;
|
|
318
|
+
turnLeftOpen?: boolean;
|
|
278
319
|
}): string;
|
|
279
320
|
/** Compact per-status counts matching the web plan strip. */
|
|
280
321
|
export declare function todoProgressLabel(todos: readonly PlanTodoItem[]): string;
|
|
@@ -404,13 +445,19 @@ export declare class SshTui {
|
|
|
404
445
|
private lastChromeKey;
|
|
405
446
|
private lastPaintWidth;
|
|
406
447
|
private lastPaintHeight;
|
|
407
|
-
private
|
|
448
|
+
private paintIntervalMs;
|
|
449
|
+
private paintLink;
|
|
450
|
+
private paintProbed;
|
|
408
451
|
private searchHits;
|
|
409
452
|
private searchIndex;
|
|
410
453
|
private searchQuery;
|
|
454
|
+
private planNudgePending;
|
|
455
|
+
private pendingReveal;
|
|
411
456
|
constructor(ctx: Context, agent: Agent, config: TuiConfig);
|
|
412
457
|
/** Enter raw mode, switch to the alternate screen, and start listening. */
|
|
413
458
|
start(): void;
|
|
459
|
+
private startRenderTimer;
|
|
460
|
+
private calibratePaintInterval;
|
|
414
461
|
/** Replay the durable session log so a resumed session renders its history. */
|
|
415
462
|
replayHistory(): void;
|
|
416
463
|
/** Show the first-launch provider/API-key onboarding when nothing is configured. */
|
|
@@ -438,6 +485,8 @@ export declare class SshTui {
|
|
|
438
485
|
private upsertPlanRow;
|
|
439
486
|
/** Whether the live plan strip should occupy the workspace footer. */
|
|
440
487
|
private shouldDockPlan;
|
|
488
|
+
/** One follow-up per leftover list; replay and cancelled turns stay quiet. */
|
|
489
|
+
private queuePlanCloseNudge;
|
|
441
490
|
/** Compact web-style plan strip pinned above the input, not in the transcript. */
|
|
442
491
|
private paintPlanDock;
|
|
443
492
|
private paintCollapsibleHeader;
|
|
@@ -447,6 +496,8 @@ export declare class SshTui {
|
|
|
447
496
|
private toggleCollapsible;
|
|
448
497
|
/** Expand all collapsible blocks, or collapse them again when all are open. */
|
|
449
498
|
private toggleAllCollapsible;
|
|
499
|
+
private highlightSearchLine;
|
|
500
|
+
private revealRow;
|
|
450
501
|
private focusCard;
|
|
451
502
|
/** Jump to the newest card in a category (thinking / plan / subagent / reply). */
|
|
452
503
|
private jumpToCategory;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ssh-tui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "SSH-friendly interactive terminal TUI plugin for DeepSeek Harness",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -42,7 +42,10 @@
|
|
|
42
42
|
"cordis.patch.yml",
|
|
43
43
|
"README.md",
|
|
44
44
|
"README.en.md",
|
|
45
|
-
"docs/screenshots",
|
|
45
|
+
"docs/screenshots/compare.png",
|
|
46
|
+
"docs/screenshots/headless.png",
|
|
47
|
+
"docs/screenshots/workspace.png",
|
|
48
|
+
"docs/screenshots/slow-link.gif",
|
|
46
49
|
"LICENSE"
|
|
47
50
|
],
|
|
48
51
|
"license": "MIT",
|
|
@@ -63,7 +66,8 @@
|
|
|
63
66
|
"install:npm": "bash scripts/install-npm.sh",
|
|
64
67
|
"uninstall:dsh": "bash scripts/uninstall.sh",
|
|
65
68
|
"verify:dsh": "bash scripts/verify.sh",
|
|
66
|
-
"screenshots": "npm run build && node scripts/capture-readme-frames.mjs"
|
|
69
|
+
"screenshots": "npm run build && node scripts/capture-readme-frames.mjs",
|
|
70
|
+
"screenshots:slow": "npm run build && node scripts/capture-slow-link.mjs"
|
|
67
71
|
},
|
|
68
72
|
"engines": {
|
|
69
73
|
"node": ">=22.19"
|
|
Binary file
|
|
Binary file
|