From 4369eb517a77a21417f8e7825764b5db42193fb6 Mon Sep 17 00:00:00 2001 From: aihyo <1391830376@qq.com> Date: Mon, 1 Jun 2026 17:59:59 +0800 Subject: [PATCH] fix(tui): preserve current log when continuing sessions --- frontends/continue_cmd.py | 37 ++++++++++++++++++++++++++++--------- frontends/tuiapp_v2.py | 5 +++-- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/frontends/continue_cmd.py b/frontends/continue_cmd.py index 260a8c349..f3e29cb88 100644 --- a/frontends/continue_cmd.py +++ b/frontends/continue_cmd.py @@ -271,12 +271,21 @@ def _rounds_for_file(path, st): return n, key -def list_sessions(exclude_pid=None): +def _normalize_path(path): + if not path: + return '' + return os.path.normcase(os.path.abspath(path)) + + +def list_sessions(exclude_pid=None, exclude_path=None): """Newest-first list of (path, mtime, preview_text, n_rounds). Preview uses head/tail window only.""" files = glob.glob(_LOG_GLOB) if exclude_pid is not None: tag = f'model_responses_{exclude_pid}.txt' files = [f for f in files if not f.endswith(tag)] + exclude_key = _normalize_path(exclude_path) + if exclude_key: + files = [f for f in files if _normalize_path(f) != exclude_key] out = [] valid_keys = [] for f in files: @@ -322,9 +331,17 @@ def _current_log_path(pid=None): return os.path.join(_LOG_DIR, f'model_responses_{pid}.txt') -def _snapshot_current_log(pid=None): - """Persist current PID log as a standalone recoverable snapshot, then clear it.""" - path = _current_log_path(pid) +def _log_path_for_agent(agent=None, pid=None): + if agent is not None: + path = getattr(agent, 'log_path', '') or getattr(getattr(agent, 'llmclient', None), 'log_path', '') + if path: + return path + return _current_log_path(pid) + + +def _snapshot_current_log(agent=None, pid=None): + """Persist the agent's active log as a recoverable snapshot, then clear it.""" + path = _log_path_for_agent(agent, pid) if not os.path.isfile(path): return None try: @@ -351,7 +368,7 @@ def reset_conversation(agent, message='🆕 已开启新对话,当前上下文 agent.abort() except Exception: pass - _snapshot_current_log() + _snapshot_current_log(agent) if hasattr(agent, 'history'): agent.history = [] for client in _agent_clients(agent): @@ -397,12 +414,13 @@ def restore(agent, path): def handle(agent, query, display_queue): """Dispatch /continue or /continue N. Returns None if consumed else original query.""" s = (query or '').strip() + exclude_path = _log_path_for_agent(agent) if s == '/continue': - display_queue.put({'done': format_list(list_sessions(exclude_pid=os.getpid())), 'source': 'system'}) + display_queue.put({'done': format_list(list_sessions(exclude_pid=os.getpid(), exclude_path=exclude_path)), 'source': 'system'}) return None m = re.match(r'/continue\s+(\d+)\s*$', s) if m: - sessions = list_sessions(exclude_pid=os.getpid()) + sessions = list_sessions(exclude_pid=os.getpid(), exclude_path=exclude_path) idx = int(m.group(1)) - 1 if not (0 <= idx < len(sessions)): display_queue.put({'done': f'❌ 索引越界(有效范围 1-{len(sessions)})', 'source': 'system'}) @@ -557,12 +575,13 @@ def handle_frontend_command(agent, query, exclude_pid=None): """Frontend-friendly /continue entry that returns text directly.""" s = (query or '').strip() exclude_pid = os.getpid() if exclude_pid is None else exclude_pid + exclude_path = _log_path_for_agent(agent, exclude_pid) if s == '/continue': - return format_list(list_sessions(exclude_pid=exclude_pid)) + return format_list(list_sessions(exclude_pid=exclude_pid, exclude_path=exclude_path)) m = re.match(r'/continue\s+(\d+)\s*$', s) if not m: return '用法: /continue 或 /continue N' - sessions = list_sessions(exclude_pid=exclude_pid) + sessions = list_sessions(exclude_pid=exclude_pid, exclude_path=exclude_path) idx = int(m.group(1)) - 1 if not (0 <= idx < len(sessions)): return f'❌ 索引越界(有效范围 1-{len(sessions)})' diff --git a/frontends/tuiapp_v2.py b/frontends/tuiapp_v2.py index aca93bd1f..ebfcc80b9 100644 --- a/frontends/tuiapp_v2.py +++ b/frontends/tuiapp_v2.py @@ -3991,10 +3991,11 @@ def _cmd_review(self, args, raw): def _cmd_continue(self, args, raw): sess = self.current m = re.match(r"/continue\s+(\S.*?)\s*$", (raw or "").strip()) + log_path = getattr(sess.agent, "log_path", "") or "" if m: token = m.group(1) if token.isdigit(): - sessions = continue_list(exclude_pid=os.getpid()) + sessions = continue_list(exclude_pid=os.getpid(), exclude_path=log_path) idx = int(token) - 1 if not (0 <= idx < len(sessions)): self._system(f"❌ 索引越界(有效范围 1-{len(sessions)})"); return @@ -4013,7 +4014,7 @@ def _cmd_continue(self, args, raw): self._system(f"❌ 找不到名为 {token!r} 的会话"); return self._do_continue_restore(path) return - sessions = continue_list(exclude_pid=os.getpid()) + sessions = continue_list(exclude_pid=os.getpid(), exclude_path=log_path) if not sessions: self._system("❌ 没有可恢复的历史会话"); return choices = []