Files
AIPass/src/aipass/api/apps/handlers/openrouter/provision.py
T
AIOSAIandClaude Opus 4.6 babedd9c64 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>
2026-03-10 01:26:42 -07:00

290 lines
8.3 KiB
Python

# =================== AIPass ====================
# Name: provision.py
# Description: Caller Auto-Provisioning Handler
# Version: 1.0.0
# Created: 2025-11-16
# Modified: 2025-11-16
# =============================================
"""
Caller Auto-Provisioning Handler
Business logic for provisioning OpenRouter API configs:
- Auto-create caller API configurations
- Provision JSON folder structure
- Set default model/temperature/max_tokens
- Initialize caller-specific tracking files
- Ensure caller has complete 3-file JSON structure
COMPLIANT STANDARDS:
- 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
- Complete docstrings with Args/Returns
- Under 300 lines
"""
import sys
from pathlib import Path
import json
from datetime import datetime
from typing import Dict, Any, Optional, Tuple
from aipass.prax import logger
from aipass.api.apps.handlers.openrouter.caller import detect_caller_from_stack
# ===========================================
# JSON UTILITIES
# ===========================================
def read_json(file_path: Path) -> Optional[Dict[str, Any]]:
"""
Read JSON file safely
Args:
file_path: Path to JSON file
Returns:
Parsed JSON dict or None on error
"""
try:
if not file_path.exists():
return None
with open(file_path, 'r', encoding='utf-8') as f:
return json.load(f)
except Exception as e:
# logger.error(f"Failed to read {file_path}: {e}")
return None
def write_json(file_path: Path, data: Dict[str, Any]) -> bool:
"""
Write JSON file safely with formatting
Args:
file_path: Path to JSON file
data: Dict to write as JSON
Returns:
True if successful, False otherwise
"""
try:
file_path.parent.mkdir(parents=True, exist_ok=True)
with open(file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
return True
except Exception as e:
# logger.error(f"Failed to write {file_path}: {e}")
return False
# ===========================================
# DEFAULT CONFIGURATION
# ===========================================
def get_default_caller_config() -> Dict[str, Any]:
"""
Get default config template for new callers
NOTE: No default ai_model - callers must set their own model in their branch config
Returns:
Dict with default OpenRouter configuration (model must be set by caller)
"""
return {
"skill_name": "openrouter",
"timestamp": datetime.now().isoformat(),
"config": {
"ai_model": "", # Caller must set their own model
"ai_temperature": 0.7,
"ai_max_tokens": 4000,
"enabled": True
}
}
def get_default_caller_data() -> Dict[str, Any]:
"""
Get default data template for tracking caller usage
Returns:
Dict with initial usage tracking data
"""
return {
"skill_name": "openrouter",
"timestamp": datetime.now().isoformat(),
"data": {
"total_requests": 0,
"successful_requests": 0,
"failed_requests": 0,
"models_used": {},
"last_request": None
}
}
def get_default_caller_log() -> Dict[str, Any]:
"""
Get default log template for caller operations
Returns:
Dict with empty log structure
"""
return {
"skill_name": "openrouter",
"timestamp": datetime.now().isoformat(),
"logs": []
}
# ===========================================
# PROVISIONING FUNCTIONS
# ===========================================
def provision_json_folder(json_folder: Path) -> bool:
"""
Create JSON folder structure if missing
Args:
json_folder: Path to caller's JSON folder
Returns:
True if folder exists or created, False on error
"""
try:
if json_folder.exists():
return True
json_folder.mkdir(parents=True, exist_ok=True)
# logger.info(f"Created JSON folder: {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}")
logger.error(f"Failed to create JSON folder: {e}")
return False
def create_caller_config(caller: str, json_folder: Path) -> Dict[str, Any]:
"""
Create new caller configuration with defaults
Creates complete 3-file JSON structure:
- openrouter_skill_config.json (API settings)
- openrouter_skill_data.json (usage tracking)
- openrouter_skill_log.json (operation log)
Args:
caller: Name of calling module
json_folder: Path to caller's JSON folder
Returns:
Dict with created config or empty dict on error
"""
try:
# Ensure JSON folder exists
if not provision_json_folder(json_folder):
return {}
# Create config file
config_file = json_folder / "openrouter_skill_config.json"
config = get_default_caller_config()
if not write_json(config_file, config):
# logger.error(f"Failed to write config for {caller}")
return {}
# logger.info(f"Created API config for {caller}: {config_file}")
logger.info(f"Created config: {config_file.name}")
# Create data file
data_file = json_folder / "openrouter_skill_data.json"
data = get_default_caller_data()
if write_json(data_file, data):
# logger.info(f"Created data file for {caller}: {data_file}")
logger.info(f"Created data: {data_file.name}")
# Create log file
log_file = json_folder / "openrouter_skill_log.json"
log_data = get_default_caller_log()
if write_json(log_file, log_data):
# logger.info(f"Created log file for {caller}: {log_file}")
logger.info(f"Created log: {log_file.name}")
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}")
logger.error(f"Config creation failed: {e}")
return {}
def ensure_caller_config(caller: str | None = None) -> Dict[str, Any]:
"""
Ensure caller has API configuration, create if missing
Auto-detects caller if not provided. Creates complete 3-file
JSON structure with default OpenRouter settings.
Args:
caller: Optional caller name (auto-detected if None)
Returns:
Dict with config or empty dict if unable to provision
"""
try:
# Auto-detect caller if not provided
json_folder = None
if not caller:
detected_caller, json_folder = detect_caller_from_stack()
if detected_caller:
caller = detected_caller
# logger.info(f"Auto-detected caller: {caller}")
else:
# logger.warning("Could not detect caller from stack")
logger.warning("Could not detect caller module")
return {}
# Get JSON folder path if not already detected
if not json_folder:
_, json_folder = detect_caller_from_stack()
if not json_folder:
# logger.error(f"Could not determine JSON folder for {caller}")
logger.error(f"Could not find JSON folder for '{caller}'")
return {}
# Check if config already exists
config_file = json_folder / "openrouter_skill_config.json"
if config_file.exists():
config = read_json(config_file)
if config:
# logger.info(f"Using existing config for {caller}")
return config
else:
# logger.warning(f"Config file corrupted for {caller}, 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}")
logger.error(f"Config provisioning failed: {e}")
return {}