diff --git a/strix/interface/checkpoint_restore.py b/strix/interface/checkpoint_restore.py index 40930bbc..5a9f1dc0 100644 --- a/strix/interface/checkpoint_restore.py +++ b/strix/interface/checkpoint_restore.py @@ -7,6 +7,7 @@ from __future__ import annotations import asyncio import threading +from datetime import UTC, datetime from typing import Any @@ -91,6 +92,15 @@ def restore_sub_agents(checkpoint_data: Any, llm_config: Any) -> list[str]: t.start() with agents_graph_actions._agents_lock: agents_graph_actions._running_agents[agent_id] = t + agents_graph_actions._agent_instances[agent_id] = agent + agents_graph_actions._agent_states[agent_id] = state + agents_graph_actions._agent_graph["nodes"][agent_id] = { + "status": "running", + "name": state.agent_name, + "task": state.task, + "parent_id": state.parent_id, + "started_at": datetime.now(UTC).isoformat(), + } restored_ids.append(agent_id) except Exception: # noqa: BLE001 diff --git a/strix/interface/cli.py b/strix/interface/cli.py index 8356713c..3950e693 100644 --- a/strix/interface/cli.py +++ b/strix/interface/cli.py @@ -11,6 +11,8 @@ from rich.panel import Panel from rich.text import Text from strix.agents.StrixAgent import StrixAgent +from strix.interface.checkpoint_restore import build_root_resume_message as _build_resume_context_message +from strix.interface.checkpoint_restore import restore_sub_agents as _restore_sub_agents from strix.llm.config import LLMConfig from strix.telemetry.tracer import Tracer, set_global_tracer @@ -97,8 +99,6 @@ def _replay_previous_output( console.print() -from strix.interface.checkpoint_restore import build_root_resume_message as _build_resume_context_message # noqa: E402 -from strix.interface.checkpoint_restore import restore_sub_agents as _restore_sub_agents # noqa: E402 async def run_cli(args: Any) -> None: # noqa: PLR0915 diff --git a/strix/interface/tui.py b/strix/interface/tui.py index 11cde76d..09b048f8 100644 --- a/strix/interface/tui.py +++ b/strix/interface/tui.py @@ -29,6 +29,8 @@ from textual.widgets import Button, Label, Static, TextArea, Tree from textual.widgets.tree import TreeNode from strix.agents.StrixAgent import StrixAgent +from strix.interface.checkpoint_restore import build_root_resume_message as _build_root_resume_message +from strix.interface.checkpoint_restore import restore_sub_agents as _restore_sub_agents_tui from strix.interface.streaming_parser import parse_streaming_content from strix.interface.tool_components.agent_message_renderer import AgentMessageRenderer from strix.interface.tool_components.registry import get_tool_renderer @@ -39,10 +41,6 @@ from strix.telemetry.tracer import Tracer, set_global_tracer logger = logging.getLogger(__name__) - - -from strix.interface.checkpoint_restore import build_root_resume_message as _build_root_resume_message # noqa: E402 -from strix.interface.checkpoint_restore import restore_sub_agents as _restore_sub_agents_tui # noqa: E402 def get_package_version() -> str: try: return pkg_version("strix-agent") diff --git a/strix/telemetry/checkpoint.py b/strix/telemetry/checkpoint.py index e621b1da..84b3ed53 100644 --- a/strix/telemetry/checkpoint.py +++ b/strix/telemetry/checkpoint.py @@ -144,7 +144,9 @@ class CheckpointManager: try: from strix.tools.agents_graph import agents_graph_actions - for sid, inst in list(agents_graph_actions._agent_instances.items()): + with agents_graph_actions._agents_lock: + snapshot = list(agents_graph_actions._agent_instances.items()) + for sid, inst in snapshot: s = getattr(inst, "state", None) if s is not None and s.parent_id is not None: sub_agent_states[sid] = ( @@ -176,19 +178,9 @@ class CheckpointManager: ) self._tmp_path.write_text(json_str, encoding="utf-8") os.rename(self._tmp_path, self.checkpoint_path) - - with open(Path.home() / "strix_checkpoint_debug.log", "a") as _dbg: - _dbg.write(f"SAVED iter={agent_state.iteration} path={self.checkpoint_path}\n") + logger.debug("[Resume] Checkpoint saved iter=%s path=%s", agent_state.iteration, self.checkpoint_path) except Exception as e: # noqa: BLE001 - try: - with open(Path.home() / "strix_checkpoint_debug.log", "a") as _dbg: - _dbg.write( - f"FAILED iter={getattr(agent_state, 'iteration', '?')} " - f"path={self.checkpoint_path} err={e}\n" - ) - except Exception: - pass logger.warning("[Resume] Checkpoint save failed (non-fatal): %s", e) def load(self) -> "CheckpointModel | None": diff --git a/strix/telemetry/tracer.py b/strix/telemetry/tracer.py index 0f5459cc..bde9750a 100644 --- a/strix/telemetry/tracer.py +++ b/strix/telemetry/tracer.py @@ -294,7 +294,7 @@ class Tracer: def get_run_dir(self) -> Path: if self._run_dir is None: - runs_dir = Path.home() / "strix_runs" + runs_dir = Path.cwd() / "strix_runs" runs_dir.mkdir(exist_ok=True) run_dir_name = self.run_name if self.run_name else self.run_id