refactor: reorganize into monorepo with separate subprojects
Structure webber into three independent subprojects: - webber-api/: FastAPI backend server with all agent code - webber-cli/: Standalone CLI client (renamed from cli/ to webber_cli/) - webber-sandbox/: Test project for functional testing Key changes: - Each subproject has its own .venv (Python 3.12+) - Added sandbox.sh for managing test project templates - Created sandbox-templates/ with calculator-cli and empty starter - Updated CI/CD for prefixed tags (api/v*, cli/v*) - Added comprehensive AGENTS.md with operational instructions - Added gitignore filtering to glob and grep tools - Created pyproject.toml for each subproject Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
"""
|
||||
Explore command - one-shot codebase exploration.
|
||||
"""
|
||||
import asyncio
|
||||
from pathlib import Path
|
||||
|
||||
import typer
|
||||
from rich.panel import Panel
|
||||
|
||||
from src.cli.theme import get_theme
|
||||
from src.cli.ui.console import get_console
|
||||
from src.cli.ui.display import format_response
|
||||
from src.shared.logging import setup_logging
|
||||
|
||||
console = get_console()
|
||||
|
||||
|
||||
def explore_command(
|
||||
query: str = typer.Argument(..., help="What to search for in the codebase"),
|
||||
directory: str = typer.Option(
|
||||
".",
|
||||
"--directory",
|
||||
"-d",
|
||||
help="Working directory to explore",
|
||||
),
|
||||
verbose: bool = typer.Option(
|
||||
False,
|
||||
"--verbose",
|
||||
"-V",
|
||||
help="Show detailed output",
|
||||
),
|
||||
) -> None:
|
||||
"""
|
||||
One-shot codebase exploration.
|
||||
|
||||
Searches the codebase for the given query and returns findings.
|
||||
|
||||
Examples:
|
||||
webber explore "where is config loaded"
|
||||
webber explore "find all API endpoints" -d ./src
|
||||
webber explore "how does authentication work"
|
||||
"""
|
||||
# Set up logging based on verbosity
|
||||
log_level = "DEBUG" if verbose else "WARNING"
|
||||
setup_logging(log_level)
|
||||
|
||||
# Resolve directory
|
||||
working_dir = str(Path(directory).resolve())
|
||||
|
||||
if not Path(working_dir).exists():
|
||||
console.print(f"[error]Error:[/] Directory not found: {working_dir}")
|
||||
raise typer.Exit(1)
|
||||
|
||||
console.print(f"[dim]Exploring:[/] [path]{working_dir}[/]")
|
||||
console.print(f"[dim]Query:[/] {query}\n")
|
||||
|
||||
# Run the exploration
|
||||
asyncio.run(_explore_async(query, working_dir, verbose))
|
||||
|
||||
|
||||
async def _explore_async(query: str, working_dir: str, verbose: bool) -> None:
|
||||
"""Async exploration implementation."""
|
||||
from src.domains.agents.explore import explore
|
||||
|
||||
theme = get_theme()
|
||||
|
||||
try:
|
||||
with console.status("[info]Searching codebase...[/]", spinner=theme.spinner):
|
||||
result = await explore(query, working_dir=working_dir)
|
||||
|
||||
# Display result
|
||||
formatted = format_response(result)
|
||||
console.print(Panel(
|
||||
formatted,
|
||||
title="[success]Findings[/]",
|
||||
border_style=theme.colors.border_success,
|
||||
))
|
||||
|
||||
except Exception as e:
|
||||
console.print(f"[error]Error:[/] {e}")
|
||||
if verbose:
|
||||
console.print_exception()
|
||||
raise typer.Exit(1)
|
||||
Reference in New Issue
Block a user