Baseline for the Kong replacement on api.riotpiao.com. Brings the working tree under version control for the first time: gateway source, the task board that drives the agent runs, test fixtures, and K8s manifests. Anchor the gateway ignore rule to the repo root. Unanchored, "gateway" also matched the cmd/gateway/ source directory, so the program entrypoint was excluded from every commit. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
2.6 KiB
2.6 KiB
2.13 — Anthropic error shape on /llm/* (RED)
Phase: 2 — LLM surfaces Stage: RED Depends on: 2.10, 4.3
/v1/* renders rejections as RFC 9457 application/problem+json. /llm/* must not.
The same underlying rejection gets two renderings, chosen purely by which surface
received the request. Write the failing tests against both renderings first.
- Every error response from a
/llm/*path has the body{"type":"error","error":{"type":"...","message":"..."}}andContent-Type: application/json - No
/llm/*response ever carriesapplication/problem+json, and no/v1/*response ever carries the Anthropic error shape - An unknown or missing
modelreturnsinvalid_request_errorwith a message naming the rejected value and listing the configured model names, derived from the registry rather than hardcoded - A request missing the required
max_tokensreturnsinvalid_request_errornamingmax_tokens - A body that is not valid JSON returns
invalid_request_errorwith a message distinguishable from the unknown-model case - A request for an out-of-scope feature returns
invalid_request_errornaming the feature, for example tools, images or prompt caching - Exhausting the shared slot queue returns HTTP 429 with error type
rate_limit_errorand aRetry-Afterheader - An upstream failure or timeout returns HTTP 5xx with error type
api_error, and the message leaks no upstream host, port or internal path - No rejection reaches an upstream, and none falls back to a default model
- Each rejection is logged with its reason and its surface; the request body is never logged
- The same malformed request sent to
/v1/chat/completionsand/llm/v1/messagesyields the same HTTP status with the two different body shapes
Verify
curl -s -i localhost:8080/llm/v1/messages -H 'content-type: application/json' \
-d '{"model":"gpt-4","max_tokens":8,"messages":[]}'
# expected: 4xx, content-type application/json, body {"type":"error","error":{"type":"invalid_request_error",...}}
# listing reasoning, ornith:35b, qwen2.5:3b-instruct
curl -s -i localhost:8080/llm/v1/messages -H 'content-type: application/json' -d 'not json' \
| grep -i 'content-type'
# expected: application/json, never application/problem+json
curl -s -i localhost:8080/v1/chat/completions -H 'content-type: application/json' \
-d '{"model":"gpt-4","messages":[]}' | grep -i 'content-type'
# expected: application/problem+json, confirming the two surfaces render differently