models-dev.test.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import path from "path"
  2. import { describe, expect } from "bun:test"
  3. import { Effect, Layer, Stream } from "effect"
  4. import { Catalog } from "@opencode-ai/core/catalog"
  5. import { Integration } from "@opencode-ai/core/integration"
  6. import { Credential } from "@opencode-ai/core/credential"
  7. import { Database } from "@opencode-ai/core/database/database"
  8. import { EventV2 } from "@opencode-ai/core/event"
  9. import { Flag } from "@opencode-ai/core/flag/flag"
  10. import { Location } from "@opencode-ai/core/location"
  11. import { ModelsDev } from "@opencode-ai/core/models-dev"
  12. import { PluginV2 } from "@opencode-ai/core/plugin"
  13. import { ModelsDevPlugin } from "@opencode-ai/core/plugin/models-dev"
  14. import { Policy } from "@opencode-ai/core/policy"
  15. import { AbsolutePath } from "@opencode-ai/core/schema"
  16. import { location } from "../fixture/location"
  17. import { testEffect } from "../lib/effect"
  18. import { catalogHost, host, integrationHost } from "./host"
  19. const events = EventV2.defaultLayer
  20. const locationLayer = Layer.succeed(
  21. Location.Service,
  22. Location.Service.of(location({ directory: AbsolutePath.make(import.meta.dir) })),
  23. )
  24. const plugins = PluginV2.layer.pipe(Layer.provide(events))
  25. const policy = Policy.layer.pipe(Layer.provide(locationLayer))
  26. const connections = Credential.defaultLayer.pipe(Layer.fresh)
  27. const integrations = Integration.locationLayer.pipe(Layer.provide(events), Layer.provide(connections))
  28. const catalog = Catalog.layer.pipe(
  29. Layer.provide(Layer.mergeAll(events, locationLayer, plugins, policy, connections, integrations)),
  30. )
  31. const layer = Layer.mergeAll(
  32. catalog.pipe(Layer.provide(connections)),
  33. integrations,
  34. connections,
  35. events,
  36. locationLayer,
  37. plugins,
  38. )
  39. const it = testEffect(layer)
  40. describe("ModelsDevPlugin", () => {
  41. it.effect("registers key methods for providers with environment variables", () =>
  42. Effect.acquireUseRelease(
  43. Effect.sync(() => {
  44. const previous = {
  45. path: Flag.OPENCODE_MODELS_PATH,
  46. disabled: Flag.OPENCODE_DISABLE_MODELS_FETCH,
  47. }
  48. Flag.OPENCODE_MODELS_PATH = path.join(import.meta.dir, "fixtures", "models-dev.json")
  49. Flag.OPENCODE_DISABLE_MODELS_FETCH = true
  50. return previous
  51. }),
  52. () =>
  53. Effect.gen(function* () {
  54. const integrations = yield* Integration.Service
  55. const catalog = yield* Catalog.Service
  56. yield* ModelsDevPlugin.effect(
  57. host({
  58. catalog: catalogHost(catalog),
  59. event: { subscribe: () => Stream.never },
  60. integration: integrationHost(integrations),
  61. }),
  62. )
  63. expect(yield* integrations.list()).toEqual([
  64. new Integration.Info({
  65. id: Integration.ID.make("acme"),
  66. name: "Acme",
  67. methods: [
  68. { type: "key" },
  69. {
  70. type: "env",
  71. names: ["ACME_API_KEY"],
  72. },
  73. ],
  74. connections: [],
  75. }),
  76. ])
  77. }).pipe(Effect.provide(ModelsDev.defaultLayer)),
  78. (previous) =>
  79. Effect.sync(() => {
  80. Flag.OPENCODE_MODELS_PATH = previous.path
  81. Flag.OPENCODE_DISABLE_MODELS_FETCH = previous.disabled
  82. }),
  83. ),
  84. )
  85. })