provider-package.test.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. import { describe, expect, test } from "bun:test"
  2. import { model } from "@opencode-ai/llm/providers/openai"
  3. describe("provider package entrypoints", () => {
  4. test("semantic API aliases expose the same contract", async () => {
  5. const modules = await Promise.all([
  6. import("@opencode-ai/llm/providers/openai"),
  7. import("@opencode-ai/llm/providers/openai/responses"),
  8. import("@opencode-ai/llm/providers/openai/chat"),
  9. import("@opencode-ai/llm/providers/anthropic"),
  10. import("@opencode-ai/llm/providers/openai-compatible"),
  11. import("@opencode-ai/llm/providers/amazon-bedrock"),
  12. import("@opencode-ai/llm/providers/azure"),
  13. import("@opencode-ai/llm/providers/azure/responses"),
  14. import("@opencode-ai/llm/providers/azure/chat"),
  15. import("@opencode-ai/llm/providers/google"),
  16. ])
  17. for (const module of modules) expect(module.model).toBeFunction()
  18. expect(modules[0].model).toBe(modules[1].model)
  19. expect(modules[6].model).toBe(modules[7].model)
  20. })
  21. test("maps package settings onto the executable model", () => {
  22. const selected = model("gpt-5", {
  23. apiKey: "fixture",
  24. baseURL: "https://api.openai.test/v1",
  25. headers: { "x-application": "opencode" },
  26. body: { service_tier: "priority" },
  27. limits: { context: 200_000, output: 64_000 },
  28. unrelatedInheritedSetting: true,
  29. })
  30. expect(selected.route.id).toBe("openai-responses")
  31. expect(selected.route.defaults.headers).toEqual({ "x-application": "opencode" })
  32. expect(selected.route.defaults.http?.body).toEqual({ service_tier: "priority" })
  33. expect(selected.route.defaults.limits).toEqual({ context: 200_000, output: 64_000 })
  34. })
  35. test("selects transport without changing the semantic API", () => {
  36. expect(model("gpt-5", { apiKey: "fixture" }).route.id).toBe("openai-responses")
  37. expect(model("gpt-5", { apiKey: "fixture", transport: "websocket" }).route.id).toBe("openai-responses-websocket")
  38. })
  39. test("maps legacy OpenAI organization and project settings to headers", () => {
  40. const selected = model("gpt-5", {
  41. apiKey: "fixture",
  42. organization: "org_123",
  43. project: "proj_123",
  44. })
  45. expect(selected.route.defaults.headers).toMatchObject({
  46. "OpenAI-Organization": "org_123",
  47. "OpenAI-Project": "proj_123",
  48. })
  49. })
  50. test("selects Azure API entrypoints with the same model contract", async () => {
  51. const Azure = await import("@opencode-ai/llm/providers/azure")
  52. const AzureChat = await import("@opencode-ai/llm/providers/azure/chat")
  53. const AzureResponses = await import("@opencode-ai/llm/providers/azure/responses")
  54. const settings = {
  55. apiKey: "fixture",
  56. resourceName: "opencode-test",
  57. headers: { "x-application": "opencode" },
  58. body: { service_tier: "priority" },
  59. limits: { context: 200_000, output: 64_000 },
  60. }
  61. const responses = AzureResponses.model("deployment", settings)
  62. const chat = AzureChat.model("deployment", settings)
  63. expect(Azure.model("deployment", settings).route.id).toBe("azure-openai-responses")
  64. expect(responses.route.id).toBe("azure-openai-responses")
  65. expect(responses.route.endpoint.baseURL).toBe("https://opencode-test.openai.azure.com/openai/v1")
  66. expect(responses.route.defaults.headers).toEqual({ "x-application": "opencode" })
  67. expect(responses.route.defaults.http?.body).toEqual({ service_tier: "priority" })
  68. expect(responses.route.defaults.limits).toEqual({ context: 200_000, output: 64_000 })
  69. expect(chat.route.id).toBe("azure-openai-chat")
  70. })
  71. test("maps Google package settings onto the Gemini model", async () => {
  72. const Google = await import("@opencode-ai/llm/providers/google")
  73. const selected = Google.model("gemini-2.5-flash", {
  74. apiKey: "fixture",
  75. baseURL: "https://generativelanguage.test/v1beta",
  76. headers: { "x-application": "opencode" },
  77. body: { safetySettings: [] },
  78. limits: { context: 1_000_000, output: 65_536 },
  79. providerOptions: { gemini: { thinkingConfig: { thinkingBudget: 1_024 } } },
  80. })
  81. expect(selected.route.id).toBe("gemini")
  82. expect(selected.route.endpoint.baseURL).toBe("https://generativelanguage.test/v1beta")
  83. expect(selected.route.defaults.headers).toEqual({ "x-application": "opencode" })
  84. expect(selected.route.defaults.http?.body).toEqual({ safetySettings: [] })
  85. expect(selected.route.defaults.limits).toEqual({ context: 1_000_000, output: 65_536 })
  86. expect(selected.route.defaults.providerOptions).toEqual({
  87. gemini: { thinkingConfig: { thinkingBudget: 1_024 } },
  88. })
  89. })
  90. })