Skip to content

Commit 9d568ef

Browse files
test(session): cover isAnthropicReasoningModel and tighten provider match
Address review on #30046: - Extract MessageV2.isAnthropicReasoningModel and replace the broad providerID.includes("anthropic") with exact provider IDs (anthropic, google-vertex-anthropic) plus ai-sdk npm checks, consistent with how provider.ts/transform.ts detect Anthropic. - Add focused unit tests: first-party, google-vertex-anthropic, the @ai-sdk/* npm packages, negative cases (openai/google/openrouter), and a regression test that a provider merely containing "anthropic" is not matched. test/session/message-v2.test.ts: 41 pass / 0 fail.
1 parent 70abf52 commit 9d568ef

2 files changed

Lines changed: 36 additions & 4 deletions

File tree

packages/opencode/src/session/message-v2.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,10 +377,7 @@ export const toModelMessagesEffect = Effect.fnUntraced(function* (
377377
// lives in part.metadata, so unlike text/tool metadata it must be preserved
378378
// even when differentModel is true (fallback model switches, variant changes,
379379
// or proxy setups where the persisted providerID differs from the live one).
380-
const isAnthropicReasoning =
381-
model.providerID === "anthropic" ||
382-
model.providerID.includes("anthropic") ||
383-
model.api?.npm === "@ai-sdk/anthropic"
380+
const isAnthropicReasoning = isAnthropicReasoningModel(model)
384381
if (differentModel && !isAnthropicReasoning) {
385382
if (part.text.trim().length > 0)
386383
assistantMessage.parts.push({

packages/opencode/test/session/message-v2.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,3 +1658,38 @@ describe("session.message-v2.latest", () => {
16581658
expect(state.tasks[0]).toMatchObject({ type: "compaction", auto: true })
16591659
})
16601660
})
1661+
1662+
describe("session.message-v2.isAnthropicReasoningModel", () => {
1663+
test("matches first-party Anthropic provider", () => {
1664+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "anthropic" })).toBe(true)
1665+
})
1666+
1667+
test("matches Google Vertex Anthropic provider", () => {
1668+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "google-vertex-anthropic" })).toBe(true)
1669+
})
1670+
1671+
test("matches by ai-sdk npm package", () => {
1672+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "custom", api: { npm: "@ai-sdk/anthropic" } })).toBe(true)
1673+
expect(
1674+
MessageV2.isAnthropicReasoningModel({ providerID: "custom", api: { npm: "@ai-sdk/google-vertex/anthropic" } }),
1675+
).toBe(true)
1676+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "custom", api: { npm: "@ai-sdk/amazon-bedrock" } })).toBe(
1677+
true,
1678+
)
1679+
})
1680+
1681+
test("does not match non-Anthropic providers", () => {
1682+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "openai" })).toBe(false)
1683+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "google" })).toBe(false)
1684+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "openrouter", api: { npm: "@openrouter/ai-sdk-provider" } })).toBe(
1685+
false,
1686+
)
1687+
})
1688+
1689+
test("does not loosely match providers that merely contain 'anthropic'", () => {
1690+
// regression: a previous version used providerID.includes("anthropic"),
1691+
// which would wrongly match a hypothetical "not-anthropic" provider.
1692+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "not-anthropic-router" })).toBe(false)
1693+
expect(MessageV2.isAnthropicReasoningModel({ providerID: "anthropic-compatible-proxy" })).toBe(false)
1694+
})
1695+
})

0 commit comments

Comments
 (0)