Make the component library a standalone product door (2.63.0).
Add /api/library datasheet import and component GET/PUT with no exam. Reorganize pytest into datasheet, library, schematic, PCB, and AF+AI. Document Rust criteria (none chosen; no rustup) and coding conformity.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"""Tests for the Anthropic cache_control breakpoint cap.
|
||||
|
||||
Anthropic rejects requests with >4 cache_control blocks. The review path adds
|
||||
one per cacheable PDF excerpt, so a hub IC fetching two interface excerpts hit
|
||||
5 (system + initial PDF + initial context + 2 excerpts) and the API returned
|
||||
"A maximum of 4 blocks with cache_control may be provided. Found 5." The
|
||||
provider caps message-block breakpoints so system(1) + messages never exceed 4.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from backend.services.llm.anthropic_provider import _enforce_cache_breakpoint_limit
|
||||
|
||||
|
||||
def _cc(block: dict) -> bool:
|
||||
return "cache_control" in block
|
||||
|
||||
|
||||
def _count(messages: list[dict]) -> int:
|
||||
return sum(_cc(b) for m in messages for b in m["content"])
|
||||
|
||||
|
||||
def _ephemeral() -> dict:
|
||||
return {"cache_control": {"type": "ephemeral"}}
|
||||
|
||||
|
||||
def test_u2_two_excerpts_capped_to_three():
|
||||
"""The exact failure: initial PDF + context + 2 excerpts = 4 message
|
||||
breakpoints (5 with system). Cap to 3 so the total lands at 4."""
|
||||
initial_pdf = {"type": "document", "source": {}, **_ephemeral()}
|
||||
initial_text = {"type": "text", "text": "ctx", **_ephemeral()}
|
||||
excerpt1 = {"type": "document", "source": {}, **_ephemeral()}
|
||||
excerpt2 = {"type": "document", "source": {}, **_ephemeral()}
|
||||
messages = [
|
||||
{"role": "user", "content": [initial_pdf, initial_text]},
|
||||
{"role": "assistant", "content": [{"type": "tool_use", "id": "a", "name": "x", "input": {}}]},
|
||||
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": "a", "content": "."}, excerpt1]},
|
||||
{"role": "assistant", "content": [{"type": "tool_use", "id": "b", "name": "x", "input": {}}]},
|
||||
{"role": "user", "content": [{"type": "tool_result", "tool_use_id": "b", "content": "."}, excerpt2]},
|
||||
]
|
||||
|
||||
_enforce_cache_breakpoint_limit(messages)
|
||||
|
||||
assert _count(messages) == 3 # +1 system = 4 total, within the limit
|
||||
# The stable full-datasheet anchor and the two most recent excerpts survive;
|
||||
# the initial context block (cheap to reprocess) loses its breakpoint.
|
||||
assert _cc(initial_pdf)
|
||||
assert not _cc(initial_text)
|
||||
assert _cc(excerpt1)
|
||||
assert _cc(excerpt2)
|
||||
|
||||
|
||||
def test_heavy_fanout_keeps_anchor_and_tail():
|
||||
"""A heavy-fanout review (many excerpts) still caps to 3 and always keeps
|
||||
the first cacheable block (the full-datasheet anchor)."""
|
||||
anchor = {"type": "document", "source": {}, **_ephemeral()}
|
||||
messages = [{"role": "user", "content": [anchor, {"type": "text", "text": "x", **_ephemeral()}]}]
|
||||
excerpts = []
|
||||
for _ in range(6):
|
||||
ex = {"type": "document", "source": {}, **_ephemeral()}
|
||||
excerpts.append(ex)
|
||||
messages.append({"role": "user", "content": [ex]})
|
||||
|
||||
_enforce_cache_breakpoint_limit(messages)
|
||||
|
||||
assert _count(messages) == 3
|
||||
assert _cc(anchor)
|
||||
# Two most-recent excerpts retained for incremental tail caching.
|
||||
assert _cc(excerpts[-1]) and _cc(excerpts[-2])
|
||||
|
||||
|
||||
def test_under_limit_untouched():
|
||||
"""Three or fewer message breakpoints are left exactly as-is."""
|
||||
pdf = {"type": "document", "source": {}, **_ephemeral()}
|
||||
text = {"type": "text", "text": "x", **_ephemeral()}
|
||||
messages = [{"role": "user", "content": [pdf, text]}]
|
||||
|
||||
_enforce_cache_breakpoint_limit(messages)
|
||||
|
||||
assert _cc(pdf) and _cc(text)
|
||||
assert _count(messages) == 2
|
||||
Reference in New Issue
Block a user