provider-anthropic.test.ts 3.5 KB

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