Revert "no message"

This reverts commit 8e7e3af0ba00a2464f75b8e847584c6acf212f08.
This commit is contained in:
zhishi 2026-02-26 18:43:00 +08:00
parent 8e7e3af0ba
commit a9ce229c89
15 changed files with 99 additions and 346 deletions

View File

@ -58,7 +58,7 @@
"jsonwebtoken": "^9.0.3",
"knex": "^3.1.0",
"morgan": "^1.10.1",
"qwen-ai-provider-v5": "^2.1.0",
"qwen-ai-provider": "^0.1.1",
"serialize-error": "^13.0.1",
"sharp": "^0.34.5",
"sqlite3": "^5.1.7",

View File

@ -1,33 +1,7 @@
import { app, BrowserWindow, dialog } from "electron";
import { app, BrowserWindow } from "electron";
import path from "path";
import net from "net";
import startServe, { closeServe } from "src/app";
// 检测端口是否被占用
function checkPortInUse(port: number): Promise<boolean> {
return new Promise((resolve) => {
const server = net.createServer();
server.once('error', (err: NodeJS.ErrnoException) => {
if (err.code === 'EADDRINUSE') {
resolve(true); // 端口被占用
} else {
resolve(false);
}
});
server.once('listening', () => {
server.close();
resolve(false); // 端口可用
});
server.listen(port);
});
}
function createMainWindow(): void {
const isDev = process.env.NODE_ENV === "dev" || !app.isPackaged;
const basePath = isDev ? process.cwd() : app.getAppPath();
@ -47,20 +21,6 @@ function createMainWindow(): void {
void win.loadFile(htmlPath);
}
app.whenReady().then(async () => {
const port = parseInt(process.env.PORT || "60000");
const isPortInUse = await checkPortInUse(port);
if (isPortInUse) {
await dialog.showErrorBox(
"端口被占用",
`端口 ${port} 已被占用,请关闭占用该端口的程序后重试。\n\n您可以使用以下命令查看占用端口的程序\nWindows: netstat -ano | findstr ${port}\nLinux/Mac: lsof -i :${port}`
);
app.quit();
return;
}
createMainWindow();
await startServe();
});

View File

@ -1,4 +1,4 @@
// @routes-hash 2c228db11434e5c7874e23f6fe832d00
// @routes-hash 3cfad40b3c8658b442ab766a9323d740
import { Express } from "express";
import route1 from "./routes/assets/addAssets";
@ -65,20 +65,19 @@ import route61 from "./routes/storyboard/uploadImage";
import route62 from "./routes/task/getTaskApi";
import route63 from "./routes/task/taskDetails";
import route64 from "./routes/user/getUser";
import route65 from "./routes/user/saveUser";
import route66 from "./routes/video/addVideo";
import route67 from "./routes/video/addVideoConfig";
import route68 from "./routes/video/deleteVideoConfig";
import route69 from "./routes/video/generatePrompt";
import route70 from "./routes/video/generateVideo";
import route71 from "./routes/video/getManufacturer";
import route72 from "./routes/video/getVideo";
import route73 from "./routes/video/getVideoConfigs";
import route74 from "./routes/video/getVideoModel";
import route75 from "./routes/video/getVideoStoryboards";
import route76 from "./routes/video/reviseVideoStoryboards";
import route77 from "./routes/video/saveVideo";
import route78 from "./routes/video/upDateVideoConfig";
import route65 from "./routes/video/addVideo";
import route66 from "./routes/video/addVideoConfig";
import route67 from "./routes/video/deleteVideoConfig";
import route68 from "./routes/video/generatePrompt";
import route69 from "./routes/video/generateVideo";
import route70 from "./routes/video/getManufacturer";
import route71 from "./routes/video/getVideo";
import route72 from "./routes/video/getVideoConfigs";
import route73 from "./routes/video/getVideoModel";
import route74 from "./routes/video/getVideoStoryboards";
import route75 from "./routes/video/reviseVideoStoryboards";
import route76 from "./routes/video/saveVideo";
import route77 from "./routes/video/upDateVideoConfig";
export default async (app: Express) => {
app.use("/assets/addAssets", route1);
@ -145,18 +144,17 @@ export default async (app: Express) => {
app.use("/task/getTaskApi", route62);
app.use("/task/taskDetails", route63);
app.use("/user/getUser", route64);
app.use("/user/saveUser", route65);
app.use("/video/addVideo", route66);
app.use("/video/addVideoConfig", route67);
app.use("/video/deleteVideoConfig", route68);
app.use("/video/generatePrompt", route69);
app.use("/video/generateVideo", route70);
app.use("/video/getManufacturer", route71);
app.use("/video/getVideo", route72);
app.use("/video/getVideoConfigs", route73);
app.use("/video/getVideoModel", route74);
app.use("/video/getVideoStoryboards", route75);
app.use("/video/reviseVideoStoryboards", route76);
app.use("/video/saveVideo", route77);
app.use("/video/upDateVideoConfig", route78);
app.use("/video/addVideo", route65);
app.use("/video/addVideoConfig", route66);
app.use("/video/deleteVideoConfig", route67);
app.use("/video/generatePrompt", route68);
app.use("/video/generateVideo", route69);
app.use("/video/getManufacturer", route70);
app.use("/video/getVideo", route71);
app.use("/video/getVideoConfigs", route72);
app.use("/video/getVideoModel", route73);
app.use("/video/getVideoStoryboards", route74);
app.use("/video/reviseVideoStoryboards", route75);
app.use("/video/saveVideo", route76);
app.use("/video/upDateVideoConfig", route77);
}

View File

@ -2,7 +2,7 @@ import express from "express";
import u from "@/utils";
import { z } from "zod";
import { v4 as uuidv4 } from "uuid";
import { success,error } from "@/lib/responseFormat";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
import sharp from "sharp";
const router = express.Router();
@ -124,8 +124,8 @@ export default router.post(
assetsId: id,
});
const apiConfig = await u.getPromptAi("assetsImage");
try{
const contentStr = await u.ai.image(
const contentStr = await u.ai.image(
{
systemPrompt,
prompt: userPrompt,
@ -175,14 +175,6 @@ export default router.post(
// const state = await u.db("t_assets").where("id", id).select("state").first();
res.status(200).send(success({ path, assetsId: id }));
}catch(e){
await u.db("t_image").where("id",imageId).update({
state:"生成失败"
})
const msg = u.error(e).message || "图片生成失败"
return res.status(400).send(error(msg))
}
},
);
async function imageAddText(name: string, imageBuffer: Buffer) {

View File

@ -1,24 +0,0 @@
import express from "express";
import u from "@/utils";
import { z } from "zod";
import { success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
const router = express.Router();
// 获取用户
export default router.post(
"/",
validateFields({
name: z.string(),
password: z.string(),
id: z.number(),
}),
async (req, res) => {
const { name, password, id } = req.body;
await u.db("t_user").where("id", id).update({
name,
password,
});
res.status(200).send(success("保存设置成功"));
},
);

View File

@ -33,6 +33,9 @@ export default router.post(
if (result.filePath) {
filesToDelete.push(result.filePath);
}
if (result.firstFrame) {
filesToDelete.push(result.firstFrame);
}
}
// 删除文件

View File

@ -6,6 +6,8 @@ import { error, success } from "@/lib/responseFormat";
import { validateFields } from "@/middleware/middleware";
import { t_config } from "@/types/database";
import sharp from "sharp";
import fs from "fs";
import path from "path";
const router = express.Router();

View File

@ -10,7 +10,7 @@ import runninghub from "./owned/runninghub";
import apimart from "./owned/apimart";
import other from "./owned/other";
import gemini from "./owned/gemini";
import modelScope from "./owned/modelScope";
const urlToBase64 = async (url: string): Promise<string> => {
const res = await axios.get(url, { responseType: "arraybuffer" });
const base64 = Buffer.from(res.data).toString("base64");
@ -26,7 +26,6 @@ const modelInstance = {
runninghub: runninghub,
// apimart: apimart,
other,
modelScope,
} as const;
export default async (input: ImageConfig, config: AIConfig) => {
@ -36,10 +35,10 @@ export default async (input: ImageConfig, config: AIConfig) => {
const manufacturerFn = modelInstance[manufacturer as keyof typeof modelInstance];
if (!manufacturerFn) if (!manufacturerFn) throw new Error("不支持的图片厂商");
// if (manufacturer !== "other" && manufacturer !== "modelScope") {
// const owned = modelList.find((m) => m.model === model);
// if (!owned) throw new Error("不支持的模型");
// }
if (manufacturer !== "other") {
const owned = modelList.find((m) => m.model === model);
if (!owned) throw new Error("不支持的模型");
}
// 补充图片的 base64 内容类型字符串
if (input.imageBase64 && input.imageBase64.length > 0) {
@ -66,6 +65,7 @@ export default async (input: ImageConfig, config: AIConfig) => {
}
let imageUrl = await manufacturerFn(input, { model, apiKey, baseURL });
console.log("%c Line:68 🍷 imageUrl", "background:#4fff4B", imageUrl);
if (!input.resType) input.resType = "b64";
if (input.resType === "b64" && imageUrl.startsWith("http")) imageUrl = await urlToBase64(imageUrl);
return imageUrl;

View File

@ -19,12 +19,6 @@ const modelList: Owned[] = [
grid: false,
type: "ti2i",
},
// {
// manufacturer: "volcengine",
// model: "doubao-seedream-5-0-260128",
// grid: false,
// type: "ti2i",
// },
//可灵
{
manufacturer: "kling",

View File

@ -1,133 +0,0 @@
import "../type";
import { generateImage, generateText, ModelMessage } from "ai";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { pollTask } from "@/utils/ai/utils";
import u from "@/utils";
import axios from "axios";
function getApiUrl(apiUrl: string) {
if (apiUrl.includes("|")) {
const parts = apiUrl.split("|");
if (parts.length !== 2 || !parts[0].trim() || !parts[1].trim()) {
throw new Error("url 格式错误,请使用 url1|url2 格式");
}
return { requestUrl: parts[0].trim(), queryUrl: parts[1].trim() };
}
throw new Error("请填写正确的url");
}
function template(replaceObj: Record<string, any>, url: string) {
return url.replace(/\{(\w+)\}/g, (match, varName) => {
return replaceObj.hasOwnProperty(varName) ? replaceObj[varName] : match;
});
}
async function compressionPrompt(prompt: string) {
const apiConfigData = await u.getPromptAi("assetsPrompt");
const result = await u.ai.text.invoke(
{
messages: [
{
role: "system",
content: `
Prompt工程师和文本摘要专家2000
1.
2. 2000
3. 2000
4.
5.
2000
`,
},
{
role: "user",
content: prompt,
},
],
},
apiConfigData,
);
return result.text;
}
export default async (input: ImageConfig, config: AIConfig): Promise<string> => {
if (!config.model) throw new Error("缺少Model名称");
if (!config.apiKey) throw new Error("缺少API Key");
const defaultBaseURL = "https://api-inference.modelscope.cn/v1/images/generations|https://api-inference.modelscope.cn/v1/tasks/{id}";
const { requestUrl, queryUrl } = getApiUrl(config.baseURL! ?? defaultBaseURL);
// 根据 size 配置映射到具体尺寸
const sizeMap: Record<string, Record<string, string>> = {
"1K": {
"16:9": "1664x928",
"9:16": "928x1664",
},
"2K": {
"16:9": "2048x1152",
"9:16": "1152x2048",
},
"4K": {
"16:9": "2048x1152",
"9:16": "1152x2048",
},
};
// 构建完整的提示词
const fullPrompt = input.systemPrompt ? `${input.systemPrompt}\n\n${input.prompt}` : input.prompt;
let newPrompt = fullPrompt;
if (fullPrompt.length > 2000) {
let compressed = await compressionPrompt(fullPrompt);
newPrompt = compressed;
}
let mergedImage = input.imageBase64;
if (mergedImage && mergedImage.length) {
const smallImage = await u.imageTools.mergeImages(mergedImage, "5mb");
mergedImage = [smallImage];
}
const size = sizeMap[input.size]?.[input.aspectRatio] ?? "1024x1024";
const taskBody: Record<string, any> = {
model: config.model,
prompt: newPrompt,
negative_prompt: "",
size,
...(mergedImage && mergedImage.length ? { image_url: mergedImage } : {}),
};
const apiKey = config.apiKey.replace("Bearer ", "");
try {
const { data } = await axios.post(requestUrl, taskBody, { headers: { Authorization: `Bearer ${apiKey}`, "X-ModelScope-Async-Mode": "true" } });
if (data.task_status != "SUCCEED") throw new Error(`任务提交失败: ${data || "未知错误"}`);
const taskId = data.task_id;
return await pollTask(async () => {
const { data: queryData } = await axios.get(template({ id: taskId }, queryUrl), {
headers: { Authorization: `Bearer ${apiKey}`, "X-ModelScope-Task-Type": "image_generation" },
});
const { task_status, output_images } = queryData || {};
if (task_status === "FAILED") {
return { completed: false, error: "图片生成失败" };
}
if (task_status === "SUCCEED") {
return { completed: true, url: output_images?.[0] };
}
return { completed: false };
});
} catch (error: any) {
console.error("%c Line:90 🥪 error", "background:#93c0a4", error.response?.data?.errors?.message);
const msg = u.error(error).message || "图片生成失败";
throw new Error(msg);
}
};
async function urlToBase64(url: string): Promise<string> {
const res = await axios.get(url, { responseType: "arraybuffer" });
const base64 = Buffer.from(res.data).toString("base64");
const mimeType = res.headers["content-type"] || "image/png";
return `data:${mimeType};base64,${base64}`;
}

View File

@ -27,7 +27,6 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
// 构建完整的提示词
const fullPrompt = input.systemPrompt ? `${input.systemPrompt}\n\n${input.prompt}` : input.prompt;
const model = config.model;
if (model.includes("gemini") || model.includes("nano")) {
let promptData;
if (input.imageBase64 && input.imageBase64.length) {
@ -70,28 +69,26 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
console.error(JSON.stringify(result.response, null, 2));
throw new Error("图片生成失败");
}
// 匹配所有 markdown 图片 ![...](url)
const mdImgPattern = /!\[.*?\]\((.+?)\)/g;
const matches = [...result.text.matchAll(mdImgPattern)];
for (const match of matches) {
const imgInfo = match[1];
// 检查是否已是 base64
const base64InMd = imgInfo.match(/data:image\/[a-z]+;base64,.+/);
const mdMatch = result.text.match(/^!\[.*?\]\((.+?)\)$/);
if (mdMatch) {
const imgInfo = mdMatch[1];
const base64InMd = imgInfo.match(/data:image\/[a-z]+;base64,(.+)/);
if (base64InMd) {
return imgInfo; // 已经是base64直接返回
return imgInfo;
} else {
return await urlToBase64(imgInfo); // 否则尝试转base64
return await urlToBase64(imgInfo);
}
}
// 检查纯base64字符串
const base64Match = result.text.match(/base64,([A-Za-z0-9+/=]+)/);
if (base64Match) {
return "data:image/jpeg;base64," + base64Match[1];
}
// 检查是否为图片直链
// 检查是否为图片直链 url
if (/^https?:\/\/.*\.(png|jpg|jpeg|gif|webp|bmp)$/i.test(result.text)) {
return await urlToBase64(result.text);
}
// 默认情况
return result.text;
}

View File

@ -8,20 +8,11 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
const apiKey = "Bearer " + config.apiKey.replace(/Bearer\s+/g, "").trim();
const size = input.size === "1K" ? "2K" : input.size;
const sizeMap: Record<string, Record<string, string>> = {
"16:9": {
"2K": "2848x1600",
"4K": "4096x2304",
},
"9:16": {
"2K": "1600x2848",
"4K": "2304x4096",
},
};
const body: Record<string, any> = {
model: config.model,
prompt: input.prompt,
size: sizeMap[input.aspectRatio][size],
size,
response_format: "url",
sequential_image_generation: "disabled",
stream: false,
@ -37,4 +28,4 @@ export default async (input: ImageConfig, config: AIConfig): Promise<string> =>
const msg = u.error(error).message || "Volcengine 图片生成失败";
throw new Error(msg);
}
};
}

View File

@ -25,12 +25,12 @@ interface AIConfig {
const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
if (!config || !config?.model || !config?.apiKey || !config?.manufacturer) throw new Error("请检查模型配置是否正确");
const { model, apiKey, baseURL, manufacturer } = { ...config };
// let owned;
// if (manufacturer == "other" || manufacturer == "modelScope") {
const owned = modelList.find((m) => m.manufacturer === manufacturer);
// } else {
// owned = modelList.find((m) => m.model === model);
// }
let owned;
if (manufacturer == "other") {
owned = modelList.find((m) => m.manufacturer === manufacturer);
} else {
owned = modelList.find((m) => m.model === model);
}
if (!owned) throw new Error("不支持的模型或厂商");
const modelInstance = owned.instance({ apiKey, baseURL: baseURL!, name: "xixixi" });
@ -52,7 +52,7 @@ const buildOptions = async (input: AIInput<any>, config: AIConfig = {}) => {
};
const output = input.output ? (outputBuilders[owned.responseFormat]?.(input.output) ?? null) : null;
const chatModelManufacturer = ["doubao", "other", "openai", "modelScope"];
const chatModelManufacturer = ["doubao", "other", "openai"];
const modelFn = chatModelManufacturer.includes(owned.manufacturer) ? (modelInstance as OpenAIProvider).chat(model!) : modelInstance(model!);
return {
config: {

View File

@ -1,11 +1,11 @@
import { createOpenAI, OpenAIProviderSettings } from "@ai-sdk/openai";
import { createOpenAI } from "@ai-sdk/openai";
import { createDeepSeek } from "@ai-sdk/deepseek";
import { createZhipu } from "zhipu-ai-provider";
import { createQwen } from "qwen-ai-provider-v5";
import { createQwen } from "qwen-ai-provider";
import { createGoogleGenerativeAI } from "@ai-sdk/google";
import { createAnthropic } from "@ai-sdk/anthropic";
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
import { createXai } from "@ai-sdk/xai";
import { createXai } from '@ai-sdk/xai';
interface Owned {
manufacturer: string;
@ -82,15 +82,6 @@ const modelList: Owned[] = [
instance: createOpenAI,
tool: true,
},
{
manufacturer: "doubao",
model: "doubao-seed-2-0-pro-260215",
responseFormat: "object",
image: true,
think: true,
instance: createOpenAI,
tool: true,
},
// GLM
{
manufacturer: "zhipu",
@ -195,25 +186,7 @@ const modelList: Owned[] = [
{
manufacturer: "qwen",
model: "qwen-vl-max",
responseFormat: "object",
image: true,
think: false,
instance: createQwen,
tool: true,
},
{
manufacturer: "qwen",
model: "qwen3.5-plus",
responseFormat: "object",
image: true,
think: false,
instance: createQwen,
tool: true,
},
{
manufacturer: "qwen",
model: "qwen3.5-plus-2026-02-15",
responseFormat: "object",
responseFormat: "schema",
image: true,
think: false,
instance: createQwen,
@ -440,7 +413,7 @@ const modelList: Owned[] = [
tool: true,
},
//xai
{
{
manufacturer: "xai",
model: "grok-3",
responseFormat: "schema",
@ -449,7 +422,7 @@ const modelList: Owned[] = [
instance: createXai,
tool: true,
},
{
{
manufacturer: "xai",
model: "grok-4",
responseFormat: "schema",
@ -458,7 +431,7 @@ const modelList: Owned[] = [
instance: createXai,
tool: true,
},
{
{
manufacturer: "xai",
model: "grok-4.1",
responseFormat: "schema",
@ -467,16 +440,6 @@ const modelList: Owned[] = [
instance: createXai,
tool: true,
},
//魔塔
{
manufacturer: "modelScope",
model: "grok-4.1",
responseFormat: "object",
image: true,
think: false,
instance: createOpenAI,
tool: true,
},
//其他
{
manufacturer: "other",

View File

@ -74,6 +74,15 @@
"@standard-schema/spec" "^1.1.0"
eventsource-parser "^3.0.6"
"@ai-sdk/provider-utils@^2.1.6":
version "2.2.8"
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-2.2.8.tgz#ad11b92d5a1763ab34ba7b5fc42494bfe08b76d1"
integrity sha512-fqhG+4sCVv8x7nFzYnFo19ryhAa3w096Kmc3hWxMQfW/TubPOmt3A6tYZhl4mUfQWWQMsuSkLrtjlWuXBVSGQA==
dependencies:
"@ai-sdk/provider" "1.1.3"
nanoid "^3.3.8"
secure-json-parse "^2.7.0"
"@ai-sdk/provider-utils@^3.0.0":
version "3.0.20"
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-3.0.20.tgz#61d7741065550833eae3ac6440d943e9d3d25120"
@ -83,14 +92,12 @@
"@standard-schema/spec" "^1.0.0"
eventsource-parser "^3.0.6"
"@ai-sdk/provider-utils@^4.0.0":
version "4.0.15"
resolved "https://registry.npmmirror.com/@ai-sdk/provider-utils/-/provider-utils-4.0.15.tgz#d585c7c89cfdf13697a40be5768ecd907a251585"
integrity sha512-8XiKWbemmCbvNN0CLR9u3PQiet4gtEVIrX4zzLxnCj06AwsEDJwJVBbKrEI4t6qE8XRSIvU2irka0dcpziKW6w==
"@ai-sdk/provider@1.1.3", "@ai-sdk/provider@^1.0.7":
version "1.1.3"
resolved "https://registry.npmmirror.com/@ai-sdk/provider/-/provider-1.1.3.tgz#ebdda8077b8d2b3f290dcba32c45ad19b2704681"
integrity sha512-qZMxYJ0qqX/RfnuIaab+zp8UAeJn/ygXXAffR5I4N0n1IrvA6qBsjc8hXLmBiMV2zoXlifkacF7sEFnYnjBcqg==
dependencies:
"@ai-sdk/provider" "3.0.8"
"@standard-schema/spec" "^1.1.0"
eventsource-parser "^3.0.6"
json-schema "^0.4.0"
"@ai-sdk/provider@2.0.1", "@ai-sdk/provider@^2.0.0":
version "2.0.1"
@ -106,13 +113,6 @@
dependencies:
json-schema "^0.4.0"
"@ai-sdk/provider@3.0.8", "@ai-sdk/provider@^3.0.0":
version "3.0.8"
resolved "https://registry.npmmirror.com/@ai-sdk/provider/-/provider-3.0.8.tgz#fd7fac7533c03534ac1d3fb710a6b96e2aa00263"
integrity sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ==
dependencies:
json-schema "^0.4.0"
"@ai-sdk/xai@^3.0.47":
version "3.0.47"
resolved "https://registry.npmmirror.com/@ai-sdk/xai/-/xai-3.0.47.tgz#a8d3e08603865c5e401e19c801c7a80c3f31b890"
@ -3160,6 +3160,11 @@ ms@^2.0.0, ms@^2.1.1, ms@^2.1.3:
resolved "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
nanoid@^3.3.8:
version "3.3.11"
resolved "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b"
integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==
napi-build-utils@^2.0.0:
version "2.0.0"
resolved "https://registry.npmmirror.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e"
@ -3609,13 +3614,13 @@ quick-lru@^5.1.1:
resolved "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932"
integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==
qwen-ai-provider-v5@^2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/qwen-ai-provider-v5/-/qwen-ai-provider-v5-2.1.0.tgz#8672871135bb4a5fda32409c00b70d10637f8a50"
integrity sha512-I+Iv45ymrez1wieZFu0n/lc/lSkbAQMlujWBCfUWBUOf6DizYfvPKaydsojXM7CU8TcqJbYJuN3ofnaxFIwBZA==
qwen-ai-provider@^0.1.1:
version "0.1.1"
resolved "https://registry.npmmirror.com/qwen-ai-provider/-/qwen-ai-provider-0.1.1.tgz#f854379514eed919fe01de20007f6238a8ad2b41"
integrity sha512-7dVu97U7fbOGgCYdaOunC4NQqC+7Or3/Gsbx+P16+Ny4VxST7WJxfUCogQl6D2EDxIJdHGz4akHm+5fyEulmyw==
dependencies:
"@ai-sdk/provider" "^3.0.0"
"@ai-sdk/provider-utils" "^4.0.0"
"@ai-sdk/provider" "^1.0.7"
"@ai-sdk/provider-utils" "^2.1.6"
range-parser@^1.2.1:
version "1.2.1"
@ -3841,6 +3846,11 @@ sax@^1.2.4:
resolved "https://registry.npmmirror.com/sax/-/sax-1.4.4.tgz#f29c2bba80ce5b86f4343b4c2be9f2b96627cf8b"
integrity sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==
secure-json-parse@^2.7.0:
version "2.7.0"
resolved "https://registry.npmmirror.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862"
integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==
semver-compare@^1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"