ai-chatbot/scripts/configure-aliyun-canvas-audio.cjs

92 lines
3.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Run on the application host: APP_ROOT=/var/www/ai-chatbot node SCRIPT [--apply] [--music-enabled]
// Only model rows are backed up; credentials never leave the existing provider.
const fs = require("node:fs");
const root = process.env.APP_ROOT || process.cwd();
require(root + "/node_modules/dotenv").config({ path: root + "/.env.local", quiet: true });
const sql = require(root + "/node_modules/postgres")(process.env.POSTGRES_URL, { max: 1 });
const providerId = "7bce5924-bfd2-4e31-9f1d-825bd9d9f8b1";
const apply = process.argv.includes("--apply"),
musicEnabled = process.argv.includes("--music-enabled");
const models = [
{
modelId: "qwen3-tts-instruct-flash",
displayName: "千问3 TTS 指令版(阿里云官方)",
kind: "tts",
enabled: true,
defaults: { voice: "Cherry", language: "Chinese", format: "wav" },
},
{
modelId: "qwen3-tts-flash",
displayName: "千问3 TTS(阿里云官方)",
kind: "tts",
enabled: true,
defaults: { voice: "Cherry", language: "Chinese", format: "wav" },
},
{
modelId: "fun-music-v1",
displayName: "Fun-Music(阿里云官方·需邀测)",
kind: "music",
enabled: musicEnabled,
defaults: { instrumental: true, format: "mp3" },
},
];
(async () => {
const [provider] =
await sql`select id,type,"baseUrl","isEnabled" from "AiProvider" where id=${providerId}`;
if (
!provider ||
provider.type !== "alibaba" ||
!provider.isEnabled ||
new URL(provider.baseUrl).origin !== "https://dashscope.aliyuncs.com"
)
throw Error("Expected enabled official Alibaba Beijing provider");
await sql.begin(async (tx) => {
await tx`select id from "AiProvider" where id=${providerId} for update`;
const before =
await tx`select * from "AiModel" where "providerId"=${providerId} and "modelId" in ${tx(models.map((m) => m.modelId))}`;
if (apply) {
const dir = root + "/.model-config-backups";
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
fs.writeFileSync(
dir + "/canvas-audio-" + Date.now() + ".json",
JSON.stringify({ providerId, models: before }, null, 2),
{ mode: 0o600 },
);
}
for (const model of models) {
const existing = before.filter((row) => row.modelId === model.modelId);
if (existing.length > 1) throw Error("Duplicate model rows: " + model.modelId);
const row = existing[0];
// Preserve an already enabled music row on subsequent idempotent runs.
const enabled = model.enabled || !!row?.isEnabled;
const capabilities = {
...(row?.capabilities || {}),
kind: "audio",
audioType: model.kind,
official: true,
activationRequired: model.kind === "music" && !enabled,
};
const defaults = { ...(row?.defaultParams || {}), ...model.defaults };
if (apply) {
if (row)
await tx`update "AiModel" set "displayName"=${model.displayName},"isEnabled"=${enabled},"isHidden"=true,capabilities=${tx.json(capabilities)},"defaultParams"=${tx.json(defaults)},"updatedAt"=now() where id=${row.id}`;
else
await tx`insert into "AiModel" ("providerId","modelId","displayName","isEnabled","isHidden",capabilities,"defaultParams","sortOrder") values (${providerId},${model.modelId},${model.displayName},${enabled},true,${tx.json(capabilities)},${tx.json(defaults)},${model.kind === "music" ? 902 : model.modelId.includes("instruct") ? 900 : 901})`;
}
console.log(
JSON.stringify({
mode: apply ? "applied" : "dry-run",
modelId: model.modelId,
enabled,
activationRequired: capabilities.activationRequired,
}),
);
}
});
})()
.catch((e) => {
console.error(e.message?.replace(/postgres:\/\/[^ ]+/g, "[redacted]") || e.name);
process.exitCode = 1;
})
.finally(() => sql.end());