1
0

provider-anthropic.test.ts 3.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import { AISDK } from "@opencode-ai/core/aisdk"
  2. import { describe, expect } from "bun:test"
  3. import { Effect } from "effect"
  4. import { Catalog } from "@opencode-ai/core/catalog"
  5. import { ModelV2 } from "@opencode-ai/core/model"
  6. import { PluginV2 } from "@opencode-ai/core/plugin"
  7. import { PluginHost } from "@opencode-ai/core/plugin/host"
  8. import { AnthropicPlugin } from "@opencode-ai/core/plugin/provider/anthropic"
  9. import { ProviderV2 } from "@opencode-ai/core/provider"
  10. import { testEffect } from "../lib/effect"
  11. import { PluginTestLayer } from "./fixture"
  12. const it = testEffect(PluginTestLayer)
  13. const addPlugin = Effect.fn(function* () {
  14. const plugin = yield* PluginV2.Service
  15. const aisdk = yield* AISDK.Service
  16. const host = yield* PluginHost.make(plugin)
  17. yield* AnthropicPlugin.effect(host)
  18. })
  19. function required<T>(value: T | undefined): T {
  20. if (value === undefined) throw new Error("Expected value")
  21. return value
  22. }
  23. describe("AnthropicPlugin", () => {
  24. it.effect("applies legacy beta headers", () =>
  25. Effect.gen(function* () {
  26. const catalog = yield* Catalog.Service
  27. yield* catalog.transform((catalog) => {
  28. const item = ProviderV2.Info.make({
  29. ...ProviderV2.Info.empty(ProviderV2.ID.anthropic),
  30. api: { type: "aisdk", package: "@ai-sdk/anthropic" },
  31. request: { headers: { Existing: "1" }, body: {} },
  32. })
  33. catalog.provider.update(item.id, (draft) => {
  34. draft.api = item.api
  35. draft.request = item.request
  36. })
  37. })
  38. yield* addPlugin()
  39. expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).request.headers["anthropic-beta"]).toBe(
  40. "interleaved-thinking-2025-05-14,fine-grained-tool-streaming-2025-05-14",
  41. )
  42. expect(required(yield* catalog.provider.get(ProviderV2.ID.anthropic)).request.headers.Existing).toBe("1")
  43. }),
  44. )
  45. it.effect("ignores non-Anthropic providers", () =>
  46. Effect.gen(function* () {
  47. const catalog = yield* Catalog.Service
  48. yield* catalog.transform((catalog) => catalog.provider.update(ProviderV2.ID.openai, () => {}))
  49. yield* addPlugin()
  50. expect(
  51. required(yield* catalog.provider.get(ProviderV2.ID.openai)).request.headers["anthropic-beta"],
  52. ).toBeUndefined()
  53. }),
  54. )
  55. it.effect("creates Anthropic SDKs with the model provider ID as the SDK name", () =>
  56. Effect.gen(function* () {
  57. const plugin = yield* PluginV2.Service
  58. const aisdk = yield* AISDK.Service
  59. yield* addPlugin()
  60. const result = yield* aisdk.runSDK({
  61. model: ModelV2.Info.make({
  62. ...ModelV2.Info.empty(ProviderV2.ID.make("custom-anthropic"), ModelV2.ID.make("claude-sonnet-4-5")),
  63. api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
  64. }),
  65. package: "@ai-sdk/anthropic",
  66. options: { name: "custom-anthropic", apiKey: "test" },
  67. })
  68. expect(result.sdk.languageModel("claude-sonnet-4-5").provider).toBe("custom-anthropic")
  69. }),
  70. )
  71. it.effect("uses the Anthropic provider ID as the SDK name for the bundled Anthropic provider", () =>
  72. Effect.gen(function* () {
  73. const plugin = yield* PluginV2.Service
  74. const aisdk = yield* AISDK.Service
  75. yield* addPlugin()
  76. const result = yield* aisdk.runSDK({
  77. model: ModelV2.Info.make({
  78. ...ModelV2.Info.empty(ProviderV2.ID.anthropic, ModelV2.ID.make("claude-sonnet-4-5")),
  79. api: { id: ModelV2.ID.make("claude-sonnet-4-5"), type: "aisdk", package: "@ai-sdk/anthropic" },
  80. }),
  81. package: "@ai-sdk/anthropic",
  82. options: { name: "anthropic", apiKey: "test" },
  83. })
  84. expect(result.sdk.languageModel("claude-sonnet-4-5").provider).toBe("anthropic")
  85. }),
  86. )
  87. })