fix(aibox): batch G audit fixes - llm hardening, thread lifecycle, cancel propagation, db transactions

P-series (llm_client): truncate non-transient HTTP error body to 200 chars, cap Retry-After at 3600s, validate fallback profiles (missing model skipped with warning), dedupe fallback list, remove dead _cancelled flag, document FailoverClient concurrency contract.

N-series (aibox/registry): batch-level drain thread with try/finally reclamation (N2), subagent cancel propagation via shared parent event + watcher thread (N5), /new reset moved off event loop (N3), streaming forward bounded by TOOL_MAX_RESULT_LENGTH (N8), persona path boundary check (N12), broadcast except narrowed + discard (N13), per-connection task set registration (N14).

db/history: FTS5 quote escaping (N7), mark_as_triggered single BEGIN IMMEDIATE transaction (N10), LIMIT parameterization (L1), archive filename collision suffix (N16).

Tests: +20 cases in test_g_fixes.py, full suite 375 passed.
This commit is contained in:
qing committed 2026-08-18 07:21:29 +08:00
1 parent aa15841d73
commit cccc946660
6 files changed
+690 -184

No files matched your search

+10 -1
View File
@@ -61,7 +61,10 @@ class ConversationHistory:
try:
with open(self.history_file, 'r', encoding='utf-8') as f:
return json.load(f)
except:
except Exception as e:
# N16:收窄为 Exception——裸 except 连 KeyboardInterrupt/SystemExit
# 也吞掉;损坏时重置为空索引并告警
self.logger.warning(f"历史索引文件损坏,已重置: {e}")
return {"conversations": [], "last_id": 0}
return {"conversations": [], "last_id": 0}
@@ -132,8 +135,14 @@ class ConversationHistory:
importance=2
)
# N16:归档文件名加序号防同秒覆盖——DATE_FORMAT 精度为秒,
# 同一秒内两次归档(如测试/快速重置)会静默覆盖前一份
timestamp = datetime.now().strftime(constants.DATE_FORMAT)
archive_filename = f"conversation_{timestamp}.json"
counter = 1
while (self.archive_dir / archive_filename).exists():
archive_filename = f"conversation_{timestamp}_{counter}.json"
counter += 1
archive_path = self.archive_dir / archive_filename
with open(archive_path, 'w', encoding='utf-8') as f: