@linxiraos/pi-tui 1.2.0 → 1.3.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/CHANGELOG.md +188 -120
- package/README.md +36 -0
- package/THIRD-PARTY-NOTICES.txt +55 -5
- package/dist/types/app-keybindings.d.ts +18 -8
- package/dist/types/apps/git/diff-pane.d.ts +5 -0
- package/dist/types/apps/git/git-tui.d.ts +16 -2
- package/dist/types/apps/git/state.d.ts +11 -0
- package/dist/types/autocomplete.d.ts +2 -0
- package/dist/types/charts/chart-svg.d.ts +7 -13
- package/dist/types/chat/advisor-message.d.ts +4 -1
- package/dist/types/chat/assistant-message.d.ts +9 -4
- package/dist/types/chat/figure-markdown.d.ts +7 -2
- package/dist/types/chat/messages.d.ts +3 -1
- package/dist/types/chat/read-tool-group.d.ts +2 -2
- package/dist/types/chat/table-chart.d.ts +11 -15
- package/dist/types/chat/tool-execution.d.ts +32 -20
- package/dist/types/chat/user-message.d.ts +3 -2
- package/dist/types/chrome/countdown-timer.d.ts +3 -2
- package/dist/types/chrome/diff.d.ts +2 -3
- package/dist/types/chrome/transcript-container.d.ts +2 -0
- package/dist/types/components/image.d.ts +2 -0
- package/dist/types/components/markdown.d.ts +49 -3
- package/dist/types/components/text.d.ts +2 -0
- package/dist/types/debug-server.d.ts +2 -0
- package/dist/types/keybinding-matchers.d.ts +6 -0
- package/dist/types/multiplexers/tmux.d.ts +1 -0
- package/dist/types/multiplexers/types.d.ts +6 -0
- package/dist/types/native/backend.d.ts +5 -4
- package/dist/types/native/blobs.d.ts +24 -12
- package/dist/types/overlays/agent-hub-projection.d.ts +10 -5
- package/dist/types/overlays/annotation-overlay.d.ts +19 -0
- package/dist/types/overlays/approval-dialog.d.ts +79 -0
- package/dist/types/overlays/ask-dialog.d.ts +11 -6
- package/dist/types/overlays/btw-history-panel.d.ts +2 -6
- package/dist/types/overlays/hook-editor.d.ts +7 -2
- package/dist/types/overlays/hook-input.d.ts +12 -4
- package/dist/types/overlays/job-tree.d.ts +50 -0
- package/dist/types/overlays/jobs-panel.d.ts +25 -11
- package/dist/types/overlays/login-dialog.d.ts +8 -3
- package/dist/types/overlays/mcp-add-wizard.d.ts +9 -1
- package/dist/types/overlays/model-browser.d.ts +6 -1
- package/dist/types/overlays/model-picker.d.ts +2 -0
- package/dist/types/overlays/pause-screen.d.ts +5 -0
- package/dist/types/overlays/plan-review-overlay.d.ts +4 -0
- package/dist/types/overlays/report-panel.d.ts +5 -1
- package/dist/types/overlays/reset-usage-selector.d.ts +7 -5
- package/dist/types/overlays/session-account-selector.d.ts +4 -0
- package/dist/types/overlays/session-info-overlay.d.ts +7 -3
- package/dist/types/overlays/session-selector.d.ts +3 -1
- package/dist/types/overlays/usage-dashboard.d.ts +6 -6
- package/dist/types/prompt/composer.d.ts +22 -26
- package/dist/types/prompt/custom-editor.d.ts +20 -10
- package/dist/types/prompt/image-references.d.ts +22 -0
- package/dist/types/prompt/internal-url-autocomplete.d.ts +1 -0
- package/dist/types/prompt/macos-spelling.d.ts +2 -1
- package/dist/types/prompt/prose-gate.d.ts +3 -0
- package/dist/types/prompt/queued-messages.d.ts +1 -1
- package/dist/types/prompt/typing-word.d.ts +25 -0
- package/dist/types/prompt/welcome.d.ts +35 -43
- package/dist/types/render/hanging-wrap.d.ts +7 -0
- package/dist/types/render/hyperlink.d.ts +2 -0
- package/dist/types/render/render-utils.d.ts +9 -1
- package/dist/types/render/utils.d.ts +1 -1
- package/dist/types/setup/scenes/splash.d.ts +6 -5
- package/dist/types/status-line/context-usage.d.ts +4 -1
- package/dist/types/status-line/host.d.ts +6 -4
- package/dist/types/status-line/startup.d.ts +6 -6
- package/dist/types/status-line/types.d.ts +3 -0
- package/dist/types/stdin-buffer.d.ts +7 -0
- package/dist/types/terminal-capabilities.d.ts +16 -1
- package/dist/types/terminal-multiplexer.d.ts +7 -0
- package/dist/types/terminal.d.ts +8 -4
- package/dist/types/theme/symbols.d.ts +1 -1
- package/dist/types/theme/theme.d.ts +11 -0
- package/dist/types/thinking.d.ts +5 -0
- package/dist/types/tmux.d.ts +39 -4
- package/dist/types/tools/ast-edit.d.ts +2 -2
- package/dist/types/tools/ast-grep.d.ts +2 -2
- package/dist/types/tools/bash.d.ts +6 -1
- package/dist/types/tools/edit.d.ts +2 -0
- package/dist/types/tools/eval.d.ts +53 -4
- package/dist/types/tools/find.d.ts +14 -4
- package/dist/types/tools/glob.d.ts +3 -3
- package/dist/types/tools/grep.d.ts +2 -2
- package/dist/types/tools/grouped-file-output.d.ts +9 -4
- package/dist/types/tools/native-view.d.ts +1 -1
- package/dist/types/tools/read.d.ts +32 -10
- package/dist/types/tools/renderer.d.ts +2 -0
- package/dist/types/tools/task.d.ts +31 -0
- package/dist/types/tools/write.d.ts +2 -0
- package/dist/types/tui.d.ts +20 -3
- package/package.json +10 -10
- package/src/app-keybindings.d.ts +18 -8
- package/src/app-keybindings.ts +20 -8
- package/src/apps/autoresearch-dashboard.ts +444 -27
- package/src/apps/debug/raw-sse.ts +2 -2
- package/src/apps/git/diff-pane.ts +39 -41
- package/src/apps/git/git-tui.ts +80 -14
- package/src/apps/git/sidebar.ts +10 -1
- package/src/apps/git/state.ts +12 -0
- package/src/autocomplete.d.ts +2 -0
- package/src/autocomplete.ts +21 -19
- package/src/bracketed-paste.ts +9 -2
- package/src/charts/chart-svg.d.ts +7 -13
- package/src/charts/chart-svg.ts +19 -22
- package/src/chat/advisor-message.d.ts +4 -1
- package/src/chat/advisor-message.ts +77 -24
- package/src/chat/assistant-message.d.ts +9 -4
- package/src/chat/assistant-message.ts +127 -31
- package/src/chat/bash-execution.ts +7 -2
- package/src/chat/figure-markdown.d.ts +7 -2
- package/src/chat/figure-markdown.ts +10 -3
- package/src/chat/image-loading.ts +9 -6
- package/src/chat/messages.d.ts +3 -1
- package/src/chat/messages.ts +4 -1
- package/src/chat/read-tool-group.d.ts +2 -2
- package/src/chat/read-tool-group.ts +97 -42
- package/src/chat/svg-figure.ts +3 -1
- package/src/chat/svg-source.ts +6 -3
- package/src/chat/table-chart.d.ts +11 -15
- package/src/chat/table-chart.ts +24 -57
- package/src/chat/tool-execution.d.ts +32 -20
- package/src/chat/tool-execution.ts +103 -36
- package/src/chat/user-message.d.ts +3 -2
- package/src/chat/user-message.ts +54 -34
- package/src/chrome/countdown-timer.ts +3 -3
- package/src/chrome/diff.d.ts +2 -3
- package/src/chrome/diff.ts +4 -9
- package/src/chrome/transcript-container.d.ts +2 -0
- package/src/chrome/transcript-container.ts +212 -28
- package/src/components/editor.ts +12 -12
- package/src/components/image.d.ts +2 -0
- package/src/components/image.ts +54 -20
- package/src/components/markdown.d.ts +49 -3
- package/src/components/markdown.ts +461 -11
- package/src/components/settings-list.ts +2 -4
- package/src/components/text.d.ts +2 -0
- package/src/components/text.ts +11 -1
- package/src/debug-server.d.ts +2 -0
- package/src/debug-server.ts +51 -69
- package/src/hotkeys-markdown.ts +2 -0
- package/src/keybinding-matchers.d.ts +6 -0
- package/src/keybinding-matchers.ts +19 -0
- package/src/multiplexers/tmux.d.ts +1 -0
- package/src/multiplexers/tmux.ts +3 -0
- package/src/multiplexers/types.d.ts +6 -0
- package/src/multiplexers/types.ts +6 -0
- package/src/native/backend.d.ts +5 -4
- package/src/native/backend.ts +13 -5
- package/src/native/blobs.d.ts +24 -12
- package/src/native/blobs.ts +56 -7
- package/src/native/reconcile.ts +43 -21
- package/src/overlays/advisor-config.ts +259 -8
- package/src/overlays/agent-hub-projection.d.ts +10 -5
- package/src/overlays/agent-hub-projection.ts +63 -12
- package/src/overlays/agent-hub.ts +2 -2
- package/src/overlays/annotation-overlay.ts +422 -168
- package/src/overlays/approval-dialog.ts +389 -0
- package/src/overlays/ask-dialog.ts +244 -105
- package/src/overlays/btw-history-panel.ts +208 -147
- package/src/overlays/extensions/extension-list.ts +4 -6
- package/src/overlays/hook-editor.ts +90 -32
- package/src/overlays/hook-input.ts +105 -19
- package/src/overlays/job-tree.ts +177 -0
- package/src/overlays/jobs-panel.ts +222 -142
- package/src/overlays/login-dialog.ts +201 -91
- package/src/overlays/mcp-add-wizard.ts +562 -279
- package/src/overlays/model-browser.ts +32 -7
- package/src/overlays/model-hub.ts +4 -10
- package/src/overlays/model-picker.ts +58 -21
- package/src/overlays/pause-screen.ts +81 -23
- package/src/overlays/plan-review-overlay.ts +16 -0
- package/src/overlays/plugin-selector.ts +17 -1
- package/src/overlays/plugin-settings.ts +8 -2
- package/src/overlays/queue-mode-selector.ts +10 -0
- package/src/overlays/report-panel.ts +6 -2
- package/src/overlays/reset-usage-selector.ts +130 -21
- package/src/overlays/session-account-selector.ts +36 -0
- package/src/overlays/session-info-overlay.ts +199 -76
- package/src/overlays/session-selector.ts +15 -10
- package/src/overlays/settings-selector.ts +3 -0
- package/src/overlays/show-images-selector.ts +1 -0
- package/src/overlays/snapcompact-shape-preview.ts +13 -6
- package/src/overlays/theme-selector.ts +6 -1
- package/src/overlays/thinking-selector.ts +8 -4
- package/src/overlays/tree-selector.ts +117 -2
- package/src/overlays/usage-dashboard.ts +498 -144
- package/src/prompt/composer-cache.ts +4 -6
- package/src/prompt/composer.ts +196 -96
- package/src/prompt/custom-editor.ts +168 -65
- package/src/prompt/image-references.d.ts +22 -0
- package/src/prompt/image-references.ts +79 -2
- package/src/prompt/internal-url-autocomplete.ts +1 -0
- package/src/prompt/macos-spelling.ts +28 -5
- package/src/prompt/prose-gate.ts +3 -0
- package/src/prompt/queued-messages.ts +9 -2
- package/src/prompt/tips.txt +1 -2
- package/src/prompt/typing-word.ts +59 -0
- package/src/prompt/welcome.ts +256 -423
- package/src/render/code-cell.ts +18 -5
- package/src/render/hanging-wrap.d.ts +7 -0
- package/src/render/hanging-wrap.ts +58 -0
- package/src/render/hyperlink.d.ts +2 -0
- package/src/render/hyperlink.ts +5 -0
- package/src/render/render-utils.d.ts +9 -1
- package/src/render/render-utils.ts +16 -2
- package/src/render/utils.d.ts +1 -1
- package/src/render/utils.ts +1 -1
- package/src/render/width-aware-text.ts +6 -5
- package/src/setup/scenes/splash.ts +137 -60
- package/src/status-line/component.ts +23 -10
- package/src/status-line/context-usage.ts +176 -73
- package/src/status-line/footer.ts +18 -35
- package/src/status-line/host.ts +6 -1
- package/src/status-line/segments.ts +16 -5
- package/src/status-line/startup.ts +6 -6
- package/src/status-line/types.ts +1 -0
- package/src/stdin-buffer.d.ts +7 -0
- package/src/stdin-buffer.ts +11 -1
- package/src/terminal-capabilities.d.ts +16 -1
- package/src/terminal-capabilities.ts +66 -28
- package/src/terminal-multiplexer.d.ts +7 -0
- package/src/terminal-multiplexer.ts +14 -0
- package/src/terminal.d.ts +8 -4
- package/src/terminal.ts +160 -46
- package/src/theme/symbols.d.ts +1 -1
- package/src/theme/symbols.ts +1 -0
- package/src/theme/theme-class.ts +1 -0
- package/src/theme/theme.d.ts +11 -0
- package/src/theme/theme.ts +46 -14
- package/src/thinking.d.ts +5 -0
- package/src/thinking.ts +9 -1
- package/src/tmux.d.ts +39 -4
- package/src/tmux.ts +110 -16
- package/src/tools/ask.ts +20 -9
- package/src/tools/ast-edit.d.ts +2 -2
- package/src/tools/ast-edit.ts +30 -7
- package/src/tools/ast-grep.d.ts +2 -2
- package/src/tools/ast-grep.ts +39 -35
- package/src/tools/bash.d.ts +6 -1
- package/src/tools/bash.ts +15 -9
- package/src/tools/debug.ts +2 -1
- package/src/tools/default-renderer.ts +3 -2
- package/src/tools/edit.d.ts +2 -0
- package/src/tools/edit.ts +100 -21
- package/src/tools/eval.d.ts +53 -4
- package/src/tools/eval.ts +173 -137
- package/src/tools/find.d.ts +14 -4
- package/src/tools/find.ts +71 -18
- package/src/tools/glob.d.ts +3 -3
- package/src/tools/glob.ts +51 -17
- package/src/tools/grep.d.ts +2 -2
- package/src/tools/grep.ts +99 -22
- package/src/tools/grouped-file-output.d.ts +9 -4
- package/src/tools/grouped-file-output.ts +21 -6
- package/src/tools/lsp.ts +30 -18
- package/src/tools/mcp.ts +2 -2
- package/src/tools/native-view.d.ts +1 -1
- package/src/tools/native-view.ts +2 -2
- package/src/tools/read.d.ts +32 -10
- package/src/tools/read.ts +89 -43
- package/src/tools/renderer.d.ts +2 -0
- package/src/tools/renderer.ts +2 -0
- package/src/tools/task.d.ts +31 -0
- package/src/tools/task.ts +40 -7
- package/src/tools/todo.ts +3 -2
- package/src/tools/wait.ts +16 -30
- package/src/tools/web-search.ts +2 -1
- package/src/tools/write.d.ts +2 -0
- package/src/tools/write.ts +36 -12
- package/src/tools/yield.ts +2 -2
- package/src/tui.d.ts +20 -3
- package/src/tui.ts +140 -36
- package/src/utils.ts +5 -3
- package/dist/types/tools/eval-format/code-mode-declarations.d.ts +0 -5
- package/src/tools/eval-format/code-mode-declarations.ts +0 -61
|
@@ -143,6 +143,7 @@ export function computeCompactionBoundaries(
|
|
|
143
143
|
|
|
144
144
|
/** Stable inputs used to cache non-message token estimates. */
|
|
145
145
|
export interface NonMessageTokenSource {
|
|
146
|
+
readonly model?: Model;
|
|
146
147
|
readonly systemPrompt?: readonly string[];
|
|
147
148
|
readonly agent?: {
|
|
148
149
|
readonly state?: {
|
|
@@ -272,30 +273,32 @@ export function estimateToolSchemaTokens(tools: ToolSchemaSource, tokenizer: Tok
|
|
|
272
273
|
return tokens;
|
|
273
274
|
}
|
|
274
275
|
|
|
276
|
+
/** Count schemas carried on every request, excluding server-side deferred catalogs. */
|
|
277
|
+
export function estimateContextToolSchemaTokens(
|
|
278
|
+
tools: ToolSchemaSource,
|
|
279
|
+
tokenizer: Tokenizer,
|
|
280
|
+
model: Model | undefined,
|
|
281
|
+
sourceRevision = 0,
|
|
282
|
+
): number {
|
|
283
|
+
return model?.toolSchemasInContext === false ? 0 : estimateToolSchemaTokens(tools, tokenizer, sourceRevision);
|
|
284
|
+
}
|
|
285
|
+
|
|
275
286
|
/**
|
|
276
287
|
* Compute just the NON-MESSAGE token total: system prompt (with its skills
|
|
277
288
|
* section subtracted, since skills are tokenized separately) + system context
|
|
278
289
|
* (the rest of the system-prompt array) + tools + skills.
|
|
279
290
|
*
|
|
280
291
|
* Exposed so callers like `StatusLineComponent` can cache the non-message
|
|
281
|
-
* total separately from the message total.
|
|
282
|
-
*
|
|
283
|
-
* streaming turn. Splitting the two lets the caller refresh each on its own
|
|
284
|
-
* cadence — non-message recomputed only when the inputs identity changes,
|
|
285
|
-
* messages walked incrementally as new entries append.
|
|
292
|
+
* total separately from the growing message total. A model switch can change
|
|
293
|
+
* which tool schemas occupy context without changing the roster.
|
|
286
294
|
*/
|
|
287
|
-
//
|
|
288
|
-
//
|
|
289
|
-
//
|
|
290
|
-
// both, and #estimateStoredContextTokens adds a third. Memoize on the identity
|
|
291
|
-
// of the three input arrays so the expensive parts (system-prompt tokenization
|
|
292
|
-
// and the per-tool JSON.stringify(toolWireSchema) inside estimateToolSchemaTokens)
|
|
293
|
-
// run at most once per input change rather than per call. The identity keys are
|
|
294
|
-
// the same stable references the StatusLineComponent cache already trusts
|
|
295
|
-
// (setSystemPrompt/setTools replace the array reference rather than mutating it).
|
|
295
|
+
// The per-turn threshold and compaction paths call these helpers repeatedly.
|
|
296
|
+
// Cache by prompt, roster, skills, tokenizer, revision, and model schema policy;
|
|
297
|
+
// setSystemPrompt/setTools replace their arrays rather than mutating them.
|
|
296
298
|
interface NonMessageTokenCache {
|
|
297
299
|
systemPromptRef: readonly string[];
|
|
298
300
|
toolsRef: ToolSchemaSource;
|
|
301
|
+
toolSchemasInContext: boolean;
|
|
299
302
|
toolsRevision: number;
|
|
300
303
|
sourceRevision: number;
|
|
301
304
|
skillful: boolean;
|
|
@@ -328,6 +331,7 @@ function nonMessageTokenCacheEntry(
|
|
|
328
331
|
const cachedSession: CachedNonMessageTokenSource = session;
|
|
329
332
|
const systemPromptRef = session.systemPrompt ?? EMPTY_STRING_PARTS;
|
|
330
333
|
const toolsRef = session.agent?.state?.tools ?? EMPTY_TOOLS;
|
|
334
|
+
const toolSchemasInContext = session.model?.toolSchemasInContext !== false;
|
|
331
335
|
const toolsRevision = getToolSchemaMetadataRevision(toolsRef);
|
|
332
336
|
const skillsRef = session.renderedSkills ?? session.skills ?? EMPTY_SKILLS;
|
|
333
337
|
let entry = cachedSession[NON_MESSAGE_TOKEN_CACHE];
|
|
@@ -335,6 +339,7 @@ function nonMessageTokenCacheEntry(
|
|
|
335
339
|
entry &&
|
|
336
340
|
entry.systemPromptRef === systemPromptRef &&
|
|
337
341
|
entry.toolsRef === toolsRef &&
|
|
342
|
+
entry.toolSchemasInContext === toolSchemasInContext &&
|
|
338
343
|
entry.toolsRevision === toolsRevision &&
|
|
339
344
|
entry.sourceRevision === sourceRevision &&
|
|
340
345
|
entry.skillsRef === skillsRef &&
|
|
@@ -345,6 +350,7 @@ function nonMessageTokenCacheEntry(
|
|
|
345
350
|
entry = {
|
|
346
351
|
systemPromptRef,
|
|
347
352
|
toolsRef,
|
|
353
|
+
toolSchemasInContext,
|
|
348
354
|
toolsRevision,
|
|
349
355
|
sourceRevision,
|
|
350
356
|
skillful: true,
|
|
@@ -368,7 +374,7 @@ export function computeNonMessageTokens(
|
|
|
368
374
|
const tools = session.agent?.state?.tools ?? EMPTY_TOOLS;
|
|
369
375
|
const tokens =
|
|
370
376
|
tokenizer.countTokens(Array.from(systemPromptParts, part => part ?? "")) +
|
|
371
|
-
|
|
377
|
+
estimateContextToolSchemaTokens(tools, tokenizer, session.model, sourceRevision);
|
|
372
378
|
entry.tokens = tokens;
|
|
373
379
|
return tokens;
|
|
374
380
|
}
|
|
@@ -400,7 +406,7 @@ export function computeNonMessageBreakdown(
|
|
|
400
406
|
renderedSkills(session.renderedSkills ?? session.skills ?? EMPTY_SKILLS, tools),
|
|
401
407
|
tokenizer,
|
|
402
408
|
);
|
|
403
|
-
const toolsTokens =
|
|
409
|
+
const toolsTokens = estimateContextToolSchemaTokens(tools, tokenizer, session.model, sourceRevision);
|
|
404
410
|
const systemPromptParts = session.systemPrompt ?? EMPTY_STRING_PARTS;
|
|
405
411
|
const systemContextTokens = tokenizer.countTokens(Array.from(systemPromptParts.slice(1), part => part ?? ""));
|
|
406
412
|
const systemPromptTokens = Math.max(0, tokenizer.countTokens(systemPromptParts[0] ?? "") - skillsTokens);
|
|
@@ -742,86 +748,183 @@ function contextMeterParts(
|
|
|
742
748
|
}
|
|
743
749
|
|
|
744
750
|
/**
|
|
745
|
-
*
|
|
746
|
-
*
|
|
747
|
-
*
|
|
748
|
-
|
|
751
|
+
* One line of the native `/context` breakdown: a swatch in the part's bar
|
|
752
|
+
* color, its name, its tokens and its share of the window; the exact count
|
|
753
|
+
* is its tooltip.
|
|
754
|
+
*/
|
|
755
|
+
function contextShareRow(
|
|
756
|
+
key: string,
|
|
757
|
+
role: string,
|
|
758
|
+
swatch: TspSpan,
|
|
759
|
+
label: string,
|
|
760
|
+
tokens: number,
|
|
761
|
+
window: number,
|
|
762
|
+
): NativeNode {
|
|
763
|
+
return node(
|
|
764
|
+
"row",
|
|
765
|
+
{ role, align: "center", title: `${label} · ${tokens.toLocaleString("en-US")} tokens` },
|
|
766
|
+
[
|
|
767
|
+
text([swatch], { role: "zeta.context.swatch", wrap: "none" }),
|
|
768
|
+
text(label, { role: "zeta.context.label", grow: 1, wrap: "none", truncate: "end" }),
|
|
769
|
+
text(formatNumber(tokens), { role: "zeta.context.tokens", wrap: "none" }),
|
|
770
|
+
text(percentString(tokens, window), { role: "zeta.context.share", wrap: "none" }),
|
|
771
|
+
],
|
|
772
|
+
key,
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* The snapcompact estimate as a titled group of lines (what is imaged, how,
|
|
778
|
+
* and what it saves), or a note saying why it is inactive; `undefined` when
|
|
779
|
+
* no snapcompact setting is on.
|
|
780
|
+
*/
|
|
781
|
+
function describeSnapcompact(breakdown: ContextBreakdown): NativeNode | undefined {
|
|
782
|
+
const snap = breakdown.snapcompact;
|
|
783
|
+
if (!snap) return undefined;
|
|
784
|
+
const head = text([span("Snapcompact", "strong"), span(" · estimated savings on the wire", "dim")], {
|
|
785
|
+
role: "zeta.context.snap.head",
|
|
786
|
+
});
|
|
787
|
+
if (!snap.visionCapable) {
|
|
788
|
+
const note = text("Inactive: the model has no image input.", { role: "zeta.context.snap.note" });
|
|
789
|
+
return node("col", { role: "zeta.context.snap" }, [head, note], "snapcompact");
|
|
790
|
+
}
|
|
791
|
+
const lines: { label: string; detail: string; value?: TspSpan }[] = [];
|
|
792
|
+
const sp = snap.systemPrompt;
|
|
793
|
+
if (sp) {
|
|
794
|
+
const label = `System prompt · ${sp.scope === "agents-md" ? "AGENTS.md" : "all"}`;
|
|
795
|
+
if (sp.applied) {
|
|
796
|
+
lines.push({
|
|
797
|
+
label,
|
|
798
|
+
detail: `${formatNumber(sp.textTokens)} text → ${sp.frames} frame${sp.frames === 1 ? "" : "s"} ≈ ${formatNumber(sp.imageTokens)}`,
|
|
799
|
+
value: span(`−${formatNumber(sp.savedTokens)}`, "success"),
|
|
800
|
+
});
|
|
801
|
+
} else {
|
|
802
|
+
const reason =
|
|
803
|
+
sp.reason === "budget"
|
|
804
|
+
? "image budget exhausted"
|
|
805
|
+
: sp.reason === "empty"
|
|
806
|
+
? "nothing to image"
|
|
807
|
+
: "frames would not save tokens";
|
|
808
|
+
lines.push({ label, detail: `Stays text: ${reason}` });
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
const tr = snap.toolResults;
|
|
812
|
+
if (tr) {
|
|
813
|
+
lines.push(
|
|
814
|
+
tr.swapped > 0
|
|
815
|
+
? {
|
|
816
|
+
label: "Tool results",
|
|
817
|
+
detail: `${tr.swapped} of ${tr.total} imaged · ${formatNumber(tr.textTokens)} text → ${tr.frames} frames ≈ ${formatNumber(tr.imageTokens)}`,
|
|
818
|
+
value: span(`−${formatNumber(tr.savedTokens)}`, "success"),
|
|
819
|
+
}
|
|
820
|
+
: { label: "Tool results", detail: `None imaged · ${tr.total} in history` },
|
|
821
|
+
);
|
|
822
|
+
}
|
|
823
|
+
if (snap.savedTokens > 0) {
|
|
824
|
+
lines.push({
|
|
825
|
+
label: "Next request",
|
|
826
|
+
detail: "tokens on the wire",
|
|
827
|
+
value: span(`~${formatNumber(Math.max(0, breakdown.usedTokens - snap.savedTokens))}`, "strong"),
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
const rows = lines.map((line, index) =>
|
|
831
|
+
node(
|
|
832
|
+
"row",
|
|
833
|
+
{ role: "zeta.context.snap.row", align: "baseline" },
|
|
834
|
+
[
|
|
835
|
+
text(line.label, { role: "zeta.context.label", wrap: "none" }),
|
|
836
|
+
text(line.detail, { role: "zeta.context.detail", grow: 1, wrap: "none", truncate: "end" }),
|
|
837
|
+
...(line.value ? [text([line.value], { role: "zeta.context.tokens", wrap: "none" })] : []),
|
|
838
|
+
],
|
|
839
|
+
`snap-${index}`,
|
|
840
|
+
),
|
|
841
|
+
);
|
|
842
|
+
return node("col", { role: "zeta.context.snap" }, [head, ...rows], "snapcompact");
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* The `/context` body for terminals that draw `meter`: the tokens used as
|
|
847
|
+
* the figure that leads, beside the room left before auto-compaction; one
|
|
848
|
+
* stacked bar of the parts (categories, free space as the empty track, the
|
|
849
|
+
* hatched buffer) ticked where compaction fires; the breakdown in the bar's
|
|
850
|
+
* order with free space and the buffer under it; then the snapcompact
|
|
851
|
+
* estimate when one is on. {@link contextUsageHead} names the model.
|
|
749
852
|
*/
|
|
750
853
|
function describeContextFrame(breakdown: ContextBreakdown): NativeNode {
|
|
751
854
|
const { contextWindow: window, usedTokens, freeTokens, autoCompactBufferTokens, thresholdTokens } = breakdown;
|
|
752
855
|
const parts = contextMeterParts(breakdown);
|
|
753
856
|
const used = Math.min(1, usedTokens / window);
|
|
754
|
-
const
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
857
|
+
const room =
|
|
858
|
+
thresholdTokens === undefined
|
|
859
|
+
? `${formatNumber(freeTokens)} free`
|
|
860
|
+
: usedTokens >= thresholdTokens
|
|
861
|
+
? `Past auto-compaction at ${percentString(thresholdTokens, window, 0)}`
|
|
862
|
+
: `${formatNumber(thresholdTokens - usedTokens)} left before auto-compaction at ${percentString(thresholdTokens, window, 0)}`;
|
|
863
|
+
const summary = node(
|
|
864
|
+
"row",
|
|
865
|
+
{ role: "zeta.context.summary", align: "baseline", wrap: true },
|
|
866
|
+
[
|
|
867
|
+
text(
|
|
868
|
+
[
|
|
869
|
+
span(formatNumber(usedTokens), "strong"),
|
|
870
|
+
span(` of ${formatNumber(window)} tokens · ${percentString(usedTokens, window, 0)}`, "dim"),
|
|
871
|
+
],
|
|
872
|
+
{ role: "zeta.context.used", grow: 1, wrap: "none" },
|
|
873
|
+
),
|
|
874
|
+
text(room, { role: "zeta.context.room", wrap: "none" }),
|
|
875
|
+
],
|
|
876
|
+
"summary",
|
|
877
|
+
);
|
|
775
878
|
const marks =
|
|
776
879
|
thresholdTokens !== undefined
|
|
777
880
|
? [
|
|
778
881
|
{
|
|
779
882
|
at: thresholdTokens / window,
|
|
780
883
|
tone: "warning" as const,
|
|
781
|
-
title: `Auto-compaction at ${percentString(thresholdTokens, window, 0)}
|
|
884
|
+
title: `Auto-compaction at ${percentString(thresholdTokens, window, 0)} · ${formatNumber(thresholdTokens)} tokens`,
|
|
782
885
|
},
|
|
783
886
|
]
|
|
784
887
|
: undefined;
|
|
785
|
-
const
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
"bar",
|
|
888
|
+
const bar = node(
|
|
889
|
+
"meter",
|
|
890
|
+
{ value: used, style: "bar", size: "lg", parts, ...(marks ? { marks } : {}), aria: "Context usage by category" },
|
|
891
|
+
undefined,
|
|
892
|
+
"bar",
|
|
893
|
+
);
|
|
894
|
+
const shares = breakdown.categories.map(category =>
|
|
895
|
+
contextShareRow(
|
|
896
|
+
category.id,
|
|
897
|
+
"zeta.context.cat",
|
|
898
|
+
span("■", category.color),
|
|
899
|
+
category.label,
|
|
900
|
+
category.tokens,
|
|
901
|
+
window,
|
|
800
902
|
),
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
if (
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
"
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
"
|
|
903
|
+
);
|
|
904
|
+
shares.push(contextShareRow("free", "zeta.context.cat.free", span("□", "dim"), "Free space", freeTokens, window));
|
|
905
|
+
if (autoCompactBufferTokens > 0) {
|
|
906
|
+
shares.push(
|
|
907
|
+
contextShareRow(
|
|
908
|
+
"buffer",
|
|
909
|
+
"zeta.context.cat.buffer",
|
|
910
|
+
span("▨", "warning"),
|
|
911
|
+
"Autocompact buffer",
|
|
912
|
+
autoCompactBufferTokens,
|
|
913
|
+
window,
|
|
810
914
|
),
|
|
811
915
|
);
|
|
812
916
|
}
|
|
813
|
-
|
|
917
|
+
const children = [summary, bar, node("col", { role: "zeta.context.cats" }, shares, "cats")];
|
|
918
|
+
const snap = describeSnapcompact(breakdown);
|
|
919
|
+
if (snap) children.push(snap);
|
|
920
|
+
return col(children, { role: "zeta.context" });
|
|
814
921
|
}
|
|
815
922
|
|
|
816
|
-
/** The `/context` title: the model
|
|
923
|
+
/** The `/context` title: the model once one is selected (the body leads with its window). */
|
|
817
924
|
export function contextUsageHead(breakdown: ContextBreakdown): TspText {
|
|
818
925
|
if (breakdown.contextWindow <= 0) return [span("Context usage", "strong")];
|
|
819
926
|
const modelName = breakdown.model?.name ?? breakdown.model?.id ?? "no model";
|
|
820
|
-
return [
|
|
821
|
-
span("Context", "strong"),
|
|
822
|
-
span(` · ${modelName}`, "muted"),
|
|
823
|
-
span(` · ${formatNumber(breakdown.contextWindow).toLowerCase()}`, "dim"),
|
|
824
|
-
];
|
|
927
|
+
return [span("Context", "strong"), span(` · ${modelName}`, "muted")];
|
|
825
928
|
}
|
|
826
929
|
|
|
827
930
|
/**
|
|
@@ -176,22 +176,11 @@ export class FooterComponent implements Component {
|
|
|
176
176
|
*/
|
|
177
177
|
describe(): NativeNode {
|
|
178
178
|
const state = this.session.state;
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
let premiumRequests = 0;
|
|
185
|
-
for (const entry of this.session.sessionManager.getEntries()) {
|
|
186
|
-
if (entry.type === "message" && entry.message?.role === "assistant") {
|
|
187
|
-
input += entry.message.usage.input;
|
|
188
|
-
output += entry.message.usage.output;
|
|
189
|
-
cacheRead += entry.message.usage.cacheRead;
|
|
190
|
-
cacheWrite += entry.message.usage.cacheWrite;
|
|
191
|
-
cost += entry.message.usage.cost.total;
|
|
192
|
-
premiumRequests += entry.message.usage.premiumRequests ?? 0;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
179
|
+
// Cumulative usage: the session manager's running rollup spans every entry
|
|
180
|
+
// in the session (so it survives compaction) and already folds in the usage
|
|
181
|
+
// completed `task` tool results carry, which is where subagent spend lands.
|
|
182
|
+
const { input, output, cacheRead, cacheWrite, cost, premiumRequests } =
|
|
183
|
+
this.session.sessionManager.getUsageStatistics();
|
|
195
184
|
const segs: NativeNode[] = [];
|
|
196
185
|
const seg = (key: string, props: TspProps<"seg">): void => {
|
|
197
186
|
segs.push(node("seg", { role: `zeta.footer.${key}`, ...props }, undefined, key));
|
|
@@ -257,25 +246,19 @@ export class FooterComponent implements Component {
|
|
|
257
246
|
render(width: number): readonly string[] {
|
|
258
247
|
const state = this.session.state;
|
|
259
248
|
|
|
260
|
-
//
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
totalCacheWrite += entry.message.usage.cacheWrite;
|
|
274
|
-
totalCost += entry.message.usage.cost.total;
|
|
275
|
-
totalPremiumRequests += entry.message.usage.premiumRequests ?? 0;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
|
|
249
|
+
// Cumulative usage comes from the session manager's running rollup, which
|
|
250
|
+
// spans every entry in the session and folds in the usage completed `task`
|
|
251
|
+
// tool results carry (subagent spend). Context usage below is a separate
|
|
252
|
+
// question and stays window-scoped on purpose. Destructured straight off the
|
|
253
|
+
// rollup: a repaint must not allocate a second copy of these six fields.
|
|
254
|
+
const {
|
|
255
|
+
input: totalInput,
|
|
256
|
+
output: totalOutput,
|
|
257
|
+
cacheRead: totalCacheRead,
|
|
258
|
+
cacheWrite: totalCacheWrite,
|
|
259
|
+
cost: totalCost,
|
|
260
|
+
premiumRequests: totalPremiumRequests,
|
|
261
|
+
} = this.session.sessionManager.getUsageStatistics();
|
|
279
262
|
// Calculate context usage from session (handles compaction correctly).
|
|
280
263
|
// After compaction, tokens are unknown until the next LLM response.
|
|
281
264
|
const contextUsage = this.session.getContextUsage();
|
package/src/status-line/host.ts
CHANGED
|
@@ -71,7 +71,12 @@ export interface FooterSession {
|
|
|
71
71
|
autoResolvedThinkingLevel(): string | undefined;
|
|
72
72
|
getContextUsage: StatusLineSession["getContextUsage"];
|
|
73
73
|
modelRegistry: Pick<StatusLineSession["modelRegistry"], "isUsingOAuth">;
|
|
74
|
-
|
|
74
|
+
/**
|
|
75
|
+
* Cumulative session rollup. Unlike the active-window stats it spans every
|
|
76
|
+
* entry in the session, so compaction does not reset the counters, and it
|
|
77
|
+
* folds in usage carried by completed `task` tool results.
|
|
78
|
+
*/
|
|
79
|
+
sessionManager: { getUsageStatistics: StatusLineSession["sessionManager"]["getUsageStatistics"] };
|
|
75
80
|
}
|
|
76
81
|
|
|
77
82
|
/**
|
|
@@ -6,6 +6,7 @@ import { SPINNER_ADVANCE_MS, TERMINAL } from "../index";
|
|
|
6
6
|
import {
|
|
7
7
|
formatDuration,
|
|
8
8
|
formatNumber,
|
|
9
|
+
getActiveProfile,
|
|
9
10
|
getProjectDir,
|
|
10
11
|
normalizePathForComparison,
|
|
11
12
|
relativePathWithinNormalizedRoot,
|
|
@@ -216,24 +217,34 @@ const piSegment: StatusLineSegment = {
|
|
|
216
217
|
// Brand fg fades between dim gray (idle) and the accent (working) across
|
|
217
218
|
// turn edges; the component samples the tween into `brandFgAnsi`.
|
|
218
219
|
const fgAnsi = ctx.brandFgAnsi ?? theme.getFgAnsi("dim");
|
|
220
|
+
const profile = ctx.options.pi?.showProfile === false ? undefined : getActiveProfile();
|
|
219
221
|
// While a turn runs the brand icon becomes a braille spinner plus a
|
|
220
222
|
// whole-unit turn timer (port of rust zeta's status-band active brand).
|
|
221
223
|
// No trailing pad: the group renderer owns inter-segment spacing, so a
|
|
222
224
|
// trailing space here would double the gap at the first separator (#11103).
|
|
223
225
|
const content =
|
|
224
226
|
ctx.turnElapsedMs != null
|
|
225
|
-
? `${brandSpinnerFrame(ctx.now?.getTime())} ${brandTimer(ctx.turnElapsedMs)}`
|
|
226
|
-
: theme.icon.omp
|
|
227
|
-
? theme.icon.omp
|
|
228
|
-
: "";
|
|
227
|
+
? `${brandMark(brandSpinnerFrame(ctx.now?.getTime()), profile)} ${brandTimer(ctx.turnElapsedMs)}`
|
|
228
|
+
: brandMark(theme.icon.omp, profile);
|
|
229
229
|
return { content: `${fgAnsi}${content}\x1b[39m`, visible: true };
|
|
230
230
|
},
|
|
231
231
|
describe(ctx) {
|
|
232
232
|
if (ctx.focusedAgentId) return segView([span(ctx.focusedAgentId, "warning")], "ghost", "warning");
|
|
233
233
|
// The dock's working row owns activity natively: the brand stays still.
|
|
234
|
-
|
|
234
|
+
const profile = ctx.options.pi?.showProfile === false ? undefined : getActiveProfile();
|
|
235
|
+
return segView(profile ? [span(profile, "muted")] : [], "omp", "muted");
|
|
235
236
|
},
|
|
236
237
|
};
|
|
238
|
+
/**
|
|
239
|
+
* Brand glyph tagged with the active named profile (`π-work`) so sessions from
|
|
240
|
+
* different profiles are distinguishable at a glance; the bare glyph for the
|
|
241
|
+
* default profile or with `segmentOptions.pi.showProfile: false`. The tag
|
|
242
|
+
* stays put while the glyph slot animates.
|
|
243
|
+
*/
|
|
244
|
+
function brandMark(glyph: string, profile: string | undefined): string {
|
|
245
|
+
if (!profile) return glyph;
|
|
246
|
+
return glyph ? `${glyph}-${profile}` : profile;
|
|
247
|
+
}
|
|
237
248
|
/** Current braille-spinner glyph on the shared clock, at the Loader's 80ms cadence. */
|
|
238
249
|
function brandSpinnerFrame(nowMs = Date.now()): string {
|
|
239
250
|
const frames = theme.getSpinnerFrames("activity");
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Status line for the speculative first frame, before any session exists.
|
|
3
3
|
*
|
|
4
|
-
* InteractiveMode persists {@link StatusLineStartupData} (settings plus the
|
|
5
|
-
*
|
|
6
|
-
* real {@link StatusLineComponent} as a fresh, unnamed session at
|
|
7
|
-
* terminal width. Path and git branch are read live; context usage is
|
|
8
|
-
* unknown so the gauge shows the window without a percent.
|
|
4
|
+
* InteractiveMode persists {@link StatusLineStartupData} (settings plus the
|
|
5
|
+
* resolved default role model and status inputs); the next launch renders it
|
|
6
|
+
* through the real {@link StatusLineComponent} as a fresh, unnamed session at
|
|
7
|
+
* the live terminal width. Path and git branch are read live; context usage is
|
|
8
|
+
* reported unknown so the gauge shows the window without a percent.
|
|
9
9
|
*
|
|
10
10
|
* @example
|
|
11
11
|
* ```ts ignore
|
|
@@ -32,7 +32,7 @@ import type { StatusLineSettings } from "./types";
|
|
|
32
32
|
export interface StatusLineStartupData {
|
|
33
33
|
readonly settings: StatusLineSettings;
|
|
34
34
|
readonly gitEnabled: boolean;
|
|
35
|
-
/** Model
|
|
35
|
+
/** Model resolved for the next fresh session's default role. */
|
|
36
36
|
readonly model?: Model;
|
|
37
37
|
readonly thinkingLevel?: ThinkingLevel;
|
|
38
38
|
readonly autoThinking: boolean;
|
package/src/status-line/types.ts
CHANGED
|
@@ -36,6 +36,7 @@ export interface CollabStatus {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export interface StatusLineSegmentOptions {
|
|
39
|
+
pi?: { showProfile?: boolean };
|
|
39
40
|
model?: { showThinkingLevel?: boolean };
|
|
40
41
|
path?: { abbreviate?: boolean; maxLength?: number; stripWorkPrefix?: boolean };
|
|
41
42
|
git?: { showBranch?: boolean; showStaged?: boolean; showUnstaged?: boolean; showUntracked?: boolean };
|
package/src/stdin-buffer.d.ts
CHANGED
|
@@ -61,6 +61,13 @@ export type StdinBufferEventMap = {
|
|
|
61
61
|
export declare class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
|
|
62
62
|
#private;
|
|
63
63
|
constructor(options?: StdinBufferOptions);
|
|
64
|
+
/**
|
|
65
|
+
* Whether a bracketed paste has started and its end marker has not arrived.
|
|
66
|
+
* Terminal skips its per-read DEC 2004 reassertion meanwhile: the host is
|
|
67
|
+
* evidently in bracketed-paste mode, and a paste delivered one key record
|
|
68
|
+
* per read would otherwise cost one terminal write per pasted key (#15757).
|
|
69
|
+
*/
|
|
70
|
+
get pasting(): boolean;
|
|
64
71
|
process(data: string | Buffer): void;
|
|
65
72
|
/**
|
|
66
73
|
* Gate unbracketed raw-paste classification on event-loop responsiveness.
|
package/src/stdin-buffer.ts
CHANGED
|
@@ -442,6 +442,16 @@ export class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
|
|
|
442
442
|
this.#pasteByteLimit = options.pasteByteLimit ?? PASTE_MAX_BYTES;
|
|
443
443
|
}
|
|
444
444
|
|
|
445
|
+
/**
|
|
446
|
+
* Whether a bracketed paste has started and its end marker has not arrived.
|
|
447
|
+
* Terminal skips its per-read DEC 2004 reassertion meanwhile: the host is
|
|
448
|
+
* evidently in bracketed-paste mode, and a paste delivered one key record
|
|
449
|
+
* per read would otherwise cost one terminal write per pasted key (#15757).
|
|
450
|
+
*/
|
|
451
|
+
get pasting(): boolean {
|
|
452
|
+
return this.#pasteMode;
|
|
453
|
+
}
|
|
454
|
+
|
|
445
455
|
process(data: string | Buffer): void {
|
|
446
456
|
// Handle high-byte conversion (for compatibility with parseKeypress)
|
|
447
457
|
// If buffer has single byte > 127, convert to ESC + (byte - 128)
|
|
@@ -578,7 +588,7 @@ export class StdinBuffer extends EventEmitter<StdinBufferEventMap> {
|
|
|
578
588
|
const probe = this.#pasteOverlap + chunk;
|
|
579
589
|
if (probe.indexOf(BRACKETED_PASTE_END) === -1) {
|
|
580
590
|
this.#pasteChunks.push(chunk);
|
|
581
|
-
this.#pasteBytes += chunk
|
|
591
|
+
this.#pasteBytes += Buffer.byteLength(chunk, "utf8");
|
|
582
592
|
const keep = BRACKETED_PASTE_END.length - 1;
|
|
583
593
|
this.#pasteOverlap = probe.length > keep ? probe.slice(probe.length - keep) : probe;
|
|
584
594
|
if (this.#pasteBytes > this.#pasteByteLimit) {
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import type { HangulCompatibilityJamoWidth } from "./utils";
|
|
2
2
|
export * from "./terminal-multiplexer";
|
|
3
3
|
export { wrapTmuxPassthrough } from "./tmux";
|
|
4
|
+
/**
|
|
5
|
+
* Trusted terminal background when reported; otherwise black for detected dark
|
|
6
|
+
* appearance or white for detected light appearance, using theme auto-detection.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getTerminalBackgroundColor(): number;
|
|
9
|
+
/** Store an OSC 11 background, or reset to appearance detection (also for tests). */
|
|
10
|
+
export declare function setTerminalBackgroundColor(color: number | undefined): void;
|
|
4
11
|
export declare enum ImageProtocol {
|
|
5
12
|
Kitty = "\u001B_G",
|
|
6
13
|
Iterm2 = "\u001B]1337;File=",
|
|
@@ -339,6 +346,14 @@ export interface ParsedKittyPlacementLine {
|
|
|
339
346
|
* callers fall back to writing the line verbatim.
|
|
340
347
|
*/
|
|
341
348
|
export declare function parseKittyDirectPlacementLine(line: string): ParsedKittyPlacementLine | null;
|
|
349
|
+
/**
|
|
350
|
+
* Rows above its own line that an {@link Image} direct-placement line paints
|
|
351
|
+
* over: the `CUU(rows-1)` of its lead-in, or 0 for any other line. The renderer
|
|
352
|
+
* erases those rows before a SIXEL/iTerm2 block is written again, because
|
|
353
|
+
* those protocols have no delete command and the block's reserved rows are
|
|
354
|
+
* byte-identical between frames, so the diff never rewrites them.
|
|
355
|
+
*/
|
|
356
|
+
export declare function directPlacementLift(line: string): number;
|
|
342
357
|
/**
|
|
343
358
|
* Rebuild an {@link Image} direct-placement line for the viewport row it is
|
|
344
359
|
* written at. The component-rendered line encodes `CUU(rows-1)`, which clamps
|
|
@@ -397,7 +412,7 @@ export declare function getImageDimensions(base64Data: string, mimeType: string)
|
|
|
397
412
|
* thread; `null` when the encode fails. For output that cannot wait for an
|
|
398
413
|
* off-thread encode.
|
|
399
414
|
*/
|
|
400
|
-
export declare function encodeSixelNow(base64Data: string, widthPx: number, heightPx: number): string | null;
|
|
415
|
+
export declare function encodeSixelNow(base64Data: string, widthPx: number, heightPx: number, backgroundRgb?: number): string | null;
|
|
401
416
|
export declare function renderImage(base64Data: string, imageDimensions: ImageDimensions, options?: ImageRenderOptions): {
|
|
402
417
|
sequence?: string;
|
|
403
418
|
lines?: string[];
|