1
0

provider-options.test.ts 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. import { describe, expect, test } from "bun:test"
  2. import { ConfigProviderOptionsV1 } from "@opencode-ai/core/v1/config/provider-options"
  3. describe("ConfigProviderOptionsV1", () => {
  4. test("keeps raw provider and request options unchanged", () => {
  5. const lowerer = ConfigProviderOptionsV1.get("custom-provider")
  6. expect(lowerer.provider({ apiKey: "secret", headers: { "x-test": "1" }, nested: { camelCase: true } })).toEqual({
  7. body: { apiKey: "secret", headers: { "x-test": "1" }, nested: { camelCase: true } },
  8. })
  9. expect(lowerer.request({ nested: { camelCase: true } })).toEqual({ nested: { camelCase: true } })
  10. })
  11. test("falls back to raw lowering for prototype property package names", () => {
  12. expect(ConfigProviderOptionsV1.get("toString").provider({ enabled: true })).toEqual({ body: { enabled: true } })
  13. })
  14. test("lowers OpenAI provider and request options", () => {
  15. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/openai")
  16. expect(
  17. lowerer.provider({
  18. apiKey: "secret",
  19. baseURL: "https://openai.example/v1",
  20. organization: "org",
  21. project: "project",
  22. headers: { "x-test": "1" },
  23. body: { store: true },
  24. timeout: 1000,
  25. }),
  26. ).toEqual({
  27. url: "https://openai.example/v1",
  28. headers: {
  29. Authorization: "Bearer secret",
  30. "OpenAI-Organization": "org",
  31. "OpenAI-Project": "project",
  32. "x-test": "1",
  33. },
  34. body: { store: true },
  35. settings: { timeout: 1000 },
  36. })
  37. expect(
  38. lowerer.request({
  39. reasoningEffort: "high",
  40. reasoningSummary: "auto",
  41. reasoning: { encryptedContent: true },
  42. textVerbosity: "low",
  43. text: { outputFormat: "plain" },
  44. nestedValue: { camelCase: true },
  45. }),
  46. ).toEqual({
  47. reasoning: { encrypted_content: true, effort: "high", summary: "auto" },
  48. text: { output_format: "plain", verbosity: "low" },
  49. nested_value: { camel_case: true },
  50. })
  51. })
  52. test("lowers Anthropic provider and request options", () => {
  53. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/anthropic")
  54. expect(
  55. lowerer.provider({
  56. apiKey: "secret",
  57. authToken: "token",
  58. baseURL: "https://anthropic.example",
  59. headers: { "x-test": "1" },
  60. body: { beta: true },
  61. generateId: "custom",
  62. }),
  63. ).toEqual({
  64. url: "https://anthropic.example",
  65. headers: { "x-api-key": "secret", Authorization: "Bearer token", "x-test": "1" },
  66. body: { beta: true },
  67. settings: { generateId: "custom" },
  68. })
  69. expect(
  70. lowerer.request({
  71. effort: "high",
  72. taskBudget: 1024,
  73. metadata: { userId: "user", traceId: "trace" },
  74. nestedValue: { camelCase: true },
  75. }),
  76. ).toEqual({
  77. output_config: { effort: "high", task_budget: 1024 },
  78. metadata: { user_id: "user", trace_id: "trace" },
  79. nested_value: { camel_case: true },
  80. })
  81. })
  82. test("lowers Google provider and request options", () => {
  83. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/google")
  84. expect(
  85. lowerer.provider({
  86. apiKey: "secret",
  87. baseURL: "https://google.example",
  88. headers: { "x-test": "1" },
  89. body: { trace: true },
  90. project: "project",
  91. }),
  92. ).toEqual({
  93. url: "https://google.example",
  94. headers: { "x-goog-api-key": "secret", "x-test": "1" },
  95. body: { trace: true },
  96. settings: { project: "project" },
  97. })
  98. expect(
  99. lowerer.request({
  100. thinkingConfig: { thinkingBudget: 1024 },
  101. responseModalities: ["TEXT"],
  102. mediaResolution: "high",
  103. imageConfig: { aspectRatio: "16:9" },
  104. safetySettings: ["safe"],
  105. }),
  106. ).toEqual({
  107. safetySettings: ["safe"],
  108. generationConfig: {
  109. thinkingConfig: { thinkingBudget: 1024 },
  110. responseModalities: ["TEXT"],
  111. mediaResolution: "high",
  112. imageConfig: { aspectRatio: "16:9" },
  113. },
  114. })
  115. })
  116. test("lowers Azure provider options and uses OpenAI request lowering", () => {
  117. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/azure")
  118. expect(
  119. lowerer.provider({
  120. apiKey: "secret",
  121. baseURL: "https://azure.example",
  122. headers: { "x-test": "1" },
  123. body: { trace: true },
  124. resourceName: "resource",
  125. }),
  126. ).toEqual({
  127. url: "https://azure.example",
  128. headers: { "api-key": "secret", "x-test": "1" },
  129. body: { trace: true },
  130. settings: { resourceName: "resource" },
  131. })
  132. expect(lowerer.request({ reasoningEffort: "high", reasoningSummary: "auto", textVerbosity: "low" })).toEqual({
  133. reasoning: { effort: "high", summary: "auto" },
  134. text: { verbosity: "low" },
  135. })
  136. })
  137. test("lowers Amazon Bedrock provider and request options", () => {
  138. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/amazon-bedrock")
  139. expect(
  140. lowerer.provider({
  141. headers: { "x-test": "1" },
  142. body: { trace: true },
  143. region: "us-east-1",
  144. profile: "dev",
  145. }),
  146. ).toEqual({
  147. headers: { "x-test": "1" },
  148. body: { trace: true },
  149. settings: { region: "us-east-1", profile: "dev" },
  150. })
  151. expect(lowerer.request({ temperature: 0.2 })).toEqual({
  152. additionalModelRequestFields: { temperature: 0.2 },
  153. })
  154. })
  155. test("lowers OpenAI-compatible provider and request options", () => {
  156. const lowerer = ConfigProviderOptionsV1.get("@ai-sdk/openai-compatible")
  157. expect(
  158. lowerer.provider({
  159. baseURL: "https://compatible.example/v1",
  160. headers: { "x-test": "1" },
  161. body: { trace: true },
  162. apiKey: "secret",
  163. }),
  164. ).toEqual({
  165. url: "https://compatible.example/v1",
  166. headers: { "x-test": "1" },
  167. body: { trace: true },
  168. settings: { apiKey: "secret" },
  169. })
  170. expect(lowerer.request({ reasoningEffort: "high", serviceTier: "priority" })).toEqual({
  171. reasoning_effort: "high",
  172. serviceTier: "priority",
  173. })
  174. })
  175. test.each([
  176. "@ai-sdk/cerebras",
  177. "@ai-sdk/deepinfra",
  178. "@ai-sdk/groq",
  179. "@ai-sdk/mistral",
  180. "@ai-sdk/togetherai",
  181. "@ai-sdk/xai",
  182. "@openrouter/ai-sdk-provider",
  183. "ai-gateway-provider",
  184. "venice-ai-sdk-provider",
  185. ])("uses OpenAI-compatible lowering for %s", (packageName) => {
  186. const lowerer = ConfigProviderOptionsV1.get(packageName)
  187. expect(lowerer.provider({ baseURL: "https://example.test", apiKey: "secret" })).toEqual({
  188. url: "https://example.test",
  189. headers: undefined,
  190. body: undefined,
  191. settings: { apiKey: "secret" },
  192. })
  193. expect(lowerer.request({ reasoningEffort: "high" })).toEqual({ reasoning_effort: "high" })
  194. })
  195. test.each(["@ai-sdk/google-vertex", "@ai-sdk/google-vertex/anthropic"])(
  196. "uses provider family lowering for %s",
  197. (packageName) => {
  198. const lowerer = ConfigProviderOptionsV1.get(packageName)
  199. expect(lowerer.provider({ baseURL: "https://example.test", profile: "dev" })).toMatchObject({
  200. url: "https://example.test",
  201. settings: { profile: "dev" },
  202. })
  203. },
  204. )
  205. })