From b677228a9609f6509cbbb4f662f07c062536a1f6 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 12 Mar 2026 21:38:19 -0400 Subject: [PATCH] get prior session history properly working. --- src/app_controller.py | 111 +++++++++++++++++++++++++++++++++++++++++- src/gui_2.py | 22 ++++----- 2 files changed, 118 insertions(+), 15 deletions(-) diff --git a/src/app_controller.py b/src/app_controller.py index bac6b1b..9a48ccf 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -286,7 +286,9 @@ class AppController: self._gemini_cache_text: str = "" self._last_stable_md: str = '' self._token_stats: Dict[str, Any] = {} - self._token_stats_dirty: bool = False + self._comms_log_dirty: bool = True + self._tool_log_dirty: bool = True + self._token_stats_dirty: bool = True self.ui_disc_truncate_pairs: int = 2 self.ui_auto_scroll_comms: bool = True self.ui_auto_scroll_tool_calls: bool = True @@ -294,10 +296,14 @@ class AppController: self._track_discussion_active: bool = False self._tier_stream_last_len: Dict[str, int] = {} self.is_viewing_prior_session: bool = False + self._current_session_usage = None + self._current_mma_tier_usage = None self.prior_session_entries: List[Dict[str, Any]] = [] self.prior_tool_calls: List[Dict[str, Any]] = [] self.prior_disc_entries: List[Dict[str, Any]] = [] - self.prior_mma_dashboard_state: Dict[str, Any] = {} + self.prior_mma_dashboard_state = {} + self._current_token_history = None + self._current_session_start_time = None self.test_hooks_enabled: bool = ("--enable-test-hooks" in sys.argv) or (os.environ.get("SLOP_TEST_HOOKS") == "1") self.ui_manual_approve: bool = False # Injection state @@ -531,6 +537,11 @@ class AppController: "payload": status }) + def _trigger_gui_refresh(self): + with self._pending_gui_tasks_lock: + self._pending_gui_tasks.append({'action': 'set_comms_dirty'}) + self._pending_gui_tasks.append({'action': 'set_tool_log_dirty'}) + def _process_pending_gui_tasks(self) -> None: # Periodic telemetry broadcast now = time.time() @@ -557,6 +568,10 @@ class AppController: # ... if action == "refresh_api_metrics": self._refresh_api_metrics(task.get("payload", {}), md_content=self.last_md or None) + elif action == 'set_comms_dirty': + self._comms_log_dirty = True + elif action == 'set_tool_log_dirty': + self._tool_log_dirty = True elif action == "set_ai_status": self.ai_status = task.get("payload", "") sys.stderr.write(f"[DEBUG] Updated ai_status via task to: {self.ai_status}\n") @@ -986,6 +1001,12 @@ class AppController: if not path: return + if not self.is_viewing_prior_session: + self._current_session_usage = copy.deepcopy(self.session_usage) + self._current_mma_tier_usage = copy.deepcopy(self.mma_tier_usage) + self._current_token_history = copy.deepcopy(self._token_history) + self._current_session_start_time = self._session_start_time + log_path = Path(path) if log_path.is_dir(): log_file = log_path / "comms.log" @@ -1020,6 +1041,15 @@ class AppController: entries = [] disc_entries = [] + paired_tools = {} + final_tool_calls = [] + new_token_history = [] + new_usage = {'input_tokens': 0, 'output_tokens': 0, 'cache_read_input_tokens': 0, 'cache_creation_input_tokens': 0, 'total_tokens': 0, 'last_latency': 0.0, 'percentage': 0.0} + new_mma_usage = copy.deepcopy(self.mma_tier_usage) + for t in new_mma_usage: + new_mma_usage[t]['input'] = 0 + new_mma_usage[t]['output'] = 0 + try: with open(log_file, "r", encoding="utf-8") as f: for line in f: @@ -1031,6 +1061,47 @@ class AppController: kind = entry.get("kind", entry.get("type", "")) payload = entry.get("payload", {}) ts = entry.get("ts", "") + + if kind == 'tool_call': + tid = payload.get('id') or payload.get('call_id') + script = payload.get('script') or json.dumps(payload.get('args', {}), indent=1) + script = _resolve_log_ref(script, session_dir) + entry_obj = { + 'source_tier': entry.get('source_tier', 'main'), + 'script': script, + 'result': '', # Waiting for result + 'ts': ts + } + if tid: + paired_tools[tid] = entry_obj + final_tool_calls.append(entry_obj) + elif kind == 'tool_result': + tid = payload.get('id') or payload.get('call_id') + output = payload.get('output', payload.get('content', '')) + output = _resolve_log_ref(output, session_dir) + if tid and tid in paired_tools: + paired_tools[tid]['result'] = output + else: + # Fallback: if no ID, try matching last entry in final_tool_calls that has no result + for old_call in reversed(final_tool_calls): + if not old_call['result']: + old_call['result'] = output + break + + if kind == 'response' and 'usage' in payload: + u = payload['usage'] + for k in ['input_tokens', 'output_tokens', 'cache_read_input_tokens', 'cache_creation_input_tokens', 'total_tokens']: + if k in new_usage: new_usage[k] += u.get(k, 0) or 0 + tier = entry.get('source_tier', 'main') + if tier in new_mma_usage: + new_mma_usage[tier]['input'] += u.get('input_tokens', 0) or 0 + new_mma_usage[tier]['output'] += u.get('output_tokens', 0) or 0 + new_token_history.append({ + 'time': ts, + 'input': u.get('input_tokens', 0) or 0, + 'output': u.get('output_tokens', 0) or 0, + 'model': entry.get('model', 'unknown') + }) if kind == "history_add": content = payload.get("content", payload.get("text", payload.get("message", ""))) @@ -1088,11 +1159,47 @@ class AppController: self._set_status(f"log load error: {e}") return + self.session_usage = new_usage + self.mma_tier_usage = new_mma_usage + self._token_history = new_token_history + if new_token_history: + try: + import datetime + first_ts = new_token_history[0]['time'] + dt = datetime.datetime.strptime(first_ts, '%Y-%m-%dT%H:%M:%S') + self._session_start_time = dt.timestamp() + except: + self._session_start_time = time.time() self.prior_session_entries = entries self.prior_disc_entries = disc_entries + self.prior_tool_calls = final_tool_calls self.is_viewing_prior_session = True + self._trigger_gui_refresh() self._set_status(f"viewing prior session: {session_dir.name} ({len(entries)} entries)") + + def cb_exit_prior_session(self): + self.is_viewing_prior_session = False + if self._current_session_usage: + self.session_usage = self._current_session_usage + self._current_session_usage = None + if self._current_mma_tier_usage: + self.mma_tier_usage = self._current_mma_tier_usage + self._current_mma_tier_usage = None + + if self._current_token_history is not None: + self._token_history = self._current_token_history + self._current_token_history = None + if self._current_session_start_time is not None: + self._session_start_time = self._current_session_start_time + self._current_session_start_time = None + + self.prior_session_entries.clear() + self.prior_disc_entries.clear() + self.prior_tool_calls.clear() + self._trigger_gui_refresh() + self._set_status('idle') + def cb_prune_logs(self) -> None: """Manually triggers the log pruning process with aggressive thresholds.""" self._set_status("Manual prune started (Age > 0d, Size < 100KB)...") diff --git a/src/gui_2.py b/src/gui_2.py index b8e501a..5e199e1 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -190,15 +190,12 @@ class App: self._new_preset_name = "" self._show_save_preset_modal = False self._comms_log_cache: list[dict[str, Any]] = [] - self._comms_log_dirty: bool = True self._tool_log_cache: list[dict[str, Any]] = [] - self._tool_log_dirty: bool = True self._last_ui_focus_agent: Optional[str] = None self._log_registry: Optional[log_registry.LogRegistry] = None self.perf_profiling_enabled = False self.perf_show_graphs: dict[str, bool] = {} self._token_stats: dict[str, Any] = {} - self._token_stats_dirty: bool = True self.perf_history: dict[str, list] = {"frame_time": [0.0] * 100, "fps": [0.0] * 100} self._nerv_crt = theme_fx.CRTFilter() self.ui_crt_filter = True @@ -442,11 +439,14 @@ class App: self._comms_log_dirty = False if self._tool_log_dirty: - log_raw = list(self._tool_log) - if self.ui_focus_agent: - self._tool_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] + if self.is_viewing_prior_session: + self._tool_log_cache = self.prior_tool_calls else: - self._tool_log_cache = log_raw + log_raw = list(self._tool_log) + if self.ui_focus_agent: + self._tool_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] + else: + self._tool_log_cache = log_raw self._tool_log_dirty = False if self.show_windows.get("Context Hub", False): @@ -1989,9 +1989,7 @@ def hello(): imgui.text_colored(vec4(255, 200, 100), "VIEWING PRIOR SESSION") imgui.same_line() if imgui.button("Exit Prior Session"): - self.is_viewing_prior_session = False - self.prior_session_entries.clear() - self.prior_disc_entries.clear() + self.controller.cb_exit_prior_session() self._comms_log_dirty = True imgui.separator() imgui.begin_child("prior_scroll", imgui.ImVec2(0, 0), False) @@ -2726,10 +2724,8 @@ def hello(): if self.is_viewing_prior_session: imgui.same_line() if imgui.button("Exit Prior Session"): - self.is_viewing_prior_session = False - self.prior_session_entries.clear() + self.controller.cb_exit_prior_session() self._comms_log_dirty = True - self.ai_status = "idle" imgui.separator() imgui.text_colored(C_OUT, "OUT")