diff --git a/crates/tty7-core/src/core/config.rs b/crates/tty7-core/src/core/config.rs index 50a40989..6f4f95ee 100644 --- a/crates/tty7-core/src/core/config.rs +++ b/crates/tty7-core/src/core/config.rs @@ -277,17 +277,6 @@ pub struct Config { pub agent_commands: HashMap, #[serde(default = "default_true")] pub restore_agent_sessions: bool, - /// Keep a capped tail of each pane's output on disk, so a daemon that dies - /// without getting to hand off — a crash, a `kill -9`, a reboot — comes - /// back to panes that still show what was in them. - /// - /// Off by default, and the default is the interesting part. What the ring - /// holds is whatever the pane printed, which routinely includes secrets: - /// an echoed token, the output of `env`, an agent's transcript. In memory - /// they die with the daemon. Writing them down is the entire feature and - /// also its entire cost, so it is the user who decides to pay it. - #[serde(default)] - pub persist_scrollback: bool, /// Give each pane its own shell history instead of one file every pane /// appends to and reads back. /// @@ -556,7 +545,6 @@ impl Default for Config { command_frecency: HashMap::new(), agent_commands: HashMap::new(), restore_agent_sessions: true, - persist_scrollback: false, per_pane_history: false, } } diff --git a/crates/tty7-core/src/daemon/scrollback.rs b/crates/tty7-core/src/daemon/scrollback.rs index 3dbe114a..dff605eb 100644 --- a/crates/tty7-core/src/daemon/scrollback.rs +++ b/crates/tty7-core/src/daemon/scrollback.rs @@ -143,11 +143,6 @@ fn take<'a>(cur: &mut &'a [u8], n: usize) -> Option<&'a [u8]> { Some(head) } -/// Whether the user has asked for scrollback to outlive the daemon. -pub fn enabled() -> bool { - crate::core::config::Config::load().persist_scrollback -} - fn dir() -> Option { crate::core::config::config_path("scrollback") } diff --git a/crates/tty7-core/src/daemon/server.rs b/crates/tty7-core/src/daemon/server.rs index 97b6fd4c..40a7f919 100644 --- a/crates/tty7-core/src/daemon/server.rs +++ b/crates/tty7-core/src/daemon/server.rs @@ -182,28 +182,14 @@ fn restorable_pane_ids(registry: &Registry) -> std::collections::HashSet { /// /// Only panes whose ring has moved are written, so an idle machine does no IO /// at all, and the busy pane that most needs a fresh copy is the one that gets -/// it. Turning the setting off mid-run is honoured here too: the next tick -/// clears the directory rather than leaving terminal output on disk that the -/// user has just said they do not want stored. +/// it. fn spawn_scrollback_writer(registry: Arc) { let spawned = std::thread::Builder::new() .name("tty7-scrollback".into()) .spawn(move || { let mut marks: HashMap = HashMap::new(); - let mut storing = crate::daemon::scrollback::enabled(); loop { std::thread::sleep(crate::daemon::scrollback::SNAPSHOT_INTERVAL); - let enabled = crate::daemon::scrollback::enabled(); - if !enabled { - if storing { - log::info!("scrollback persistence turned off; dropping what was stored"); - crate::daemon::scrollback::sweep(&std::collections::HashSet::new()); - marks.clear(); - storing = false; - } - continue; - } - storing = true; for pane in registry.all() { if marks.get(&pane.id) == Some(&pane.scrollback_mark()) { continue; @@ -228,9 +214,6 @@ fn spawn_scrollback_writer(registry: Arc) { /// covers the ones we do, and makes the copy exact rather than up to /// [`SNAPSHOT_INTERVAL`](crate::daemon::scrollback::SNAPSHOT_INTERVAL) stale. fn store_scrollback_now(registry: &Registry) { - if !crate::daemon::scrollback::enabled() { - return; - } for pane in registry.all() { let (segments, _) = pane.scrollback_snapshot(); crate::daemon::scrollback::save(pane.id, &segments); @@ -246,9 +229,6 @@ fn store_scrollback_now(registry: &Registry) { fn restored_screen( request: crate::daemon::protocol::RestoreFrom, ) -> Option { - if !crate::daemon::scrollback::enabled() { - return None; - } let segments = crate::daemon::scrollback::load(request.pane_id)?; if segments.is_empty() { return None; @@ -570,25 +550,18 @@ fn run_with(registry: Arc) -> anyhow::Result<()> { spawn_orphan_sweep(registry.clone()); let restorable = restorable_pane_ids(®istry); - // Deliberately not swept here while the setting is on. Startup is the one - // moment this process knows least: it owns no panes yet, and the windows - // that know which screens are still wanted cannot say so until the - // endpoint below is listening. Answering "is anyone going to ask for - // this?" here answers it when nobody can — and the answer deletes. A tree - // that failed to parse makes it worse, because `read_machine` quarantines - // it and hands back an empty `Machine`, so one bad file would take every - // pane's screen with it. + // No scrollback sweep here, deliberately. Startup is the one moment this + // process knows least: it owns no panes yet, and the windows that know + // which screens are still wanted cannot say so until the endpoint below is + // listening. Answering "is anyone going to ask for this?" here answers it + // when nobody can — and the answer deletes. A tree that failed to parse + // makes it worse, because `read_machine` quarantines it and hands back an + // empty `Machine`, so one bad file would take every pane's screen with it. // - // The periodic sweep asks the same question a tick later, with the - // registry filled in and the tree caught up, and that is soon enough: - // nothing here is serving a request in the meantime. + // The periodic sweep asks the same question a tick later, with the registry + // filled in and the tree caught up, and that is soon enough: nothing here + // is serving a request in the meantime. // - // Off is not the same question. Then nothing on disk is worth keeping and - // deleting it promptly is the setting's whole promise, so that one still - // happens before anything else runs. - if !crate::daemon::scrollback::enabled() { - crate::daemon::scrollback::sweep(&std::collections::HashSet::new()); - } // A daemon that was killed outright never retired anything, so the files of // panes that died with it are still here. Their commands cannot be // recovered — the mark saying which were new belongs to a shell that is diff --git a/crates/tty7-server/tests/scrollback_restore.rs b/crates/tty7-server/tests/scrollback_restore.rs index 2664a477..971aa6e5 100644 --- a/crates/tty7-server/tests/scrollback_restore.rs +++ b/crates/tty7-server/tests/scrollback_restore.rs @@ -38,13 +38,11 @@ struct Instance { impl Instance { fn new() -> Instance { - let dir = tempfile::TempDir::new().unwrap(); - std::fs::write( - dir.path().join("config.json"), - r#"{"persist_scrollback": true}"#, - ) - .unwrap(); - Instance { dir } + // No config: keeping each pane's screen is what the daemon does, not + // something it is asked to do. + Instance { + dir: tempfile::TempDir::new().unwrap(), + } } fn path(&self) -> &std::path::Path { diff --git a/src/ui/app.rs b/src/ui/app.rs index 105ef9ee..4c8d9ab8 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -2539,14 +2539,6 @@ impl Tty7App { self.update_config(cx, |cfg| cfg.restore_session = on); } - /// The daemon reads this from the config file on its own — it is the one - /// holding the output — so there is nothing to tell it here. Turning it off - /// also removes what was already stored, which the daemon does on its next - /// pass rather than leaving the bytes behind. - pub(crate) fn set_persist_scrollback(&mut self, on: bool, cx: &mut Context) { - self.update_config(cx, |cfg| cfg.persist_scrollback = on); - } - /// Takes effect on the next pane: a shell is told where its history lives /// when it starts, and nothing can move it afterwards. pub(crate) fn set_per_pane_history(&mut self, on: bool, cx: &mut Context) { diff --git a/src/ui/i18n/en.rs b/src/ui/i18n/en.rs index b9751096..6914debd 100644 --- a/src/ui/i18n/en.rs +++ b/src/ui/i18n/en.rs @@ -1483,14 +1483,6 @@ pub fn translate_en(key: L10nKey) -> &'static str { adds is written back when it closes, so nothing is lost. Applies to bash and zsh \ panes that tty7 can set up; a shell started with your own arguments is left alone." } - L10nKey::SettingsPersistScrollback => "Keep pane output on disk", - L10nKey::SettingsPersistScrollbackDescription => { - "If the background service dies without warning — a crash, or a reboot — panes come \ - back showing what was on them instead of blank. The processes are gone either way; \ - this restores the picture. It writes a capped tail of every pane's output to disk, \ - including anything printed there: tokens, the output of `env`, an agent's \ - transcript. Off means that output only ever lives in memory." - } L10nKey::PanelMoreChangedFiles => { "… and {count} more changed files — run git diff to see them." } diff --git a/src/ui/i18n/ja.rs b/src/ui/i18n/ja.rs index 3ed1c505..a8b2cccb 100644 --- a/src/ui/i18n/ja.rs +++ b/src/ui/i18n/ja.rs @@ -1530,14 +1530,6 @@ pub fn translate_ja(key: L10nKey) -> Option<&'static str> { 新しいペインは空ではなく既存の履歴から始まり、追加された分はペインを閉じるときに書き戻されるので失われません。\ tty7 が設定できる bash と zsh のペインが対象で、独自の引数で起動したシェルはそのままです" } - L10nKey::SettingsPersistScrollback => "ペインの出力をディスクに残す", - L10nKey::SettingsPersistScrollbackDescription => { - "バックグラウンドサービスが引き継ぎの間もなく落ちた場合(クラッシュや再起動)、\ - ペインは空ではなく、そこにあった内容を表示して戻ります。プロセスはいずれにせよ失われ、\ - ここで戻るのは画面だけです。各ペインの出力の末尾を上限つきでディスクに書き込みます。\ - そこに表示されたもの(トークン、`env` の出力、エージェントの記録)も含みます。\ - オフなら、その出力はメモリ上にしか存在しません。" - } L10nKey::PanelMoreChangedFiles => { "… さらに変更されたファイル {count} 個 — 表示するには `git diff` を実行してください" } diff --git a/src/ui/i18n/mod.rs b/src/ui/i18n/mod.rs index 1a448775..489d29f7 100644 --- a/src/ui/i18n/mod.rs +++ b/src/ui/i18n/mod.rs @@ -1226,8 +1226,6 @@ l10n_keys! { PaneRestoredScreenBanner, AppRestartServerBodyInPlace, SettingsDaemonStaleDescInPlace, - SettingsPersistScrollback, - SettingsPersistScrollbackDescription, SettingsPerPaneHistory, SettingsPerPaneHistoryDescription, } diff --git a/src/ui/i18n/zh.rs b/src/ui/i18n/zh.rs index 1761731e..ec546971 100644 --- a/src/ui/i18n/zh.rs +++ b/src/ui/i18n/zh.rs @@ -1406,12 +1406,6 @@ pub fn translate_zh(key: L10nKey) -> Option<&'static str> { 新面板会从你已有的历史开始,而不是一片空白;面板关闭时,它新增的部分会写回原来的历史文件,不会丢。\ 只对 tty7 能接管的 bash 和 zsh 面板生效;用你自己参数启动的 shell 不受影响。" } - L10nKey::SettingsPersistScrollback => "把面板输出留在磁盘上", - L10nKey::SettingsPersistScrollbackDescription => { - "后台服务如果没来得及交接就没了(崩溃、重启机器),面板回来时会显示原先的内容,而不是一片空白。\ - 进程无论如何都救不回来,这里恢复的只是画面。它会把每个面板输出的末尾(有上限)写到磁盘上,\ - 包括那里打印过的一切:token、`env` 的输出、agent 的对话记录。关掉则这些输出只存在于内存里。" - } L10nKey::PanelMoreChangedFiles => "…还有 {count} 个变更文件——运行 git diff 查看。", L10nKey::PanelMoreChangedFiles => "…还有 {count} 个变更文件——运行 `git diff` 查看。", L10nKey::ScmFilesChanged => "{count} 个文件改动", diff --git a/src/ui/settings.rs b/src/ui/settings.rs index 1b9db4c1..704e9f3e 100644 --- a/src/ui/settings.rs +++ b/src/ui/settings.rs @@ -4743,7 +4743,6 @@ impl Tty7App { NewTabPosition::End => 1, }; let restore_session = cfg.restore_session; - let persist_scrollback = cfg.persist_scrollback; let remember_window_size = cfg.remember_window_size; let show_tray_icon = cfg.show_tray_icon; let tab_bar_idx = match cfg.tab_bar_position { @@ -4804,10 +4803,6 @@ impl Tty7App { .checked(restore_session) .on_click(cx.listener(|this, on: &bool, _w, cx| this.set_restore_session(*on, cx))) .into_any_element(); - let persist_scrollback_switch = crate::ui::theme::switch("wt-persist-scrollback", cx) - .checked(persist_scrollback) - .on_click(cx.listener(|this, on: &bool, _w, cx| this.set_persist_scrollback(*on, cx))) - .into_any_element(); let remember_window_switch = crate::ui::theme::switch("wt-remember-window", cx) .checked(remember_window_size) .on_click(cx.listener(|this, on: &bool, _w, cx| this.set_remember_window_size(*on, cx))) @@ -4901,12 +4896,6 @@ impl Tty7App { restore_switch, cx, )) - .child(self.settings_row( - t(L10nKey::SettingsPersistScrollback), - t(L10nKey::SettingsPersistScrollbackDescription), - persist_scrollback_switch, - cx, - )) .child(self.settings_row( t(L10nKey::SettingsShowTrayIcon), t(L10nKey::SettingsShowTrayIconDesc),