dsh-ssh-tui 0.8.1 → 0.8.2

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.
Files changed (93) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/README.en.md +118 -15
  3. package/README.md +78 -13
  4. package/docs/release-notes-0.7.4.md +91 -0
  5. package/docs/release-notes-0.8.0.md +56 -0
  6. package/docs/release-notes-0.8.1.md +79 -0
  7. package/docs/release-notes-0.8.2-rc.1.md +159 -0
  8. package/docs/release-notes-0.8.2.md +62 -0
  9. package/docs/screenshots/reconnect.gif +0 -0
  10. package/docs/terminals.md +23 -0
  11. package/docs/windows.md +13 -0
  12. package/lib/approval-state.js +148 -0
  13. package/lib/approval-state.js.map +1 -0
  14. package/lib/auth-failure.js +38 -0
  15. package/lib/auth-failure.js.map +1 -1
  16. package/lib/color-depth.js +26 -0
  17. package/lib/color-depth.js.map +1 -1
  18. package/lib/copy-text.js +30 -8
  19. package/lib/copy-text.js.map +1 -1
  20. package/lib/dialogs.js +81 -0
  21. package/lib/dialogs.js.map +1 -1
  22. package/lib/display-sock.js +138 -23
  23. package/lib/display-sock.js.map +1 -1
  24. package/lib/footer-accents.js +28 -0
  25. package/lib/footer-accents.js.map +1 -0
  26. package/lib/footer-budget.js +328 -0
  27. package/lib/footer-budget.js.map +1 -0
  28. package/lib/footer-format.js +433 -0
  29. package/lib/footer-format.js.map +1 -0
  30. package/lib/footer-layout.js +407 -0
  31. package/lib/footer-layout.js.map +1 -0
  32. package/lib/footer-meters.js +185 -0
  33. package/lib/footer-meters.js.map +1 -0
  34. package/lib/footer.js +19 -558
  35. package/lib/footer.js.map +1 -1
  36. package/lib/i18n/en.js +65 -5
  37. package/lib/i18n/en.js.map +1 -1
  38. package/lib/i18n/zh.js +67 -5
  39. package/lib/i18n/zh.js.map +1 -1
  40. package/lib/paint.js +53 -8
  41. package/lib/paint.js.map +1 -1
  42. package/lib/plan-projection.js +291 -0
  43. package/lib/plan-projection.js.map +1 -0
  44. package/lib/plan.js +50 -0
  45. package/lib/plan.js.map +1 -1
  46. package/lib/question-state.js +83 -0
  47. package/lib/question-state.js.map +1 -0
  48. package/lib/representation.js +283 -0
  49. package/lib/representation.js.map +1 -0
  50. package/lib/screen.js +105 -0
  51. package/lib/screen.js.map +1 -0
  52. package/lib/selection.js +5 -3
  53. package/lib/selection.js.map +1 -1
  54. package/lib/startup.js +49 -0
  55. package/lib/startup.js.map +1 -1
  56. package/lib/stats.js +101 -3
  57. package/lib/stats.js.map +1 -1
  58. package/lib/term-text.js +154 -55
  59. package/lib/term-text.js.map +1 -1
  60. package/lib/theme.js +20 -3
  61. package/lib/theme.js.map +1 -1
  62. package/lib/throughput.js +305 -0
  63. package/lib/throughput.js.map +1 -0
  64. package/lib/tool-present.js +57 -7
  65. package/lib/tool-present.js.map +1 -1
  66. package/lib/tui.js +3776 -1105
  67. package/lib/tui.js.map +1 -1
  68. package/lib/types/approval-state.d.ts +75 -0
  69. package/lib/types/auth-failure.d.ts +25 -0
  70. package/lib/types/color-depth.d.ts +21 -0
  71. package/lib/types/copy-text.d.ts +18 -1
  72. package/lib/types/dialogs.d.ts +111 -1
  73. package/lib/types/display-sock.d.ts +15 -0
  74. package/lib/types/footer-accents.d.ts +22 -0
  75. package/lib/types/footer-budget.d.ts +204 -0
  76. package/lib/types/footer-format.d.ts +221 -0
  77. package/lib/types/footer-layout.d.ts +292 -0
  78. package/lib/types/footer-meters.d.ts +151 -0
  79. package/lib/types/footer.d.ts +19 -269
  80. package/lib/types/paint.d.ts +48 -0
  81. package/lib/types/plan-projection.d.ts +162 -0
  82. package/lib/types/plan.d.ts +13 -0
  83. package/lib/types/question-state.d.ts +96 -0
  84. package/lib/types/representation.d.ts +498 -0
  85. package/lib/types/screen.d.ts +126 -0
  86. package/lib/types/startup.d.ts +24 -0
  87. package/lib/types/stats.d.ts +64 -1
  88. package/lib/types/term-text.d.ts +45 -1
  89. package/lib/types/throughput.d.ts +163 -0
  90. package/lib/types/tool-present.d.ts +41 -0
  91. package/lib/types/transcript-types.d.ts +63 -2
  92. package/lib/types/tui.d.ts +862 -11
  93. package/package.json +16 -6
