dsh-ssh-tui 0.3.5 → 0.3.6

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.
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Remember the last model/effort per provider so /model and /setup can switch
3
+ * routes without wiping the previous provider's choice.
4
+ */
5
+ import z from '@deepseek-ai/schemastery';
6
+ import type { Context } from '@deepseek-ai/cordis';
7
+ export declare const ROUTE_MEMORY_NAMESPACE: import("@deepseek-ai/dsh-settings").SettingsNamespace;
8
+ /** Settings schema for `$DSH_HOME/settings.yaml` under ssh-tui-routes. */
9
+ export declare const ROUTE_MEMORY_SCHEMA: z<Schemastery.ObjectS<{
10
+ providers: z<import("@deepseek-ai/cosmokit").Dict<{
11
+ model?: string | null | undefined;
12
+ reasoningEffort?: string | null | undefined;
13
+ } & import("@deepseek-ai/cosmokit").Dict, string>, import("@deepseek-ai/cosmokit").Dict<Schemastery.ObjectT<{
14
+ model: z<string, string>;
15
+ reasoningEffort: z<string, string>;
16
+ }>, string>>;
17
+ }>, Schemastery.ObjectT<{
18
+ providers: z<import("@deepseek-ai/cosmokit").Dict<{
19
+ model?: string | null | undefined;
20
+ reasoningEffort?: string | null | undefined;
21
+ } & import("@deepseek-ai/cosmokit").Dict, string>, import("@deepseek-ai/cosmokit").Dict<Schemastery.ObjectT<{
22
+ model: z<string, string>;
23
+ reasoningEffort: z<string, string>;
24
+ }>, string>>;
25
+ }>>;
26
+ export interface RememberedRoute {
27
+ model: string;
28
+ reasoningEffort?: string;
29
+ }
30
+ export type RouteMemoryMap = Record<string, RememberedRoute>;
31
+ export declare function parseRouteMemory(raw: unknown): RouteMemoryMap;
32
+ export declare function rememberedRouteFor(memory: RouteMemoryMap, provider: string): RememberedRoute | undefined;
33
+ /** Register the route-memory settings section so /model and /provider can persist. */
34
+ export declare function installRouteMemory(ctx: Context): void;
35
+ export declare function upsertRememberedRoute(memory: RouteMemoryMap, provider: string, route: RememberedRoute): RouteMemoryMap;
@@ -173,6 +173,11 @@ export interface TuiController {
173
173
  dispose(): Promise<void>;
174
174
  }
175
175
  export type PaintLinkKind = 'local' | 'ssh';
176
+ /** Compact token count, matching the web stats line (517 / 12.2K / 1.2M). */
177
+ export declare function formatTokens(n: number): string;
178
+ /** Compact duration, matching the web stats line (45.2s / 2m42s). */
179
+ export declare function formatDuration(ms: number): string;
180
+ export declare function formatTokensPerSecond(tokensPerSecond: number): string;
176
181
  /**
177
182
  * Explicit env/config always wins. Otherwise local TTYs stay snappy and SSH
178
183
  * sessions pick a tier from a measured round-trip (CSI 6n), falling back to
@@ -187,6 +192,73 @@ export declare function detectSshSession(env?: NodeJS.ProcessEnv): boolean;
187
192
  /** Map a CSI-6n round-trip to a paint cadence. Unknown RTT uses the SSH default. */
188
193
  export declare function paintIntervalForRtt(rttMs: number | undefined): number;
189
194
  export declare function paintLinkLabel(kind: PaintLinkKind, intervalMs: number, probed: boolean): string;
