* feat(models): add Claude Sonnet 5 to models.json SPOT
Adds `claude-sonnet-5` (the latest Sonnet, supported by claude CLI >= 2.1.206)
to models.json — the single source of truth (ADR 0003). Both the /v1/models
endpoint and setup.mjs OpenClaw registration derive from it automatically.
- New model entry `claude-sonnet-5` (reasoning, 200k ctx, 16k max tokens),
mirroring the existing Sonnet entry shape.
- Point the `sonnet` alias at `claude-sonnet-5` (newest Sonnet), consistent
with `opus` -> `claude-opus-4-8`. Previous `claude-sonnet-4-6` is retained
for pinning.
- README "Available Models" table updated (release-kit 5.3).
- Update the aliases.sonnet SPOT test to the new default.
Endpoint class: B.1 (/v1/models), data-only via the models.json SPOT.
Authorized by ADR 0006 (OpenAI shim scope) + ADR 0003 (models.json SPOT).
Verified: `claude --model claude-sonnet-5 -p` returns a valid response on a
current subscription CLI (2.1.206); npm test green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(models): make PR #152 purely additive + close ocp-connect drift + real SPOT test
Addresses the maintainer's review. Rescopes this PR to the additive change only —
adding claude-sonnet-5 to models.json — and defers the `sonnet` alias repoint to
its own PR per Iron Rule 11 (the alias is the default for every request that omits
`model`; repointing it is a behavior change that deserves separate review + a
CHANGELOG entry). No server.mjs change, so no cli.js citation required.
Metadata confirmed unchanged: contextWindow 200000 / maxTokens 16384 stay, per the
maintainer's correction (OCP truncates at MAX_PROMPT_CHARS, and contextWindow feeds
OpenClaw's compaction budget — advertising a larger window than OCP delivers just
makes OpenClaw overshoot).
Fixes vs review:
1. Reverted `aliases.sonnet` back to claude-sonnet-4-6 — this PR only *adds* the
model; the repoint ships separately. README updated to match (5 is available by
full ID; 4-6 remains the alias default).
2. Replaced the tautological SPOT test. The old assertion read a literal out of
models.json and asserted it equalled the same literal — it passed even with a
dangling alias. Added referential-integrity tests: every aliases/legacyAliases
value must resolve to a real models[].id, plus an explicit assertion that
claude-sonnet-5 exists in models[]. This is the guard that actually catches an
alias pointing at a non-existent model (VALID_MODELS keys on alias names, never
targets, so nothing else checks this).
3. Fixed ocp-connect classification drift. Its prefix table pinned "claude-sonnet-4",
which misses "claude-sonnet-5" and falls through to the non-reasoning / 8k-output
default. Broadened both the model_meta and alias_prefixes tables to family
prefixes (claude-opus / claude-sonnet / claude-haiku) so any future versioned ID
classifies correctly with no per-model edit. /v1/models does not expose
reasoning/maxTokens (OpenAI /v1/models schema has no such fields — adding them
would be a Rule 2 invention), so family classification stays in ocp-connect.
primary_model stays claude-sonnet-4-6, matching the (unchanged) sonnet alias — it
moves with the alias in the repoint PR.
Tests: 266 passed, 0 failed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: vvlasy-openclaw <vvlasy@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>