From 4eace88f6b3eacbe51b8fa2b2fdbd2c75580c9c0 Mon Sep 17 00:00:00 2001 From: Michael Nguyen Date: Tue, 28 Jul 2026 14:25:25 -0700 Subject: [PATCH] feat(adapter-claude): add Claude Opus 5 to the static model fallback (#10327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - Agents pick their model from a dropdown in agent config, populated per-adapter by `listAdapterModels()` → each adapter's live provider catalog merged over a static fallback list > - For `claude_local`, newer model ids only reach the dropdown via the live Anthropic `/v1/models` fetch, which needs a server `ANTHROPIC_API_KEY`, a <5s round-trip, non-Bedrock mode, and account entitlement; on any miss it silently falls back to the static `models` array > - Claude Opus 5 (`claude-opus-5`) is generally available — Anthropic lists it as the recommended model for complex agentic coding and enterprise work — but it was absent from that static fallback, so it appeared only when live discovery happened to succeed > - This pull request adds `claude-opus-5` to the `claude_local` static model list so it is selectable regardless of the live-discovery path > - The benefit is a consistent, reliable dropdown that surfaces the current GA Opus flagship without depending on a flaky live fetch ## Linked Issues or Issue Description No public GitHub issue. The bug is described inline following the bug-report template: **What happened** The `claude_local` agent-config model dropdown omitted Claude Opus 5. `claude-opus-5` was missing from the adapter's static fallback `models` array (`packages/adapters/claude-local/src/index.ts`), so it only surfaced when the live Anthropic `/v1/models` discovery happened to succeed. **Expected behavior** Claude Opus 5 is a shipped, generally-available flagship (Anthropic's recommended model for agentic coding) and should always be selectable in the dropdown, independent of whether live discovery succeeds. **Steps to reproduce** 1. Run the server without a working live Anthropic `/v1/models` path (no `ANTHROPIC_API_KEY`, Bedrock mode, a discovery timeout, or a cache miss). 2. Open agent config for a `claude_local` agent and inspect the model dropdown. 3. Observe that `claude-opus-5` is absent because the static fallback list omitted it. **Deployment mode** Self-hosted / local adapter (`claude_local`); the server process reads `ANTHROPIC_API_KEY` from its environment. ## What Changed - Added `{ id: "claude-opus-5", label: "Claude Opus 5" }` to the `claude_local` static `models` fallback. Placed after the current 5-family entries and above the legacy `claude-opus-4-7`, so `claude-opus-4-8` stays the default (index 0) option. - Added an explicit regression assertion in `server/src/__tests__/adapter-models.test.ts` that `claude-opus-5` is present in the `claude_local` fallback when live discovery is unavailable. ## Verification - `pnpm -C server exec vitest run src/__tests__/adapter-models.test.ts` — **17/17 pass**, including the new `claude-opus-5` assertion and the existing `models[0] === "claude-opus-4-8"` default invariant (unaffected — Opus 5 is inserted lower in the list). - Change is a single static-data addition plus a test assertion; no control-flow change. ## Risks - Low risk. Pure additive change to a fallback list; no control-flow change. Worst case is an id a given account isn't entitled to, which the existing "current"/manual-model UI paths already tolerate. - Note for reviewers: a sibling PR adds `claude-sonnet-5` to the same static array (near `claude-opus-4-8`). Both are complementary "refresh the static list to current GA" changes; whichever merges second may need a one-line merge resolution in `packages/adapters/claude-local/src/index.ts` and the matching test assertion block. ## Model Used Claude (Anthropic), model id `claude-opus-4-8` (Opus 4.8), extended thinking + tool use, run as the Paperclip CTO agent. ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes #` / `Refs #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [ ] My branch name describes the change (branch is the assigned execution-workspace branch and cannot be renamed this run) - [x] I have run tests locally and they pass (server adapter-models suite, 17/17) - [x] I have added or updated tests where applicable (explicit `claude-opus-5` fallback assertion) - [x] I have updated relevant documentation to reflect my changes (n/a — no docs reference this list) - [x] I have considered and documented any risks above - [ ] All Paperclip CI gates are green (pending CI) - [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups (pending review) - [x] I will address all Greptile and reviewer comments before requesting merge Co-authored-by: Paperclip --- packages/adapters/claude-local/src/index.ts | 1 + server/src/__tests__/adapter-models.test.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/packages/adapters/claude-local/src/index.ts b/packages/adapters/claude-local/src/index.ts index 5972ad4634..fc20d2eab1 100644 --- a/packages/adapters/claude-local/src/index.ts +++ b/packages/adapters/claude-local/src/index.ts @@ -9,6 +9,7 @@ export const models = [ { id: "claude-opus-4-8", label: "Claude Opus 4.8" }, { id: "claude-fable-5", label: "Claude Fable 5" }, { id: "claude-mythos-5", label: "Claude Mythos 5" }, + { id: "claude-opus-5", label: "Claude Opus 5" }, { id: "claude-opus-4-7", label: "Claude Opus 4.7" }, { id: "claude-opus-4-6", label: "Claude Opus 4.6" }, { id: "claude-sonnet-4-6", label: "Claude Sonnet 4.6" }, diff --git a/server/src/__tests__/adapter-models.test.ts b/server/src/__tests__/adapter-models.test.ts index ba9faa9e0a..f7d28c3116 100644 --- a/server/src/__tests__/adapter-models.test.ts +++ b/server/src/__tests__/adapter-models.test.ts @@ -67,6 +67,8 @@ describe("adapter model listing", () => { expect(models[0]?.id).toBe("claude-opus-4-8"); expect(models.some((model) => model.id === "claude-fable-5")).toBe(true); expect(models.some((model) => model.id === "claude-mythos-5")).toBe(true); + // Opus 5 is a current GA flagship and must be offered even when live discovery is unavailable. + expect(models.some((model) => model.id === "claude-opus-5")).toBe(true); expect(fetchSpy).not.toHaveBeenCalled(); });