feat(04-02): use user context for project selection in generic commands
- Generic commands now use project from user context first - Fall back to context param or default if no user context - Add users_root parameter to Orchestrator for test isolation - Update integration tests to use tmp_users_root fixture Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,10 @@ This module provides the central command routing system that:
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Any, Dict, Optional, Tuple
|
||||
from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pathlib import Path
|
||||
|
||||
from gsd_openclaw.tmux_session import TmuxSession, TmuxSessionManager
|
||||
from gsd_openclaw.command_executor import CommandExecutor, CommandResult
|
||||
@@ -47,7 +50,8 @@ class Orchestrator:
|
||||
def __init__(
|
||||
self,
|
||||
tmux_manager: Optional[TmuxSessionManager] = None,
|
||||
formatter: Optional[FeishuResponseFormatter] = None
|
||||
formatter: Optional[FeishuResponseFormatter] = None,
|
||||
users_root: Optional["Path"] = None
|
||||
):
|
||||
"""Initialize Orchestrator.
|
||||
|
||||
@@ -56,6 +60,7 @@ class Orchestrator:
|
||||
If not provided, a new one will be created.
|
||||
formatter: Optional FeishuResponseFormatter instance.
|
||||
If not provided, a new one will be created.
|
||||
users_root: Optional custom root for user contexts (useful for testing).
|
||||
"""
|
||||
self.tmux_manager = tmux_manager or TmuxSessionManager()
|
||||
self.formatter = formatter or FeishuResponseFormatter()
|
||||
@@ -63,6 +68,7 @@ class Orchestrator:
|
||||
self.approval_handler = ApprovalHandler(self.formatter)
|
||||
self.progress_monitor = ProgressMonitor(self.formatter)
|
||||
self.user_context_managers: Dict[str, UserContextManager] = {}
|
||||
self._users_root = users_root
|
||||
|
||||
def _get_user_context_manager(self, user_id: str) -> UserContextManager:
|
||||
"""Get or create UserContextManager for a user.
|
||||
@@ -74,7 +80,7 @@ class Orchestrator:
|
||||
UserContextManager instance for the user.
|
||||
"""
|
||||
if user_id not in self.user_context_managers:
|
||||
self.user_context_managers[user_id] = UserContextManager(user_id)
|
||||
self.user_context_managers[user_id] = UserContextManager(user_id, self._users_root)
|
||||
return self.user_context_managers[user_id]
|
||||
|
||||
def _handle_new_project(self, user_id: str, project_name: str) -> Dict[str, Any]:
|
||||
@@ -249,8 +255,13 @@ class Orchestrator:
|
||||
if command == 'use':
|
||||
return self._handle_use_project(user_id, args)
|
||||
|
||||
# Get project name from context
|
||||
project_name = context.get("project", "default")
|
||||
# Generic commands - get project from user context first
|
||||
user_ctx = self._get_user_context_manager(user_id)
|
||||
project_name = user_ctx.get_current_project()
|
||||
|
||||
# Fall back to context param or default
|
||||
if not project_name:
|
||||
project_name = context.get("project", "default")
|
||||
|
||||
# Get or create session (auto-create per CONTEXT.md)
|
||||
session = self.tmux_manager.get_session(project_name)
|
||||
|
||||
@@ -345,7 +345,7 @@ class TestIntegrationFlows:
|
||||
"""Integration-style tests for complete flows."""
|
||||
|
||||
@pytest.fixture
|
||||
def orchestrator_with_real_components(self):
|
||||
def orchestrator_with_real_components(self, tmp_users_root):
|
||||
"""Create orchestrator with real components (mock only tmux)."""
|
||||
from gsd_openclaw.orchestrator import Orchestrator
|
||||
from gsd_openclaw.response_formatter import FeishuResponseFormatter
|
||||
@@ -359,7 +359,8 @@ class TestIntegrationFlows:
|
||||
|
||||
orchestrator = Orchestrator(
|
||||
tmux_manager=mock_tmux_manager,
|
||||
formatter=formatter
|
||||
formatter=formatter,
|
||||
users_root=tmp_users_root
|
||||
)
|
||||
orchestrator.approval_handler = approval_handler
|
||||
orchestrator.executor = MagicMock()
|
||||
|
||||
Reference in New Issue
Block a user