mirror of
https://github.com/anomalyco/opencode.git
synced 2026-10-27 21:13:50 +00:00
feat(core): let custom models in config set a model type (#59388)
This commit is contained in:
parent
804a7f3c01
commit
a697f53611
7 changed files with 71 additions and 1 deletions
1
packages/client/src/promise/generated/types.ts
generated
1
packages/client/src/promise/generated/types.ts
generated
|
|
@ -2306,6 +2306,7 @@ export type ConfigEntry =
|
|||
models?: {
|
||||
[x: string]: {
|
||||
modelID?: string
|
||||
type?: ModelType
|
||||
family?: string
|
||||
name?: string
|
||||
releaseDate?: string
|
||||
|
|
|
|||
|
|
@ -217,6 +217,7 @@ function overlay(
|
|||
if (item.package !== undefined) model.package = undefined
|
||||
if (item.settings?.baseURL !== undefined && model.settings) delete model.settings.baseURL
|
||||
}
|
||||
if (config.type !== undefined) model.type = config.type
|
||||
if (config.family !== undefined) model.family = config.family
|
||||
if (config.name) model.name = config.name
|
||||
if (config.modelID !== undefined) model.modelID = config.modelID
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ export const register = Effect.fn("OpencodeLegacy.register")(function* (
|
|||
const base = source?.models.get(config.modelID ?? modelID) ?? source?.models.get(modelID)
|
||||
providers.models.update(providerID, modelID, (model) => {
|
||||
Object.assign(model, structuredClone(base ?? model))
|
||||
if (config.type !== undefined) model.type = config.type
|
||||
if (config.family !== undefined) model.family = config.family
|
||||
if (config.name !== undefined) model.name = config.name
|
||||
if (config.modelID !== undefined) model.modelID = config.modelID
|
||||
|
|
|
|||
|
|
@ -397,6 +397,68 @@ describe("ConfigProviderPlugin.Plugin", () => {
|
|||
}),
|
||||
)
|
||||
|
||||
it.effect("lists a custom model by its configured type and an untyped one as chat", () =>
|
||||
Effect.gen(function* () {
|
||||
const models = yield* Model.Service
|
||||
const entries = [
|
||||
new Document({
|
||||
type: "document",
|
||||
info: decode({
|
||||
providers: {
|
||||
custom: {
|
||||
package: "aisdk:@ai-sdk/openai-compatible",
|
||||
models: { chat: {}, painter: { type: "image" } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
]
|
||||
|
||||
yield* addPlugin(entries)
|
||||
|
||||
expect((yield* models.available()).map((model) => model.id)).toEqual([Model.ID.make("chat")])
|
||||
expect((yield* models.available(["image"])).map((model) => model.id)).toEqual([Model.ID.make("painter")])
|
||||
expect(yield* models.get(Provider.ID.make("custom"), Model.ID.make("painter"))).toBeUndefined()
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("lets config change a catalog model's type and keeps it when unset", () =>
|
||||
Effect.gen(function* () {
|
||||
const providers = yield* Provider.Service
|
||||
const models = yield* Model.Service
|
||||
const providerID = Provider.ID.make("custom")
|
||||
const retypedID = Model.ID.make("retyped")
|
||||
const keptID = Model.ID.make("kept")
|
||||
yield* providers.transform((editor) => {
|
||||
editor.models.update(providerID, retypedID, () => {})
|
||||
editor.models.update(providerID, keptID, (model) => {
|
||||
model.type = "decision"
|
||||
})
|
||||
})
|
||||
const entries = [
|
||||
new Document({
|
||||
type: "document",
|
||||
info: decode({
|
||||
providers: {
|
||||
custom: {
|
||||
package: "aisdk:@ai-sdk/openai-compatible",
|
||||
models: { retyped: { type: "image" }, kept: { name: "Kept" } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
}),
|
||||
]
|
||||
|
||||
yield* addPlugin(entries)
|
||||
|
||||
expect(yield* models.available()).toEqual([])
|
||||
expect((yield* models.available(["image"])).map((model) => model.id)).toEqual([retypedID])
|
||||
expect((yield* models.available(["decision"])).map((model) => [model.id, model.name])).toEqual([
|
||||
[keptID, "Kept"],
|
||||
])
|
||||
}),
|
||||
)
|
||||
|
||||
it.effect("preserves catalog capabilities unless config overrides them", () =>
|
||||
Effect.gen(function* () {
|
||||
const providers = yield* Provider.Service
|
||||
|
|
|
|||
3
packages/protocol/openapi.json
generated
3
packages/protocol/openapi.json
generated
|
|
@ -15544,6 +15544,9 @@
|
|||
"modelID": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/components/schemas/Model.Type"
|
||||
},
|
||||
"family": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ export * as ConfigProvider from "./provider.js"
|
|||
|
||||
import { Schema } from "effect"
|
||||
import { Money } from "../money.js"
|
||||
import { Capabilities, Compatibility, Family, ID, Model, VariantID } from "../model.js"
|
||||
import { Capabilities, Compatibility, Family, ID, Model, Type, VariantID } from "../model.js"
|
||||
import { ProviderCompatibility } from "../model-compatibility.js"
|
||||
import { Provider } from "../provider.js"
|
||||
import { optional } from "../schema.js"
|
||||
|
|
@ -74,6 +74,7 @@ export type Reasoning = typeof Reasoning.Type
|
|||
|
||||
class ModelConfig extends Schema.Class<ModelConfig>("Config.Model")({
|
||||
modelID: ID.pipe(optional),
|
||||
type: Type.pipe(optional),
|
||||
family: Family.pipe(optional),
|
||||
name: Schema.String.pipe(optional),
|
||||
releaseDate: Schema.String.check(Schema.isPattern(/^\d{4}-\d{2}(-\d{2})?$/u))
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ ID sent to the provider.
|
|||
| `modelID` | Model or deployment ID sent to the provider. |
|
||||
| `name` | Display name. |
|
||||
| `family` | Model family used for grouping related models. |
|
||||
| `type` | What the model produces, such as `chat`, `image` or `decision`. Defaults to `chat`; only chat models are offered for sessions. |
|
||||
| `releaseDate` | Release date as `YYYY-MM-DD` or `YYYY-MM`. |
|
||||
| `package` | Runtime override for this model. |
|
||||
| `settings` | Model-level OpenCode controls and package-specific JSON settings. |
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue