diff --git a/CHANGELOG.md b/CHANGELOG.md index bd729598..db876f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ ### Added +- **Opt-in: start a new chat when switching workspace.** A new default-off setting (Settings → Preferences → "Start a new chat when switching workspace"). When enabled, selecting a *different* workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace — avoiding stale cross-workspace context carrying into the conversation. Selecting the same workspace stays an in-place refresh, and when the setting is off (the default) switching workspace changes the current conversation's workspace in place exactly as before, so nothing changes for anyone who doesn't opt in. Thanks @ruizanthony. (#5473) + - **Public read-only conversation sharing.** You can now opt in to share a single conversation via a public link (session action menu → Share). The link serves a redacted, read-only snapshot at `/share/` that anyone can view without logging in — nothing is public unless you explicitly share it, and you can revoke the link at any time (Stop sharing). The public page renders the transcript through the same sanitized markdown path as the app, is theme- and skin-aware (light/dark + all skins), and looks clean on desktop and mobile. The share payload is hardened at a dedicated always-on boundary: credentials, local workspace/worktree/home paths, system/tool messages, and any non-text structured content are stripped regardless of your API-redaction setting; only the conversation title and user/assistant text reach the public snapshot. Share tokens are 144-bit CSPRNG; create/revoke stay authenticated + CSRF-protected. Thanks @MicoRobot. (#5337) - **Per-event timestamps in the Transparent Stream worklog.** In Transparent Stream activity mode, each worklog event row (thinking / tool call) now shows a small right-aligned time label, so you can see when each step of a long agent run happened — useful for telling whether a run is progressing or stuck. The timestamp resolves from whatever timing the event carries (falling back to the observed live time only for a genuinely live event, never fabricating a time for a recovered/replayed old session), persists correctly when the turn settles, and carries a full date+time tooltip on hover so a session reviewed days later isn't date-ambiguous. The label is hidden on narrow (<420px) viewports so it never squeezes the command preview, and Compact Worklog / Final answer only modes are unaffected. Thanks @rodboev. (#5739, #5700) diff --git a/api/config.py b/api/config.py index f7b6d30e..d8d60235 100644 --- a/api/config.py +++ b/api/config.py @@ -8409,6 +8409,7 @@ _SETTINGS_DEFAULTS = { "show_conversation_outline": False, # show opt-in desktop jump-to-question outline panel "show_busy_placeholder_hint": False, # opt-in busy composer placeholder hint "hide_empty_state_suggestions": False, # hide the default new-chat suggestion buttons + "new_chat_on_workspace_switch": False, # #5473 opt-in: switching to a DIFFERENT workspace starts a new chat (leaving the current conversation on its original workspace) instead of mutating the current session's workspace in place. Default OFF preserves the shipped in-place-switch behavior. "virtualize_transcript": False, # #4343: virtualize long (>80 msg) transcripts. EXPERIMENTAL, opt-IN (default OFF). Was opt-out/default-on in #4325 but caused scroll-up flicker on long sessions with tall tool-call rows (variable-height anchor oscillation) — flipped off for everyone in #4343; re-enabling requires an explicit opt-in (see virtualize_transcript_optin migration in load_settings). "virtualize_transcript_optin": False, # #4343 migration marker: True only once the user explicitly enables virtualize_transcript AFTER the default-off flip. A stored virtualize_transcript=True WITHOUT this marker is a stale pre-flip value and is reset to False on load (force-off-for-everyone migration). "show_tps": False, # show tokens-per-second chip in assistant message headers @@ -8729,6 +8730,7 @@ _SETTINGS_BOOL_KEYS = { "show_conversation_outline", "show_busy_placeholder_hint", "hide_empty_state_suggestions", + "new_chat_on_workspace_switch", "virtualize_transcript", "virtualize_transcript_optin", "show_tps", diff --git a/static/boot.js b/static/boot.js index a05b8306..d20bd7cb 100644 --- a/static/boot.js +++ b/static/boot.js @@ -2976,6 +2976,7 @@ window._mirrorSpeechSettingsFromServer=_mirrorSpeechSettingsFromServer; // after a reload honors the saved choice. window._defaultMessageMode=_persistDefaultMessageMode(s.default_message_mode||s.busy_input_mode); window._showBusyPlaceholderHint=!!s.show_busy_placeholder_hint; + window._newChatOnWorkspaceSwitch=!!s.new_chat_on_workspace_switch; // #5473 opt-in window._sessionEndlessScrollEnabled=!!s.session_endless_scroll; window._autoScrollFollow=s.auto_scroll_follow!==false; window._largeTextPasteAsAttachment=s.large_text_paste_as_attachment!==false; diff --git a/static/i18n.js b/static/i18n.js index 0076ad45..155c7e4a 100644 --- a/static/i18n.js +++ b/static/i18n.js @@ -324,6 +324,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Interrupt current turn', settings_default_message_mode_steer: 'Steer (mid-turn correction)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -2040,6 +2043,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Interrompi turno corrente', settings_default_message_mode_steer: 'Steer (correzione a metà turno)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -3747,6 +3753,9 @@ const LOCALES = { settings_default_message_mode_interrupt: '現在のターンを中断', settings_default_message_mode_steer: 'ステア (ターン中の修正)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -5402,6 +5411,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Прервать текущий оборот', settings_default_message_mode_steer: 'Steer (коррекция в середине хода)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -7099,6 +7111,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Interrumpir turno actual', settings_default_message_mode_steer: 'Steer (corrección a mitad de turno)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -8711,6 +8726,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Aktuellen Durchgang unterbrechen', settings_default_message_mode_steer: 'Steer (Korrektur ohne Unterbrechung)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -10388,6 +10406,9 @@ const LOCALES = { settings_default_message_mode_interrupt: '中断当前轮次', settings_default_message_mode_steer: '引导(中间修正)', settings_label_busy_placeholder_hint: '显示忙碌占位提示', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: '在会话运行且草稿为空时,显示带有当前忙碌操作的编辑器占位符。', composer_placeholder_busy_queue: 'Enter = 队列 | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = 中断 | /queue | /background | /steer', @@ -12039,6 +12060,9 @@ const LOCALES = { settings_default_message_mode_interrupt: '中斷目前回合', settings_default_message_mode_steer: 'Steer(中途修正)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -13675,6 +13699,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Interromper turno atual', settings_default_message_mode_steer: 'Steer (correção no meio do turno)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -15265,6 +15292,9 @@ const LOCALES = { settings_default_message_mode_interrupt: '현재 작업 중단', settings_default_message_mode_steer: '조정(중간 수정)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -16964,6 +16994,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Interrompre le tour en cours', settings_default_message_mode_steer: 'Steer (correction en milieu de tour)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -19873,6 +19906,9 @@ const LOCALES = { settings_desc_model: 'Používá se pro nové konverzace. Stávající konverzace si zachovají svůj vybraný model.', settings_desc_rtl: 'Převrátí zarovnání chatových zpráv a vstupního pole editoru pro jazyky jako arabština nebo hebrejština. Ovlivňuje pouze oblast chatu — postranní panel a další panely zůstávají zleva doprava.', settings_label_busy_placeholder_hint: 'Zobrazit nápovědu zaneprázdněného zástupného symbolu', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_label_fade_text_effect: 'Efekt vyblednutí textu', settings_label_language: 'Jazyk', settings_label_max_tokens: 'Maximální výstupní tokeny', @@ -20327,6 +20363,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Mevcut dönüşü kes', settings_default_message_mode_steer: 'Yönlendirme (dönüş ortası düzeltme)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -22020,6 +22059,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Przerwij bieżącą turę', settings_default_message_mode_steer: 'Korekta w trakcie tury (steer)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', @@ -23699,6 +23741,9 @@ const LOCALES = { settings_default_message_mode_interrupt: 'Ngắt lượt hiện tại', settings_default_message_mode_steer: 'Steer (điều chỉnh giữa lượt)', settings_label_busy_placeholder_hint: 'Show busy placeholder hint', + settings_label_new_chat_on_workspace_switch: 'Start a new chat when switching workspace', + settings_desc_new_chat_on_workspace_switch: 'When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace, avoiding stale cross-workspace context. When off (default), switching workspace changes the current workspace in place.', + workspace_switched_new_chat: 'Started a new chat in {0}', settings_desc_busy_placeholder_hint: 'Shows the composer placeholder with the current busy action while the session is running and the draft is empty.', composer_placeholder_busy_queue: 'Enter = queue | /interrupt | /background | /steer', composer_placeholder_busy_interrupt: 'Enter = interrupt | /queue | /background | /steer', diff --git a/static/index.html b/static/index.html index 9e80551e..dd760428 100644 --- a/static/index.html +++ b/static/index.html @@ -1357,6 +1357,13 @@
Shows the composer placeholder with the current busy action while the session is running and the draft is empty.
+
+ +
When on, selecting a different workspace starts a fresh conversation bound to that workspace and leaves your current chat on its original workspace — avoiding stale cross-workspace context. When off (default), switching workspace changes the current conversation's workspace in place.
+