Release v0.51.249 — Release HQ (stage-q21) (#3523)
Some checks failed
Release & Docker / release (push) Has been cancelled
Some checks failed
Release & Docker / release (push) Has been cancelled
## Release v0.51.249 — Release HQ (stage-q21) Small opt-in feature. UX-approved (screenshot of the toggle in Settings → Preferences). ### Added | Issue | Author | Feature | |-------|--------|---------| | #2974 | @rodboev | **"Auto-expand terminal on output"** preference (Settings → Preferences, **off by default**). When enabled, the collapsed embedded terminal panel expands automatically the first time a running command emits output. Fires once per stream (guarded on open && collapsed — not per chunk), and uses `expandComposerTerminal({focus:false})` so it doesn't steal focus from the composer. Backend-persisted boolean mirroring the `simplified_tool_calling` pattern; default-off = no behavior change on upgrade. | ### Gate - Full pytest suite: **7557 passed, 0 failed** - ESLint: CLEAN · ruff: CLEAN · browser-smoke: CLEAN · screenshot vision-verified (toggle renders cleanly under "Compact tool activity", unchecked by default) - Codex (regression): **SAFE TO SHIP** (clean first pass) — no-arg `expandComposerTerminal` callers unchanged, default-off incl. settings-load-failure path, all 5 plumb sites mirror the existing pattern Co-authored-by: rodboev <rodboev@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,11 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [v0.51.249] — 2026-06-03 — Release HQ (stage-q21 — auto-expand terminal on output toggle)
|
||||
|
||||
### Added
|
||||
- New **"Auto-expand terminal on output"** preference (Settings → Preferences, **off by default**). When enabled, the collapsed embedded terminal panel surfaces itself automatically the first time a running command emits output, so long-running command output isn't silently collected behind a collapsed panel. The auto-expand does not steal focus from the composer, and fires once per stream (not per output chunk). Mirrors the existing `simplified_tool_calling` setting pattern; default-off means no behavior change on upgrade. (#2974, @rodboev)
|
||||
|
||||
## [v0.51.248] — 2026-06-03 — Release HP (stage-q20 — self-heal deleted WebUI sessions instead of bricking the chat)
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -5050,6 +5050,7 @@ _SETTINGS_DEFAULTS = {
|
||||
"notifications_enabled": False, # browser notification when tab is in background
|
||||
"show_thinking": True, # show/hide thinking/reasoning blocks in chat view
|
||||
"simplified_tool_calling": True, # render tools/thinking as compact inline timeline activity
|
||||
"terminal_auto_expand_on_output": False, # auto-expand terminal panel when output arrives while collapsed
|
||||
"api_redact_enabled": True, # redact sensitive data (API keys, secrets) from API responses
|
||||
"dashboard_plugins": {}, # plugin_name -> bool, opt-in per plugin (default off per PF-10b)
|
||||
"sidebar_density": "compact", # compact | detailed
|
||||
@@ -5196,6 +5197,7 @@ _SETTINGS_BOOL_KEYS = {
|
||||
"notifications_enabled",
|
||||
"show_thinking",
|
||||
"simplified_tool_calling",
|
||||
"terminal_auto_expand_on_output",
|
||||
"api_redact_enabled",
|
||||
"session_jump_buttons",
|
||||
"session_endless_scroll",
|
||||
|
||||
@@ -1687,6 +1687,7 @@ function applyBotName(){
|
||||
window._whatsNewSummaryEnabled=!!s.whats_new_summary_enabled;
|
||||
window._showThinking=s.show_thinking!==false;
|
||||
window._simplifiedToolCalling=s.simplified_tool_calling!==false;
|
||||
window._terminalAutoExpandOnOutput=!!s.terminal_auto_expand_on_output;
|
||||
window._activityFeedExpandedDefault=!!s.activity_feed_expanded_default;
|
||||
window._sidebarDensity=(s.sidebar_density==='detailed'?'detailed':'compact');
|
||||
window._pinnedSessionsLimit=parseInt(s.pinned_sessions_limit||3,10)||3;
|
||||
@@ -1784,6 +1785,7 @@ function applyBotName(){
|
||||
window._whatsNewSummaryEnabled=false;
|
||||
window._showThinking=true;
|
||||
window._simplifiedToolCalling=true;
|
||||
window._terminalAutoExpandOnOutput=false;
|
||||
window._sessionJumpButtonsEnabled=false;
|
||||
window._sidebarDensity='compact';
|
||||
window._pinnedSessionsLimit=3;
|
||||
|
||||
@@ -1146,6 +1146,13 @@
|
||||
</label>
|
||||
<div style="font-size:11px;color:var(--muted);margin-top:4px">Show thinking and tool calls as compact inline activity while preserving the agent timeline.</div>
|
||||
</div>
|
||||
<div class="settings-field">
|
||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||||
<input type="checkbox" id="settingsTerminalAutoExpand" style="width:15px;height:15px;accent-color:var(--accent)">
|
||||
<span>Auto-expand terminal on output</span>
|
||||
</label>
|
||||
<div style="font-size:11px;color:var(--muted);margin-top:4px">Expand the collapsed terminal panel automatically when a running command emits new output.</div>
|
||||
</div>
|
||||
<div class="settings-field">
|
||||
<label style="display:flex;align-items:center;gap:8px;cursor:pointer">
|
||||
<input type="checkbox" id="settingsApiRedact" checked style="width:15px;height:15px;accent-color:var(--accent)">
|
||||
|
||||
@@ -5961,6 +5961,8 @@ function _preferencesPayloadFromUi(){
|
||||
if(fadeTextCb) payload.fade_text_effect=fadeTextCb.checked;
|
||||
const simplifiedToolCb=$('settingsSimplifiedToolCalling');
|
||||
if(simplifiedToolCb) payload.simplified_tool_calling=simplifiedToolCb.checked;
|
||||
const terminalAutoExpandCb=$('settingsTerminalAutoExpand');
|
||||
if(terminalAutoExpandCb) payload.terminal_auto_expand_on_output=terminalAutoExpandCb.checked;
|
||||
const apiRedactCb=$('settingsApiRedact');
|
||||
if(apiRedactCb) payload.api_redact_enabled=apiRedactCb.checked;
|
||||
const showCliCb=$('settingsShowCliSessions');
|
||||
@@ -6035,6 +6037,9 @@ async function _autosavePreferencesSettings(payload){
|
||||
if(typeof clearMessageRenderCache==='function') clearMessageRenderCache();
|
||||
if(typeof renderMessages==='function') renderMessages();
|
||||
}
|
||||
if(payload&&payload.terminal_auto_expand_on_output!==undefined){
|
||||
window._terminalAutoExpandOnOutput=!!(saved&&saved.terminal_auto_expand_on_output);
|
||||
}
|
||||
if(payload&&Object.prototype.hasOwnProperty.call(payload,'fade_text_effect')) window._fadeTextEffect=!!payload.fade_text_effect;
|
||||
if(saved&&Object.prototype.hasOwnProperty.call(saved,'pinned_sessions_limit')) window._pinnedSessionsLimit=parseInt(saved.pinned_sessions_limit,10)||3;
|
||||
if(payload&&payload.show_tps!==undefined){
|
||||
@@ -6265,6 +6270,8 @@ async function loadSettingsPanel(){
|
||||
if(fadeTextCb){fadeTextCb.checked=!!settings.fade_text_effect;window._fadeTextEffect=fadeTextCb.checked;fadeTextCb.addEventListener('change',_schedulePreferencesAutosave,{once:false});}
|
||||
const simplifiedToolCb=$('settingsSimplifiedToolCalling');
|
||||
if(simplifiedToolCb){simplifiedToolCb.checked=settings.simplified_tool_calling!==false;simplifiedToolCb.addEventListener('change',_schedulePreferencesAutosave,{once:false});}
|
||||
const terminalAutoExpandCb=$('settingsTerminalAutoExpand');
|
||||
if(terminalAutoExpandCb){terminalAutoExpandCb.checked=!!settings.terminal_auto_expand_on_output;window._terminalAutoExpandOnOutput=terminalAutoExpandCb.checked;terminalAutoExpandCb.addEventListener('change',_schedulePreferencesAutosave,{once:false});}
|
||||
const apiRedactCb=$('settingsApiRedact');
|
||||
if(apiRedactCb){apiRedactCb.checked=settings.api_redact_enabled!==false;apiRedactCb.addEventListener('change',_schedulePreferencesAutosave,{once:false});}
|
||||
const showCliCb=$('settingsShowCliSessions');
|
||||
@@ -7322,6 +7329,7 @@ function _applySavedSettingsUi(saved, body, opts){
|
||||
window._whatsNewSummaryEnabled=!!body.whats_new_summary_enabled;
|
||||
window._showThinking=body.show_thinking!==false;
|
||||
window._simplifiedToolCalling=body.simplified_tool_calling!==false;
|
||||
window._terminalAutoExpandOnOutput=!!body.terminal_auto_expand_on_output;
|
||||
window._sessionJumpButtonsEnabled=!!body.session_jump_buttons;
|
||||
if(typeof _applySessionNavigationPrefs==='function') _applySessionNavigationPrefs();
|
||||
window._sidebarDensity=sidebarDensity==='detailed'?'detailed':'compact';
|
||||
@@ -7662,6 +7670,7 @@ async function saveSettings(andClose){
|
||||
body.show_tps=showTps;
|
||||
body.fade_text_effect=fadeTextEffect;
|
||||
body.simplified_tool_calling=!!($('settingsSimplifiedToolCalling')||{}).checked;
|
||||
body.terminal_auto_expand_on_output=!!($('settingsTerminalAutoExpand')||{}).checked;
|
||||
body.api_redact_enabled=!!($('settingsApiRedact')||{}).checked;
|
||||
body.show_cli_sessions=showCliSessions;
|
||||
body.show_previous_messaging_sessions=showPreviousMessagingSessions;
|
||||
|
||||
@@ -383,6 +383,7 @@ function _connectTerminalOutput(){
|
||||
try{text=(JSON.parse(ev.data)||{}).text||'';}
|
||||
catch(_){text=ev.data||'';}
|
||||
if(TERMINAL_UI.term&&text)TERMINAL_UI.term.write(text);
|
||||
if(text&&window._terminalAutoExpandOnOutput&&TERMINAL_UI.open&&TERMINAL_UI.collapsed)expandComposerTerminal({focus:false});
|
||||
});
|
||||
source.addEventListener('terminal_closed',()=>{
|
||||
if(TERMINAL_UI.source!==source)return;
|
||||
@@ -476,8 +477,9 @@ function collapseComposerTerminal(){
|
||||
syncTerminalButton();
|
||||
}
|
||||
|
||||
function expandComposerTerminal(){
|
||||
function expandComposerTerminal(opts){
|
||||
if(!TERMINAL_UI.open)return;
|
||||
const focus = !opts || opts.focus !== false;
|
||||
const {panel}= _terminalEls();
|
||||
const messages=_terminalMessagesEl();
|
||||
TERMINAL_UI.collapsed=false;
|
||||
@@ -490,7 +492,7 @@ function expandComposerTerminal(){
|
||||
_resetTerminalHeightForViewport();
|
||||
requestAnimationFrame(()=>{
|
||||
_fitTerminal();
|
||||
focusComposerTerminalInput();
|
||||
if(focus) focusComposerTerminalInput();
|
||||
setTimeout(()=>{
|
||||
if(panel)panel.classList.remove('is-expanding-from-dock');
|
||||
if(messages)messages.classList.remove('terminal-expanding-from-dock');
|
||||
|
||||
29
tests/test_terminal_auto_expand_setting.py
Normal file
29
tests/test_terminal_auto_expand_setting.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""Regression tests for the terminal auto-expand-on-output setting."""
|
||||
|
||||
import json
|
||||
|
||||
|
||||
def test_terminal_auto_expand_on_output_defaults_disabled_and_round_trips(monkeypatch, tmp_path):
|
||||
import api.config as config
|
||||
|
||||
settings_path = tmp_path / "settings.json"
|
||||
monkeypatch.setattr(config, "SETTINGS_FILE", settings_path)
|
||||
|
||||
loaded = config.load_settings()
|
||||
assert loaded["terminal_auto_expand_on_output"] is False
|
||||
|
||||
saved = config.save_settings({"terminal_auto_expand_on_output": False})
|
||||
assert saved["terminal_auto_expand_on_output"] is False
|
||||
assert json.loads(settings_path.read_text(encoding="utf-8"))["terminal_auto_expand_on_output"] is False
|
||||
|
||||
saved = config.save_settings({"terminal_auto_expand_on_output": True})
|
||||
assert saved["terminal_auto_expand_on_output"] is True
|
||||
assert json.loads(settings_path.read_text(encoding="utf-8"))["terminal_auto_expand_on_output"] is True
|
||||
|
||||
|
||||
def test_terminal_auto_expand_on_output_is_a_valid_boolean_setting():
|
||||
import api.config as config
|
||||
|
||||
assert "terminal_auto_expand_on_output" in config._SETTINGS_DEFAULTS
|
||||
assert "terminal_auto_expand_on_output" in config._SETTINGS_BOOL_KEYS
|
||||
assert "terminal_auto_expand_on_output" in config._SETTINGS_ALLOWED_KEYS
|
||||
Reference in New Issue
Block a user