import { THEME_CSS, escapeHtml, escapeAttr } from "../render/layout"; import { projectSettingsTabsHTML } from "./projectUpstreams"; import type { ProjectRow, CachedModel } from "../store"; interface Flash { kind: "ok" | "err"; msg: string; } export function buildProjectModelPage( project: ProjectRow, globalDefault: string, models: CachedModel[], flash: Flash | null, ): { html: string } { const base = `/${encodeURIComponent(project.owner)}/${encodeURIComponent(project.name)}/settings`; const cur = project.model; const effective = cur || globalDefault; const effectiveLine = effective ? `

实际生效:${escapeHtml(effective)}${cur ? "" : " (继承全局默认)"}

` : `

实际生效:未配置 — daemon 不会加 --model,opencode 按 opencode.json 选;注意环境变量(如 OPENCODE_MODEL)可能污染。建议去 全局设置 点「刷新 opencode 模型列表」自动选一个默认。

`; // Empty cache → free-text input (same degradation as global settings). const field = models.length === 0 ? `` : (() => { const opts = [``] .concat( models.map( (m) => ``, ), ) .join(""); return ``; })(); const banner = flash ? `
${escapeHtml(flash.msg)}
` : ""; const html = ` ${escapeHtml(project.owner + "/" + project.name)} · 模型设置
${projectSettingsTabsHTML(project.owner, project.name, "model")}

🤖 模型设置

${banner} ${effectiveLine}

项目级模型覆盖

${field}

空 = 继承 全局默认(当前: ${escapeHtml(globalDefault || "(未配置)")})。
模型列表来源:opencode models。要刷新去 全局设置 点「刷新 opencode 模型列表」。

`; return { html }; }