koishi-plugin-aka-ai-generator 0.6.9 → 0.6.10
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/lib/index.js +90 -30
- package/lib/providers/gemini.d.ts +1 -1
- package/lib/providers/gptgod.d.ts +1 -1
- package/lib/providers/types.d.ts +2 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -295,7 +295,7 @@ var GptGodProvider = class {
|
|
|
295
295
|
constructor(config) {
|
|
296
296
|
this.config = config;
|
|
297
297
|
}
|
|
298
|
-
async generateImages(prompt, imageUrls, numImages) {
|
|
298
|
+
async generateImages(prompt, imageUrls, numImages, onImageGenerated) {
|
|
299
299
|
const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls];
|
|
300
300
|
const logger = this.config.logger;
|
|
301
301
|
const ctx = this.config.ctx;
|
|
@@ -410,7 +410,18 @@ var GptGodProvider = class {
|
|
|
410
410
|
throw new Error(`生成失败:${shortError}`);
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
|
-
|
|
413
|
+
for (let imgIdx = 0; imgIdx < images.length; imgIdx++) {
|
|
414
|
+
const imageUrl = images[imgIdx];
|
|
415
|
+
const currentIndex = allImages.length;
|
|
416
|
+
allImages.push(imageUrl);
|
|
417
|
+
if (onImageGenerated) {
|
|
418
|
+
try {
|
|
419
|
+
await onImageGenerated(imageUrl, currentIndex, numImages);
|
|
420
|
+
} catch (callbackError) {
|
|
421
|
+
logger.warn("图片生成回调函数执行失败", { error: sanitizeError(callbackError) });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
414
425
|
logger.success("GPTGod 图像编辑 API 调用成功", { current: i + 1, total: numImages });
|
|
415
426
|
success = true;
|
|
416
427
|
break;
|
|
@@ -609,7 +620,7 @@ var GeminiProvider = class {
|
|
|
609
620
|
constructor(config) {
|
|
610
621
|
this.config = config;
|
|
611
622
|
}
|
|
612
|
-
async generateImages(prompt, imageUrls, numImages) {
|
|
623
|
+
async generateImages(prompt, imageUrls, numImages, onImageGenerated) {
|
|
613
624
|
let urls = [];
|
|
614
625
|
if (Array.isArray(imageUrls)) {
|
|
615
626
|
urls = imageUrls.filter((url) => url && typeof url === "string" && url.trim());
|
|
@@ -682,8 +693,19 @@ var GeminiProvider = class {
|
|
|
682
693
|
});
|
|
683
694
|
} else {
|
|
684
695
|
logger.success("Gemini API 调用成功", { current: i + 1, total: numImages, imagesCount: images.length });
|
|
696
|
+
for (let imgIdx = 0; imgIdx < images.length; imgIdx++) {
|
|
697
|
+
const imageUrl = images[imgIdx];
|
|
698
|
+
const currentIndex = allImages.length;
|
|
699
|
+
allImages.push(imageUrl);
|
|
700
|
+
if (onImageGenerated) {
|
|
701
|
+
try {
|
|
702
|
+
await onImageGenerated(imageUrl, currentIndex, numImages);
|
|
703
|
+
} catch (callbackError) {
|
|
704
|
+
logger.warn("图片生成回调函数执行失败", { error: sanitizeError(callbackError) });
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
}
|
|
685
708
|
}
|
|
686
|
-
allImages.push(...images);
|
|
687
709
|
} catch (error) {
|
|
688
710
|
const sanitizedError = sanitizeError(error);
|
|
689
711
|
const safeMessage = typeof error?.message === "string" ? sanitizeString(error.message) : "未知错误";
|
|
@@ -1505,7 +1527,7 @@ function apply(ctx, config) {
|
|
|
1505
1527
|
return { images: collectedImages, text: collectedText };
|
|
1506
1528
|
}
|
|
1507
1529
|
__name(getInputData, "getInputData");
|
|
1508
|
-
async function requestProviderImages(prompt, imageUrls, numImages, requestContext) {
|
|
1530
|
+
async function requestProviderImages(prompt, imageUrls, numImages, requestContext, onImageGenerated) {
|
|
1509
1531
|
const providerType = requestContext?.provider || config.provider;
|
|
1510
1532
|
const targetModelId = requestContext?.modelId;
|
|
1511
1533
|
const providerInstance = getProviderInstance(providerType, targetModelId);
|
|
@@ -1516,7 +1538,7 @@ function apply(ctx, config) {
|
|
|
1516
1538
|
numImages
|
|
1517
1539
|
});
|
|
1518
1540
|
}
|
|
1519
|
-
return await providerInstance.generateImages(prompt, imageUrls, numImages);
|
|
1541
|
+
return await providerInstance.generateImages(prompt, imageUrls, numImages, onImageGenerated);
|
|
1520
1542
|
}
|
|
1521
1543
|
__name(requestProviderImages, "requestProviderImages");
|
|
1522
1544
|
async function processImageWithTimeout(session, img, prompt, styleName, requestContext, displayInfo, mode = "single") {
|
|
@@ -1612,21 +1634,38 @@ ${infoParts.join("\n")}`;
|
|
|
1612
1634
|
}
|
|
1613
1635
|
statusMessage += "...";
|
|
1614
1636
|
await session.send(statusMessage);
|
|
1615
|
-
const
|
|
1637
|
+
const generatedImages = [];
|
|
1638
|
+
let creditDeducted = false;
|
|
1639
|
+
const onImageGenerated = /* @__PURE__ */ __name(async (imageUrl, index, total) => {
|
|
1640
|
+
if (checkTimeout && checkTimeout()) {
|
|
1641
|
+
throw new Error("命令执行超时");
|
|
1642
|
+
}
|
|
1643
|
+
generatedImages.push(imageUrl);
|
|
1644
|
+
if (!creditDeducted && generatedImages.length > 0) {
|
|
1645
|
+
creditDeducted = true;
|
|
1646
|
+
await recordUserUsage(session, styleName, total);
|
|
1647
|
+
logger.info("流式处理:第一张图片生成,积分已扣除", {
|
|
1648
|
+
userId,
|
|
1649
|
+
totalImages: total,
|
|
1650
|
+
currentIndex: index
|
|
1651
|
+
});
|
|
1652
|
+
}
|
|
1653
|
+
await session.send(import_koishi2.h.image(imageUrl));
|
|
1654
|
+
logger.debug("流式处理:图片已发送", { index: index + 1, total });
|
|
1655
|
+
if (total > 1 && index < total - 1) {
|
|
1656
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1657
|
+
}
|
|
1658
|
+
}, "onImageGenerated");
|
|
1659
|
+
const images = await requestProviderImages(finalPrompt, imageUrls, imageCount, requestContext, onImageGenerated);
|
|
1616
1660
|
if (checkTimeout && checkTimeout()) throw new Error("命令执行超时");
|
|
1617
1661
|
if (images.length === 0) {
|
|
1618
1662
|
return "图像处理失败:未能生成图片";
|
|
1619
1663
|
}
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
for (let i = 0; i < images.length; i++) {
|
|
1624
|
-
if (checkTimeout && checkTimeout()) break;
|
|
1625
|
-
await session.send(import_koishi2.h.image(images[i]));
|
|
1626
|
-
if (images.length > 1 && i < images.length - 1) {
|
|
1627
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1628
|
-
}
|
|
1664
|
+
if (!creditDeducted) {
|
|
1665
|
+
await recordUserUsage(session, styleName, images.length);
|
|
1666
|
+
logger.warn("流式处理:积分在最后扣除(异常情况)", { userId, imagesCount: images.length });
|
|
1629
1667
|
}
|
|
1668
|
+
await session.send("图像处理完成!");
|
|
1630
1669
|
} finally {
|
|
1631
1670
|
userManager.endTask(userId);
|
|
1632
1671
|
}
|
|
@@ -1648,7 +1687,8 @@ ${infoParts.join("\n")}`;
|
|
|
1648
1687
|
}
|
|
1649
1688
|
const userPromptText = userPromptParts.join(" - ");
|
|
1650
1689
|
const numImages = options?.num || config.defaultNumImages;
|
|
1651
|
-
const
|
|
1690
|
+
const userName = session.username || session.userId || "未知用户";
|
|
1691
|
+
const limitCheck = await userManager.checkAndReserveQuota(session.userId, userName, numImages, config);
|
|
1652
1692
|
if (!limitCheck.allowed) {
|
|
1653
1693
|
return limitCheck.message;
|
|
1654
1694
|
}
|
|
@@ -1684,7 +1724,8 @@ ${infoParts.join("\n")}`;
|
|
|
1684
1724
|
ctx.command(`${COMMANDS.TXT_TO_IMG} [prompt:text]`, "根据文字描述生成图像").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async ({ session, options }, prompt) => {
|
|
1685
1725
|
if (!session?.userId) return "会话无效";
|
|
1686
1726
|
const numImages = options?.num || config.defaultNumImages;
|
|
1687
|
-
const
|
|
1727
|
+
const userName = session.username || session.userId || "未知用户";
|
|
1728
|
+
const limitCheck = await userManager.checkAndReserveQuota(session.userId, userName, numImages, config);
|
|
1688
1729
|
if (!limitCheck.allowed) {
|
|
1689
1730
|
return limitCheck.message;
|
|
1690
1731
|
}
|
|
@@ -1697,7 +1738,8 @@ ${infoParts.join("\n")}`;
|
|
|
1697
1738
|
if (!session?.userId) return "会话无效";
|
|
1698
1739
|
const numImages = options?.num || config.defaultNumImages;
|
|
1699
1740
|
const mode = options?.multiple ? "multiple" : "single";
|
|
1700
|
-
const
|
|
1741
|
+
const userName = session.username || session.userId || "未知用户";
|
|
1742
|
+
const limitCheck = await userManager.checkAndReserveQuota(session.userId, userName, numImages, config);
|
|
1701
1743
|
if (!limitCheck.allowed) {
|
|
1702
1744
|
return limitCheck.message;
|
|
1703
1745
|
}
|
|
@@ -1759,7 +1801,8 @@ ${infoParts.join("\n")}`;
|
|
|
1759
1801
|
if (imageCount < 1 || imageCount > 4) {
|
|
1760
1802
|
return "生成数量必须在 1-4 之间";
|
|
1761
1803
|
}
|
|
1762
|
-
const
|
|
1804
|
+
const userName = session.username || userId || "未知用户";
|
|
1805
|
+
const limitCheck = await userManager.checkAndReserveQuota(userId, userName, imageCount, config);
|
|
1763
1806
|
if (!limitCheck.allowed) {
|
|
1764
1807
|
return limitCheck.message;
|
|
1765
1808
|
}
|
|
@@ -1773,21 +1816,38 @@ ${infoParts.join("\n")}`;
|
|
|
1773
1816
|
});
|
|
1774
1817
|
await session.send(`开始合成图(${collectedImages.length}张)...
|
|
1775
1818
|
Prompt: ${prompt}`);
|
|
1776
|
-
const
|
|
1819
|
+
const generatedImages = [];
|
|
1820
|
+
let creditDeducted = false;
|
|
1821
|
+
const onImageGenerated = /* @__PURE__ */ __name(async (imageUrl, index, total) => {
|
|
1822
|
+
if (isTimeout) {
|
|
1823
|
+
throw new Error("命令执行超时");
|
|
1824
|
+
}
|
|
1825
|
+
generatedImages.push(imageUrl);
|
|
1826
|
+
if (!creditDeducted && generatedImages.length > 0) {
|
|
1827
|
+
creditDeducted = true;
|
|
1828
|
+
await recordUserUsage(session, COMMANDS.COMPOSE_IMAGE, total);
|
|
1829
|
+
logger.info("流式处理:第一张图片生成,积分已扣除", {
|
|
1830
|
+
userId,
|
|
1831
|
+
totalImages: total,
|
|
1832
|
+
currentIndex: index
|
|
1833
|
+
});
|
|
1834
|
+
}
|
|
1835
|
+
await session.send(import_koishi2.h.image(imageUrl));
|
|
1836
|
+
logger.debug("流式处理:图片已发送", { index: index + 1, total });
|
|
1837
|
+
if (total > 1 && index < total - 1) {
|
|
1838
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1839
|
+
}
|
|
1840
|
+
}, "onImageGenerated");
|
|
1841
|
+
const resultImages = await requestProviderImages(prompt, collectedImages, imageCount, void 0, onImageGenerated);
|
|
1777
1842
|
if (isTimeout) throw new Error("命令执行超时");
|
|
1778
1843
|
if (resultImages.length === 0) {
|
|
1779
1844
|
return "图片合成失败:未能生成图片";
|
|
1780
1845
|
}
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
for (let i = 0; i < resultImages.length; i++) {
|
|
1785
|
-
if (isTimeout) break;
|
|
1786
|
-
await session.send(import_koishi2.h.image(resultImages[i]));
|
|
1787
|
-
if (resultImages.length > 1 && i < resultImages.length - 1) {
|
|
1788
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
1789
|
-
}
|
|
1846
|
+
if (!creditDeducted) {
|
|
1847
|
+
await recordUserUsage(session, COMMANDS.COMPOSE_IMAGE, resultImages.length);
|
|
1848
|
+
logger.warn("流式处理:积分在最后扣除(异常情况)", { userId, imagesCount: resultImages.length });
|
|
1790
1849
|
}
|
|
1850
|
+
await session.send("图片合成完成!");
|
|
1791
1851
|
} finally {
|
|
1792
1852
|
userManager.endTask(userId);
|
|
1793
1853
|
}
|
|
@@ -7,5 +7,5 @@ export interface GeminiConfig extends ProviderConfig {
|
|
|
7
7
|
export declare class GeminiProvider implements ImageProvider {
|
|
8
8
|
private config;
|
|
9
9
|
constructor(config: GeminiConfig);
|
|
10
|
-
generateImages(prompt: string, imageUrls: string | string[], numImages: number): Promise<string[]>;
|
|
10
|
+
generateImages(prompt: string, imageUrls: string | string[], numImages: number, onImageGenerated?: (imageUrl: string, index: number, total: number) => void | Promise<void>): Promise<string[]>;
|
|
11
11
|
}
|
|
@@ -6,5 +6,5 @@ export interface GptGodConfig extends ProviderConfig {
|
|
|
6
6
|
export declare class GptGodProvider implements ImageProvider {
|
|
7
7
|
private config;
|
|
8
8
|
constructor(config: GptGodConfig);
|
|
9
|
-
generateImages(prompt: string, imageUrls: string | string[], numImages: number): Promise<string[]>;
|
|
9
|
+
generateImages(prompt: string, imageUrls: string | string[], numImages: number, onImageGenerated?: (imageUrl: string, index: number, total: number) => void | Promise<void>): Promise<string[]>;
|
|
10
10
|
}
|
package/lib/providers/types.d.ts
CHANGED
|
@@ -4,9 +4,10 @@ export interface ImageProvider {
|
|
|
4
4
|
* @param prompt 提示词
|
|
5
5
|
* @param imageUrls 输入图片 URL 数组
|
|
6
6
|
* @param numImages 需要生成的图片数量
|
|
7
|
+
* @param onImageGenerated 可选的回调函数,每生成一张图片时调用(用于流式处理)
|
|
7
8
|
* @returns 生成的图片 URL 数组(data: URL 或 http URL)
|
|
8
9
|
*/
|
|
9
|
-
generateImages(prompt: string, imageUrls: string | string[], numImages: number): Promise<string[]>;
|
|
10
|
+
generateImages(prompt: string, imageUrls: string | string[], numImages: number, onImageGenerated?: (imageUrl: string, index: number, total: number) => void | Promise<void>): Promise<string[]>;
|
|
10
11
|
}
|
|
11
12
|
export interface ProviderConfig {
|
|
12
13
|
apiTimeout: number;
|