dsh-ssh-tui 0.3.9 → 0.4.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.
- package/README.en.md +25 -14
- package/README.md +13 -14
- package/lib/i18n/en.js +32 -3
- package/lib/i18n/en.js.map +1 -1
- package/lib/i18n/index.js +2 -0
- package/lib/i18n/index.js.map +1 -1
- package/lib/i18n/zh.js +32 -3
- package/lib/i18n/zh.js.map +1 -1
- package/lib/tui.js +454 -54
- package/lib/tui.js.map +1 -1
- package/lib/types/i18n/index.d.ts +4 -0
- package/lib/types/tui.d.ts +75 -5
- package/lib/types/update-check.d.ts +16 -2
- package/lib/update-check.js +46 -5
- package/lib/update-check.js.map +1 -1
- package/package.json +1 -1
|
@@ -12,8 +12,12 @@ export type MessageVars = Record<string, string | number>;
|
|
|
12
12
|
export declare const UI_LOCALE_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
|
|
13
13
|
export declare const UI_LOCALE_SCHEMA: z<Schemastery.ObjectS<{
|
|
14
14
|
language: z<string, string>;
|
|
15
|
+
skipUpdate: z<string, string>;
|
|
16
|
+
view: z<string, string>;
|
|
15
17
|
}>, Schemastery.ObjectT<{
|
|
16
18
|
language: z<string, string>;
|
|
19
|
+
skipUpdate: z<string, string>;
|
|
20
|
+
view: z<string, string>;
|
|
17
21
|
}>>;
|
|
18
22
|
export declare function localeFromTag(tag: string): Locale | undefined;
|
|
19
23
|
/** Pick zh/en from env, optionally after a saved settings value. */
|
package/lib/types/tui.d.ts
CHANGED
|
@@ -280,6 +280,7 @@ export interface FooterStatusInput {
|
|
|
280
280
|
multiLineInput: boolean;
|
|
281
281
|
queued: number;
|
|
282
282
|
cwdLabel?: string;
|
|
283
|
+
compactView?: boolean;
|
|
283
284
|
}
|
|
284
285
|
export declare function footerActivity(input: FooterStatusInput): {
|
|
285
286
|
kind: FooterActivityKind;
|
|
@@ -348,6 +349,34 @@ export declare function providerUsesLocalOAuth(provider: string): boolean;
|
|
|
348
349
|
* Overflow into the input box is handled by clipping/padding painted rows to
|
|
349
350
|
* the measured column count, not by inflating glyph width.
|
|
350
351
|
*/
|
|
352
|
+
/**
|
|
353
|
+
* Codex-style compact elapsed: `0s`, `1m 05s`, `1h 01m 01s`.
|
|
354
|
+
* Used by the workspace wait card while the model has not streamed yet.
|
|
355
|
+
*/
|
|
356
|
+
export declare function fmtElapsedCompact(elapsedSecs: number): string;
|
|
357
|
+
/**
|
|
358
|
+
* Sweep highlight across `text` (Codex `shimmer.rs`). Truecolor blends a
|
|
359
|
+
* highlight band; otherwise DIM / default / BOLD. Process-start based so
|
|
360
|
+
* every paint of the same frame stays in phase.
|
|
361
|
+
*/
|
|
362
|
+
export declare function shimmerText(text: string, nowMs: number, color: boolean): string;
|
|
363
|
+
/**
|
|
364
|
+
* Codex-style short status from reasoning: first `**bold**` / heading, else
|
|
365
|
+
* the first short clause. Keeps the wait card in sync with what the model is
|
|
366
|
+
* doing instead of repeating the user's prompt.
|
|
367
|
+
*/
|
|
368
|
+
export declare function waitSummaryFromReasoning(text: string, maxChars?: number): string | undefined;
|
|
369
|
+
/** Wait-card header + optional detail. Header tracks model work when known. */
|
|
370
|
+
export declare function waitCardCopy(input: {
|
|
371
|
+
toolTitle?: string;
|
|
372
|
+
toolSummary?: string;
|
|
373
|
+
reasoning?: string;
|
|
374
|
+
reply?: string;
|
|
375
|
+
prompt?: string;
|
|
376
|
+
}): {
|
|
377
|
+
header: string;
|
|
378
|
+
detail?: string;
|
|
379
|
+
};
|
|
351
380
|
export declare function displayWidth(text: string): number;
|
|
352
381
|
/** Pad or clip one already-sanitized line so it occupies exactly `width` cells. */
|
|
353
382
|
export declare function padToWidth(text: string, width: number): string;
|
|
@@ -388,9 +417,12 @@ interface InputView {
|
|
|
388
417
|
folded: boolean;
|
|
389
418
|
}
|
|
390
419
|
/**
|
|
391
|
-
* Fold a long
|
|
392
|
-
*
|
|
393
|
-
*
|
|
420
|
+
* Fold a long input into one terminal row around the cursor.
|
|
421
|
+
*
|
|
422
|
+
* Newlines from a paste are display-only: they do not occupy cells, so a
|
|
423
|
+
* naive `displayWidth(input)` under-counts a multi-line paste and parks the
|
|
424
|
+
* caret in the middle of later text. Fold the *current line* (between the
|
|
425
|
+
* surrounding newlines) and keep `\n` out of the visible slice.
|
|
394
426
|
*/
|
|
395
427
|
export declare function foldInputView(input: string, cursor: number, maxWidth: number): InputView;
|
|
396
428
|
/** A recognized OpenCode provider route, used by /usage and /quota. */
|
|
@@ -477,6 +509,21 @@ export declare function parseCursorPositionReply(text: string): {
|
|
|
477
509
|
* coordinates — only the elapsed milliseconds matter.
|
|
478
510
|
*/
|
|
479
511
|
export declare function probeTerminalRttMs(stdin?: NodeJS.ReadStream, stdout?: NodeJS.WriteStream, timeoutMs?: number): Promise<number | undefined>;
|
|
512
|
+
export type WorkspaceView = 'detailed' | 'compact';
|
|
513
|
+
export declare function parseWorkspaceView(raw: string): WorkspaceView | undefined;
|
|
514
|
+
export declare function countDiffLines(hunks: readonly ToolDiffHunk[] | undefined): number;
|
|
515
|
+
export declare function compactToolGroups(tools: readonly Extract<Row, {
|
|
516
|
+
kind: 'tool';
|
|
517
|
+
}>[]): {
|
|
518
|
+
edits: Extract<Row, {
|
|
519
|
+
kind: 'tool';
|
|
520
|
+
}>[];
|
|
521
|
+
calls: Extract<Row, {
|
|
522
|
+
kind: 'tool';
|
|
523
|
+
}>[];
|
|
524
|
+
editLines: number;
|
|
525
|
+
failedCalls: number;
|
|
526
|
+
};
|
|
480
527
|
/** True while a plan still belongs in the dock (latest incomplete work). */
|
|
481
528
|
export declare function planIsLive(plan: {
|
|
482
529
|
active: boolean;
|
|
@@ -634,6 +681,7 @@ export declare class SshTui {
|
|
|
634
681
|
private readonly color;
|
|
635
682
|
private readonly maxToolOutputLines;
|
|
636
683
|
private readonly showReasoning;
|
|
684
|
+
private workspaceView;
|
|
637
685
|
private readonly goodbye;
|
|
638
686
|
private readonly resume;
|
|
639
687
|
private readonly providerName;
|
|
@@ -654,6 +702,7 @@ export declare class SshTui {
|
|
|
654
702
|
private focusedRow;
|
|
655
703
|
private pendingMessages;
|
|
656
704
|
private lastActivity;
|
|
705
|
+
private lastIdleCtrlCAt;
|
|
657
706
|
private stalledWarningShown;
|
|
658
707
|
private lastPaintAt;
|
|
659
708
|
private commandAbort;
|
|
@@ -671,6 +720,8 @@ export declare class SshTui {
|
|
|
671
720
|
private escapeBuffer;
|
|
672
721
|
private escapeTimer;
|
|
673
722
|
private thinkingStartedAt;
|
|
723
|
+
private waitStartedAt;
|
|
724
|
+
private waitPrompt;
|
|
674
725
|
private completionSignaled;
|
|
675
726
|
private replaying;
|
|
676
727
|
private completedAt;
|
|
@@ -704,6 +755,14 @@ export declare class SshTui {
|
|
|
704
755
|
/** Enter raw mode, switch to the alternate screen, and start listening. */
|
|
705
756
|
start(): void;
|
|
706
757
|
private notifyPluginUpdate;
|
|
758
|
+
private readSkippedUpdate;
|
|
759
|
+
private persistSkippedUpdate;
|
|
760
|
+
private mergeUiSettings;
|
|
761
|
+
private readWorkspaceView;
|
|
762
|
+
private isCompactView;
|
|
763
|
+
/** Test helper: switch the workspace view without going through /view. */
|
|
764
|
+
setWorkspaceView(view: WorkspaceView): void;
|
|
765
|
+
private paintCompactSummary;
|
|
707
766
|
private startRenderTimer;
|
|
708
767
|
private calibratePaintInterval;
|
|
709
768
|
/** Replay the durable session log so a resumed session renders its history. */
|
|
@@ -726,6 +785,15 @@ export declare class SshTui {
|
|
|
726
785
|
/** The transcript rows that support per-row expand/collapse. */
|
|
727
786
|
private collapsibleRows;
|
|
728
787
|
private spinnerFrame;
|
|
788
|
+
/**
|
|
789
|
+
* Codex wait card: shown while the turn is running. Thinking/reply streams
|
|
790
|
+
* feed the shimmer header; a live tool becomes the detail line.
|
|
791
|
+
*/
|
|
792
|
+
private waitCardVisible;
|
|
793
|
+
private beginWait;
|
|
794
|
+
private endWait;
|
|
795
|
+
private waitCardSource;
|
|
796
|
+
private planShouldDefaultExpand;
|
|
729
797
|
private findSubagentRow;
|
|
730
798
|
private findLivePlanRow;
|
|
731
799
|
/** Older / finished plans stay in the scrolling transcript. */
|
|
@@ -746,10 +814,10 @@ export declare class SshTui {
|
|
|
746
814
|
/** Move the expand/collapse focus among reasoning and tool rows. */
|
|
747
815
|
private moveCollapsibleFocus;
|
|
748
816
|
/** Toggle the focused block; without focus, toggle the most recent one. */
|
|
749
|
-
|
|
817
|
+
toggleCollapsible(): void;
|
|
750
818
|
toggleCard(target: CollapsibleBlock): void;
|
|
751
819
|
/** Expand all collapsible blocks, or collapse them again when all are open. */
|
|
752
|
-
|
|
820
|
+
toggleAllCollapsible(): void;
|
|
753
821
|
private highlightSearchLine;
|
|
754
822
|
private revealRow;
|
|
755
823
|
private focusCard;
|
|
@@ -881,6 +949,8 @@ export declare class SshTui {
|
|
|
881
949
|
private runSubeffortCommand;
|
|
882
950
|
/** /language or /lang: persist zh/en and repaint chrome immediately. */
|
|
883
951
|
private runLanguageCommand;
|
|
952
|
+
/** /view: detailed (see the work) vs compact (Codex-like summary). */
|
|
953
|
+
private runViewCommand;
|
|
884
954
|
/** /mode: pick an agent preset (standard / minimal / ptc / cordis / routing-suite / ...). */
|
|
885
955
|
private runModeCommand;
|
|
886
956
|
/** /resume: switch to a past session, or open a picker when no id is given. */
|
|
@@ -1,4 +1,18 @@
|
|
|
1
|
+
export declare const PLUGIN_PACKAGE = "dsh-ssh-tui";
|
|
1
2
|
export declare function compareSemver(a: string, b: string): number;
|
|
2
|
-
export declare function
|
|
3
|
+
export declare function resolvePluginProfileName(env?: NodeJS.ProcessEnv): string;
|
|
4
|
+
export declare function pluginUpgradeCommand(profile?: string): string;
|
|
5
|
+
export declare function formatUpdateNotice(current: string, latest: string, profile?: string): string;
|
|
3
6
|
export declare function fetchLatestNpmVersion(fetchImpl?: typeof fetch): Promise<string | undefined>;
|
|
4
|
-
export
|
|
7
|
+
export interface PluginUpdateInfo {
|
|
8
|
+
current: string;
|
|
9
|
+
latest: string;
|
|
10
|
+
profile: string;
|
|
11
|
+
command: string;
|
|
12
|
+
notice: string;
|
|
13
|
+
}
|
|
14
|
+
export declare function checkForPluginUpdate(current: string): Promise<PluginUpdateInfo | undefined>;
|
|
15
|
+
export declare function installPluginLatest(profile?: string): Promise<{
|
|
16
|
+
ok: boolean;
|
|
17
|
+
output: string;
|
|
18
|
+
}>;
|
package/lib/update-check.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Best-effort npm latest check.
|
|
2
|
+
* Best-effort npm latest check. Failures stay quiet. The TUI may offer to
|
|
3
|
+
* run `dsh plugin --profile <name> add dsh-ssh-tui@latest` — pnpm otherwise
|
|
4
|
+
* keeps the lockfile pin (e.g. 0.3.7) when the spec is a bare package name.
|
|
3
5
|
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { t } from './i18n/index.js';
|
|
4
8
|
const NPM_REGISTRY = 'https://registry.npmjs.org/dsh-ssh-tui/latest';
|
|
5
9
|
const CHECK_TIMEOUT_MS = 4000;
|
|
10
|
+
export const PLUGIN_PACKAGE = 'dsh-ssh-tui';
|
|
6
11
|
export function compareSemver(a, b) {
|
|
7
12
|
const parse = (value) => {
|
|
8
13
|
const core = value.trim().replace(/^v/u, '').split('-')[0] ?? '0';
|
|
@@ -17,9 +22,20 @@ export function compareSemver(a, b) {
|
|
|
17
22
|
}
|
|
18
23
|
return 0;
|
|
19
24
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
25
|
+
export function resolvePluginProfileName(env = process.env) {
|
|
26
|
+
const fromEnv = env.DSH_TUI_PROFILE?.trim();
|
|
27
|
+
if (fromEnv !== undefined && fromEnv !== '')
|
|
28
|
+
return fromEnv;
|
|
29
|
+
const arg = env.DSH_PROFILE?.trim();
|
|
30
|
+
if (arg !== undefined && arg !== '')
|
|
31
|
+
return arg;
|
|
32
|
+
return 'tui';
|
|
33
|
+
}
|
|
34
|
+
export function pluginUpgradeCommand(profile = resolvePluginProfileName()) {
|
|
35
|
+
return `dsh plugin --profile ${profile} add ${PLUGIN_PACKAGE}@latest`;
|
|
36
|
+
}
|
|
37
|
+
export function formatUpdateNotice(current, latest, profile = resolvePluginProfileName()) {
|
|
38
|
+
return t('update.notice', { latest, current, command: pluginUpgradeCommand(profile) });
|
|
23
39
|
}
|
|
24
40
|
export async function fetchLatestNpmVersion(fetchImpl = fetch) {
|
|
25
41
|
try {
|
|
@@ -45,6 +61,31 @@ export async function checkForPluginUpdate(current) {
|
|
|
45
61
|
return undefined;
|
|
46
62
|
if (compareSemver(latest, current) <= 0)
|
|
47
63
|
return undefined;
|
|
48
|
-
|
|
64
|
+
const profile = resolvePluginProfileName();
|
|
65
|
+
return {
|
|
66
|
+
current,
|
|
67
|
+
latest,
|
|
68
|
+
profile,
|
|
69
|
+
command: pluginUpgradeCommand(profile),
|
|
70
|
+
notice: formatUpdateNotice(current, latest, profile),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
export async function installPluginLatest(profile = resolvePluginProfileName()) {
|
|
74
|
+
return await new Promise(resolve => {
|
|
75
|
+
const child = spawn('dsh', ['plugin', '--profile', profile, 'add', `${PLUGIN_PACKAGE}@latest`], {
|
|
76
|
+
env: process.env,
|
|
77
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
78
|
+
});
|
|
79
|
+
const chunks = [];
|
|
80
|
+
child.stdout?.on('data', chunk => chunks.push(Buffer.from(chunk)));
|
|
81
|
+
child.stderr?.on('data', chunk => chunks.push(Buffer.from(chunk)));
|
|
82
|
+
child.on('error', error => {
|
|
83
|
+
resolve({ ok: false, output: error instanceof Error ? error.message : String(error) });
|
|
84
|
+
});
|
|
85
|
+
child.on('close', code => {
|
|
86
|
+
const output = Buffer.concat(chunks).toString('utf8').trim();
|
|
87
|
+
resolve({ ok: code === 0, output });
|
|
88
|
+
});
|
|
89
|
+
});
|
|
49
90
|
}
|
|
50
91
|
//# sourceMappingURL=update-check.js.map
|
package/lib/update-check.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"update-check.js","sourceRoot":"","sources":["../src/update-check.ts"],"names":[],"mappings":"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"}
|