mirror of
https://github.com/furyhawk/ai_agent.git
synced 2026-07-21 10:15:44 +00:00
- Implemented `conversation-store` for managing conversations and messages. - Created `file-preview-store` to handle file preview state. - Added `sidebar-store` for sidebar visibility management. - Developed `theme-store` for theme persistence and management. - Introduced `kb-selection-store` for managing active knowledge base selections with persistence. chore: define API and chat types - Added types for API responses, authentication, chat messages, conversations, and projects. - Defined interfaces for various entities including users, sessions, and message ratings. build: configure TypeScript and testing setup - Set up `tsconfig.json` for TypeScript configuration. - Created `vitest.config.ts` for testing configuration with Vitest. - Added `vitest.setup.ts` for global test setup including mocks for Next.js router and media queries. - Configured Vercel deployment settings in `vercel.json`.
121 lines
3.1 KiB
Python
121 lines
3.1 KiB
Python
"""
|
|
Custom commands system with auto-discovery.
|
|
|
|
This module provides a Django-like custom commands system for FastAPI + Click.
|
|
Commands are auto-discovered from this package and registered to the CLI.
|
|
|
|
Usage:
|
|
# In app/commands/my_command.py
|
|
from app.commands import command
|
|
import click
|
|
|
|
@command("my-command", help="Description of my command")
|
|
@click.option("--option", "-o", help="Some option")
|
|
def my_command(option: str):
|
|
click.echo(f"Running with {option}")
|
|
|
|
# Then use it:
|
|
# project cmd my-command --option value
|
|
"""
|
|
|
|
import importlib
|
|
import pkgutil
|
|
from collections.abc import Callable
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
import click
|
|
|
|
# Registry for custom commands
|
|
_commands: list[click.Command] = []
|
|
_discovered = False
|
|
|
|
|
|
def command(name: str | None = None, **kwargs: Any) -> Callable[..., Any]:
|
|
"""
|
|
Decorator to register a custom command.
|
|
|
|
Args:
|
|
name: Command name (defaults to function name with underscores replaced by hyphens)
|
|
**kwargs: Additional arguments passed to click.command()
|
|
|
|
Example:
|
|
@command("seed", help="Seed database with initial data")
|
|
@click.option("--count", "-c", default=10)
|
|
def seed_data(count: int):
|
|
click.echo(f"Seeding {count} records...")
|
|
"""
|
|
|
|
def decorator(func: Callable[..., Any]) -> click.Command:
|
|
cmd_name = name or func.__name__.replace("_", "-")
|
|
cmd: click.Command = click.command(cmd_name, **kwargs)(func) # type: ignore[no-untyped-call]
|
|
_commands.append(cmd)
|
|
return cmd
|
|
|
|
return decorator
|
|
|
|
|
|
def discover_commands() -> list[click.Command]:
|
|
"""
|
|
Auto-discover all commands in this package.
|
|
|
|
Imports all modules in the app.commands package (except those starting with _)
|
|
which triggers the @command decorator to register them.
|
|
|
|
Returns:
|
|
List of discovered click.Command objects
|
|
"""
|
|
global _discovered
|
|
|
|
if _discovered:
|
|
return _commands
|
|
|
|
package_dir = Path(__file__).parent
|
|
|
|
for _, module_name, _ in pkgutil.iter_modules([str(package_dir)]):
|
|
if module_name.startswith("_"):
|
|
continue
|
|
|
|
try:
|
|
importlib.import_module(f"app.commands.{module_name}")
|
|
except ImportError as e:
|
|
click.secho(
|
|
f"Warning: Failed to import command module '{module_name}': {e}", fg="yellow"
|
|
)
|
|
|
|
_discovered = True
|
|
return _commands
|
|
|
|
|
|
def register_commands(cli: click.Group) -> None:
|
|
"""
|
|
Register all discovered commands to a CLI group.
|
|
|
|
Args:
|
|
cli: The click.Group to add commands to
|
|
"""
|
|
commands = discover_commands()
|
|
|
|
for cmd in commands:
|
|
cli.add_command(cmd)
|
|
|
|
|
|
def success(message: str) -> None:
|
|
"""Print success message in green."""
|
|
click.secho(message, fg="green")
|
|
|
|
|
|
def error(message: str) -> None:
|
|
"""Print error message in red."""
|
|
click.secho(message, fg="red")
|
|
|
|
|
|
def warning(message: str) -> None:
|
|
"""Print warning message in yellow."""
|
|
click.secho(message, fg="yellow")
|
|
|
|
|
|
def info(message: str) -> None:
|
|
"""Print info message."""
|
|
click.echo(message)
|