dsh-ssh-tui 0.5.3 → 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 +36 -10
- package/README.md +21 -12
- package/lib/approval-reviewer.js +56 -15
- package/lib/approval-reviewer.js.map +1 -1
- package/lib/auto-approval.js +251 -35
- package/lib/auto-approval.js.map +1 -1
- 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/footer.js +337 -0
- package/lib/footer.js.map +1 -0
- package/lib/i18n/en.js +62 -3
- package/lib/i18n/en.js.map +1 -1
- package/lib/i18n/zh.js +62 -3
- package/lib/i18n/zh.js.map +1 -1
- package/lib/index.js +7 -5
- package/lib/index.js.map +1 -1
- package/lib/json-args.js +30 -0
- package/lib/json-args.js.map +1 -0
- package/lib/paint.js +288 -0
- package/lib/paint.js.map +1 -0
- package/lib/picker.js +453 -66
- package/lib/picker.js.map +1 -1
- package/lib/plan.js +369 -0
- package/lib/plan.js.map +1 -0
- package/lib/quota.js +408 -0
- package/lib/quota.js.map +1 -0
- package/lib/session-index.js +80 -0
- package/lib/session-index.js.map +1 -0
- package/lib/session-list.js +210 -88
- package/lib/session-list.js.map +1 -1
- package/lib/term-text.js +953 -0
- package/lib/term-text.js.map +1 -0
- package/lib/tool-present.js +744 -0
- package/lib/tool-present.js.map +1 -0
- package/lib/transcript-types.js +6 -0
- package/lib/transcript-types.js.map +1 -0
- package/lib/tui.js +643 -3299
- package/lib/tui.js.map +1 -1
- package/lib/types/approval-reviewer.d.ts +8 -2
- package/lib/types/auto-approval.d.ts +28 -0
- package/lib/types/copy-text.d.ts +9 -0
- package/lib/types/dsh-compat.d.ts +78 -6
- package/lib/types/footer.d.ts +155 -0
- package/lib/types/json-args.d.ts +7 -0
- package/lib/types/paint.d.ts +80 -0
- package/lib/types/picker.d.ts +101 -7
- package/lib/types/plan.d.ts +80 -0
- package/lib/types/quota.d.ts +94 -0
- package/lib/types/session-index.d.ts +32 -0
- package/lib/types/session-list.d.ts +35 -2
- package/lib/types/term-text.d.ts +149 -0
- package/lib/types/tool-present.d.ts +165 -0
- package/lib/types/transcript-types.d.ts +152 -0
- package/lib/types/tui.d.ts +53 -723
- package/package.json +20 -18
package/lib/types/tui.d.ts
CHANGED
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
* write of dirty rows only — jump-host / proxied SSH should see one packet
|
|
10
10
|
* per paint, not one per line. Cadence is DSH_TUI_PAINT_MS, else local 80 ms
|
|
11
11
|
* or an SSH tier from a CSI 6n round-trip (default 160 ms).
|
|
12
|
+
*
|
|
13
|
+
* Pure helpers live next to this file (`term-text`, `paint`, `footer`,
|
|
14
|
+
* `quota`, `plan`, `tool-present`) and are re-exported here so existing
|
|
15
|
+
* `lib/tui.js` imports keep working. The launch picker imports `paint` /
|
|
16
|
+
* `term-text` directly and does not load this module.
|
|
12
17
|
*/
|
|
13
18
|
import type { Agent, ModelSelection, ModelSelectionRef } from '@deepseek-ai/dsh-agent';
|
|
14
19
|
import type { Context } from '@deepseek-ai/cordis';
|
|
@@ -18,7 +23,16 @@ import type { SubagentRunEndInfo, SubagentRunInfo } from '@deepseek-ai/dsh-subag
|
|
|
18
23
|
import { type SubagentSelectionRef } from './subagent-model.js';
|
|
19
24
|
import { type AskUserQuestionAnswer, type AskUserQuestionRequest } from '@deepseek-ai/dsh-user-questions';
|
|
20
25
|
import type { ApprovalOutcome, ApprovalRequest } from '@deepseek-ai/dsh-user-approval';
|
|
21
|
-
|
|
26
|
+
import type { CollapsibleBlock, DisconnectPolicyName } from './transcript-types.js';
|
|
27
|
+
import { paintedLinkHits } from './term-text.js';
|
|
28
|
+
export type { CollapsibleBlock, DisplayKind, DisconnectPolicyName, PlanTodoItem, Row, SubagentLogEntry, ToolDiffHunk, } from './transcript-types.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';
|
|
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';
|
|
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';
|
|
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';
|
|
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';
|
|
22
36
|
/** Presentation configuration for the terminal channel. */
|
|
23
37
|
export interface TuiConfig {
|
|
24
38
|
/** Exact shared agent/session identity driven by this terminal. */
|
|
@@ -70,537 +84,13 @@ export interface TuiConfig {
|
|
|
70
84
|
/** Hangup policy while busy: pause cancels the turn; continue lets it finish detached. Idle hangup always exits. */
|
|
71
85
|
disconnectPolicy?: DisconnectPolicyName;
|
|
72
86
|
}
|
|
73
|
-
type SubagentLogKind = 'user' | 'assistant' | 'tool' | 'result' | 'turn' | 'approval' | 'team' | 'system';
|
|
74
|
-
/** One child-session event folded into a parent-side subagent card. */
|
|
75
|
-
export interface SubagentLogEntry {
|
|
76
|
-
kind: SubagentLogKind;
|
|
77
|
-
text: string;
|
|
78
|
-
}
|
|
79
|
-
/** One todo-list item as the plan card renders it. */
|
|
80
|
-
export interface PlanTodoItem {
|
|
81
|
-
content: string;
|
|
82
|
-
status: 'pending' | 'in_progress' | 'completed';
|
|
83
|
-
}
|
|
84
|
-
type Row = {
|
|
85
|
-
kind: 'user';
|
|
86
|
-
text: string;
|
|
87
|
-
} | {
|
|
88
|
-
kind: 'assistant';
|
|
89
|
-
text: string;
|
|
90
|
-
} | {
|
|
91
|
-
kind: 'reasoning';
|
|
92
|
-
text: string;
|
|
93
|
-
expanded: boolean;
|
|
94
|
-
} | {
|
|
95
|
-
kind: 'brand';
|
|
96
|
-
text: string;
|
|
97
|
-
} | {
|
|
98
|
-
kind: 'brand-logo';
|
|
99
|
-
} | {
|
|
100
|
-
kind: 'tool';
|
|
101
|
-
callId: string;
|
|
102
|
-
name: string;
|
|
103
|
-
args: string;
|
|
104
|
-
status?: 'running' | 'ok' | 'error';
|
|
105
|
-
output: string;
|
|
106
|
-
title: string;
|
|
107
|
-
summary: string;
|
|
108
|
-
command?: string;
|
|
109
|
-
cwd?: string;
|
|
110
|
-
diff?: ToolDiffHunk[];
|
|
111
|
-
exitCode?: number;
|
|
112
|
-
signal?: string;
|
|
113
|
-
expanded: boolean;
|
|
114
|
-
/** Consecutive same-path reads/edits folded into this card. */
|
|
115
|
-
repeats?: number;
|
|
116
|
-
/** Call ids folded into this card; results still match after merge. */
|
|
117
|
-
mergedCallIds?: string[];
|
|
118
|
-
/** Sum of output characters across folded reads. */
|
|
119
|
-
totalChars?: number;
|
|
120
|
-
/** Sum of output lines across folded reads. */
|
|
121
|
-
totalLines?: number;
|
|
122
|
-
/** Flip-card animation until this timestamp (ms since epoch). */
|
|
123
|
-
flipUntil?: number;
|
|
124
|
-
} | {
|
|
125
|
-
kind: 'subagent';
|
|
126
|
-
sessionId: string;
|
|
127
|
-
runId: string;
|
|
128
|
-
provider: string;
|
|
129
|
-
local: boolean;
|
|
130
|
-
label: string;
|
|
131
|
-
status: 'running' | 'ok' | 'error' | 'aborted';
|
|
132
|
-
startedAt: number;
|
|
133
|
-
endedAt?: number;
|
|
134
|
-
stopReason?: string;
|
|
135
|
-
lastActivity: string;
|
|
136
|
-
logs: SubagentLogEntry[];
|
|
137
|
-
expanded: boolean;
|
|
138
|
-
} | {
|
|
139
|
-
kind: 'plan';
|
|
140
|
-
active: boolean;
|
|
141
|
-
pending: boolean;
|
|
142
|
-
todos: PlanTodoItem[];
|
|
143
|
-
planMarkdown?: string;
|
|
144
|
-
expanded: boolean;
|
|
145
|
-
/** When true the plan stays in the scrolling transcript, not the dock. */
|
|
146
|
-
archived?: boolean;
|
|
147
|
-
/**
|
|
148
|
-
* Display-only: the last turn ended while todos were still open.
|
|
149
|
-
* Does not rewrite the session log.
|
|
150
|
-
*/
|
|
151
|
-
turnLeftOpen?: boolean;
|
|
152
|
-
} | {
|
|
153
|
-
kind: 'question';
|
|
154
|
-
questionId: string;
|
|
155
|
-
title: string;
|
|
156
|
-
header?: string;
|
|
157
|
-
detail?: string;
|
|
158
|
-
intent: 'ask' | 'plan-review';
|
|
159
|
-
status: 'waiting' | 'answered' | 'cancelled';
|
|
160
|
-
summary: string;
|
|
161
|
-
expanded: boolean;
|
|
162
|
-
} | {
|
|
163
|
-
kind: 'goal';
|
|
164
|
-
objective: string;
|
|
165
|
-
phase: 'active' | 'paused' | 'blocked' | 'complete' | 'cleared';
|
|
166
|
-
blockedReason?: string;
|
|
167
|
-
expanded: boolean;
|
|
168
|
-
} | {
|
|
169
|
-
kind: 'compaction';
|
|
170
|
-
compactionId: string;
|
|
171
|
-
status: 'running' | 'ok' | 'error';
|
|
172
|
-
startedAt: number;
|
|
173
|
-
endedAt?: number;
|
|
174
|
-
pruneCount: number;
|
|
175
|
-
prunedTokens: number;
|
|
176
|
-
summary?: string;
|
|
177
|
-
error?: string;
|
|
178
|
-
expanded: boolean;
|
|
179
|
-
} | {
|
|
180
|
-
kind: 'prompt';
|
|
181
|
-
sources: string[];
|
|
182
|
-
text: string;
|
|
183
|
-
plugin?: string;
|
|
184
|
-
expanded: boolean;
|
|
185
|
-
} | {
|
|
186
|
-
kind: 'system';
|
|
187
|
-
text: string;
|
|
188
|
-
} | {
|
|
189
|
-
kind: 'error';
|
|
190
|
-
text: string;
|
|
191
|
-
};
|
|
192
|
-
/** A reasoning/tool/subagent/plan row or the live streaming-reasoning block. */
|
|
193
|
-
type CollapsibleBlock = Extract<Row, {
|
|
194
|
-
kind: 'reasoning';
|
|
195
|
-
} | {
|
|
196
|
-
kind: 'tool';
|
|
197
|
-
} | {
|
|
198
|
-
kind: 'subagent';
|
|
199
|
-
} | {
|
|
200
|
-
kind: 'plan';
|
|
201
|
-
} | {
|
|
202
|
-
kind: 'question';
|
|
203
|
-
} | {
|
|
204
|
-
kind: 'goal';
|
|
205
|
-
} | {
|
|
206
|
-
kind: 'compaction';
|
|
207
|
-
} | {
|
|
208
|
-
kind: 'prompt';
|
|
209
|
-
}> | {
|
|
210
|
-
kind: 'streaming-reasoning';
|
|
211
|
-
expanded: boolean;
|
|
212
|
-
};
|
|
213
|
-
type DisplayKind = Row['kind'] | 'tool-result' | 'diff-add' | 'diff-del' | 'diff-path' | 'todo-done' | 'todo-active' | 'todo-pending' | 'plan-dock';
|
|
214
|
-
/** One file's change, matching the web diff-card contract (`card: 'diff'`). */
|
|
215
|
-
interface ToolDiffHunk {
|
|
216
|
-
path: string;
|
|
217
|
-
oldText: string | null;
|
|
218
|
-
newText: string;
|
|
219
|
-
}
|
|
220
87
|
/** Lifecycle handle for a mounted interactive terminal channel. */
|
|
221
88
|
export interface TuiController {
|
|
222
89
|
dispose(): Promise<void>;
|
|
223
90
|
handleHangup(): Promise<void>;
|
|
224
91
|
disconnectPolicy(): DisconnectPolicyName;
|
|
225
92
|
}
|
|
226
|
-
export type PaintLinkKind = 'local' | 'ssh';
|
|
227
|
-
/** Compact token count, matching the web stats line (517 / 12.2K / 1.2M). */
|
|
228
|
-
export declare function formatTokens(n: number): string;
|
|
229
|
-
/**
|
|
230
|
-
* Prompt occupancy of the next request, from DSH `contextPressure`.
|
|
231
|
-
* Provider-agnostic: uses the routed model's advertised window, not a
|
|
232
|
-
* hardcoded xAI size. Compaction-basic still owns in-turn pressure at 80%.
|
|
233
|
-
*/
|
|
234
|
-
export declare const CONTEXT_PRESSURE_WARN_RATIO = 0.8;
|
|
235
|
-
export declare const CONTEXT_PRESSURE_DANGER_RATIO = 0.95;
|
|
236
|
-
/** Idle auto-compact starts here so recovery finishes before the 80% in-turn trigger. */
|
|
237
|
-
export declare const CONTEXT_IDLE_COMPACT_RATIO = 0.72;
|
|
238
|
-
export interface ContextPressureSample {
|
|
239
|
-
usedTokens: number;
|
|
240
|
-
contextWindow: number;
|
|
241
|
-
}
|
|
242
|
-
export interface ContextPressureView {
|
|
243
|
-
usedTokens: number;
|
|
244
|
-
contextWindow: number;
|
|
245
|
-
percent: number;
|
|
246
|
-
level: 'ok' | 'warn' | 'danger';
|
|
247
|
-
}
|
|
248
|
-
/** Prompt-side occupancy of one usage sample: uncached input plus cache traffic. */
|
|
249
|
-
export declare function promptPressureTokens(usage: {
|
|
250
|
-
inputTokens: number;
|
|
251
|
-
cacheReadTokens?: number;
|
|
252
|
-
cacheWriteTokens?: number;
|
|
253
|
-
}): number;
|
|
254
|
-
/** Prefer the next-request projection; fall back to last-request pressure. */
|
|
255
|
-
export declare function contextPressureUsedTokens(pressure: {
|
|
256
|
-
projectedTokens?: number;
|
|
257
|
-
pressureTokens?: number;
|
|
258
|
-
} | undefined): number | undefined;
|
|
259
|
-
export declare function parseContextPressure(value: unknown): ContextPressureSample | undefined;
|
|
260
|
-
export declare function contextPressureView(sample: ContextPressureSample): ContextPressureView;
|
|
261
|
-
/**
|
|
262
|
-
* 8-segment Braille ring. Empty `⣀`; full `⣿`. Width is always 1 cell.
|
|
263
|
-
* Index is `ceil(percent / 12.5)` clamped to 0..8.
|
|
264
|
-
*/
|
|
265
|
-
export declare const CONTEXT_RING_EMPTY = "\u28C0";
|
|
266
|
-
export declare const CONTEXT_RING_SEGMENTS: readonly ["⣀", "⠉", "⠋", "⠛", "⠞", "⠟", "⠿", "⡿", "⣿"];
|
|
267
|
-
export declare function formatContextPressureRing(percent: number): string;
|
|
268
|
-
export declare function contextPressureRingColor(level: ContextPressureView['level']): string;
|
|
269
|
-
export declare function formatContextPressureChip(view: ContextPressureView, color?: boolean): string;
|
|
270
|
-
export declare function formatContextPressureStatusLine(view: ContextPressureView | undefined): string;
|
|
271
|
-
export declare function contextPressureAlertText(view: ContextPressureView): string;
|
|
272
|
-
export declare function shouldIdleAutoCompact(view: ContextPressureView | undefined): boolean;
|
|
273
|
-
/** Compact duration, matching the web stats line (45.2s / 2m42s). */
|
|
274
|
-
export declare function formatDuration(ms: number): string;
|
|
275
|
-
export declare function formatTokensPerSecond(tokensPerSecond: number): string;
|
|
276
|
-
/**
|
|
277
|
-
* Explicit env/config always wins. Otherwise local TTYs stay snappy and SSH
|
|
278
|
-
* sessions pick a tier from a measured round-trip (CSI 6n), falling back to
|
|
279
|
-
* 160 ms when the probe is missing.
|
|
280
|
-
*/
|
|
281
|
-
export declare function resolvePaintIntervalMs(configured?: number, env?: NodeJS.ProcessEnv, options?: {
|
|
282
|
-
ssh?: boolean;
|
|
283
|
-
rttMs?: number;
|
|
284
|
-
}): number;
|
|
285
|
-
/** True when this process is attached to an SSH session (jump host / proxy). */
|
|
286
|
-
export declare function detectSshSession(env?: NodeJS.ProcessEnv): boolean;
|
|
287
|
-
/** Node errno on a write/close that means the TTY is gone (SSH drop, HUP). */
|
|
288
|
-
export declare function isHangupErrno(error: unknown): boolean;
|
|
289
|
-
/**
|
|
290
|
-
* Replace launcher SIGTERM/SIGINT/SIGHUP handlers with `handler`. SSH drop
|
|
291
|
-
* otherwise lets `dsh` dispose the whole tree before this plugin can detach.
|
|
292
|
-
*/
|
|
293
|
-
export declare function captureHangupSignals(handler: () => void): void;
|
|
294
|
-
export declare function releaseHangupSignals(handler: () => void): void;
|
|
295
|
-
/** After detach, extra HUP/TERM from sshd must not kill the leftover Host. */
|
|
296
|
-
export declare function ignoreFurtherHangupSignals(): void;
|
|
297
|
-
/**
|
|
298
|
-
* Wait until `isIdle` is true or `timeoutMs` elapses. Used after cancel so a
|
|
299
|
-
* hangup can flush a settled session log instead of tearing a live write.
|
|
300
|
-
*/
|
|
301
|
-
export declare function waitUntilIdleOrTimeout(isIdle: () => boolean, timeoutMs: number, now?: () => number, wait?: (ms: number) => Promise<void>): Promise<'idle' | 'timeout'>;
|
|
302
|
-
/** Map a CSI-6n round-trip to a paint cadence. Unknown RTT uses the SSH default. */
|
|
303
|
-
export declare function paintIntervalForRtt(rttMs: number | undefined): number;
|
|
304
|
-
export declare function paintLinkLabel(kind: PaintLinkKind, intervalMs: number, probed: boolean): string;
|
|
305
|
-
export type LinkQuality = 'local' | 'good' | 'ok' | 'slow' | 'poor' | 'unknown';
|
|
306
|
-
/** Signal-bar quality from a measured SSH round-trip, or local TTY. */
|
|
307
|
-
export declare function linkQualityOf(kind: PaintLinkKind, rttMs: number | undefined): LinkQuality;
|
|
308
|
-
/** How many filled signal pips: 4 local/fast, 3 ok, 2 slow, 1 poor, 0 unknown. */
|
|
309
|
-
export declare function linkSignalPips(quality: LinkQuality): number;
|
|
310
|
-
/** Compact footer chip: `SSH ●●●○ 90ms` — 1 pip red, 2 yellow, 3+ green. */
|
|
311
|
-
export declare function formatLinkQualityChip(kind: PaintLinkKind, intervalMs: number, rttMs: number | undefined, probed: boolean, color?: boolean): string;
|
|
312
|
-
export declare function providerShortCode(provider: string): string;
|
|
313
|
-
export interface FooterStatsInput {
|
|
314
|
-
turns: number;
|
|
315
|
-
steps: number;
|
|
316
|
-
llmMs: number;
|
|
317
|
-
toolMs: number;
|
|
318
|
-
ttftMs: number;
|
|
319
|
-
ttftSteps: number;
|
|
320
|
-
decodeMs: number;
|
|
321
|
-
decodeTokens: number;
|
|
322
|
-
inputTokens: number;
|
|
323
|
-
outputTokens: number;
|
|
324
|
-
cacheReadTokens: number;
|
|
325
|
-
cacheWriteTokens: number;
|
|
326
|
-
}
|
|
327
|
-
/** Stats groups in drop order (last is dropped first when the row is too wide). */
|
|
328
|
-
export declare function footerStatsGroups(stats: FooterStatsInput): string[];
|
|
329
|
-
export declare function fitFooterStatsLine(chip: string, groups: readonly string[], width: number): string;
|
|
330
|
-
export type FooterActivityKind = 'plan-review' | 'waiting' | 'compacting' | 'retry' | 'subagents' | 'tools' | 'plan-open' | 'plan-pending' | 'goal' | 'waiting-llm' | 'idle';
|
|
331
|
-
export interface FooterStatusInput {
|
|
332
|
-
running: boolean;
|
|
333
|
-
planReview: boolean;
|
|
334
|
-
waitingQuestion: boolean;
|
|
335
|
-
compacting: boolean;
|
|
336
|
-
retry?: {
|
|
337
|
-
retry: number;
|
|
338
|
-
maxRetries: number;
|
|
339
|
-
};
|
|
340
|
-
subagents: number;
|
|
341
|
-
tools: number;
|
|
342
|
-
planLeftOpen: boolean;
|
|
343
|
-
planPending: boolean;
|
|
344
|
-
planActive: boolean;
|
|
345
|
-
goalPhase?: 'active' | 'paused' | 'blocked';
|
|
346
|
-
idleMs: number;
|
|
347
|
-
model: string;
|
|
348
|
-
effort?: string;
|
|
349
|
-
preset?: string;
|
|
350
|
-
provider: string;
|
|
351
|
-
parentModel: string;
|
|
352
|
-
subModel: string;
|
|
353
|
-
subDiffers: boolean;
|
|
354
|
-
quotaCode?: string;
|
|
355
|
-
quotaPercent?: number;
|
|
356
|
-
contextChip?: string;
|
|
357
|
-
balanceText?: string;
|
|
358
|
-
search?: {
|
|
359
|
-
index: number;
|
|
360
|
-
total: number;
|
|
361
|
-
};
|
|
362
|
-
foldedInput: boolean;
|
|
363
|
-
multiLineInput: boolean;
|
|
364
|
-
queued: number;
|
|
365
|
-
cwdLabel?: string;
|
|
366
|
-
compactView?: boolean;
|
|
367
|
-
}
|
|
368
|
-
export declare function footerActivity(input: FooterStatusInput): {
|
|
369
|
-
kind: FooterActivityKind;
|
|
370
|
-
text: string;
|
|
371
|
-
};
|
|
372
|
-
/** Short remaining-quota bar: 8 pips, filled from the left. */
|
|
373
|
-
export declare function formatQuotaBar(remainingPercent: number, width?: number): string;
|
|
374
|
-
export declare function footerIdentityParts(input: FooterStatusInput): string[];
|
|
375
|
-
/** `SuperGrok ███████░ 82%`, or just the bar + percent when `code` is omitted. */
|
|
376
|
-
export declare function formatFooterQuota(percent: number, code?: string): string;
|
|
377
|
-
/**
|
|
378
|
-
* Drop the Go / SuperGrok plan name from a quota identity part, keeping the
|
|
379
|
-
* remaining-percent bar. Returns true when a part was rewritten.
|
|
380
|
-
*/
|
|
381
|
-
export declare function dropFooterQuotaPlanName(parts: string[]): boolean;
|
|
382
|
-
export declare function fitFooterStatusLine(activity: string, identity: readonly string[], width: number): string;
|
|
383
|
-
/** One incremental paint as a single stdout write (one SSH packet when corked). */
|
|
384
|
-
export declare function composePaintOutput(options: {
|
|
385
|
-
width: number;
|
|
386
|
-
height: number;
|
|
387
|
-
paintRows: readonly string[];
|
|
388
|
-
previousRows: readonly string[];
|
|
389
|
-
sizeChanged: boolean;
|
|
390
|
-
chromeChanged: boolean;
|
|
391
|
-
chromeStart: number;
|
|
392
|
-
previousChromeStart?: number;
|
|
393
|
-
cursorRow: number;
|
|
394
|
-
cursorColumn: number;
|
|
395
|
-
}): string;
|
|
396
|
-
export interface StatusReportInput {
|
|
397
|
-
sessionId: string;
|
|
398
|
-
pluginVersion: string;
|
|
399
|
-
provider: string;
|
|
400
|
-
model: string;
|
|
401
|
-
effort?: string;
|
|
402
|
-
agentStatus: string;
|
|
403
|
-
preset: string;
|
|
404
|
-
activeSubagents: number;
|
|
405
|
-
plan: 'off' | 'pending' | 'on';
|
|
406
|
-
paint: string;
|
|
407
|
-
disconnect?: DisconnectPolicyName;
|
|
408
|
-
waitingQuestions: number;
|
|
409
|
-
quota?: QuotaSnapshot;
|
|
410
|
-
context?: ContextPressureView;
|
|
411
|
-
parentModel?: string;
|
|
412
|
-
subProvider?: string;
|
|
413
|
-
subModel: string;
|
|
414
|
-
cwd?: string;
|
|
415
|
-
}
|
|
416
|
-
/** Lines printed by `/status` — SSH first-boot diagnostics, no extra command. */
|
|
417
|
-
export declare function formatStatusReport(input: StatusReportInput): string[];
|
|
418
|
-
/** Human-facing kind for a live LLM route. */
|
|
419
|
-
export declare function describeProviderRoute(provider: string): {
|
|
420
|
-
kind: string;
|
|
421
|
-
short: string;
|
|
422
|
-
};
|
|
423
|
-
/** Routes that authenticate without a harness API-key credential. */
|
|
424
|
-
export declare function providerUsesLocalOAuth(provider: string): boolean;
|
|
425
|
-
/**
|
|
426
|
-
* Terminal cell width for one string.
|
|
427
|
-
*
|
|
428
|
-
* Match glibc wcwidth / typical UTF-8 SSH terminals: CJK ideographs and
|
|
429
|
-
* fullwidth forms occupy two cells; East-Asian Ambiguous box-drawing and
|
|
430
|
-
* ornaments (`─`, `●`, `·`, `▸`, `❯`, Braille spinners) occupy one. Counting
|
|
431
|
-
* those ambiguous glyphs as two made `repeatToWidth('─', cols)` paint a
|
|
432
|
-
* half-width rule and parked the input cursor half a cell past the text.
|
|
433
|
-
*
|
|
434
|
-
* Overflow into the input box is handled by clipping/padding painted rows to
|
|
435
|
-
* the measured column count, not by inflating glyph width.
|
|
436
|
-
*/
|
|
437
|
-
/**
|
|
438
|
-
* Codex-style compact elapsed: `0s`, `1m 05s`, `1h 01m 01s`.
|
|
439
|
-
* Used by the workspace wait card while the model has not streamed yet.
|
|
440
|
-
*/
|
|
441
|
-
export declare function fmtElapsedCompact(elapsedSecs: number): string;
|
|
442
|
-
/**
|
|
443
|
-
* Sweep highlight across `text` (Codex `shimmer.rs`). Truecolor blends a
|
|
444
|
-
* highlight band; otherwise DIM / default / BOLD. Process-start based so
|
|
445
|
-
* every paint of the same frame stays in phase.
|
|
446
|
-
*/
|
|
447
|
-
export declare function shimmerText(text: string, nowMs: number, color: boolean): string;
|
|
448
|
-
/**
|
|
449
|
-
* Codex `extract_first_bold`: the first **closed** `**bold**` in the thinking
|
|
450
|
-
* stream, else the first markdown heading. An unclosed `**` means the title
|
|
451
|
-
* has not arrived yet, so return undefined and keep the default header —
|
|
452
|
-
* never fall back to hard-truncated reasoning, reply, or prompt text.
|
|
453
|
-
*/
|
|
454
|
-
export declare function waitSummaryFromReasoning(text: string): string | undefined;
|
|
455
|
-
/** Wait-card header + optional detail. Header tracks model work when known. */
|
|
456
|
-
export declare function waitCardCopy(input: {
|
|
457
|
-
toolTitle?: string;
|
|
458
|
-
toolSummary?: string;
|
|
459
|
-
reasoning?: string;
|
|
460
|
-
}): {
|
|
461
|
-
header: string;
|
|
462
|
-
detail?: string;
|
|
463
|
-
};
|
|
464
|
-
/**
|
|
465
|
-
* Codex `wrapped_details_lines`: word-wrap the wait-card detail under the
|
|
466
|
-
* ` └ ` prefix, continue wrapped rows at the prefix width, cap at 3 rows and
|
|
467
|
-
* end the last one with an ellipsis when the text does not fit.
|
|
468
|
-
*/
|
|
469
|
-
export declare function wrapWaitDetails(detail: string, width: number, maxLines?: number): string[];
|
|
470
|
-
export declare function displayWidth(text: string): number;
|
|
471
|
-
/** Pad or clip one already-sanitized line so it occupies exactly `width` cells. */
|
|
472
|
-
export declare function padToWidth(text: string, width: number): string;
|
|
473
|
-
/**
|
|
474
|
-
* Pad an already-styled ANSI line to `width` cells without resetting SGR.
|
|
475
|
-
* Diff add/del rows keep their background across the whole terminal row
|
|
476
|
-
* instead of only the glyphs.
|
|
477
|
-
*/
|
|
478
|
-
export declare function padAnsiToWidth(text: string, width: number): string;
|
|
479
|
-
/** Visible width of an ANSI-styled line, ignoring CSI / OSC sequences. */
|
|
480
|
-
export declare function visibleWidth(text: string): number;
|
|
481
|
-
/** Repeat a glyph until it occupies exactly `width` cells. */
|
|
482
|
-
export declare function repeatToWidth(glyph: string, width: number): string;
|
|
483
|
-
/** One colored span inside a tool-card header line. Offsets are UTF-16 char indices. */
|
|
484
|
-
interface TextSegment {
|
|
485
|
-
start: number;
|
|
486
|
-
end: number;
|
|
487
|
-
sgr: string;
|
|
488
|
-
}
|
|
489
|
-
/**
|
|
490
|
-
* Render workspace markdown into width-bounded terminal rows. Assistant
|
|
491
|
-
* replies get a bold-white base; code blocks, headings, quotes, lists, rules,
|
|
492
|
-
* links and inline spans keep their own ANSI treatment.
|
|
493
|
-
*/
|
|
494
|
-
export declare function renderMarkdownLines(text: string, width: number, color: boolean): string[];
|
|
495
|
-
/** Cut one line to fit a width, appending an ellipsis when truncated. */
|
|
496
|
-
export declare function truncateToWidth(text: string, width: number): string;
|
|
497
|
-
/**
|
|
498
|
-
* Clip an already-styled ANSI line to `width` terminal cells without dropping
|
|
499
|
-
* the reset/SGR sequences. Used by the incremental painter so a leftover wide
|
|
500
|
-
* glyph cannot wrap into the next row.
|
|
501
|
-
*/
|
|
502
|
-
export declare function clipAnsiToWidth(text: string, width: number): string;
|
|
503
|
-
/** One renderable view of the input line: text plus the cursor's visual offset. */
|
|
504
|
-
interface InputView {
|
|
505
|
-
text: string;
|
|
506
|
-
cursorOffset: number;
|
|
507
|
-
folded: boolean;
|
|
508
|
-
}
|
|
509
|
-
/**
|
|
510
|
-
* Fold a long input into one terminal row around the cursor.
|
|
511
|
-
*
|
|
512
|
-
* Newlines from a paste are display-only: they do not occupy cells, so a
|
|
513
|
-
* naive `displayWidth(input)` under-counts a multi-line paste and parks the
|
|
514
|
-
* caret in the middle of later text. Fold the *current line* (between the
|
|
515
|
-
* surrounding newlines) and keep `\n` out of the visible slice.
|
|
516
|
-
*/
|
|
517
|
-
export declare function foldInputView(input: string, cursor: number, maxWidth: number): InputView;
|
|
518
|
-
/** A recognized OpenCode provider route, used by /usage and /quota. */
|
|
519
|
-
export type OpenCodeFlavor = 'zen' | 'go';
|
|
520
|
-
export interface OpenCodeSource {
|
|
521
|
-
provider: string;
|
|
522
|
-
flavor: OpenCodeFlavor;
|
|
523
|
-
label: string;
|
|
524
|
-
apiKeyEnv: string;
|
|
525
|
-
baseURL?: string;
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* Classify the currently selected provider as an OpenCode route. Built-in
|
|
529
|
-
* `opencode`/`opencode-go` ids are recognized directly, and custom llm-pi-ai
|
|
530
|
-
* routes are recognized by their `opencode.ai` base URL.
|
|
531
|
-
*/
|
|
532
|
-
export declare function openCodeSourceFor(provider: string, llmPiAiSection: unknown): OpenCodeSource | null;
|
|
533
|
-
export type QuotaPeriod = 'hourly' | 'weekly' | 'monthly' | 'unknown';
|
|
534
|
-
export interface QuotaWindow {
|
|
535
|
-
label: string;
|
|
536
|
-
period: QuotaPeriod;
|
|
537
|
-
/** Remaining percent of the window (100 = unused). */
|
|
538
|
-
remainingPercent: number;
|
|
539
|
-
resetsAt?: string;
|
|
540
|
-
}
|
|
541
|
-
export interface QuotaSnapshot {
|
|
542
|
-
provider: string;
|
|
543
|
-
plan: string;
|
|
544
|
-
windows: QuotaWindow[];
|
|
545
|
-
}
|
|
546
|
-
export declare function remainingPercentFromUsed(usedPercent: number): number;
|
|
547
|
-
/** Cross a remaining-percent threshold from above (50 / 25 / 10 / 5).
|
|
548
|
-
* Only the tightest (lowest) crossed threshold is returned, so one drop
|
|
549
|
-
* never paints 50/25/10 as three identical warnings. */
|
|
550
|
-
export declare function crossedQuotaThresholds(previousRemaining: number | undefined, remaining: number): number[];
|
|
551
|
-
export declare function quotaAlertText(snapshot: QuotaSnapshot, window: QuotaWindow): string;
|
|
552
|
-
/**
|
|
553
|
-
* How often to re-fetch quota or prepaid balance, counted in model steps.
|
|
554
|
-
* Default is every 10 steps. Near a remaining-percent threshold, hourly
|
|
555
|
-
* windows refresh every 4 steps.
|
|
556
|
-
*/
|
|
557
|
-
export declare function quotaRefreshEverySteps(window: QuotaWindow | undefined): number;
|
|
558
|
-
/** @deprecated Same cadence as {@link quotaRefreshEverySteps}; the name predates step accounting. */
|
|
559
|
-
export declare const quotaRefreshEveryTurns: typeof quotaRefreshEverySteps;
|
|
560
|
-
export declare function parseSuperGrokBilling(payload: unknown): QuotaSnapshot;
|
|
561
|
-
export declare function parseOpenCodeGoQuota(payload: unknown, provider: string): QuotaSnapshot;
|
|
562
|
-
export declare function formatQuotaSnapshot(snapshot: QuotaSnapshot): string;
|
|
563
|
-
/** Compact `/status` quota line: tightest window first, then the rest. */
|
|
564
|
-
export declare function formatQuotaStatusLine(snapshot: QuotaSnapshot | undefined): string;
|
|
565
|
-
/** Tightest remaining window — used for threshold alerts. */
|
|
566
|
-
export declare function tightestQuotaWindow(snapshot: QuotaSnapshot): QuotaWindow | undefined;
|
|
567
|
-
/** Render the OpenCode Go quota payload as a transcript block. */
|
|
568
|
-
export declare function formatOpenCodeGoUsage(payload: unknown, source: OpenCodeSource): string;
|
|
569
|
-
export interface AccountBalanceLine {
|
|
570
|
-
label: string;
|
|
571
|
-
amount: string;
|
|
572
|
-
currency?: string;
|
|
573
|
-
}
|
|
574
|
-
export interface AccountBalanceSnapshot {
|
|
575
|
-
provider: string;
|
|
576
|
-
plan: string;
|
|
577
|
-
available?: boolean;
|
|
578
|
-
lines: AccountBalanceLine[];
|
|
579
|
-
sourcePath?: string;
|
|
580
|
-
}
|
|
581
|
-
export declare function joinUrl(base: string, path: string): string;
|
|
582
|
-
export declare function parseDeepSeekBalance(payload: unknown, provider?: string): AccountBalanceSnapshot;
|
|
583
|
-
/** Best-effort parse of OpenAI-compatible credit/balance JSON. */
|
|
584
|
-
export declare function parseOpenAiCompatibleBalance(payload: unknown, provider: string, path: string): AccountBalanceSnapshot | undefined;
|
|
585
|
-
/** Compact footer chip: `余额 86.42 CNY`. Prefers remaining/available lines. */
|
|
586
|
-
export declare function formatFooterBalance(snapshot: AccountBalanceSnapshot): string | undefined;
|
|
587
|
-
export declare function formatAccountBalance(snapshot: AccountBalanceSnapshot): string;
|
|
588
|
-
/** Whether `text` could still grow into a recognized escape sequence. */
|
|
589
|
-
export declare function isEscapePrefix(text: string): boolean;
|
|
590
|
-
/** Parse a Device Status Report cursor reply (`CSI row;col R`). */
|
|
591
|
-
export declare function parseCursorPositionReply(text: string): {
|
|
592
|
-
row: number;
|
|
593
|
-
column: number;
|
|
594
|
-
} | undefined;
|
|
595
|
-
/**
|
|
596
|
-
* Round-trip to the attached terminal via CSI 6n. Returns undefined when the
|
|
597
|
-
* reply never arrives (dumb pipe, blocked DSR). Does not interpret the
|
|
598
|
-
* coordinates — only the elapsed milliseconds matter.
|
|
599
|
-
*/
|
|
600
|
-
export declare function probeTerminalRttMs(stdin?: NodeJS.ReadStream, stdout?: NodeJS.WriteStream, timeoutMs?: number): Promise<number | undefined>;
|
|
601
93
|
export type WorkspaceView = 'detailed' | 'compact';
|
|
602
|
-
/** Sliding window of `windowSize` items that keeps `cursor` visible. */
|
|
603
|
-
export declare function pickerWindowStart(cursor: number, total: number, windowSize?: number): number;
|
|
604
94
|
export declare function parseDisconnectPolicy(raw: string): DisconnectPolicyName | undefined;
|
|
605
95
|
/** Parse `/effort high` / `/subeffort default`. Empty or unknown → undefined. */
|
|
606
96
|
export declare function parseEffortArg(raw: string): {
|
|
@@ -610,201 +100,6 @@ export declare function parseEffortArg(raw: string): {
|
|
|
610
100
|
id: string;
|
|
611
101
|
} | undefined;
|
|
612
102
|
export declare function parseWorkspaceView(raw: string): WorkspaceView | undefined;
|
|
613
|
-
export declare function countDiffLines(hunks: readonly ToolDiffHunk[] | undefined): number;
|
|
614
|
-
/** Added / removed line counts for a diff (`oldText: null` means a new file). */
|
|
615
|
-
export declare function countDiffAddDel(hunks: readonly ToolDiffHunk[] | undefined): {
|
|
616
|
-
add: number;
|
|
617
|
-
del: number;
|
|
618
|
-
};
|
|
619
|
-
/**
|
|
620
|
-
* Git diffstat token, deletions first like `-13 +24`. Zero parts drop out
|
|
621
|
-
* (a new file shows only `+24`); empty when the diff has no counted lines.
|
|
622
|
-
*/
|
|
623
|
-
export declare function diffStatToken(add: number, del: number): string;
|
|
624
|
-
export declare function toolTargetPath(name: string, args: string, fallback?: string): string;
|
|
625
|
-
/** Path shown on a compact single-file edit summary. */
|
|
626
|
-
export declare function compactEditPath(item: {
|
|
627
|
-
name: string;
|
|
628
|
-
args: string;
|
|
629
|
-
summary?: string;
|
|
630
|
-
diff?: readonly {
|
|
631
|
-
path?: string;
|
|
632
|
-
}[];
|
|
633
|
-
}): string;
|
|
634
|
-
export declare function countOutputLines(text: string): number;
|
|
635
|
-
/**
|
|
636
|
-
* Consecutive same-path reads (or edits) collapse onto one card.
|
|
637
|
-
* A → B → C → A becomes four cards; A ×5 stays one card with repeats=5.
|
|
638
|
-
*/
|
|
639
|
-
export declare function canMergeToolCall(previous: Extract<Row, {
|
|
640
|
-
kind: 'tool';
|
|
641
|
-
}> | undefined, next: {
|
|
642
|
-
name: string;
|
|
643
|
-
args: string;
|
|
644
|
-
}): previous is Extract<Row, {
|
|
645
|
-
kind: 'tool';
|
|
646
|
-
}>;
|
|
647
|
-
export declare function compactToolGroups(tools: readonly Extract<Row, {
|
|
648
|
-
kind: 'tool';
|
|
649
|
-
}>[]): {
|
|
650
|
-
edits: Extract<Row, {
|
|
651
|
-
kind: 'tool';
|
|
652
|
-
}>[];
|
|
653
|
-
calls: Extract<Row, {
|
|
654
|
-
kind: 'tool';
|
|
655
|
-
}>[];
|
|
656
|
-
failedCalls: number;
|
|
657
|
-
};
|
|
658
|
-
/**
|
|
659
|
-
* Split compact-view tools into the bursts that belong with each assistant
|
|
660
|
-
* reply: tools after reply N sit with that reply, until the next reply.
|
|
661
|
-
*/
|
|
662
|
-
export declare function compactToolBursts(rows: readonly Row[]): Array<{
|
|
663
|
-
after: Extract<Row, {
|
|
664
|
-
kind: 'assistant';
|
|
665
|
-
}> | undefined;
|
|
666
|
-
groups: ReturnType<typeof compactToolGroups>;
|
|
667
|
-
}>;
|
|
668
|
-
/** True while a plan still belongs in the dock (latest incomplete work). */
|
|
669
|
-
export declare function planIsLive(plan: {
|
|
670
|
-
active: boolean;
|
|
671
|
-
pending: boolean;
|
|
672
|
-
todos: readonly PlanTodoItem[];
|
|
673
|
-
planMarkdown?: string;
|
|
674
|
-
archived?: boolean;
|
|
675
|
-
}): boolean;
|
|
676
|
-
/** Open todos left behind when a turn ends without a completing todo_write. */
|
|
677
|
-
export declare function planTurnLeftOpen(plan: {
|
|
678
|
-
todos: readonly PlanTodoItem[];
|
|
679
|
-
}): boolean;
|
|
680
|
-
/** Mark leftover in-progress/pending todos as display-stale after turn/end. */
|
|
681
|
-
export declare function applyTurnEndToPlan<T extends {
|
|
682
|
-
todos: PlanTodoItem[];
|
|
683
|
-
turnLeftOpen?: boolean;
|
|
684
|
-
}>(plan: T): T;
|
|
685
|
-
/** Follow-up that asks the model to close leftover todos. One per open list. */
|
|
686
|
-
export declare function planCloseNudgeText(plan: {
|
|
687
|
-
todos: readonly PlanTodoItem[];
|
|
688
|
-
}): string;
|
|
689
|
-
export type CardCategory = 'thinking' | 'plan' | 'subagent' | 'reply' | 'tool' | 'question' | 'goal' | 'prompt';
|
|
690
|
-
/** Category for jump / search. Assistant replies are not collapsible cards. */
|
|
691
|
-
export declare function cardCategoryOf(row: {
|
|
692
|
-
kind: string;
|
|
693
|
-
}): CardCategory | undefined;
|
|
694
|
-
/** Split `/find thinking padAnsi` into an optional category and a query. */
|
|
695
|
-
export declare function parseFindQuery(raw: string): {
|
|
696
|
-
category?: CardCategory;
|
|
697
|
-
query: string;
|
|
698
|
-
};
|
|
699
|
-
/** Classify one injected prompt blob into display sources. */
|
|
700
|
-
export declare function promptInjectionSources(text: string, plugin?: string): string[];
|
|
701
|
-
export declare function promptInjectionTitle(sources: readonly string[]): string;
|
|
702
|
-
export declare function isPromptInjectionMessage(sourceKind: string, text: string, plugin?: string): boolean;
|
|
703
|
-
/** Official `/compact` idle-only failures, mapped to a local sentence. */
|
|
704
|
-
export declare function formatCompactCommandError(text: string): string;
|
|
705
|
-
export declare function compactionHeaderText(row: {
|
|
706
|
-
status: 'running' | 'ok' | 'error';
|
|
707
|
-
pruneCount: number;
|
|
708
|
-
prunedTokens: number;
|
|
709
|
-
error?: string;
|
|
710
|
-
}): string;
|
|
711
|
-
/** Transcript rows matching a `/find` query, newest last. */
|
|
712
|
-
export declare function matchTranscriptRows(rows: readonly Row[], raw: string): Row[];
|
|
713
|
-
/** One-line note under an expanded plan strip. */
|
|
714
|
-
export declare function planDockNote(plan: {
|
|
715
|
-
active: boolean;
|
|
716
|
-
pending: boolean;
|
|
717
|
-
todos: readonly PlanTodoItem[];
|
|
718
|
-
planMarkdown?: string;
|
|
719
|
-
turnLeftOpen?: boolean;
|
|
720
|
-
}): string;
|
|
721
|
-
/** Compact per-status counts matching the web plan strip. */
|
|
722
|
-
export declare function todoProgressLabel(todos: readonly PlanTodoItem[]): string;
|
|
723
|
-
/** First markdown heading of an exit_plan_mode plan body. */
|
|
724
|
-
export declare function planTitleFromMarkdown(markdown: string): string | undefined;
|
|
725
|
-
/** Parse a todo_write payload into displayable plan items. */
|
|
726
|
-
export declare function parsePlanTodos(value: unknown): PlanTodoItem[];
|
|
727
|
-
/** Compact todo-list summary: done/total plus the first in-progress task. */
|
|
728
|
-
export declare function todoSummary(value: unknown): string;
|
|
729
|
-
/** Compact ask_user_question summary from tool arguments. */
|
|
730
|
-
export declare function askSummary(value: unknown): string;
|
|
731
|
-
/** One-line subagent card header used while collapsed. */
|
|
732
|
-
export declare function subagentHeaderText(row: Extract<Row, {
|
|
733
|
-
kind: 'subagent';
|
|
734
|
-
}>, now?: number): string;
|
|
735
|
-
/** One-line friendly tool-call presentation (command / path / arg summary). */
|
|
736
|
-
export declare function presentToolCall(name: string, args: string): {
|
|
737
|
-
title: string;
|
|
738
|
-
summary: string;
|
|
739
|
-
command?: string;
|
|
740
|
-
cwd?: string;
|
|
741
|
-
diff?: ToolDiffHunk[];
|
|
742
|
-
};
|
|
743
|
-
/** Validate a tool/result meta payload's structured diff, mirroring the web card. */
|
|
744
|
-
export declare function diffMetaDiffs(meta: unknown): ToolDiffHunk[] | null;
|
|
745
|
-
/** One rendered diff body line with its display role. */
|
|
746
|
-
interface DiffDisplayLine {
|
|
747
|
-
kind: DisplayKind;
|
|
748
|
-
text: string;
|
|
749
|
-
}
|
|
750
|
-
/** Running / ok / error → ANSI color for the status dot and status word only. */
|
|
751
|
-
export declare function toolStateColor(status: 'running' | 'ok' | 'error' | undefined): '33' | '32' | '31';
|
|
752
|
-
export declare function toolStateLabel(status: 'running' | 'ok' | 'error' | undefined): string;
|
|
753
|
-
/** Header + SGR spans: default title, dim operand, colored ●. `[ok]` is omitted — the green dot is enough. */
|
|
754
|
-
export declare function buildToolHeader(input: {
|
|
755
|
-
focused: boolean;
|
|
756
|
-
expanded: boolean;
|
|
757
|
-
title: string;
|
|
758
|
-
summary: string;
|
|
759
|
-
status?: 'running' | 'ok' | 'error';
|
|
760
|
-
command?: string;
|
|
761
|
-
signal?: string;
|
|
762
|
-
exitCode?: number;
|
|
763
|
-
spinner?: string;
|
|
764
|
-
flipping?: boolean;
|
|
765
|
-
diffStat?: {
|
|
766
|
-
add: number;
|
|
767
|
-
del: number;
|
|
768
|
-
};
|
|
769
|
-
}): {
|
|
770
|
-
plain: string;
|
|
771
|
-
segments: TextSegment[];
|
|
772
|
-
};
|
|
773
|
-
/** How many terminal rows a tool body occupies after wrapping. */
|
|
774
|
-
export declare function wrappedToolBodyLineCount(lines: readonly {
|
|
775
|
-
text: string;
|
|
776
|
-
}[], width: number): number;
|
|
777
|
-
/**
|
|
778
|
-
* True when the full tool body plus a one-line header fits in the workspace
|
|
779
|
-
* (the rows between the title bar and the input chrome). Oversized bodies
|
|
780
|
-
* open a dedicated inspect overlay instead of dumping into the transcript.
|
|
781
|
-
*/
|
|
782
|
-
export declare function toolBodyFitsWorkspace(bodyLines: number, workspaceRows: number): boolean;
|
|
783
|
-
/** Flatten hunks into git-style `-`/`+` lines plus the web-compatible footer. */
|
|
784
|
-
export declare function renderToolDiff(diffs: ToolDiffHunk[], maxLines: number): DiffDisplayLine[];
|
|
785
|
-
/** Convert any parsed JSON value into readable indented display lines. */
|
|
786
|
-
export declare function friendlyJsonLines(value: unknown, depth?: number): string[];
|
|
787
|
-
/** Minimal tool-row shape the expanded-body renderer reads. */
|
|
788
|
-
interface ToolBodySource {
|
|
789
|
-
name?: string;
|
|
790
|
-
diff?: ToolDiffHunk[];
|
|
791
|
-
command?: string;
|
|
792
|
-
status?: 'running' | 'ok' | 'error';
|
|
793
|
-
output: string;
|
|
794
|
-
args: string;
|
|
795
|
-
}
|
|
796
|
-
/**
|
|
797
|
-
* The expanded body of one tool card: diffs and shell output keep their
|
|
798
|
-
* dedicated views; every other tool's JSON arguments and JSON result are
|
|
799
|
-
* converted into readable indented content instead of raw JSON text.
|
|
800
|
-
*/
|
|
801
|
-
export declare function toolBodyLines(row: ToolBodySource, maxLines: number): DiffDisplayLine[];
|
|
802
|
-
/** Recover the shell tools' exit marker, mirroring @deepseek-ai/dsh-shell/render. */
|
|
803
|
-
export declare function parseExitStatus(text: string): {
|
|
804
|
-
body: string;
|
|
805
|
-
exitCode?: number;
|
|
806
|
-
signal?: string;
|
|
807
|
-
};
|
|
808
103
|
/** Owns one interactive terminal channel and its agent event wiring. */
|
|
809
104
|
export declare class SshTui {
|
|
810
105
|
private readonly ctx;
|
|
@@ -891,6 +186,12 @@ export declare class SshTui {
|
|
|
891
186
|
private lastStatsTurn;
|
|
892
187
|
private scrollOffset;
|
|
893
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>>;
|
|
894
195
|
private streamingReasoning;
|
|
895
196
|
private escapeBuffer;
|
|
896
197
|
private escapeTimer;
|
|
@@ -898,9 +199,13 @@ export declare class SshTui {
|
|
|
898
199
|
private waitStartedAt;
|
|
899
200
|
private completionSignaled;
|
|
900
201
|
private replaying;
|
|
202
|
+
/** Display-line budget for the first paint after resume; 0 = full transcript. */
|
|
203
|
+
private paintTailBudget;
|
|
901
204
|
private completedAt;
|
|
902
205
|
private lastTitleUpdateAt;
|
|
903
206
|
private lastPaintRows;
|
|
207
|
+
private lastPaintCursorColumn;
|
|
208
|
+
private lastPaintCursorRow;
|
|
904
209
|
private lastChromeKey;
|
|
905
210
|
private lastPaintWidth;
|
|
906
211
|
private lastPaintHeight;
|
|
@@ -991,6 +296,10 @@ export declare class SshTui {
|
|
|
991
296
|
private exitProcess;
|
|
992
297
|
/** Capture one painted frame. Used by README screenshot fixtures. */
|
|
993
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;
|
|
994
303
|
private screenColumns;
|
|
995
304
|
private screenRows;
|
|
996
305
|
private write;
|
|
@@ -1069,6 +378,18 @@ export declare class SshTui {
|
|
|
1069
378
|
private playCompletionSignal;
|
|
1070
379
|
private render;
|
|
1071
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;
|
|
1072
393
|
/**
|
|
1073
394
|
* Apply the TUI's subagent model selection to every child-agent request.
|
|
1074
395
|
* The parent request is left untouched (its own `/model` waterfall already
|
|
@@ -1119,8 +440,16 @@ export declare class SshTui {
|
|
|
1119
440
|
* 'allow' | 'deny', or undefined when the reviewer is unavailable or its
|
|
1120
441
|
* output was unusable (caller falls back to prompt/reject).
|
|
1121
442
|
*/
|
|
443
|
+
private latestUserAuthorizationText;
|
|
1122
444
|
private reviewUnknownWithModel;
|
|
1123
445
|
private recordAutoApproval;
|
|
446
|
+
/**
|
|
447
|
+
* Host ApprovalOutcome cannot carry a reason, so the model only sees
|
|
448
|
+
* `the user rejected tool "bash"`. Steer a plugin notice with the real
|
|
449
|
+
* classifier/reviewer reason. Summary matches the workspace decision row
|
|
450
|
+
* so the handler does not paint the body twice.
|
|
451
|
+
*/
|
|
452
|
+
private tellModelApprovalDenied;
|
|
1124
453
|
readonly handleApproval: (request: ApprovalRequest, _next: () => Promise<ApprovalOutcome>) => Promise<ApprovalOutcome>;
|
|
1125
454
|
readonly handleUserQuestions: (request: AskUserQuestionRequest) => Promise<AskUserQuestionAnswer>;
|
|
1126
455
|
/** Queue one dialog behind an already-open one instead of overwriting it. */
|
|
@@ -1249,8 +578,10 @@ export declare class SshTui {
|
|
|
1249
578
|
/** Idempotently source $DSH_HOME/env.sh from the user's POSIX shell rc files. */
|
|
1250
579
|
private ensurePosixEnvHook;
|
|
1251
580
|
private handleEscape;
|
|
1252
|
-
/** Toggle the collapsible row under a click
|
|
1253
|
-
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;
|
|
1254
585
|
private scrollInspectOrTranscript;
|
|
1255
586
|
private handleCtrlC;
|
|
1256
587
|
private submit;
|
|
@@ -1275,4 +606,3 @@ export declare class SshTui {
|
|
|
1275
606
|
* @returns lifecycle controller used by the Cordis effect disposer.
|
|
1276
607
|
*/
|
|
1277
608
|
export declare function mountTui(ctx: Context, config: TuiConfig): TuiController;
|
|
1278
|
-
export {};
|