Files
homelab-frontend/tasks/2.15-dialect-scope-boundary.md
T

52 lines
2.7 KiB
Markdown
Raw Normal View History

2026-08-19 20:52:13 -07:00
# 2.15 — Anthropic dialect scope boundary (GREEN)
Phase: 2 — LLM surfaces
Stage: GREEN
Depends on: [2.10](2.10-anthropic-request-translation.md), [2.13](2.13-anthropic-error-shape.md)
The only client of `/llm/*` is the first-party riotpiao frontend. It is not Claude
Code and not the Anthropic SDK, so the surface implements a deliberately narrow slice
of the Messages API. The narrowness is the design; the risk is a half-built feature
that appears to work.
- [ ] The unsupported set is enumerated in one place and covers at least: `tools` and
`tool_choice`, `tool_use` blocks, `tool_result` turns, image content blocks,
prompt-caching controls and cache headers, the batch API, and user messages
carrying more than one content block
- [ ] Each unsupported feature is detected during request translation, before any
upstream is contacted
- [ ] Rejection uses the Anthropic error shape
`{"type":"error","error":{"type":"invalid_request_error","message":"..."}}` and
the message names the specific unsupported feature, not just "unsupported"
- [ ] No unsupported feature is silently ignored, stripped, or partially honoured; a
request containing one never produces a 200
- [ ] A request combining a supported and an unsupported field is rejected, not
serviced with the unsupported part dropped
- [ ] The `/v1/*` OpenAI surface is unaffected: tool calling continues to work there
exactly as it does today
- [ ] Every entry in the unsupported set has a test asserting the rejection, so
widening scope forces a deliberate test change rather than a quiet code change
- [ ] The list is documented on the surface, so the frontend can see the boundary
without reading gateway code
Enabling any of these later must be an explicit config or code change accompanied by
its own translation work and tests. A silent partial implementation is the specific
failure this task exists to prevent.
## Verify
```bash
curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
-d '{"model":"reasoning","max_tokens":8,"tools":[{"name":"x"}],"messages":[{"role":"user","content":"hi"}]}'
# expected: 4xx, error.message names tools, no upstream stub hit
curl -s localhost:8080/llm/v1/messages -H 'content-type: application/json' \
-d '{"model":"reasoning","max_tokens":8,"messages":[{"role":"user","content":[{"type":"image","source":{}}]}]}'
# expected: 4xx, error.message names image content blocks, no upstream stub hit
curl -s -o /dev/null -w '%{http_code}\n' localhost:8080/v1/chat/completions \
-H 'content-type: application/json' \
-d '{"model":"reasoning","messages":[{"role":"user","content":"hi"}],"tools":[{"type":"function","function":{"name":"x"}}]}'
# expected: 200, tool calling still works on the OpenAI surface
```