koishi-plugin-aka-ai-generator 0.0.2 → 0.0.4

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
@@ -37,6 +37,7 @@ export interface Config {
37
37
  rateLimitMax: number;
38
38
  adminUsers: string[];
39
39
  styles: StyleConfig[];
40
+ logLevel: 'info' | 'debug';
40
41
  }
41
42
  export interface RechargeRecord {
42
43
  id: string;
package/lib/index.js CHANGED
@@ -195,7 +195,9 @@ async function downloadImageAsBase642(ctx, url, timeout, logger) {
195
195
  mimeType = "image/gif";
196
196
  }
197
197
  }
198
- logger.debug("图片下载并转换为Base64", { url, mimeType, size: base64.length });
198
+ if (logger) {
199
+ logger.debug("图片下载并转换为Base64", { url, mimeType, size: base64.length });
200
+ }
199
201
  return { data: base64, mimeType };
200
202
  } catch (error) {
201
203
  logger.error("下载图片失败", { url, error });
@@ -203,14 +205,23 @@ async function downloadImageAsBase642(ctx, url, timeout, logger) {
203
205
  }
204
206
  }
205
207
  __name(downloadImageAsBase642, "downloadImageAsBase64");
206
- function parseGptGodResponse(response) {
208
+ function parseGptGodResponse(response, logger) {
207
209
  try {
208
210
  const images = [];
209
211
  if (Array.isArray(response.images)) {
212
+ if (logger) {
213
+ logger.debug("从 response.images 数组提取图片", { count: response.images.length });
214
+ }
210
215
  return response.images;
211
216
  }
212
- if (response.image && typeof response.image === "string" && response.image.startsWith("data:")) {
213
- images.push(response.image);
217
+ if (response.image && typeof response.image === "string") {
218
+ if (response.image.startsWith("data:") || response.image.startsWith("http")) {
219
+ if (logger) {
220
+ logger.debug("从 response.image 提取图片");
221
+ }
222
+ images.push(response.image);
223
+ return images;
224
+ }
214
225
  }
215
226
  if (response?.choices?.length > 0) {
216
227
  const firstChoice = response.choices[0];
@@ -219,33 +230,123 @@ function parseGptGodResponse(response) {
219
230
  if (typeof messageContent === "string") {
220
231
  contentText = messageContent;
221
232
  } else if (Array.isArray(messageContent)) {
222
- contentText = messageContent.map((part) => part?.text || "").join("\n");
233
+ for (const part of messageContent) {
234
+ if (part?.type === "image_url" && part?.image_url?.url) {
235
+ if (logger) {
236
+ logger.debug("从 content 数组的 image_url 提取图片");
237
+ }
238
+ images.push(part.image_url.url);
239
+ } else if (part?.type === "text" && part?.text) {
240
+ contentText += part.text + "\n";
241
+ } else if (part?.text) {
242
+ contentText += part.text + "\n";
243
+ }
244
+ }
223
245
  } else if (messageContent?.text) {
224
246
  contentText = messageContent.text;
225
247
  }
226
- const mdImageRegex = /!\[.*?\]\((https?:\/\/[^\)]+)\)/g;
227
- let match;
228
- while ((match = mdImageRegex.exec(contentText)) !== null) {
229
- images.push(match[1]);
248
+ if (images.length > 0) {
249
+ return images;
230
250
  }
231
- if (images.length === 0) {
232
- const urlRegex = /(https?:\/\/[^\s"')]+\.(?:png|jpg|jpeg|webp|gif))/gi;
233
- let urlMatch;
234
- while ((urlMatch = urlRegex.exec(contentText)) !== null) {
235
- images.push(urlMatch[1]);
251
+ if (contentText) {
252
+ const mdImageRegex = /!\[.*?\]\((https?:\/\/[^\)]+)\)/g;
253
+ let match;
254
+ while ((match = mdImageRegex.exec(contentText)) !== null) {
255
+ images.push(match[1]);
256
+ }
257
+ if (images.length === 0) {
258
+ const urlRegex = /(https?:\/\/[^\s"')<>]+\.(?:png|jpg|jpeg|webp|gif|bmp))/gi;
259
+ let urlMatch;
260
+ while ((urlMatch = urlRegex.exec(contentText)) !== null) {
261
+ images.push(urlMatch[1]);
262
+ }
263
+ }
264
+ if (images.length === 0 && contentText.trim().startsWith("http")) {
265
+ const trimmedUrl = contentText.trim().split(/\s/)[0];
266
+ if (trimmedUrl.match(/^https?:\/\//)) {
267
+ images.push(trimmedUrl);
268
+ }
269
+ }
270
+ const dataUrlRegex = /(data:image\/[^;]+;base64,[^\s"')<>]+)/gi;
271
+ let dataUrlMatch;
272
+ while ((dataUrlMatch = dataUrlRegex.exec(contentText)) !== null) {
273
+ images.push(dataUrlMatch[1]);
274
+ }
275
+ }
276
+ if (images.length === 0 && firstChoice.message) {
277
+ if (firstChoice.message.image_url) {
278
+ if (logger) {
279
+ logger.debug("从 message.image_url 提取图片");
280
+ }
281
+ images.push(firstChoice.message.image_url);
282
+ }
283
+ if (Array.isArray(firstChoice.message.images)) {
284
+ if (logger) {
285
+ logger.debug("从 message.images 数组提取图片", { count: firstChoice.message.images.length });
286
+ }
287
+ return firstChoice.message.images;
288
+ }
289
+ }
290
+ }
291
+ if (images.length === 0) {
292
+ if (response.data) {
293
+ if (Array.isArray(response.data)) {
294
+ const dataImages = response.data.filter(
295
+ (item) => item?.url || item?.image_url || typeof item === "string" && (item.startsWith("http") || item.startsWith("data:"))
296
+ ).map((item) => item?.url || item?.image_url || item);
297
+ if (dataImages.length > 0) {
298
+ if (logger) {
299
+ logger.debug("从 response.data 数组提取图片", { count: dataImages.length });
300
+ }
301
+ return dataImages;
302
+ }
303
+ } else if (response.data.url || response.data.image_url) {
304
+ if (logger) {
305
+ logger.debug("从 response.data 提取图片");
306
+ }
307
+ images.push(response.data.url || response.data.image_url);
236
308
  }
237
309
  }
238
- if (images.length === 0 && contentText.trim().startsWith("http")) {
239
- images.push(contentText.trim());
310
+ if (response.result) {
311
+ if (Array.isArray(response.result)) {
312
+ const resultImages = response.result.filter(
313
+ (item) => item?.url || item?.image_url || typeof item === "string" && (item.startsWith("http") || item.startsWith("data:"))
314
+ ).map((item) => item?.url || item?.image_url || item);
315
+ if (resultImages.length > 0) {
316
+ if (logger) {
317
+ logger.debug("从 response.result 数组提取图片", { count: resultImages.length });
318
+ }
319
+ return resultImages;
320
+ }
321
+ } else if (typeof response.result === "string" && (response.result.startsWith("http") || response.result.startsWith("data:"))) {
322
+ if (logger) {
323
+ logger.debug("从 response.result 提取图片");
324
+ }
325
+ images.push(response.result);
326
+ }
240
327
  }
241
- const dataUrlRegex = /(data:image\/[^;]+;base64,[^\s"')]+)/gi;
242
- let dataUrlMatch;
243
- while ((dataUrlMatch = dataUrlRegex.exec(contentText)) !== null) {
244
- images.push(dataUrlMatch[1]);
328
+ }
329
+ if (images.length > 0) {
330
+ if (logger) {
331
+ logger.debug("成功提取图片", { count: images.length });
332
+ }
333
+ } else {
334
+ if (logger) {
335
+ logger.warn("未能从响应中提取图片", {
336
+ responseStructure: {
337
+ hasChoices: !!response?.choices,
338
+ hasImages: !!response?.images,
339
+ hasImage: !!response?.image,
340
+ hasData: !!response?.data,
341
+ hasResult: !!response?.result,
342
+ keys: Object.keys(response || {})
343
+ }
344
+ });
245
345
  }
246
346
  }
247
347
  return images;
248
348
  } catch (error) {
349
+ logger?.error("解析响应时出错", { error });
249
350
  return [];
250
351
  }
251
352
  }
@@ -265,7 +366,9 @@ var GptGodProvider = class {
265
366
  if (!this.config.apiKey) {
266
367
  throw new Error("GPTGod 配置不完整,请检查 API Key");
267
368
  }
268
- logger.debug("调用 GPTGod 图像编辑 API", { prompt, imageCount: urls.length, numImages });
369
+ if (this.config.logLevel === "debug") {
370
+ logger.debug("调用 GPTGod 图像编辑 API", { prompt, imageCount: urls.length, numImages });
371
+ }
269
372
  const contentParts = [
270
373
  {
271
374
  type: "text",
@@ -312,9 +415,26 @@ var GptGodProvider = class {
312
415
  }
313
416
  );
314
417
  logger.success("GPTGod 图像编辑 API 调用成功");
315
- const images = parseGptGodResponse(response);
418
+ if (this.config.logLevel === "debug") {
419
+ logger.debug("GPTGod API 响应结构", {
420
+ hasChoices: !!response?.choices,
421
+ choicesLength: response?.choices?.length,
422
+ hasImages: !!response?.images,
423
+ hasImage: !!response?.image,
424
+ responseKeys: Object.keys(response || {}),
425
+ firstChoiceContent: response?.choices?.[0]?.message?.content ? typeof response.choices[0].message.content === "string" ? response.choices[0].message.content.substring(0, 200) : JSON.stringify(response.choices[0].message.content).substring(0, 200) : "none"
426
+ });
427
+ }
428
+ const images = parseGptGodResponse(response, this.config.logLevel === "debug" ? logger : null);
316
429
  if (images.length < numImages) {
317
- logger.warn("生成的图片数量不足", { requested: numImages, received: images.length });
430
+ const warnData = {
431
+ requested: numImages,
432
+ received: images.length
433
+ };
434
+ if (this.config.logLevel === "debug") {
435
+ warnData.responsePreview = JSON.stringify(response).substring(0, 500);
436
+ }
437
+ logger.warn("生成的图片数量不足", warnData);
318
438
  }
319
439
  return images;
320
440
  } catch (error) {
@@ -337,6 +457,7 @@ function createImageProvider(config) {
337
457
  apiKey: config.yunwuApiKey,
338
458
  modelId: config.yunwuModelId,
339
459
  apiTimeout: config.apiTimeout,
460
+ logLevel: config.logLevel,
340
461
  logger: config.logger,
341
462
  ctx: config.ctx
342
463
  });
@@ -345,6 +466,7 @@ function createImageProvider(config) {
345
466
  apiKey: config.gptgodApiKey,
346
467
  modelId: config.gptgodModelId,
347
468
  apiTimeout: config.apiTimeout,
469
+ logLevel: config.logLevel,
348
470
  logger: config.logger,
349
471
  ctx: config.ctx
350
472
  });
@@ -384,7 +506,12 @@ var Config = import_koishi.Schema.intersect([
384
506
  rateLimitWindow: import_koishi.Schema.number().default(300).min(60).max(3600).description("限流时间窗口(秒)"),
385
507
  rateLimitMax: import_koishi.Schema.number().default(3).min(1).max(20).description("限流窗口内最大调用次数"),
386
508
  // 管理员设置
387
- adminUsers: import_koishi.Schema.array(import_koishi.Schema.string()).default([]).description("管理员用户ID列表(不受每日使用限制)")
509
+ adminUsers: import_koishi.Schema.array(import_koishi.Schema.string()).default([]).description("管理员用户ID列表(不受每日使用限制)"),
510
+ // 日志级别设置
511
+ logLevel: import_koishi.Schema.union([
512
+ import_koishi.Schema.const("info").description("普通信息"),
513
+ import_koishi.Schema.const("debug").description("完整的debug信息")
514
+ ]).default("info").description("日志输出详细程度")
388
515
  }),
389
516
  // 自定义风格命令配置
390
517
  import_koishi.Schema.object({
@@ -432,6 +559,7 @@ function apply(ctx, config) {
432
559
  gptgodApiKey: config.gptgodApiKey,
433
560
  gptgodModelId: config.gptgodModelId,
434
561
  apiTimeout: config.apiTimeout,
562
+ logLevel: config.logLevel,
435
563
  logger,
436
564
  ctx
437
565
  });
@@ -688,7 +816,9 @@ function apply(ctx, config) {
688
816
  if (img) {
689
817
  url = img.attrs?.src || null;
690
818
  if (url) {
691
- logger.debug("从命令参数获取图片", { url });
819
+ if (config.logLevel === "debug") {
820
+ logger.debug("从命令参数获取图片", { url });
821
+ }
692
822
  return url;
693
823
  }
694
824
  }
@@ -701,7 +831,9 @@ function apply(ctx, config) {
701
831
  return null;
702
832
  }
703
833
  url = images2[0].attrs.src;
704
- logger.debug("从引用消息获取图片", { url });
834
+ if (config.logLevel === "debug") {
835
+ logger.debug("从引用消息获取图片", { url });
836
+ }
705
837
  return url;
706
838
  }
707
839
  }
@@ -722,7 +854,9 @@ function apply(ctx, config) {
722
854
  return null;
723
855
  }
724
856
  url = images[0].attrs.src;
725
- logger.debug("从用户输入获取图片", { url });
857
+ if (config.logLevel === "debug") {
858
+ logger.debug("从用户输入获取图片", { url });
859
+ }
726
860
  return url;
727
861
  }
728
862
  __name(getImageUrl, "getImageUrl");
@@ -7,6 +7,7 @@ export interface ProviderFactoryConfig {
7
7
  gptgodApiKey: string;
8
8
  gptgodModelId: string;
9
9
  apiTimeout: number;
10
+ logLevel: 'info' | 'debug';
10
11
  logger: any;
11
12
  ctx: any;
12
13
  }
@@ -10,6 +10,7 @@ export interface ImageProvider {
10
10
  }
11
11
  export interface ProviderConfig {
12
12
  apiTimeout: number;
13
+ logLevel: 'info' | 'debug';
13
14
  logger: any;
14
15
  ctx: any;
15
16
  }
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.0.2",
4
+ "version": "0.0.4",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [