Add plans directory support to CLI session management

- Introduced `plans_directory` parameter in `CLISessionManager`, `CLISession`, and updated related methods to handle plan files.
- Updated `api/app.py` to pass the plans directory to the CLI session manager.
- Added a new test in `test_cli.py` to verify that the `--settings plansDirectory` argument is included when starting a task with a specified plans directory.
This commit is contained in:
Alishahryar1
2026-02-16 15:34:26 -08:00
parent 6939b52bca
commit 71cc814efb
4 changed files with 49 additions and 1 deletions
+5
View File
@@ -79,11 +79,16 @@ async def lifespan(app: FastAPI):
api_url = f"http://{settings.host}:{settings.port}/v1"
allowed_dirs = [workspace] if settings.allowed_dir else []
plans_dir_abs = os.path.abspath(
os.path.join(settings.claude_workspace, "plans")
)
plans_directory = os.path.relpath(plans_dir_abs, workspace)
cli_manager = CLISessionManager(
workspace_path=workspace,
api_url=api_url,
allowed_dirs=allowed_dirs,
max_sessions=settings.max_cli_sessions,
plans_directory=plans_directory,
)
# Initialize session store
+4
View File
@@ -28,6 +28,7 @@ class CLISessionManager:
api_url: str,
allowed_dirs: Optional[List[str]] = None,
max_sessions: int = 10,
plans_directory: Optional[str] = None,
):
"""
Initialize the session manager.
@@ -37,10 +38,12 @@ class CLISessionManager:
api_url: API URL for the proxy
allowed_dirs: Directories the CLI is allowed to access
max_sessions: Maximum concurrent sessions
plans_directory: Directory for Claude Code CLI plan files (passed via --settings)
"""
self.workspace = workspace_path
self.api_url = api_url
self.allowed_dirs = allowed_dirs or []
self.plans_directory = plans_directory
self.max_sessions = max_sessions
self._sessions: Dict[str, CLISession] = {}
@@ -83,6 +86,7 @@ class CLISessionManager:
workspace_path=self.workspace,
api_url=self.api_url,
allowed_dirs=self.allowed_dirs,
plans_directory=self.plans_directory,
)
self._pending_sessions[temp_id] = new_session
logger.info(f"Created new session: {temp_id}")
+6
View File
@@ -17,10 +17,12 @@ class CLISession:
workspace_path: str,
api_url: str,
allowed_dirs: Optional[List[str]] = None,
plans_directory: Optional[str] = None,
):
self.workspace = os.path.normpath(os.path.abspath(workspace_path))
self.api_url = api_url
self.allowed_dirs = [os.path.normpath(d) for d in (allowed_dirs or [])]
self.plans_directory = plans_directory
self.process: Optional[asyncio.subprocess.Process] = None
self.current_session_id: Optional[str] = None
self._is_busy = False
@@ -94,6 +96,10 @@ class CLISession:
for d in self.allowed_dirs:
cmd.extend(["--add-dir", d])
if self.plans_directory is not None:
settings_json = json.dumps({"plansDirectory": self.plans_directory})
cmd.extend(["--settings", settings_json])
try:
self.process = await asyncio.create_subprocess_exec(
*cmd,
+34 -1
View File
@@ -1,8 +1,11 @@
"""Tests for cli/ module."""
import pytest
import asyncio
import json
import os
import pytest
from unittest.mock import AsyncMock, MagicMock, patch
from messaging.event_parser import parse_cli_event
@@ -476,6 +479,36 @@ class TestCLISession:
assert os.path.normpath("/dir1") in cmd
assert os.path.normpath("/dir2") in cmd
@pytest.mark.asyncio
async def test_start_task_plans_directory(self):
"""Test start_task includes --settings plansDirectory when plans_directory set."""
from cli.session import CLISession
session = CLISession(
"/tmp",
"http://localhost:8082/v1",
plans_directory="./agent_workspace/plans",
)
mock_process = AsyncMock()
mock_process.stdout.read.side_effect = [b""]
mock_process.stderr.read.return_value = b""
mock_process.wait.return_value = 0
with patch(
"asyncio.create_subprocess_exec", new_callable=AsyncMock
) as mock_exec:
mock_exec.return_value = mock_process
async for _ in session.start_task("test"):
pass
cmd = mock_exec.call_args[0]
assert "--settings" in cmd
settings_idx = cmd.index("--settings")
assert settings_idx + 1 < len(cmd)
settings = json.loads(cmd[settings_idx + 1])
assert settings["plansDirectory"] == "./agent_workspace/plans"
@pytest.mark.asyncio
async def test_start_task_json_error(self):
"""Test handling of non-JSON output from CLI."""