195
+ export type LinkQuality = 'local' | 'good' | 'ok' | 'slow' | 'poor' | 'unknown';
196
+ /** Signal-bar quality from a measured SSH round-trip, or local TTY. */
197
+ export declare function linkQualityOf(kind: PaintLinkKind, rttMs: number | undefined): LinkQuality;
198
+ /** How many filled signal pips: 4 local/fast, 3 ok, 2 slow, 1 poor, 0 unknown. */
199
+ export declare function linkSignalPips(quality: LinkQuality): number;
200
+ /** Compact footer chip: `SSH ●●●○ 90ms` — 1 pip red, 2 yellow, 3+ green. */
201
+ export declare function formatLinkQualityChip(kind: PaintLinkKind, intervalMs: number, rttMs: number | undefined, probed: boolean, color?: boolean): string;
202
+ export declare function providerShortCode(provider: string): string;
203
+ export interface FooterStatsInput {
204
+ turns: number;
205
+ steps: number;
206
+ llmMs: number;
207
+ toolMs: number;
208
+ ttftMs: number;
209
+ ttftSteps: number;
210
+ decodeMs: number;
211
+ decodeTokens: number;
212
+ inputTokens: number;
213
+ outputTokens: number;
214
+ cacheReadTokens: number;
215
+ cacheWriteTokens: number;
216
+ }
217
+ /** Stats groups in drop order (last is dropped first when the row is too wide). */
218
+ export declare function footerStatsGroups(stats: FooterStatsInput): string[];
219
+ export declare function fitFooterStatsLine(chip: string, groups: readonly string[], width: number): string;
220
+ export type FooterActivityKind = 'plan-review' | 'waiting' | 'compacting' | 'retry' | 'subagents' | 'tools' | 'plan-open' | 'plan-pending' | 'goal' | 'waiting-llm' | 'idle';
221
+ export interface FooterStatusInput {
222
+ running: boolean;
223
+ planReview: boolean;
224
+ waitingQuestion: boolean;
225
+ compacting: boolean;
226
+ retry?: {
227
+ retry: number;
228
+ maxRetries: number;
229
+ };
230
+ subagents: number;
231
+ tools: number;
232
+ planLeftOpen: boolean;
233
+ planPending: boolean;
234
+ planActive: boolean;
235
+ goalPhase?: 'active' | 'paused' | 'blocked';
236
+ idleMs: number;
237
+ model: string;
238
+ effort?: string;
239
+ preset?: string;
240
+ provider: string;
241
+ parentModel: string;
242
+ subModel: string;
243
+ subDiffers: boolean;
244
+ quotaCode?: string;
245
+ quotaPercent?: number;
246
+ search?: {
247
+ index: number;
248
+ total: number;
249
+ };
250
+ foldedInput: boolean;
251
+ multiLineInput: boolean;
252
+ queued: number;
253
+ }
254
+ export declare function footerActivity(input: FooterStatusInput): {
255
+ kind: FooterActivityKind;
256
+ text: string;
257
+ };
258
+ /** Short remaining-quota bar: 8 pips, filled from the left. */
259
+ export declare function formatQuotaBar(remainingPercent: number, width?: number): string;
260
+ export declare function footerIdentityParts(input: FooterStatusInput): string[];
261
+ export declare function fitFooterStatusLine(activity: string, identity: readonly string[], width: number): string;
190
262
  /** One incremental paint as a single stdout write (one SSH packet when corked). */
