koishi-plugin-aka-ai-generator 0.3.0 → 0.3.3

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 CHANGED
@@ -9,7 +9,6 @@ export interface ModelMappingConfig {
9
9
  export interface StyleConfig {
10
10
  commandName: string;
11
11
  prompt: string;
12
- mode?: 'single' | 'multiple';
13
12
  }
14
13
  export interface StyleGroupConfig {
15
14
  prompts: StyleConfig[];
package/lib/index.js CHANGED
@@ -753,12 +753,8 @@ var COMMANDS = {
753
753
  IMAGE_COMMANDS: "图像指令"
754
754
  };
755
755
  var StyleItemSchema = import_koishi.Schema.object({
756
- commandName: import_koishi.Schema.string().required().description("命令名称(不含前缀斜杠)"),
757
- prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt"),
758
- mode: import_koishi.Schema.union([
759
- import_koishi.Schema.const("single").description("单图模式"),
760
- import_koishi.Schema.const("multiple").description("多图模式")
761
- ]).default("single").description("图片输入模式")
756
+ commandName: import_koishi.Schema.string().required().description("命令名称").role("table-cell", { width: 100 }),
757
+ prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt")
762
758
  });
763
759
  var Config = import_koishi.Schema.intersect([
764
760
  import_koishi.Schema.object({
@@ -805,13 +801,11 @@ var Config = import_koishi.Schema.intersect([
805
801
  styles: import_koishi.Schema.array(StyleItemSchema).role("table").default([
806
802
  {
807
803
  commandName: "变手办",
808
- prompt: "将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子,桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座,角色手办站在上面。如果可能的话,将场景设置在室内",
809
- mode: "single"
804
+ prompt: "将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子,桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座,角色手办站在上面。如果可能的话,将场景设置在室内"
810
805
  },
811
806
  {
812
807
  commandName: "变写实",
813
- 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. 如果主体是人物脸部,脸部生成效果应参考欧美混血白人精致美丽帅气英俊的外观特征进行生成,保持精致立体的五官轮廓、健康光泽的肌肤质感、优雅的气质和自然的表情,确保面部特征协调美观。",
814
- mode: "single"
808
+ 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. 如果主体是人物脸部,脸部生成效果应参考欧美混血白人精致美丽帅气英俊的外观特征进行生成,保持精致立体的五官轮廓、健康光泽的肌肤质感、优雅的气质和自然的表情,确保面部特征协调美观。"
815
809
  }
816
810
  ]).description("自定义风格命令配置")
817
811
  }),
@@ -1254,11 +1248,6 @@ function apply(ctx, config) {
1254
1248
  if (typeof imgParam === "string" && imgParam.trim()) {
1255
1249
  return { images: [], text: imgParam.trim() };
1256
1250
  }
1257
- if (session.content) {
1258
- const elements2 = import_koishi.h.parse(session.content);
1259
- const text2 = import_koishi.h.select(elements2, "text").map((e) => e.attrs.content).join(" ").trim();
1260
- if (text2) return { images: [], text: text2 };
1261
- }
1262
1251
  await session.send("请输入画面描述");
1263
1252
  const msg = await session.prompt(3e4);
1264
1253
  if (!msg) return { error: "等待超时" };
@@ -1431,7 +1420,7 @@ ${infoParts.join("\n")}`;
1431
1420
  if (styleDefinitions.length > 0) {
1432
1421
  for (const style of styleDefinitions) {
1433
1422
  if (style.commandName && style.prompt) {
1434
- ctx.command(`${style.commandName} [img:text]`, "图像风格转换").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async (argv, img) => {
1423
+ ctx.command(`${style.commandName} [img:text]`, "图像风格转换").option("num", "-n <num:number> 生成图片数量 (1-4)").option("multiple", "-m 允许多图输入").action(async (argv, img) => {
1435
1424
  const { session, options } = argv;
1436
1425
  if (!session?.userId) return "会话无效";
1437
1426
  const modifiers = parseStyleCommandModifiers(argv, img);
@@ -1470,7 +1459,7 @@ ${infoParts.join("\n")}`;
1470
1459
  displayInfo.modelId = modifiers.modelMapping.modelId;
1471
1460
  displayInfo.modelDescription = modifiers.modelMapping.suffix || modifiers.modelMapping.modelId;
1472
1461
  }
1473
- const mode = style.mode || "single";
1462
+ const mode = options?.multiple ? "multiple" : "single";
1474
1463
  return processImageWithTimeout(session, img, mergedPrompt, style.commandName, requestContext, displayInfo, mode);
1475
1464
  });
1476
1465
  logger.info(`已注册命令: ${style.commandName}`);
@@ -1489,113 +1478,18 @@ ${infoParts.join("\n")}`;
1489
1478
  };
1490
1479
  return processImageWithTimeout(session, prompt, "", COMMANDS.TXT_TO_IMG, requestContext, {}, "text");
1491
1480
  });
1492
- ctx.command(COMMANDS.IMG_TO_IMG, "使用自定义prompt进行图像处理").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async ({ session, options }) => {
1481
+ ctx.command(`${COMMANDS.IMG_TO_IMG} [img:text]`, "使用自定义prompt进行图像处理").option("num", "-n <num:number> 生成图片数量 (1-4)").option("multiple", "-m 允许多图输入").action(async ({ session, options }, img) => {
1493
1482
  if (!session?.userId) return "会话无效";
1494
- return Promise.race([
1495
- (async () => {
1496
- const userId = session.userId;
1497
- if (!userId) return "会话无效";
1498
- if (activeTasks.has(userId)) {
1499
- return "您有一个图像处理任务正在进行中,请等待完成";
1500
- }
1501
- await session.send("图片+描述");
1502
- const collectedImages = [];
1503
- let prompt = "";
1504
- while (true) {
1505
- const msg = await session.prompt(6e4);
1506
- if (!msg) {
1507
- return "等待超时,请重试";
1508
- }
1509
- const elements = import_koishi.h.parse(msg);
1510
- const images = import_koishi.h.select(elements, "img");
1511
- const textElements = import_koishi.h.select(elements, "text");
1512
- const text = textElements.map((el) => el.attrs.content).join(" ").trim();
1513
- if (images.length > 0) {
1514
- if (collectedImages.length > 0) {
1515
- return '本功能仅支持处理一张图片,如需合成多张图片请使用"合成图"命令';
1516
- }
1517
- if (images.length > 1) {
1518
- return '本功能仅支持处理一张图片,检测到多张图片。如需合成多张图片请使用"合成图"命令';
1519
- }
1520
- for (const img of images) {
1521
- collectedImages.push(img.attrs.src);
1522
- }
1523
- if (text) {
1524
- prompt = text;
1525
- break;
1526
- }
1527
- await session.send("请发送描述");
1528
- continue;
1529
- }
1530
- if (text) {
1531
- if (collectedImages.length === 0) {
1532
- return "未检测到图片,请先发送图片";
1533
- }
1534
- prompt = text;
1535
- break;
1536
- }
1537
- return "未检测到有效内容,请重新发送";
1538
- }
1539
- if (collectedImages.length === 0) {
1540
- return "未检测到图片,请重新发送";
1541
- }
1542
- if (collectedImages.length > 1) {
1543
- return '本功能仅支持处理一张图片,检测到多张图片。如需合成多张图片请使用"合成图"命令';
1544
- }
1545
- if (!prompt) {
1546
- return "未检测到prompt描述,请重新发送";
1547
- }
1548
- const imageUrl = collectedImages[0];
1549
- const imageCount = options?.num || config.defaultNumImages;
1550
- if (imageCount < 1 || imageCount > 4) {
1551
- return "生成数量必须在 1-4 之间";
1552
- }
1553
- const limitCheck = await checkDailyLimit(userId, imageCount);
1554
- if (!limitCheck.allowed) {
1555
- return limitCheck.message;
1556
- }
1557
- logger.info("开始自定义图像处理", {
1558
- userId,
1559
- imageUrl,
1560
- prompt,
1561
- numImages: imageCount
1562
- });
1563
- await session.send(`开始处理图片(自定义prompt)...
1564
- Prompt: ${prompt}`);
1565
- try {
1566
- activeTasks.set(userId, "processing");
1567
- const resultImages = await requestProviderImages(prompt, imageUrl, imageCount);
1568
- if (resultImages.length === 0) {
1569
- activeTasks.delete(userId);
1570
- return "图像处理失败:未能生成图片";
1571
- }
1572
- await session.send("图像处理完成!");
1573
- for (let i = 0; i < resultImages.length; i++) {
1574
- await session.send(import_koishi.h.image(resultImages[i]));
1575
- if (resultImages.length > 1 && i < resultImages.length - 1) {
1576
- await new Promise((resolve) => setTimeout(resolve, 1e3));
1577
- }
1578
- }
1579
- await recordUserUsage(session, COMMANDS.IMG_TO_IMG, resultImages.length);
1580
- activeTasks.delete(userId);
1581
- } catch (error) {
1582
- activeTasks.delete(userId);
1583
- logger.error("自定义图像处理失败", { userId, error });
1584
- if (error?.message) {
1585
- return `图像处理失败:${error.message}`;
1586
- }
1587
- return "图像处理失败,请稍后重试";
1588
- }
1589
- })(),
1590
- new Promise(
1591
- (_, reject) => setTimeout(() => reject(new Error("命令执行超时")), config.commandTimeout * 1e3)
1592
- )
1593
- ]).catch((error) => {
1594
- const userId = session.userId;
1595
- if (userId) activeTasks.delete(userId);
1596
- logger.error("自定义图像处理超时或失败", { userId, error });
1597
- return error.message === "命令执行超时" ? "图像处理超时,请重试" : `图像处理失败:${error.message}`;
1598
- });
1483
+ const numImages = options?.num || config.defaultNumImages;
1484
+ const mode = options?.multiple ? "multiple" : "single";
1485
+ const limitCheck = await checkDailyLimit(session.userId, numImages);
1486
+ if (!limitCheck.allowed) {
1487
+ return limitCheck.message;
1488
+ }
1489
+ const requestContext = {
1490
+ numImages
1491
+ };
1492
+ return processImageWithTimeout(session, img, "", COMMANDS.IMG_TO_IMG, requestContext, {}, mode);
1599
1493
  });
1600
1494
  ctx.command(COMMANDS.COMPOSE_IMAGE, "合成多张图片,使用自定义prompt控制合成效果").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async ({ session, options }) => {
1601
1495
  if (!session?.userId) return "会话无效";
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-aka-ai-generator",
3
3
  "description": "自用AI生成插件(GPTGod & Yunwu)",
4
- "version": "0.3.0",
4
+ "version": "0.3.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [