dsh-dock 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -19
- package/client.js +2461 -1008
- package/features/animation/host.js +2 -1
- package/features/balance/host.js +2 -1
- package/features/mobile/host.js +93 -98
- package/features/mobile/view.js +136 -133
- package/features/mobile-relay/host.js +2 -1
- package/features/modelconfig/host.js +21 -462
- package/features/modelconfig/view.js +19 -704
- package/features/notify/host.js +2 -1
- package/features/notify/view.jsx +153 -30
- package/features/providerconfig/host.js +235 -0
- package/features/providerconfig/view.js +604 -0
- package/features/runstate/host.js +12 -1
- package/features/tokenlog/host.js +2 -1
- package/features/tokenlog/view.jsx +42 -12
- package/features/tts/host.js +164 -0
- package/features/tts/view.jsx +1189 -0
- package/features/visionproxy/host.js +1 -1
- package/index.js +9 -1
- package/package.json +3 -3
- package/screenshots/dock-modelconfig.png +0 -0
- package/src/client.jsx +54 -24
- package/src/host-core.js +84 -0
- package/src/model-directory.js +275 -0
- package/src/model-draft.js +119 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// dsh-dock · 模型目录客户端共享层(草稿工具)
|
|
2
|
+
//
|
|
3
|
+
// 【模型设置】(编辑已有 Provider 的模型条目)与【模型提供商】(新建/更新 Provider 时
|
|
4
|
+
// 随带模型)在浏览器里编辑的是同一种「模型草稿」:id / 名称 / 容量 / 输入模态 / 标注 /
|
|
5
|
+
// 思考强度档位。这里放两边共用的常量与纯函数,避免各自复刻一份口径(曾经两份实现漂移过:
|
|
6
|
+
// 思考档位与输入模态的默认值不一致)。
|
|
7
|
+
|
|
8
|
+
// 官方 schema 接受的真实输入模态;其余(视频等)仅作为 dockTags 标注随配置持久化
|
|
9
|
+
export const DKM_MODALITIES = [["text", "文本"], ["image", "图片"]];
|
|
10
|
+
export const DKM_TAGS = [["video", "视频"], ["audio", "音频"], ["document", "文档"]];
|
|
11
|
+
export const DKM_PI_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
|
|
12
|
+
export const DKM_DS_LEVELS = ["off", "low", "high", "max"];
|
|
13
|
+
export const DKM_EFFORT_NAMES = { off: "关闭", minimal: "极低", low: "低", medium: "中", high: "高", xhigh: "超高", max: "最高" };
|
|
14
|
+
// Provider 级增删改:api 协议选项(与宿主 PI_AI_APIS 一致)与路由 key 约束(与宿主同规则)
|
|
15
|
+
export const DKM_APIS = [
|
|
16
|
+
["openai-completions", "OpenAI 兼容(chat/completions)"],
|
|
17
|
+
["openai-responses", "OpenAI Responses"],
|
|
18
|
+
["anthropic-messages", "Anthropic Messages"]
|
|
19
|
+
];
|
|
20
|
+
export const DKM_ROUTE_KEY_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
21
|
+
|
|
22
|
+
/** 由路由 key 推导凭据库条目名:jiyuanlvdong -> JIYUANLVDONG_API_KEY。让 apiKeyEnv 可以真的留空。 */
|
|
23
|
+
export function dkmEnvFromRoute(route) {
|
|
24
|
+
const s = String(route || "").toUpperCase().replace(/[^A-Z0-9]+/g, "_").replace(/^_+|_+$/g, "");
|
|
25
|
+
if (!s) return "";
|
|
26
|
+
return (/^[0-9]/.test(s) ? "KEY_" + s : s) + "_API_KEY";
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const DKM_ALL_INPUT = DKM_MODALITIES.map((x) => x[0]);
|
|
30
|
+
export const DKM_ALL_TAGS = DKM_TAGS.map((x) => x[0]);
|
|
31
|
+
|
|
32
|
+
export function dkmToggleIn(list, v) {
|
|
33
|
+
return list.indexOf(v) >= 0 ? list.filter((x) => x !== v) : list.concat([v]);
|
|
34
|
+
}
|
|
35
|
+
export function dkmAllInputs(on) {
|
|
36
|
+
return { input: on ? DKM_ALL_INPUT.slice() : [], tags: on ? DKM_ALL_TAGS.slice() : [] };
|
|
37
|
+
}
|
|
38
|
+
export function dkmAllLevels(on) {
|
|
39
|
+
const lv = {};
|
|
40
|
+
for (const k of DKM_PI_LEVELS) lv[k] = !!on;
|
|
41
|
+
return { effortsMode: "custom", effortLevels: lv };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 单个目录模型条目 → 可编辑草稿(目录编辑器与 Provider 表单共用)。 */
|
|
45
|
+
export function draftFromModel(m) {
|
|
46
|
+
// effortMap: {档位: wire},声明过(wire 字符串或 null)即视为勾选,undefined = 未提供
|
|
47
|
+
const levels = {};
|
|
48
|
+
if (m.efforts === "custom" && m.effortMap && typeof m.effortMap === "object") {
|
|
49
|
+
for (const lv of DKM_PI_LEVELS) levels[lv] = m.effortMap[lv] !== undefined;
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
id: m.id || "",
|
|
53
|
+
name: m.name || "",
|
|
54
|
+
contextWindow: m.contextWindow != null ? String(m.contextWindow) : "",
|
|
55
|
+
maxTokens: m.maxTokens != null ? String(m.maxTokens) : "",
|
|
56
|
+
input: m.input && m.input.length ? m.input.slice() : ["text"],
|
|
57
|
+
tags: (m.tags || []).slice(),
|
|
58
|
+
effortsMode: m.efforts === "custom" ? "custom" : m.efforts === "off" ? "off" : "inherit",
|
|
59
|
+
effortLevels: levels,
|
|
60
|
+
raw: m.raw && typeof m.raw === "object" ? m.raw : null
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** 空白模型行(新增 Provider / 添加模型用)。 */
|
|
65
|
+
export function emptyModelDraft() {
|
|
66
|
+
return { id: "", name: "", contextWindow: "", maxTokens: "", input: ["text"], tags: [], effortsMode: "inherit", effortLevels: {}, raw: null };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** 新增 Provider 的空表单。 */
|
|
70
|
+
export function emptyProviderForm() {
|
|
71
|
+
return {
|
|
72
|
+
route: "",
|
|
73
|
+
displayName: "",
|
|
74
|
+
api: "openai-completions",
|
|
75
|
+
baseURL: "",
|
|
76
|
+
apiKeyEnv: "",
|
|
77
|
+
apiKey: "",
|
|
78
|
+
defaultInput: ["text"],
|
|
79
|
+
models: [],
|
|
80
|
+
extra: {}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** 从目录 Provider 视图构建可编辑草稿(模型设置页只取 models 字段)。 */
|
|
85
|
+
export function draftFromProvider(p) {
|
|
86
|
+
return {
|
|
87
|
+
id: p.id,
|
|
88
|
+
kind: p.kind,
|
|
89
|
+
thinking: p.thinking === "disabled" ? "disabled" : "enabled",
|
|
90
|
+
defaultEffort: DKM_DS_LEVELS.indexOf(p.defaultEffort) >= 0 ? p.defaultEffort : "high",
|
|
91
|
+
models: (p.models || []).map(draftFromModel)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* 由目录 Provider 视图构建「编辑 Provider」表单。
|
|
97
|
+
* 以用户层原始配置(rawProfile)为准回填;面板不负责的未知字段(自配 compat/description 等)
|
|
98
|
+
* 收进 extra,保存时原样并回,避免把用户手写配置抹掉。API Key 明文永不回显。
|
|
99
|
+
*/
|
|
100
|
+
export function providerFormFromProvider(p) {
|
|
101
|
+
const raw = p.rawProfile && typeof p.rawProfile === "object" && !Array.isArray(p.rawProfile) ? p.rawProfile : {};
|
|
102
|
+
const extra = Object.assign({}, raw);
|
|
103
|
+
delete extra.displayName; delete extra.api; delete extra.baseURL;
|
|
104
|
+
delete extra.apiKeyEnv; delete extra.defaultInput; delete extra.models;
|
|
105
|
+
const models = draftFromProvider(p).models;
|
|
106
|
+
return {
|
|
107
|
+
route: p.route || p.id || "",
|
|
108
|
+
displayName: typeof raw.displayName === "string" ? raw.displayName : (p.displayName || ""),
|
|
109
|
+
api: typeof raw.api === "string" && raw.api ? raw.api : (p.api || "openai-completions"),
|
|
110
|
+
baseURL: typeof raw.baseURL === "string" ? raw.baseURL : (p.baseURL || ""),
|
|
111
|
+
apiKeyEnv: typeof raw.apiKeyEnv === "string" ? raw.apiKeyEnv : (p.apiKeyEnv || ""),
|
|
112
|
+
apiKey: "",
|
|
113
|
+
defaultInput: Array.isArray(raw.defaultInput) && raw.defaultInput.length
|
|
114
|
+
? raw.defaultInput.slice()
|
|
115
|
+
: (Array.isArray(p.defaultInput) && p.defaultInput.length ? p.defaultInput.slice() : ["text"]),
|
|
116
|
+
models: models.length ? models : [emptyModelDraft()],
|
|
117
|
+
extra
|
|
118
|
+
};
|
|
119
|
+
}
|