This commit is contained in:
2026-09-27 23:06:24 +08:00
parent 2d4f9230b1
commit 22450e5bb3
40 changed files with 3040 additions and 697 deletions
+30 -11
View File
@@ -27,16 +27,35 @@ from app.services.i18n import parse_accept_language
from app.api.simulate import router as simulate_router
from app.api.agents import router as agents_router
from app.api.gallery import router as gallery_router
from app.api.presets import router as presets_router
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s")
logger = logging.getLogger(__name__)
from app.api.presets import router as presets_router
from app.services.simulation_logging import (
ChineseSimulationFormatter,
install_simulation_log_handler,
)
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(name)s %(levelname)s %(message)s")
install_simulation_log_handler()
# Use Chinese labels for the terminal's timestamp/level/module metadata too;
# the original message is kept intact so stack traces and search terms remain
# useful when diagnosing third-party libraries.
for _handler in logging.getLogger().handlers:
if not isinstance(_handler, logging.NullHandler):
_handler.setFormatter(ChineseSimulationFormatter())
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
logs_dir = Path(__file__).resolve().parent.parent / "logs"
logs_dir.mkdir(parents=True, exist_ok=True)
async def lifespan(app: FastAPI):
# Keep user-authored scenario files available even before the first
# presets request (and create the folder on a fresh checkout).
custom_simulation_dir = Path(__file__).resolve().parents[2] / "custom_simulation"
custom_simulation_dir.mkdir(parents=True, exist_ok=True)
logs_dir = Path(__file__).resolve().parent.parent / "logs"
logs_dir.mkdir(parents=True, exist_ok=True)
# Project-level text logs are created per simulation, but ensure the
# directory exists as soon as the application starts.
project_logs_dir = Path(__file__).resolve().parents[2] / "logs"
project_logs_dir.mkdir(parents=True, exist_ok=True)
store = SimulationStore(settings.database_dir)
await store.init()
@@ -48,9 +67,9 @@ async def lifespan(app: FastAPI):
try:
interrupted = await store.sweep_orphan_running_sims()
if interrupted:
logger.warning("Marked %d orphan simulations as interrupted", interrupted)
logger.warning("已将 %d 个遗留模拟标记为已中断", interrupted)
except Exception as e: # pragma: no cover - best effort
logger.warning("Orphan sweep failed: %s", e)
logger.warning("清理遗留模拟失败:%s", e)
llm = LLMClient(
api_key=settings.llm_api_key,
@@ -84,9 +103,9 @@ async def lifespan(app: FastAPI):
app.state.event_queues = {}
app.state.cancelled_sims = set()
logger.info("MiroSociety started — LLM: %s @ %s", settings.llm_model, settings.llm_base_url)
logger.info("MiroSociety 已启动:模型=%s,地址=%s", settings.llm_model, settings.llm_base_url)
yield
logger.info("MiroSociety shutting down")
logger.info("MiroSociety 正在关闭")
app = FastAPI(title="MiroSociety", version="0.1.0", lifespan=lifespan)