hermes: normalize Switchyard Codex inputs
This commit is contained in:
parent
ac61725dee
commit
a7feed5dba
@ -25,7 +25,7 @@ spec:
|
||||
ai.bstein.dev/execution: Hermes Kanban with durable direct Codex and Claude Code CLI workers
|
||||
ai.bstein.dev/model-policy: Jetson-assisted AUTO routing, low through xhigh, cross-provider fallback
|
||||
ai.bstein.dev/placement: rpi5 preferred; Jetson deferred until state storage is available
|
||||
ai.bstein.dev/config-rev: "20260811-image-routing"
|
||||
ai.bstein.dev/config-rev: "20260811-switchyard-responses-input"
|
||||
vault.hashicorp.com/agent-inject: "true"
|
||||
vault.hashicorp.com/role: hermes-agent
|
||||
vault.hashicorp.com/agent-inject-secret-anthropic-token: kv/data/atlas/hermes/agent-tokens
|
||||
|
||||
@ -105,6 +105,25 @@ def _validate_payload(payload: Any) -> dict[str, Any]:
|
||||
if not model.startswith("gpt-"):
|
||||
raise ValueError("unsupported Codex model")
|
||||
payload["model"] = model
|
||||
response_input = payload.get("input")
|
||||
if isinstance(response_input, str):
|
||||
if not response_input.strip():
|
||||
raise ValueError("non-empty Responses input required")
|
||||
# Switchyard accepts OpenAI Chat Completions requests and translates
|
||||
# their final text to a scalar Responses input. The first-party Codex
|
||||
# endpoint is stricter than the public Responses API and only accepts
|
||||
# a list of typed input items.
|
||||
payload["input"] = [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{"type": "input_text", "text": response_input}],
|
||||
}
|
||||
]
|
||||
elif isinstance(response_input, dict):
|
||||
payload["input"] = [response_input]
|
||||
elif not isinstance(response_input, list) or not response_input:
|
||||
raise ValueError("non-empty Responses input list required")
|
||||
# Tenant conversations must not enter the owner's server-side history.
|
||||
payload["store"] = False
|
||||
payload["stream"] = True
|
||||
|
||||
@ -499,16 +499,48 @@ def test_codex_broker_auth_and_request_contract(tmp_path: Path, monkeypatch):
|
||||
assert module._authorized("Bearer wrong") is False
|
||||
assert module._real_model("route/codex/gpt-5.6-sol/xhigh") == "gpt-5.6-sol"
|
||||
payload = module._validate_payload(
|
||||
{"model": "gpt-5.6-terra", "store": True, "stream": False}
|
||||
{
|
||||
"model": "gpt-5.6-terra",
|
||||
"input": "route this chat turn",
|
||||
"store": True,
|
||||
"stream": False,
|
||||
}
|
||||
)
|
||||
assert payload["store"] is False
|
||||
assert payload["stream"] is True
|
||||
assert payload["input"] == [
|
||||
{
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{"type": "input_text", "text": "route this chat turn"}],
|
||||
}
|
||||
]
|
||||
response_item = {
|
||||
"type": "message",
|
||||
"role": "user",
|
||||
"content": [{"type": "input_text", "text": "keep this item"}],
|
||||
}
|
||||
assert module._validate_payload(
|
||||
{"model": "gpt-5.6-terra", "input": response_item}
|
||||
)["input"] == [response_item]
|
||||
response_items = [response_item]
|
||||
assert module._validate_payload(
|
||||
{"model": "gpt-5.6-terra", "input": response_items}
|
||||
)["input"] is response_items
|
||||
routed = module._validate_payload(
|
||||
{"model": "route/codex/gpt-5.6-luna/low", "stream": False}
|
||||
{
|
||||
"model": "route/codex/gpt-5.6-luna/low",
|
||||
"input": "use the low route",
|
||||
"stream": False,
|
||||
}
|
||||
)
|
||||
assert routed["model"] == "gpt-5.6-luna"
|
||||
with pytest.raises(ValueError, match="unsupported Codex model"):
|
||||
module._validate_payload({"model": "unapproved-model"})
|
||||
module._validate_payload({"model": "unapproved-model", "input": "hello"})
|
||||
with pytest.raises(ValueError, match="non-empty Responses input"):
|
||||
module._validate_payload({"model": "gpt-5.6-terra", "input": ""})
|
||||
with pytest.raises(ValueError, match="non-empty Responses input list"):
|
||||
module._validate_payload({"model": "gpt-5.6-terra", "input": []})
|
||||
|
||||
auth_dir = tmp_path / ".codex"
|
||||
auth_dir.mkdir()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user