Buckets:
GHHG10/CodeServer / opencode /packages /console /app /src /routes /workspace /[id] /model-section.tsx
| import { Model } from "@opencode-ai/console-core/model.js" | |
| import { query, action, useParams, createAsync, json } from "@solidjs/router" | |
| import { createMemo, For, Show } from "solid-js" | |
| import { withActor } from "~/context/auth.withActor" | |
| import { ZenData } from "@opencode-ai/console-core/model.js" | |
| import styles from "./model-section.module.css" | |
| import { querySessionInfo } from "../common" | |
| import { | |
| IconAlibaba, | |
| IconAnthropic, | |
| IconArcee, | |
| IconGemini, | |
| IconDeepSeek, | |
| IconMiniMax, | |
| IconMoonshotAI, | |
| IconNvidia, | |
| IconOpenAI, | |
| IconStealth, | |
| IconXai, | |
| IconXiaomi, | |
| IconZai, | |
| } from "~/component/icon" | |
| import { useI18n } from "~/context/i18n" | |
| import { useLanguage } from "~/context/language" | |
| import { formError } from "~/lib/form-error" | |
| const getModelLab = (modelId: string) => { | |
| if (modelId.startsWith("claude")) return "Anthropic" | |
| if (modelId.startsWith("gpt")) return "OpenAI" | |
| if (modelId.startsWith("gemini")) return "Google" | |
| if (modelId.startsWith("deepseek")) return "DeepSeek" | |
| if (modelId.startsWith("kimi")) return "Moonshot AI" | |
| if (modelId.startsWith("glm")) return "Z.ai" | |
| if (modelId.startsWith("qwen")) return "Alibaba" | |
| if (modelId.startsWith("minimax")) return "MiniMax" | |
| if (modelId.startsWith("grok")) return "xAI" | |
| if (modelId.startsWith("mimo")) return "Xiaomi" | |
| if (modelId.startsWith("nemotron")) return "NVIDIA" | |
| if (modelId.startsWith("trinity")) return "Arcee" | |
| return "Stealth" | |
| } | |
| const getModelsInfo = query(async (workspaceID: string) => { | |
| "use server" | |
| return withActor(async () => { | |
| return { | |
| all: Object.entries(ZenData.list("full").models) | |
| .filter(([id, _model]) => !["claude-3-5-haiku"].includes(id)) | |
| .filter(([id, _model]) => !id.startsWith("alpha-")) | |
| .filter(([id, _model]) => !id.endsWith(":global")) | |
| .sort(([idA, modelA], [idB, modelB]) => { | |
| const priority = [ | |
| "big-pickle", | |
| "claude", | |
| "gpt", | |
| "gemini", | |
| "deepseek", | |
| "glm", | |
| "kimi", | |
| "qwen", | |
| "grok", | |
| "minimax", | |
| "mimo", | |
| ] | |
| const getPriority = (id: string) => { | |
| const index = priority.findIndex((p) => id.startsWith(p)) | |
| return index === -1 ? Infinity : index | |
| } | |
| const pA = getPriority(idA) | |
| const pB = getPriority(idB) | |
| if (pA !== pB) return pA - pB | |
| const modelAName = Array.isArray(modelA) ? modelA[0].name : modelA.name | |
| const modelBName = Array.isArray(modelB) ? modelB[0].name : modelB.name | |
| return modelAName.localeCompare(modelBName) | |
| }) | |
| .map(([id, model]) => ({ id, name: Array.isArray(model) ? model[0].name : model.name })), | |
| disabled: await Model.listDisabled(), | |
| } | |
| }, workspaceID) | |
| }, "model.info") | |
| const updateModel = action(async (form: FormData) => { | |
| "use server" | |
| const model = form.get("model") as string | null | |
| if (!model) return { error: formError.modelRequired } | |
| const workspaceID = form.get("workspaceID") as string | null | |
| if (!workspaceID) return { error: formError.workspaceRequired } | |
| const enabled = (form.get("enabled") as string | null) === "true" | |
| return json( | |
| withActor(async () => { | |
| if (enabled) { | |
| await Model.disable({ model }) | |
| } else { | |
| await Model.enable({ model }) | |
| } | |
| }, workspaceID), | |
| { revalidate: getModelsInfo.key }, | |
| ) | |
| }, "model.toggle") | |
| export function ModelSection() { | |
| const params = useParams() | |
| const i18n = useI18n() | |
| const language = useLanguage() | |
| const modelsInfo = createAsync(() => getModelsInfo(params.id!)) | |
| const userInfo = createAsync(() => querySessionInfo(params.id!)) | |
| const modelsWithLab = createMemo(() => { | |
| const info = modelsInfo() | |
| if (!info) return [] | |
| return info.all.map((model) => ({ | |
| ...model, | |
| lab: getModelLab(model.id), | |
| })) | |
| }) | |
| return ( | |
| <section class={styles.root}> | |
| <div data-slot="section-title"> | |
| <h2>{i18n.t("workspace.models.title")}</h2> | |
| <p> | |
| {i18n.t("workspace.models.subtitle.beforeLink")}{" "} | |
| <a href={language.route("/docs/zen#pricing")}>{i18n.t("common.learnMore")}</a>. | |
| </p> | |
| </div> | |
| <div data-slot="models-list"> | |
| <Show when={modelsInfo()}> | |
| <div data-slot="models-table"> | |
| <table data-slot="models-table-element"> | |
| <thead> | |
| <tr> | |
| <th>{i18n.t("workspace.models.table.model")}</th> | |
| <th></th> | |
| <th>{i18n.t("workspace.models.table.enabled")}</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| <For each={modelsWithLab()}> | |
| {({ id, name, lab }) => { | |
| const isEnabled = createMemo(() => !modelsInfo()!.disabled.includes(id)) | |
| return ( | |
| <tr data-slot="model-row" data-disabled={!isEnabled()}> | |
| <td data-slot="model-name"> | |
| <div> | |
| {(() => { | |
| switch (lab) { | |
| case "OpenAI": | |
| return <IconOpenAI width={16} height={16} /> | |
| case "Anthropic": | |
| return <IconAnthropic width={16} height={16} /> | |
| case "Google": | |
| return <IconGemini width={16} height={16} /> | |
| case "DeepSeek": | |
| return <IconDeepSeek width={16} height={16} /> | |
| case "Moonshot AI": | |
| return <IconMoonshotAI width={16} height={16} /> | |
| case "Z.ai": | |
| return <IconZai width={16} height={16} /> | |
| case "Alibaba": | |
| return <IconAlibaba width={16} height={16} /> | |
| case "xAI": | |
| return <IconXai width={16} height={16} /> | |
| case "MiniMax": | |
| return <IconMiniMax width={16} height={16} /> | |
| case "Xiaomi": | |
| return <IconXiaomi width={16} height={16} /> | |
| case "NVIDIA": | |
| return <IconNvidia width={16} height={16} /> | |
| case "Arcee": | |
| return <IconArcee width={16} height={16} /> | |
| default: | |
| return <IconStealth width={16} height={16} /> | |
| } | |
| })()} | |
| <span>{name}</span> | |
| </div> | |
| </td> | |
| <td data-slot="model-lab">{lab}</td> | |
| <td data-slot="model-toggle"> | |
| <form action={updateModel} method="post"> | |
| <input type="hidden" name="model" value={id} /> | |
| <input type="hidden" name="workspaceID" value={params.id} /> | |
| <input type="hidden" name="enabled" value={String(isEnabled())} /> | |
| <label data-slot="model-toggle-label"> | |
| <input | |
| type="checkbox" | |
| checked={isEnabled()} | |
| disabled={!userInfo()?.isAdmin} | |
| onChange={(e) => { | |
| const form = e.currentTarget.closest("form") | |
| if (form) form.requestSubmit() | |
| }} | |
| /> | |
| <span></span> | |
| </label> | |
| </form> | |
| </td> | |
| </tr> | |
| ) | |
| }} | |
| </For> | |
| </tbody> | |
| </table> | |
| </div> | |
| </Show> | |
| </div> | |
| </section> | |
| ) | |
| } | |
Xet Storage Details
- Size:
- 8.29 kB
- Xet hash:
- 13f79b94f5038ec0017a75361cf55b8bb0d574f592620faa0c253b37aab32d4f
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.