gsd-pi 2.73.1-dev.1040fb0 → 2.73.1-dev.47ed32a
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/dist/resource-loader.js +2 -2
- package/dist/resources/extensions/gsd/auto-start.js +3 -0
- package/dist/resources/extensions/gsd/auto.js +8 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +9 -9
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +9 -9
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +138 -0
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +21 -4
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +6 -2
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +157 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +21 -4
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +6 -2
- package/packages/pi-tui/dist/__tests__/tui.test.js +30 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +7 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +10 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/tui.test.ts +38 -1
- package/packages/pi-tui/src/tui.ts +11 -0
- package/src/resources/extensions/gsd/auto-start.ts +3 -0
- package/src/resources/extensions/gsd/auto.ts +5 -0
- /package/dist/web/standalone/.next/static/{5dzOW4v8Vz23I5xRsiNSk → WawMb3TMcYLkGJLTg_x1u}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5dzOW4v8Vz23I5xRsiNSk → WawMb3TMcYLkGJLTg_x1u}/_ssgManifest.js +0 -0
|
@@ -656,3 +656,160 @@ test("chat-controller does not duplicate text when content is [text, tool, text]
|
|
|
656
656
|
|
|
657
657
|
assert.deepEqual((secondText as any).range, { startIndex: 2, endIndex: 2 }, "range must not be cleared on message_end (would cause duplication)");
|
|
658
658
|
});
|
|
659
|
+
|
|
660
|
+
// Regression for the claude-code sub-turn bug that followed #4144:
|
|
661
|
+
// an adapter can reset content[] back to 0/1 mid-lifecycle when a new provider
|
|
662
|
+
// sub-turn begins. The segment walker must NOT update prior-sub-turn text-run
|
|
663
|
+
// components in place (which would destroy earlier history) and must NOT reuse
|
|
664
|
+
// stale tool registrations for a new tool at the same contentIndex. Prior
|
|
665
|
+
// sub-turn children must stay frozen; new sub-turn segments must append after
|
|
666
|
+
// them, and the pinned "Latest Output" mirror must re-evaluate for the new sub-turn.
|
|
667
|
+
test("chat-controller freezes prior sub-turn and appends new segments when content shrinks", async () => {
|
|
668
|
+
(globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
|
|
669
|
+
fg: (_key: string, text: string) => text,
|
|
670
|
+
bg: (_key: string, text: string) => text,
|
|
671
|
+
bold: (text: string) => text,
|
|
672
|
+
italic: (text: string) => text,
|
|
673
|
+
truncate: (text: string) => text,
|
|
674
|
+
};
|
|
675
|
+
|
|
676
|
+
const host = createHost();
|
|
677
|
+
host.getMarkdownThemeWithSettings = () => ({});
|
|
678
|
+
|
|
679
|
+
const t1 = { type: "toolCall", id: "t1", name: "tool_one", arguments: {} };
|
|
680
|
+
const t2 = { type: "toolCall", id: "t2", name: "tool_two", arguments: {} };
|
|
681
|
+
|
|
682
|
+
await handleAgentEvent(host, { type: "message_start", message: makeAssistant([]) } as any);
|
|
683
|
+
|
|
684
|
+
// Sub-turn 1: grow to [A, T1, B]
|
|
685
|
+
await handleAgentEvent(host, {
|
|
686
|
+
type: "message_update",
|
|
687
|
+
message: makeAssistant([{ type: "text", text: "A" }]),
|
|
688
|
+
assistantMessageEvent: {
|
|
689
|
+
type: "text_delta", contentIndex: 0, delta: "A",
|
|
690
|
+
partial: makeAssistant([{ type: "text", text: "A" }]),
|
|
691
|
+
},
|
|
692
|
+
} as any);
|
|
693
|
+
await handleAgentEvent(host, {
|
|
694
|
+
type: "message_update",
|
|
695
|
+
message: makeAssistant([{ type: "text", text: "A" }, t1]),
|
|
696
|
+
assistantMessageEvent: {
|
|
697
|
+
type: "toolcall_end", contentIndex: 1,
|
|
698
|
+
toolCall: { ...t1, externalResult: { content: [{ type: "text", text: "r1" }], details: {}, isError: false } },
|
|
699
|
+
partial: makeAssistant([{ type: "text", text: "A" }, t1]),
|
|
700
|
+
},
|
|
701
|
+
} as any);
|
|
702
|
+
await handleAgentEvent(host, {
|
|
703
|
+
type: "message_update",
|
|
704
|
+
message: makeAssistant([{ type: "text", text: "A" }, t1, { type: "text", text: "B" }]),
|
|
705
|
+
assistantMessageEvent: {
|
|
706
|
+
type: "text_delta", contentIndex: 2, delta: "B",
|
|
707
|
+
partial: makeAssistant([{ type: "text", text: "A" }, t1, { type: "text", text: "B" }]),
|
|
708
|
+
},
|
|
709
|
+
} as any);
|
|
710
|
+
|
|
711
|
+
assert.equal(host.chatContainer.children.length, 3, "sub-turn 1 renders 3 children");
|
|
712
|
+
const priorA = host.chatContainer.children[0];
|
|
713
|
+
const priorT1 = host.chatContainer.children[1];
|
|
714
|
+
const priorB = host.chatContainer.children[2];
|
|
715
|
+
|
|
716
|
+
// Sub-turn boundary: adapter resets content[] to [C]
|
|
717
|
+
await handleAgentEvent(host, {
|
|
718
|
+
type: "message_update",
|
|
719
|
+
message: makeAssistant([{ type: "text", text: "C" }]),
|
|
720
|
+
assistantMessageEvent: {
|
|
721
|
+
type: "text_delta", contentIndex: 0, delta: "C",
|
|
722
|
+
partial: makeAssistant([{ type: "text", text: "C" }]),
|
|
723
|
+
},
|
|
724
|
+
} as any);
|
|
725
|
+
|
|
726
|
+
// Prior 3 children must still exist in DOM — and a NEW text-run for "C" appended after them.
|
|
727
|
+
assert.equal(host.chatContainer.children.length, 4, "shrink must append new segment, not replace prior history");
|
|
728
|
+
assert.equal(host.chatContainer.children[0], priorA, "prior A component stays at index 0");
|
|
729
|
+
assert.equal(host.chatContainer.children[1], priorT1, "prior T1 component stays at index 1");
|
|
730
|
+
assert.equal(host.chatContainer.children[2], priorB, "prior B component stays at index 2");
|
|
731
|
+
assert.notEqual(host.chatContainer.children[3], priorA, "new C text-run must be a different component from prior A");
|
|
732
|
+
assert.equal(host.chatContainer.children[3]?.constructor?.name, "AssistantMessageComponent");
|
|
733
|
+
|
|
734
|
+
// Prior A component must still render "A", not be overwritten with "C".
|
|
735
|
+
function getRenderedTexts(comp: any): string[] {
|
|
736
|
+
const contentContainer = comp.children?.[0];
|
|
737
|
+
if (!contentContainer) return [];
|
|
738
|
+
return (contentContainer.children ?? [])
|
|
739
|
+
.filter((c: any) => c.constructor?.name === "Markdown")
|
|
740
|
+
.map((c: any) => (c as any).text as string);
|
|
741
|
+
}
|
|
742
|
+
assert.deepEqual(getRenderedTexts(priorA), ["A"], "prior A text-run must still contain 'A' after shrink");
|
|
743
|
+
assert.deepEqual(getRenderedTexts(priorB), ["B"], "prior B text-run must still contain 'B' after shrink");
|
|
744
|
+
assert.deepEqual(getRenderedTexts(host.chatContainer.children[3]), ["C"], "new text-run must contain only 'C'");
|
|
745
|
+
|
|
746
|
+
// Sub-turn 2 grows with a new tool T2 at contentIndex=1.
|
|
747
|
+
await handleAgentEvent(host, {
|
|
748
|
+
type: "message_update",
|
|
749
|
+
message: makeAssistant([{ type: "text", text: "C" }, t2]),
|
|
750
|
+
assistantMessageEvent: {
|
|
751
|
+
type: "toolcall_end", contentIndex: 1,
|
|
752
|
+
toolCall: { ...t2, externalResult: { content: [{ type: "text", text: "r2" }], details: {}, isError: false } },
|
|
753
|
+
partial: makeAssistant([{ type: "text", text: "C" }, t2]),
|
|
754
|
+
},
|
|
755
|
+
} as any);
|
|
756
|
+
|
|
757
|
+
// T2 must be appended after the new C text-run, not conflated with the stale T1 registration.
|
|
758
|
+
assert.equal(host.chatContainer.children.length, 5, "new tool appends after new text-run");
|
|
759
|
+
assert.equal(host.chatContainer.children[4]?.constructor?.name, "ToolExecutionComponent");
|
|
760
|
+
assert.notEqual(host.chatContainer.children[4], priorT1, "new T2 must be a different component from prior T1");
|
|
761
|
+
|
|
762
|
+
// Finalize so the module-level pinned spinner (setInterval) is torn down and the test process can exit.
|
|
763
|
+
await handleAgentEvent(host, { type: "message_end", message: makeAssistant([{ type: "text", text: "C" }, t2]) } as any);
|
|
764
|
+
});
|
|
765
|
+
|
|
766
|
+
// Regression: after a sub-turn shrink, lastPinnedText must be cleared so the
|
|
767
|
+
// pinned "Latest Output" mirror can display text from the new sub-turn instead
|
|
768
|
+
// of staying frozen on a stale snapshot (the "bottom green stays" symptom).
|
|
769
|
+
test("chat-controller updates pinned zone after sub-turn shrink", async () => {
|
|
770
|
+
(globalThis as any)[Symbol.for("@gsd/pi-coding-agent:theme")] = {
|
|
771
|
+
fg: (_key: string, text: string) => text,
|
|
772
|
+
bg: (_key: string, text: string) => text,
|
|
773
|
+
bold: (text: string) => text,
|
|
774
|
+
italic: (text: string) => text,
|
|
775
|
+
truncate: (text: string) => text,
|
|
776
|
+
};
|
|
777
|
+
|
|
778
|
+
const host = createHost();
|
|
779
|
+
host.getMarkdownThemeWithSettings = () => ({});
|
|
780
|
+
|
|
781
|
+
const t1 = { type: "toolCall", id: "t1", name: "tool_one", arguments: {} };
|
|
782
|
+
const t2 = { type: "toolCall", id: "t2", name: "tool_two", arguments: {} };
|
|
783
|
+
|
|
784
|
+
await handleAgentEvent(host, { type: "message_start", message: makeAssistant([]) } as any);
|
|
785
|
+
|
|
786
|
+
// Sub-turn 1 with pinnable text before a tool → populates pinned zone with "first".
|
|
787
|
+
await handleAgentEvent(host, {
|
|
788
|
+
type: "message_update",
|
|
789
|
+
message: makeAssistant([{ type: "text", text: "first" }, t1]),
|
|
790
|
+
assistantMessageEvent: {
|
|
791
|
+
type: "toolcall_end", contentIndex: 1,
|
|
792
|
+
toolCall: { ...t1, externalResult: { content: [{ type: "text", text: "r1" }], details: {}, isError: false } },
|
|
793
|
+
partial: makeAssistant([{ type: "text", text: "first" }, t1]),
|
|
794
|
+
},
|
|
795
|
+
} as any);
|
|
796
|
+
const pinnedMarkdown = host.pinnedMessageContainer.children[1];
|
|
797
|
+
assert.equal((pinnedMarkdown as any)?.text, "first", "pinned zone seeded with sub-turn 1 text");
|
|
798
|
+
|
|
799
|
+
// Sub-turn boundary: content resets to [second, t2].
|
|
800
|
+
await handleAgentEvent(host, {
|
|
801
|
+
type: "message_update",
|
|
802
|
+
message: makeAssistant([{ type: "text", text: "second" }, t2]),
|
|
803
|
+
assistantMessageEvent: {
|
|
804
|
+
type: "toolcall_end", contentIndex: 1,
|
|
805
|
+
toolCall: { ...t2, externalResult: { content: [{ type: "text", text: "r2" }], details: {}, isError: false } },
|
|
806
|
+
partial: makeAssistant([{ type: "text", text: "second" }, t2]),
|
|
807
|
+
},
|
|
808
|
+
} as any);
|
|
809
|
+
|
|
810
|
+
// Pinned markdown must now reflect the new sub-turn's text, not stay frozen on "first".
|
|
811
|
+
assert.equal((pinnedMarkdown as any)?.text, "second", "pinned zone must update after sub-turn shrink (#4144 regression)");
|
|
812
|
+
|
|
813
|
+
// Finalize so the module-level pinned spinner (setInterval) is torn down and the test process can exit.
|
|
814
|
+
await handleAgentEvent(host, { type: "message_end", message: makeAssistant([{ type: "text", text: "second" }, t2]) } as any);
|
|
815
|
+
});
|
|
@@ -10,6 +10,10 @@ import { appKey } from "../components/keybinding-hints.js";
|
|
|
10
10
|
// Tracks the last processed content index to avoid re-scanning all blocks on every message_update
|
|
11
11
|
let lastProcessedContentIndex = 0;
|
|
12
12
|
|
|
13
|
+
// Tracks the previous content[] length so we can detect when an adapter resets
|
|
14
|
+
// the assistant content array for a new provider sub-turn within one lifecycle.
|
|
15
|
+
let lastContentLength = 0;
|
|
16
|
+
|
|
13
17
|
// --- Segment walker state (per streaming assistant turn) ---
|
|
14
18
|
type RenderedSegment =
|
|
15
19
|
| { kind: "text-run"; startIndex: number; endIndex: number; component: AssistantMessageComponent }
|
|
@@ -85,6 +89,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
85
89
|
// Reset content index tracker and pinned state when a new assistant message starts
|
|
86
90
|
if (event.type === "message_start" && event.message.role === "assistant") {
|
|
87
91
|
lastProcessedContentIndex = 0;
|
|
92
|
+
lastContentLength = 0;
|
|
88
93
|
lastPinnedText = "";
|
|
89
94
|
hasToolsInTurn = false;
|
|
90
95
|
renderedSegments = [];
|
|
@@ -108,6 +113,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
108
113
|
lastPinnedText = "";
|
|
109
114
|
hasToolsInTurn = false;
|
|
110
115
|
renderedSegments = [];
|
|
116
|
+
lastContentLength = 0;
|
|
111
117
|
if (pinnedBorder) pinnedBorder.stopSpinner();
|
|
112
118
|
pinnedBorder = undefined;
|
|
113
119
|
pinnedTextComponent = undefined;
|
|
@@ -211,12 +217,22 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
211
217
|
}
|
|
212
218
|
|
|
213
219
|
const contentBlocks = host.streamingMessage.content;
|
|
214
|
-
// Some adapters reuse a single assistant
|
|
215
|
-
// spanning multiple provider turns.
|
|
216
|
-
//
|
|
217
|
-
|
|
220
|
+
// Some adapters (notably claude-code) reuse a single assistant
|
|
221
|
+
// lifecycle while internally spanning multiple provider sub-turns.
|
|
222
|
+
// When a new sub-turn starts, content[] length shrinks back to 0/1.
|
|
223
|
+
// The scan loop needs its index reset, AND the segment walker's
|
|
224
|
+
// renderedSegments map must be cleared so existing text-run
|
|
225
|
+
// components don't get overwritten in place with new sub-turn
|
|
226
|
+
// content (#4144 regression). Prior sub-turn children stay in
|
|
227
|
+
// chatContainer as frozen history; new segments append after them.
|
|
228
|
+
if (contentBlocks.length < lastContentLength) {
|
|
229
|
+
renderedSegments = [];
|
|
230
|
+
lastPinnedText = "";
|
|
231
|
+
lastProcessedContentIndex = 0;
|
|
232
|
+
} else if (lastProcessedContentIndex >= contentBlocks.length) {
|
|
218
233
|
lastProcessedContentIndex = 0;
|
|
219
234
|
}
|
|
235
|
+
lastContentLength = contentBlocks.length;
|
|
220
236
|
for (let i = lastProcessedContentIndex; i < contentBlocks.length; i++) {
|
|
221
237
|
const content = contentBlocks[i];
|
|
222
238
|
if (content.type === "toolCall") {
|
|
@@ -474,6 +490,7 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
474
490
|
host.streamingComponent = undefined;
|
|
475
491
|
host.streamingMessage = undefined;
|
|
476
492
|
renderedSegments = [];
|
|
493
|
+
lastContentLength = 0;
|
|
477
494
|
// Clear pinned output once the message is finalized in the chat
|
|
478
495
|
// container — prevents duplicate display when the agent continues
|
|
479
496
|
// (e.g. form elicitation) after the assistant message ends.
|
|
@@ -1402,7 +1402,9 @@ export class InteractiveMode {
|
|
|
1402
1402
|
|
|
1403
1403
|
// widgetContainerAbove: spacer collapses when pinned content is visible
|
|
1404
1404
|
// so there's no extra blank line between pinned output and the editor border.
|
|
1405
|
-
|
|
1405
|
+
// Use detachChildren() (not clear()) — the extensionWidgetsAbove map owns
|
|
1406
|
+
// disposal; clear() would dispose every mounted widget on every re-render.
|
|
1407
|
+
this.widgetContainerAbove.detachChildren();
|
|
1406
1408
|
const pinned = this.pinnedMessageContainer;
|
|
1407
1409
|
this.widgetContainerAbove.addChild({
|
|
1408
1410
|
render: () => pinned.children.length > 0 ? [] : [""],
|
|
@@ -1422,7 +1424,9 @@ export class InteractiveMode {
|
|
|
1422
1424
|
spacerWhenEmpty: boolean,
|
|
1423
1425
|
leadingSpacer: boolean,
|
|
1424
1426
|
): void {
|
|
1425
|
-
|
|
1427
|
+
// Detach without disposing — the widgets map owns lifecycle; disposing
|
|
1428
|
+
// here would kill refresh timers and subscriptions on every re-render.
|
|
1429
|
+
container.detachChildren();
|
|
1426
1430
|
|
|
1427
1431
|
if (widgets.size === 0) {
|
|
1428
1432
|
if (spacerWhenEmpty) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { describe, it } from "node:test";
|
|
3
|
-
import { TUI } from "../tui.js";
|
|
3
|
+
import { Container, TUI } from "../tui.js";
|
|
4
4
|
function makeTerminal() {
|
|
5
5
|
return {
|
|
6
6
|
isTTY: true,
|
|
@@ -40,4 +40,33 @@ describe("TUI", () => {
|
|
|
40
40
|
assert.equal(anyTui.inputBuffer, "");
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
|
+
describe("Container", () => {
|
|
44
|
+
function makeDisposableChild(counter) {
|
|
45
|
+
return {
|
|
46
|
+
render: () => [],
|
|
47
|
+
invalidate() { },
|
|
48
|
+
dispose() {
|
|
49
|
+
counter.disposed++;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
it("detachChildren() removes children without disposing them", () => {
|
|
54
|
+
const c = new Container();
|
|
55
|
+
const counter = { disposed: 0 };
|
|
56
|
+
c.addChild(makeDisposableChild(counter));
|
|
57
|
+
c.addChild(makeDisposableChild(counter));
|
|
58
|
+
c.detachChildren();
|
|
59
|
+
assert.equal(c.children.length, 0);
|
|
60
|
+
assert.equal(counter.disposed, 0);
|
|
61
|
+
});
|
|
62
|
+
it("clear() still disposes children (regression guard for detach/dispose split)", () => {
|
|
63
|
+
const c = new Container();
|
|
64
|
+
const counter = { disposed: 0 };
|
|
65
|
+
c.addChild(makeDisposableChild(counter));
|
|
66
|
+
c.addChild(makeDisposableChild(counter));
|
|
67
|
+
c.clear();
|
|
68
|
+
assert.equal(c.children.length, 0);
|
|
69
|
+
assert.equal(counter.disposed, 2);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
43
72
|
//# sourceMappingURL=tui.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.test.js","sourceRoot":"","sources":["../../src/__tests__/tui.test.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAEzC,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"tui.test.js","sourceRoot":"","sources":["../../src/__tests__/tui.test.ts"],"names":[],"mappings":"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","sourcesContent":["import assert from \"node:assert/strict\";\nimport { describe, it } from \"node:test\";\n\nimport { Container, TUI } from \"../tui.js\";\nimport type { Component } from \"../tui.js\";\nimport type { Terminal } from \"../terminal.js\";\n\nfunction makeTerminal(): Terminal {\n\treturn {\n\t\tisTTY: true,\n\t\tcolumns: 80,\n\t\trows: 24,\n\t\tkittyProtocolActive: false,\n\t\tstart() {},\n\t\tstop() {},\n\t\tdrainInput: async () => {},\n\t\twrite() {},\n\t\tmoveBy() {},\n\t\thideCursor() {},\n\t\tshowCursor() {},\n\t\tclearLine() {},\n\t\tclearFromCursor() {},\n\t\tclearScreen() {},\n\t\tsetTitle() {},\n\t};\n}\n\ndescribe(\"TUI\", () => {\n\tit(\"does not swallow a bare Escape keypress while waiting for the cell-size response\", () => {\n\t\tconst tui = new TUI(makeTerminal());\n\t\tconst received: string[] = [];\n\n\t\ttui.setFocus({\n\t\t\trender: () => [],\n\t\t\thandleInput: (data: string) => {\n\t\t\t\treceived.push(data);\n\t\t\t},\n\t\t\tinvalidate() {},\n\t\t});\n\n\t\tconst anyTui = tui as any;\n\t\tanyTui.cellSizeQueryPending = true;\n\t\tanyTui.inputBuffer = \"\";\n\n\t\tanyTui.handleInput(\"\\x1b\");\n\n\t\tassert.deepEqual(received, [\"\\x1b\"]);\n\t\tassert.equal(anyTui.cellSizeQueryPending, false);\n\t\tassert.equal(anyTui.inputBuffer, \"\");\n\t});\n});\n\ndescribe(\"Container\", () => {\n\tfunction makeDisposableChild(counter: { disposed: number }): Component & { dispose(): void } {\n\t\treturn {\n\t\t\trender: () => [],\n\t\t\tinvalidate() {},\n\t\t\tdispose() {\n\t\t\t\tcounter.disposed++;\n\t\t\t},\n\t\t};\n\t}\n\n\tit(\"detachChildren() removes children without disposing them\", () => {\n\t\tconst c = new Container();\n\t\tconst counter = { disposed: 0 };\n\t\tc.addChild(makeDisposableChild(counter));\n\t\tc.addChild(makeDisposableChild(counter));\n\n\t\tc.detachChildren();\n\n\t\tassert.equal(c.children.length, 0);\n\t\tassert.equal(counter.disposed, 0);\n\t});\n\n\tit(\"clear() still disposes children (regression guard for detach/dispose split)\", () => {\n\t\tconst c = new Container();\n\t\tconst counter = { disposed: 0 };\n\t\tc.addChild(makeDisposableChild(counter));\n\t\tc.addChild(makeDisposableChild(counter));\n\n\t\tc.clear();\n\n\t\tassert.equal(c.children.length, 0);\n\t\tassert.equal(counter.disposed, 2);\n\t});\n});\n"]}
|
|
@@ -128,6 +128,13 @@ export declare class Container implements Component {
|
|
|
128
128
|
addChild(component: Component): void;
|
|
129
129
|
removeChild(component: Component): void;
|
|
130
130
|
clear(): void;
|
|
131
|
+
/**
|
|
132
|
+
* Remove all children without calling dispose on them.
|
|
133
|
+
* Use when child lifecycle is owned elsewhere and the container is only a
|
|
134
|
+
* render mount (e.g. extension widget containers in InteractiveMode, where
|
|
135
|
+
* the extensionWidgets* maps own disposal).
|
|
136
|
+
*/
|
|
137
|
+
detachChildren(): void;
|
|
131
138
|
invalidate(): void;
|
|
132
139
|
render(width: number): string[];
|
|
133
140
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../src/tui.ts"],"names":[],"mappings":"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"}
|
|
@@ -52,6 +52,16 @@ export class Container {
|
|
|
52
52
|
this.children = [];
|
|
53
53
|
this._prevRender = null;
|
|
54
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Remove all children without calling dispose on them.
|
|
57
|
+
* Use when child lifecycle is owned elsewhere and the container is only a
|
|
58
|
+
* render mount (e.g. extension widget containers in InteractiveMode, where
|
|
59
|
+
* the extensionWidgets* maps own disposal).
|
|
60
|
+
*/
|
|
61
|
+
detachChildren() {
|
|
62
|
+
this.children = [];
|
|
63
|
+
this._prevRender = null;
|
|
64
|
+
}
|
|
55
65
|
invalidate() {
|
|
56
66
|
for (const child of this.children) {
|
|
57
67
|
child.invalidate?.();
|