feat(platform): close AI expense value loop
Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
@@ -39,7 +39,9 @@ def test_runtime_chat_fails_over_to_backup_before_retrying_main(monkeypatch) ->
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_completion(config, messages, *, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_completion(
|
||||
config, messages, *, max_tokens, temperature, timeout_seconds
|
||||
):
|
||||
del messages, max_tokens, temperature, timeout_seconds
|
||||
calls.append(config["slot"])
|
||||
if config["slot"] == "main":
|
||||
@@ -70,7 +72,9 @@ def test_runtime_chat_complete_with_trace_records_slot_failover(monkeypatch) ->
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_completion(config, messages, *, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_completion(
|
||||
config, messages, *, max_tokens, temperature, timeout_seconds
|
||||
):
|
||||
del messages, max_tokens, temperature, timeout_seconds
|
||||
if config["slot"] == "main":
|
||||
raise RuntimeError("incorrect api key")
|
||||
@@ -104,7 +108,9 @@ def test_runtime_chat_does_not_rehit_failed_slots_during_cooldown(monkeypatch) -
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_completion(config, messages, *, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_completion(
|
||||
config, messages, *, max_tokens, temperature, timeout_seconds
|
||||
):
|
||||
del messages, max_tokens, temperature, timeout_seconds
|
||||
calls.append(config["slot"])
|
||||
raise RuntimeError("unavailable")
|
||||
@@ -134,7 +140,7 @@ def test_runtime_chat_disables_glm_thinking_for_direct_user_answers(monkeypatch)
|
||||
|
||||
monkeypatch.setattr("app.services.runtime_chat._send_json_request", fake_send_json_request)
|
||||
|
||||
answer = service._request_openai_compatible(
|
||||
provider_response = service._request_openai_compatible(
|
||||
provider="GLM",
|
||||
endpoint="https://open.bigmodel.cn/api/paas/v4/",
|
||||
model="glm-5.1",
|
||||
@@ -145,7 +151,7 @@ def test_runtime_chat_disables_glm_thinking_for_direct_user_answers(monkeypatch)
|
||||
timeout_seconds=17,
|
||||
)
|
||||
|
||||
assert answer == "ok"
|
||||
assert provider_response.output == "ok"
|
||||
assert captured["payload"]["thinking"] == {"type": "disabled"}
|
||||
assert captured["timeout_seconds"] == 17
|
||||
|
||||
@@ -184,7 +190,7 @@ def test_runtime_chat_openai_compatible_tool_call_payload(monkeypatch) -> None:
|
||||
|
||||
monkeypatch.setattr("app.services.runtime_chat._send_json_request", fake_send_json_request)
|
||||
|
||||
tool_call = service._request_openai_compatible_tool_call(
|
||||
provider_response = service._request_openai_compatible_tool_call(
|
||||
provider="OpenAI Compatible",
|
||||
endpoint="https://api.example.com/v1",
|
||||
model="gpt-test",
|
||||
@@ -197,12 +203,16 @@ def test_runtime_chat_openai_compatible_tool_call_payload(monkeypatch) -> None:
|
||||
timeout_seconds=19,
|
||||
)
|
||||
|
||||
tool_call = provider_response.output
|
||||
assert tool_call is not None
|
||||
assert tool_call.name == "submit_steward_intent_plan"
|
||||
assert tool_call.arguments == {"tasks": []}
|
||||
assert captured["url"] == "https://api.example.com/v1/chat/completions"
|
||||
assert captured["payload"]["tools"][0]["function"]["name"] == "submit_steward_intent_plan"
|
||||
assert captured["payload"]["tool_choice"]["function"]["name"] == "submit_steward_intent_plan"
|
||||
assert (
|
||||
captured["payload"]["tool_choice"]["function"]["name"]
|
||||
== "submit_steward_intent_plan"
|
||||
)
|
||||
assert captured["headers"]["Authorization"] == "Bearer secret"
|
||||
|
||||
|
||||
@@ -222,7 +232,9 @@ def test_runtime_chat_supports_single_pass_fast_failover(monkeypatch) -> None:
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_completion(config, messages, *, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_completion(
|
||||
config, messages, *, max_tokens, temperature, timeout_seconds
|
||||
):
|
||||
del messages, max_tokens, temperature
|
||||
calls.append((config["slot"], timeout_seconds))
|
||||
raise RuntimeError("unavailable")
|
||||
@@ -242,7 +254,9 @@ def test_runtime_chat_supports_single_pass_fast_failover(monkeypatch) -> None:
|
||||
assert calls == [("main", 8), ("backup", 20)]
|
||||
|
||||
|
||||
def test_runtime_chat_complete_with_tool_call_fails_over_to_backup_before_retrying_main(monkeypatch) -> None:
|
||||
def test_runtime_chat_tool_call_fails_over_to_backup_before_retrying_main(
|
||||
monkeypatch,
|
||||
) -> None:
|
||||
_clear_runtime_chat_cooldown()
|
||||
session_factory = build_session_factory()
|
||||
with session_factory() as db:
|
||||
@@ -258,7 +272,16 @@ def test_runtime_chat_complete_with_tool_call_fails_over_to_backup_before_retryi
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_tool_call(config, messages, *, tools, tool_choice, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_tool_call(
|
||||
config,
|
||||
messages,
|
||||
*,
|
||||
tools,
|
||||
tool_choice,
|
||||
max_tokens,
|
||||
temperature,
|
||||
timeout_seconds,
|
||||
):
|
||||
del messages, tools, tool_choice, max_tokens, temperature, timeout_seconds
|
||||
calls.append(config["slot"])
|
||||
if config["slot"] == "main":
|
||||
@@ -302,7 +325,9 @@ def test_runtime_chat_skips_slot_during_cooldown(monkeypatch) -> None:
|
||||
"apiKey": "secret",
|
||||
}
|
||||
|
||||
def fake_request_chat_completion(config, messages, *, max_tokens, temperature, timeout_seconds):
|
||||
def fake_request_chat_completion(
|
||||
config, messages, *, max_tokens, temperature, timeout_seconds
|
||||
):
|
||||
del messages, max_tokens, temperature, timeout_seconds
|
||||
calls.append(config["slot"])
|
||||
if config["slot"] == "main":
|
||||
@@ -312,8 +337,14 @@ def test_runtime_chat_skips_slot_during_cooldown(monkeypatch) -> None:
|
||||
monkeypatch.setattr(service, "_load_chat_slot", fake_load_chat_slot)
|
||||
monkeypatch.setattr(service, "_request_chat_completion", fake_request_chat_completion)
|
||||
|
||||
assert service.complete([{"role": "user", "content": "hello"}], max_attempts=1) == "backup answer"
|
||||
assert service.complete([{"role": "user", "content": "hello again"}], max_attempts=1) == "backup answer"
|
||||
first = service.complete(
|
||||
[{"role": "user", "content": "hello"}], max_attempts=1
|
||||
)
|
||||
second = service.complete(
|
||||
[{"role": "user", "content": "hello again"}], max_attempts=1
|
||||
)
|
||||
assert first == "backup answer"
|
||||
assert second == "backup answer"
|
||||
assert calls == ["main", "backup", "backup"]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user