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]>
54 lines
3.0 KiB
Markdown
54 lines
3.0 KiB
Markdown
# 2.10 — Anthropic request translation (GREEN)
|
|
|
|
Phase: 2 — LLM surfaces
|
|
Stage: GREEN
|
|
Depends on: [2.9](2.9-canonical-request-model.md), [2.1](2.1-model-registry.md)
|
|
|
|
`POST /llm/v1/messages` accepts an Anthropic Messages request body and turns it into
|
|
the dialect-neutral canonical request. The path carries `/v1/messages` because the
|
|
Anthropic base-URL convention appends that suffix; the gateway prefix is `/llm`.
|
|
|
|
- [ ] `POST /llm/v1/messages` is accepted and selects its upstream from the body's
|
|
`model` field, using the same registry as `/v1`: `reasoning` reaches
|
|
`reasoning-predictor.llm-serving:80`, `ornith:35b` and `qwen2.5:3b-instruct`
|
|
reach `ornith-predictor.llm-serving:80`
|
|
- [ ] The top-level `system` field becomes the canonical system instruction; it is a
|
|
distinct field in this dialect and is not a member of `messages`
|
|
- [ ] Each message `content` may be a plain string or an array of blocks; a string and
|
|
a single text block carrying the same characters translate identically
|
|
- [ ] `max_tokens` is REQUIRED on this surface, matching the Anthropic contract; a
|
|
request without it is rejected as a client error and no upstream is contacted
|
|
- [ ] `max_tokens` above what the upstream can serve is clamped rather than rejected,
|
|
and the clamp is logged; `reasoning` has `--max-model-len=16384`
|
|
- [ ] Roles are restricted to `user` and `assistant`; any other role, including
|
|
`system` inside `messages`, is a client error naming the offending role
|
|
- [ ] `stop_sequences` becomes the canonical stop sequences, and `stream` becomes the
|
|
canonical streaming flag
|
|
- [ ] `tools`, `tool_choice`, any `tool_use` or `tool_result` block, any `image` block,
|
|
any cache-control marker, and any user message with more than one content block
|
|
are rejected as unsupported, naming the feature; none is silently dropped
|
|
- [ ] Unknown top-level fields are rejected rather than ignored, so a client cannot
|
|
believe an unimplemented option took effect
|
|
- [ ] Reading the body respects the route's configured body size cap
|
|
|
|
`max_tokens` stays optional on `/v1/chat/completions`. The policy is per-surface: each
|
|
dialect keeps its own contract, and the canonical request records whichever value
|
|
resulted.
|
|
|
|
## Verify
|
|
|
|
```bash
|
|
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/llm/v1/messages \
|
|
-H 'content-type: application/json' \
|
|
-d '{"model":"reasoning","max_tokens":64,"system":"be terse","messages":[{"role":"user","content":"hi"}]}'
|
|
# expected: 200, reasoning stub hit, system text present in the upstream request
|
|
|
|
curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
|
|
-d '{"model":"reasoning","messages":[{"role":"user","content":"hi"}]}'
|
|
# expected: 400, body names max_tokens as the missing required field, no upstream stub hit
|
|
|
|
curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
|
|
-d '{"model":"reasoning","max_tokens":8,"messages":[{"role":"system","content":"x"}]}'
|
|
# expected: 400, body names the rejected role, no upstream stub hit
|
|
```
|