models.test.ts 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. import { expect, test } from "bun:test"
  2. import { CopilotModels } from "@opencode-ai/core/github-copilot/models"
  3. import { ModelV2 } from "@opencode-ai/core/model"
  4. import { ProviderV2 } from "@opencode-ai/core/provider"
  5. test("defensively syncs advertised Copilot models", async () => {
  6. const server = Bun.serve({
  7. port: 0,
  8. fetch: () =>
  9. Response.json({
  10. data: [
  11. {
  12. model_picker_enabled: true,
  13. id: "gpt-5",
  14. name: "GPT-5 remote",
  15. version: "gpt-5-2026-06-01",
  16. supported_endpoints: ["/responses"],
  17. billing: {
  18. token_prices: {
  19. batch_size: 0,
  20. default: { input_price: 10, output_price: 20, cache_price: 5 },
  21. },
  22. },
  23. capabilities: {
  24. family: "gpt",
  25. limits: {
  26. max_context_window_tokens: 200000,
  27. max_output_tokens: 16384,
  28. max_prompt_tokens: 180000,
  29. },
  30. supports: { tool_calls: true, reasoning_effort: ["low", "high"] },
  31. },
  32. },
  33. {
  34. model_picker_enabled: false,
  35. id: "utility",
  36. name: "Utility",
  37. version: "utility-2026-06-01",
  38. capabilities: {
  39. family: "utility",
  40. limits: { max_output_tokens: 1000, max_prompt_tokens: 8000 },
  41. supports: { tool_calls: false },
  42. },
  43. },
  44. { model_picker_enabled: true, id: "incomplete" },
  45. ],
  46. }),
  47. })
  48. try {
  49. const existing = ModelV2.Info.make({
  50. ...ModelV2.Info.empty(ProviderV2.ID.githubCopilot, ModelV2.ID.make("gpt-5")),
  51. modelID: ModelV2.ID.make("gpt-5"),
  52. name: "GPT-5 local",
  53. })
  54. const stale = ModelV2.Info.make({
  55. ...ModelV2.Info.empty(ProviderV2.ID.githubCopilot, ModelV2.ID.make("stale")),
  56. modelID: ModelV2.ID.make("stale"),
  57. })
  58. const models = await CopilotModels.get(server.url.origin, {}, [existing, stale])
  59. const model = models.get(ModelV2.ID.make("gpt-5"))
  60. expect(model?.name).toBe("GPT-5 local")
  61. expect(model?.settings).toMatchObject({ baseURL: server.url.origin, endpoint: "responses" })
  62. expect(model?.cost[0]).toMatchObject({ input: 0, output: 0, cache: { read: 0, write: 0 } })
  63. expect(model?.variants.map((variant) => variant.id)).toEqual([
  64. ModelV2.VariantID.make("low"),
  65. ModelV2.VariantID.make("high"),
  66. ])
  67. expect(models.get(ModelV2.ID.make("utility"))?.enabled).toBe(false)
  68. expect(models.has(ModelV2.ID.make("stale"))).toBe(false)
  69. expect(models.has(ModelV2.ID.make("incomplete"))).toBe(false)
  70. } finally {
  71. await server.stop(true)
  72. }
  73. })