provider.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. export * as ConfigProviderPlugin from "./provider"
  2. import { define } from "../../plugin/internal"
  3. import { Effect } from "effect"
  4. import { Config } from "../../config"
  5. import { ModelV2 } from "../../model"
  6. import { ProviderV2 } from "../../provider"
  7. export const Plugin = define({
  8. id: "config-provider",
  9. effect: Effect.fn(function* (ctx) {
  10. const config = yield* Config.Service
  11. yield* ctx.integration.transform(
  12. Effect.fn(function* (integrations) {
  13. const files = (yield* config.entries()).filter((entry): entry is Config.Document => entry.type === "document")
  14. const configuredIntegrations = new Set(
  15. files.flatMap((file) =>
  16. Object.entries(file.info.providers ?? {}).flatMap(([id, provider]) =>
  17. provider.env === undefined ? [] : [id],
  18. ),
  19. ),
  20. )
  21. for (const file of files) {
  22. for (const [id, item] of Object.entries(file.info.providers ?? {})) {
  23. const integrationID = id
  24. if (!configuredIntegrations.has(id) && !integrations.get(integrationID)) continue
  25. integrations.update(integrationID, (integration) => {
  26. integration.name = item.name ?? integration.name
  27. })
  28. if (item.env !== undefined) {
  29. integrations.method.update({
  30. integrationID,
  31. method: { type: "env", names: [...item.env] },
  32. })
  33. }
  34. }
  35. }
  36. }),
  37. )
  38. yield* ctx.catalog.transform(
  39. Effect.fn(function* (catalog) {
  40. const entries = yield* config.entries()
  41. const files = entries.filter((entry): entry is Config.Document => entry.type === "document")
  42. const configuredDefault = Config.latest(entries, "model")
  43. if (configuredDefault !== undefined) {
  44. const model = ModelV2.parse(configuredDefault)
  45. catalog.model.default.set(model.providerID, model.modelID)
  46. }
  47. for (const file of files) {
  48. for (const [id, item] of Object.entries(file.info.providers ?? {})) {
  49. const providerID = id
  50. catalog.provider.update(providerID, (provider) => {
  51. if (item.name !== undefined) provider.name = item.name
  52. if (item.api !== undefined) provider.api = { ...item.api }
  53. if (item.request !== undefined) {
  54. Object.assign(provider.request.headers, item.request.headers)
  55. Object.assign(provider.request.body, item.request.body)
  56. }
  57. })
  58. for (const [id, config] of Object.entries(item.models ?? {})) {
  59. catalog.model.update(providerID, id, (model) => {
  60. if (config.family !== undefined) model.family = config.family
  61. if (config.name !== undefined) model.name = config.name
  62. if (config.api !== undefined) model.api = { ...model.api, ...config.api }
  63. if (config.capabilities !== undefined) {
  64. model.capabilities = {
  65. tools: config.capabilities.tools,
  66. input: [...config.capabilities.input],
  67. output: [...config.capabilities.output],
  68. }
  69. }
  70. if (config.request !== undefined) {
  71. Object.assign(model.request.headers, config.request.headers)
  72. Object.assign(model.request.body, config.request.body)
  73. if (config.request.variant !== undefined) model.request.variant = config.request.variant
  74. }
  75. if (config.variants !== undefined) {
  76. for (const variant of config.variants) {
  77. let existing = model.variants.find((item) => item.id === variant.id)
  78. if (!existing) {
  79. existing = {
  80. id: variant.id,
  81. headers: {},
  82. body: {},
  83. }
  84. model.variants.push(existing)
  85. }
  86. Object.assign(existing.headers, variant.headers)
  87. Object.assign(existing.body, variant.body)
  88. }
  89. }
  90. if (config.cost !== undefined) {
  91. model.cost = (Array.isArray(config.cost) ? config.cost : [config.cost]).map((cost) => ({
  92. tier: cost.tier && { ...cost.tier },
  93. input: cost.input,
  94. output: cost.output,
  95. cache: {
  96. read: cost.cache?.read ?? 0,
  97. write: cost.cache?.write ?? 0,
  98. },
  99. }))
  100. }
  101. if (config.disabled !== undefined) model.enabled = !config.disabled
  102. if (config.limit !== undefined) model.limit = { ...model.limit, ...config.limit }
  103. })
  104. }
  105. }
  106. }
  107. }),
  108. )
  109. }),
  110. })