feat(models): add Claude Opus 5 and repoint the opus alias to it (#192)

* feat(models): add Claude Opus 5 and repoint the `opus` alias to it

Adds `claude-opus-5` to models.json (the SPOT) and moves the `opus` alias
from `claude-opus-4-8` to it. `/v1/models` goes 6 -> 7; OpenClaw picks the
new entry up on the next `ocp update` via scripts/sync-openclaw.mjs.

server.mjs is NOT modified by this PR — models.json is the single source of
truth (ADR 0003) and every consumer (server.mjs MODEL_MAP, setup.mjs,
sync-openclaw.mjs, ocp-connect) derives from it. ocp-connect needs no change
either: its metadata table matches on the `claude-opus` FAMILY prefix, which
`claude-opus-5` hits (the guard added in PR #152 review).

Alignment evidence. The claim "the CLI itself defaults opus -> claude-opus-5"
is verified from the compiled CLI binary 2.1.220 via `strings`, the same
protocol used for #152/#168:

    latest_per_family:{fable:"claude-fable-5",opus:"claude-opus-5",
                       sonnet:"claude-sonnet-5",haiku:"claude-haiku-4-5"}

The same registry entry gives context:{window:1e6,native_1m:true},
max_output_tokens:{default:64000,upper:128000} and pricing:"tier_5_25" --
i.e. identical $5/$25 per MTok to Opus 4.8, so the alias repoint carries no
cost change. Availability confirmed with a live subscription-pool completion
(`claude -p --model claude-opus-5` -> "OK"). This mirrors #168 (sonnet ->
sonnet-5), which established the precedent that following the CLI's own
latest_per_family is the correct default behavior.

contextWindow is deliberately 200000, not the native 1M:

1. MAX_PROMPT_CHARS is a SINGLE GLOBAL budget, not per-model.
   derivePromptCharBudget (lib/prompt.mjs) returns
   `max(floor, max(...contextWindows) * 3)` across ALL entries, so a 1M entry
   would lift the truncation ceiling to 3,000,000 chars for
   claude-haiku-4-5-20251001 as well -- genuinely a 200k-native model --
   turning clean OCP-side truncation into an upstream API rejection.
2. OpenClaw scales its history budget linearly off this value:
   contextWindow * maxHistoryShare * SAFETY_MARGIN (= x0.6), plus an
   oversized-message threshold at x0.5 (compaction-planning, OpenClaw
   2026.7.1). Its own bundled registry hardcodes 200000 for Claude models,
   and the upstream request to raise it to 1M (openclaw#22979) was closed
   "not planned" -- 1M needs a beta header its compaction path omits.

Raising the window for real requires per-model budgets and is ADR-level;
a new regression test pins the invariant so that change has to be deliberate.

Tests: 452 passed, 0 failed. Three mutations verified to bite:
  - revert aliases.opus -> 4-8            => 1 failure (opus-alias SPOT)
  - delete the claude-opus-5 entry        => 2 failures (presence + dangling alias)
  - set its contextWindow to 1000000      => 2 failures (invariant + budget SPOT)

E2E on an isolated port (:3999, prod on :3456 untouched and verified so):
/v1/models returns 7 ids with claude-opus-5 first; a request with
model:"opus" logs event=claude_spawned model=claude-opus-5 tier=opus and
returns a real completion. Derived MAX_PROMPT_CHARS stays 600000.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gbqUZ8HfBZpjjbzQ85oH8

* fix(docs,test): restore the dropped Opus 4.8 line; assert the window CEILING

Two review findings from the independent Iron-Rule-10 reviewer, both confirmed
before applying:

1. docs/lan-mode.md: the sample `ocp update` output lost `ocp/claude-opus-4-8`
   entirely — the edit substituted the id instead of inserting the new one, so
   the block listed 6 bullets while line 219 of the same document claims
   "7 models available". Self-contradictory. Restored; the block is 7 again.

2. test-features.mjs: "every contextWindow is 200000" was too rigid and
   contradicted ADR 0009, which states the budget "scales automatically — no
   code change". Asserting every entry turned that documented no-code-change
   path into a must-edit-tests path, and would have failed on a future entry
   with a legitimately SMALLER window. Now asserts the MAX instead: raising the
   ceiling (the actual hazard, since the budget is global) still fails, while a
   smaller-window model stays legal.

Verified the reformulation is strictly better, not just different:
  - raise a window to 1000000  -> 2 failures (ceiling + derivePromptCharBudget SPOT)
  - add a legitimate 128k model -> 452 passed, 0 failed   (old test would have failed here)

Tests: 452 passed, 0 failed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017gbqUZ8HfBZpjjbzQ85oH8

---------

Co-authored-by: dtzp555 <dtzp555@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
dtzp555-max
2026-07-27 07:37:31 +10:00
committed by GitHub
co-authored by taodeng Claude Opus 5
parent 9f6707ee9d
commit fdd6dadf96
5 changed files with 50 additions and 10 deletions
+6 -5
View File
@@ -78,7 +78,7 @@ Run `ocp lan` to see your IP and ready-to-share instructions.
**Verify:**
```bash
curl http://127.0.0.1:3456/v1/models
# Returns: claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-5, claude-sonnet-4-6, claude-haiku-4-5-20251001
# Returns: claude-opus-5, claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-5, claude-sonnet-4-6, claude-haiku-4-5-20251001
```
### Headless install notes
@@ -114,7 +114,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/README.md
installed and logged in (`claude auth status`). Install missing pieces
using my system's package manager.
2. git clone the repo, cd in, and run `node setup.mjs`.
3. Verify with `curl http://127.0.0.1:3456/v1/models` (should list 6 models).
3. Verify with `curl http://127.0.0.1:3456/v1/models` (should list 7 models).
4. Add `export OPENAI_BASE_URL=http://127.0.0.1:3456/v1` to my shell rc.
5. Tell me to reload my shell and try a tool like Cline / Continue / Cursor.
@@ -141,7 +141,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/docs/lan-mode.md
5. Add OCP_ADMIN_KEY to my shell rc (~/.zshrc or ~/.bashrc).
6. Run `ocp lan` to show me the LAN IP and connect command.
7. Optionally create example keys: `ocp keys add laptop`, `ocp keys add tablet`.
8. Verify: `curl http://127.0.0.1:3456/v1/models` returns 6 models.
8. Verify: `curl http://127.0.0.1:3456/v1/models` returns 7 models.
Tell me each step before running it. On error, diagnose before retrying.
```
@@ -163,7 +163,7 @@ Please follow https://github.com/dtzp555-max/ocp/blob/main/docs/lan-mode.md
chmod +x ocp-connect
2. Run `./ocp-connect <SERVER_IP>` (add `--key <KEY>` if you have one).
3. Follow any IDE-specific manual hints it prints.
4. Verify: `curl http://<SERVER_IP>:3456/v1/models` returns 6 models.
4. Verify: `curl http://<SERVER_IP>:3456/v1/models` returns 7 models.
5. Tell me to reload my shell + restart any IDE that was already running.
Don't auto-retry on error. Tell me the failure mode first.
@@ -216,7 +216,7 @@ OCP Connect v1.3.0
(set by admin via PROXY_ANONYMOUS_KEY; see issue #12 §14 Path A)
Testing API access...
✓ API accessible (6 models available)
✓ API accessible (7 models available)
Shell config:
✓ .bashrc
@@ -246,6 +246,7 @@ OCP Connect v1.3.0
✓ OpenClaw configured
Provider: ocp
Models:
• ocp/claude-opus-5
• ocp/claude-opus-4-8
• ocp/claude-opus-4-7
• ocp/claude-opus-4-6