feat: engine/model in audit log + docs update

- tool_audit: ContextVars (engine, model) set at orchestrator run start; fields added to every entry
- orchestrator_engine: tool_audit.set_context("gemini", model_name) at run() start
- openai_orchestrator: tool_audit.set_context("openai", model label) at run() start
- audit table: Model column between Status and Args
- HELP.md: push notifications section, audit log in Files section, tool count 30→40, new API endpoints
- TODO__Agents.md: web_push and audit log marked complete with full detail

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-05 20:42:32 -04:00
parent 02accefe8f
commit 7d221863dc
7 changed files with 55 additions and 6 deletions

View File

@@ -16,6 +16,7 @@ Each line is a JSON object:
import asyncio
import json
import logging
from contextvars import ContextVar
from datetime import datetime, date
from pathlib import Path
@@ -29,6 +30,16 @@ _SNIPPET_MAX = 300 # chars of result to keep as snippet
# Per-file write locks — prevents interleaved lines under concurrent tool calls
_locks: dict[str, asyncio.Lock] = {}
# ContextVars set by orchestrators before their tool loop runs
_audit_engine: ContextVar[str] = ContextVar("_audit_engine", default="")
_audit_model: ContextVar[str] = ContextVar("_audit_model", default="")
def set_context(engine: str, model: str) -> None:
"""Call at the start of each orchestrator run to tag subsequent tool calls."""
_audit_engine.set(engine)
_audit_model.set(model)
def _truncate_args(args: dict) -> dict:
out = {}
@@ -63,6 +74,8 @@ async def record(
entry = {
"ts": datetime.now().isoformat(timespec="seconds"),
"user": user,
"engine": _audit_engine.get(),
"model": _audit_model.get(),
"tool": tool,
"args": _truncate_args(args),
"status": status,