chore: initial commit of Go API gateway
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]>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
# 2.13 — Anthropic error shape on `/llm/*` (RED)
|
||||
|
||||
Phase: 2 — LLM surfaces
|
||||
Stage: RED
|
||||
Depends on: [2.10](2.10-anthropic-request-translation.md), [4.3](4.3-problem-json-errors.md)
|
||||
|
||||
`/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":"..."}}` and
|
||||
`Content-Type: application/json`
|
||||
- [ ] No `/llm/*` response ever carries `application/problem+json`, and no `/v1/*`
|
||||
response ever carries the Anthropic error shape
|
||||
- [ ] An unknown or missing `model` returns `invalid_request_error` with 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_tokens` returns `invalid_request_error`
|
||||
naming `max_tokens`
|
||||
- [ ] A body that is not valid JSON returns `invalid_request_error` with a message
|
||||
distinguishable from the unknown-model case
|
||||
- [ ] A request for an out-of-scope feature returns `invalid_request_error` naming the
|
||||
feature, for example tools, images or prompt caching
|
||||
- [ ] Exhausting the shared slot queue returns HTTP 429 with error type
|
||||
`rate_limit_error` and a `Retry-After` header
|
||||
- [ ] 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/completions` and `/llm/v1/messages`
|
||||
yields the same HTTP status with the two different body shapes
|
||||
|
||||
## Verify
|
||||
|
||||
```bash
|
||||
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
|
||||
```
|
||||
Reference in New Issue
Block a user