Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions src/deepwork/cli/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,10 @@ def _install_deepwork(platform_name: str | None, project_path: Path) -> None:
)
console.print(" [green]✓[/green] Git repository found")

# Step 2: Detect or validate platform
# Step 2: Detect or validate platform(s)
detector = PlatformDetector(project_path)
platforms_to_add: list[str] = []
detected_adapters: list[AgentAdapter] = []

if platform_name:
# User specified platform - check if it's available
Expand All @@ -234,10 +236,11 @@ def _install_deepwork(platform_name: str | None, project_path: Path) -> None:
)

console.print(f" [green]✓[/green] {adapter.display_name} detected")
platform_to_add = adapter.name
platforms_to_add = [adapter.name]
detected_adapters = [adapter]
else:
# Auto-detect platform
console.print("[yellow]→[/yellow] Auto-detecting AI platform...")
# Auto-detect all available platforms
console.print("[yellow]→[/yellow] Auto-detecting AI platforms...")
available_adapters = detector.detect_all_platforms()

if not available_adapters:
Expand All @@ -251,17 +254,11 @@ def _install_deepwork(platform_name: str | None, project_path: Path) -> None:
"Please set up one of these platforms first, or use --platform to specify."
)

if len(available_adapters) > 1:
# Multiple platforms - ask user to specify
platform_names = ", ".join(a.display_name for a in available_adapters)
raise InstallError(
f"Multiple AI platforms detected: {platform_names}\n"
"Please specify which platform to use with --platform option."
)

adapter = available_adapters[0]
console.print(f" [green]✓[/green] {adapter.display_name} detected")
platform_to_add = adapter.name
# Add all detected platforms
for adapter in available_adapters:
console.print(f" [green]✓[/green] {adapter.display_name} detected")
platforms_to_add.append(adapter.name)
detected_adapters = available_adapters

# Step 3: Create .deepwork/ directory structure
console.print("[yellow]→[/yellow] Creating DeepWork directory structure...")
Expand Down Expand Up @@ -304,12 +301,16 @@ def _install_deepwork(platform_name: str | None, project_path: Path) -> None:
if "platforms" not in config_data:
config_data["platforms"] = []

# Add platform if not already present
if platform_to_add not in config_data["platforms"]:
config_data["platforms"].append(platform_to_add)
console.print(f" [green]✓[/green] Added {adapter.display_name} to platforms")
else:
console.print(f" [dim]•[/dim] {adapter.display_name} already configured")
# Add each platform if not already present
added_platforms: list[str] = []
for i, platform in enumerate(platforms_to_add):
adapter = detected_adapters[i]
if platform not in config_data["platforms"]:
config_data["platforms"].append(platform)
added_platforms.append(adapter.display_name)
console.print(f" [green]✓[/green] Added {adapter.display_name} to platforms")
else:
console.print(f" [dim]•[/dim] {adapter.display_name} already configured")

save_yaml(config_file, config_data)
console.print(f" [green]✓[/green] Updated {config_file.relative_to(project_path)}")
Expand All @@ -328,8 +329,9 @@ def _install_deepwork(platform_name: str | None, project_path: Path) -> None:

# Success message
console.print()
platform_names = ", ".join(a.display_name for a in detected_adapters)
console.print(
f"[bold green]✓ DeepWork installed successfully for {adapter.display_name}![/bold green]"
f"[bold green]✓ DeepWork installed successfully for {platform_names}![/bold green]"
)
console.print()
console.print("[bold]Next steps:[/bold]")
Expand Down
20 changes: 20 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ def mock_claude_project(mock_git_repo: Path) -> Path:
return mock_git_repo


@pytest.fixture
def mock_gemini_project(mock_git_repo: Path) -> Path:
"""Create a mock project with Gemini CLI setup."""
gemini_dir = mock_git_repo / ".gemini"
gemini_dir.mkdir(exist_ok=True)
return mock_git_repo


@pytest.fixture
def mock_multi_platform_project(mock_git_repo: Path) -> Path:
"""Create a mock project with multiple AI platforms setup."""
claude_dir = mock_git_repo / ".claude"
claude_dir.mkdir(exist_ok=True)
(claude_dir / "settings.json").write_text('{"version": "1.0"}')

gemini_dir = mock_git_repo / ".gemini"
gemini_dir.mkdir(exist_ok=True)
return mock_git_repo


@pytest.fixture
def fixtures_dir() -> Path:
"""Return the path to the fixtures directory."""
Expand Down
34 changes: 32 additions & 2 deletions tests/integration/test_install_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,38 @@ def test_install_fails_without_platform(self, mock_git_repo: Path) -> None:
assert result.exit_code != 0
assert "No AI platform detected" in result.output

# NOTE: Multiple platform detection test removed since we currently only support Claude.
# When more adapters are added, this test should be reinstated.
def test_install_with_multiple_platforms_auto_detect(
self, mock_multi_platform_project: Path
) -> None:
"""Test installing with auto-detection when multiple platforms are present."""
runner = CliRunner()

result = runner.invoke(
cli,
["install", "--path", str(mock_multi_platform_project)],
catch_exceptions=False,
)

assert result.exit_code == 0
assert "Auto-detecting AI platforms" in result.output
assert "Claude Code detected" in result.output
assert "Gemini CLI detected" in result.output
assert "DeepWork installed successfully for Claude Code, Gemini CLI" in result.output

# Verify config.yml has both platforms
config_file = mock_multi_platform_project / ".deepwork" / "config.yml"
config = load_yaml(config_file)
assert config is not None
assert "claude" in config["platforms"]
assert "gemini" in config["platforms"]

# Verify commands were created for both platforms
claude_dir = mock_multi_platform_project / ".claude" / "commands"
assert (claude_dir / "deepwork_jobs.define.md").exists()

# Gemini uses job_name/step_id.toml structure
gemini_dir = mock_multi_platform_project / ".gemini" / "commands"
assert (gemini_dir / "deepwork_jobs" / "define.toml").exists()

def test_install_with_specified_platform_when_missing(self, mock_git_repo: Path) -> None:
"""Test that install fails when specified platform is not present."""
Expand Down