feat(workspace): set default workspace root and ensure directories in CLI agent

This commit is contained in:
X-iZhang
2026-02-15 11:46:30 +00:00
parent 7b598dd6a6
commit 3758ae1c1d
2 changed files with 47 additions and 30 deletions
+36 -30
View File
@@ -204,12 +204,15 @@ def __getattr__(name: str):
def create_cli_agent(workspace_dir: str | None = None, checkpointer=None):
"""Create agent with checkpointer for CLI multi-turn support.
A fresh backend is constructed on every call using the current
``paths.WORKSPACE_ROOT`` (or the explicit *workspace_dir*), so
runtime ``set_workspace_root()`` changes are always respected.
Args:
workspace_dir: Optional per-session workspace directory. If provided,
creates a fresh backend rooted at this path. If None, uses the
module-level default backend.
checkpointer: Optional LangGraph checkpointer. If None, falls back
to ``InMemorySaver`` (non-persistent).
workspace_dir: Per-session workspace directory. If ``None``,
defaults to the current ``paths.WORKSPACE_ROOT``.
checkpointer: Optional LangGraph checkpointer. If ``None``,
falls back to ``InMemorySaver`` (non-persistent).
"""
from . import paths as _paths
@@ -221,31 +224,34 @@ def create_cli_agent(workspace_dir: str | None = None, checkpointer=None):
_mem_dir = str(_paths.MEMORY_DIR)
_usr_skills_dir = str(_paths.USER_SKILLS_DIR)
if workspace_dir:
set_active_workspace(workspace_dir)
ws_backend = CustomSandboxBackend(
root_dir=workspace_dir,
virtual_mode=True,
timeout=300,
)
sk_backend = MergedReadOnlyBackend(
primary_dir=_usr_skills_dir,
secondary_dir=SKILLS_DIR,
)
# Memory always uses SHARED directory (not per-session) for cross-session persistence
mem_backend = FilesystemBackend(
root_dir=_mem_dir,
virtual_mode=True,
)
be = CompositeBackend(
default=ws_backend,
routes={
"/skills/": sk_backend,
"/memory/": mem_backend,
},
)
else:
be = backend
# Default to current WORKSPACE_ROOT when no explicit dir is provided
if workspace_dir is None:
workspace_dir = str(_paths.WORKSPACE_ROOT)
# Always construct fresh backends from current paths (avoids stale
# module-level backend when workspace root changed at runtime).
set_active_workspace(workspace_dir)
ws_backend = CustomSandboxBackend(
root_dir=workspace_dir,
virtual_mode=True,
timeout=300,
)
sk_backend = MergedReadOnlyBackend(
primary_dir=_usr_skills_dir,
secondary_dir=SKILLS_DIR,
)
# Memory always uses SHARED directory (not per-session) for cross-session persistence
mem_backend = FilesystemBackend(
root_dir=_mem_dir,
virtual_mode=True,
)
be = CompositeBackend(
default=ws_backend,
routes={
"/skills/": sk_backend,
"/memory/": mem_backend,
},
)
mw = [
create_memory_middleware(_mem_dir, extraction_model=chat_model),
+11
View File
@@ -50,10 +50,21 @@ def create_agent_handler(
on_todo: Optional async callback for todo list updates.
Signature: async def on_todo(sender: str, content: str, metadata: dict) -> None
"""
import os
from langchain_core.messages import HumanMessage
from ...config import get_effective_config, apply_config_to_env
from ...paths import set_workspace_root, ensure_dirs
from ...EvoScientist import create_cli_agent
from ...stream.events import stream_agent_events
# Apply config so default_workdir is respected in non-CLI entry points
config = get_effective_config()
apply_config_to_env(config)
if config.default_workdir:
workdir = os.path.abspath(os.path.expanduser(config.default_workdir))
set_workspace_root(workdir)
ensure_dirs()
agent = create_cli_agent()
sessions: dict[str, str] = {} # sender -> thread_id