From 9e9bd8679f07e5646046003757a6e82cc3acc144 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 20 Apr 2026 20:41:12 +0800 Subject: [PATCH] fix(aider-watch): code-review fixes (4 issues) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. aiderw: session_end 補 model+cwd (AI Router feedback loop 修通) 2. repository: model_stats_since SQL 改 COALESCE(session_end, session_start) model 3. aider_event_service: classify_severity 移除 error_count 觸發告警(防假陽性) 4. worker: run_aider_event_processor_loop 包 proc.start() try/except(防靜默崩潰) 2026-04-20 @ Asia/Taipei --- .../src/repositories/aider_event_repository.py | 16 ++++++++++++---- apps/api/src/services/aider_event_service.py | 2 +- apps/api/src/workers/aider_event_processor.py | 6 +++++- .../aider_watch_client/aiderw.py | 5 ++++- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/apps/api/src/repositories/aider_event_repository.py b/apps/api/src/repositories/aider_event_repository.py index 944e9064..77819e9f 100644 --- a/apps/api/src/repositories/aider_event_repository.py +++ b/apps/api/src/repositories/aider_event_repository.py @@ -75,10 +75,18 @@ class AiderEventRepository: r = await self.session.execute(text(""" WITH session_models AS ( SELECT session_id, - MAX(CASE WHEN type='session_start' - THEN payload->>'model' END) AS model, - MAX(CASE WHEN type='session_start' - THEN payload->>'cwd' END) AS repo, + COALESCE( + MAX(CASE WHEN type='session_end' + THEN payload->>'model' END), + MAX(CASE WHEN type='session_start' + THEN payload->>'model' END) + ) AS model, + COALESCE( + MAX(CASE WHEN type='session_end' + THEN payload->>'cwd' END), + MAX(CASE WHEN type='session_start' + THEN payload->>'cwd' END) + ) AS repo, COUNT(*) FILTER (WHERE type='error') AS err_count, COUNT(*) FILTER (WHERE type='session_end' AND (payload->>'exit_code')::int != 0) AS nonzero_exit diff --git a/apps/api/src/services/aider_event_service.py b/apps/api/src/services/aider_event_service.py index 49e6fc6d..ac26b44a 100644 --- a/apps/api/src/services/aider_event_service.py +++ b/apps/api/src/services/aider_event_service.py @@ -36,7 +36,7 @@ def classify_severity(ev: AiderEventIn) -> str | None: err_count = ev.payload.get("error_count", 0) if exit_code != 0 and err_count >= 3: return "high" - if exit_code != 0 or err_count >= 1: + if exit_code != 0: return "warning" return None diff --git a/apps/api/src/workers/aider_event_processor.py b/apps/api/src/workers/aider_event_processor.py index d7a8ad67..4ceaeb6c 100644 --- a/apps/api/src/workers/aider_event_processor.py +++ b/apps/api/src/workers/aider_event_processor.py @@ -190,7 +190,11 @@ def get_aider_event_processor() -> AiderEventProcessor: async def run_aider_event_processor_loop() -> None: """main.py lifespan 呼叫此函式。""" proc = get_aider_event_processor() - await proc.start() + try: + await proc.start() + except Exception: + logger.exception("aider_processor_start_failed") + return try: while proc._running: await asyncio.sleep(60) diff --git a/scripts/aider_watch_client/aider_watch_client/aiderw.py b/scripts/aider_watch_client/aider_watch_client/aiderw.py index 99a8f016..28b05243 100644 --- a/scripts/aider_watch_client/aider_watch_client/aiderw.py +++ b/scripts/aider_watch_client/aider_watch_client/aiderw.py @@ -157,6 +157,7 @@ def main(argv: list[str] | None = None) -> int: "context_50chars": stdout_text[-50:]}, }) + banner = parse_stdout_banner(stdout_text) events_tail.append({ "ts": _now_iso(), "session_id": sid, "host": host, "type": "session_end", @@ -166,7 +167,9 @@ def main(argv: list[str] | None = None) -> int: "files_changed": len([e for e in events_tail if e["type"] == "file_edit"]), "error_count": error_count[0], - "exit_code": exit_code}, + "exit_code": exit_code, + "model": banner.get("model", "unknown"), + "cwd": str(cwd)}, }) if events_tail: