Rename v2 auth service to account (#28260)

This commit is contained in:
Dax
2026-05-21 00:53:27 +00:00
committed by GitHub
parent bd41dac88f
commit 8643c0721e
67 changed files with 2541 additions and 1379 deletions
+97 -117
View File
@@ -1,5 +1,5 @@
import { describe, expect } from "bun:test"
import { DateTime, Effect, Fiber, Layer, Option, Stream } from "effect"
import { DateTime, Effect, Layer, Option } from "effect"
import { Catalog } from "@opencode-ai/core/catalog"
import { EventV2 } from "@opencode-ai/core/event"
import { Location } from "@opencode-ai/core/location"
@@ -22,24 +22,20 @@ describe("CatalogV2", () => {
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, (provider) => {
provider.endpoint = {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://default.example.com",
}
provider.options.aisdk.provider.baseURL = "https://override.example.com"
})
yield* load((catalog) =>
catalog.provider.update(providerID, (provider) => {
provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://default.example.com" }
provider.options.aisdk.provider.baseURL = "https://override.example.com"
}),
)
const provider = yield* catalog.provider.get(providerID)
expect(provider.endpoint).toEqual({
expect((yield* catalog.provider.get(providerID)).endpoint).toEqual({
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://override.example.com",
})
expect(provider.options.aisdk.provider.baseURL).toBeUndefined()
}),
)
@@ -48,56 +44,23 @@ describe("CatalogV2", () => {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const modelID = ModelV2.ID.make("model")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, (provider) => {
provider.endpoint = {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://provider.example.com",
}
})
yield* catalog.model.update(providerID, modelID, (model) => {
model.endpoint = {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://model.example.com",
}
model.options.aisdk.provider.baseURL = "https://override.example.com"
yield* load((catalog) => {
catalog.provider.update(providerID, (provider) => {
provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://provider.example.com" }
})
catalog.model.update(providerID, modelID, (model) => {
model.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://model.example.com" }
model.options.aisdk.provider.baseURL = "https://override.example.com"
})
})
const model = yield* catalog.model.get(providerID, modelID)
expect(model.endpoint).toEqual({
expect((yield* catalog.model.get(providerID, modelID)).endpoint).toEqual({
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://override.example.com",
})
expect(model.options.aisdk.provider.baseURL).toBeUndefined()
}),
)
it.effect("publishes model updated events", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const events = yield* EventV2.Service
const providerID = ProviderV2.ID.make("test")
const modelID = ModelV2.ID.make("model")
const fiber = yield* events
.subscribe(Catalog.Event.ModelUpdated)
.pipe(Stream.take(1), Stream.runCollect, Effect.forkScoped)
yield* Effect.yieldNow
yield* catalog.provider.update(providerID, () => {})
yield* catalog.model.update(providerID, modelID, (model) => {
model.name = "Updated Model"
})
const event = Array.from(yield* Fiber.join(fiber))[0]
expect(event?.type).toBe("catalog.model.updated")
expect(event?.data.model.providerID).toBe(providerID)
expect(event?.data.model.id).toBe(modelID)
expect(event?.data.model.name).toBe("Updated Model")
expect(event?.location).toEqual({ directory: "test" })
}),
)
@@ -106,19 +69,16 @@ describe("CatalogV2", () => {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const modelID = ModelV2.ID.make("model")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, (provider) => {
provider.endpoint = {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://provider.example.com",
}
yield* load((catalog) => {
catalog.provider.update(providerID, (provider) => {
provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible", url: "https://provider.example.com" }
})
catalog.model.update(providerID, modelID, () => {})
})
yield* catalog.model.update(providerID, modelID, () => {})
const model = yield* catalog.model.get(providerID, modelID)
expect(model.endpoint).toEqual({
expect((yield* catalog.model.get(providerID, modelID)).endpoint).toEqual({
type: "aisdk",
package: "@ai-sdk/openai-compatible",
url: "https://provider.example.com",
@@ -126,58 +86,82 @@ describe("CatalogV2", () => {
}),
)
it.effect("runs provider hooks after baseURL is normalized", () =>
it.effect("runs catalog transform hooks after baseURL is normalized", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const plugin = yield* PluginV2.Service
const providerID = ProviderV2.ID.make("test")
const seen: unknown[] = []
const load = yield* catalog.loader()
yield* plugin.add({
id: PluginV2.ID.make("test"),
effect: Effect.succeed({
"provider.update": (evt) =>
"catalog.transform": (evt) =>
Effect.sync(() => {
seen.push(evt.provider.endpoint.type)
if (evt.provider.endpoint.type === "aisdk") seen.push(evt.provider.endpoint.url)
seen.push(evt.provider.options.aisdk.provider.baseURL)
const item = evt.data.find((record) => record.provider.id === providerID)
if (!item) return
seen.push(item.provider.endpoint.type)
if (item?.provider.endpoint.type === "aisdk") seen.push(item.provider.endpoint.url)
seen.push(item?.provider.options.aisdk.provider.baseURL)
}),
}),
})
yield* catalog.provider.update(providerID, (provider) => {
provider.endpoint = {
type: "aisdk",
package: "@ai-sdk/openai-compatible",
}
provider.options.aisdk.provider.baseURL = "https://provider.example.com"
})
yield* load((catalog) =>
catalog.provider.update(providerID, (provider) => {
provider.endpoint = { type: "aisdk", package: "@ai-sdk/openai-compatible" }
provider.options.aisdk.provider.baseURL = "https://provider.example.com"
}),
)
expect(seen).toEqual(["aisdk", "https://provider.example.com", undefined])
}),
)
it.effect("runs catalog transform when a plugin is added", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const plugin = yield* PluginV2.Service
const providerID = ProviderV2.ID.make("test")
const load = yield* catalog.loader()
yield* load((catalog) => catalog.provider.update(providerID, (provider) => { provider.name = "Before" }))
yield* plugin.add({
id: PluginV2.ID.make("test-transform"),
effect: Effect.succeed({
"catalog.transform": (evt) => Effect.sync(() => evt.provider.update(providerID, (provider) => { provider.name = "After" })),
}),
})
yield* Effect.yieldNow
expect((yield* catalog.provider.get(providerID)).name).toBe("After")
}),
)
it.effect("resolves provider and model option merges", () =>
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const modelID = ModelV2.ID.make("model")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, (provider) => {
provider.options.headers.provider = "provider"
provider.options.headers.shared = "provider"
provider.options.body.provider = true
provider.options.aisdk.provider.provider = true
})
yield* catalog.model.update(providerID, modelID, (model) => {
model.options.headers.model = "model"
model.options.headers.shared = "model"
model.options.body.model = true
model.options.aisdk.provider.model = true
model.options.aisdk.request.request = true
yield* load((catalog) => {
catalog.provider.update(providerID, (provider) => {
provider.options.headers.provider = "provider"
provider.options.headers.shared = "provider"
provider.options.body.provider = true
provider.options.aisdk.provider.provider = true
})
catalog.model.update(providerID, modelID, (model) => {
model.options.headers.model = "model"
model.options.headers.shared = "model"
model.options.body.model = true
model.options.aisdk.provider.model = true
model.options.aisdk.request.request = true
})
})
const model = yield* catalog.model.get(providerID, modelID)
expect(model.options.headers).toEqual({ provider: "provider", shared: "model", model: "model" })
expect(model.options.body).toEqual({ provider: true, model: true })
expect(model.options.aisdk.provider).toEqual({ provider: true, model: true })
@@ -189,20 +173,15 @@ describe("CatalogV2", () => {
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, (provider) => {
provider.enabled = { via: "custom", data: {} }
})
yield* catalog.model.update(providerID, ModelV2.ID.make("old"), (model) => {
model.time.released = DateTime.makeUnsafe(1000)
})
yield* catalog.model.update(providerID, ModelV2.ID.make("new"), (model) => {
model.time.released = DateTime.makeUnsafe(2000)
yield* load((catalog) => {
catalog.provider.update(providerID, (provider) => { provider.enabled = { via: "custom", data: {} } })
catalog.model.update(providerID, ModelV2.ID.make("old"), (model) => { model.time.released = DateTime.makeUnsafe(1000) })
catalog.model.update(providerID, ModelV2.ID.make("new"), (model) => { model.time.released = DateTime.makeUnsafe(2000) })
})
const model = yield* catalog.model.default()
expect(Option.getOrUndefined(model)?.id).toMatch("new")
expect(Option.getOrUndefined(yield* catalog.model.default())?.id).toMatch("new")
}),
)
@@ -210,24 +189,25 @@ describe("CatalogV2", () => {
Effect.gen(function* () {
const catalog = yield* Catalog.Service
const providerID = ProviderV2.ID.make("test")
const load = yield* catalog.loader()
yield* catalog.provider.update(providerID, () => {})
yield* catalog.model.update(providerID, ModelV2.ID.make("cheap-large"), (model) => {
model.capabilities.input = ["text"]
model.capabilities.output = ["text"]
model.cost = [{ input: 1, output: 1, cache: { read: 0, write: 0 } }]
model.time.released = DateTime.makeUnsafe(Date.now())
})
yield* catalog.model.update(providerID, ModelV2.ID.make("expensive-mini"), (model) => {
model.capabilities.input = ["text"]
model.capabilities.output = ["text"]
model.cost = [{ input: 10, output: 10, cache: { read: 0, write: 0 } }]
model.time.released = DateTime.makeUnsafe(Date.now())
yield* load((catalog) => {
catalog.provider.update(providerID, () => {})
catalog.model.update(providerID, ModelV2.ID.make("cheap-large"), (model) => {
model.capabilities.input = ["text"]
model.capabilities.output = ["text"]
model.cost = [{ input: 1, output: 1, cache: { read: 0, write: 0 } }]
model.time.released = DateTime.makeUnsafe(Date.now())
})
catalog.model.update(providerID, ModelV2.ID.make("expensive-mini"), (model) => {
model.capabilities.input = ["text"]
model.capabilities.output = ["text"]
model.cost = [{ input: 10, output: 10, cache: { read: 0, write: 0 } }]
model.time.released = DateTime.makeUnsafe(Date.now())
})
})
const model = yield* catalog.model.small(providerID)
expect(Option.getOrUndefined(model)?.id).toMatch("expensive-mini")
expect(Option.getOrUndefined(yield* catalog.model.small(providerID))?.id).toMatch("expensive-mini")
}),
)
})