fix(cli): resolve persistence bug, lint issues, and import placement (#8675 / #8623)
CI / benchmark-publish (pull_request) Has been skipped
CI / push-validation (pull_request) Successful in 45s
CI / helm (pull_request) Successful in 51s
CI / lint (pull_request) Failing after 1m19s
CI / build (pull_request) Successful in 1m17s
CI / benchmark-regression (pull_request) Failing after 1m32s
CI / quality (pull_request) Successful in 1m30s
CI / typecheck (pull_request) Successful in 1m35s
CI / security (pull_request) Successful in 2m7s
CI / integration_tests (pull_request) Successful in 4m48s
CI / e2e_tests (pull_request) Successful in 4m58s
CI / unit_tests (pull_request) Failing after 6m15s
CI / coverage (pull_request) Has been skipped
CI / docker (pull_request) Has been skipped
CI / status-check (pull_request) Failing after 3s

This commit is contained in:
2026-05-09 23:08:47 +00:00
parent df234095b7
commit 8edb113632
2 changed files with 29 additions and 67 deletions
+6 -13
View File
@@ -40,6 +40,11 @@ from cleveragents.core.exceptions import (
ValidationError,
)
from cleveragents.cli.commands.project_switch import switch_project
_FORMAT_HELP = "Output format: json, yaml, plain, or rich (default: rich)"
# Create sub-app for project commands
app = typer.Typer(help="Project management commands")
file_filter_app = typer.Typer(
@@ -48,8 +53,7 @@ file_filter_app = typer.Typer(
console = _get_console()
err_console = _get_err_console()
# Reusable --format option description
_FORMAT_HELP = "Output format: json, yaml, plain, table, or rich (default: rich)"
# ---------------------------------------------------------------------------
@@ -994,17 +998,6 @@ def delete(
)
# ---------------------------------------------------------------------------
# Switch subcommand — delegates to standalone project_switch module
# ---------------------------------------------------------------------------
from cleveragents.cli.commands.project_switch import (
switch_project,
)
@app.command(name="switch")
def switch(
name: Annotated[
+23 -54
View File
@@ -12,6 +12,8 @@ Commands:
from __future__ import annotations
from pathlib import Path
from typing import Any
import typer
@@ -58,8 +60,16 @@ def switch_project(
err_console.print(f"[red]Project not found:[/red] {name}")
raise typer.Exit(1) from exc
# Persist active-project selection to user config
_persist_active_project(container, name)
# Persist active-project selection via the project's .cleveragents dir
proj_path = getattr(proj, 'path', None) or getattr(proj, 'local_path', None)
if proj_path is not None:
_persist_active_project(Path(proj_path), name)
else:
# Fallback: write to cwd project marker
try:
_persist_active_project(Path.cwd(), name)
except Exception:
pass
data = svc.project_to_dict(proj)
@@ -72,63 +82,22 @@ def switch_project(
console.print(format_output(data, output_format))
def _persist_active_project(container: Any, namespaced_name: str) -> None:
"""Persist the active project name to ``~/.cleveragents/config.toml``.
Reads an existing config (if present), updates the
``active_project`` key, and writes back. If no config file
exists yet, one is created with the default directory structure.
def _persist_active_project(project_dir: Path, namespaced_name: str) -> None:
"""Persist the project name to {project_dir}/.cleveragents/project.name.
Args:
container: The application DI container.
project_dir: The resolved path of the project directory to use as context.
namespaced_name: The project's namespaced name to persist.
"""
from pathlib import Path
# Resolve the base data directory (same location ProjectService uses)
# Write project name inside the project's .cleveragents dir
clever_dir = project_dir / ".cleveragents"
try:
settings = getattr(container, "settings", None)
if settings is not None:
base_dir = getattr(settings, "data_path", Path.home() / ".cleveragents")
else:
base_dir = Path.home() / ".cleveragents"
except Exception:
base_dir = Path.home() / ".cleveragents"
config_file = base_dir / "config.toml"
# Ensure directory exists
try:
config_file.parent.mkdir(parents=True, exist_ok=True)
except Exception:
# Silently fail on write if home dir is not writable
clever_dir.mkdir(parents=True, exist_ok=True)
except OSError:
return
# Read existing config if present (simple key-value TOML)
current_lines: list[str] = []
name_file = clever_dir / "project.name"
try:
if config_file.exists():
raw_config = config_file.read_text()
current_lines = raw_config.strip().splitlines(keepends=True) if raw_config.strip() else []
except Exception:
pass
# Update or append active_project key
_found_active = False
new_lines: list[str] = []
for line in current_lines:
stripped = line.strip()
if stripped.startswith("active_project"):
new_lines.append(f'active_project = "{namespaced_name}"\n')
_found_active = True
else:
new_lines.append(line)
if not _found_active:
new_lines.append("\n" + f'active_project = "{namespaced_name}"\n')
try:
config_file.write_text("".join(new_lines), encoding="utf-8")
except Exception:
# Silently fail on write if not writable
pass
name_file.write_text(namespaced_name, encoding="utf-8")
except OSError:
pass # Silently fail on write