#!/usr/bin/env python # -*- coding: utf-8 -*- """ Self-evolution MVP cycle runner. """ from __future__ import annotations import argparse import json import os import sys from pathlib import Path from dotenv import load_dotenv PROJECT_ROOT = Path(__file__).resolve().parent.parent sys.path.insert(0, str(PROJECT_ROOT)) load_dotenv(dotenv_path=PROJECT_ROOT / ".env") from evolution.mvp import ChatSourceConfig, DEFAULT_CANDIDATE_PATH, DEFAULT_POLICY_PATH, run_cycle def parse_args() -> argparse.Namespace: parser = argparse.ArgumentParser(description="Run self-evolution MVP cycle") parser.add_argument( "--source", type=str, default="mysql", choices=["auto", "sqlite", "mysql"], help="Chat data source, default mysql (online)", ) parser.add_argument("--hours", type=int, default=24, help="Lookback window for chat samples") parser.add_argument("--max-customers", type=int, default=200, help="Max customers sampled") parser.add_argument( "--max-messages-per-customer", type=int, default=80, help="Max messages loaded per customer", ) parser.add_argument("--runtime-hours", type=int, default=24, help="Runtime metric window") parser.add_argument( "--publish", action="store_true", help="Write config/evolution_candidate.json when gate passes", ) parser.add_argument( "--policy-path", type=str, default=str(DEFAULT_POLICY_PATH), help="Path to evolution gate policy file", ) parser.add_argument( "--candidate-path", type=str, default=str(DEFAULT_CANDIDATE_PATH), help="Path to candidate output file", ) parser.add_argument("--db-path", type=str, default="", help="SQLite path when --source sqlite") parser.add_argument("--mysql-host", type=str, default=os.getenv("MYSQL_HOST", "127.0.0.1")) parser.add_argument("--mysql-port", type=int, default=int(os.getenv("MYSQL_PORT", "3306"))) parser.add_argument("--mysql-user", type=str, default=os.getenv("MYSQL_USER", "root")) parser.add_argument("--mysql-password", type=str, default=os.getenv("MYSQL_PASSWORD", "")) parser.add_argument("--mysql-database", type=str, default=os.getenv("MYSQL_DATABASE", "ai_cs")) return parser.parse_args() def main() -> int: args = parse_args() os.environ.setdefault("PYTHONUTF8", "1") chat_source = ChatSourceConfig( source=args.source, sqlite_path=args.db_path or str(PROJECT_ROOT / "db" / "chat_log_db" / "chats.db"), mysql_host=args.mysql_host, mysql_port=args.mysql_port, mysql_user=args.mysql_user, mysql_password=args.mysql_password, mysql_database=args.mysql_database, ) result = run_cycle( hours=args.hours, max_customers=args.max_customers, max_messages_per_customer=args.max_messages_per_customer, runtime_hours=args.runtime_hours, publish=args.publish, chat_source=chat_source, policy_path=Path(args.policy_path), candidate_path=Path(args.candidate_path), ) print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())