191
263
  export declare function composePaintOutput(options: {
192
264
  width: number;
@@ -196,6 +268,7 @@ export declare function composePaintOutput(options: {
196
268
  sizeChanged: boolean;
197
269
  chromeChanged: boolean;
198
270
  chromeStart: number;
271
+ previousChromeStart?: number;
199
272
  cursorRow: number;
200
273
  cursorColumn: number;
201
274
  }): string;
@@ -303,6 +376,23 @@ export declare function formatQuotaSnapshot(snapshot: QuotaSnapshot): string;
303
376
  export declare function tightestQuotaWindow(snapshot: QuotaSnapshot): QuotaWindow | undefined;
304
377
  /** Render the OpenCode Go quota payload as a transcript block. */
305
378
  export declare function formatOpenCodeGoUsage(payload: unknown, source: OpenCodeSource): string;
379
+ export interface AccountBalanceLine {
380
+ label: string;
381
+ amount: string;
382
+ currency?: string;
383
+ }
384
+ export interface AccountBalanceSnapshot {
385
+ provider: string;
386
+ plan: string;
387
+ available?: boolean;
388
+ lines: AccountBalanceLine[];
389
+ sourcePath?: string;
390
+ }
391
+ export declare function joinUrl(base: string, path: string): string;
392
+ export declare function parseDeepSeekBalance(payload: unknown, provider?: string): AccountBalanceSnapshot;
393
+ /** Best-effort parse of OpenAI-compatible credit/balance JSON. */
394
+ export declare function parseOpenAiCompatibleBalance(payload: unknown, provider: string, path: string): AccountBalanceSnapshot | undefined;
395
+ export declare function formatAccountBalance(snapshot: AccountBalanceSnapshot): string;
306
396
  /** Whether `text` could still grow into a recognized escape sequence. */
307
397
  export declare function isEscapePrefix(text: string): boolean;
308
398
  /** Parse a Device Status Report cursor reply (`CSI row;col R`). */
@@ -417,11 +507,6 @@ export declare function parseExitStatus(text: string): {
417
507
  exitCode?: number;
418
508
  signal?: string;
419
509
  };
420
- /** Compact token count, matching the web stats line (517 / 12.2K / 1.2M). */
421
- export declare function formatTokens(n: number): string;
422
- /** Compact duration, matching the web stats line (45.2s / 2m42s). */
423
- export declare function formatDuration(ms: number): string;
424
- export declare function formatTokensPerSecond(tokensPerSecond: number): string;
425
510
  /** Owns one interactive terminal channel and its agent event wiring. */
426
511
  export declare class SshTui {
427
512
  private readonly ctx;
@@ -491,9 +576,11 @@ export declare class SshTui {
491
576
  private lastChromeKey;
492
577
  private lastPaintWidth;
493
578
  private lastPaintHeight;
579
+ private lastChromeStart;
494
580
  private paintIntervalMs;
495
581
  private paintLink;
496
582
  private paintProbed;
583
+ private paintRttMs;
497
584
  private sessionTitle;
498
585
  private llmRetry;
499
586
  private quotaSnapshot;
@@ -564,7 +651,7 @@ export declare class SshTui {
564
651
  private currentSelectionLabel;
565
652
  /** Replace one step's usage sample so a repeated report never double counts. */
566
653
  private recordUsage;
567
- /** The web-aligned session stats strip: counts, timings, cache, tokens. */
654
+ /** Compact session stats groups for the first footer row. */
568
655
  private statsText;
569
656
  /** Refresh the terminal window title (throttled while running). */
570
657
  private updateTerminalTitle;
@@ -641,9 +728,14 @@ export declare class SshTui {
641
728
  private listSelectableProviders;
642
729
  /** Built-in SuperGrok catalog used when the live adapter list is still warming up. */
643
730
  private static readonly XAI_FALLBACK_MODELS;
644
- /** /model: stay on the current provider by default; switching providers is opt-in. */
731
+ private loadModelOptions;
732
+ /** /model: models and effort for the current provider only. */
645
733
  private runModelCommand;
734
+ /** /provider: pick a provider, then its model (remembered route pre-filled). */
735
+ private runProviderCommand;
646
736
  /** Persist a provider/model/effort choice and keep the subagent on the same family. */
737
+ private rememberedRoute;
738
+ private rememberRoute;
647
739
  private applyModelSelection;
648
740
  /** Provider route the next subagent request should use. */
649
741
  private effectiveSubagentProvider;
@@ -653,6 +745,8 @@ export declare class SshTui {
653
745
  * switching to xAI is treated as stale.
654
746
  */
655
747
  private syncSubagentToProvider;
748
+ private promptSubagentAfterProviderSwitch;
749
+ private clearQuotaForProvider;
656
750
  /** Persist one subagent selection and publish it to the live request waterfall. */
657
751
  private saveSubagentSelection;
658
752
  /** Resolve the picker model list for one provider (endpoint first, then catalog). */
@@ -673,10 +767,11 @@ export declare class SshTui {
673
767
  private fetchOpenCodeGoUsage;
674
768
  /** Explain Zen metered billing instead of pretending it has a quota. */
675
769
  private zenUsageText;
676
- /** /usage and /quota: remaining quota for the current subscription provider. */
770
+ /** /usage and /balance: remaining quota or prepaid balance for the current provider. */
677
771
  private runUsageCommand;
678
772
  private applyQuotaSnapshot;
679
773
  private refreshQuota;
774
+ private fetchAccountBalance;
680
775
  private fetchQuotaSnapshot;
681
776
  private resolveSuperGrokToken;
682
777
  private fetchJson;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ssh-tui",
3
- "version": "0.3.5",
3
+ "version": "0.3.6",
4
4
  "description": "SSH-friendly interactive terminal TUI plugin for DeepSeek Harness",
5
5
  "keywords": [
6
6
  "deepseek-harness",