feat(system): seedgo v2 operational, full system audit, 14/15 branches at 99%

Three days of intensive work bringing seedgo to full operational status
and driving all branches through comprehensive standards compliance.

Seedgo v2.0.0:
- 22 checkers active (up from 20), standards pack fully operational
- New introspection standard researched from Dev-Pass, FPLAN-0017 open
- Bypass system for false positives (.seedgo config)
- Standards query and audit commands fully functional

System-wide audit (FPLAN-0016):
- All 14 auditable branches at 99%+ compliance
- CLI imports standardized across all branches (console from cli.apps.modules)
- handle_command(command, args) → bool contract added to all modules
- print_help() function naming fixed for checker pattern matching
- Handler extraction: large modules split, file I/O moved to handler layer
- New handlers created across ai_mail, backup, daemon, flow, skills, spawn, seedgo

Branch-specific highlights:
- ai_mail: email.py split 840→420 lines, 4 new handlers
- flow: dplan_flow.py 688→591 lines, 4 new handlers
- seedgo: massive restructure — standards moved to handlers/aipass_standards/,
  old standards/ tree removed, bypass system added, diagnostics module
- commons: database module added, CLI imports fixed
- skills: 5 handle_commands added, help function renamed
- trigger: error reporter handler, handle_command routing
- All branches: consistent architecture, clean drone routing

