This commit is contained in:
Frank
2025-10-08 01:14:39 -04:00
parent 99b72eb1ea
commit af684c80d4
2 changed files with 28 additions and 28 deletions

View File

@@ -24,7 +24,6 @@ const updateModel = action(async (form: FormData) => {
const workspaceID = form.get("workspaceID")?.toString() const workspaceID = form.get("workspaceID")?.toString()
if (!workspaceID) return { error: "Workspace ID is required" } if (!workspaceID) return { error: "Workspace ID is required" }
const enabled = form.get("enabled")?.toString() === "true" const enabled = form.get("enabled")?.toString() === "true"
console.log({ model, workspaceID, enabled })
return json( return json(
withActor(async () => { withActor(async () => {
if (enabled) { if (enabled) {

View File

@@ -12,6 +12,7 @@ import { Actor } from "@opencode-ai/console-core/actor.js"
import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js" import { WorkspaceTable } from "@opencode-ai/console-core/schema/workspace.sql.js"
import { ZenModel } from "@opencode-ai/console-core/model.js" import { ZenModel } from "@opencode-ai/console-core/model.js"
import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js" import { UserTable } from "@opencode-ai/console-core/schema/user.sql.js"
import { ModelTable } from "@opencode-ai/console-core/schema/model.sql.js"
export async function handler( export async function handler(
input: APIEvent, input: APIEvent,
@@ -67,6 +68,7 @@ export async function handler(
const providerInfo = selectProvider(modelInfo) const providerInfo = selectProvider(modelInfo)
const authInfo = await authenticate(modelInfo) const authInfo = await authenticate(modelInfo)
validateBilling(modelInfo, authInfo) validateBilling(modelInfo, authInfo)
validateModelSettings(authInfo)
logger.metric({ provider: providerInfo.id }) logger.metric({ provider: providerInfo.id })
// Request to model provider // Request to model provider
@@ -222,14 +224,14 @@ export async function handler(
return { id: modelId, ...modelData } return { id: modelId, ...modelData }
} }
function selectProvider(model: Model) { function selectProvider(model: Awaited<ReturnType<typeof validateModel>>) {
const providers = model.providers const providers = model.providers
.filter((provider) => !provider.disabled) .filter((provider) => !provider.disabled)
.flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider)) .flatMap((provider) => Array<typeof provider>(provider.weight ?? 1).fill(provider))
return providers[Math.floor(Math.random() * providers.length)] return providers[Math.floor(Math.random() * providers.length)]
} }
async function authenticate(model: Model) { async function authenticate(model: Awaited<ReturnType<typeof validateModel>>) {
const apiKey = opts.parseApiKey(input.request.headers) const apiKey = opts.parseApiKey(input.request.headers)
if (!apiKey) { if (!apiKey) {
if (model.allowAnonymous) return if (model.allowAnonymous) return
@@ -241,20 +243,26 @@ export async function handler(
.select({ .select({
apiKey: KeyTable.id, apiKey: KeyTable.id,
workspaceID: KeyTable.workspaceID, workspaceID: KeyTable.workspaceID,
balance: BillingTable.balance, billing: {
paymentMethodID: BillingTable.paymentMethodID, balance: BillingTable.balance,
monthlyLimit: BillingTable.monthlyLimit, paymentMethodID: BillingTable.paymentMethodID,
monthlyUsage: BillingTable.monthlyUsage, monthlyLimit: BillingTable.monthlyLimit,
timeMonthlyUsageUpdated: BillingTable.timeMonthlyUsageUpdated, monthlyUsage: BillingTable.monthlyUsage,
userID: UserTable.id, timeMonthlyUsageUpdated: BillingTable.timeMonthlyUsageUpdated,
userMonthlyLimit: UserTable.monthlyLimit, },
userMonthlyUsage: UserTable.monthlyUsage, user: {
timeUserMonthlyUsageUpdated: UserTable.timeMonthlyUsageUpdated, id: UserTable.id,
monthlyLimit: UserTable.monthlyLimit,
monthlyUsage: UserTable.monthlyUsage,
timeMonthlyUsageUpdated: UserTable.timeMonthlyUsageUpdated,
},
timeDisabled: ModelTable.timeCreated,
}) })
.from(KeyTable) .from(KeyTable)
.innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID)) .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, KeyTable.workspaceID))
.innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID)) .innerJoin(BillingTable, eq(BillingTable.workspaceID, KeyTable.workspaceID))
.innerJoin(UserTable, and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID))) .innerJoin(UserTable, and(eq(UserTable.workspaceID, KeyTable.workspaceID), eq(UserTable.id, KeyTable.userID)))
.leftJoin(ModelTable, and(eq(ModelTable.workspaceID, KeyTable.workspaceID), eq(ModelTable.model, model.id)))
.where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted))) .where(and(eq(KeyTable.key, apiKey), isNull(KeyTable.timeDeleted)))
.then((rows) => rows[0]), .then((rows) => rows[0]),
) )
@@ -265,25 +273,13 @@ export async function handler(
workspace: data.workspaceID, workspace: data.workspaceID,
}) })
const isFree = FREE_WORKSPACES.includes(data.workspaceID)
return { return {
apiKeyId: data.apiKey, apiKeyId: data.apiKey,
workspaceID: data.workspaceID, workspaceID: data.workspaceID,
billing: { billing: data.billing,
paymentMethodID: data.paymentMethodID, user: data.user,
balance: data.balance, isFree: FREE_WORKSPACES.includes(data.workspaceID),
monthlyLimit: data.monthlyLimit, isDisabled: !!data.timeDisabled,
monthlyUsage: data.monthlyUsage,
timeMonthlyUsageUpdated: data.timeMonthlyUsageUpdated,
},
user: {
id: data.userID,
monthlyLimit: data.userMonthlyLimit,
monthlyUsage: data.userMonthlyUsage,
timeMonthlyUsageUpdated: data.timeUserMonthlyUsageUpdated,
},
isFree,
} }
} }
@@ -325,6 +321,11 @@ export async function handler(
} }
} }
function validateModelSettings(authInfo: Awaited<ReturnType<typeof authenticate>>) {
if (!authInfo) return
if (authInfo.isDisabled) throw new ModelError("Model is disabled")
}
async function trackUsage( async function trackUsage(
authInfo: Awaited<ReturnType<typeof authenticate>>, authInfo: Awaited<ReturnType<typeof authenticate>>,
modelInfo: ReturnType<typeof validateModel>, modelInfo: ReturnType<typeof validateModel>,