dsh-ssh-tui 0.7.0-rc.2 → 0.7.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 +133 -64
- package/README.md +75 -75
- package/docs/remote-ops.md +21 -0
- package/lib/color-depth.js +34 -0
- package/lib/color-depth.js.map +1 -1
- package/lib/footer.js +123 -16
- package/lib/footer.js.map +1 -1
- package/lib/quota.js +23 -2
- package/lib/quota.js.map +1 -1
- package/lib/tui.js +94 -11
- package/lib/tui.js.map +1 -1
- package/lib/types/footer.d.ts +67 -7
- package/lib/types/quota.d.ts +17 -0
- package/lib/types/transcript-types.d.ts +8 -0
- package/lib/types/tui.d.ts +19 -2
- package/package.json +1 -1
package/lib/types/footer.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Footer stats, status identity, context-pressure chips, and `/status` report.
|
|
3
3
|
*/
|
|
4
|
-
import { type QuotaSnapshot } from './quota.js';
|
|
4
|
+
import { type QuotaPeriod, type QuotaSnapshot, type QuotaSource } from './quota.js';
|
|
5
5
|
import type { DisconnectPolicyName } from './transcript-types.js';
|
|
6
6
|
export declare const WAIT_INDICATOR_MS = 8000;
|
|
7
7
|
/** Compact token count, matching the web stats line (517 / 12.2K / 1.2M). */
|
|
@@ -135,6 +135,10 @@ export interface FooterStatusInput {
|
|
|
135
135
|
subEffort?: string;
|
|
136
136
|
quotaCode?: string;
|
|
137
137
|
quotaPercent?: number;
|
|
138
|
+
/** Which rolling window `quotaPercent` belongs to: tagged `5Hr`/`1Wk`/`1Mo`. */
|
|
139
|
+
quotaPeriod?: QuotaPeriod;
|
|
140
|
+
/** The provider has a quota surface but no reading yet: paint `░░░░░░░░ ?%`. */
|
|
141
|
+
quotaUnknown?: boolean;
|
|
138
142
|
contextChip?: string;
|
|
139
143
|
balanceText?: string;
|
|
140
144
|
search?: {
|
|
@@ -154,15 +158,62 @@ export declare function footerActivity(input: FooterStatusInput): {
|
|
|
154
158
|
/** Short remaining-quota bar: 8 pips, filled from the left. */
|
|
155
159
|
export declare function formatQuotaBar(remainingPercent: number, width?: number): string;
|
|
156
160
|
/**
|
|
157
|
-
* `sub:<model>` chip for the identity row
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
+
* `sub:<model>` chip for the identity row: `sub:grok-4.5`, or
|
|
162
|
+
* `sub:grok-4.5(xhigh)` when an explicit `/subeffort` is set.
|
|
163
|
+
*
|
|
164
|
+
* It shows the model name only, like the parent's own chip: a `provider/model`
|
|
165
|
+
* prefix on both chips doubled the same route and pushed the quota badge towards
|
|
166
|
+
* the drop edge. The provider is not lost — `/submodel` and `/status` report it,
|
|
167
|
+
* and the child's model name is the part that differs from the parent's.
|
|
161
168
|
*/
|
|
162
169
|
export declare function subagentRouteLabel(model: string, provider?: string, effort?: string): string;
|
|
170
|
+
/**
|
|
171
|
+
* The model as the footer shows it: the model's own name, without a
|
|
172
|
+
* `provider/model` route prefix.
|
|
173
|
+
*
|
|
174
|
+
* Some providers carry the vendor in the model id (`xai/grok-4.6`,
|
|
175
|
+
* `deepseek-official/deepseek-v4-flash`). The route is worth a row in the header
|
|
176
|
+
* and in `/status`; in the status line it spent cells on something the reader
|
|
177
|
+
* already knows, and it pushed the quota badge towards the drop edge.
|
|
178
|
+
* `sub:` routes keep their provider on purpose — that is a *different* route
|
|
179
|
+
* from the parent's, and hiding it would make the two indistinguishable.
|
|
180
|
+
*/
|
|
181
|
+
export declare function shortModelName(model: string): string;
|
|
163
182
|
export declare function footerIdentityParts(input: FooterStatusInput): string[];
|
|
164
|
-
/**
|
|
165
|
-
|
|
183
|
+
/**
|
|
184
|
+
* `SuperGrok 5Hr ███████░ 82%` — short plan badge, the window the number belongs
|
|
185
|
+
* to, then the bar.
|
|
186
|
+
*
|
|
187
|
+
* The tags are fixed technical labels (`5Hr` / `1Wk` / `1Mo`) rather than
|
|
188
|
+
* localized words: they sit in a footer that is already fighting for cells, and
|
|
189
|
+
* a window tag that changes with the locale would be unreadable in a screenshot
|
|
190
|
+
* or a bug report. Everything else about the window (label, reset time, detail)
|
|
191
|
+
* stays in `/quota`.
|
|
192
|
+
*/
|
|
193
|
+
export declare function formatFooterQuota(percent: number, code?: string, period?: QuotaPeriod): string;
|
|
194
|
+
/**
|
|
195
|
+
* The quota widget before the first reading arrives, or while the provider
|
|
196
|
+
* cannot be reached: an empty bar and a question mark.
|
|
197
|
+
*
|
|
198
|
+
* Deliberately not `0%`: an unreachable quota API is not a used-up quota, and a
|
|
199
|
+
* number the footer cannot back up is worse than no number. The bar is there
|
|
200
|
+
* from the first frame so the row does not jump when the reading lands.
|
|
201
|
+
*/
|
|
202
|
+
export declare function formatQuotaUnknown(): string;
|
|
203
|
+
/** Fixed-width tag for the window a footer quota number belongs to. */
|
|
204
|
+
export declare function quotaWindowTag(period: QuotaPeriod | undefined): string;
|
|
205
|
+
/**
|
|
206
|
+
* The badge the footer shows instead of the billing plan's own label:
|
|
207
|
+
* `SuperGrok`, `OC·GO` (OpenCode Go), `CC·GOAT` (Command Code Goat).
|
|
208
|
+
*
|
|
209
|
+
* The long names live in `/quota`; this one has to survive next to a model id.
|
|
210
|
+
* Without a `source` (a hand-built snapshot) the plan label is matched instead,
|
|
211
|
+
* so old callers and tests keep a sensible badge.
|
|
212
|
+
*/
|
|
213
|
+
export declare function shortQuotaPlanName(snapshot: {
|
|
214
|
+
plan: string;
|
|
215
|
+
source?: QuotaSource;
|
|
216
|
+
}): string;
|
|
166
217
|
/**
|
|
167
218
|
* Drop the Go / SuperGrok plan name from a quota identity part, keeping the
|
|
168
219
|
* remaining-percent bar. Returns true when a part was rewritten.
|
|
@@ -198,3 +249,12 @@ export declare function describeProviderRoute(provider: string): {
|
|
|
198
249
|
};
|
|
199
250
|
/** Routes that authenticate without a harness API-key credential. */
|
|
200
251
|
export declare function providerUsesLocalOAuth(provider: string): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Whether a provider has a quota surface at all, without asking it.
|
|
254
|
+
*
|
|
255
|
+
* The footer paints a quota widget from the first frame — an empty bar and `?%`
|
|
256
|
+
* until a reading arrives — so it needs to tell "this provider will have one"
|
|
257
|
+
* from "this provider reports a balance instead" (DeepSeek) or nothing at all.
|
|
258
|
+
* Every branch is a synchronous settings read, so a repaint never does IO.
|
|
259
|
+
*/
|
|
260
|
+
export declare function providerHasQuotaSurface(provider: string, llmPiAiSection: unknown): boolean;
|
package/lib/types/quota.d.ts
CHANGED
|
@@ -62,6 +62,12 @@ export interface CommandCodeSource {
|
|
|
62
62
|
*/
|
|
63
63
|
export declare function commandCodeSourceFor(provider: string, llmPiAiSection: unknown): CommandCodeSource | null;
|
|
64
64
|
export type QuotaPeriod = 'hourly' | 'weekly' | 'monthly' | 'unknown';
|
|
65
|
+
/**
|
|
66
|
+
* Which billing surface a snapshot came from. The footer shows a short plan
|
|
67
|
+
* badge (`SuperGrok` / `OC·GO` / `CC·GOAT`), and the provider string alone is
|
|
68
|
+
* not enough to tell the three apart.
|
|
69
|
+
*/
|
|
70
|
+
export type QuotaSource = 'supergrok' | 'opencode-go' | 'command-code';
|
|
65
71
|
export interface QuotaWindow {
|
|
66
72
|
label: string;
|
|
67
73
|
period: QuotaPeriod;
|
|
@@ -74,6 +80,8 @@ export interface QuotaWindow {
|
|
|
74
80
|
export interface QuotaSnapshot {
|
|
75
81
|
provider: string;
|
|
76
82
|
plan: string;
|
|
83
|
+
/** Billing surface, for the footer's short badge. Absent on hand-built snapshots. */
|
|
84
|
+
source?: QuotaSource;
|
|
77
85
|
windows: QuotaWindow[];
|
|
78
86
|
}
|
|
79
87
|
export declare function remainingPercentFromUsed(usedPercent: number): number;
|
|
@@ -118,6 +126,15 @@ export declare function formatQuotaSnapshot(snapshot: QuotaSnapshot): string;
|
|
|
118
126
|
export declare function formatQuotaStatusLine(snapshot: QuotaSnapshot | undefined): string;
|
|
119
127
|
/** Tightest remaining window — used for threshold alerts. */
|
|
120
128
|
export declare function tightestQuotaWindow(snapshot: QuotaSnapshot): QuotaWindow | undefined;
|
|
129
|
+
/**
|
|
130
|
+
* The window the footer shows by default: the *finest* one, not the tightest.
|
|
131
|
+
*
|
|
132
|
+
* A five-hour cap is what runs out first inside a working session, so it is the
|
|
133
|
+
* number a glance should find; a monthly window at 12% would otherwise hide a
|
|
134
|
+
* five-hour window at 3%. Ties (and a provider that reports only one window)
|
|
135
|
+
* fall back to the lowest remaining percent.
|
|
136
|
+
*/
|
|
137
|
+
export declare function preferredQuotaWindow(snapshot: QuotaSnapshot): QuotaWindow | undefined;
|
|
121
138
|
/** Render the OpenCode Go quota payload as a transcript block. */
|
|
122
139
|
export declare function formatOpenCodeGoUsage(payload: unknown, source: OpenCodeSource): string;
|
|
123
140
|
export interface AccountBalanceLine {
|
|
@@ -87,6 +87,14 @@ export type Row = {
|
|
|
87
87
|
* Does not rewrite the session log.
|
|
88
88
|
*/
|
|
89
89
|
turnLeftOpen?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Display-only: the one leftover-todo reminder for this open list has
|
|
92
|
+
* been sent. The model's answer is itself a `todo_write`, so this must
|
|
93
|
+
* survive that patch — otherwise every turn end asks again, and each ask
|
|
94
|
+
* is another model turn. Reset when the list closes, so a list that opens
|
|
95
|
+
* again gets its own single reminder.
|
|
96
|
+
*/
|
|
97
|
+
nudged?: boolean;
|
|
90
98
|
} | {
|
|
91
99
|
kind: 'question';
|
|
92
100
|
questionId: string;
|
package/lib/types/tui.d.ts
CHANGED
|
@@ -28,8 +28,8 @@ import { paintedLinkHits } from './term-text.js';
|
|
|
28
28
|
export type { CollapsibleBlock, DisplayKind, DisconnectPolicyName, PlanTodoItem, Row, SubagentLogEntry, ToolDiffHunk, } from './transcript-types.js';
|
|
29
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
30
|
export { captureHangupSignals, composePaintOutput, detectSshSession, formatLinkQualityChip, ignoreFurtherHangupSignals, isEscapePrefix, findCursorPositionReply, 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, subagentRouteLabel, type ContextPressureSample, type ContextPressureView, type FooterActivityKind, type FooterStatsInput, type FooterStatusInput, type StatusReportInput, } from './footer.js';
|
|
32
|
-
export { commandCodePeriodStart, commandCodeSourceFor, crossedQuotaThresholds, formatAccountBalance, formatFooterBalance, formatOpenCodeGoUsage, formatQuotaSnapshot, formatQuotaStatusLine, joinUrl, openCodeSourceFor, parseCommandCodeQuota, parseDeepSeekBalance, parseOpenAiCompatibleBalance, parseOpenCodeGoQuota, parseSuperGrokBilling, quotaAlertText, quotaRefreshEverySteps, quotaRefreshEveryTurns, remainingPercentFromUsed, tightestQuotaWindow, type AccountBalanceLine, type AccountBalanceSnapshot, type CommandCodeSource, type OpenCodeFlavor, type OpenCodeSource, type QuotaPeriod, type QuotaSnapshot, type QuotaWindow, } from './quota.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, formatQuotaUnknown, formatStatusReport, providerHasQuotaSurface, quotaWindowTag, shortModelName, shortQuotaPlanName, formatTokens, formatTokensPerSecond, parseContextPressure, promptPressureTokens, providerShortCode, providerUsesLocalOAuth, shouldIdleAutoCompact, subagentRouteLabel, type ContextPressureSample, type ContextPressureView, type FooterActivityKind, type FooterStatsInput, type FooterStatusInput, type StatusReportInput, } from './footer.js';
|
|
32
|
+
export { commandCodePeriodStart, commandCodeSourceFor, crossedQuotaThresholds, formatAccountBalance, formatFooterBalance, formatOpenCodeGoUsage, formatQuotaSnapshot, formatQuotaStatusLine, joinUrl, openCodeSourceFor, parseCommandCodeQuota, parseDeepSeekBalance, parseOpenAiCompatibleBalance, parseOpenCodeGoQuota, parseSuperGrokBilling, preferredQuotaWindow, quotaAlertText, quotaRefreshEverySteps, quotaRefreshEveryTurns, remainingPercentFromUsed, tightestQuotaWindow, type AccountBalanceLine, type AccountBalanceSnapshot, type CommandCodeSource, type OpenCodeFlavor, type OpenCodeSource, type QuotaPeriod, type QuotaSnapshot, type QuotaWindow, } from './quota.js';
|
|
33
33
|
export { commandAcceptsAttachments, forEachSessionEvent, isAssistantStreamEvent, isTokenDeltaChunk, listPersistenceHeaders, inspectPersistenceSession, sessionEventType, sessionEvents, settingsNamespace, streamChunkOf, streamFirstTokenTime, streamFrameAttemptId, streamFrameOwner, } from './dsh-compat.js';
|
|
34
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
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';
|
|
@@ -329,6 +329,13 @@ export declare class SshTui {
|
|
|
329
329
|
private quotaAlerted;
|
|
330
330
|
private quotaStepsSinceRefresh;
|
|
331
331
|
private quotaRefreshInFlight;
|
|
332
|
+
/**
|
|
333
|
+
* While the first reading is missing, ask again on this cadence instead of
|
|
334
|
+
* waiting for the next step: a quota API that was down at boot is usually up a
|
|
335
|
+
* few seconds later, and until then the footer shows `?%`.
|
|
336
|
+
*/
|
|
337
|
+
private quotaRetryMs;
|
|
338
|
+
private quotaRetryTimer;
|
|
332
339
|
private contextPressure;
|
|
333
340
|
private contextAlertLevel;
|
|
334
341
|
private idleCompactInFlight;
|
|
@@ -840,6 +847,16 @@ export declare class SshTui {
|
|
|
840
847
|
/** /usage and /balance: remaining quota or prepaid balance for the current provider. */
|
|
841
848
|
private runUsageCommand;
|
|
842
849
|
private applyQuotaSnapshot;
|
|
850
|
+
/** Stop the first-reading retry; the normal cadence owns the refresh now. */
|
|
851
|
+
private clearQuotaRetry;
|
|
852
|
+
/** Ask again soon, but only while the footer still has nothing to show. */
|
|
853
|
+
private armQuotaRetry;
|
|
854
|
+
/**
|
|
855
|
+
* Whether this provider has a quota surface at all. `false` means the footer
|
|
856
|
+
* shows no quota widget — a balance line covers DeepSeek, and a provider with
|
|
857
|
+
* neither gets nothing.
|
|
858
|
+
*/
|
|
859
|
+
private hasQuotaSurface;
|
|
843
860
|
private refreshQuota;
|
|
844
861
|
private fetchAccountBalance;
|
|
845
862
|
private fetchQuotaSnapshot;
|