bd307f3a11
* feat(gateway): graph gateway protocol * refactor(cli): wire gateway in cli/tui * refactor(gateway): centralize runtime gateway init * chore(gateway): restrict RunRequest message type * feat(gateway): add langgraph server gateway * chore(cli): tighten serve runtime state typing * refactor(cli): route async task state reads through graph gateway * refactor(gateway): support graph targets in server gateway * refactor(cli): route session commands through graph gateway * refactor(cli): fold thread store under graph gateway * refactor(gateway): route graph state access through gateway * refactor(channels): wire graph gateway * refactor(memory): preserve graph threads for cloning * feat(gateway): add thread cloning * fix(tui): pass effective workspace for thread creation * chore(memory): add workspare dir to memory worker metadata * fix(sessions): filter preloaded UUID registy entries by the current scope * test(fakes): use https * refactor(consumer): consolidate imports * fix(stream): optional summarization event * fix(gateway): resolve abbreviated thread IDs by search * fix(gateway): page server thread listings * fix(gateway): emit pending interrupt events * style: fmt * feat(gateway): persist workspace_dir & model in thread metadata * fix(gateway): page server thread prefix resolution * fix(gateway): expose server thread list metadata * refactor: add back type def * refactor: tighten types * revert: add back worker thread deletion The worker thread forking changes are out of scope for now, so to maintain parity with the existing behavior we'll leave this intact. * fix(gateway): apply compaction to server thread history * refactor(stream): restore direct summary replay suppression * fix(gateway): preserve compaction state and server stream output * fix(gateway): close local stream generator on cancellation --------- Co-authored-by: Xi Zhang <106144707+X-iZhang@users.noreply.github.com>
96 lines
2.9 KiB
Python
96 lines
2.9 KiB
Python
"""Agent loading and workspace helpers."""
|
|
|
|
import os
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from typing import TYPE_CHECKING
|
|
|
|
from ..paths import new_run_dir
|
|
|
|
if TYPE_CHECKING:
|
|
from langgraph.graph.state import CompiledStateGraph
|
|
|
|
|
|
def _shorten_path(path: str) -> str:
|
|
"""Shorten absolute path to relative path from current directory."""
|
|
if not path:
|
|
return path
|
|
try:
|
|
cwd = os.getcwd()
|
|
if path.startswith(cwd):
|
|
rel = path[len(cwd) :].lstrip(os.sep)
|
|
return (
|
|
os.path.join(os.path.basename(cwd), rel)
|
|
if rel
|
|
else os.path.basename(cwd)
|
|
)
|
|
return path
|
|
except Exception:
|
|
return path
|
|
|
|
|
|
def _deduplicate_run_name(name: str, runs_dir: Path | None = None) -> str:
|
|
"""Return *name* if available, otherwise *name_1*, *name_2*, etc."""
|
|
if runs_dir is None:
|
|
from ..paths import RUNS_DIR
|
|
|
|
runs_dir = RUNS_DIR
|
|
if not (runs_dir / name).exists():
|
|
return name
|
|
i = 1
|
|
while (runs_dir / f"{name}_{i}").exists():
|
|
i += 1
|
|
return f"{name}_{i}"
|
|
|
|
|
|
def _create_session_workspace(name: str | None = None) -> str:
|
|
"""Create a per-session workspace directory and return its path.
|
|
|
|
Args:
|
|
name: Optional human-friendly run name. Duplicates are resolved
|
|
by appending ``_1``, ``_2``, etc. Falls back to a timestamp
|
|
if *name* is None.
|
|
"""
|
|
if name:
|
|
from ..paths import RUNS_DIR
|
|
|
|
session_id = _deduplicate_run_name(name, RUNS_DIR)
|
|
else:
|
|
session_id = datetime.now().strftime("%Y%m%d_%H%M%S")
|
|
workspace_dir = str(new_run_dir(session_id))
|
|
os.makedirs(workspace_dir, exist_ok=True)
|
|
return workspace_dir
|
|
|
|
|
|
def _load_agent(
|
|
workspace_dir: str | None = None,
|
|
checkpointer=None,
|
|
config=None,
|
|
chat_model=None,
|
|
*,
|
|
on_mcp_progress=None,
|
|
) -> "CompiledStateGraph":
|
|
"""Load the CLI agent with optional persistent checkpointer.
|
|
|
|
Args:
|
|
workspace_dir: Optional per-session workspace directory.
|
|
checkpointer: Optional LangGraph checkpointer (e.g. ``AsyncSqliteSaver``).
|
|
Falls back to ``InMemorySaver`` when ``None``.
|
|
config: Optional pre-loaded ``EvoScientistConfig``. Forwarded to
|
|
``create_cli_agent`` to avoid double config loading.
|
|
chat_model: Optional pre-built chat model. Forwarded to
|
|
``create_cli_agent``; combined with an explicit ``config`` it
|
|
selects the pure (no module-global write) build path.
|
|
on_mcp_progress: Optional per-server MCP progress callback.
|
|
Signature ``(event, server_name, detail) -> None``.
|
|
"""
|
|
from ..EvoScientist import create_cli_agent
|
|
|
|
return create_cli_agent(
|
|
workspace_dir=workspace_dir,
|
|
checkpointer=checkpointer,
|
|
config=config,
|
|
chat_model=chat_model,
|
|
on_mcp_progress=on_mcp_progress,
|
|
)
|