Merge branch '108' of https://github.com/HBAI-Ltd/Toonflow-app into 108
This commit is contained in:
commit
8b5a8ff9c2
BIN
data/latest.zip
Normal file
BIN
data/latest.zip
Normal file
Binary file not shown.
27
data/update.json
Normal file
27
data/update.json
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
"version": "1.0.8",
|
||||
"time": 1775118545494,
|
||||
"data": {
|
||||
"toonflow": [
|
||||
{
|
||||
"type": "zip",
|
||||
"url": "https://toonflow.oss-cn-beijing.aliyuncs.com/latest/latest.zip"
|
||||
},
|
||||
{
|
||||
"type": "windows",
|
||||
"url": "https://toonflow.oss-cn-beijing.aliyuncs.com/latest/latest.exe"
|
||||
},
|
||||
{
|
||||
"type": "linux",
|
||||
"url": "https://toonflow.oss-cn-beijing.aliyuncs.com/latest/latest.AppImage"
|
||||
},
|
||||
{
|
||||
"type": "macos",
|
||||
"url": "https://toonflow.oss-cn-beijing.aliyuncs.com/latest/latest.dmg"
|
||||
}
|
||||
],
|
||||
"github": [],
|
||||
"atomgit": [],
|
||||
"gitee": []
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 169 KiB |
2282
data/web/index.html
2282
data/web/index.html
File diff suppressed because one or more lines are too long
BIN
docs/g-star.png
Normal file
BIN
docs/g-star.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
@ -13,19 +13,16 @@ declare const __APP_VERSION__: string | undefined;
|
||||
* 将 extraResources 中的 data 目录复制到用户数据目录(跳过已存在的文件,保留用户修改)
|
||||
*/
|
||||
|
||||
function getVersionFromFile(filePath: string): string | null {
|
||||
function getVersionFromUpdateJson(filePath: string): string | null {
|
||||
try {
|
||||
if (fs.existsSync(filePath)) {
|
||||
return fs.readFileSync(filePath, "utf8").trim();
|
||||
const data = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
||||
return data.version ?? null;
|
||||
}
|
||||
} catch {}
|
||||
return null;
|
||||
}
|
||||
|
||||
function writeVersionToFile(filePath: string, version: string): void {
|
||||
fs.writeFileSync(filePath, version, { encoding: "utf8" });
|
||||
}
|
||||
|
||||
function copyDirForce(src: string, dest: string): void {
|
||||
if (!fs.existsSync(src)) return;
|
||||
if (fs.existsSync(dest)) {
|
||||
@ -37,14 +34,13 @@ function copyDirForce(src: string, dest: string): void {
|
||||
function initializeData(): void {
|
||||
const srcDir = path.join(process.resourcesPath, "data");
|
||||
const destDir = path.join(app.getPath("userData"), "data");
|
||||
const versionFile = path.join(destDir, "version.txt");
|
||||
const updateJsonFile = path.join(destDir, "update.json");
|
||||
const currentVersion = typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "0.0.0";
|
||||
const userVersion = getVersionFromFile(versionFile);
|
||||
const userVersion = getVersionFromUpdateJson(updateJsonFile);
|
||||
|
||||
// 首次安装或无version.txt,直接全量拷贝
|
||||
// 首次安装或无update.json,直接全量拷贝
|
||||
if (!fs.existsSync(destDir) || !userVersion) {
|
||||
copyDirRecursive(srcDir, destDir);
|
||||
writeVersionToFile(versionFile, currentVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -52,7 +48,6 @@ function initializeData(): void {
|
||||
if (userVersion !== currentVersion) {
|
||||
copyDirForce(path.join(srcDir, "serve"), path.join(destDir, "serve"));
|
||||
copyDirForce(path.join(srcDir, "web"), path.join(destDir, "web"));
|
||||
writeVersionToFile(versionFile, currentVersion);
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +56,7 @@ function copyDirRecursive(src: string, dest: string): void {
|
||||
if (!fs.existsSync(dest)) fs.mkdirSync(dest, { recursive: true });
|
||||
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
||||
// 跳过 oss 文件夹和 db2.sqlite 文件
|
||||
if (entry.isDirectory() && entry.name === "logs") continue;
|
||||
if (entry.isDirectory() && entry.name === "oss") continue;
|
||||
if (!entry.isDirectory() && entry.name === "db2.sqlite") continue;
|
||||
const srcPath = path.join(src, entry.name);
|
||||
|
||||
@ -43,12 +43,23 @@ export async function decisionAI(ctx: AgentContext) {
|
||||
const skill = path.join(u.getPath("skills"), "production_agent_decision.md");
|
||||
const prompt = await fs.promises.readFile(skill, "utf-8");
|
||||
|
||||
const projectInfo = await u.db("o_project").where("id", ctx.resTool.data.projectId).first();
|
||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${ctx.resTool.data.projectId}`);
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(":");
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(":");
|
||||
const data = await u.db("o_vendorConfig").where("id", id).select("models").first();
|
||||
const models = JSON.parse(data!.models!);
|
||||
const findData = models.find((i: any) => i.modelName == name);
|
||||
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
||||
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
||||
|
||||
|
||||
const mem = buildMemPrompt(await memory.get(text));
|
||||
|
||||
const { textStream } = await u.Ai.Text("productionAgent").stream({
|
||||
messages: [
|
||||
{ role: "system", content: prompt },
|
||||
{ role: "assistant", content: mem },
|
||||
{ role: "assistant", content: mem + "\n" + modelInfo },
|
||||
{ role: "user", content: text },
|
||||
],
|
||||
abortSignal,
|
||||
@ -138,13 +149,20 @@ function createSubAgent(parentCtx: AgentContext) {
|
||||
"分镜面板:<storyboardItem videoDesc='视频描述' prompt=提示词内容 track='分组' duration='视频推荐时间' associateAssetsIds='[该分镜所需的资产ID列表]'></storyboardItem>",
|
||||
"```",
|
||||
].join("\n");
|
||||
const projectData = await u.db("o_project").where("id", resTool.data.projectId).first();
|
||||
const modelInfo = `项目使用的模型如下:\n图像模型:${projectData?.imageModel}\n视频模型:${projectData?.videoModel}`;
|
||||
|
||||
|
||||
const projectInfo = await u.db("o_project").where("id", resTool.data.projectId).first();
|
||||
if (!projectInfo) throw new Error(`项目不存在,ID: ${resTool.data.projectId}`);
|
||||
const artSkills = await createArtSkills(projectInfo?.artStyle!);
|
||||
|
||||
const [_, imageModelName] = projectInfo.imageModel!.split(":");
|
||||
const [id, videoModelName] = projectInfo.videoModel!.split(":");
|
||||
const data = await u.db("o_vendorConfig").where("id", id).select("models").first();
|
||||
const models = JSON.parse(data!.models!);
|
||||
const findData = models.find((i: any) => i.modelName == name);
|
||||
const isRef = findData.mode.every((i: any) => Array.isArray(i));
|
||||
const modelInfo = `项目使用的模型如下:\n图像模型:${imageModelName}\n视频模型:${videoModelName}\n多参:${isRef ? "是" : "否"}`;
|
||||
|
||||
return runAgent({
|
||||
prompt,
|
||||
system: systemPrompt + addPrompt,
|
||||
@ -194,7 +212,6 @@ async function createArtSkills(artName: string) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
function removeAllXmlTags(text: string): string {
|
||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?>([\s\S]*?)<\/\1>/g, "");
|
||||
text = text.replace(/<([a-zA-Z][\w-]*)(\s+[^>]*)?\/>/g, "");
|
||||
|
||||
@ -95,8 +95,12 @@ export default router.post(
|
||||
`;
|
||||
|
||||
const { text } = await u.Ai.Text("universalAi").invoke({
|
||||
system: `${videoPrompt?.data}\n${visualManual}\n${directorManual}`,
|
||||
system: videoPrompt?.data!,
|
||||
messages: [
|
||||
{
|
||||
role: "assistant",
|
||||
content: `${visualManual}\n${directorManual}`,
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: content,
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import express from "express";
|
||||
import { success } from "@/lib/responseFormat";
|
||||
import { success, error } from "@/lib/responseFormat";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
import { z } from "zod";
|
||||
const router = express.Router();
|
||||
|
||||
import fs from "fs";
|
||||
@ -17,21 +19,49 @@ const APP_VERSION: string = (() => {
|
||||
return pkg.version;
|
||||
})();
|
||||
|
||||
export default router.post("/", async (req, res) => {
|
||||
const tagger = "1.1.0";
|
||||
const taggerList = tagger.split(".").map(Number);
|
||||
const currentVersionList = APP_VERSION.split(".").map(Number);
|
||||
//对比Major
|
||||
if (taggerList[0] > currentVersionList[0]) {
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false }));
|
||||
}
|
||||
//对比Minor
|
||||
if (taggerList[1] > currentVersionList[1]) {
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false }));
|
||||
}
|
||||
//Patch
|
||||
if (taggerList[2] > currentVersionList[2]) {
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false }));
|
||||
}
|
||||
return res.status(200).send(success({ needUpdate: false, latestVersion: tagger, reinstall: false }));
|
||||
});
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
source: z.enum(["toonflow", "github", "gitee", "atomgit"]),
|
||||
}),
|
||||
async (req, res) => {
|
||||
const { source } = req.body;
|
||||
|
||||
const getUrl = "https://toonflow.oss-cn-beijing.aliyuncs.com/update.json";
|
||||
|
||||
const versionInfo = await fetch(getUrl).then((res) => res.json());
|
||||
if (!versionInfo) return res.status(400).send(error("无法获取版本信息"));
|
||||
const { version: tagger, time, data } = versionInfo;
|
||||
|
||||
const sourceData = data[source];
|
||||
if (!sourceData) return res.status(400).send(error("无法获取该源的下载信息"));
|
||||
|
||||
const platformType: Record<string, string> = {
|
||||
win32: "windows",
|
||||
darwin: "macos",
|
||||
linux: "linux",
|
||||
};
|
||||
|
||||
const zipItem = sourceData.find((d: any) => d.type === "zip");
|
||||
const installerItem = sourceData.find((d: any) => d.type === platformType[process.platform]);
|
||||
|
||||
const taggerList = tagger.split(".").map(Number);
|
||||
const currentVersionList = APP_VERSION.split(".").map(Number);
|
||||
//对比Major
|
||||
if (taggerList[0] > currentVersionList[0]) {
|
||||
if (!installerItem) return res.status(400).send(error("该源暂无适用于当前系统的安装包"));
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: true, time, url: installerItem.url }));
|
||||
}
|
||||
//对比Minor
|
||||
if (taggerList[1] > currentVersionList[1]) {
|
||||
if (!installerItem) return res.status(400).send(error("该源暂无适用于当前系统的安装包"));
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: true, time, url: installerItem.url }));
|
||||
}
|
||||
//Patch
|
||||
if (taggerList[2] > currentVersionList[2]) {
|
||||
if (!zipItem) return res.status(400).send(error("该源暂无增量更新包"));
|
||||
return res.status(200).send(success({ needUpdate: true, latestVersion: tagger, reinstall: false, time, url: zipItem.url }));
|
||||
}
|
||||
return res.status(200).send(success({ needUpdate: false, latestVersion: tagger, reinstall: false, time }));
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,238 +1,64 @@
|
||||
import express from "express";
|
||||
import { success, error } from "@/lib/responseFormat";
|
||||
import getPath from "@/utils/getPath";
|
||||
import z from "zod";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
import u from "@/utils";
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import axios from "axios";
|
||||
import compressing from "compressing";
|
||||
import { validateFields } from "@/middleware/middleware";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
import path from "path";
|
||||
import { success, error } from "@/lib/responseFormat";
|
||||
const router = express.Router();
|
||||
|
||||
/** 仓库源配置 */
|
||||
const REPO_SOURCES = {
|
||||
github: {
|
||||
repo: "HBAI-Ltd/Toonflow-app",
|
||||
api: "https://api.github.com/repos/HBAI-Ltd/Toonflow-app/releases/latest",
|
||||
headers: { Accept: "application/vnd.github.v3+json" },
|
||||
},
|
||||
gitee: {
|
||||
repo: "HBAI-Ltd/Toonflow-app",
|
||||
api: "https://gitee.com/api/v5/repos/HBAI-Ltd/Toonflow-app/releases/latest",
|
||||
headers: {},
|
||||
},
|
||||
} as const;
|
||||
|
||||
type SourceType = keyof typeof REPO_SOURCES;
|
||||
|
||||
function normalizeAssets(source: SourceType, release: any): { name: string; browser_download_url: string }[] {
|
||||
if (source === "github") {
|
||||
return (release.assets ?? []).map((a: any) => ({
|
||||
name: a.name,
|
||||
browser_download_url: a.browser_download_url,
|
||||
}));
|
||||
const runInstaller = (installerPath: string) => {
|
||||
const { exec } = require("child_process");
|
||||
if (process.platform === "darwin") {
|
||||
exec(`open "${installerPath}"`);
|
||||
} else {
|
||||
if (process.platform !== "win32") fs.chmodSync(installerPath, 0o755);
|
||||
exec(`"${installerPath}"`);
|
||||
}
|
||||
return (release.assets ?? []).map((a: any) => ({
|
||||
name: a.name,
|
||||
browser_download_url: a.browser_download_url,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
/** 获取当前系统平台和架构标识,用于匹配安装包文件名 */
|
||||
function getPlatformArch(): { platform: string; arch: string } {
|
||||
const platform = process.platform === "win32" ? "win" : process.platform === "darwin" ? "mac" : "linux";
|
||||
const arch = process.arch === "arm64" ? "arm64" : "x64";
|
||||
return { platform, arch };
|
||||
}
|
||||
|
||||
/** 匹配安装包资产(.exe / .dmg / .AppImage / .portable.exe) */
|
||||
function findInstallerAsset(assets: any[]): any | null {
|
||||
const { platform, arch } = getPlatformArch();
|
||||
const installerExtensions: Record<string, string[]> = {
|
||||
win: [".exe"],
|
||||
mac: [".dmg"],
|
||||
linux: [".AppImage"],
|
||||
};
|
||||
const exts = installerExtensions[platform] || [".exe"];
|
||||
// 优先找 nsis 安装包(排除 portable),如果没有再找 portable
|
||||
return (
|
||||
assets.find(
|
||||
(a: any) =>
|
||||
exts.some((ext) => a.name.endsWith(ext)) &&
|
||||
a.name.includes(arch) &&
|
||||
!a.name.toLowerCase().includes("portable") &&
|
||||
!a.name.endsWith(".blockmap"),
|
||||
) ??
|
||||
assets.find((a: any) => exts.some((ext) => a.name.endsWith(ext)) && a.name.includes(arch) && !a.name.endsWith(".blockmap")) ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载文件到指定路径(支持流式写入与进度)
|
||||
*/
|
||||
async function downloadFile(url: string, destPath: string): Promise<void> {
|
||||
const dir = path.dirname(destPath);
|
||||
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||
|
||||
const response = await axios.get(url, {
|
||||
responseType: "stream",
|
||||
headers: { Accept: "application/octet-stream" },
|
||||
timeout: 600_000, // 10 分钟超时
|
||||
});
|
||||
|
||||
const writer = fs.createWriteStream(destPath);
|
||||
response.data.pipe(writer);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
writer.on("finish", resolve);
|
||||
writer.on("error", reject);
|
||||
});
|
||||
}
|
||||
export default router.post(
|
||||
"/",
|
||||
validateFields({
|
||||
source: z.enum(["github", "gitee"]),
|
||||
url: z.url(),
|
||||
reinstall: z.boolean(),
|
||||
latestVersion: z.string(),
|
||||
}),
|
||||
async (req, res) => {
|
||||
try {
|
||||
const { reinstall, latestVersion, source } = req.body as {
|
||||
reinstall: boolean;
|
||||
latestVersion: string;
|
||||
source: string;
|
||||
};
|
||||
|
||||
if (!latestVersion) {
|
||||
return res.status(400).send(error("缺少目标版本号 latestVersion"));
|
||||
const { reinstall, url } = req.body;
|
||||
const rootDir = u.getPath(["temp"]);
|
||||
fs.mkdirSync(rootDir, { recursive: true });
|
||||
if (reinstall) {
|
||||
const response = await axios.get(url, { responseType: "arraybuffer" });
|
||||
const ext =
|
||||
path.extname(new URL(url).pathname) || (process.platform === "win32" ? ".exe" : process.platform === "darwin" ? ".dmg" : ".AppImage");
|
||||
const installerPath = path.join(rootDir, `latest${ext}`);
|
||||
fs.writeFileSync(installerPath, response.data);
|
||||
runInstaller(installerPath);
|
||||
res.status(200).send(success("安装包已下载并启动"));
|
||||
} else {
|
||||
const zip = await axios.get(url, { responseType: "arraybuffer" }).then((res) => res.data);
|
||||
fs.writeFileSync(`${rootDir}/latest.zip`, zip);
|
||||
await compressing.zip.uncompress(`${rootDir}/latest.zip`, rootDir);
|
||||
const tempServerPath = u.getPath(["temp", "serve"]);
|
||||
if (fs.existsSync(tempServerPath)) {
|
||||
fs.cpSync(tempServerPath, u.getPath(["serve"]), { recursive: true });
|
||||
}
|
||||
|
||||
const sourceConfig = REPO_SOURCES[source as SourceType] ?? REPO_SOURCES.github;
|
||||
|
||||
// ─── 获取 Release 信息(支持 GitHub / Gitee) ──────────────────────
|
||||
let releaseRes;
|
||||
try {
|
||||
releaseRes = await axios.get(sourceConfig.api, {
|
||||
headers: sourceConfig.headers,
|
||||
timeout: 30_000,
|
||||
});
|
||||
} catch (e) {
|
||||
return res.status(500).send(error(`获取 ${source} Release 信息失败`));
|
||||
const webPath = u.getPath(["temp", "web"]);
|
||||
if (fs.existsSync(webPath)) {
|
||||
fs.cpSync(webPath, u.getPath(["web"]), { recursive: true });
|
||||
}
|
||||
|
||||
const release = releaseRes.data;
|
||||
|
||||
const assets = normalizeAssets(source as SourceType, release);
|
||||
|
||||
if (reinstall) {
|
||||
// ═══════════════ 模式 A:下载完整安装包 ═══════════════
|
||||
const installerAsset = findInstallerAsset(assets);
|
||||
|
||||
if (!installerAsset) {
|
||||
return res.status(404).send(error("未找到当前平台的安装包,请前往 GitHub Releases 手动下载"));
|
||||
}
|
||||
|
||||
const tempDir = getPath(["temp"]);
|
||||
|
||||
if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir, { recursive: true });
|
||||
const installerPath = path.join(tempDir, installerAsset.name);
|
||||
|
||||
// 如果已经下载过相同文件,跳过下载
|
||||
if (!fs.existsSync(installerPath)) {
|
||||
await downloadFile(installerAsset.browser_download_url, installerPath);
|
||||
}
|
||||
|
||||
// 使用 shell 打开安装程序
|
||||
const sub = spawn("cmd", ["/c", `${installerPath}`], {
|
||||
cwd: tempDir,
|
||||
detached: true,
|
||||
stdio: "ignore",
|
||||
windowsHide: false,
|
||||
});
|
||||
|
||||
sub.unref();
|
||||
|
||||
return res.status(200).send(
|
||||
success({
|
||||
type: "reinstall",
|
||||
version: latestVersion,
|
||||
filePath: installerPath,
|
||||
message: "安装包已下载并打开,请按照安装向导完成更新",
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
// ═══════════════ 模式 B:data 补丁热更新 ═══════════════
|
||||
const patchAsset = assets.find((a: any) => a.name.startsWith(latestVersion) && a.name.endsWith(".zip")) ?? null;
|
||||
|
||||
if (!patchAsset) {
|
||||
return res.status(404).send(error("未找到 data 补丁包,请前往 GitHub Releases 手动下载"));
|
||||
}
|
||||
//
|
||||
|
||||
const tempDir = getPath(["temp"]);
|
||||
if (!fs.existsSync(tempDir)) fs.mkdirSync(tempDir, { recursive: true });
|
||||
const patchZipPath = path.join(tempDir, `${latestVersion}.zip`);
|
||||
|
||||
// 下载补丁 zip
|
||||
await downloadFile(patchAsset.browser_download_url, patchZipPath);
|
||||
|
||||
// 解压覆盖到 data 目录(同名文件夹先删除再解压,确保完全替换)
|
||||
const dataDir = getPath();
|
||||
|
||||
// 先读取 zip 内的顶层文件夹/文件列表,删除 data 目录下的同名项
|
||||
const zipStream = new compressing.zip.UncompressStream({ source: patchZipPath, zipFileNameEncoding: "utf8" });
|
||||
const topLevelEntries = new Set<string>();
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
zipStream.on("entry", (_header: any, stream: any, next: () => void) => {
|
||||
const entryName: string = _header.name || "";
|
||||
// 取顶层名称(第一个 / 之前的部分)
|
||||
const topName = entryName.split("/")[0];
|
||||
if (topName) topLevelEntries.add(topName);
|
||||
stream.resume();
|
||||
next();
|
||||
});
|
||||
zipStream.on("finish", resolve);
|
||||
zipStream.on("error", reject);
|
||||
});
|
||||
|
||||
// 删除 data 目录下与 zip 顶层同名的文件夹/文件
|
||||
for (const name of topLevelEntries) {
|
||||
const targetPath = path.join(dataDir, name);
|
||||
if (fs.existsSync(targetPath)) {
|
||||
const stat = fs.statSync(targetPath);
|
||||
if (stat.isDirectory()) {
|
||||
fs.rmSync(targetPath, { recursive: true, force: true });
|
||||
} else {
|
||||
fs.unlinkSync(targetPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await compressing.zip.uncompress(patchZipPath, dataDir, { zipFileNameEncoding: "utf8" });
|
||||
|
||||
// 清理临时文件
|
||||
try {
|
||||
fs.unlinkSync(patchZipPath);
|
||||
} catch {
|
||||
// 忽略清理失败
|
||||
}
|
||||
|
||||
return res.status(200).send(
|
||||
success({
|
||||
type: "patch",
|
||||
version: latestVersion,
|
||||
message: "补丁更新完成,请重启应用以使更新生效",
|
||||
restartRequired: true,
|
||||
}),
|
||||
);
|
||||
const tempSkillsPath = u.getPath(["temp", "skills"]);
|
||||
if (fs.existsSync(tempSkillsPath)) {
|
||||
fs.cpSync(tempSkillsPath, u.getPath(["skills"]), { recursive: true, force: false });
|
||||
}
|
||||
} catch (err: any) {
|
||||
console.error("[downloadApp] 更新失败:", err);
|
||||
const message = err?.response?.status === 404 ? "未找到更新资源,请检查版本号或稍后重试" : (err?.message ?? "更新失败,请稍后重试");
|
||||
return res.status(500).send(error(message));
|
||||
const tempModelsPath = u.getPath(["temp", "models"]);
|
||||
if (fs.existsSync(tempModelsPath)) {
|
||||
fs.cpSync(tempModelsPath, u.getPath(["models"]), { recursive: true, force: false });
|
||||
}
|
||||
fs.rmSync(rootDir, { recursive: true, force: true });
|
||||
res.status(200).send(success("更新成功,5秒后重启"));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@ -14,7 +14,5 @@ export default router.post("/", async (req, res) => {
|
||||
onlyFiles: true,
|
||||
});
|
||||
|
||||
console.log("%c Line:15 🍺 entries", "background:#e41a6a", entries);
|
||||
|
||||
res.status(200).send(success(entries));
|
||||
});
|
||||
|
||||
67
src/types/database.d.ts
vendored
67
src/types/database.d.ts
vendored
@ -1,60 +1,10 @@
|
||||
// @db-hash 7af86e2bafe5cab7d175eb68cf76ed7a
|
||||
<<<<<<< HEAD
|
||||
// @db-hash 6fa5017e455bc367c9c902ba574d11b4
|
||||
=======
|
||||
// @db-hash 35cf00f711e9d4df398703de70511684
|
||||
>>>>>>> c7be353ef92bb888df3af432bb21220b2fd35d7d
|
||||
//该文件由脚本自动生成,请勿手动修改
|
||||
|
||||
export interface _o_storyboard_old_20260402 {
|
||||
'createTime'?: number | null;
|
||||
'duration'?: string | null;
|
||||
'filePath'?: string | null;
|
||||
'flowId'?: number | null;
|
||||
'id'?: number;
|
||||
'index'?: number | null;
|
||||
'projectId'?: number | null;
|
||||
'prompt'?: string | null;
|
||||
'reason'?: string | null;
|
||||
'scriptId'?: number | null;
|
||||
'state'?: string | null;
|
||||
'trackId'?: number | null;
|
||||
}
|
||||
export interface _o_storyboard_old_20260402_1 {
|
||||
'createTime'?: number | null;
|
||||
'duration'?: string | null;
|
||||
'filePath'?: string | null;
|
||||
'flowId'?: number | null;
|
||||
'id'?: number;
|
||||
'index'?: number | null;
|
||||
'projectId'?: number | null;
|
||||
'prompt'?: string | null;
|
||||
'reason'?: string | null;
|
||||
'scriptId'?: number | null;
|
||||
'shouldGenerateImage'?: number | null;
|
||||
'state'?: string | null;
|
||||
'track'?: string | null;
|
||||
'trackId'?: number | null;
|
||||
'videoPrompt'?: string | null;
|
||||
}
|
||||
export interface _o_vendorConfig_old_20260401 {
|
||||
'author'?: string | null;
|
||||
'code'?: string | null;
|
||||
'createTime'?: number | null;
|
||||
'description'?: string | null;
|
||||
'enableEnglish'?: number | null;
|
||||
'icon'?: string | null;
|
||||
'id'?: string;
|
||||
'inputs'?: string | null;
|
||||
'inputValues'?: string | null;
|
||||
'models'?: string | null;
|
||||
'name'?: string | null;
|
||||
}
|
||||
export interface _o_videoTrack_old_20260402 {
|
||||
'id'?: number;
|
||||
'projectId'?: number | null;
|
||||
'prompt'?: string | null;
|
||||
'reason'?: string | null;
|
||||
'scriptId'?: number | null;
|
||||
'selectVideoId'?: number | null;
|
||||
'state'?: string | null;
|
||||
'videoId'?: number | null;
|
||||
}
|
||||
export interface memories {
|
||||
'content': string;
|
||||
'createTime': number;
|
||||
@ -130,7 +80,6 @@ export interface o_image {
|
||||
'filePath'?: string | null;
|
||||
'id'?: number;
|
||||
'model'?: string | null;
|
||||
'reason'?: string | null;
|
||||
'resolution'?: string | null;
|
||||
'state'?: string | null;
|
||||
'type'?: string | null;
|
||||
@ -165,6 +114,7 @@ export interface o_outlineNovel {
|
||||
export interface o_project {
|
||||
'artStyle'?: string | null;
|
||||
'createTime'?: number | null;
|
||||
'directorManual'?: string | null;
|
||||
'id'?: number | null;
|
||||
'imageModel'?: string | null;
|
||||
'imageQuality'?: string | null;
|
||||
@ -255,7 +205,6 @@ export interface o_vendorConfig {
|
||||
'createTime'?: number | null;
|
||||
'description'?: string | null;
|
||||
'enable'?: number | null;
|
||||
'enableEnglish'?: number | null;
|
||||
'icon'?: string | null;
|
||||
'id'?: string;
|
||||
'inputs'?: string | null;
|
||||
@ -285,10 +234,6 @@ export interface o_videoTrack {
|
||||
}
|
||||
|
||||
export interface DB {
|
||||
"_o_storyboard_old_20260402": _o_storyboard_old_20260402;
|
||||
"_o_storyboard_old_20260402_1": _o_storyboard_old_20260402_1;
|
||||
"_o_vendorConfig_old_20260401": _o_vendorConfig_old_20260401;
|
||||
"_o_videoTrack_old_20260402": _o_videoTrack_old_20260402;
|
||||
"memories": memories;
|
||||
"o_agentDeploy": o_agentDeploy;
|
||||
"o_agentWorkData": o_agentWorkData;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user