fix(coding-agent): stabilize interactive status indicators
Closes #6026
This commit is contained in:
@@ -0,0 +1,114 @@
|
||||
import { type Component, Loader, type TUI } from "@earendil-works/pi-tui";
|
||||
import type { WorkingIndicatorOptions } from "../../../core/extensions/index.ts";
|
||||
import { theme } from "../theme/theme.ts";
|
||||
import { CountdownTimer } from "./countdown-timer.ts";
|
||||
import { keyText } from "./keybinding-hints.ts";
|
||||
|
||||
export type StatusIndicatorKind = "working" | "retry" | "compaction" | "branchSummary";
|
||||
|
||||
export class StatusIndicator extends Loader {
|
||||
readonly kind: StatusIndicatorKind;
|
||||
|
||||
constructor(
|
||||
kind: StatusIndicatorKind,
|
||||
ui: TUI,
|
||||
spinnerColorFn: (str: string) => string,
|
||||
messageColorFn: (str: string) => string,
|
||||
message: string,
|
||||
indicator?: WorkingIndicatorOptions,
|
||||
) {
|
||||
super(ui, spinnerColorFn, messageColorFn, message, indicator);
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.stop();
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkingStatusIndicator extends StatusIndicator {
|
||||
constructor(ui: TUI, message: string, indicator?: WorkingIndicatorOptions) {
|
||||
super(
|
||||
"working",
|
||||
ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
message,
|
||||
indicator,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class RetryStatusIndicator extends StatusIndicator {
|
||||
private countdown: CountdownTimer | undefined;
|
||||
|
||||
constructor(ui: TUI, attempt: number, maxAttempts: number, delayMs: number) {
|
||||
const retryMessage = (seconds: number) =>
|
||||
`Retrying (${attempt}/${maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;
|
||||
super(
|
||||
"retry",
|
||||
ui,
|
||||
(spinner) => theme.fg("warning", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
retryMessage(Math.ceil(delayMs / 1000)),
|
||||
);
|
||||
this.countdown = new CountdownTimer(
|
||||
delayMs,
|
||||
ui,
|
||||
(seconds) => {
|
||||
this.setMessage(retryMessage(seconds));
|
||||
},
|
||||
() => {
|
||||
this.countdown = undefined;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
override dispose(): void {
|
||||
this.countdown?.dispose();
|
||||
this.countdown = undefined;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export type CompactionStatusReason = "manual" | "threshold" | "overflow";
|
||||
|
||||
export class CompactionStatusIndicator extends StatusIndicator {
|
||||
constructor(ui: TUI, reason: CompactionStatusReason) {
|
||||
const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
|
||||
const label =
|
||||
reason === "manual"
|
||||
? `Compacting context... ${cancelHint}`
|
||||
: `${reason === "overflow" ? "Context overflow detected, " : ""}Auto-compacting... ${cancelHint}`;
|
||||
super(
|
||||
"compaction",
|
||||
ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
label,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class BranchSummaryStatusIndicator extends StatusIndicator {
|
||||
constructor(ui: TUI) {
|
||||
super(
|
||||
"branchSummary",
|
||||
ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
`Summarizing branch... (${keyText("app.interrupt")} to cancel)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class IdleStatus implements Component {
|
||||
invalidate(): void {
|
||||
// No cached state to invalidate.
|
||||
}
|
||||
|
||||
render(width: number): string[] {
|
||||
const emptyLine = " ".repeat(width);
|
||||
return [emptyLine, emptyLine];
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,6 @@ import {
|
||||
fuzzyFilter,
|
||||
getCapabilities,
|
||||
hyperlink,
|
||||
Loader,
|
||||
type LoaderIndicatorOptions,
|
||||
Markdown,
|
||||
matchesKey,
|
||||
ProcessTerminal,
|
||||
@@ -72,6 +70,7 @@ import type {
|
||||
ExtensionUIDialogOptions,
|
||||
ExtensionWidgetOptions,
|
||||
ProjectTrustContext,
|
||||
WorkingIndicatorOptions,
|
||||
} from "../../core/extensions/index.ts";
|
||||
import { FooterDataProvider, type ReadonlyFooterDataProvider } from "../../core/footer-data-provider.ts";
|
||||
import { configureHttpDispatcher, formatHttpIdleTimeoutMs } from "../../core/http-dispatcher.ts";
|
||||
@@ -103,7 +102,6 @@ import { BashExecutionComponent } from "./components/bash-execution.ts";
|
||||
import { BorderedLoader } from "./components/bordered-loader.ts";
|
||||
import { BranchSummaryMessageComponent } from "./components/branch-summary-message.ts";
|
||||
import { CompactionSummaryMessageComponent } from "./components/compaction-summary-message.ts";
|
||||
import { CountdownTimer } from "./components/countdown-timer.ts";
|
||||
import { CustomEditor } from "./components/custom-editor.ts";
|
||||
import { CustomMessageComponent } from "./components/custom-message.ts";
|
||||
import { DaxnutsComponent } from "./components/daxnuts.ts";
|
||||
@@ -121,6 +119,14 @@ import { ScopedModelsSelectorComponent } from "./components/scoped-models-select
|
||||
import { SessionSelectorComponent } from "./components/session-selector.ts";
|
||||
import { SettingsSelectorComponent } from "./components/settings-selector.ts";
|
||||
import { SkillInvocationMessageComponent } from "./components/skill-invocation-message.ts";
|
||||
import {
|
||||
BranchSummaryStatusIndicator,
|
||||
CompactionStatusIndicator,
|
||||
IdleStatus,
|
||||
RetryStatusIndicator,
|
||||
type StatusIndicator,
|
||||
WorkingStatusIndicator,
|
||||
} from "./components/status-indicator.ts";
|
||||
import { ToolExecutionComponent } from "./components/tool-execution.ts";
|
||||
import { TreeSelectorComponent } from "./components/tree-selector.ts";
|
||||
import { TrustSelectorComponent } from "./components/trust-selector.ts";
|
||||
@@ -284,10 +290,11 @@ export class InteractiveMode {
|
||||
private isInitialized = false;
|
||||
private onInputCallback?: (text: string) => void;
|
||||
private pendingUserInputs: string[] = [];
|
||||
private loadingAnimation: Loader | undefined = undefined;
|
||||
private activeStatusIndicator: StatusIndicator | undefined = undefined;
|
||||
private readonly idleStatus = new IdleStatus();
|
||||
private workingMessage: string | undefined = undefined;
|
||||
private workingVisible = true;
|
||||
private workingIndicatorOptions: LoaderIndicatorOptions | undefined = undefined;
|
||||
private workingIndicatorOptions: WorkingIndicatorOptions | undefined = undefined;
|
||||
private readonly defaultWorkingMessage = "Working...";
|
||||
private readonly defaultHiddenThinkingLabel = "Thinking...";
|
||||
private hiddenThinkingLabel = this.defaultHiddenThinkingLabel;
|
||||
@@ -332,12 +339,9 @@ export class InteractiveMode {
|
||||
private pendingBashComponents: BashExecutionComponent[] = [];
|
||||
|
||||
// Auto-compaction state
|
||||
private autoCompactionLoader: Loader | undefined = undefined;
|
||||
private autoCompactionEscapeHandler?: () => void;
|
||||
|
||||
// Auto-retry state
|
||||
private retryLoader: Loader | undefined = undefined;
|
||||
private retryCountdown: CountdownTimer | undefined = undefined;
|
||||
private retryEscapeHandler?: () => void;
|
||||
|
||||
// Messages queued while compaction is running
|
||||
@@ -1548,11 +1552,7 @@ export class InteractiveMode {
|
||||
commandContextActions: {
|
||||
waitForIdle: () => this.session.agent.waitForIdle(),
|
||||
newSession: async (options) => {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
this.clearStatusIndicator();
|
||||
try {
|
||||
return await this.runtimeHost.newSession(options);
|
||||
} catch (error: unknown) {
|
||||
@@ -1625,7 +1625,11 @@ export class InteractiveMode {
|
||||
this.footerDataProvider.setCwd(this.sessionManager.getCwd());
|
||||
this.hideThinkingBlock = this.settingsManager.getHideThinkingBlock();
|
||||
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
||||
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
||||
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
||||
this.ui.setClearOnShrink(clearOnShrink);
|
||||
if (!clearOnShrink && !this.activeStatusIndicator) {
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
const editorPaddingX = this.settingsManager.getEditorPaddingX();
|
||||
const autocompleteMaxVisible = this.settingsManager.getAutocompleteMaxVisible();
|
||||
this.defaultEditor.setPaddingX(editorPaddingX);
|
||||
@@ -1744,46 +1748,50 @@ export class InteractiveMode {
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
private getWorkingLoaderMessage(): string {
|
||||
return this.workingMessage ?? this.defaultWorkingMessage;
|
||||
}
|
||||
|
||||
private createWorkingLoader(): Loader {
|
||||
return new Loader(
|
||||
this.ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
this.getWorkingLoaderMessage(),
|
||||
this.workingIndicatorOptions,
|
||||
);
|
||||
}
|
||||
|
||||
private stopWorkingLoader(): void {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
private showStatusIndicator(indicator: StatusIndicator): void {
|
||||
this.activeStatusIndicator?.dispose();
|
||||
this.activeStatusIndicator = indicator;
|
||||
this.statusContainer.clear();
|
||||
this.statusContainer.addChild(indicator);
|
||||
}
|
||||
|
||||
private clearStatusIndicator(kind?: StatusIndicator["kind"]): void {
|
||||
if (kind && this.activeStatusIndicator?.kind !== kind) {
|
||||
return;
|
||||
}
|
||||
const hadActiveStatusIndicator = this.activeStatusIndicator !== undefined;
|
||||
this.activeStatusIndicator?.dispose();
|
||||
this.activeStatusIndicator = undefined;
|
||||
this.statusContainer.clear();
|
||||
if (hadActiveStatusIndicator && this.ui.getClearOnShrink()) {
|
||||
this.statusContainer.addChild(this.idleStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private setWorkingVisible(visible: boolean): void {
|
||||
this.workingVisible = visible;
|
||||
if (!visible) {
|
||||
this.stopWorkingLoader();
|
||||
this.clearStatusIndicator("working");
|
||||
this.ui.requestRender();
|
||||
return;
|
||||
}
|
||||
if (this.session.isStreaming && !this.loadingAnimation) {
|
||||
this.statusContainer.clear();
|
||||
this.loadingAnimation = this.createWorkingLoader();
|
||||
this.statusContainer.addChild(this.loadingAnimation);
|
||||
if (this.session.isStreaming && this.activeStatusIndicator?.kind !== "working") {
|
||||
this.showStatusIndicator(
|
||||
new WorkingStatusIndicator(
|
||||
this.ui,
|
||||
this.workingMessage ?? this.defaultWorkingMessage,
|
||||
this.workingIndicatorOptions,
|
||||
),
|
||||
);
|
||||
}
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
private setWorkingIndicator(options?: LoaderIndicatorOptions): void {
|
||||
private setWorkingIndicator(options?: WorkingIndicatorOptions): void {
|
||||
this.workingIndicatorOptions = options;
|
||||
this.loadingAnimation?.setIndicator(options);
|
||||
if (this.activeStatusIndicator?.kind === "working") {
|
||||
this.activeStatusIndicator.setIndicator(options);
|
||||
}
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
@@ -1882,8 +1890,10 @@ export class InteractiveMode {
|
||||
this.workingMessage = undefined;
|
||||
this.workingVisible = true;
|
||||
this.setWorkingIndicator();
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.setMessage(`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`);
|
||||
if (this.activeStatusIndicator?.kind === "working") {
|
||||
this.activeStatusIndicator.setMessage(
|
||||
`${this.defaultWorkingMessage} (${keyText("app.interrupt")} to interrupt)`,
|
||||
);
|
||||
}
|
||||
this.setHiddenThinkingLabel();
|
||||
}
|
||||
@@ -2047,8 +2057,8 @@ export class InteractiveMode {
|
||||
setStatus: (key, text) => this.setExtensionStatus(key, text),
|
||||
setWorkingMessage: (message) => {
|
||||
this.workingMessage = message;
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.setMessage(message ?? this.defaultWorkingMessage);
|
||||
if (this.activeStatusIndicator?.kind === "working") {
|
||||
this.activeStatusIndicator.setMessage(message ?? this.defaultWorkingMessage);
|
||||
}
|
||||
},
|
||||
setWorkingVisible: (visible) => this.setWorkingVisible(visible),
|
||||
@@ -2749,18 +2759,16 @@ export class InteractiveMode {
|
||||
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
||||
this.retryEscapeHandler = undefined;
|
||||
}
|
||||
if (this.retryCountdown) {
|
||||
this.retryCountdown.dispose();
|
||||
this.retryCountdown = undefined;
|
||||
}
|
||||
if (this.retryLoader) {
|
||||
this.retryLoader.stop();
|
||||
this.retryLoader = undefined;
|
||||
}
|
||||
this.stopWorkingLoader();
|
||||
if (this.workingVisible) {
|
||||
this.loadingAnimation = this.createWorkingLoader();
|
||||
this.statusContainer.addChild(this.loadingAnimation);
|
||||
this.showStatusIndicator(
|
||||
new WorkingStatusIndicator(
|
||||
this.ui,
|
||||
this.workingMessage ?? this.defaultWorkingMessage,
|
||||
this.workingIndicatorOptions,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
this.clearStatusIndicator();
|
||||
}
|
||||
this.ui.requestRender();
|
||||
break;
|
||||
@@ -2924,11 +2932,7 @@ export class InteractiveMode {
|
||||
if (this.settingsManager.getShowTerminalProgress()) {
|
||||
this.ui.terminal.setProgress(false);
|
||||
}
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
this.clearStatusIndicator("working");
|
||||
if (this.streamingComponent) {
|
||||
this.chatContainer.removeChild(this.streamingComponent);
|
||||
this.streamingComponent = undefined;
|
||||
@@ -2950,19 +2954,7 @@ export class InteractiveMode {
|
||||
this.defaultEditor.onEscape = () => {
|
||||
this.session.abortCompaction();
|
||||
};
|
||||
this.statusContainer.clear();
|
||||
const cancelHint = `(${keyText("app.interrupt")} to cancel)`;
|
||||
const label =
|
||||
event.reason === "manual"
|
||||
? `Compacting context... ${cancelHint}`
|
||||
: `${event.reason === "overflow" ? "Context overflow detected, " : ""}Auto-compacting... ${cancelHint}`;
|
||||
this.autoCompactionLoader = new Loader(
|
||||
this.ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
label,
|
||||
);
|
||||
this.statusContainer.addChild(this.autoCompactionLoader);
|
||||
this.showStatusIndicator(new CompactionStatusIndicator(this.ui, event.reason));
|
||||
this.ui.requestRender();
|
||||
break;
|
||||
}
|
||||
@@ -2975,11 +2967,7 @@ export class InteractiveMode {
|
||||
this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
|
||||
this.autoCompactionEscapeHandler = undefined;
|
||||
}
|
||||
if (this.autoCompactionLoader) {
|
||||
this.autoCompactionLoader.stop();
|
||||
this.autoCompactionLoader = undefined;
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
this.clearStatusIndicator("compaction");
|
||||
if (event.aborted) {
|
||||
if (event.reason === "manual") {
|
||||
this.showError("Compaction cancelled");
|
||||
@@ -3016,28 +3004,9 @@ export class InteractiveMode {
|
||||
this.defaultEditor.onEscape = () => {
|
||||
this.session.abortRetry();
|
||||
};
|
||||
// Show retry indicator
|
||||
this.statusContainer.clear();
|
||||
this.retryCountdown?.dispose();
|
||||
const retryMessage = (seconds: number) =>
|
||||
`Retrying (${event.attempt}/${event.maxAttempts}) in ${seconds}s... (${keyText("app.interrupt")} to cancel)`;
|
||||
this.retryLoader = new Loader(
|
||||
this.ui,
|
||||
(spinner) => theme.fg("warning", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
retryMessage(Math.ceil(event.delayMs / 1000)),
|
||||
this.showStatusIndicator(
|
||||
new RetryStatusIndicator(this.ui, event.attempt, event.maxAttempts, event.delayMs),
|
||||
);
|
||||
this.retryCountdown = new CountdownTimer(
|
||||
event.delayMs,
|
||||
this.ui,
|
||||
(seconds) => {
|
||||
this.retryLoader?.setMessage(retryMessage(seconds));
|
||||
},
|
||||
() => {
|
||||
this.retryCountdown = undefined;
|
||||
},
|
||||
);
|
||||
this.statusContainer.addChild(this.retryLoader);
|
||||
this.ui.requestRender();
|
||||
break;
|
||||
}
|
||||
@@ -3048,16 +3017,7 @@ export class InteractiveMode {
|
||||
this.defaultEditor.onEscape = this.retryEscapeHandler;
|
||||
this.retryEscapeHandler = undefined;
|
||||
}
|
||||
if (this.retryCountdown) {
|
||||
this.retryCountdown.dispose();
|
||||
this.retryCountdown = undefined;
|
||||
}
|
||||
// Stop loader
|
||||
if (this.retryLoader) {
|
||||
this.retryLoader.stop();
|
||||
this.retryLoader = undefined;
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
this.clearStatusIndicator("retry");
|
||||
// Show error only on final failure (success shows normal response)
|
||||
if (!event.success) {
|
||||
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError || "Unknown error"}`);
|
||||
@@ -4111,6 +4071,9 @@ export class InteractiveMode {
|
||||
onClearOnShrinkChange: (enabled) => {
|
||||
this.settingsManager.setClearOnShrink(enabled);
|
||||
this.ui.setClearOnShrink(enabled);
|
||||
if (!enabled && !this.activeStatusIndicator) {
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
},
|
||||
onShowTerminalProgressChange: (enabled) => {
|
||||
this.settingsManager.setShowTerminalProgress(enabled);
|
||||
@@ -4490,8 +4453,8 @@ export class InteractiveMode {
|
||||
}
|
||||
}
|
||||
|
||||
// Set up escape handler and loader if summarizing
|
||||
let summaryLoader: Loader | undefined;
|
||||
// Set up escape handler and status indicator if summarizing
|
||||
let showingSummaryIndicator = false;
|
||||
const originalOnEscape = this.defaultEditor.onEscape;
|
||||
|
||||
if (wantsSummary) {
|
||||
@@ -4499,13 +4462,8 @@ export class InteractiveMode {
|
||||
this.session.abortBranchSummary();
|
||||
};
|
||||
this.chatContainer.addChild(new Spacer(1));
|
||||
summaryLoader = new Loader(
|
||||
this.ui,
|
||||
(spinner) => theme.fg("accent", spinner),
|
||||
(text) => theme.fg("muted", text),
|
||||
`Summarizing branch... (${keyText("app.interrupt")} to cancel)`,
|
||||
);
|
||||
this.statusContainer.addChild(summaryLoader);
|
||||
this.showStatusIndicator(new BranchSummaryStatusIndicator(this.ui));
|
||||
showingSummaryIndicator = true;
|
||||
this.ui.requestRender();
|
||||
}
|
||||
|
||||
@@ -4537,9 +4495,8 @@ export class InteractiveMode {
|
||||
} catch (error) {
|
||||
this.showError(error instanceof Error ? error.message : String(error));
|
||||
} finally {
|
||||
if (summaryLoader) {
|
||||
summaryLoader.stop();
|
||||
this.statusContainer.clear();
|
||||
if (showingSummaryIndicator) {
|
||||
this.clearStatusIndicator("branchSummary");
|
||||
}
|
||||
this.defaultEditor.onEscape = originalOnEscape;
|
||||
}
|
||||
@@ -4601,11 +4558,7 @@ export class InteractiveMode {
|
||||
sessionPath: string,
|
||||
options?: Parameters<ExtensionCommandContext["switchSession"]>[1],
|
||||
): Promise<{ cancelled: boolean }> {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
this.clearStatusIndicator();
|
||||
try {
|
||||
const result = await this.runtimeHost.switchSession(sessionPath, {
|
||||
withSession: options?.withSession,
|
||||
@@ -5114,7 +5067,11 @@ export class InteractiveMode {
|
||||
this.editor.setAutocompleteMaxVisible?.(autocompleteMaxVisible);
|
||||
}
|
||||
this.ui.setShowHardwareCursor(this.settingsManager.getShowHardwareCursor());
|
||||
this.ui.setClearOnShrink(this.settingsManager.getClearOnShrink());
|
||||
const clearOnShrink = this.settingsManager.getClearOnShrink();
|
||||
this.ui.setClearOnShrink(clearOnShrink);
|
||||
if (!clearOnShrink && !this.activeStatusIndicator) {
|
||||
this.statusContainer.clear();
|
||||
}
|
||||
this.setupAutocompleteProvider();
|
||||
const runner = this.session.extensionRunner;
|
||||
this.setupExtensionShortcuts(runner);
|
||||
@@ -5201,11 +5158,7 @@ export class InteractiveMode {
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
this.clearStatusIndicator();
|
||||
const result = await this.runtimeHost.importFromJsonl(inputPath);
|
||||
if (result.cancelled) {
|
||||
this.showStatus("Import cancelled");
|
||||
@@ -5556,11 +5509,7 @@ export class InteractiveMode {
|
||||
}
|
||||
|
||||
private async handleClearCommand(): Promise<void> {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
this.clearStatusIndicator();
|
||||
try {
|
||||
const result = await this.runtimeHost.newSession();
|
||||
if (result.cancelled) {
|
||||
@@ -5719,11 +5668,7 @@ export class InteractiveMode {
|
||||
}
|
||||
|
||||
private async handleCompactCommand(customInstructions?: string): Promise<void> {
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.statusContainer.clear();
|
||||
this.clearStatusIndicator();
|
||||
|
||||
try {
|
||||
await this.session.compact(customInstructions);
|
||||
@@ -5736,10 +5681,7 @@ export class InteractiveMode {
|
||||
if (this.settingsManager.getShowTerminalProgress()) {
|
||||
this.ui.terminal.setProgress(false);
|
||||
}
|
||||
if (this.loadingAnimation) {
|
||||
this.loadingAnimation.stop();
|
||||
this.loadingAnimation = undefined;
|
||||
}
|
||||
this.clearStatusIndicator();
|
||||
this.themeController.disableAutoSync();
|
||||
this.clearExtensionTerminalInputListeners();
|
||||
this.footer.dispose();
|
||||
|
||||
Reference in New Issue
Block a user