fix(logging): replace stdlib-style exc_info kwargs with loguru opt(exception=)

Loguru has no exc_info kwarg: extra kwargs are str.format() arguments, so
logger.error(f"...{e}", exc_info=True) forces .format() on the rendered
message — any error text containing braces (e.g. a JSON error body) raises
KeyError FROM the log call itself, escaping the surrounding except block and
killing the caller (observed: whole agent turns dying in benchmark runs).
The intended traceback was also never logged, since exc_info is not a loguru
feature.

Batch fix of all 143 sites across 11 files:
  logger.X(msg, exc_info=True) -> logger.opt(exception=True).X(msg)
  (one exc_info=exc site -> opt(exception=exc))
Messages are byte-identical; with the kwarg gone loguru never calls
.format(), so brace-containing f-string messages are inert.

Verified: AST post-conditions per file, py_compile, import smoke of all
modules, behavioral equivalence of the 3 patterns, full unit suite (1549
passed) with a failure set identical to the pristine tree (22 pre-existing,
zero regressions).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Also add pixel-agents to the README acknowledgements.
This commit is contained in:
LZH-YS1998
2026-07-03 17:09:11 +08:00
parent d78931979d
commit 08e48c2f9c
12 changed files with 156 additions and 172 deletions
+4 -4
View File
@@ -2630,7 +2630,7 @@ async def _build_company_runtime_control_by_task(
if sid and sid not in checkpoints_by_session:
checkpoints_by_session[sid] = checkpoint
except Exception:
logger.debug("snapshot: failed to load company runtime checkpoints", exc_info=True)
logger.opt(exception=True).debug("snapshot: failed to load company runtime checkpoints")
result: dict[str, dict[str, Any]] = {}
for parent_session_id, group in tasks_by_parent_session.items():
@@ -2892,7 +2892,7 @@ async def build_project_index_sync(
try:
tasks = await engine.store.get_tasks(project_id=project_id)
except Exception:
logger.warning("Failed to load tasks for project index", exc_info=True)
logger.opt(exception=True).warning("Failed to load tasks for project index")
existing_task_ids = {
str(getattr(task, "id", "") or "").strip()
@@ -3286,7 +3286,7 @@ async def build_collab_sync(
event_adapter=event_adapter,
)
except Exception:
logger.warning("Failed to build company-mode kanban projection", exc_info=True)
logger.opt(exception=True).warning("Failed to build company-mode kanban projection")
# Per-session DelegationWorkItem rollups produced alongside the company
# kanban projection. Used by the work-item-driven Execution Progress
# panel — keyed by ``task.session_id`` (matches the formatted_sessions
@@ -3308,7 +3308,7 @@ async def build_collab_sync(
if backfilled:
logger.info(f"Reconciled {backfilled} total messages from engine → ChatStore")
except Exception:
logger.warning("Session reconciliation failed (non-fatal)", exc_info=True)
logger.opt(exception=True).warning("Session reconciliation failed (non-fatal)")
existing_task_ids = {
str(getattr(task, "id", "") or "").strip()