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

+17 -1
View File
@@ -8,6 +8,8 @@
import type {
BusinessPlugin,
CredentialKey,
CredentialKeyMeta,
CredentialLandingRow,
CreateSessionInput,
CreateUserInput,
Domain,
@@ -71,9 +73,23 @@ export interface DbAdapter {
setDomainVerified(id: string, verified: boolean): Promise<boolean>
// credential vault
listCredentialKeys(userId: string): Promise<CredentialKey[]>
/** 档案 86:该用户**全部已启用**的条目(spawn 时按它们写实例配置)。 */
listEnabledCredentialKeys(userId: string): Promise<CredentialKey[]>
/** 档案 87:同上 + **encrypted ref** —— **仅供 `server.ts` 的落地层**,绝不经 API 返回。 */
listCredentialLandingRows(userId: string): Promise<CredentialLandingRow[]>
getEnabledCredentialKeyRef(userId: string): Promise<string | null>
setCredentialKey(userId: string, name: string, encryptedRef: string): Promise<CredentialKey>
setCredentialKey(
userId: string,
name: string,
encryptedRef: string,
meta?: CredentialKeyMeta,
): Promise<CredentialKey>
selectCredentialKey(userId: string, id: string): Promise<boolean>
/** 档案 86:开/关**单个**条目(不动其它条目 —— 用户口径:可同时启用多个)。 */
toggleCredentialKey(userId: string, id: string, enabled: boolean): Promise<boolean>
/** 档案 86:用户是否使用「平台共享模型」(admin 配的那把)—— 用户侧偏好。 */
getSharedModelEnabled(userId: string): Promise<boolean>
setSharedModelEnabled(userId: string, enabled: boolean): Promise<boolean>
deleteCredentialKey(userId: string, id: string): Promise<boolean>
// instances (desired state the k8s controller reconciles against — docs/k8s.md §5.7)
upsertInstance(input: UpsertDshInstanceInput): Promise<void>