koishi-plugin-aka-ai-generator 0.7.12 → 0.8.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 +126 -59
  2. package/package.json +1 -1
package/lib/index.js CHANGED
@@ -51,7 +51,7 @@ function sanitizeError(error) {
51
51
  const sanitized = {};
52
52
  for (const key in error) {
53
53
  const lowerKey = key.toLowerCase();
54
- if (lowerKey.includes("apikey") || lowerKey.includes("api_key") || lowerKey.includes("apikey") || lowerKey === "key" || lowerKey === "authorization" || lowerKey === "token" || lowerKey === "secret" || lowerKey === "password") {
54
+ if (lowerKey.includes("apikey") || lowerKey.includes("api_key") || lowerKey.includes("api-key") || lowerKey === "key" || lowerKey === "authorization" || lowerKey === "token" || lowerKey === "secret" || lowerKey === "password") {
55
55
  sanitized[key] = "[REDACTED]";
56
56
  continue;
57
57
  }
@@ -64,7 +64,7 @@ function sanitizeError(error) {
64
64
  __name(sanitizeError, "sanitizeError");
65
65
  function sanitizeString(str) {
66
66
  if (typeof str !== "string") return str;
67
- 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]");
67
+ return str.replace(/key["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'key="[REDACTED]"').replace(/apikey["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'apikey="[REDACTED]"').replace(/api_key["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'api_key="[REDACTED]"').replace(/api-key["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'api-key="[REDACTED]"').replace(/x-api-key["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'x-api-key="[REDACTED]"').replace(/authorization["'\s:=]+(Bearer\s+)?([a-zA-Z0-9_-]{10,})/gi, 'authorization="[REDACTED]"').replace(/Bearer\s+([a-zA-Z0-9_-]{10,})/gi, "Bearer [REDACTED]").replace(/([?&])key=([a-zA-Z0-9_-]{10,})/gi, "$1key=[REDACTED]").replace(/([?&])apikey=([a-zA-Z0-9_-]{10,})/gi, "$1apikey=[REDACTED]").replace(/([?&])api_key=([a-zA-Z0-9_-]{10,})/gi, "$1api_key=[REDACTED]").replace(/([?&])token=([a-zA-Z0-9_-]{10,})/gi, "$1token=[REDACTED]").replace(/([?&])access_token=([a-zA-Z0-9_-]{10,})/gi, "$1access_token=[REDACTED]").replace(/sk-[a-zA-Z0-9]{20,}/gi, "[REDACTED-SK]").replace(/AIza[a-zA-Z0-9_-]{30,}/gi, "[REDACTED-GAPI]").replace(/secret["'\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'secret="[REDACTED]"').replace(/password["'\s:=]+([^\s"']{4,})/gi, 'password="[REDACTED]"');
68
68
  }
69
69
  __name(sanitizeString, "sanitizeString");
70
70
  async function downloadImageAsBase64(ctx, url, timeout, logger, maxSize = 10 * 1024 * 1024) {
@@ -806,7 +806,13 @@ var GeminiProvider = class {
806
806
  ],
807
807
  generationConfig: {
808
808
  responseModalities: ["IMAGE"]
809
- }
809
+ },
810
+ safetySettings: [
811
+ { category: "HARM_CATEGORY_HARASSMENT", threshold: "BLOCK_NONE" },
812
+ { category: "HARM_CATEGORY_HATE_SPEECH", threshold: "BLOCK_NONE" },
813
+ { category: "HARM_CATEGORY_SEXUALLY_EXPLICIT", threshold: "BLOCK_NONE" },
814
+ { category: "HARM_CATEGORY_DANGEROUS_CONTENT", threshold: "BLOCK_NONE" }
815
+ ]
810
816
  };
811
817
  logger.debug("调用 Gemini API", { prompt, imageCount: urls.length, numImages, current: i + 1, endpoint });
812
818
  try {
@@ -1806,49 +1812,90 @@ var StyleItemSchema = import_koishi2.Schema.object({
1806
1812
  prompt: import_koishi2.Schema.string().role("textarea", { rows: 4 }).required().description("生成 prompt")
1807
1813
  });
1808
1814
  var Config = import_koishi2.Schema.intersect([
1815
+ // ===== 1. 供应商选择 =====
1809
1816
  import_koishi2.Schema.object({
1810
1817
  provider: import_koishi2.Schema.union([
1811
1818
  import_koishi2.Schema.const("yunwu").description("云雾 Gemini 服务"),
1812
1819
  import_koishi2.Schema.const("gptgod").description("GPTGod 服务"),
1813
1820
  import_koishi2.Schema.const("gemini").description("Google Gemini 原生")
1814
- ]).default("yunwu").description("图像生成供应商"),
1815
- yunwuApiKey: import_koishi2.Schema.string().description("云雾API密钥").role("secret").required(),
1816
- yunwuModelId: import_koishi2.Schema.string().default("gemini-2.5-flash-image").description("云雾图像生成模型ID"),
1817
- gptgodApiKey: import_koishi2.Schema.string().description("GPTGod API 密钥").role("secret").default(""),
1818
- gptgodModelId: import_koishi2.Schema.string().default("nano-banana").description("GPTGod 模型ID"),
1819
- geminiApiKey: import_koishi2.Schema.string().description("Gemini API 密钥").role("secret").default(""),
1820
- geminiModelId: import_koishi2.Schema.string().default("gemini-2.5-flash").description("Gemini 模型ID"),
1821
- geminiApiBase: import_koishi2.Schema.string().default("https://generativelanguage.googleapis.com").description("Gemini API 基础地址"),
1822
- modelMappings: import_koishi2.Schema.array(import_koishi2.Schema.object({
1823
- suffix: import_koishi2.Schema.string().required().description("指令后缀(例如 4K,对应输入 -4K)"),
1824
- provider: import_koishi2.Schema.union([
1825
- import_koishi2.Schema.const("yunwu").description("云雾 Gemini 服务"),
1826
- import_koishi2.Schema.const("gptgod").description("GPTGod 服务"),
1827
- import_koishi2.Schema.const("gemini").description("Google Gemini 原生")
1828
- ]).description("可选:覆盖供应商"),
1829
- modelId: import_koishi2.Schema.string().required().description("触发该后缀时使用的模型 ID")
1830
- })).role("table").default([]).description("根据 -后缀切换模型/供应商"),
1821
+ ]).default("yunwu").description("图像生成供应商")
1822
+ }).description("🎨 供应商选择"),
1823
+ // ===== 2. 云雾 API 配置(条件显示) =====
1824
+ import_koishi2.Schema.union([
1825
+ import_koishi2.Schema.object({
1826
+ provider: import_koishi2.Schema.const("yunwu").required(),
1827
+ yunwuApiKey: import_koishi2.Schema.string().role("secret").required().description("云雾 API 密钥"),
1828
+ yunwuModelId: import_koishi2.Schema.string().default("gemini-2.5-flash-image").description("云雾图像生成模型ID")
1829
+ }),
1830
+ import_koishi2.Schema.object({
1831
+ yunwuApiKey: import_koishi2.Schema.string().role("secret").default("").hidden(),
1832
+ yunwuModelId: import_koishi2.Schema.string().default("gemini-2.5-flash-image").hidden()
1833
+ })
1834
+ ]),
1835
+ // ===== 3. GPTGod API 配置(条件显示) =====
1836
+ import_koishi2.Schema.union([
1837
+ import_koishi2.Schema.object({
1838
+ provider: import_koishi2.Schema.const("gptgod").required(),
1839
+ gptgodApiKey: import_koishi2.Schema.string().role("secret").required().description("GPTGod API 密钥"),
1840
+ gptgodModelId: import_koishi2.Schema.string().default("nano-banana").description("GPTGod 模型ID")
1841
+ }),
1842
+ import_koishi2.Schema.object({
1843
+ gptgodApiKey: import_koishi2.Schema.string().role("secret").default("").hidden(),
1844
+ gptgodModelId: import_koishi2.Schema.string().default("nano-banana").hidden()
1845
+ })
1846
+ ]),
1847
+ // ===== 4. Gemini API 配置(条件显示) =====
1848
+ import_koishi2.Schema.union([
1849
+ import_koishi2.Schema.object({
1850
+ provider: import_koishi2.Schema.const("gemini").required(),
1851
+ geminiApiKey: import_koishi2.Schema.string().role("secret").required().description("Gemini API 密钥"),
1852
+ geminiModelId: import_koishi2.Schema.string().default("gemini-2.5-flash").description("Gemini 模型ID"),
1853
+ geminiApiBase: import_koishi2.Schema.string().default("https://generativelanguage.googleapis.com").description("Gemini API 基础地址")
1854
+ }),
1855
+ import_koishi2.Schema.object({
1856
+ geminiApiKey: import_koishi2.Schema.string().role("secret").default("").hidden(),
1857
+ geminiModelId: import_koishi2.Schema.string().default("gemini-2.5-flash").hidden(),
1858
+ geminiApiBase: import_koishi2.Schema.string().default("https://generativelanguage.googleapis.com").hidden()
1859
+ })
1860
+ ]),
1861
+ // ===== 5. 通用设置 =====
1862
+ import_koishi2.Schema.object({
1831
1863
  apiTimeout: import_koishi2.Schema.number().default(120).description("API请求超时时间(秒)"),
1832
1864
  commandTimeout: import_koishi2.Schema.number().default(180).description("命令执行总超时时间(秒)"),
1833
- // 默认设置
1834
- defaultNumImages: import_koishi2.Schema.number().default(1).min(1).max(4).description("默认生成图片数量"),
1835
- // 配额设置
1865
+ defaultNumImages: import_koishi2.Schema.number().default(1).min(1).max(4).description("默认生成图片数量")
1866
+ }).description("⚙️ 通用设置"),
1867
+ // ===== 6. 限流与配额 =====
1868
+ import_koishi2.Schema.object({
1836
1869
  dailyFreeLimit: import_koishi2.Schema.number().default(5).min(1).max(100).description("每日免费调用次数"),
1837
- // 限流设置
1838
1870
  rateLimitWindow: import_koishi2.Schema.number().default(300).min(60).max(3600).description("限流时间窗口(秒)"),
1839
- rateLimitMax: import_koishi2.Schema.number().default(3).min(1).max(20).description("限流窗口内最大调用次数"),
1840
- // 管理员设置
1871
+ rateLimitMax: import_koishi2.Schema.number().default(3).min(1).max(20).description("限流窗口内最大调用次数")
1872
+ }).description("🚦 限流与配额"),
1873
+ // ===== 7. 管理员设置 =====
1874
+ import_koishi2.Schema.object({
1841
1875
  adminUsers: import_koishi2.Schema.array(import_koishi2.Schema.string()).default([]).description("管理员用户ID列表(不受每日使用限制)"),
1842
- // 日志级别设置
1843
1876
  logLevel: import_koishi2.Schema.union([
1844
1877
  import_koishi2.Schema.const("info").description("普通信息"),
1845
1878
  import_koishi2.Schema.const("debug").description("完整的debug信息")
1846
- ]).default("info").description("日志输出详细程度"),
1847
- // 安全策略拦截设置
1848
- securityBlockWindow: import_koishi2.Schema.number().default(600).min(60).max(3600).description("安全策略拦截追踪时间窗口(秒),在此时间窗口内连续触发拦截会被记录"),
1849
- securityBlockWarningThreshold: import_koishi2.Schema.number().default(3).min(1).max(10).description("安全策略拦截警示阈值,连续触发此次数拦截后将发送警示消息,再次触发将被扣除积分")
1850
- }),
1851
- // 自定义风格命令配置
1879
+ ]).default("info").description("日志输出详细程度")
1880
+ }).description("👑 管理员设置"),
1881
+ // ===== 8. 安全策略 =====
1882
+ import_koishi2.Schema.object({
1883
+ securityBlockWindow: import_koishi2.Schema.number().default(600).min(60).max(3600).description("安全策略拦截追踪时间窗口(秒)"),
1884
+ securityBlockWarningThreshold: import_koishi2.Schema.number().default(3).min(1).max(10).description("安全策略拦截警示阈值,连续触发此次数后将发送警示")
1885
+ }).description("🛡️ 安全策略"),
1886
+ // ===== 9. 模型映射 =====
1887
+ import_koishi2.Schema.object({
1888
+ modelMappings: import_koishi2.Schema.array(import_koishi2.Schema.object({
1889
+ suffix: import_koishi2.Schema.string().required().description("指令后缀(例如 4K,对应输入 -4K)"),
1890
+ provider: import_koishi2.Schema.union([
1891
+ import_koishi2.Schema.const("yunwu").description("云雾 Gemini 服务"),
1892
+ import_koishi2.Schema.const("gptgod").description("GPTGod 服务"),
1893
+ import_koishi2.Schema.const("gemini").description("Google Gemini 原生")
1894
+ ]).description("可选:覆盖供应商"),
1895
+ modelId: import_koishi2.Schema.string().required().description("触发该后缀时使用的模型 ID")
1896
+ })).role("table").default([]).description("根据 -后缀切换模型/供应商")
1897
+ }).description("🔀 模型映射"),
1898
+ // ===== 10. 风格命令 =====
1852
1899
  import_koishi2.Schema.object({
1853
1900
  styles: import_koishi2.Schema.array(StyleItemSchema).role("table").default([
1854
1901
  {
@@ -1860,37 +1907,57 @@ var Config = import_koishi2.Schema.intersect([
1860
1907
  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. 如果主体是人物脸部,脸部生成效果应参考欧美混血白人精致美丽帅气英俊的外观特征进行生成,保持精致立体的五官轮廓、健康光泽的肌肤质感、优雅的气质和自然的表情,确保面部特征协调美观。"
1861
1908
  }
1862
1909
  ]).description("自定义风格命令配置")
1863
- }),
1910
+ }).description("🎭 风格命令"),
1911
+ // ===== 11. 风格分组 =====
1864
1912
  import_koishi2.Schema.object({
1865
1913
  styleGroups: import_koishi2.Schema.dict(import_koishi2.Schema.object({
1866
1914
  prompts: import_koishi2.Schema.array(StyleItemSchema).role("table").default([]).description("属于该类型的 prompt 列表")
1867
1915
  })).role("table").default({}).description("按类型管理的 prompt 组,键名即为分组名称")
1868
- }),
1869
- // 视频生成配置(独立于图像生成配置)
1916
+ }).description("📂 风格分组"),
1917
+ // ===== 12. 视频生成(条件显示) =====
1870
1918
  import_koishi2.Schema.object({
1871
- enableVideoGeneration: import_koishi2.Schema.boolean().default(false).description("启用图生成视频功能(消耗较大,需谨慎开启)"),
1872
- videoProvider: import_koishi2.Schema.union([
1873
- import_koishi2.Schema.const("yunwu").description("云雾服务")
1874
- ]).default("yunwu").description("视频生成供应商(目前只支持云雾)"),
1875
- videoApiKey: import_koishi2.Schema.string().description("视频生成 API 密钥(独立于图像生成配置)").role("secret").default(""),
1876
- videoApiBase: import_koishi2.Schema.string().default("https://yunwu.ai").description("视频生成 API 地址"),
1877
- videoModelId: import_koishi2.Schema.string().default("sora-2").description("视频生成模型ID (sora-2 或 sora-2-pro)"),
1878
- videoMaxWaitTime: import_koishi2.Schema.number().default(300).min(60).max(600).description("视频生成最大等待时间(秒),超时后可异步查询"),
1879
- videoCreditsMultiplier: import_koishi2.Schema.number().default(5).min(1).max(20).description("视频生成积分倍数(相对于图片生成,默认5倍)"),
1880
- videoStyles: import_koishi2.Schema.array(import_koishi2.Schema.object({
1881
- commandName: import_koishi2.Schema.string().required().description("命令名称").role("table-cell", { width: 100 }),
1882
- prompt: import_koishi2.Schema.string().role("textarea", { rows: 2 }).required().description("视频描述 prompt"),
1883
- duration: import_koishi2.Schema.number().default(15).description("视频时长(秒,仅支持 15 或 25)"),
1884
- aspectRatio: import_koishi2.Schema.string().description("宽高比(如 16:9)")
1885
- })).role("table").default([
1886
- {
1887
- commandName: "变视频",
1888
- prompt: "将该图片生成一段符合产品展现的流畅视频",
1889
- duration: 15,
1890
- aspectRatio: "16:9"
1891
- }
1892
- ]).description("视频风格预设")
1893
- })
1919
+ enableVideoGeneration: import_koishi2.Schema.boolean().default(false).description("启用图生成视频功能(消耗较大,需谨慎开启)")
1920
+ }).description("🎬 视频生成"),
1921
+ import_koishi2.Schema.union([
1922
+ import_koishi2.Schema.object({
1923
+ enableVideoGeneration: import_koishi2.Schema.const(true).required(),
1924
+ videoProvider: import_koishi2.Schema.union([
1925
+ import_koishi2.Schema.const("yunwu").description("云雾服务")
1926
+ ]).default("yunwu").description("视频生成供应商(目前只支持云雾)"),
1927
+ videoApiKey: import_koishi2.Schema.string().role("secret").default("").description("视频生成 API 密钥(独立于图像生成配置)"),
1928
+ videoApiBase: import_koishi2.Schema.string().default("https://yunwu.ai").description("视频生成 API 地址"),
1929
+ videoModelId: import_koishi2.Schema.string().default("sora-2").description("视频生成模型ID (sora-2 sora-2-pro)"),
1930
+ videoMaxWaitTime: import_koishi2.Schema.number().default(300).min(60).max(600).description("视频生成最大等待时间(秒)"),
1931
+ videoCreditsMultiplier: import_koishi2.Schema.number().default(5).min(1).max(20).description("视频生成积分倍数(相对于图片生成,默认5倍)"),
1932
+ videoStyles: import_koishi2.Schema.array(import_koishi2.Schema.object({
1933
+ commandName: import_koishi2.Schema.string().required().description("命令名称").role("table-cell", { width: 100 }),
1934
+ prompt: import_koishi2.Schema.string().role("textarea", { rows: 2 }).required().description("视频描述 prompt"),
1935
+ duration: import_koishi2.Schema.number().default(15).description("视频时长(秒,仅支持 15 或 25)"),
1936
+ aspectRatio: import_koishi2.Schema.string().description("宽高比(如 16:9)")
1937
+ })).role("table").default([
1938
+ {
1939
+ commandName: "变视频",
1940
+ prompt: "将该图片生成一段符合产品展现的流畅视频",
1941
+ duration: 15,
1942
+ aspectRatio: "16:9"
1943
+ }
1944
+ ]).description("视频风格预设")
1945
+ }),
1946
+ import_koishi2.Schema.object({
1947
+ videoProvider: import_koishi2.Schema.union([import_koishi2.Schema.const("yunwu")]).default("yunwu").hidden(),
1948
+ videoApiKey: import_koishi2.Schema.string().role("secret").default("").hidden(),
1949
+ videoApiBase: import_koishi2.Schema.string().default("https://yunwu.ai").hidden(),
1950
+ videoModelId: import_koishi2.Schema.string().default("sora-2").hidden(),
1951
+ videoMaxWaitTime: import_koishi2.Schema.number().default(300).hidden(),
1952
+ videoCreditsMultiplier: import_koishi2.Schema.number().default(5).hidden(),
1953
+ videoStyles: import_koishi2.Schema.array(import_koishi2.Schema.object({
1954
+ commandName: import_koishi2.Schema.string().required(),
1955
+ prompt: import_koishi2.Schema.string().required(),
1956
+ duration: import_koishi2.Schema.number().default(15),
1957
+ aspectRatio: import_koishi2.Schema.string()
1958
+ })).default([]).hidden()
1959
+ })
1960
+ ])
1894
1961
  ]);
1895
1962
  function apply(ctx, config) {
1896
1963
  const logger = ctx.logger("aka-ai-generator");
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.7.12",
4
+ "version": "0.8.0",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "files": [