fix(coding-agent): make terminal progress escape sequences configurable, disabled by default
Adds terminal.showTerminalProgress setting (default false) and wires it to /settings. Guards all OSC 9;4 setProgress calls in interactive-mode. closes #3588
This commit is contained in:
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Breaking Changes
|
||||||
|
|
||||||
|
- Disabled OSC 9;4 terminal progress indicators by default. Set `terminal.showTerminalProgress` to `true` in `/settings` to re-enable ([#3588](https://github.com/badlogic/pi-mono/issues/3588))
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Fixed `ctx.ui.setWorkingMessage()` to persist across loader recreation, matching the behavior of `ctx.ui.setWorkingIndicator()` ([#3566](https://github.com/badlogic/pi-mono/issues/3566))
|
- Fixed `ctx.ui.setWorkingMessage()` to persist across loader recreation, matching the behavior of `ctx.ui.setWorkingIndicator()` ([#3566](https://github.com/badlogic/pi-mono/issues/3566))
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ export interface TerminalSettings {
|
|||||||
showImages?: boolean; // default: true (only relevant if terminal supports images)
|
showImages?: boolean; // default: true (only relevant if terminal supports images)
|
||||||
imageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)
|
imageWidthCells?: number; // default: 60 (preferred inline image width in terminal cells)
|
||||||
clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
|
clearOnShrink?: boolean; // default: false (clear empty rows when content shrinks)
|
||||||
|
showTerminalProgress?: boolean; // default: false (OSC 9;4 terminal progress indicators)
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ImageSettings {
|
export interface ImageSettings {
|
||||||
@@ -905,6 +906,19 @@ export class SettingsManager {
|
|||||||
this.save();
|
this.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getShowTerminalProgress(): boolean {
|
||||||
|
return this.settings.terminal?.showTerminalProgress ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowTerminalProgress(enabled: boolean): void {
|
||||||
|
if (!this.globalSettings.terminal) {
|
||||||
|
this.globalSettings.terminal = {};
|
||||||
|
}
|
||||||
|
this.globalSettings.terminal.showTerminalProgress = enabled;
|
||||||
|
this.markModified("terminal", "showTerminalProgress");
|
||||||
|
this.save();
|
||||||
|
}
|
||||||
|
|
||||||
getImageAutoResize(): boolean {
|
getImageAutoResize(): boolean {
|
||||||
return this.settings.images?.autoResize ?? true;
|
return this.settings.images?.autoResize ?? true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ export interface SettingsConfig {
|
|||||||
autocompleteMaxVisible: number;
|
autocompleteMaxVisible: number;
|
||||||
quietStartup: boolean;
|
quietStartup: boolean;
|
||||||
clearOnShrink: boolean;
|
clearOnShrink: boolean;
|
||||||
|
showTerminalProgress: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SettingsCallbacks {
|
export interface SettingsCallbacks {
|
||||||
@@ -77,6 +78,7 @@ export interface SettingsCallbacks {
|
|||||||
onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
|
onAutocompleteMaxVisibleChange: (maxVisible: number) => void;
|
||||||
onQuietStartupChange: (enabled: boolean) => void;
|
onQuietStartupChange: (enabled: boolean) => void;
|
||||||
onClearOnShrinkChange: (enabled: boolean) => void;
|
onClearOnShrinkChange: (enabled: boolean) => void;
|
||||||
|
onShowTerminalProgressChange: (enabled: boolean) => void;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,6 +374,16 @@ export class SettingsSelectorComponent extends Container {
|
|||||||
values: ["true", "false"],
|
values: ["true", "false"],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Terminal progress toggle (insert after clear-on-shrink)
|
||||||
|
const clearOnShrinkIndex = items.findIndex((item) => item.id === "clear-on-shrink");
|
||||||
|
items.splice(clearOnShrinkIndex + 1, 0, {
|
||||||
|
id: "terminal-progress",
|
||||||
|
label: "Terminal progress",
|
||||||
|
description: "Show OSC 9;4 progress indicators in the terminal tab bar",
|
||||||
|
currentValue: config.showTerminalProgress ? "true" : "false",
|
||||||
|
values: ["true", "false"],
|
||||||
|
});
|
||||||
|
|
||||||
// Add borders
|
// Add borders
|
||||||
this.addChild(new DynamicBorder());
|
this.addChild(new DynamicBorder());
|
||||||
|
|
||||||
@@ -440,6 +452,9 @@ export class SettingsSelectorComponent extends Container {
|
|||||||
case "clear-on-shrink":
|
case "clear-on-shrink":
|
||||||
callbacks.onClearOnShrinkChange(newValue === "true");
|
callbacks.onClearOnShrinkChange(newValue === "true");
|
||||||
break;
|
break;
|
||||||
|
case "terminal-progress":
|
||||||
|
callbacks.onShowTerminalProgressChange(newValue === "true");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
callbacks.onCancel,
|
callbacks.onCancel,
|
||||||
|
|||||||
@@ -2594,7 +2594,9 @@ export class InteractiveMode {
|
|||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "agent_start":
|
case "agent_start":
|
||||||
|
if (this.settingsManager.getShowTerminalProgress()) {
|
||||||
this.ui.terminal.setProgress(true);
|
this.ui.terminal.setProgress(true);
|
||||||
|
}
|
||||||
// Restore main escape handler if retry handler is still active
|
// Restore main escape handler if retry handler is still active
|
||||||
// (retry success event fires later, but we need main handler now)
|
// (retry success event fires later, but we need main handler now)
|
||||||
if (this.retryEscapeHandler) {
|
if (this.retryEscapeHandler) {
|
||||||
@@ -2769,7 +2771,9 @@ export class InteractiveMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "agent_end":
|
case "agent_end":
|
||||||
|
if (this.settingsManager.getShowTerminalProgress()) {
|
||||||
this.ui.terminal.setProgress(false);
|
this.ui.terminal.setProgress(false);
|
||||||
|
}
|
||||||
if (this.loadingAnimation) {
|
if (this.loadingAnimation) {
|
||||||
this.loadingAnimation.stop();
|
this.loadingAnimation.stop();
|
||||||
this.loadingAnimation = undefined;
|
this.loadingAnimation = undefined;
|
||||||
@@ -2788,7 +2792,9 @@ export class InteractiveMode {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "compaction_start": {
|
case "compaction_start": {
|
||||||
|
if (this.settingsManager.getShowTerminalProgress()) {
|
||||||
this.ui.terminal.setProgress(true);
|
this.ui.terminal.setProgress(true);
|
||||||
|
}
|
||||||
// Keep editor active; submissions are queued during compaction.
|
// Keep editor active; submissions are queued during compaction.
|
||||||
this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
|
this.autoCompactionEscapeHandler = this.defaultEditor.onEscape;
|
||||||
this.defaultEditor.onEscape = () => {
|
this.defaultEditor.onEscape = () => {
|
||||||
@@ -2812,7 +2818,9 @@ export class InteractiveMode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case "compaction_end": {
|
case "compaction_end": {
|
||||||
|
if (this.settingsManager.getShowTerminalProgress()) {
|
||||||
this.ui.terminal.setProgress(false);
|
this.ui.terminal.setProgress(false);
|
||||||
|
}
|
||||||
if (this.autoCompactionEscapeHandler) {
|
if (this.autoCompactionEscapeHandler) {
|
||||||
this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
|
this.defaultEditor.onEscape = this.autoCompactionEscapeHandler;
|
||||||
this.autoCompactionEscapeHandler = undefined;
|
this.autoCompactionEscapeHandler = undefined;
|
||||||
@@ -3711,6 +3719,7 @@ export class InteractiveMode {
|
|||||||
autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
|
autocompleteMaxVisible: this.settingsManager.getAutocompleteMaxVisible(),
|
||||||
quietStartup: this.settingsManager.getQuietStartup(),
|
quietStartup: this.settingsManager.getQuietStartup(),
|
||||||
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
clearOnShrink: this.settingsManager.getClearOnShrink(),
|
||||||
|
showTerminalProgress: this.settingsManager.getShowTerminalProgress(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onAutoCompactChange: (enabled) => {
|
onAutoCompactChange: (enabled) => {
|
||||||
@@ -3821,6 +3830,9 @@ export class InteractiveMode {
|
|||||||
this.settingsManager.setClearOnShrink(enabled);
|
this.settingsManager.setClearOnShrink(enabled);
|
||||||
this.ui.setClearOnShrink(enabled);
|
this.ui.setClearOnShrink(enabled);
|
||||||
},
|
},
|
||||||
|
onShowTerminalProgressChange: (enabled) => {
|
||||||
|
this.settingsManager.setShowTerminalProgress(enabled);
|
||||||
|
},
|
||||||
onCancel: () => {
|
onCancel: () => {
|
||||||
done();
|
done();
|
||||||
this.ui.requestRender();
|
this.ui.requestRender();
|
||||||
@@ -5329,7 +5341,9 @@ export class InteractiveMode {
|
|||||||
|
|
||||||
stop(): void {
|
stop(): void {
|
||||||
this.unregisterSignalHandlers();
|
this.unregisterSignalHandlers();
|
||||||
|
if (this.settingsManager.getShowTerminalProgress()) {
|
||||||
this.ui.terminal.setProgress(false);
|
this.ui.terminal.setProgress(false);
|
||||||
|
}
|
||||||
if (this.loadingAnimation) {
|
if (this.loadingAnimation) {
|
||||||
this.loadingAnimation.stop();
|
this.loadingAnimation.stop();
|
||||||
this.loadingAnimation = undefined;
|
this.loadingAnimation = undefined;
|
||||||
|
|||||||
Reference in New Issue
Block a user