Files
Artemis-Eapil/artemis/llm/cache_affinity.py
chenmingxuan 2328a4df0c fix: improve cross-device evidence and exploration lifecycle
Align Responses cache affinity across execution and summary calls, preserve required checks and evidence uncertainty, and allow safe deletion of inactive explorations while retaining independent reruns.

Validation: backend suite passed except intentional prompt golden drift, then all 17 transcript tests passed after snapshot refresh; 268 frontend tests and production build passed; Ruff, quality ratchet and core type checks passed.
2026-10-17 19:43:20 +08:00

41 lines
1.7 KiB
Python

"""Per-conversation routing hints shared by agent and auxiliary Responses calls."""
from collections.abc import Mapping
import hashlib
import re
from typing import Any
from uuid import UUID
def cache_affinity_options(
ctx: Any, role: str | None, model_name: str | None, options: dict | None = None
) -> dict:
"""Keep body and header routing keys aligned without changing model defaults.
An exploration survives multiple execution sessions. Each model role keeps
its own cache scope so background summaries do not compete with the agent.
Set hints per call: raw models/HTTP clients may be shared by concurrent tasks.
Explicit caller keys and headers take precedence (including underscore aliases).
"""
result = dict(options or {})
engine = getattr(ctx, "data_engine", None)
session = getattr(ctx, "exploration_id", None) or getattr(engine, "current_session_id", None)
if isinstance(session, (str, UUID)) and str(session):
identity = f"{session}:{role or 'model'}:{model_name}"
result.setdefault(
"prompt_cache_key", "artemis:" + hashlib.sha256(identity.encode()).hexdigest()[:40]
)
key = result.get("prompt_cache_key")
if not isinstance(key, str) or not re.fullmatch(r"[-0-9A-Za-z._:]{1,128}", key):
return result
existing = result.get("extra_headers")
if existing is not None and not isinstance(existing, Mapping):
return result
headers = dict(existing or {})
names = {name.lower().replace("_", "-") for name in headers}
for name in ("Thread-Id", "Session-Id"):
if name.lower() not in names:
headers[name] = key
result["extra_headers"] = headers
return result