mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(tui): preserve shared prompts when scrollback is full (#115165)
This commit is contained in:
committed by
GitHub
parent
89b6d85cdd
commit
0f188c8cc6
@@ -387,6 +387,38 @@ describe("ChatLog", () => {
|
||||
expect(normalizeTestText(chatLog.render(120).join("\n"))).toContain("Still streaming.");
|
||||
});
|
||||
|
||||
it("preserves a delayed shared prompt and its active reply when scrollback is full", () => {
|
||||
const chatLog = new ChatLog(20);
|
||||
chatLog.updateAssistant("Already streaming.", "shared-run");
|
||||
for (let index = 0; index < 19; index += 1) {
|
||||
chatLog.addSystem(`Older notice ${index}.`);
|
||||
}
|
||||
|
||||
chatLog.addLiveUser("Sent from the other client.", {
|
||||
messageId: "shared-overflow-user",
|
||||
runId: "shared-run",
|
||||
});
|
||||
chatLog.addLiveUser("Sent from the other client.", {
|
||||
messageId: "shared-overflow-user",
|
||||
runId: "shared-run",
|
||||
});
|
||||
|
||||
const rendered = normalizeTestText(chatLog.render(120).join("\n"));
|
||||
expect(chatLog.children).toHaveLength(20);
|
||||
expect(rendered).toContain("Sent from the other client.");
|
||||
expect(rendered).toContain("Already streaming.");
|
||||
expect(rendered).not.toContain("Older notice 0.");
|
||||
expect(rendered.match(/Sent from the other client\./g)).toHaveLength(1);
|
||||
expect(rendered.indexOf("Sent from the other client.")).toBeLessThan(
|
||||
rendered.indexOf("Already streaming."),
|
||||
);
|
||||
|
||||
chatLog.updateAssistant("Still streaming after overflow.", "shared-run");
|
||||
expect(normalizeTestText(chatLog.render(120).join("\n"))).toContain(
|
||||
"Still streaming after overflow.",
|
||||
);
|
||||
});
|
||||
|
||||
it("deduplicates authoritative user events and adopts the matching pending prompt", () => {
|
||||
const chatLog = new ChatLog(40);
|
||||
chatLog.addPendingUser("shared-run", "Persisted prompt.");
|
||||
|
||||
@@ -87,9 +87,11 @@ export class ChatLog extends Container {
|
||||
}
|
||||
}
|
||||
|
||||
private pruneOverflow() {
|
||||
private pruneOverflow(protectedComponents?: ReadonlySet<Component>) {
|
||||
while (this.children.length > this.maxComponents) {
|
||||
const oldest = this.children[0];
|
||||
const oldest = protectedComponents
|
||||
? this.children.find((component) => !protectedComponents.has(component))
|
||||
: this.children[0];
|
||||
if (!oldest) {
|
||||
return;
|
||||
}
|
||||
@@ -231,12 +233,13 @@ export class ChatLog extends Container {
|
||||
frozen?.values().next().value ??
|
||||
(options.runId ? this.streamingRuns.get(options.runId) : undefined);
|
||||
const assistantIndex = assistant ? this.children.indexOf(assistant) : -1;
|
||||
if (assistantIndex >= 0) {
|
||||
if (assistant && assistantIndex >= 0) {
|
||||
// Transcript broadcasts can trail the first delta; insert their prompt
|
||||
// before the existing reply without resetting live stream or tool state.
|
||||
// before the existing reply. Preserve both when full scrollback evicts
|
||||
// older components so the newly recovered prompt cannot disappear.
|
||||
this.repeatableSystemMessage = null;
|
||||
this.children.splice(assistantIndex, 0, component);
|
||||
this.pruneOverflow();
|
||||
this.pruneOverflow(new Set([component, assistant]));
|
||||
return component;
|
||||
}
|
||||
this.appendNonSystem(component);
|
||||
|
||||
Reference in New Issue
Block a user