koishi-plugin-aka-ai-generator 0.3.9 → 0.4.0

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.
Files changed (2) hide show
  1. package/lib/index.js +64 -6
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -587,11 +587,31 @@ async function downloadImageAsBase643(ctx, url, timeout, logger) {
587
587
  }
588
588
  }
589
589
  __name(downloadImageAsBase643, "downloadImageAsBase64");
590
- function parseGeminiResponse(response) {
590
+ function parseGeminiResponse(response, logger) {
591
591
  try {
592
592
  const images = [];
593
+ if (!response) {
594
+ logger?.error("Gemini API 响应为空");
595
+ return [];
596
+ }
597
+ if (response.error) {
598
+ logger?.error("Gemini API 返回错误", { error: response.error });
599
+ throw new Error(`Gemini API 错误: ${response.error.message || JSON.stringify(response.error)}`);
600
+ }
593
601
  if (response.candidates && response.candidates.length > 0) {
594
602
  for (const candidate of response.candidates) {
603
+ if (candidate.finishReason && candidate.finishReason !== "STOP") {
604
+ logger?.warn("Gemini 响应 finishReason 异常", {
605
+ finishReason: candidate.finishReason,
606
+ safetyRatings: candidate.safetyRatings
607
+ });
608
+ if (candidate.finishReason === "SAFETY" || candidate.finishReason === "RECITATION") {
609
+ throw new Error(`内容被阻止: ${candidate.finishReason},可能包含不安全的内容`);
610
+ }
611
+ if (candidate.finishReason !== "MAX_TOKENS") {
612
+ logger?.warn("Gemini 响应可能不完整", { finishReason: candidate.finishReason });
613
+ }
614
+ }
595
615
  if (candidate.content && candidate.content.parts) {
596
616
  for (const part of candidate.content.parts) {
597
617
  if (part.inlineData && part.inlineData.data) {
@@ -599,21 +619,39 @@ function parseGeminiResponse(response) {
599
619
  const mimeType = part.inlineData.mimeType || "image/jpeg";
600
620
  const dataUrl = `data:${mimeType};base64,${base64Data}`;
601
621
  images.push(dataUrl);
622
+ logger?.debug("从响应中提取到图片 (inlineData)", { mimeType, dataLength: base64Data.length });
602
623
  } else if (part.inline_data && part.inline_data.data) {
603
624
  const base64Data = part.inline_data.data;
604
625
  const mimeType = part.inline_data.mime_type || "image/jpeg";
605
626
  const dataUrl = `data:${mimeType};base64,${base64Data}`;
606
627
  images.push(dataUrl);
628
+ logger?.debug("从响应中提取到图片 (inline_data)", { mimeType, dataLength: base64Data.length });
607
629
  } else if (part.fileData && part.fileData.fileUri) {
608
630
  images.push(part.fileData.fileUri);
631
+ logger?.debug("从响应中提取到图片 (fileData)", { fileUri: part.fileData.fileUri });
632
+ } else if (part.text) {
633
+ logger?.warn("响应中包含文本而非图片", { text: part.text.substring(0, 100) });
609
634
  }
610
635
  }
636
+ } else {
637
+ logger?.warn("候选响应中没有 content.parts", { candidate: JSON.stringify(candidate).substring(0, 200) });
611
638
  }
612
639
  }
640
+ } else {
641
+ logger?.warn("Gemini API 响应中没有 candidates", { response: JSON.stringify(response).substring(0, 500) });
642
+ }
643
+ if (images.length === 0) {
644
+ logger?.error("未能从 Gemini API 响应中提取到任何图片", {
645
+ hasCandidates: !!response.candidates,
646
+ candidatesCount: response.candidates?.length || 0,
647
+ responseKeys: Object.keys(response),
648
+ firstCandidate: response.candidates?.[0] ? JSON.stringify(response.candidates[0]).substring(0, 300) : null
649
+ });
613
650
  }
614
651
  return images;
615
652
  } catch (error) {
616
- return [];
653
+ logger?.error("解析 Gemini 响应时出错", { error: error.message, stack: error.stack });
654
+ throw error;
617
655
  }
618
656
  }
619
657
  __name(parseGeminiResponse, "parseGeminiResponse");
@@ -626,12 +664,18 @@ var GeminiProvider = class {
626
664
  this.config = config;
627
665
  }
628
666
  async generateImages(prompt, imageUrls, numImages) {
629
- const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls];
667
+ let urls = [];
668
+ if (Array.isArray(imageUrls)) {
669
+ urls = imageUrls.filter((url) => url && typeof url === "string" && url.trim());
670
+ } else if (imageUrls && typeof imageUrls === "string" && imageUrls.trim()) {
671
+ urls = [imageUrls];
672
+ }
630
673
  const logger = this.config.logger;
631
674
  const ctx = this.config.ctx;
632
- logger.debug("开始下载图片并转换为Base64", { urls });
675
+ logger.debug("开始处理图片输入", { urls, promptLength: prompt.length, isTextToImage: urls.length === 0 });
633
676
  const imageParts = [];
634
677
  for (const url of urls) {
678
+ if (!url || !url.trim()) continue;
635
679
  const { data, mimeType } = await downloadImageAsBase643(
636
680
  ctx,
637
681
  url,
@@ -678,14 +722,24 @@ var GeminiProvider = class {
678
722
  timeout: this.config.apiTimeout * 1e3
679
723
  }
680
724
  );
681
- const images = parseGeminiResponse(response);
725
+ const images = parseGeminiResponse(response, logger);
726
+ if (images.length === 0) {
727
+ logger.warn("Gemini API 调用成功但未解析到图片", {
728
+ current: i + 1,
729
+ total: numImages,
730
+ responseHasCandidates: !!response.candidates,
731
+ responseKeys: Object.keys(response)
732
+ });
733
+ } else {
734
+ logger.success("Gemini API 调用成功", { current: i + 1, total: numImages, imagesCount: images.length });
735
+ }
682
736
  allImages.push(...images);
683
- logger.success("Gemini API 调用成功", { current: i + 1, total: numImages });
684
737
  } catch (error) {
685
738
  logger.error("Gemini API 调用失败", {
686
739
  message: error?.message || "未知错误",
687
740
  code: error?.code,
688
741
  status: error?.response?.status,
742
+ responseData: error?.response?.data ? JSON.stringify(error.response.data).substring(0, 500) : void 0,
689
743
  current: i + 1,
690
744
  total: numImages
691
745
  });
@@ -696,6 +750,10 @@ var GeminiProvider = class {
696
750
  throw new Error(`图像处理API调用失败: ${error?.message || "未知错误"}`);
697
751
  }
698
752
  }
753
+ if (allImages.length === 0) {
754
+ logger.error("所有 Gemini API 调用都未生成图片", { numImages });
755
+ throw new Error("未能从 Gemini API 生成图片,请检查 prompt 和模型配置");
756
+ }
699
757
  return allImages;
700
758
  }
701
759
  };
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.9",
4
+ "version": "0.4.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [