mirror of
https://github.com/Alishahryar1/free-claude-code.git
synced 2026-07-03 14:05:26 +02:00
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:
@@ -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
|
||||
|
||||
@@ -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}")
|
||||
|
||||
@@ -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
@@ -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."""
|
||||
|
||||
Reference in New Issue
Block a user