koishi-plugin-aka-ai-generator 0.2.14 → 0.2.16
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.d.ts +1 -0
- package/lib/index.js +92 -63
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -604,7 +604,11 @@ var COMMANDS = {
|
|
|
604
604
|
};
|
|
605
605
|
var StyleItemSchema = import_koishi.Schema.object({
|
|
606
606
|
commandName: import_koishi.Schema.string().required().description("命令名称(不含前缀斜杠)"),
|
|
607
|
-
prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt")
|
|
607
|
+
prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt"),
|
|
608
|
+
mode: import_koishi.Schema.union([
|
|
609
|
+
import_koishi.Schema.const("single").description("单图模式"),
|
|
610
|
+
import_koishi.Schema.const("multiple").description("多图模式")
|
|
611
|
+
]).default("single").description("图片输入模式")
|
|
608
612
|
});
|
|
609
613
|
var Config = import_koishi.Schema.intersect([
|
|
610
614
|
import_koishi.Schema.object({
|
|
@@ -646,11 +650,13 @@ var Config = import_koishi.Schema.intersect([
|
|
|
646
650
|
styles: import_koishi.Schema.array(StyleItemSchema).role("table").default([
|
|
647
651
|
{
|
|
648
652
|
commandName: "变手办",
|
|
649
|
-
prompt: "将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子,桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座,角色手办站在上面。如果可能的话,将场景设置在室内"
|
|
653
|
+
prompt: "将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子,桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座,角色手办站在上面。如果可能的话,将场景设置在室内",
|
|
654
|
+
mode: "single"
|
|
650
655
|
},
|
|
651
656
|
{
|
|
652
657
|
commandName: "变写实",
|
|
653
|
-
prompt: "请根据用户提供的图片,在严格保持主体身份、外观特征与姿态不变的前提下,生成一张照片级真实感的超写实摄影作品。要求:1. 采用专业相机拍摄(如佳能EOS R5),使用85mm f/1.4人像镜头,呈现柯达Portra 400胶片质感,8K超高清画质,HDR高动态范围,电影级打光效果;2. 画面应具有照片级真实感、超现实主义风格和高细节表现,确保光影、皮肤质感、服饰纹理与背景环境都贴近真实世界;3. 使用自然光影营造真实氛围,呈现raw and natural的原始自然感,具有authentic film snapshot的真实胶片质感;4. 整体需具备tactile feel触感质感和simulated texture模拟纹理细节,可以适度优化噪点与瑕疵,但不要改变主体特征或添加额外元素;5. 整体效果需像专业摄影棚拍摄的真实照片,具有电影级画质;6. 如果主体是人物脸部,脸部生成效果应参考欧美混血白人精致美丽帅气英俊的外观特征进行生成,保持精致立体的五官轮廓、健康光泽的肌肤质感、优雅的气质和自然的表情,确保面部特征协调美观。"
|
|
658
|
+
prompt: "请根据用户提供的图片,在严格保持主体身份、外观特征与姿态不变的前提下,生成一张照片级真实感的超写实摄影作品。要求:1. 采用专业相机拍摄(如佳能EOS R5),使用85mm f/1.4人像镜头,呈现柯达Portra 400胶片质感,8K超高清画质,HDR高动态范围,电影级打光效果;2. 画面应具有照片级真实感、超现实主义风格和高细节表现,确保光影、皮肤质感、服饰纹理与背景环境都贴近真实世界;3. 使用自然光影营造真实氛围,呈现raw and natural的原始自然感,具有authentic film snapshot的真实胶片质感;4. 整体需具备tactile feel触感质感和simulated texture模拟纹理细节,可以适度优化噪点与瑕疵,但不要改变主体特征或添加额外元素;5. 整体效果需像专业摄影棚拍摄的真实照片,具有电影级画质;6. 如果主体是人物脸部,脸部生成效果应参考欧美混血白人精致美丽帅气英俊的外观特征进行生成,保持精致立体的五官轮廓、健康光泽的肌肤质感、优雅的气质和自然的表情,确保面部特征协调美观。",
|
|
659
|
+
mode: "single"
|
|
654
660
|
}
|
|
655
661
|
]).description("自定义风格命令配置")
|
|
656
662
|
}),
|
|
@@ -1111,55 +1117,72 @@ function apply(ctx, config) {
|
|
|
1111
1117
|
});
|
|
1112
1118
|
}
|
|
1113
1119
|
__name(recordUserUsage, "recordUserUsage");
|
|
1114
|
-
async function
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
if (
|
|
1119
|
-
|
|
1120
|
-
|
|
1120
|
+
async function getInputData(session, imgParam, mode) {
|
|
1121
|
+
const collectedImages = [];
|
|
1122
|
+
let collectedText = "";
|
|
1123
|
+
if (imgParam) {
|
|
1124
|
+
if (typeof imgParam === "object" && imgParam.attrs?.src) {
|
|
1125
|
+
collectedImages.push(imgParam.attrs.src);
|
|
1126
|
+
} else if (typeof imgParam === "string") {
|
|
1127
|
+
if (imgParam.startsWith("http") || imgParam.startsWith("data:")) {
|
|
1128
|
+
collectedImages.push(imgParam);
|
|
1121
1129
|
}
|
|
1122
|
-
return url;
|
|
1123
1130
|
}
|
|
1124
1131
|
}
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
const
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
+
if (session.quote?.elements) {
|
|
1133
|
+
const quoteImages = import_koishi.h.select(session.quote.elements, "img");
|
|
1134
|
+
for (const img of quoteImages) {
|
|
1135
|
+
if (img.attrs.src) collectedImages.push(img.attrs.src);
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
if (collectedImages.length > 0) {
|
|
1139
|
+
if (mode === "single") {
|
|
1140
|
+
if (collectedImages.length > 1) {
|
|
1141
|
+
return { error: '本功能仅支持处理一张图片,检测到多张图片。如需合成多张图片请使用"合成图像"命令' };
|
|
1142
|
+
}
|
|
1143
|
+
return { images: collectedImages };
|
|
1144
|
+
}
|
|
1145
|
+
return { images: collectedImages };
|
|
1146
|
+
}
|
|
1147
|
+
const promptMsg = mode === "single" ? "请在30秒内发送一张图片" : "请发送图片(发送纯文字结束,至少需要2张)";
|
|
1148
|
+
await session.send(promptMsg);
|
|
1149
|
+
while (true) {
|
|
1150
|
+
const msg = await session.prompt(mode === "multiple" ? 6e4 : 3e4);
|
|
1151
|
+
if (!msg) return { error: "等待超时" };
|
|
1152
|
+
const elements = import_koishi.h.parse(msg);
|
|
1153
|
+
const images = import_koishi.h.select(elements, "img");
|
|
1154
|
+
const textElements = import_koishi.h.select(elements, "text");
|
|
1155
|
+
const text = textElements.map((el) => el.attrs.content).join(" ").trim();
|
|
1156
|
+
if (images.length > 0) {
|
|
1157
|
+
for (const img of images) {
|
|
1158
|
+
collectedImages.push(img.attrs.src);
|
|
1132
1159
|
}
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1160
|
+
if (mode === "single") {
|
|
1161
|
+
if (collectedImages.length > 1) {
|
|
1162
|
+
return { error: "本功能仅支持处理一张图片,检测到多张图片" };
|
|
1163
|
+
}
|
|
1164
|
+
if (text) collectedText = text;
|
|
1165
|
+
break;
|
|
1166
|
+
}
|
|
1167
|
+
if (text) {
|
|
1168
|
+
collectedText = text;
|
|
1169
|
+
break;
|
|
1136
1170
|
}
|
|
1137
|
-
|
|
1171
|
+
await session.send(`已收到 ${collectedImages.length} 张图片,继续发送或输入文字结束`);
|
|
1172
|
+
continue;
|
|
1173
|
+
}
|
|
1174
|
+
if (text) {
|
|
1175
|
+
if (collectedImages.length === 0) {
|
|
1176
|
+
await session.send("未检测到图片,请先发送图片");
|
|
1177
|
+
continue;
|
|
1178
|
+
}
|
|
1179
|
+
collectedText = text;
|
|
1180
|
+
break;
|
|
1138
1181
|
}
|
|
1139
1182
|
}
|
|
1140
|
-
|
|
1141
|
-
const msg = await session.prompt(3e4);
|
|
1142
|
-
if (!msg) {
|
|
1143
|
-
await session.send("等待超时");
|
|
1144
|
-
return null;
|
|
1145
|
-
}
|
|
1146
|
-
elements = import_koishi.h.parse(msg);
|
|
1147
|
-
const images = import_koishi.h.select(elements, "img");
|
|
1148
|
-
if (images.length === 0) {
|
|
1149
|
-
await session.send("未检测到图片,请重试");
|
|
1150
|
-
return null;
|
|
1151
|
-
}
|
|
1152
|
-
if (images.length > 1) {
|
|
1153
|
-
await session.send('本功能仅支持处理一张图片,检测到多张图片。如需合成多张图片请使用"合成图像"命令');
|
|
1154
|
-
return null;
|
|
1155
|
-
}
|
|
1156
|
-
url = images[0].attrs.src;
|
|
1157
|
-
if (config.logLevel === "debug") {
|
|
1158
|
-
logger.debug("从用户输入获取图片", { url });
|
|
1159
|
-
}
|
|
1160
|
-
return url;
|
|
1183
|
+
return { images: collectedImages, text: collectedText };
|
|
1161
1184
|
}
|
|
1162
|
-
__name(
|
|
1185
|
+
__name(getInputData, "getInputData");
|
|
1163
1186
|
async function requestProviderImages(prompt, imageUrls, numImages, requestContext) {
|
|
1164
1187
|
const providerType = requestContext?.provider || config.provider;
|
|
1165
1188
|
const targetModelId = requestContext?.modelId;
|
|
@@ -1174,9 +1197,9 @@ function apply(ctx, config) {
|
|
|
1174
1197
|
return await providerInstance.generateImages(prompt, imageUrls, numImages);
|
|
1175
1198
|
}
|
|
1176
1199
|
__name(requestProviderImages, "requestProviderImages");
|
|
1177
|
-
async function processImageWithTimeout(session, img, prompt, styleName, requestContext, displayInfo) {
|
|
1200
|
+
async function processImageWithTimeout(session, img, prompt, styleName, requestContext, displayInfo, mode = "single") {
|
|
1178
1201
|
return Promise.race([
|
|
1179
|
-
processImage(session, img, prompt, styleName, requestContext, displayInfo),
|
|
1202
|
+
processImage(session, img, prompt, styleName, requestContext, displayInfo, mode),
|
|
1180
1203
|
new Promise(
|
|
1181
1204
|
(_, reject) => setTimeout(() => reject(new Error("命令执行超时")), config.commandTimeout * 1e3)
|
|
1182
1205
|
)
|
|
@@ -1184,11 +1207,11 @@ function apply(ctx, config) {
|
|
|
1184
1207
|
const userId = session.userId;
|
|
1185
1208
|
if (userId) activeTasks.delete(userId);
|
|
1186
1209
|
logger.error("图像处理超时或失败", { userId, error });
|
|
1187
|
-
return error.message === "命令执行超时" ? "图像处理超时,请重试" :
|
|
1210
|
+
return error.message === "命令执行超时" ? "图像处理超时,请重试" : `图像处理失败:${error.message}`;
|
|
1188
1211
|
});
|
|
1189
1212
|
}
|
|
1190
1213
|
__name(processImageWithTimeout, "processImageWithTimeout");
|
|
1191
|
-
async function processImage(session, img, prompt, styleName, requestContext, displayInfo) {
|
|
1214
|
+
async function processImage(session, img, prompt, styleName, requestContext, displayInfo, mode = "single") {
|
|
1192
1215
|
const userId = session.userId;
|
|
1193
1216
|
if (activeTasks.has(userId)) {
|
|
1194
1217
|
return "您有一个图像处理任务正在进行中,请等待完成";
|
|
@@ -1197,17 +1220,22 @@ function apply(ctx, config) {
|
|
|
1197
1220
|
if (imageCount < 1 || imageCount > 4) {
|
|
1198
1221
|
return "生成数量必须在 1-4 之间";
|
|
1199
1222
|
}
|
|
1200
|
-
const
|
|
1201
|
-
if (
|
|
1202
|
-
return;
|
|
1223
|
+
const inputResult = await getInputData(session, img, mode);
|
|
1224
|
+
if ("error" in inputResult) {
|
|
1225
|
+
return inputResult.error;
|
|
1226
|
+
}
|
|
1227
|
+
const { images: imageUrls, text: extraText } = inputResult;
|
|
1228
|
+
let finalPrompt = prompt;
|
|
1229
|
+
if (extraText) {
|
|
1230
|
+
finalPrompt += " " + extraText;
|
|
1203
1231
|
}
|
|
1204
1232
|
const providerType = requestContext?.provider || config.provider;
|
|
1205
1233
|
const providerModelId = requestContext?.modelId || (providerType === "yunwu" ? config.yunwuModelId : config.gptgodModelId);
|
|
1206
1234
|
logger.info("开始图像处理", {
|
|
1207
1235
|
userId,
|
|
1208
|
-
|
|
1236
|
+
imageUrls,
|
|
1209
1237
|
styleName,
|
|
1210
|
-
prompt,
|
|
1238
|
+
prompt: finalPrompt,
|
|
1211
1239
|
numImages: imageCount,
|
|
1212
1240
|
provider: providerType,
|
|
1213
1241
|
modelId: providerModelId
|
|
@@ -1229,7 +1257,7 @@ ${infoParts.join("\n")}`;
|
|
|
1229
1257
|
await session.send(statusMessage);
|
|
1230
1258
|
try {
|
|
1231
1259
|
activeTasks.set(userId, "processing");
|
|
1232
|
-
const images = await requestProviderImages(
|
|
1260
|
+
const images = await requestProviderImages(finalPrompt, imageUrls, imageCount, requestContext);
|
|
1233
1261
|
if (images.length === 0) {
|
|
1234
1262
|
activeTasks.delete(userId);
|
|
1235
1263
|
return "图像处理失败:未能生成图片";
|
|
@@ -1246,8 +1274,8 @@ ${infoParts.join("\n")}`;
|
|
|
1246
1274
|
} catch (error) {
|
|
1247
1275
|
activeTasks.delete(userId);
|
|
1248
1276
|
logger.error("图像处理失败", { userId, error });
|
|
1249
|
-
if (error?.message
|
|
1250
|
-
return error.message
|
|
1277
|
+
if (error?.message) {
|
|
1278
|
+
return `图像处理失败:${error.message}`;
|
|
1251
1279
|
}
|
|
1252
1280
|
return "图像处理失败,请稍后重试";
|
|
1253
1281
|
}
|
|
@@ -1307,7 +1335,8 @@ ${infoParts.join("\n")}`;
|
|
|
1307
1335
|
displayInfo.modelId = modifiers.modelMapping.modelId;
|
|
1308
1336
|
displayInfo.modelDescription = modifiers.modelMapping.suffix || modifiers.modelMapping.modelId;
|
|
1309
1337
|
}
|
|
1310
|
-
|
|
1338
|
+
const mode = style.mode || "single";
|
|
1339
|
+
return processImageWithTimeout(session, img, mergedPrompt, style.commandName, requestContext, displayInfo, mode);
|
|
1311
1340
|
});
|
|
1312
1341
|
logger.info(`已注册命令: ${style.commandName}`);
|
|
1313
1342
|
}
|
|
@@ -1412,8 +1441,8 @@ Prompt: ${prompt}`);
|
|
|
1412
1441
|
} catch (error) {
|
|
1413
1442
|
activeTasks.delete(userId);
|
|
1414
1443
|
logger.error("自定义图像处理失败", { userId, error });
|
|
1415
|
-
if (error?.message
|
|
1416
|
-
return error.message
|
|
1444
|
+
if (error?.message) {
|
|
1445
|
+
return `图像处理失败:${error.message}`;
|
|
1417
1446
|
}
|
|
1418
1447
|
return "图像处理失败,请稍后重试";
|
|
1419
1448
|
}
|
|
@@ -1425,7 +1454,7 @@ Prompt: ${prompt}`);
|
|
|
1425
1454
|
const userId = session.userId;
|
|
1426
1455
|
if (userId) activeTasks.delete(userId);
|
|
1427
1456
|
logger.error("自定义图像处理超时或失败", { userId, error });
|
|
1428
|
-
return error.message === "命令执行超时" ? "图像处理超时,请重试" :
|
|
1457
|
+
return error.message === "命令执行超时" ? "图像处理超时,请重试" : `图像处理失败:${error.message}`;
|
|
1429
1458
|
});
|
|
1430
1459
|
});
|
|
1431
1460
|
ctx.command(COMMANDS.COMPOSE_IMAGE, "合成多张图片,使用自定义prompt控制合成效果").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async ({ session, options }) => {
|
|
@@ -1518,8 +1547,8 @@ Prompt: ${prompt}`);
|
|
|
1518
1547
|
} catch (error) {
|
|
1519
1548
|
activeTasks.delete(userId);
|
|
1520
1549
|
logger.error("图片合成失败", { userId, error });
|
|
1521
|
-
if (error?.message
|
|
1522
|
-
return error.message
|
|
1550
|
+
if (error?.message) {
|
|
1551
|
+
return `图片合成失败:${error.message}`;
|
|
1523
1552
|
}
|
|
1524
1553
|
return "图片合成失败,请稍后重试";
|
|
1525
1554
|
}
|
|
@@ -1531,7 +1560,7 @@ Prompt: ${prompt}`);
|
|
|
1531
1560
|
const userId = session.userId;
|
|
1532
1561
|
if (userId) activeTasks.delete(userId);
|
|
1533
1562
|
logger.error("图片合成超时或失败", { userId, error });
|
|
1534
|
-
return error.message === "命令执行超时" ? "图片合成超时,请重试" :
|
|
1563
|
+
return error.message === "命令执行超时" ? "图片合成超时,请重试" : `图片合成失败:${error.message}`;
|
|
1535
1564
|
});
|
|
1536
1565
|
});
|
|
1537
1566
|
ctx.command(`${COMMANDS.RECHARGE} [content:text]`, "为用户充值次数(仅管理员)").action(async ({ session }, content) => {
|