feat: add gateway client with env-driven assembly
Includes config aggregation for multi-source env keys, from_env and from_settings factories with explicit shared-backend injection, gather_bounded, top-level exports, tightened import-linter layers with the gate removed from the Makefile, and the finalized .env.example.
This commit is contained in:
+42
-16
@@ -15,12 +15,21 @@ _MSGS = [{"role": "user", "content": "hi"}]
|
||||
|
||||
|
||||
def _resp(content="cached", **overrides):
|
||||
base = dict(
|
||||
content=content, thinking="", model="m", provider="p",
|
||||
prompt_tokens=1, completion_tokens=2, latency_ms=30,
|
||||
ttft_ms=5.0, max_inter_token_ms=2.0, cache_hit=False, call_id="orig",
|
||||
source_name="s1", usage_source="measured",
|
||||
)
|
||||
base = {
|
||||
"content": content,
|
||||
"thinking": "",
|
||||
"model": "m",
|
||||
"provider": "p",
|
||||
"prompt_tokens": 1,
|
||||
"completion_tokens": 2,
|
||||
"latency_ms": 30,
|
||||
"ttft_ms": 5.0,
|
||||
"max_inter_token_ms": 2.0,
|
||||
"cache_hit": False,
|
||||
"call_id": "orig",
|
||||
"source_name": "s1",
|
||||
"usage_source": "measured",
|
||||
}
|
||||
base.update(overrides)
|
||||
return LLMResponse(**base)
|
||||
|
||||
@@ -46,21 +55,33 @@ class TestKeyFormula:
|
||||
|
||||
def test_multimodal_part_digested_not_inlined(self):
|
||||
big_b64 = "data:image/png;base64," + "A" * 1_000_000
|
||||
messages = [{"role": "user", "content": [
|
||||
{"type": "image_url", "image_url": {"url": big_b64}},
|
||||
{"type": "text", "text": "describe"},
|
||||
]}]
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "image_url", "image_url": {"url": big_b64}},
|
||||
{"type": "text", "text": "describe"},
|
||||
],
|
||||
}
|
||||
]
|
||||
digested = digest_messages(messages)
|
||||
payload = json.dumps(digested, ensure_ascii=False)
|
||||
assert len(payload) < 500 # 大图不进 canonical_json
|
||||
expected = hashlib.sha256(big_b64.encode()).hexdigest()
|
||||
assert expected in payload # 但字节变化仍改变 key
|
||||
# 图像字节变化 → key 变
|
||||
messages2 = [{"role": "user", "content": [
|
||||
{"type": "image_url", "image_url": {"url": big_b64[:-1] + "B"}},
|
||||
{"type": "text", "text": "describe"},
|
||||
]}]
|
||||
assert build_cache_key("m", messages, "p", None) != build_cache_key("m", messages2, "p", None)
|
||||
messages2 = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{"type": "image_url", "image_url": {"url": big_b64[:-1] + "B"}},
|
||||
{"type": "text", "text": "describe"},
|
||||
],
|
||||
}
|
||||
]
|
||||
assert build_cache_key("m", messages, "p", None) != build_cache_key(
|
||||
"m", messages2, "p", None
|
||||
)
|
||||
|
||||
|
||||
class _Terminal:
|
||||
@@ -76,7 +97,12 @@ class _Terminal:
|
||||
|
||||
|
||||
def _mw(backend, **kwargs):
|
||||
defaults = dict(backend=backend, model_fingerprint="m", default_namespace="proj", ttl_s=3600)
|
||||
defaults = {
|
||||
"backend": backend,
|
||||
"model_fingerprint": "m",
|
||||
"default_namespace": "proj",
|
||||
"ttl_s": 3600,
|
||||
}
|
||||
defaults.update(kwargs)
|
||||
return CacheMW(**defaults)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user