Skip to content

Commit 88fef05

Browse files
committed
wip: zen
1 parent 8552f35 commit 88fef05

File tree

5 files changed

+44
-27
lines changed

5 files changed

+44
-27
lines changed

packages/console/app/src/routes/workspace/[id]/model-section.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Model } from "@opencode-ai/console-core/model.js"
22
import { query, action, useParams, createAsync, json } from "@solidjs/router"
33
import { createMemo, For, Show } from "solid-js"
44
import { withActor } from "~/context/auth.withActor"
5-
import { ZenModel } from "@opencode-ai/console-core/model.js"
5+
import { ZenData } from "@opencode-ai/console-core/model.js"
66
import styles from "./model-section.module.css"
77
import { querySessionInfo } from "../common"
88
import { IconAlibaba, IconAnthropic, IconMoonshotAI, IconOpenAI, IconStealth, IconXai, IconZai } from "~/component/icon"
@@ -21,7 +21,7 @@ const getModelsInfo = query(async (workspaceID: string) => {
2121
"use server"
2222
return withActor(async () => {
2323
return {
24-
all: Object.entries(ZenModel.list())
24+
all: Object.entries(ZenData.list().models)
2525
.filter(([id, _model]) => !["claude-3-5-haiku"].includes(id))
2626
.filter(([id, _model]) => !id.startsWith("an-"))
2727
.sort(([_idA, modelA], [_idB, modelB]) => modelA.name.localeCompare(modelB.name))

packages/console/app/src/routes/zen/handler.ts

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Resource } from "@opencode-ai/console-resource"
1010
import { Billing } from "../../../../core/src/billing"
1111
import { Actor } from "@opencode-ai/console-core/actor.js"
1212
import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js"
13-
import { ZenModel } from "@opencode-ai/console-core/model.js"
13+
import { ZenData } from "@opencode-ai/console-core/model.js"
1414
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
1515
import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
1616
import { ProviderTable } from "@opencode-ai/console-core/schema/provider.sql.js"
@@ -39,7 +39,8 @@ export async function handler(
3939
class UserLimitError extends Error {}
4040
class ModelError extends Error {}
4141

42-
type Model = z.infer<typeof ZenModel.ModelSchema>
42+
type ZenData = Awaited<ReturnType<typeof ZenData.list>>
43+
type Model = ZenData["models"][string]
4344

4445
const FREE_WORKSPACES = [
4546
"wrk_01K46JDFR0E75SG2Q8K172KF3Y", // frank
@@ -66,8 +67,9 @@ export async function handler(
6667
session: input.request.headers.get("x-opencode-session"),
6768
request: input.request.headers.get("x-opencode-request"),
6869
})
69-
const modelInfo = validateModel(body.model)
70-
const providerInfo = selectProvider(modelInfo)
70+
const zenData = ZenData.list()
71+
const modelInfo = validateModel(zenData, body.model)
72+
const providerInfo = selectProvider(zenData, modelInfo)
7173
const authInfo = await authenticate(modelInfo, providerInfo)
7274
validateBilling(modelInfo, authInfo)
7375
validateModelSettings(authInfo)
@@ -211,27 +213,29 @@ export async function handler(
211213
)
212214
}
213215

214-
function validateModel(reqModel: string) {
215-
const json = JSON.parse(Resource.ZEN_MODELS.value)
216-
217-
const allModels = ZenModel.ModelsSchema.parse(json)
218-
219-
if (!(reqModel in allModels)) {
216+
function validateModel(zenData: ZenData, reqModel: string) {
217+
if (!(reqModel in zenData.models)) {
220218
throw new ModelError(`Model ${reqModel} not supported`)
221219
}
222-
const modelId = reqModel as keyof typeof allModels
223-
const modelData = allModels[modelId]
220+
const modelId = reqModel as keyof typeof zenData.models
221+
const modelData = zenData.models[modelId]
224222

225223
logger.metric({ model: modelId })
226224

227225
return { id: modelId, ...modelData }
228226
}
229227

230-
function selectProvider(model: Awaited<ReturnType<typeof validateModel>>) {
228+
function selectProvider(zenData: ZenData, model: Awaited<ReturnType<typeof validateModel>>) {
231229
const providers = model.providers
232230
.filter((provider) => !provider.disabled)
233231
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
234-
return providers[Math.floor(Math.random() * providers.length)]
232+
const provider = providers[Math.floor(Math.random() * providers.length)]
233+
234+
if (!(provider.id in zenData.providers)) {
235+
throw new ModelError(`Provider ${provider.id} not supported`)
236+
}
237+
238+
return { ...provider, ...zenData.providers[provider.id] }
235239
}
236240

237241
async function authenticate(

packages/console/core/script/promote-models.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { $ } from "bun"
44
import path from "path"
5-
import { ZenModel } from "../src/model"
5+
import { ZenData } from "../src/model"
66

77
const stage = process.argv[2]
88
if (!stage) throw new Error("Stage is required")
@@ -18,7 +18,7 @@ const value = ret
1818
if (!value) throw new Error("ZEN_MODELS not found")
1919

2020
// validate value
21-
ZenModel.ModelsSchema.parse(JSON.parse(value))
21+
ZenData.validate(JSON.parse(value))
2222

2323
// update the secret
2424
await $`bun sst secret set ZEN_MODELS ${value} --stage ${stage}`

packages/console/core/script/update-models.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import { $ } from "bun"
44
import path from "path"
55
import os from "os"
6-
import { ZenModel } from "../src/model"
6+
import { ZenData } from "../src/model"
77

88
const root = path.resolve(process.cwd(), "..", "..", "..")
99
const models = await $`bun sst secret list`.cwd(root).text()
@@ -26,7 +26,7 @@ console.log("tempFile", tempFile.name)
2626
// open temp file in vim and read the file on close
2727
await $`vim ${tempFile.name}`
2828
const newValue = JSON.parse(await tempFile.text())
29-
ZenModel.ModelsSchema.parse(newValue)
29+
ZenData.validate(newValue)
3030

3131
// update the secret
3232
await $`bun sst secret set ZEN_MODELS ${JSON.stringify(newValue)}`

packages/console/core/src/model.ts

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { fn } from "./util/fn"
77
import { Actor } from "./actor"
88
import { Resource } from "@opencode-ai/console-resource"
99

10-
export namespace ZenModel {
10+
export namespace ZenData {
1111
const ModelCostSchema = z.object({
1212
input: z.number(),
1313
output: z.number(),
@@ -16,27 +16,40 @@ export namespace ZenModel {
1616
cacheWrite1h: z.number().optional(),
1717
})
1818

19-
export const ModelSchema = z.object({
19+
const ModelSchema = z.object({
2020
name: z.string(),
2121
cost: ModelCostSchema,
2222
cost200K: ModelCostSchema.optional(),
2323
allowAnonymous: z.boolean().optional(),
2424
providers: z.array(
2525
z.object({
2626
id: z.string(),
27-
api: z.string(),
28-
apiKey: z.string(),
2927
model: z.string(),
3028
weight: z.number().optional(),
31-
headerMappings: z.record(z.string(), z.string()).optional(),
3229
disabled: z.boolean().optional(),
3330
}),
3431
),
3532
})
3633

37-
export const ModelsSchema = z.record(z.string(), ModelSchema)
34+
const ProviderSchema = z.object({
35+
api: z.string(),
36+
apiKey: z.string(),
37+
headerMappings: z.record(z.string(), z.string()).optional(),
38+
})
39+
40+
const ModelsSchema = z.object({
41+
models: z.record(z.string(), ModelSchema),
42+
providers: z.record(z.string(), ProviderSchema),
43+
})
3844

39-
export const list = fn(z.void(), () => ModelsSchema.parse(JSON.parse(Resource.ZEN_MODELS.value)))
45+
export const validate = fn(ModelsSchema, (input) => {
46+
return input
47+
})
48+
49+
export const list = fn(z.void(), () => {
50+
const json = JSON.parse(Resource.ZEN_MODELS.value)
51+
return ModelsSchema.parse(json)
52+
})
4053
}
4154

4255
export namespace Model {

0 commit comments

Comments
 (0)