@@ -0,0 +1,433 @@
1
+ /**
2
+ * Presentation formatting: a value in, text out.
3
+ *
4
+ * Pure functions that know nothing about rows or widths, and exist as their own
5
+ * module because the *same* reading is painted in several places (the status row,
6
+ * the workspace row, `/status`, a transcript chip) and those call sites must not
7
+ * each grow their own spelling of it.
8
+ *
9
+ * It also owns the context-pressure reading — parsing DSH's `contextPressure`,
10
+ * its bands, and its alert text. That is a deliberate exception to "formatting
11
+ * only": the chip, the status line and the thresholds are one decision about one
12
+ * number, and splitting them would let the painted level drift from the level
13
+ * compaction acts on.
14
+ *
15
+ * @module dsh-ssh-tui/footer-format
16
+ */
17
+ import { t } from './i18n/index.js';
18
+ import { activeTheme, themeThresholdToken } from './theme.js';
19
+ import { commandCodeSourceFor, openCodeSourceFor, } from './quota.js';
20
+ /** Compact token count, matching the web stats line (517 / 12.2K / 1.2M). */
21
+ export function formatTokens(n) {
22
+ const scaled = (value) => value >= 100 ? String(Math.round(value)) : String(Math.round(value * 10) / 10);
23
+ if (n < 1_000)
24
+ return String(n);
25
+ if (n < 1_000_000)
26
+ return `${scaled(n / 1_000)}K`;
27
+ return `${scaled(n / 1_000_000)}M`;
28
+ }
29
+ /**
30
+ * Prompt occupancy of the next request, from DSH `contextPressure`.
31
+ * Provider-agnostic: uses the routed model's advertised window, not a
32
+ * hardcoded xAI size. Compaction-basic still owns in-turn pressure at 80%.
33
+ */
34
+ export const CONTEXT_PRESSURE_WARN_RATIO = 0.8;
35
+ export const CONTEXT_PRESSURE_DANGER_RATIO = 0.95;
36
+ /** Idle auto-compact starts here so recovery finishes before the 80% in-turn trigger. */
37
+ export const CONTEXT_IDLE_COMPACT_RATIO = 0.72;
38
+ /** Prompt-side occupancy of one usage sample: uncached input plus cache traffic. */
39
+ export function promptPressureTokens(usage) {
40
+ return usage.inputTokens + (usage.cacheReadTokens ?? 0) + (usage.cacheWriteTokens ?? 0);
41
+ }
42
+ /** Prefer the next-request projection; fall back to last-request pressure. */
43
+ export function contextPressureUsedTokens(pressure) {
44
+ if (pressure === undefined)
45
+ return undefined;
46
+ if (typeof pressure.projectedTokens === 'number' && Number.isFinite(pressure.projectedTokens)) {
47
+ return Math.max(0, pressure.projectedTokens);
48
+ }
49
+ if (typeof pressure.pressureTokens === 'number' && Number.isFinite(pressure.pressureTokens)) {
50
+ return Math.max(0, pressure.pressureTokens);
51
+ }
52
+ return undefined;
53
+ }
54
+ export function parseContextPressure(value) {
55
+ if (value === null || typeof value !== 'object')
56
+ return undefined;
57
+ const raw = value;
58
+ const window = typeof raw.contextWindow === 'number' && Number.isFinite(raw.contextWindow)
59
+ ? raw.contextWindow
60
+ : undefined;
61
+ if (window === undefined || window <= 0)
62
+ return undefined;
63
+ const used = contextPressureUsedTokens({
64
+ ...(typeof raw.projectedTokens === 'number' ? { projectedTokens: raw.projectedTokens } : {}),
65
+ ...(typeof raw.pressureTokens === 'number' ? { pressureTokens: raw.pressureTokens } : {}),
66
+ });
67
+ if (used === undefined)
68
+ return undefined;
69
+ return { usedTokens: used, contextWindow: window };
70
+ }
71
+ export function contextPressureView(sample) {
72
+ const percent = (sample.usedTokens / sample.contextWindow) * 100;
73
+ return {
74
+ usedTokens: sample.usedTokens,
75
+ contextWindow: sample.contextWindow,
76
+ percent,
77
+ level: percent >= CONTEXT_PRESSURE_DANGER_RATIO * 100
78
+ ? 'danger'
79
+ : percent >= CONTEXT_PRESSURE_WARN_RATIO * 100
80
+ ? 'warn'
81
+ : 'ok',
82
+ };
83
+ }
84
+ /**
85
+ * 8-segment Braille ring. Empty `⣀`; full `⣿`. Width is always 1 cell.
86
+ * Index is `ceil(percent / 12.5)` clamped to 0..8.
87
+ */
88
+ export const CONTEXT_RING_EMPTY = '⣀';
89
+ export const CONTEXT_RING_SEGMENTS = ['⣀', '⠉', '⠋', '⠛', '⠞', '⠟', '⠿', '⡿', '⣿'];
90
+ /** The full cell of the same Braille family, for bars built like the ring. */
91
+ export const CONTEXT_RING_FULL = '⣿';
92
+ export function formatContextPressureRing(percent) {
93
+ if (!Number.isFinite(percent) || percent <= 0)
94
+ return CONTEXT_RING_EMPTY;
95
+ const filled = Math.min(8, Math.max(0, Math.ceil(percent / 12.5)));
96
+ return CONTEXT_RING_SEGMENTS[filled] ?? '⣿';
97
+ }
98
+ export function contextPressureRingColor(level) {
99
+ return themeThresholdToken(activeTheme(), level === 'danger' ? 'over' : level === 'warn' ? 'warn' : 'ok');
100
+ }
101
+ export function formatContextPressureChip(view, color = false) {
102
+ const ring = formatContextPressureRing(view.percent);
103
+ const painted = color
104
+ ? `\x1b[${contextPressureRingColor(view.level)}m${ring}\x1b[0m`
105
+ : ring;
106
+ return t('footer.contextRing', {
107
+ ring: painted,
108
+ used: formatTokens(view.usedTokens),
109
+ window: formatTokens(view.contextWindow),
110
+ percent: Math.round(view.percent),
111
+ });
112
+ }
113
+ export function formatContextPressureStatusLine(view) {
114
+ if (view === undefined)
115
+ return t('status.contextNone');
116
+ return t('status.contextLine', {
117
+ used: formatTokens(view.usedTokens),
118
+ window: formatTokens(view.contextWindow),
119
+ percent: view.percent.toFixed(1),
120
+ level: t(`status.contextLevel.${view.level}`),
121
+ });
122
+ }
123
+ export function contextPressureAlertText(view) {
124
+ const vars = {
125
+ used: formatTokens(view.usedTokens),
126
+ window: formatTokens(view.contextWindow),
127
+ percent: view.percent.toFixed(0),
128
+ };
129
+ return view.level === 'danger'
130
+ ? t('context.alertDanger', vars)
131
+ : t('context.alertWarn', vars);
132
+ }
133
+ export function shouldIdleAutoCompact(view) {
134
+ if (view === undefined)
135
+ return false;
136
+ return view.usedTokens / view.contextWindow >= CONTEXT_IDLE_COMPACT_RATIO;
137
+ }
138
+ /**
139
+ * Compact elapsed time for the activity chip: `28s`, `3m12s`, `1h04m`.
140
+ *
141
+ * Distinct from {@link formatDuration} on purpose: that one is a session
142
+ * statistic (`45.2s`), where a decimal is informative, while this one ticks
143
+ * every second beside a spinner and should move in whole units.
144
+ */
145
+ export function formatElapsedShort(ms) {
146
+ const seconds = Math.max(0, Math.round(ms / 1_000));
147
+ if (seconds < 60)
148
+ return `${seconds}s`;
149
+ const minutes = Math.floor(seconds / 60);
150
+ if (minutes < 60)
151
+ return `${minutes}m${String(seconds % 60).padStart(2, '0')}s`;
152
+ const hours = Math.floor(minutes / 60);
153
+ return `${hours}h${String(minutes % 60).padStart(2, '0')}m`;
154
+ }
155
+ /** Compact duration, matching the web stats line (45.2s / 2m42s). */
156
+ export function formatDuration(ms) {
157
+ const seconds = ms / 1_000;
158
+ if (seconds < 60)
159
+ return `${Math.round(seconds * 10) / 10}s`;
160
+ const whole = Math.round(seconds);
161
+ return `${Math.floor(whole / 60)}m${whole % 60}s`;
162
+ }
163
+ /**
164
+ * @deprecated Legacy surface, removed in 0.9.
165
+ *
166
+ * The default row stopped using this when the footer became the status row
167
+ * (`docs/plans/footer-debt.md`, D-7): what is left of it is the previous
168
+ * generation's fitting and formatting, kept exported so 0.8.x does not break an
169
+ * importer. New callers want the budget module's `runtimeStrip`, the meters, or
170
+ * `formatStatusReport` for the spelled-out numbers.
171
+ */
172
+ export function formatTokensPerSecond(tokensPerSecond) {
173
+ // A slow step (a few tokens over tens of seconds) still decoded something;
174
+ // rounding that to "0 tok/s" reads as a stalled model.
175
+ if (!Number.isFinite(tokensPerSecond) || tokensPerSecond <= 0)
176
+ return '0 tok/s';
177
+ if (tokensPerSecond < 0.5)
178
+ return '<1 tok/s';
179
+ return `${Math.round(tokensPerSecond)} tok/s`;
180
+ }
181
+ export function providerShortCode(provider) {
182
+ const id = provider.trim();
183
+ if (id === 'deepseek-official' || id === 'deepseek')
184
+ return t('route.deepseek');
185
+ if (id === 'xai' || id === 'grok' || id.startsWith('xai-'))
186
+ return 'SuperGrok';
187
+ if (id === 'opencode-go')
188
+ return 'OpenCode Go';
189
+ if (id === 'opencode')
190
+ return 'OpenCode Zen';
191
+ return id;
192
+ }
193
+ /** Short remaining-quota bar: 8 pips, filled from the left. */
194
+ export function formatQuotaBar(remainingPercent, width = 8) {
195
+ const remaining = Math.max(0, Math.min(100, remainingPercent));
196
+ const filled = Math.round(remaining / 100 * width);
197
+ return `${'█'.repeat(filled)}${'░'.repeat(width - filled)}`;
198
+ }
199
+ /**
200
+ * `sub:<model>` chip for the identity row: `sub:grok-4.5`, or
201
+ * `sub:grok-4.5(xhigh)` when an explicit `/subeffort` is set.
202
+ *
203
+ * It shows the model name only, like the parent's own chip, unless `/submodel`
204
+ * pinned a different provider — then `sub:xai/grok-4.5` so the foreign route
205
+ * is visible on the identity row as well as the recolored chip.
206
+ */
207
+ export function subagentRouteLabel(model, provider, effort) {
208
+ const id = shortModelName(model);
209
+ if (id === '')
210
+ return '';
211
+ const suffix = effort === undefined || effort.trim() === '' ? '' : `(${effort.trim()})`;
212
+ const host = provider === undefined || provider.trim() === '' ? '' : `${provider.trim()}/`;
213
+ return `sub:${host}${id}${suffix}`;
214
+ }
215
+ /**
216
+ * The model as the footer shows it: the model's own name, without a
217
+ * `provider/model` route prefix.
218
+ *
219
+ * Some providers carry the vendor in the model id (`xai/grok-4.6`,
220
+ * `deepseek-official/deepseek-v4-flash`). The route is worth a row in the header
221
+ * and in `/status`; in the status line it spent cells on something the reader
222
+ * already knows, and it pushed the quota badge towards the drop edge.
223
+ * `sub:` routes keep their provider on purpose — that is a *different* route
224
+ * from the parent's, and hiding it would make the two indistinguishable.
225
+ */
226
+ export function shortModelName(model) {
227
+ const id = model.trim();
228
+ const slash = id.lastIndexOf('/');
229
+ if (slash < 0)
230
+ return id;
231
+ const tail = id.slice(slash + 1).trim();
232
+ // A trailing slash (or a bare `/`) leaves nothing to show: keep the original.
233
+ return tail === '' ? id : tail;
234
+ }
235
+ /**
236
+ * `SuperGrok 5Hr ███████░ 82%` — short plan badge, the window the number belongs
237
+ * to, then the bar.
238
+ *
239
+ * The tags are fixed technical labels (`5Hr` / `1Wk` / `1Mo`) rather than
240
+ * localized words: they sit in a footer that is already fighting for cells, and
241
+ * a window tag that changes with the locale would be unreadable in a screenshot
242
+ * or a bug report. Everything else about the window (label, reset time, detail)
243
+ * stays in `/quota`.
244
+ */
245
+ /**
246
+ * @deprecated Legacy surface, removed in 0.9.
247
+ *
248
+ * The default row stopped using this when the footer became the status row
249
+ * (`docs/plans/footer-debt.md`, D-7): what is left of it is the previous
250
+ * generation's fitting and formatting, kept exported so 0.8.x does not break an
251
+ * importer. New callers want the budget module's `runtimeStrip`, the meters, or
252
+ * `formatStatusReport` for the spelled-out numbers.
253
+ */
254
+ export function formatFooterQuota(percent, code, period) {
255
+ const bar = `${formatQuotaBar(percent)} ${percent.toFixed(0)}%`;
256
+ const tag = quotaWindowTag(period);
257
+ const name = code === undefined ? '' : code.trim();
258
+ return [name, tag, bar].filter(part => part !== '').join(' ');
259
+ }
260
+ /**
261
+ * The quota widget before the first reading arrives, or while the provider
262
+ * cannot be reached: an empty bar and a question mark.
263
+ *
264
+ * Deliberately not `0%`: an unreachable quota API is not a used-up quota, and a
265
+ * number the footer cannot back up is worse than no number. The bar is there
266
+ * from the first frame so the row does not jump when the reading lands.
267
+ */
268
+ /**
269
+ * @deprecated Legacy surface, removed in 0.9.
270
+ *
271
+ * The default row stopped using this when the footer became the status row
272
+ * (`docs/plans/footer-debt.md`, D-7): what is left of it is the previous
273
+ * generation's fitting and formatting, kept exported so 0.8.x does not break an
274
+ * importer. New callers want the budget module's `runtimeStrip`, the meters, or
275
+ * `formatStatusReport` for the spelled-out numbers.
276
+ */
277
+ export function formatQuotaUnknown() {
278
+ return `${formatQuotaBar(0)} ?%`;
279
+ }
280
+ /** Fixed-width tag for the window a footer quota number belongs to. */
281
+ export function quotaWindowTag(period) {
282
+ if (period === 'hourly')
283
+ return '5Hr';
284
+ if (period === 'weekly')
285
+ return '1Wk';
286
+ if (period === 'monthly')
287
+ return '1Mo';
288
+ return '';
289
+ }
290
+ /**
291
+ * The window tag as an out-of-room row spells it: `5Hr` → `5h`, `1Wk` → `1w`.
292
+ *
293
+ * Deliberately not `toLowerCase()`: the tag encodes two facts in three cells
294
+ * (how many, and which unit), and the unit letter is the one worth keeping —
295
+ * `5hr` costs a cell to repeat that it is hours, which the `h` already said.
296
+ */
297
+ export function quotaWindowTagShort(period) {
298
+ if (period === 'hourly')
299
+ return '5h';
300
+ if (period === 'weekly')
301
+ return '1w';
302
+ if (period === 'monthly')
303
+ return '1m';
304
+ return '';
305
+ }
306
+ /**
307
+ * The badge the footer shows instead of the billing plan's own label:
308
+ * `SuperGrok`, `OC·GO` (OpenCode Go), `CC·GOAT` (Command Code Goat).
309
+ *
310
+ * The long names live in `/quota`; this one has to survive next to a model id.
311
+ * Without a `source` (a hand-built snapshot) the plan label is matched instead,
312
+ * so old callers and tests keep a sensible badge.
313
+ */
314
+ export function shortQuotaPlanName(snapshot) {
315
+ const plan = snapshot.plan.trim();
316
+ if (snapshot.source === 'supergrok')
317
+ return 'SuperGrok';
318
+ if (snapshot.source === 'opencode-go')
319
+ return 'OC·GO';
320
+ if (snapshot.source === 'command-code') {
321
+ const tier = plan === '' || plan.toLowerCase() === 'command code' ? '' : plan.toUpperCase();
322
+ return tier === '' ? 'CC' : `CC·${tier}`;
323
+ }
324
+ if (/supergrok/iu.test(plan))
325
+ return 'SuperGrok';
326
+ if (/opencode/iu.test(plan))
327
+ return 'OC·GO';
328
+ if (/goat/iu.test(plan))
329
+ return 'CC·GOAT';
330
+ return plan;
331
+ }
332
+ /**
333
+ * The subscription a session is running on, spelled out for the footer's last
334
+ * part: `OpenCode-GO`, `CommandCode-GOAT`.
335
+ *
336
+ * Only the two generations that carry a *named subscription* get one. SuperGrok
337
+ * already says so in its quota chip's window tag, and DeepSeek is metered (its
338
+ * balance line is the reading), so neither claims a badge here. The spelling is
339
+ * longer than the identity row's old `OC·GO` / `CC·GOAT` on purpose: this one sits
340
+ * at the very end of the row where the least load-bearing part goes, and a reader
341
+ * who still has it on screen reads a plan name rather than an abbreviation.
342
+ *
343
+ * The provider id alone is enough for the Go route; Command Code's *tier* comes
344
+ * from the billing reply, so before the first reading lands the badge names the
345
+ * vendor without claiming a tier it has not seen.
346
+ * @param provider - the live route's provider id.
347
+ * @param snapshot - the quota reading, when it belongs to that provider.
348
+ * @returns the badge, or undefined when this route has none.
349
+ */
350
+ export function planRouteBadge(provider, snapshot) {
351
+ const id = provider.trim();
352
+ const source = snapshot?.source
353
+ ?? (id === 'opencode-go' ? 'opencode-go' : id === 'command-code' ? 'command-code' : undefined);
354
+ if (source === 'opencode-go')
355
+ return 'OpenCode-GO';
356
+ if (source !== 'command-code')
357
+ return undefined;
358
+ const plan = (snapshot?.plan ?? '').trim();
359
+ if (plan === '' || /^command ?code$/iu.test(plan)) {
360
+ // The provider is known and the tier is not: name the vendor, claim nothing.
361
+ return 'CommandCode';
362
+ }
363
+ return `CommandCode-${plan.toUpperCase()}`;
364
+ }
365
+ /**
366
+ * Drop the Go / SuperGrok plan name from a quota identity part, keeping the
367
+ * remaining-percent bar. Returns true when a part was rewritten.
368
+ */
369
+ /**
370
+ * @deprecated Legacy surface, removed in 0.9.
371
+ *
372
+ * The default row stopped using this when the footer became the status row
373
+ * (`docs/plans/footer-debt.md`, D-7): what is left of it is the previous
374
+ * generation's fitting and formatting, kept exported so 0.8.x does not break an
375
+ * importer. New callers want the budget module's `runtimeStrip`, the meters, or
376
+ * `formatStatusReport` for the spelled-out numbers.
377
+ */
378
+ export function dropFooterQuotaPlanName(parts) {
379
+ for (let index = 0; index < parts.length; index++) {
380
+ const part = parts[index];
381
+ if (part === undefined)
382
+ continue;
383
+ const barAt = part.search(/[█░]{8} \d+%$/);
384
+ if (barAt <= 0)
385
+ continue;
386
+ // The window tag is the last thing before the bar and survives the badge:
387
+ // `SuperGrok 5Hr ███ 82%` narrows to `5Hr ███ 82%`, not to a bare bar.
388
+ const tag = /(?:5Hr|1Wk|1Mo)$/u.exec(part.slice(0, barAt).trimEnd())?.[0];
389
+ parts[index] = tag === undefined ? part.slice(barAt) : `${tag} ${part.slice(barAt)}`;
390
+ return true;
391
+ }
392
+ return false;
393
+ }
394
+ /** Human-facing kind for a live LLM route. */
395
+ export function describeProviderRoute(provider) {
396
+ const id = provider.trim();
397
+ if (id === 'deepseek-official' || id === 'deepseek') {
398
+ return { kind: t('route.deepseek'), short: t('route.deepseek') };
399
+ }
400
+ if (id === 'xai' || id === 'grok' || id.startsWith('xai-')) {
401
+ return { kind: t('route.supergrokKind'), short: t('route.supergrokShort') };
402
+ }
403
+ if (id === 'opencode-go')
404
+ return { kind: t('route.go'), short: t('route.go') };
405
+ if (id === 'opencode')
406
+ return { kind: t('route.zen'), short: t('route.zen') };
407
+ return { kind: t('route.registered'), short: id };
408
+ }
409
+ /** Routes that authenticate without a harness API-key credential. */
410
+ export function providerUsesLocalOAuth(provider) {
411
+ const id = provider.trim();
412
+ return id === 'xai' || id === 'grok' || id.startsWith('xai-');
413
+ }
414
+ /**
415
+ * Whether a provider has a quota surface at all, without asking it.
416
+ *
417
+ * The footer paints a quota widget from the first frame — an empty bar and `?%`
418
+ * until a reading arrives — so it needs to tell "this provider will have one"
419
+ * from "this provider reports a balance instead" (DeepSeek) or nothing at all.
420
+ * Every branch is a synchronous settings read, so a repaint never does IO.
421
+ */
422
+ export function providerHasQuotaSurface(provider, llmPiAiSection) {
423
+ const id = provider.trim();
424
+ if (id === '')
425
+ return false;
426
+ if (providerUsesLocalOAuth(id))
427
+ return true;
428
+ if (commandCodeSourceFor(id, llmPiAiSection) !== null)
429
+ return true;
430
+ const source = openCodeSourceFor(id, llmPiAiSection);
431
+ return source !== null && source.flavor === 'go';
432
+ }
433
+ //# sourceMappingURL=footer-format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"footer-format.js","sourceRoot":"","sources":["../src/footer-format.ts"],"names":[],"mappings":"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"}