dsh-ssh-tui 0.5.4 → 0.5.5
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 +10 -5
- package/README.md +6 -5
- package/lib/copy-text.js +62 -0
- package/lib/copy-text.js.map +1 -0
- package/lib/dsh-compat.js +142 -1
- package/lib/dsh-compat.js.map +1 -1
- package/lib/i18n/en.js +14 -1
- package/lib/i18n/en.js.map +1 -1
- package/lib/i18n/zh.js +14 -1
- package/lib/i18n/zh.js.map +1 -1
- package/lib/index.js +7 -5
- package/lib/index.js.map +1 -1
- package/lib/paint.js +28 -2
- package/lib/paint.js.map +1 -1
- package/lib/picker.js +51 -15
- package/lib/picker.js.map +1 -1
- package/lib/session-index.js +80 -0
- package/lib/session-index.js.map +1 -0
- package/lib/session-list.js +197 -72
- package/lib/session-list.js.map +1 -1
- package/lib/term-text.js +178 -52
- package/lib/term-text.js.map +1 -1
- package/lib/tui.js +186 -61
- package/lib/tui.js.map +1 -1
- package/lib/types/copy-text.d.ts +9 -0
- package/lib/types/dsh-compat.d.ts +78 -6
- package/lib/types/paint.d.ts +2 -0
- package/lib/types/picker.d.ts +2 -0
- package/lib/types/session-index.d.ts +32 -0
- package/lib/types/session-list.d.ts +22 -2
- package/lib/types/term-text.d.ts +22 -3
- package/lib/types/tui.d.ts +34 -4
- package/package.json +20 -18
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plain-text extraction for /copy. Kept off tui.ts so tests do not load SshTui.
|
|
3
|
+
*/
|
|
4
|
+
import type { CollapsibleBlock, Row } from './transcript-types.js';
|
|
5
|
+
export declare function copyTextFromRow(row: Row | CollapsibleBlock | undefined): string;
|
|
6
|
+
export declare function copyTextFromTranscript(rows: readonly Row[], focused: Row | CollapsibleBlock | null): {
|
|
7
|
+
text: string;
|
|
8
|
+
source: 'focused' | 'assistant' | 'empty';
|
|
9
|
+
};
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Dual-stack shims for dsh 0.1.
|
|
2
|
+
* Dual-stack shims for dsh 0.1.2-rc.1 and 0.1.5-rc.1 (and the 0.1.5-alpha
|
|
3
|
+
* handle API that landed with it).
|
|
3
4
|
*
|
|
4
|
-
* 0.1.2 turned
|
|
5
|
-
* replaced `Session.events` with on-demand readers
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* 0.1.2 turned settings free functions into `SettingsProvider` methods and
|
|
6
|
+
* replaced `Session.events` with on-demand readers. 0.1.5 replaced
|
|
7
|
+
* `SessionPersistence.list`/`inspect`/`locate` with snapshot `list` plus
|
|
8
|
+
* per-session `open` handles, and moved live tokens from durable
|
|
9
|
+
* `assistant/chunk` events to process-local `agent/assistant-stream`.
|
|
10
|
+
* Every shim here picks the API that is actually present so one build
|
|
11
|
+
* runs on either host.
|
|
8
12
|
*/
|
|
9
13
|
import type { Context } from '@deepseek-ai/cordis';
|
|
10
14
|
import type { SessionEvent } from '@deepseek-ai/dsh-session';
|
|
11
15
|
import type { SettingsNamespace, SettingsSectionHooks } from '@deepseek-ai/dsh-settings';
|
|
12
16
|
import type z from '@deepseek-ai/schemastery';
|
|
13
17
|
/**
|
|
14
|
-
* 0.1.1-rc.2 wraps namespaces via `settingsNamespace()`; 0.1.2 brands them at
|
|
18
|
+
* 0.1.1-rc.2 wraps namespaces via `settingsNamespace()`; 0.1.2+ brands them at
|
|
15
19
|
* the type level and takes the plain string at runtime. A cast covers both.
|
|
16
20
|
*/
|
|
17
21
|
export declare function settingsNamespace(value: string): SettingsNamespace;
|
|
@@ -28,3 +32,71 @@ export declare function installSettingsSection<T>(ctx: Context, ns: SettingsName
|
|
|
28
32
|
* property with on-demand readers; 0.1.1-rc.2 still exposes the property.
|
|
29
33
|
*/
|
|
30
34
|
export declare function sessionEvents(session: object): readonly SessionEvent[];
|
|
35
|
+
/**
|
|
36
|
+
* Walk the durable log without copying it. Prefer `eventAt` so resume does
|
|
37
|
+
* not materialize a second array of every chunk.
|
|
38
|
+
*/
|
|
39
|
+
export declare function forEachSessionEvent(session: object, visit: (event: SessionEvent) => void): void;
|
|
40
|
+
/** Header fields the picker and resume path actually read. */
|
|
41
|
+
export interface SessionHeaderLike {
|
|
42
|
+
id: string;
|
|
43
|
+
createdAt: number;
|
|
44
|
+
cwd?: string;
|
|
45
|
+
origin?: string;
|
|
46
|
+
delegationDepth?: number;
|
|
47
|
+
}
|
|
48
|
+
/** Logical log plus the header it belongs to. */
|
|
49
|
+
export interface SessionInspectionLike {
|
|
50
|
+
events: readonly unknown[];
|
|
51
|
+
meta?: SessionHeaderLike;
|
|
52
|
+
header?: SessionHeaderLike;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* 0.1.2 `list()` returns headers; 0.1.5 returns `{ header, revision, … }`
|
|
56
|
+
* snapshots. Normalize to headers so the picker does not care which host
|
|
57
|
+
* it is talking to.
|
|
58
|
+
*/
|
|
59
|
+
export declare function listPersistenceHeaders(persistence: object): Promise<SessionHeaderLike[]>;
|
|
60
|
+
/**
|
|
61
|
+
* 0.1.2 `inspect(id)` returns `{ meta, events }`. 0.1.5 dropped inspect in
|
|
62
|
+
* favour of `open(id, 'read')` + `handle.read()`. Close the handle so a
|
|
63
|
+
* listing pass does not pin write ownership.
|
|
64
|
+
*/
|
|
65
|
+
export declare function inspectPersistenceSession(persistence: object, id: unknown): Promise<SessionInspectionLike>;
|
|
66
|
+
/** 0.1.2 owns `locate(header)`; 0.1.5 hid it on the JSONL backend. */
|
|
67
|
+
export declare function persistenceLocate(persistence: object, meta: object): {
|
|
68
|
+
path?: string;
|
|
69
|
+
} | undefined;
|
|
70
|
+
/**
|
|
71
|
+
* 0.1.2 command input advertised `images`; 0.1.5 renamed the flag to
|
|
72
|
+
* `attachments`. Either true means the slash command accepts composer files.
|
|
73
|
+
*/
|
|
74
|
+
export declare function commandAcceptsAttachments(input: unknown): boolean;
|
|
75
|
+
/** One model stream chunk, from either `assistant/chunk` or `agent/assistant-stream`. */
|
|
76
|
+
export interface StreamChunkLike {
|
|
77
|
+
type: string;
|
|
78
|
+
text?: string;
|
|
79
|
+
usage?: {
|
|
80
|
+
inputTokens?: number;
|
|
81
|
+
outputTokens?: number;
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** Durable `assistant/chunk` payload, or a live stream frame's inner chunk. */
|
|
85
|
+
export declare function streamChunkOf(eventOrFrame: unknown): {
|
|
86
|
+
chunk: StreamChunkLike;
|
|
87
|
+
turn: number;
|
|
88
|
+
step: number;
|
|
89
|
+
time: number;
|
|
90
|
+
} | undefined;
|
|
91
|
+
/** Durable event type as a plain string so 0.1.5 hosts can omit `assistant/chunk`. */
|
|
92
|
+
export declare function sessionEventType(event: unknown): string;
|
|
93
|
+
/** True when this event is a live-or-durable assistant token that replay should skip. */
|
|
94
|
+
export declare function isAssistantStreamEvent(event: unknown): boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Subscribe to a host event that may not exist on the compile-time Events
|
|
97
|
+
* map. 0.1.5 emits `agent/assistant-stream`; 0.1.2 never does. Cordis
|
|
98
|
+
* still accepts the string; the listener is simply never called on 0.1.2.
|
|
99
|
+
*/
|
|
100
|
+
export declare function listenHostEvent(ctx: {
|
|
101
|
+
on: (event: never, handler: never) => unknown;
|
|
102
|
+
}, event: string, handler: (...args: unknown[]) => unknown): () => void;
|
package/lib/types/paint.d.ts
CHANGED
|
@@ -76,3 +76,5 @@ export declare function parseCursorPositionReply(text: string): {
|
|
|
76
76
|
export declare function probeTerminalRttMs(stdin?: NodeJS.ReadStream, stdout?: NodeJS.WriteStream, timeoutMs?: number): Promise<number | undefined>;
|
|
77
77
|
/** Sliding window of `windowSize` items that keeps `cursor` visible. */
|
|
78
78
|
export declare function pickerWindowStart(cursor: number, total: number, windowSize?: number): number;
|
|
79
|
+
/** Immediate first-frame chrome so a 2–3s Host boot is not a blank TTY. */
|
|
80
|
+
export declare function writeBootSplash(message: string, color?: boolean): void;
|
package/lib/types/picker.d.ts
CHANGED
|
@@ -37,6 +37,8 @@ export interface SessionPickerState {
|
|
|
37
37
|
* shortcuts. Set automatically by the first letter, or by `/` / Ctrl+F.
|
|
38
38
|
*/
|
|
39
39
|
filterActive: boolean;
|
|
40
|
+
/** Older logs are still being inspected in the background. */
|
|
41
|
+
loading?: boolean;
|
|
40
42
|
}
|
|
41
43
|
/** One key / control action against {@link SessionPickerState}. */
|
|
42
44
|
export type SessionPickerAction = {
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Disk cache of picker labels so listing history does not inspect every
|
|
3
|
+
* session.jsonl.zstd on each launch. Invalidated by file mtime/size.
|
|
4
|
+
*/
|
|
5
|
+
/** One cached picker row for a stored session. */
|
|
6
|
+
export interface SessionIndexEntry {
|
|
7
|
+
id: string;
|
|
8
|
+
label: string;
|
|
9
|
+
updatedAt: number;
|
|
10
|
+
cwd: string;
|
|
11
|
+
hasUserInput: boolean;
|
|
12
|
+
hasReply: boolean;
|
|
13
|
+
unreadable?: boolean;
|
|
14
|
+
mtimeMs: number;
|
|
15
|
+
size: number;
|
|
16
|
+
}
|
|
17
|
+
/** First page of recent sessions inspected after the header sketch paints. */
|
|
18
|
+
export declare const PICKER_PRIORITY_COUNT = 9;
|
|
19
|
+
export declare function sessionIndexPath(dshHome?: string): string;
|
|
20
|
+
/** Artifact fingerprint used as the cache key. Missing files return zeros. */
|
|
21
|
+
export declare function sessionArtifactStat(persistence: object, meta: object): {
|
|
22
|
+
mtimeMs: number;
|
|
23
|
+
size: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function indexEntryMatchesStat(entry: SessionIndexEntry | undefined, stat: {
|
|
26
|
+
mtimeMs: number;
|
|
27
|
+
size: number;
|
|
28
|
+
}): boolean;
|
|
29
|
+
export declare function loadSessionIndex(path: string): Promise<Map<string, SessionIndexEntry>>;
|
|
30
|
+
export declare function saveSessionIndex(path: string, entries: ReadonlyMap<string, SessionIndexEntry>): Promise<void>;
|
|
31
|
+
/** Drop ids that are no longer in the store so the file cannot grow forever. */
|
|
32
|
+
export declare function pruneSessionIndex(entries: Map<string, SessionIndexEntry>, keepIds: ReadonlySet<string>): void;
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* in-app `/resume` command use the same candidates, labels, and ordering, so
|
|
4
4
|
* both surfaces offer the same sessions.
|
|
5
5
|
*/
|
|
6
|
-
import type { SessionPersistence } from '@deepseek-ai/dsh-session-persistence';
|
|
7
6
|
import { listAttachableHosts } from './session-lock.js';
|
|
8
7
|
/** Last path segment for the footer chip (`\root\genshin\srv` → `srv`). */
|
|
9
8
|
export declare function sessionCwdLabel(cwd: string): string;
|
|
@@ -38,6 +37,13 @@ export interface ResumableSession {
|
|
|
38
37
|
}
|
|
39
38
|
/** `MM-DD HH:mm` local-time label for session lists. */
|
|
40
39
|
export declare function formatSessionTime(timestamp: number): string;
|
|
40
|
+
/** Incremental listing so the picker can paint before older logs are parsed. */
|
|
41
|
+
export interface ResumableSessionListing {
|
|
42
|
+
/** Sessions already inspected (or restored from the disk cache). */
|
|
43
|
+
sessions: ResumableSession[];
|
|
44
|
+
/** Whether older logs are still being inspected. */
|
|
45
|
+
pending: boolean;
|
|
46
|
+
}
|
|
41
47
|
/**
|
|
42
48
|
* List resumable top-level sessions, newest first.
|
|
43
49
|
*
|
|
@@ -51,4 +57,18 @@ export declare function formatSessionTime(timestamp: number): string;
|
|
|
51
57
|
* @returns every resumable candidate in display order (attachable live
|
|
52
58
|
* hosts first, then readable logs, then unreadable).
|
|
53
59
|
*/
|
|
54
|
-
export declare function listResumableSessions(persistence:
|
|
60
|
+
export declare function listResumableSessions(persistence: object, currentId: string, listHosts?: typeof listAttachableHosts): Promise<ResumableSession[]>;
|
|
61
|
+
/**
|
|
62
|
+
* List resumable sessions, painting the recent page first.
|
|
63
|
+
*
|
|
64
|
+
* `onUpdate` fires after the priority page (cached + newest logs) and again
|
|
65
|
+
* after each later inspect batch. Unchanged logs reuse `$DSH_HOME/tui-session-index.json`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function listResumableSessionsProgressive(persistence: object, currentId: string, options?: {
|
|
68
|
+
listHosts?: typeof listAttachableHosts;
|
|
69
|
+
onUpdate?: (listing: ResumableSessionListing) => void;
|
|
70
|
+
indexPath?: string;
|
|
71
|
+
priorityCount?: number;
|
|
72
|
+
}): Promise<ResumableSessionListing & {
|
|
73
|
+
complete: ResumableSession[];
|
|
74
|
+
}>;
|
package/lib/types/term-text.d.ts
CHANGED
|
@@ -84,12 +84,31 @@ export declare function paintSegmentedLine(line: string, start: number, end: num
|
|
|
84
84
|
/** Wrap `text` and color each output line by overlapping `segments`. */
|
|
85
85
|
export declare function wrapSegmented(text: string, width: number, segments: readonly TextSegment[]): string[];
|
|
86
86
|
export declare function truncate(text: string, maxLines: number): string;
|
|
87
|
+
/** One OSC-8 hyperlink span in a painted row, in display columns. */
|
|
88
|
+
export interface PaintedLinkHit {
|
|
89
|
+
href: string;
|
|
90
|
+
startCol: number;
|
|
91
|
+
endCol: number;
|
|
92
|
+
}
|
|
93
|
+
export declare function osc8Open(href: string): string;
|
|
94
|
+
export declare function osc8Close(): string;
|
|
95
|
+
/** True when OSC 8 hyperlinks should be painted. Off when DSH_TUI_OSC8=0/false. */
|
|
96
|
+
export declare function osc8Enabled(env?: NodeJS.ProcessEnv): boolean;
|
|
97
|
+
/** OSC 52 clipboard write. Empty payload clears. ST is ESC \\ so a following CSI cannot be eaten as OSC payload. */
|
|
98
|
+
export declare function osc52Clipboard(text: string): string;
|
|
99
|
+
export declare function stripAnsi(text: string): string;
|
|
100
|
+
/**
|
|
101
|
+
* Locate OSC 8 hyperlinks in a painted ANSI line. Columns are 0-based
|
|
102
|
+
* display cells of the visible glyphs (not counting the sequences).
|
|
103
|
+
*/
|
|
104
|
+
export declare function paintedLinkHits(line: string): PaintedLinkHit[];
|
|
105
|
+
export declare function hrefAtColumn(hits: readonly PaintedLinkHit[], col: number): string | undefined;
|
|
87
106
|
/**
|
|
88
107
|
* Render workspace markdown into width-bounded terminal rows. Assistant
|
|
89
|
-
* replies
|
|
90
|
-
* links and inline spans keep their own ANSI
|
|
108
|
+
* replies use a normal-white base so inline bold can contrast; code blocks,
|
|
109
|
+
* headings, quotes, lists, rules, links and inline spans keep their own ANSI.
|
|
91
110
|
*/
|
|
92
|
-
export declare function renderMarkdownLines(text: string, width: number, color: boolean): string[];
|
|
111
|
+
export declare function renderMarkdownLines(text: string, width: number, color: boolean, hyperlinks?: boolean): string[];
|
|
93
112
|
/** Cut one line to fit a width, appending an ellipsis when truncated. */
|
|
94
113
|
export declare function truncateToWidth(text: string, width: number): string;
|
|
95
114
|
/**
|
package/lib/types/tui.d.ts
CHANGED
|
@@ -24,11 +24,13 @@ import { type SubagentSelectionRef } from './subagent-model.js';
|
|
|
24
24
|
import { type AskUserQuestionAnswer, type AskUserQuestionRequest } from '@deepseek-ai/dsh-user-questions';
|
|
25
25
|
import type { ApprovalOutcome, ApprovalRequest } from '@deepseek-ai/dsh-user-approval';
|
|
26
26
|
import type { CollapsibleBlock, DisconnectPolicyName } from './transcript-types.js';
|
|
27
|
+
import { paintedLinkHits } from './term-text.js';
|
|
27
28
|
export type { CollapsibleBlock, DisplayKind, DisconnectPolicyName, PlanTodoItem, Row, SubagentLogEntry, ToolDiffHunk, } from './transcript-types.js';
|
|
28
|
-
export { clipAnsiToWidth, displayWidth, foldInputView, fmtElapsedCompact, padAnsiToWidth, padToWidth, renderMarkdownLines, repeatToWidth, shimmerText, truncateToWidth, visibleWidth, waitCardCopy, waitSummaryFromReasoning, wrapWaitDetails, } from './term-text.js';
|
|
29
|
-
export { captureHangupSignals, composePaintOutput, detectSshSession, formatLinkQualityChip, ignoreFurtherHangupSignals, isEscapePrefix, isHangupErrno, linkQualityOf, linkSignalPips, paintIntervalForRtt, paintLinkLabel, parseCursorPositionReply, pickerWindowStart, probeTerminalRttMs, releaseHangupSignals, resolvePaintIntervalMs, waitUntilIdleOrTimeout, type LinkQuality, type PaintLinkKind, } from './paint.js';
|
|
29
|
+
export { clipAnsiToWidth, cursorVisualPosition, displayWidth, foldInputView, hrefAtColumn, osc52Clipboard, osc8Enabled, paintedLinkHits, fmtElapsedCompact, padAnsiToWidth, padToWidth, renderMarkdownLines, repeatToWidth, shimmerText, truncateToWidth, visibleWidth, waitCardCopy, waitSummaryFromReasoning, wrapWaitDetails, } from './term-text.js';
|
|
30
|
+
export { captureHangupSignals, composePaintOutput, detectSshSession, formatLinkQualityChip, ignoreFurtherHangupSignals, isEscapePrefix, isHangupErrno, linkQualityOf, linkSignalPips, paintIntervalForRtt, paintLinkLabel, parseCursorPositionReply, pickerWindowStart, probeTerminalRttMs, releaseHangupSignals, resolvePaintIntervalMs, waitUntilIdleOrTimeout, writeBootSplash, type LinkQuality, type PaintLinkKind, } from './paint.js';
|
|
30
31
|
export { CONTEXT_IDLE_COMPACT_RATIO, CONTEXT_PRESSURE_DANGER_RATIO, CONTEXT_PRESSURE_WARN_RATIO, CONTEXT_RING_EMPTY, CONTEXT_RING_SEGMENTS, contextPressureAlertText, contextPressureRingColor, contextPressureUsedTokens, contextPressureView, describeProviderRoute, dropFooterQuotaPlanName, fitFooterStatsLine, fitFooterStatusLine, footerActivity, footerIdentityParts, footerStatsGroups, formatContextPressureChip, formatContextPressureRing, formatContextPressureStatusLine, formatDuration, formatFooterQuota, formatQuotaBar, formatStatusReport, formatTokens, formatTokensPerSecond, parseContextPressure, promptPressureTokens, providerShortCode, providerUsesLocalOAuth, shouldIdleAutoCompact, type ContextPressureSample, type ContextPressureView, type FooterActivityKind, type FooterStatsInput, type FooterStatusInput, type StatusReportInput, } from './footer.js';
|
|
31
32
|
export { crossedQuotaThresholds, formatAccountBalance, formatFooterBalance, formatOpenCodeGoUsage, formatQuotaSnapshot, formatQuotaStatusLine, joinUrl, openCodeSourceFor, parseDeepSeekBalance, parseOpenAiCompatibleBalance, parseOpenCodeGoQuota, parseSuperGrokBilling, quotaAlertText, quotaRefreshEverySteps, quotaRefreshEveryTurns, remainingPercentFromUsed, tightestQuotaWindow, type AccountBalanceLine, type AccountBalanceSnapshot, type OpenCodeFlavor, type OpenCodeSource, type QuotaPeriod, type QuotaSnapshot, type QuotaWindow, } from './quota.js';
|
|
33
|
+
export { commandAcceptsAttachments, forEachSessionEvent, isAssistantStreamEvent, listPersistenceHeaders, inspectPersistenceSession, sessionEventType, sessionEvents, settingsNamespace, streamChunkOf, } from './dsh-compat.js';
|
|
32
34
|
export { applyTurnEndToPlan, askSummary, cardCategoryOf, compactionHeaderText, formatCompactCommandError, isPromptInjectionMessage, matchTranscriptRows, parseFindQuery, parsePlanTodos, planCloseNudgeText, planDockNote, planIsLive, planTitleFromMarkdown, planTurnLeftOpen, promptInjectionSources, promptInjectionTitle, subagentHeaderText, todoProgressLabel, todoSummary, type CardCategory, } from './plan.js';
|
|
33
35
|
export { buildToolHeader, canMergeToolCall, compactEditPath, compactToolBursts, compactToolGroups, countDiffAddDel, countDiffLines, countOutputLines, diffMetaDiffs, diffStatToken, friendlyJsonLines, parseExitStatus, presentToolCall, READ_TOOL_NAMES, renderToolDiff, toolBodyFitsWorkspace, toolBodyLines, toolStateColor, toolStateLabel, wrappedToolBodyLineCount, } from './tool-present.js';
|
|
34
36
|
/** Presentation configuration for the terminal channel. */
|
|
@@ -184,6 +186,12 @@ export declare class SshTui {
|
|
|
184
186
|
private lastStatsTurn;
|
|
185
187
|
private scrollOffset;
|
|
186
188
|
private readonly clickableRows;
|
|
189
|
+
private readonly paintedLinkHitsByRow;
|
|
190
|
+
private copyYank;
|
|
191
|
+
/** Last OSC-52 payload (tests; empty when nothing has been copied). */
|
|
192
|
+
get lastCopiedText(): string;
|
|
193
|
+
/** Screen-row → OSC 8 hits from the last paint (tests). */
|
|
194
|
+
get linkHitsByRow(): Map<number, ReturnType<typeof paintedLinkHits>>;
|
|
187
195
|
private streamingReasoning;
|
|
188
196
|
private escapeBuffer;
|
|
189
197
|
private escapeTimer;
|
|
@@ -191,9 +199,13 @@ export declare class SshTui {
|
|
|
191
199
|
private waitStartedAt;
|
|
192
200
|
private completionSignaled;
|
|
193
201
|
private replaying;
|
|
202
|
+
/** Display-line budget for the first paint after resume; 0 = full transcript. */
|
|
203
|
+
private paintTailBudget;
|
|
194
204
|
private completedAt;
|
|
195
205
|
private lastTitleUpdateAt;
|
|
196
206
|
private lastPaintRows;
|
|
207
|
+
private lastPaintCursorColumn;
|
|
208
|
+
private lastPaintCursorRow;
|
|
197
209
|
private lastChromeKey;
|
|
198
210
|
private lastPaintWidth;
|
|
199
211
|
private lastPaintHeight;
|
|
@@ -284,6 +296,10 @@ export declare class SshTui {
|
|
|
284
296
|
private exitProcess;
|
|
285
297
|
/** Capture one painted frame. Used by README screenshot fixtures. */
|
|
286
298
|
captureFrame(columns?: number, rows?: number): string[];
|
|
299
|
+
/** Last CSI cursor column written by {@link paint} (1-based). Tests only. */
|
|
300
|
+
lastPaintedCursorColumn(): number;
|
|
301
|
+
/** Last CSI cursor row written by {@link paint} (1-based). Tests only. */
|
|
302
|
+
lastPaintedCursorRow(): number;
|
|
287
303
|
private screenColumns;
|
|
288
304
|
private screenRows;
|
|
289
305
|
private write;
|
|
@@ -362,6 +378,18 @@ export declare class SshTui {
|
|
|
362
378
|
private playCompletionSignal;
|
|
363
379
|
private render;
|
|
364
380
|
private styleLine;
|
|
381
|
+
/**
|
|
382
|
+
* Fold one live or durable stream chunk into the in-progress assistant
|
|
383
|
+
* row. 0.1.2 hosts append `assistant/chunk`; 0.1.5 emits the same chunk
|
|
384
|
+
* on `agent/assistant-stream` and never writes it to the log.
|
|
385
|
+
*/
|
|
386
|
+
private applyStreamChunk;
|
|
387
|
+
/**
|
|
388
|
+
* 0.1.5 live tokens arrive as process-local `agent/assistant-stream`
|
|
389
|
+
* frames (start / chunk / end). Chunk frames carry the same
|
|
390
|
+
* `StreamChunk` the 0.1.2 log used to store as `assistant/chunk`.
|
|
391
|
+
*/
|
|
392
|
+
readonly handleAssistantStream: (...args: unknown[]) => void;
|
|
365
393
|
/**
|
|
366
394
|
* Apply the TUI's subagent model selection to every child-agent request.
|
|
367
395
|
* The parent request is left untouched (its own `/model` waterfall already
|
|
@@ -550,8 +578,10 @@ export declare class SshTui {
|
|
|
550
578
|
/** Idempotently source $DSH_HOME/env.sh from the user's POSIX shell rc files. */
|
|
551
579
|
private ensurePosixEnvHook;
|
|
552
580
|
private handleEscape;
|
|
553
|
-
/** Toggle the collapsible row under a click
|
|
554
|
-
handleMouseClick(y: number): void;
|
|
581
|
+
/** Toggle the collapsible row under a click, or copy an OSC-8 link. */
|
|
582
|
+
handleMouseClick(y: number, x?: number): void;
|
|
583
|
+
private copyPlainText;
|
|
584
|
+
copyFocusedCard(): boolean;
|
|
555
585
|
private scrollInspectOrTranscript;
|
|
556
586
|
private handleCtrlC;
|
|
557
587
|
private submit;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ssh-tui",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.5",
|
|
4
4
|
"description": "SSH-friendly interactive terminal TUI plugin for DeepSeek Harness",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"deepseek-harness",
|
|
@@ -56,12 +56,14 @@
|
|
|
56
56
|
"patch": "./cordis.patch.yml"
|
|
57
57
|
},
|
|
58
58
|
"compatibility": {
|
|
59
|
-
"dsh": ">=0.1.
|
|
59
|
+
"dsh": ">=0.1.2-rc.1 <0.1.6",
|
|
60
60
|
"dshReleases": {
|
|
61
61
|
"0.1.2-rc.1": "compatible",
|
|
62
62
|
"0.1.3-alpha.1": "unknown",
|
|
63
|
-
"0.1.3-alpha.2": "
|
|
64
|
-
"0.1.5-alpha.1": "
|
|
63
|
+
"0.1.3-alpha.2": "compatible",
|
|
64
|
+
"0.1.5-alpha.1": "compatible",
|
|
65
|
+
"0.1.5-alpha.2": "compatible",
|
|
66
|
+
"0.1.5-rc.1": "compatible"
|
|
65
67
|
},
|
|
66
68
|
"profiles": ["tui"]
|
|
67
69
|
}
|
|
@@ -90,20 +92,20 @@
|
|
|
90
92
|
},
|
|
91
93
|
"peerDependencies": {
|
|
92
94
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
93
|
-
"@deepseek-ai/dsh-agent": ">=0.1.
|
|
94
|
-
"@deepseek-ai/dsh-agent-default-model": ">=0.1.
|
|
95
|
-
"@deepseek-ai/dsh-agent-loop": ">=0.1.
|
|
96
|
-
"@deepseek-ai/dsh-agent-presets": ">=0.1.
|
|
97
|
-
"@deepseek-ai/dsh-cmdline": ">=0.1.
|
|
98
|
-
"@deepseek-ai/dsh-commands": ">=0.1.
|
|
99
|
-
"@deepseek-ai/dsh-credentials": ">=0.1.
|
|
100
|
-
"@deepseek-ai/dsh-llm": ">=0.1.
|
|
101
|
-
"@deepseek-ai/dsh-session": ">=0.1.
|
|
102
|
-
"@deepseek-ai/dsh-settings": ">=0.1.
|
|
103
|
-
"@deepseek-ai/dsh-subagent": ">=0.1.
|
|
104
|
-
"@deepseek-ai/dsh-user-approval": ">=0.1.
|
|
105
|
-
"@deepseek-ai/dsh-user-questions": ">=0.1.
|
|
106
|
-
"@deepseek-ai/dsh-session-persistence": ">=0.1.
|
|
95
|
+
"@deepseek-ai/dsh-agent": ">=0.1.2-rc.1",
|
|
96
|
+
"@deepseek-ai/dsh-agent-default-model": ">=0.1.2-rc.1",
|
|
97
|
+
"@deepseek-ai/dsh-agent-loop": ">=0.1.2-rc.1",
|
|
98
|
+
"@deepseek-ai/dsh-agent-presets": ">=0.1.2-rc.1",
|
|
99
|
+
"@deepseek-ai/dsh-cmdline": ">=0.1.2-rc.1",
|
|
100
|
+
"@deepseek-ai/dsh-commands": ">=0.1.2-rc.1",
|
|
101
|
+
"@deepseek-ai/dsh-credentials": ">=0.1.2-rc.1",
|
|
102
|
+
"@deepseek-ai/dsh-llm": ">=0.1.2-rc.1",
|
|
103
|
+
"@deepseek-ai/dsh-session": ">=0.1.2-rc.1",
|
|
104
|
+
"@deepseek-ai/dsh-settings": ">=0.1.2-rc.1",
|
|
105
|
+
"@deepseek-ai/dsh-subagent": ">=0.1.2-rc.1",
|
|
106
|
+
"@deepseek-ai/dsh-user-approval": ">=0.1.2-rc.1",
|
|
107
|
+
"@deepseek-ai/dsh-user-questions": ">=0.1.2-rc.1",
|
|
108
|
+
"@deepseek-ai/dsh-session-persistence": ">=0.1.2-rc.1"
|
|
107
109
|
},
|
|
108
110
|
"peerDependenciesMeta": {
|
|
109
111
|
"@deepseek-ai/dsh-user-approval": {
|