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.
41 lines
1.7 KiB
Python
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
|