feat(models): 平台自建「模型设置」—— 用户自配厂家 / 条目各自开关 / 共享模型开关(档案 87)

- 官方「设置 → 模型」页在平台环境**必然报错**(判据在**浏览器页面**的 loopback 判定;官方 README 原文 Non-loopback pages get no durable settings)⇒ 该分区对全角色(含 admin)隐藏,用户自配改走平台自建页(插件 0.3.11)
- DB 迁移 V6:credential_vault.route/base_url/api/models + users.shared_model_enabled;并**重定义 getEnabledCredentialKeyRef**(互斥删除后原实现无 ORDER BY ⇒ 「任取一条」)
- 新落地层 src/web/model-landing.ts:spawn 时把「已启用条目」写进实例 .credentials.yaml 与 settings.yaml 的 llm-pi-ai.providers.<route>;字段名与官方包实测对齐(apiKeyEnv / baseURL / api,**不是** protocol);只碰自己写过的 + 一次性交接
- 接口 /api/me/keys、/api/me/keys/:id/toggle、/api/me/models/shared;前端新增「设置 → 模型设置」分区(settings.section id=model-settings / order 100 / 全角色)
- 顺手修两处:ensure-role-profile-patch.cjs 的 --force 整文件覆盖会抹掉 admin 的 disable-hmr 与 workspace-scoped-picker 两个平台块(改为 stripManagedBlock 只替换自己那段);verify-mem-model.mjs 因档案 86 重构而长期失败的陈旧断言

⚠️ 本提交同时包含**档案 86(admin 跨用户实例管理 + 两处改名)**的代码改动 —— 该部分已上线并端到端验证;其 import/register 与本次改动同处 src/web/server.ts、poc/business-plugins/lib/client.js 等文件,按**文件粒度无法拆分**,且不带它会让仓库 tsc 直接失败(缺 src/web/routes/admin-user-ops.ts)。
This commit is contained in:
admin committed 2026-09-14 00:00:15 +08:00
1 parent eb50ca2d5b
commit 918f1d3a51
20 files changed
+2073 -276

No files matched your search

+3 -3
View File
@@ -151,7 +151,7 @@ function readAsBase64(file) { return String(new Promise((res, rej) => { const r
function emptyRow(cols, text) { return `<tr><td colspan="${cols}" style="text-align:center;color:var(--bp-dim);padding:40px 10px">${esc(text)}</td></tr>` }
/* ================= 路由 ================= */
const CRUMB_TITLES = { files: '服务管理', keys: '密钥管理', users: '用户管理', skills: '技能管理', plugins: '插件管理' }
const CRUMB_TITLES = { files: '实例管理', keys: '模型管理', users: '用户管理', skills: '技能管理', plugins: '插件管理' }
function parseHash() { const h = (location.hash || '#/').replace(/^#/, ''); const parts = h.split('/').filter(Boolean); return parts[0] || '' }
function updateCrumbs(name) {
const c = $('crumbs')
@@ -164,8 +164,8 @@ function pageHead(title, sub) {
function renderHome() {
const sec1 = [
{ ic: '🖥️', t: '服务管理', d: '文件树 + DSH 启动', hash: '#/files' },
{ ic: '🔑', t: '密钥管理', d: '平台共享密钥', hash: '#/keys' },
{ ic: '🖥️', t: '实例管理', d: '文件树 + DSH 启动', hash: '#/files' },
{ ic: '🔑', t: '模型管理', d: '平台共享密钥', hash: '#/keys' },
]
const sec2 = [
{ ic: '👥', t: '用户管理', d: '审批 / 禁用 / 删除', hash: '#/users', admin: true },