koishi-plugin-aka-ai-generator 0.5.1 → 0.5.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.js CHANGED
@@ -42,10 +42,14 @@ function sanitizeError(error) {
42
42
  const sanitized = {};
43
43
  for (const key in error) {
44
44
  const lowerKey = key.toLowerCase();
45
- if (lowerKey.includes("apikey") || lowerKey.includes("api_key") || lowerKey.includes("apikey") || lowerKey === "key" || lowerKey === "authorization" || lowerKey === "token" || lowerKey === "secret" || lowerKey === "password") {
45
+ if (lowerKey.includes("apikey") || lowerKey.includes("api_key") || lowerKey === "key" || lowerKey === "authorization" || lowerKey === "token" || lowerKey === "secret" || lowerKey === "password" || lowerKey === "x-goog-api-key") {
46
46
  sanitized[key] = "[REDACTED]";
47
47
  continue;
48
48
  }
49
+ if (lowerKey === "url" && typeof error[key] === "string") {
50
+ sanitized[key] = sanitizeUrl(error[key]);
51
+ continue;
52
+ }
49
53
  sanitized[key] = sanitizeError(error[key]);
50
54
  }
51
55
  return sanitized;
@@ -55,9 +59,26 @@ function sanitizeError(error) {
55
59
  __name(sanitizeError, "sanitizeError");
56
60
  function sanitizeString(str) {
57
61
  if (typeof str !== "string") return str;
58
- return str.replace(/key["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'key="[REDACTED]"').replace(/apikey["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'apikey="[REDACTED]"').replace(/api_key["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'api_key="[REDACTED]"').replace(/authorization["\s:=]+(Bearer\s+)?([a-zA-Z0-9_-]{20,})/gi, 'authorization="[REDACTED]"').replace(/Bearer\s+([a-zA-Z0-9_-]{20,})/gi, "Bearer [REDACTED]");
62
+ let sanitized = str.replace(/[?&]key=[^&\s"']+/gi, "?key=[REDACTED]").replace(/[?&]apikey=[^&\s"']+/gi, "&apikey=[REDACTED]").replace(/[?&]api_key=[^&\s"']+/gi, "&api_key=[REDACTED]");
63
+ sanitized = sanitized.replace(/key["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'key="[REDACTED]"').replace(/apikey["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'apikey="[REDACTED]"').replace(/api_key["\s:=]+([a-zA-Z0-9_-]{20,})/gi, 'api_key="[REDACTED]"').replace(/authorization["\s:=]+(Bearer\s+)?([a-zA-Z0-9_-]{20,})/gi, 'authorization="[REDACTED]"').replace(/Bearer\s+([a-zA-Z0-9_-]{20,})/gi, "Bearer [REDACTED]").replace(/x-goog-api-key["\s:]+([a-zA-Z0-9_-]{20,})/gi, "x-goog-api-key: [REDACTED]").replace(/X-Goog-Api-Key["\s:]+([a-zA-Z0-9_-]{20,})/gi, "X-Goog-Api-Key: [REDACTED]");
64
+ return sanitized;
59
65
  }
60
66
  __name(sanitizeString, "sanitizeString");
67
+ function sanitizeUrl(url) {
68
+ if (typeof url !== "string") return url;
69
+ try {
70
+ const urlObj = new URL(url);
71
+ urlObj.searchParams.delete("key");
72
+ urlObj.searchParams.delete("apikey");
73
+ urlObj.searchParams.delete("api_key");
74
+ urlObj.searchParams.delete("token");
75
+ urlObj.searchParams.delete("secret");
76
+ return urlObj.toString();
77
+ } catch (e) {
78
+ return sanitizeString(url);
79
+ }
80
+ }
81
+ __name(sanitizeUrl, "sanitizeUrl");
61
82
 
62
83
  // src/providers/yunwu.ts
63
84
  async function downloadImageAsBase64(ctx, url, timeout, logger) {
@@ -752,6 +773,9 @@ var GeminiProvider = class {
752
773
  this.config = config;
753
774
  }
754
775
  async generateImages(prompt, imageUrls, numImages) {
776
+ if (!this.config.apiKey || !this.config.apiKey.trim()) {
777
+ throw new Error("Gemini API key 未配置或为空");
778
+ }
755
779
  let urls = [];
756
780
  if (Array.isArray(imageUrls)) {
757
781
  urls = imageUrls.filter((url) => url && typeof url === "string" && url.trim());
@@ -771,8 +795,8 @@ var GeminiProvider = class {
771
795
  logger
772
796
  );
773
797
  imageParts.push({
774
- inline_data: {
775
- mime_type: mimeType,
798
+ inlineData: {
799
+ mimeType,
776
800
  data
777
801
  }
778
802
  });
@@ -792,17 +816,30 @@ var GeminiProvider = class {
792
816
  }
793
817
  ],
794
818
  generationConfig: {
795
- responseModalities: ["IMAGE"]
819
+ responseModalities: ["IMAGE"],
820
+ imageConfig: {
821
+ aspectRatio: "16:9"
822
+ }
796
823
  }
797
824
  };
798
- logger.debug("调用 Gemini API", { prompt, imageCount: urls.length, numImages, current: i + 1, endpoint });
825
+ logger.debug("调用 Gemini API", {
826
+ prompt: prompt.substring(0, 100),
827
+ imageCount: urls.length,
828
+ numImages,
829
+ current: i + 1,
830
+ endpoint,
831
+ hasApiKey: !!this.config.apiKey,
832
+ apiKeyLength: this.config.apiKey?.length || 0,
833
+ modelId: this.config.modelId
834
+ });
799
835
  try {
800
836
  const response = await ctx.http.post(
801
837
  endpoint,
802
838
  requestData,
803
839
  {
804
840
  headers: {
805
- "Content-Type": "application/json"
841
+ "Content-Type": "application/json",
842
+ "X-Goog-Api-Key": this.config.apiKey
806
843
  },
807
844
  params: {
808
845
  key: this.config.apiKey
@@ -825,14 +862,27 @@ var GeminiProvider = class {
825
862
  } catch (error) {
826
863
  const sanitizedError = sanitizeError(error);
827
864
  const safeMessage = typeof error?.message === "string" ? sanitizeString(error.message) : "未知错误";
828
- logger.error("Gemini API 调用失败", {
865
+ const errorDetails = {
829
866
  message: safeMessage,
830
867
  code: error?.code,
831
868
  status: error?.response?.status,
832
- responseData: error?.response?.data ? sanitizeString(JSON.stringify(error.response.data).substring(0, 500)) : void 0,
869
+ statusText: error?.response?.statusText,
833
870
  current: i + 1,
834
871
  total: numImages
835
- });
872
+ };
873
+ if (error?.response?.data) {
874
+ try {
875
+ const responseStr = JSON.stringify(error.response.data);
876
+ errorDetails.responseData = sanitizeString(responseStr.substring(0, 1e3));
877
+ } catch (e) {
878
+ errorDetails.responseData = "无法序列化响应数据";
879
+ }
880
+ }
881
+ if (error?.config) {
882
+ errorDetails.url = error.config.url ? sanitizeUrl(error.config.url) : void 0;
883
+ errorDetails.method = error.config.method;
884
+ }
885
+ logger.error("Gemini API 调用失败", errorDetails);
836
886
  if (allImages.length > 0) {
837
887
  logger.warn("部分图片生成失败,返回已生成的图片", { generated: allImages.length, requested: numImages });
838
888
  break;
@@ -22,3 +22,7 @@ export declare function sanitizeError(error: any): any;
22
22
  * 清理字符串中的 API KEY 模式
23
23
  */
24
24
  export declare function sanitizeString(str: string): string;
25
+ /**
26
+ * 清理 URL 中的敏感查询参数
27
+ */
28
+ export declare function sanitizeUrl(url: string): string;
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.5.1",
4
+ "version": "0.5.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [