Skip to content

Commit 6849f96

Browse files
kitlangtonDeveloper
andauthored
refactor(provider): share model status schema (anomalyco#26595)
Co-authored-by: Developer <temp@example.com>
1 parent 00c3248 commit 6849f96

6 files changed

Lines changed: 78 additions & 4 deletions

File tree

packages/opencode/src/config/provider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Schema } from "effect"
22
import { zod } from "@opencode-ai/core/effect-zod"
33
import { PositiveInt, withStatics } from "@opencode-ai/core/schema"
4+
import { ModelStatus } from "@/provider/model-status"
45

56
export const Model = Schema.Struct({
67
id: Schema.optional(Schema.String),
@@ -49,7 +50,7 @@ export const Model = Schema.Struct({
4950
}),
5051
),
5152
experimental: Schema.optional(Schema.Boolean),
52-
status: Schema.optional(Schema.Literals(["alpha", "beta", "deprecated", "active"])),
53+
status: Schema.optional(ModelStatus),
5354
provider: Schema.optional(
5455
Schema.Struct({ npm: Schema.optional(Schema.String), api: Schema.optional(Schema.String) }),
5556
),
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Schema } from "effect"
2+
3+
export const CatalogModelStatus = Schema.Literals(["alpha", "beta", "deprecated"])
4+
export type CatalogModelStatus = typeof CatalogModelStatus.Type
5+
6+
export const ModelStatus = Schema.Literals(["alpha", "beta", "deprecated", "active"])
7+
export type ModelStatus = typeof ModelStatus.Type
8+
9+
export * as ProviderModelStatus from "./model-status"

packages/opencode/src/provider/models.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Flock } from "@opencode-ai/core/util/flock"
88
import { Hash } from "@opencode-ai/core/util/hash"
99
import { AppFileSystem } from "@opencode-ai/core/filesystem"
1010
import { withTransientReadRetry } from "@/util/effect-http-client"
11+
import { CatalogModelStatus } from "./model-status"
1112

1213
const Cost = Schema.Struct({
1314
input: Schema.Finite,
@@ -71,7 +72,7 @@ export const Model = Schema.Struct({
7172
),
7273
}),
7374
),
74-
status: Schema.optional(Schema.Literals(["alpha", "beta", "deprecated", "active"])),
75+
status: Schema.optional(CatalogModelStatus),
7576
provider: Schema.optional(
7677
Schema.Struct({ npm: Schema.optional(Schema.String), api: Schema.optional(Schema.String) }),
7778
),

packages/opencode/src/provider/provider.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { optionalOmitUndefined, withStatics } from "@opencode-ai/core/schema"
2828

2929
import * as ProviderTransform from "./transform"
3030
import { ModelID, ProviderID } from "./schema"
31+
import { ModelStatus } from "./model-status"
3132

3233
const log = Log.create({ service: "provider" })
3334

@@ -897,7 +898,7 @@ export const Model = Schema.Struct({
897898
capabilities: ProviderCapabilities,
898899
cost: ProviderCost,
899900
limit: ProviderLimit,
900-
status: Schema.Literals(["alpha", "beta", "deprecated", "active"]),
901+
status: ModelStatus,
901902
options: Schema.Record(Schema.String, Schema.Any),
902903
headers: Schema.Record(Schema.String, Schema.String),
903904
release_date: Schema.String,

packages/opencode/src/v2/model.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { withStatics } from "@opencode-ai/core/schema"
2+
import { ModelStatus } from "@/provider/model-status"
23
import { Array, Context, Effect, HashMap, Layer, Option, Order, pipe, Schema } from "effect"
34
import { DateTimeUtcFromMillis } from "effect/Schema"
45

@@ -114,7 +115,7 @@ export class Info extends Schema.Class<Info>("Model.Info")({
114115
released: DateTimeUtcFromMillis,
115116
}),
116117
cost: Cost.pipe(Schema.Array),
117-
status: Schema.Literals(["alpha", "beta", "deprecated", "active"]),
118+
status: ModelStatus,
118119
limit: Schema.Struct({
119120
context: Schema.Int,
120121
input: Schema.Int.pipe(Schema.optional),
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, test } from "bun:test"
2+
import { Schema } from "effect"
3+
import { ConfigProvider } from "@/config/provider"
4+
import { CatalogModelStatus, ModelStatus } from "@/provider/model-status"
5+
import { ModelsDev } from "@/provider/models"
6+
import { Provider } from "@/provider/provider"
7+
8+
describe("provider model status schemas", () => {
9+
test("keeps catalog status separate from normalized provider status", () => {
10+
expect(Schema.decodeUnknownSync(CatalogModelStatus)("deprecated")).toBe("deprecated")
11+
expect(() => Schema.decodeUnknownSync(CatalogModelStatus)("active")).toThrow()
12+
expect(Schema.decodeUnknownSync(ModelStatus)("active")).toBe("active")
13+
})
14+
15+
test("accepts active status across public provider schemas", () => {
16+
expect(Schema.decodeUnknownSync(ConfigProvider.Model)({ status: "active" }).status).toBe("active")
17+
expect(
18+
Schema.decodeUnknownSync(ModelsDev.Model)({
19+
id: "test-model",
20+
name: "Test Model",
21+
release_date: "2026-01-01",
22+
attachment: false,
23+
reasoning: false,
24+
temperature: true,
25+
tool_call: true,
26+
limit: { context: 128000, output: 8192 },
27+
}).status,
28+
).toBeUndefined()
29+
expect(
30+
Schema.decodeUnknownSync(Provider.Model)({
31+
id: "test-model",
32+
providerID: "test-provider",
33+
api: {
34+
id: "test-model",
35+
url: "",
36+
npm: "@ai-sdk/openai-compatible",
37+
},
38+
name: "Test Model",
39+
capabilities: {
40+
temperature: true,
41+
reasoning: false,
42+
attachment: false,
43+
toolcall: true,
44+
input: { text: true, audio: false, image: false, video: false, pdf: false },
45+
output: { text: true, audio: false, image: false, video: false, pdf: false },
46+
interleaved: false,
47+
},
48+
cost: {
49+
input: 0,
50+
output: 0,
51+
cache: { read: 0, write: 0 },
52+
},
53+
limit: { context: 128000, output: 8192 },
54+
status: "active",
55+
options: {},
56+
headers: {},
57+
release_date: "2026-01-01",
58+
}).status,
59+
).toBe("active")
60+
})
61+
})

0 commit comments

Comments
 (0)