koishi-plugin-aka-ai-generator 0.2.6 → 0.2.8
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 +6 -0
- package/lib/index.js +112 -16
- package/package.json +1 -1
package/lib/index.d.ts
CHANGED
|
@@ -10,6 +10,11 @@ export interface StyleConfig {
|
|
|
10
10
|
commandName: string;
|
|
11
11
|
prompt: string;
|
|
12
12
|
}
|
|
13
|
+
export interface StyleGroupConfig {
|
|
14
|
+
typeName: string;
|
|
15
|
+
typeDescription?: string;
|
|
16
|
+
prompts: StyleConfig[];
|
|
17
|
+
}
|
|
13
18
|
export interface UserData {
|
|
14
19
|
userId: string;
|
|
15
20
|
userName: string;
|
|
@@ -41,6 +46,7 @@ export interface Config {
|
|
|
41
46
|
rateLimitMax: number;
|
|
42
47
|
adminUsers: string[];
|
|
43
48
|
styles: StyleConfig[];
|
|
49
|
+
styleGroups?: StyleGroupConfig[];
|
|
44
50
|
logLevel: 'info' | 'debug';
|
|
45
51
|
}
|
|
46
52
|
export interface RechargeRecord {
|
package/lib/index.js
CHANGED
|
@@ -604,6 +604,10 @@ var COMMANDS = {
|
|
|
604
604
|
RECHARGE_HISTORY: "图像充值记录",
|
|
605
605
|
FUNCTION_LIST: "图像功能"
|
|
606
606
|
};
|
|
607
|
+
var StyleItemSchema = import_koishi.Schema.object({
|
|
608
|
+
commandName: import_koishi.Schema.string().required().description("命令名称(不含前缀斜杠)"),
|
|
609
|
+
prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt")
|
|
610
|
+
});
|
|
607
611
|
var Config = import_koishi.Schema.intersect([
|
|
608
612
|
import_koishi.Schema.object({
|
|
609
613
|
provider: import_koishi.Schema.union([
|
|
@@ -641,10 +645,7 @@ var Config = import_koishi.Schema.intersect([
|
|
|
641
645
|
}),
|
|
642
646
|
// 自定义风格命令配置
|
|
643
647
|
import_koishi.Schema.object({
|
|
644
|
-
styles: import_koishi.Schema.array(
|
|
645
|
-
commandName: import_koishi.Schema.string().required().description("命令名称(不含前缀斜杠)"),
|
|
646
|
-
prompt: import_koishi.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt")
|
|
647
|
-
})).role("table").default([
|
|
648
|
+
styles: import_koishi.Schema.array(StyleItemSchema).role("table").default([
|
|
648
649
|
{
|
|
649
650
|
commandName: "变手办",
|
|
650
651
|
prompt: "将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子,桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座,角色手办站在上面。如果可能的话,将场景设置在室内"
|
|
@@ -669,7 +670,12 @@ var Config = import_koishi.Schema.intersect([
|
|
|
669
670
|
commandName: "变像素",
|
|
670
671
|
prompt: "请根据用户提供的图片,将图像主体转换为经典的8位像素艺术风格。要求:1. 完全保持主体的身份、外观特征和核心识别元素不变,确保转换后仍然清晰可识别;2. 采用极简的8位像素风格,使用有限的复古调色板(通常为16-256色),营造经典街机游戏的美学氛围;3. 所有细节都进行像素化处理,使用清晰的像素块和锐利的边缘,避免平滑渐变;4. 采用干净的块状形式,保持简单、标志性的设计,突出主体的核心特征;5. 背景可以简化为纯色背景(如纯白或纯黑),或者保持简单的像素化背景,确保主体突出;6. 整体风格应具有强烈的复古游戏感,让人联想到经典街机游戏和早期电子游戏的视觉美学;7. 保持主体的比例和基本结构,但用像素块重新诠释所有细节。"
|
|
671
672
|
}
|
|
672
|
-
]).description("自定义风格命令配置")
|
|
673
|
+
]).description("自定义风格命令配置"),
|
|
674
|
+
styleGroups: import_koishi.Schema.array(import_koishi.Schema.object({
|
|
675
|
+
typeName: import_koishi.Schema.string().required().description("类型名称,用于分组展示"),
|
|
676
|
+
typeDescription: import_koishi.Schema.string().role("textarea", { rows: 2 }).description("可选:类型说明"),
|
|
677
|
+
prompts: import_koishi.Schema.array(StyleItemSchema).role("table").default([]).description("属于该类型的 prompt 列表")
|
|
678
|
+
})).role("table").default([]).description("按类型管理的 prompt 组,保存时将自动展开为 styles")
|
|
673
679
|
})
|
|
674
680
|
]);
|
|
675
681
|
function apply(ctx, config) {
|
|
@@ -701,6 +707,35 @@ function apply(ctx, config) {
|
|
|
701
707
|
return value?.replace(/^\-+/, "").trim().toLowerCase();
|
|
702
708
|
}
|
|
703
709
|
__name(normalizeSuffix, "normalizeSuffix");
|
|
710
|
+
function parseNumImagesFromPrompt(prompt) {
|
|
711
|
+
if (!prompt || typeof prompt !== "string") {
|
|
712
|
+
return { numImages: void 0, cleanedPrompt: prompt };
|
|
713
|
+
}
|
|
714
|
+
const patterns = [
|
|
715
|
+
/生成\s*([1-4])\s*张(?:图片)?/i,
|
|
716
|
+
/([1-4])\s*张(?:图片)?/,
|
|
717
|
+
/生成\s*([1-4])\s*个(?:图片)?/i,
|
|
718
|
+
/([1-4])\s*个(?:图片)?/,
|
|
719
|
+
/num[:\s]*([1-4])/i,
|
|
720
|
+
/数量[:\s]*([1-4])/i
|
|
721
|
+
];
|
|
722
|
+
let numImages = void 0;
|
|
723
|
+
let cleanedPrompt = prompt;
|
|
724
|
+
for (const pattern of patterns) {
|
|
725
|
+
const match = prompt.match(pattern);
|
|
726
|
+
if (match) {
|
|
727
|
+
const num = parseInt(match[1], 10);
|
|
728
|
+
if (num >= 1 && num <= 4) {
|
|
729
|
+
numImages = num;
|
|
730
|
+
cleanedPrompt = prompt.replace(pattern, "").trim();
|
|
731
|
+
cleanedPrompt = cleanedPrompt.replace(/\s+/g, " ").replace(/[,,]\s*$/, "").trim();
|
|
732
|
+
break;
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return { numImages, cleanedPrompt };
|
|
737
|
+
}
|
|
738
|
+
__name(parseNumImagesFromPrompt, "parseNumImagesFromPrompt");
|
|
704
739
|
function buildModelMappingIndex(mappings) {
|
|
705
740
|
const map = /* @__PURE__ */ new Map();
|
|
706
741
|
if (!Array.isArray(mappings)) return map;
|
|
@@ -783,11 +818,41 @@ function apply(ctx, config) {
|
|
|
783
818
|
return modifiers;
|
|
784
819
|
}
|
|
785
820
|
__name(parseStyleCommandModifiers, "parseStyleCommandModifiers");
|
|
821
|
+
const styleDefinitions = collectStyleDefinitions();
|
|
822
|
+
function collectStyleDefinitions() {
|
|
823
|
+
const unique = /* @__PURE__ */ new Map();
|
|
824
|
+
const pushStyle = /* @__PURE__ */ __name((style, groupName) => {
|
|
825
|
+
if (!style?.commandName || !style?.prompt) return;
|
|
826
|
+
if (unique.has(style.commandName)) {
|
|
827
|
+
logger.warn("检测到重复的风格命令名称,已跳过", { commandName: style.commandName, groupName });
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
unique.set(style.commandName, {
|
|
831
|
+
...style,
|
|
832
|
+
groupName
|
|
833
|
+
});
|
|
834
|
+
}, "pushStyle");
|
|
835
|
+
if (Array.isArray(config.styles)) {
|
|
836
|
+
for (const style of config.styles) {
|
|
837
|
+
pushStyle(style);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
if (Array.isArray(config.styleGroups)) {
|
|
841
|
+
for (const group of config.styleGroups) {
|
|
842
|
+
if (!group?.typeName || !Array.isArray(group.prompts)) continue;
|
|
843
|
+
for (const style of group.prompts) {
|
|
844
|
+
pushStyle(style, group.typeName);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
return Array.from(unique.values());
|
|
849
|
+
}
|
|
850
|
+
__name(collectStyleDefinitions, "collectStyleDefinitions");
|
|
786
851
|
function getStyleCommands() {
|
|
787
|
-
if (!
|
|
788
|
-
return
|
|
852
|
+
if (!styleDefinitions.length) return [];
|
|
853
|
+
return styleDefinitions.filter((style) => style.commandName && style.prompt).map((style) => ({
|
|
789
854
|
name: style.commandName,
|
|
790
|
-
description: "图像风格转换"
|
|
855
|
+
description: style.groupName ? `图像风格转换(${style.groupName})` : "图像风格转换"
|
|
791
856
|
}));
|
|
792
857
|
}
|
|
793
858
|
__name(getStyleCommands, "getStyleCommands");
|
|
@@ -1173,8 +1238,8 @@ ${infoParts.join("\n")}`;
|
|
|
1173
1238
|
}
|
|
1174
1239
|
}
|
|
1175
1240
|
__name(processImage, "processImage");
|
|
1176
|
-
if (
|
|
1177
|
-
for (const style of
|
|
1241
|
+
if (styleDefinitions.length > 0) {
|
|
1242
|
+
for (const style of styleDefinitions) {
|
|
1178
1243
|
if (style.commandName && style.prompt) {
|
|
1179
1244
|
ctx.command(`${style.commandName} [img:text]`, "图像风格转换").option("num", "-n <num:number> 生成图片数量 (1-4)").action(async (argv, img) => {
|
|
1180
1245
|
const { session, options } = argv;
|
|
@@ -1184,16 +1249,33 @@ ${infoParts.join("\n")}`;
|
|
|
1184
1249
|
return limitCheck.message;
|
|
1185
1250
|
}
|
|
1186
1251
|
const modifiers = parseStyleCommandModifiers(argv, img);
|
|
1187
|
-
|
|
1252
|
+
let userPromptParts = [];
|
|
1188
1253
|
if (modifiers.customAdditions?.length) {
|
|
1189
|
-
|
|
1254
|
+
userPromptParts.push(...modifiers.customAdditions);
|
|
1190
1255
|
}
|
|
1191
1256
|
if (modifiers.customPromptSuffix) {
|
|
1192
|
-
|
|
1257
|
+
userPromptParts.push(modifiers.customPromptSuffix);
|
|
1258
|
+
}
|
|
1259
|
+
const userPromptText = userPromptParts.join(" - ");
|
|
1260
|
+
let promptNumImages = void 0;
|
|
1261
|
+
let cleanedUserPrompt = userPromptText;
|
|
1262
|
+
if (userPromptText) {
|
|
1263
|
+
const parsed = parseNumImagesFromPrompt(userPromptText);
|
|
1264
|
+
if (parsed.numImages) {
|
|
1265
|
+
promptNumImages = parsed.numImages;
|
|
1266
|
+
cleanedUserPrompt = parsed.cleanedPrompt;
|
|
1267
|
+
if (config.logLevel === "debug") {
|
|
1268
|
+
logger.debug("从 prompt 中解析到生成数量", { numImages: promptNumImages, cleanedPrompt: cleanedUserPrompt });
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
}
|
|
1272
|
+
const promptSegments = [style.prompt];
|
|
1273
|
+
if (cleanedUserPrompt) {
|
|
1274
|
+
promptSegments.push(cleanedUserPrompt);
|
|
1193
1275
|
}
|
|
1194
1276
|
const mergedPrompt = promptSegments.filter(Boolean).join(" - ");
|
|
1195
1277
|
const requestContext = {
|
|
1196
|
-
numImages: options?.num
|
|
1278
|
+
numImages: options?.num || promptNumImages
|
|
1197
1279
|
};
|
|
1198
1280
|
if (modifiers.modelMapping?.provider) {
|
|
1199
1281
|
requestContext.provider = modifiers.modelMapping.provider;
|
|
@@ -1275,8 +1357,15 @@ ${infoParts.join("\n")}`;
|
|
|
1275
1357
|
if (!prompt) {
|
|
1276
1358
|
return "未检测到prompt描述,请重新发送";
|
|
1277
1359
|
}
|
|
1360
|
+
const { numImages: promptNumImages, cleanedPrompt } = parseNumImagesFromPrompt(prompt);
|
|
1361
|
+
if (promptNumImages) {
|
|
1362
|
+
prompt = cleanedPrompt;
|
|
1363
|
+
if (config.logLevel === "debug") {
|
|
1364
|
+
logger.debug("从 prompt 中解析到生成数量", { numImages: promptNumImages, cleanedPrompt });
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1278
1367
|
const imageUrl = collectedImages[0];
|
|
1279
|
-
const imageCount = options?.num || config.defaultNumImages;
|
|
1368
|
+
const imageCount = options?.num || promptNumImages || config.defaultNumImages;
|
|
1280
1369
|
if (imageCount < 1 || imageCount > 4) {
|
|
1281
1370
|
return "生成数量必须在 1-4 之间";
|
|
1282
1371
|
}
|
|
@@ -1374,7 +1463,14 @@ Prompt: ${prompt}`);
|
|
|
1374
1463
|
if (!prompt) {
|
|
1375
1464
|
return "未检测到prompt描述,请重新发送";
|
|
1376
1465
|
}
|
|
1377
|
-
const
|
|
1466
|
+
const { numImages: promptNumImages, cleanedPrompt } = parseNumImagesFromPrompt(prompt);
|
|
1467
|
+
if (promptNumImages) {
|
|
1468
|
+
prompt = cleanedPrompt;
|
|
1469
|
+
if (config.logLevel === "debug") {
|
|
1470
|
+
logger.debug("从 prompt 中解析到生成数量", { numImages: promptNumImages, cleanedPrompt });
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
const imageCount = options?.num || promptNumImages || config.defaultNumImages;
|
|
1378
1474
|
if (imageCount < 1 || imageCount > 4) {
|
|
1379
1475
|
return "生成数量必须在 1-4 之间";
|
|
1380
1476
|
}
|