@code-yeongyu/senpi 2026.6.12-2 → 2026.6.14
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 +57 -0
- package/README.md +4 -4
- package/dist/cli/startup-ui.d.ts.map +1 -1
- package/dist/cli/startup-ui.js +19 -14
- package/dist/cli/startup-ui.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +14 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +3 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.d.ts +3 -0
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.d.ts.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js +10 -0
- package/dist/core/extensions/builtin/prompt-preset/kimi-k2-7.js.map +1 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/presets.js +12 -0
- package/dist/core/extensions/builtin/prompt-preset/presets.js.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.d.ts.map +1 -1
- package/dist/core/extensions/builtin/prompt-preset/settings.js +1 -0
- package/dist/core/extensions/builtin/prompt-preset/settings.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +6 -57
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +23 -1
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +31 -17
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.js +2 -2
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +0 -1
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +0 -4
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +11 -2
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/trust-manager.d.ts +8 -3
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +26 -11
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +9 -5
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +1 -123
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/aborted-error-label.d.ts +2 -0
- package/dist/modes/interactive/aborted-error-label.d.ts.map +1 -0
- package/dist/modes/interactive/aborted-error-label.js +8 -0
- package/dist/modes/interactive/aborted-error-label.js.map +1 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +4 -4
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +39 -15
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts +12 -8
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +19 -41
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +1 -1
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/event-output-buffer.d.ts +10 -0
- package/dist/modes/rpc/event-output-buffer.d.ts.map +1 -0
- package/dist/modes/rpc/event-output-buffer.js +27 -0
- package/dist/modes/rpc/event-output-buffer.js.map +1 -0
- package/dist/modes/rpc/jsonl.d.ts.map +1 -1
- package/dist/modes/rpc/jsonl.js +9 -11
- package/dist/modes/rpc/jsonl.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +17 -7
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +10 -3
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +14 -0
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +4 -27
- package/dist/utils/version-check.js.map +1 -1
- package/docs/extensions.md +7 -1
- package/docs/models.md +1 -1
- package/docs/providers.md +2 -2
- package/docs/security.md +9 -5
- package/docs/settings.md +3 -3
- package/docs/usage.md +4 -4
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +8 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +6 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +216 -78
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +410 -304
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +29 -16
- package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +3 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +7 -0
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/event-stream.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js +15 -21
- package/node_modules/@earendil-works/pi-ai/dist/utils/event-stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js +3 -2
- package/node_modules/@earendil-works/pi-ai/dist/utils/overflow.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +31 -20
- package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +2 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +18 -2
- package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.d.ts +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js +2 -2
- package/node_modules/@earendil-works/pi-tui/dist/fuzzy.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/index.js +2 -0
- package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js +15 -8
- package/node_modules/@earendil-works/pi-tui/dist/stdin-buffer.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal-colors.d.ts +8 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal-colors.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal-colors.js +51 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal-colors.js.map +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +1 -0
- package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js +9 -1
- package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts +17 -2
- package/node_modules/@earendil-works/pi-tui/dist/tui.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-tui/dist/tui.js +152 -18
- package/node_modules/@earendil-works/pi-tui/dist/tui.js.map +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/npm-shrinkwrap.json +25 -12
- package/package.json +7 -5
|
@@ -6,28 +6,42 @@ import * as os from "node:os";
|
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import { performance } from "node:perf_hooks";
|
|
8
8
|
import { isKeyRelease, matchesKey } from "./keys.js";
|
|
9
|
+
import { isOsc11BackgroundColorResponse, parseOsc11BackgroundColor } from "./terminal-colors.js";
|
|
9
10
|
import { deleteKittyImage, getCapabilities, isImageLine, setCellDimensions } from "./terminal-image.js";
|
|
10
11
|
import { extractSegments, normalizeTerminalOutput, sliceByColumn, sliceWithWidth, visibleWidth } from "./utils.js";
|
|
11
12
|
const KITTY_SEQUENCE_PREFIX = "\x1b_G";
|
|
12
|
-
function
|
|
13
|
+
function parseKittyImageHeader(line) {
|
|
13
14
|
const sequenceStart = line.indexOf(KITTY_SEQUENCE_PREFIX);
|
|
14
15
|
if (sequenceStart === -1)
|
|
15
|
-
return
|
|
16
|
+
return undefined;
|
|
16
17
|
const paramsStart = sequenceStart + KITTY_SEQUENCE_PREFIX.length;
|
|
17
18
|
const paramsEnd = line.indexOf(";", paramsStart);
|
|
18
19
|
if (paramsEnd === -1)
|
|
19
|
-
return
|
|
20
|
+
return undefined;
|
|
21
|
+
const ids = [];
|
|
22
|
+
let rows = 1;
|
|
20
23
|
const params = line.slice(paramsStart, paramsEnd);
|
|
21
24
|
for (const param of params.split(",")) {
|
|
22
25
|
const [key, value] = param.split("=", 2);
|
|
23
|
-
if (
|
|
26
|
+
if (value === undefined)
|
|
24
27
|
continue;
|
|
25
|
-
const
|
|
26
|
-
if (Number.isInteger(
|
|
27
|
-
|
|
28
|
+
const numberValue = Number(value);
|
|
29
|
+
if (!Number.isInteger(numberValue) || numberValue <= 0 || numberValue > 0xffffffff)
|
|
30
|
+
continue;
|
|
31
|
+
if (key === "i") {
|
|
32
|
+
ids.push(numberValue);
|
|
33
|
+
}
|
|
34
|
+
else if (key === "r") {
|
|
35
|
+
rows = numberValue;
|
|
28
36
|
}
|
|
29
37
|
}
|
|
30
|
-
return
|
|
38
|
+
return { ids, rows };
|
|
39
|
+
}
|
|
40
|
+
function extractKittyImageIds(line) {
|
|
41
|
+
return parseKittyImageHeader(line)?.ids ?? [];
|
|
42
|
+
}
|
|
43
|
+
function extractKittyImageRows(line) {
|
|
44
|
+
return parseKittyImageHeader(line)?.rows ?? 1;
|
|
31
45
|
}
|
|
32
46
|
/** Type guard to check if a component implements Focusable */
|
|
33
47
|
export function isFocusable(component) {
|
|
@@ -107,6 +121,7 @@ export class TUI extends Container {
|
|
|
107
121
|
this.inputListeners = new Set();
|
|
108
122
|
this.renderRequested = false;
|
|
109
123
|
this.lastRenderAt = 0;
|
|
124
|
+
this.inputRenderPending = false;
|
|
110
125
|
this.cursorRow = 0; // Logical cursor row (end of rendered content)
|
|
111
126
|
this.hardwareCursorRow = 0; // Actual terminal cursor row (may differ due to IME positioning)
|
|
112
127
|
this.showHardwareCursor = process.env.PI_HARDWARE_CURSOR === "1";
|
|
@@ -115,6 +130,8 @@ export class TUI extends Container {
|
|
|
115
130
|
this.previousViewportTop = 0; // Track previous viewport top for resize-aware cursor moves
|
|
116
131
|
this.fullRedrawCount = 0;
|
|
117
132
|
this.stopped = false;
|
|
133
|
+
this.pendingOsc11BackgroundReplies = 0;
|
|
134
|
+
this.pendingOsc11BackgroundQueries = [];
|
|
118
135
|
// Overlay stack for modal components rendered on top of base content
|
|
119
136
|
this.focusOrderCounter = 0;
|
|
120
137
|
this.overlayStack = [];
|
|
@@ -462,8 +479,9 @@ export class TUI extends Container {
|
|
|
462
479
|
this.maxLinesRendered = 0;
|
|
463
480
|
this.previousViewportTop = 0;
|
|
464
481
|
}
|
|
465
|
-
requestRender(force = false) {
|
|
482
|
+
requestRender(force = false, source = "unknown") {
|
|
466
483
|
if (force) {
|
|
484
|
+
this.inputRenderPending = false;
|
|
467
485
|
this.previousLines = [];
|
|
468
486
|
this.previousWidth = -1; // -1 triggers widthChanged, forcing a full clear
|
|
469
487
|
this.previousHeight = -1; // -1 triggers heightChanged, forcing a full clear
|
|
@@ -486,6 +504,14 @@ export class TUI extends Container {
|
|
|
486
504
|
});
|
|
487
505
|
return;
|
|
488
506
|
}
|
|
507
|
+
if (source === "input" || source === "editor.input") {
|
|
508
|
+
if (!this.inputRenderPending) {
|
|
509
|
+
this.inputRenderPending = true;
|
|
510
|
+
this.renderRequested = true;
|
|
511
|
+
process.nextTick(() => this.commitExpeditedRender());
|
|
512
|
+
}
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
489
515
|
if (this.renderRequested)
|
|
490
516
|
return;
|
|
491
517
|
this.renderRequested = true;
|
|
@@ -510,7 +536,25 @@ export class TUI extends Container {
|
|
|
510
536
|
}
|
|
511
537
|
}, delay);
|
|
512
538
|
}
|
|
539
|
+
commitExpeditedRender() {
|
|
540
|
+
if (!this.inputRenderPending)
|
|
541
|
+
return;
|
|
542
|
+
this.inputRenderPending = false;
|
|
543
|
+
if (this.stopped || !this.renderRequested) {
|
|
544
|
+
return;
|
|
545
|
+
}
|
|
546
|
+
if (this.renderTimer) {
|
|
547
|
+
clearTimeout(this.renderTimer);
|
|
548
|
+
this.renderTimer = undefined;
|
|
549
|
+
}
|
|
550
|
+
this.renderRequested = false;
|
|
551
|
+
this.lastRenderAt = performance.now();
|
|
552
|
+
this.doRender();
|
|
553
|
+
}
|
|
513
554
|
handleInput(data) {
|
|
555
|
+
if (this.consumeOsc11BackgroundResponse(data)) {
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
514
558
|
if (this.inputListeners.size > 0) {
|
|
515
559
|
let current = data;
|
|
516
560
|
for (const listener of this.inputListeners) {
|
|
@@ -573,9 +617,30 @@ export class TUI extends Container {
|
|
|
573
617
|
return;
|
|
574
618
|
}
|
|
575
619
|
this.focusedComponent.handleInput(data);
|
|
576
|
-
this.requestRender();
|
|
620
|
+
this.requestRender(false, "input");
|
|
577
621
|
}
|
|
578
622
|
}
|
|
623
|
+
consumeOsc11BackgroundResponse(data) {
|
|
624
|
+
if (this.pendingOsc11BackgroundReplies <= 0) {
|
|
625
|
+
return false;
|
|
626
|
+
}
|
|
627
|
+
if (!isOsc11BackgroundColorResponse(data)) {
|
|
628
|
+
return false;
|
|
629
|
+
}
|
|
630
|
+
const rgb = parseOsc11BackgroundColor(data);
|
|
631
|
+
this.pendingOsc11BackgroundReplies -= 1;
|
|
632
|
+
const query = this.pendingOsc11BackgroundQueries.shift();
|
|
633
|
+
if (query && !query.settled) {
|
|
634
|
+
query.settled = true;
|
|
635
|
+
if (query.timer) {
|
|
636
|
+
clearTimeout(query.timer);
|
|
637
|
+
query.timer = undefined;
|
|
638
|
+
}
|
|
639
|
+
query.resolve?.(rgb);
|
|
640
|
+
query.resolve = undefined;
|
|
641
|
+
}
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
579
644
|
consumeCellSizeResponse(data) {
|
|
580
645
|
// Response format: ESC [ 6 ; height ; width t
|
|
581
646
|
const match = data.match(/^\x1b\[6;(\d+);(\d+)t$/);
|
|
@@ -795,14 +860,37 @@ export class TUI extends Container {
|
|
|
795
860
|
}
|
|
796
861
|
return buffer;
|
|
797
862
|
}
|
|
798
|
-
|
|
863
|
+
getKittyImageReservedRows(lines, index, maxIndex = lines.length - 1) {
|
|
864
|
+
const rows = extractKittyImageRows(lines[index] ?? "");
|
|
865
|
+
if (rows <= 1)
|
|
866
|
+
return 1;
|
|
867
|
+
const maxRows = Math.min(rows, maxIndex - index + 1, lines.length - index);
|
|
868
|
+
let reservedRows = 1;
|
|
869
|
+
while (reservedRows < maxRows) {
|
|
870
|
+
const line = lines[index + reservedRows] ?? "";
|
|
871
|
+
if (isImageLine(line) || visibleWidth(line) > 0)
|
|
872
|
+
break;
|
|
873
|
+
reservedRows++;
|
|
874
|
+
}
|
|
875
|
+
return reservedRows;
|
|
876
|
+
}
|
|
877
|
+
expandChangedRangeForKittyImages(firstChanged, lastChanged, newLines) {
|
|
878
|
+
let expandedFirstChanged = firstChanged;
|
|
799
879
|
let expandedLastChanged = lastChanged;
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
880
|
+
const expandForLines = (lines) => {
|
|
881
|
+
for (let i = 0; i < lines.length; i++) {
|
|
882
|
+
if (extractKittyImageIds(lines[i]).length === 0)
|
|
883
|
+
continue;
|
|
884
|
+
const blockEnd = i + this.getKittyImageReservedRows(lines, i) - 1;
|
|
885
|
+
if (i >= firstChanged || (i <= lastChanged && blockEnd >= firstChanged)) {
|
|
886
|
+
expandedFirstChanged = Math.min(expandedFirstChanged, i);
|
|
887
|
+
expandedLastChanged = Math.max(expandedLastChanged, blockEnd);
|
|
888
|
+
}
|
|
803
889
|
}
|
|
804
|
-
}
|
|
805
|
-
|
|
890
|
+
};
|
|
891
|
+
expandForLines(this.previousLines);
|
|
892
|
+
expandForLines(newLines);
|
|
893
|
+
return { firstChanged: expandedFirstChanged, lastChanged: expandedLastChanged };
|
|
806
894
|
}
|
|
807
895
|
deleteChangedKittyImages(firstChanged, lastChanged) {
|
|
808
896
|
if (firstChanged < 0 || lastChanged < firstChanged)
|
|
@@ -1086,7 +1174,9 @@ export class TUI extends Container {
|
|
|
1086
1174
|
lastChanged = newLines.length - 1;
|
|
1087
1175
|
}
|
|
1088
1176
|
if (firstChanged !== -1) {
|
|
1089
|
-
|
|
1177
|
+
const expandedRange = this.expandChangedRangeForKittyImages(firstChanged, lastChanged, newLines);
|
|
1178
|
+
firstChanged = expandedRange.firstChanged;
|
|
1179
|
+
lastChanged = expandedRange.lastChanged;
|
|
1090
1180
|
}
|
|
1091
1181
|
const appendStart = appendedLines && firstChanged === this.previousLines.length && firstChanged > 0;
|
|
1092
1182
|
const insertScrollPlan = this.createViewportInsertScrollPlan(newLines, prevViewportTop, height, lineCountDelta);
|
|
@@ -1249,9 +1339,27 @@ export class TUI extends Container {
|
|
|
1249
1339
|
for (let i = firstChanged; i <= renderEnd; i++) {
|
|
1250
1340
|
if (i > firstChanged)
|
|
1251
1341
|
buffer += "\r\n";
|
|
1252
|
-
buffer += "\x1b[2K"; // Clear current line
|
|
1253
1342
|
const line = newLines[i];
|
|
1254
1343
|
const isImage = isImageLine(line);
|
|
1344
|
+
const imageReservedRows = isImage ? this.getKittyImageReservedRows(newLines, i, renderEnd) : 1;
|
|
1345
|
+
if (imageReservedRows > 1) {
|
|
1346
|
+
const imageStartScreenRow = i - viewportTop;
|
|
1347
|
+
if (imageStartScreenRow < 0 || imageStartScreenRow + imageReservedRows > height) {
|
|
1348
|
+
logRedraw(`kitty image pre-clear would scroll (${imageStartScreenRow} + ${imageReservedRows} > ${height})`);
|
|
1349
|
+
fullRender(true);
|
|
1350
|
+
return;
|
|
1351
|
+
}
|
|
1352
|
+
buffer += "\x1b[2K";
|
|
1353
|
+
for (let row = 1; row < imageReservedRows; row++) {
|
|
1354
|
+
buffer += "\r\n\x1b[2K";
|
|
1355
|
+
}
|
|
1356
|
+
buffer += `\x1b[${imageReservedRows - 1}A`;
|
|
1357
|
+
buffer += line;
|
|
1358
|
+
buffer += `\x1b[${imageReservedRows - 1}B`;
|
|
1359
|
+
i += imageReservedRows - 1;
|
|
1360
|
+
continue;
|
|
1361
|
+
}
|
|
1362
|
+
buffer += "\x1b[2K"; // Clear current line
|
|
1255
1363
|
if (!isImage && visibleWidth(line) > width) {
|
|
1256
1364
|
// Log all lines to crash file for debugging
|
|
1257
1365
|
const crashLogPath = path.join(os.homedir(), ".senpi", "agent", "senpi-crash.log");
|
|
@@ -1378,5 +1486,31 @@ export class TUI extends Container {
|
|
|
1378
1486
|
this.terminal.hideCursor();
|
|
1379
1487
|
}
|
|
1380
1488
|
}
|
|
1489
|
+
/**
|
|
1490
|
+
* Query the terminal's default background color with OSC 11 (`ESC ] 11 ; ? BEL`).
|
|
1491
|
+
* @param timeoutMs Query timeout in milliseconds.
|
|
1492
|
+
* @returns Promise containing the parsed RGB color, or undefined if it times out or fails to parse.
|
|
1493
|
+
*/
|
|
1494
|
+
queryTerminalBackgroundColor({ timeoutMs }) {
|
|
1495
|
+
return new Promise((resolve) => {
|
|
1496
|
+
const query = {
|
|
1497
|
+
settled: false,
|
|
1498
|
+
resolve,
|
|
1499
|
+
timer: undefined,
|
|
1500
|
+
};
|
|
1501
|
+
query.timer = setTimeout(() => {
|
|
1502
|
+
if (query.settled) {
|
|
1503
|
+
return;
|
|
1504
|
+
}
|
|
1505
|
+
query.settled = true;
|
|
1506
|
+
query.timer = undefined;
|
|
1507
|
+
query.resolve?.(undefined);
|
|
1508
|
+
query.resolve = undefined;
|
|
1509
|
+
}, timeoutMs);
|
|
1510
|
+
this.pendingOsc11BackgroundQueries.push(query);
|
|
1511
|
+
this.pendingOsc11BackgroundReplies += 1;
|
|
1512
|
+
this.terminal.write("\x1b]11;?\x07");
|
|
1513
|
+
});
|
|
1514
|
+
}
|
|
1381
1515
|
}
|
|
1382
1516
|
//# sourceMappingURL=tui.js.map
|