github-copilot.ts 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import { AuthOptions, type ProviderAuthOption } from "../route/auth-options"
  2. import type { RouteDefaultsInput } from "../route/client"
  3. import { ProviderID, type ModelID } from "../schema"
  4. import * as OpenAIChat from "../protocols/openai-chat"
  5. import * as OpenAIResponses from "../protocols/openai-responses"
  6. import { withOpenAIOptions, type OpenAIProviderOptionsInput } from "./openai-options"
  7. export const id = ProviderID.make("github-copilot")
  8. // GitHub Copilot has no canonical public URL — callers (opencode, etc.) must
  9. // supply `baseURL` explicitly.
  10. export type ModelOptions = Omit<RouteDefaultsInput, "providerOptions"> &
  11. ProviderAuthOption<"optional"> & {
  12. readonly baseURL: string
  13. readonly providerOptions?: OpenAIProviderOptionsInput
  14. }
  15. export const shouldUseResponsesApi = (modelID: string | ModelID) => {
  16. const model = String(modelID)
  17. const match = /^gpt-(\d+)/.exec(model)
  18. if (!match) return false
  19. return Number(match[1]) >= 5 && !model.startsWith("gpt-5-mini")
  20. }
  21. export const routes = [OpenAIResponses.route, OpenAIChat.route]
  22. const chatRoute = OpenAIChat.route.with({ provider: id })
  23. const responsesRoute = OpenAIResponses.route.with({ provider: id })
  24. const defaults = (options: ModelOptions) => {
  25. const { apiKey: _, auth: _auth, baseURL: _baseURL, ...rest } = options
  26. return rest
  27. }
  28. const configuredResponsesRoute = (options: ModelOptions) =>
  29. responsesRoute.with({
  30. endpoint: { baseURL: options.baseURL },
  31. auth: AuthOptions.bearer(options, []),
  32. })
  33. const configuredChatRoute = (options: ModelOptions) =>
  34. chatRoute.with({
  35. endpoint: { baseURL: options.baseURL },
  36. auth: AuthOptions.bearer(options, []),
  37. })
  38. export const configure = (options: ModelOptions) => {
  39. const responsesRoute = configuredResponsesRoute(options)
  40. const chatRoute = configuredChatRoute(options)
  41. const responses = (modelID: string | ModelID) =>
  42. responsesRoute.with(withOpenAIOptions(modelID, defaults(options))).model({ id: modelID })
  43. const chat = (modelID: string | ModelID) =>
  44. chatRoute.with(withOpenAIOptions(modelID, defaults(options))).model({ id: modelID })
  45. return {
  46. id,
  47. model: (modelID: string | ModelID) => (shouldUseResponsesApi(modelID) ? responses(modelID) : chat(modelID)),
  48. responses,
  49. chat,
  50. configure,
  51. }
  52. }
  53. export const provider = {
  54. id,
  55. configure,
  56. }