Culture doc (CLAUDE.md) added — documents AIPass philosophy, identity,
memory system, and collaboration principles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
AIOSAI
2026-03-10 01:26:42 -07:00
co-authored by Claude Opus 4.6
parent 09e759a8a4
commit babedd9c64
589 changed files with 17140 additions and 24881 deletions
+9 -1
View File
@@ -2,6 +2,7 @@
**Purpose:** LLM API access layer with provider abstraction, key management, model routing, and usage tracking.
**Module:** `aipass.api`
**Last Updated:** 2026-03-08
---
@@ -20,7 +21,7 @@
---
## CLI
## Commands / Usage
```bash
drone @api get-key # Retrieve API key for provider
@@ -30,8 +31,11 @@ drone @api models # List available models from provider
drone @api track # Track API usage metrics
drone @api stats # Display API usage statistics
drone @api --help # Full help output
drone @api --version # Show version
```
Running `drone @api` with no arguments displays module introspection (discovered modules and status).
---
## Architecture
@@ -76,3 +80,7 @@ api/
### Provides To
- All modules -- LLM API access for any branch that needs model inference
- System-wide API key management and credential validation
---
*Last Updated: 2026-03-08*
+5 -10
View File
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: main.py - api Branch Orchestrator
# Date: 2025-11-08
# =================== AIPass ====================
# Name: api.py
# Description: Entry point CLI for drone @api — LLM client via OpenRouter
# Version: 1.0.0
# Category: api/entry_point
# CODE STANDARDS: Seed v1.0.0
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-08): Initial version - modular architecture
# Created: 2026-03-08
# Modified: 2026-03-08
# =============================================
"""
+13 -23
View File
@@ -1,20 +1,10 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: env.py - .env file operations
# Date: 2025-11-16
# =================== AIPass ====================
# Name: env.py
# Description: .env file operations
# Version: 0.2.0
# Category: api/handlers
#
# CHANGELOG (Max 5 entries):
# - v0.2.0 (2025-11-16): Extracted from api_connect.py - complete implementation
# - v0.1.0 (2025-11-15): Initial handler stub
#
# CODE STANDARDS:
# - Handler layer (standalone functions)
# - Uses CLI service for output
# - Under 300 lines
# ==============================================
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
.env File Handler
@@ -36,8 +26,8 @@ import sys
# Standard library
from typing import Optional, Dict, List
# CLI services
from aipass.cli.apps.modules import console
# Logging
from aipass.prax import logger
# ==============================================
@@ -172,7 +162,7 @@ def create_env_template(provider: str = "openrouter", target_path: Optional[Path
# Don't overwrite existing file
if env_path.exists():
# .env file already exists
console.print(f"[yellow]ℹ[/yellow] .env file already exists at {env_path}")
logger.info(f".env file already exists at {env_path}")
return True
# Template content based on provider
@@ -208,12 +198,12 @@ OPENAI_API_KEY=sk-your-openai-key-here
f.write(env_template)
# Created .env template
console.print(f"[green]✓[/green] Created .env template at {env_path}")
logger.info(f"Created .env template at {env_path}")
return True
except Exception as e:
# Failed to create .env template
console.print(f"[red]✗[/red] Failed to create .env template: {e}")
logger.error(f"Failed to create .env template: {e}")
return False
@@ -267,12 +257,12 @@ def create_custom_env_template(variables: Dict[str, str], target_path: Path,
f.write(content)
# Created custom .env template
console.print(f"[green]✓[/green] Created custom .env template at {target_path}")
logger.info(f"Created custom .env template at {target_path}")
return True
except Exception as e:
# Failed to create custom .env template
console.print(f"[red]✗[/red] Failed to create custom .env template: {e}")
logger.error(f"Failed to create custom .env template: {e}")
return False
+6 -17
View File
@@ -1,21 +1,10 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: keys.py - API Key Management Handler
# Date: 2025-11-16
# =================== AIPass ====================
# Name: keys.py
# Description: API Key Management Handler
# Version: 2.0.0
# Category: api/handlers
#
# CHANGELOG (Max 5 entries):
# - v2.0.0 (2025-11-16): Extracted from api_connect.py - complete implementation
# - v1.0.0 (2025-11-15): Initial handler stub
#
# CODE STANDARDS:
# - Handler layer (standalone functions)
# - Uses CLI service for output
# - Uses prax logger for system logs
# - Under 300 lines
# ==============================================
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
API Key Management Handler
+10 -23
View File
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: provider.py - Provider Configuration Handler
# Date: 2025-11-16
# =================== AIPass ====================
# Name: provider.py
# Description: Provider Configuration Handler
# Version: 2.0.0
# Category: api/handlers/config
#
# CHANGELOG (Max 5 entries):
# - v2.0.0 (2025-11-16): Complete extraction from api_connect.py
# - v1.0.0 (2025-11-15): Initial handler stub
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
@@ -36,16 +31,8 @@ from typing import Dict, Any, Optional
# Internal handlers
from aipass.api.apps.handlers.json.json_handler import load_json, save_json
# Console for user feedback
try:
from rich.console import Console
console = Console()
except ImportError:
# Fallback console if rich not available
class SimpleConsole:
def print(self, *args, **kwargs):
print(*args)
console = SimpleConsole()
# Logging
from aipass.prax import logger
# =============================================
# CONSTANTS
@@ -223,12 +210,12 @@ def update_provider_config(provider: str, updates: Dict[str, Any]) -> bool:
json.dump(config, f, indent=2, ensure_ascii=False)
# Updated config for provider
console.print(f"[green]✓[/green] Provider config updated: {provider}")
logger.info(f"Provider config updated: {provider}")
return True
except Exception as e:
# Failed to update provider config
console.print(f"[red]✗[/red] Failed to update provider config: {e}")
logger.error(f"Failed to update provider config: {e}")
return False
@@ -345,7 +332,7 @@ def _create_default_config() -> bool:
json.dump(default_config, f, indent=2, ensure_ascii=False)
# Created default config
console.print(f"[green]✓[/green] Created default config: {config_path}")
logger.info(f"Created default config: {config_path}")
return True
except Exception as e:
@@ -1,18 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: json_handler.py - JSON Auto-Creating Handler
# Date: 2025-11-21
# =================== AIPass ====================
# Name: json_handler.py
# Description: JSON Auto-Creating Handler
# Version: 1.1.0
# Category: api/handlers/json
#
# CHANGELOG (Max 5 entries):
# - v1.1.0 (2025-11-21): Refactored to comply with error handling
# - v1.0.0 (2025-11-13): Initial JSON auto-creation system
#
# CODE STANDARDS:
# - Pure functions with proper error raising
# - No Prax imports (handler tier 3)
# Created: 2025-11-21
# Modified: 2025-11-21
# =============================================
import json
@@ -1,13 +1,9 @@
# =============================================
# META DATA HEADER
# =================== AIPass ====================
# Name: caller.py
# Date: 2025-11-16
# Description: OpenRouter Caller Detection Handler
# Version: 1.0.0
# Category: api/handlers
#
# CHANGELOG:
# - v1.0.0 (2025-11-16): Initial caller detection handler extracted from archive
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
@@ -1,15 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: client.py - OpenRouter Client Handler
# Date: 2025-11-15
# =================== AIPass ====================
# Name: client.py
# Description: OpenRouter Client Handler
# Version: 3.0.0
# Category: api/handlers/openrouter
#
# CHANGELOG (Max 5 entries):
# - v3.0.0 (2026-02-20): Fallback model chain in get_response() + retry logic in make_api_request()
# - v2.0.0 (2025-11-16): Complete extraction from archive - client creation, API requests, response handling
# - v1.0.0 (2025-11-15): Initial handler stub
# Created: 2025-11-15
# Modified: 2025-11-15
# =============================================
"""
@@ -31,7 +25,7 @@ Configuration:
- Connection pooling via client caching
Standards:
- Uses console.print() for user output (NO print())
- Uses prax logger for output (NO print() or console.print())
- Uses logger.info() for system logging
- Integrates with auth/keys, caller detection, usage tracking handlers
- Standalone functions (no classes)
@@ -46,8 +40,8 @@ from pathlib import Path
import time
from typing import Optional, Dict, List, Any
# AIPASS imports
from aipass.cli.apps.modules import console
# Logging
from aipass.prax import logger
# OpenAI SDK for OpenRouter compatibility
try:
@@ -104,12 +98,12 @@ def create_client(api_key: str, base_url: str = OPENROUTER_BASE_URL, timeout: in
"""
if not OPENAI_AVAILABLE:
# logger.error("OpenAI SDK not installed - cannot create client")
console.print("[red]Error: OpenAI SDK not installed. Run: pip install openai[/red]")
logger.error("OpenAI SDK not installed. Run: pip install openai")
return None
if not api_key:
# logger.error("Cannot create client - no API key provided")
console.print("[red]Error: API key required for client creation[/red]")
logger.error("API key required for client creation")
return None
try:
@@ -126,7 +120,7 @@ def create_client(api_key: str, base_url: str = OPENROUTER_BASE_URL, timeout: in
except Exception as e:
# logger.error(f"Failed to create OpenRouter client: {e}")
console.print(f"[red]Error creating OpenRouter client: {e}[/red]")
logger.error(f"Error creating OpenRouter client: {e}")
return None
@@ -208,16 +202,16 @@ def make_api_request(client: OpenAI, messages: List[Dict], model: str, retries:
try:
response = client.chat.completions.create(**api_params)
if attempt > 0:
print(f"[INFO] API request succeeded on retry {attempt} for model {model}")
logger.info(f"API request succeeded on retry {attempt} for model {model}")
return response
except Exception as e:
last_error = e
if attempt < retries:
delay = 1.0 * (attempt + 1) # 1s, 2s, ...
print(f"[INFO] API request failed for {model} (attempt {attempt + 1}/{1 + retries}): {e} — retrying in {delay:.0f}s")
logger.info(f"API request failed for {model} (attempt {attempt + 1}/{1 + retries}): {e} — retrying in {delay:.0f}s")
time.sleep(delay)
print(f"[INFO] API request failed for {model} after {1 + retries} attempts: {last_error}")
logger.error(f"API request failed for {model} after {1 + retries} attempts: {last_error}")
return None
@@ -318,15 +312,15 @@ def get_response(prompt: str, caller: Optional[str] = None, model: Optional[str]
# Step 2: Require model from caller - no defaults
if not model:
# logger.error("No model specified - caller must provide model from their branch config")
console.print("[red]Error: No model specified.[/red]")
console.print("[yellow]Callers must provide their own model via branch config (e.g., flow_json/openrouter_config.json)[/yellow]")
logger.error("No model specified.")
logger.warning("Callers must provide their own model via branch config (e.g., flow_json/openrouter_config.json)")
return None
# Step 3: Get API key
api_key = get_api_key("openrouter")
if not api_key:
# logger.error("Cannot get response - no API key available")
console.print("[red]Error: No OpenRouter API key available[/red]")
logger.error("No OpenRouter API key available")
return None
# Step 4: Get or create client
@@ -376,7 +370,7 @@ def clear_client_cache() -> None:
count = len(_client_cache)
_client_cache.clear()
# logger.info(f"Cleared {count} cached clients")
console.print(f"[green]Cleared {count} cached OpenRouter clients[/green]")
logger.info(f"Cleared {count} cached OpenRouter clients")
def get_cache_stats() -> Dict[str, Any]:
@@ -1,13 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: models.py - OpenRouter Model Management
# Date: 2025-11-16
# =================== AIPass ====================
# Name: models.py
# Description: OpenRouter Model Management
# Version: 1.0.0
# Category: api/handlers
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-16): Complete handler - model fetching, filtering, pricing
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
@@ -29,8 +25,8 @@ from pathlib import Path
# Standard library imports
from typing import Dict, List, Optional
# Console import (NO print())
from aipass.cli.apps.modules import console
# Logging
from aipass.prax import logger
# Third-party imports
import requests
@@ -67,7 +63,7 @@ def get_available_models(api_key: Optional[str] = None) -> List[Dict]:
Example:
>>> models = get_available_models()
>>> console.print(f"Found {len(models)} models")
>>> logger.info(f"Found {len(models)} models")
"""
try:
# Get API key if not provided
@@ -76,7 +72,7 @@ def get_available_models(api_key: Optional[str] = None) -> List[Dict]:
if not api_key:
# logger.info(f"[{MODULE_NAME}] No API key available for OpenRouter")
console.print("[yellow]No OpenRouter API key found[/yellow]")
logger.warning("No OpenRouter API key found")
return []
# Fetch models from API
@@ -91,7 +87,7 @@ def get_available_models(api_key: Optional[str] = None) -> List[Dict]:
except Exception as e:
# logger.info(f"[{MODULE_NAME}] Failed to get available models: {e}")
console.print(f"[red]Error fetching models: {e}[/red]")
logger.error(f"Error fetching models: {e}")
return []
@@ -111,7 +107,7 @@ def get_free_models(api_key: Optional[str] = None) -> List[Dict]:
Example:
>>> free_models = get_free_models()
>>> for model in free_models:
... console.print(f"Free: {model['id']}")
... logger.info(f"Free: {model['id']}")
"""
try:
# Get all models first
@@ -128,7 +124,7 @@ def get_free_models(api_key: Optional[str] = None) -> List[Dict]:
except Exception as e:
# logger.info(f"[{MODULE_NAME}] Failed to get free models: {e}")
console.print(f"[red]Error fetching free models: {e}[/red]")
logger.error(f"Error fetching free models: {e}")
return []
@@ -166,7 +162,7 @@ def fetch_models_from_api(api_key: str) -> List[Dict]:
# Check response status
if response.status_code != 200:
# logger.info(f"[{MODULE_NAME}] API request failed with status {response.status_code}")
console.print(f"[red]OpenRouter API error: {response.status_code}[/red]")
logger.error(f"OpenRouter API error: {response.status_code}")
return []
# Parse JSON response
@@ -183,22 +179,22 @@ def fetch_models_from_api(api_key: str) -> List[Dict]:
except requests.exceptions.Timeout:
# logger.info(f"[{MODULE_NAME}] API request timeout after {DEFAULT_TIMEOUT}s")
console.print(f"[red]Request timeout - OpenRouter API not responding[/red]")
logger.error("Request timeout - OpenRouter API not responding")
return []
except requests.exceptions.RequestException as e:
# logger.info(f"[{MODULE_NAME}] Network error: {e}")
console.print(f"[red]Network error: {e}[/red]")
logger.error(f"Network error: {e}")
return []
except ValueError as e:
# logger.info(f"[{MODULE_NAME}] JSON parse error: {e}")
console.print(f"[red]Invalid JSON response from API[/red]")
logger.error("Invalid JSON response from API")
return []
except Exception as e:
# logger.info(f"[{MODULE_NAME}] Unexpected error fetching models: {e}")
console.print(f"[red]Error: {e}[/red]")
logger.error(f"Error: {e}")
return []
@@ -291,7 +287,7 @@ def extract_model_metadata(model: Dict) -> Dict:
Example:
>>> model = get_model_by_id("meta-llama/llama-3.3-70b-instruct:free")
>>> meta = extract_model_metadata(model)
>>> console.print(f"Context: {meta['context_length']}")
>>> logger.info(f"Context: {meta['context_length']}")
"""
try:
pricing = model.get("pricing", {})
@@ -341,27 +337,27 @@ def list_model_ids(models: List[Dict]) -> List[str]:
def display_models(models: List[Dict], show_pricing: bool = True) -> None:
"""
Display models in formatted output using console
Display models in formatted output using logger
Args:
models: List of model dictionaries to display
show_pricing: Whether to show pricing information
"""
if not models:
console.print("[yellow]No models to display[/yellow]")
logger.info("No models to display")
return
console.print(f"\n[bold]Found {len(models)} models:[/bold]\n")
logger.info(f"Found {len(models)} models:")
for i, model in enumerate(models, 1):
model_id = model.get("id", "unknown")
name = model.get("name", "")
context = model.get("context_length", 0)
console.print(f"[cyan]{i}. {model_id}[/cyan]")
logger.info(f"{i}. {model_id}")
if name:
console.print(f" Name: {name}")
console.print(f" Context: {context:,} tokens")
logger.info(f" Name: {name}")
logger.info(f" Context: {context:,} tokens")
if show_pricing:
pricing = model.get("pricing", {})
@@ -369,11 +365,9 @@ def display_models(models: List[Dict], show_pricing: bool = True) -> None:
completion_cost = pricing.get("completion", "0")
if prompt_cost == "0" and completion_cost == "0":
console.print(" [green]FREE[/green]")
logger.info(" FREE")
else:
console.print(f" Prompt: ${prompt_cost} / Completion: ${completion_cost}")
console.print()
logger.info(f" Prompt: ${prompt_cost} / Completion: ${completion_cost}")
def display_free_models_summary(api_key: Optional[str] = None) -> None:
@@ -386,20 +380,20 @@ def display_free_models_summary(api_key: Optional[str] = None) -> None:
Args:
api_key: Optional OpenRouter API key
"""
console.print("[bold]Searching for FREE models on OpenRouter...[/bold]")
console.print("=" * 60)
logger.info("Searching for FREE models on OpenRouter...")
logger.info("=" * 60)
free_models = get_free_models(api_key)
if not free_models:
console.print("[yellow]No free models found[/yellow]")
console.print("OpenRouter may have changed pricing.")
console.print("Alternative: Use very cheap models like openai/gpt-4o-mini")
logger.info("No free models found")
logger.info("OpenRouter may have changed pricing.")
logger.info("Alternative: Use very cheap models like openai/gpt-4o-mini")
return
display_models(free_models, show_pricing=False)
console.print("\n[bold]RECOMMENDED FREE MODELS TO TRY:[/bold]")
console.print("-" * 60)
logger.info("RECOMMENDED FREE MODELS TO TRY:")
logger.info("-" * 60)
for model in free_models[:5]: # Top 5
console.print(f" - {model.get('id', '')}")
logger.info(f" - {model.get('id', '')}")
@@ -1,13 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: provision.py - Caller Auto-Provisioning Handler
# Date: 2025-11-16
# =================== AIPass ====================
# Name: provision.py
# Description: Caller Auto-Provisioning Handler
# Version: 1.0.0
# Category: api/handlers/openrouter
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-16): Initial handler - auto-provision caller configs
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
@@ -21,7 +17,7 @@ Business logic for provisioning OpenRouter API configs:
- Ensure caller has complete 3-file JSON structure
COMPLIANT STANDARDS:
- Uses console.print() for output (NO print())
- Uses prax logger for output (NO print() or console.print())
- Uses prax logger for operations
- Standalone functions (no class dependencies)
- Imports from caller handler for detection logic
@@ -36,7 +32,7 @@ import json
from datetime import datetime
from typing import Dict, Any, Optional, Tuple
from aipass.cli.apps.modules import console
from aipass.prax import logger
from aipass.api.apps.handlers.openrouter.caller import detect_caller_from_stack
@@ -168,12 +164,12 @@ def provision_json_folder(json_folder: Path) -> bool:
json_folder.mkdir(parents=True, exist_ok=True)
# logger.info(f"Created JSON folder: {json_folder}")
console.print(f"[green]Created JSON folder:[/green] {json_folder}")
logger.info(f"Created JSON folder: {json_folder}")
return True
except Exception as e:
# logger.error(f"Failed to create JSON folder {json_folder}: {e}")
console.print(f"[red]Error:[/red] Failed to create JSON folder: {e}")
logger.error(f"Failed to create JSON folder: {e}")
return False
@@ -207,7 +203,7 @@ def create_caller_config(caller: str, json_folder: Path) -> Dict[str, Any]:
return {}
# logger.info(f"Created API config for {caller}: {config_file}")
console.print(f"[green]Created config:[/green] {config_file.name}")
logger.info(f"Created config: {config_file.name}")
# Create data file
data_file = json_folder / "openrouter_skill_data.json"
@@ -215,7 +211,7 @@ def create_caller_config(caller: str, json_folder: Path) -> Dict[str, Any]:
if write_json(data_file, data):
# logger.info(f"Created data file for {caller}: {data_file}")
console.print(f"[green]Created data:[/green] {data_file.name}")
logger.info(f"Created data: {data_file.name}")
# Create log file
log_file = json_folder / "openrouter_skill_log.json"
@@ -223,16 +219,16 @@ def create_caller_config(caller: str, json_folder: Path) -> Dict[str, Any]:
if write_json(log_file, log_data):
# logger.info(f"Created log file for {caller}: {log_file}")
console.print(f"[green]Created log:[/green] {log_file.name}")
logger.info(f"Created log: {log_file.name}")
console.print(f"[cyan]Info:[/cyan] Auto-provisioned OpenRouter config for '{caller}'")
console.print(f"[yellow]Note:[/yellow] Reload config and retry request")
logger.info(f"Auto-provisioned OpenRouter config for '{caller}'")
logger.warning("Reload config and retry request")
return config
except Exception as e:
# logger.error(f"Failed to create config for {caller}: {e}")
console.print(f"[red]Error:[/red] Config creation failed: {e}")
logger.error(f"Config creation failed: {e}")
return {}
@@ -259,7 +255,7 @@ def ensure_caller_config(caller: str | None = None) -> Dict[str, Any]:
# logger.info(f"Auto-detected caller: {caller}")
else:
# logger.warning("Could not detect caller from stack")
console.print("[yellow]Warning:[/yellow] Could not detect caller module")
logger.warning("Could not detect caller module")
return {}
# Get JSON folder path if not already detected
@@ -267,7 +263,7 @@ def ensure_caller_config(caller: str | None = None) -> Dict[str, Any]:
_, json_folder = detect_caller_from_stack()
if not json_folder:
# logger.error(f"Could not determine JSON folder for {caller}")
console.print(f"[red]Error:[/red] Could not find JSON folder for '{caller}'")
logger.error(f"Could not find JSON folder for '{caller}'")
return {}
# Check if config already exists
@@ -280,14 +276,14 @@ def ensure_caller_config(caller: str | None = None) -> Dict[str, Any]:
return config
else:
# logger.warning(f"Config file corrupted for {caller}, regenerating")
console.print(f"[yellow]Warning:[/yellow] Corrupted config, regenerating...")
logger.warning("Corrupted config, regenerating...")
# Create new config
return create_caller_config(caller, json_folder)
except Exception as e:
# logger.error(f"Failed to ensure config for {caller}: {e}")
console.print(f"[red]Error:[/red] Config provisioning failed: {e}")
logger.error(f"Config provisioning failed: {e}")
return {}
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: aggregation.py - Usage Aggregation Handler
# Date: 2025-11-15
# =================== AIPass ====================
# Name: aggregation.py
# Description: Usage Aggregation Handler
# Version: 1.0.0
# Category: api/handlers/usage
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-15): Initial handler - usage stats aggregation
# - v1.1.0 (2025-11-16): Extracted aggregation logic from archive
# Created: 2025-11-15
# Modified: 2025-11-15
# =============================================
"""
+13 -23
View File
@@ -1,20 +1,10 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: cleanup.py - Usage data retention and cleanup
# Date: 2025-11-16
# =================== AIPass ====================
# Name: cleanup.py
# Description: Usage data retention and cleanup
# Version: 0.1.0
# Category: api/handlers
#
# CHANGELOG (Max 5 entries):
# - v0.1.0 (2025-11-16): Extracted from api_usage.py
# - v1.0.0 (2025-11-15): Initial handler - old data cleanup
#
# CODE STANDARDS:
# - Handler layer (standalone functions)
# - Uses CLI service for output
# - Under 300 lines
# ==============================================
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
Usage Data Cleanup Handler
@@ -32,8 +22,8 @@ import json
from datetime import datetime, timedelta
from typing import Optional, Dict, List
# CLI services
from aipass.cli.apps.modules import console, success, warning
# Logging
from aipass.prax import logger
def _read_json(file_path: Path) -> Optional[Dict]:
@@ -99,13 +89,13 @@ def cleanup_old_data(data_file_path: Path, retention_days: int = 30) -> int:
_write_json(data_file_path, data)
# logger.info(f"Cleaned up {len(old_generations)} generation entries")
success(f"Cleaned up {len(old_generations)} generation entries older than {retention_days} days")
logger.info(f"Cleaned up {len(old_generations)} generation entries older than {retention_days} days")
return len(old_generations)
except Exception as e:
# logger.error(f"Cleanup failed: {e}")
console.print(f"[red]Cleanup failed: {e}[/red]")
logger.error(f"Cleanup failed: {e}")
raise
@@ -162,13 +152,13 @@ def cleanup_daily_totals(data_file_path: Path, retention_days: int = 90) -> int:
_write_json(data_file_path, data)
# logger.info(f"Cleaned up {len(old_dates)} daily total entries")
success(f"Cleaned up {len(old_dates)} daily total entries older than {retention_days} days")
logger.info(f"Cleaned up {len(old_dates)} daily total entries older than {retention_days} days")
return len(old_dates)
except Exception as e:
# logger.error(f"Daily totals cleanup failed: {e}")
console.print(f"[red]Daily totals cleanup failed: {e}[/red]")
logger.error(f"Daily totals cleanup failed: {e}")
raise
@@ -190,7 +180,7 @@ def auto_cleanup(data_file_path: Path, config: Optional[Dict] = None) -> Dict[st
except Exception as e:
# logger.error(f"Auto cleanup failed: {e}")
console.print(f"[red]Auto cleanup failed: {e}[/red]")
logger.error(f"Auto cleanup failed: {e}")
raise
@@ -1,13 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: tracking.py - Usage Tracking Handler
# Date: 2025-11-16
# =================== AIPass ====================
# Name: tracking.py
# Description: Usage Tracking Handler
# Version: 1.0.0
# Category: api/handlers/usage
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-16): Extracted tracking logic from archive
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
+5 -10
View File
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: api_key.py - API Key Management Module
# Date: 2025-11-15
# =================== AIPass ====================
# Name: api_key.py
# Description: API Key Management Module
# Version: 1.0.0
# Category: api/modules
# CODE STANDARDS: Seed v1.0.0
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-15): Initial module - orchestrates key management
# Created: 2025-11-15
# Modified: 2025-11-15
# =============================================
"""
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: openrouter_client.py - OpenRouter Client Module
# Date: 2025-11-15
# =================== AIPass ====================
# Name: openrouter_client.py
# Description: OpenRouter Client Module
# Version: 1.0.0
# Category: api/modules
# CODE STANDARDS: Seed v1.0.0
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-15): Initial module - orchestrates OpenRouter operations
# Created: 2025-11-15
# Modified: 2025-11-15
# =============================================
"""
@@ -237,7 +232,7 @@ def get_response(prompt: str, caller: str | None = None, model: str | None = Non
>>> from aipass.api.apps.modules.openrouter_client import get_response
>>> response = get_response("Hello", caller="flow", model="anthropic/claude-3.5-sonnet")
>>> if response:
... print(response['content'])
... console.print(response['content'])
"""
return client.get_response(prompt, caller, model, **kwargs)
+5 -10
View File
@@ -1,14 +1,9 @@
# ===================AIPASS====================
# META DATA HEADER
# Name: usage_tracker.py - Usage Tracking Module
# Date: 2025-11-15
# =================== AIPass ====================
# Name: usage_tracker.py
# Description: Usage Tracking Module
# Version: 1.0.0
# Category: api/modules
# CODE STANDARDS: Seed v1.0.0
#
# CHANGELOG (Max 5 entries):
# - v1.0.0 (2025-11-15): Initial module - orchestrates usage tracking
# Created: 2025-11-15
# Modified: 2025-11-15
# =============================================
"""