This commit is contained in:
fengchuanhn@gmail.com
2026-05-17 12:54:13 +08:00
parent 1b8ca10ec9
commit 3db327d93b
38 changed files with 2820 additions and 14 deletions

View File

@@ -0,0 +1,129 @@
"use strict";
/**
* 从进程环境变量读取 desktop_configsRust 注入 AICLIENT_CFG_*)。
* 库表 name 经规范化后作为 env 后缀,如 name=LLM_API_KEY → AICLIENT_CFG_LLM_API_KEY
*/
const ENV_PREFIX = "AICLIENT_CFG_";
function normalizeKey(name) {
return String(name || "")
.trim()
.replace(/[^a-zA-Z0-9]+/g, "_")
.replace(/^_+|_+$/g, "")
.toUpperCase();
}
/** @returns {Record<string, string>} 逻辑键(大写+下划线)→ 值 */
function readAllFromEnv() {
const out = {};
for (const [ek, ev] of Object.entries(process.env)) {
if (!ek.startsWith(ENV_PREFIX) || ev == null || ev === "") continue;
const logical = ek.slice(ENV_PREFIX.length);
out[logical] = ev;
}
return out;
}
function get(logicalKey, fallback = "") {
const k = normalizeKey(logicalKey);
return process.env[ENV_PREFIX + k] || fallback;
}
function parseJson(val, fallback = null) {
if (!val) return fallback;
try {
return JSON.parse(val);
} catch {
return fallback;
}
}
/**
* 将扁平配置组装为流水线使用的 modelConfig兼容现有脚本字段名
* 可在库表增加任意键;复杂对象用 JSON 字符串存于 OSS_CONFIG、ASR_SERVER_INFO 等。
*/
function buildModelConfig() {
const c = readAllFromEnv();
const pick = (...keys) => {
for (const k of keys) {
const v = c[normalizeKey(k)];
if (v) return v;
}
return "";
};
let apiUrl = pick("LLM_API_URL", "API_URL");
if (apiUrl) {
apiUrl = apiUrl.replace(/\/$/, "");
if (!apiUrl.includes("/chat/completions")) {
apiUrl = apiUrl.endsWith("/v1")
? `${apiUrl}/chat/completions`
: `${apiUrl}/v1/chat/completions`;
}
}
const asrMode = pick("ASR_MODE", "asr_mode") || "online";
let ossConfig = parseJson(pick("OSS_CONFIG"));
if (!ossConfig && pick("OSS_ACCESS_KEY_ID")) {
ossConfig = {
accessKeyId: pick("OSS_ACCESS_KEY_ID"),
accessKeySecret: pick("OSS_ACCESS_KEY_SECRET"),
bucket: pick("OSS_BUCKET"),
region: pick("OSS_REGION"),
endpoint: pick("OSS_ENDPOINT") || undefined,
};
}
let asrServerInfo = parseJson(pick("ASR_SERVER_INFO"));
if (!asrServerInfo && pick("ASR_SERVER_URL")) {
asrServerInfo = {
name: pick("ASR_SERVER_NAME", "local") || "local",
baseUrl: pick("ASR_SERVER_URL").replace(/\/$/, ""),
asrPath: pick("ASR_SERVER_ASR_PATH", "/asr") || "/asr",
};
}
return {
providerId: pick("LLM_PROVIDER_ID", "PROVIDER_ID") || "openai",
modelId: pick("LLM_MODEL_ID", "MODEL_ID"),
apiUrl,
apiKey: pick("LLM_API_KEY", "API_KEY"),
type: pick("LLM_TYPE", "TYPE") || "openai",
asrMode,
aliyunApiKey: pick("DASHSCOPE_API_KEY", "ALIYUN_API_KEY"),
ossConfig: ossConfig || undefined,
asrServerInfo: asrServerInfo || undefined,
};
}
function validateModelConfig(modelConfig) {
if (!modelConfig.apiKey) {
return { ok: false, error: "缺少配置 LLM_API_KEYdesktop_configs 表)" };
}
if (!modelConfig.apiUrl) {
return { ok: false, error: "缺少配置 LLM_API_URL" };
}
if (modelConfig.asrMode === "online") {
if (!modelConfig.aliyunApiKey) {
return { ok: false, error: "在线 ASR 需配置 DASHSCOPE_API_KEY" };
}
if (!modelConfig.ossConfig?.bucket) {
return { ok: false, error: "在线 ASR 需配置 OSS或 OSS_CONFIG JSON" };
}
}
if (modelConfig.asrMode === "local" && !modelConfig.asrServerInfo) {
return { ok: false, error: "本地 ASR 需配置 ASR_SERVER_URL 或 ASR_SERVER_INFO" };
}
return { ok: true };
}
module.exports = {
ENV_PREFIX,
readAllFromEnv,
get,
buildModelConfig,
validateModelConfig,
};