{"version":3,"sources":["../src/index.ts","../src/shared/chatluna-tool-definitions.ts","../src/shared/constants.ts","../src/bridge/chatluna/context-injection.ts","../src/bridge/chatluna/runtime.ts","../src/bridge/chatluna/tool-runtime.ts","../src/shared/billing.ts","../src/bridge/chatluna/tools.ts","../src/bridge/chatluna/manager.ts","../src/bridge/yesimbot/tool-definitions.ts","../src/bridge/yesimbot/tool-runtime.ts","../src/bridge/yesimbot/tools.ts","../src/bridge/yesimbot/manager.ts","../src/commands/help.ts","../src/commands/image.ts","../src/utils/parser.ts","../src/commands/index.ts","../src/orchestrators/ImageGenerationOrchestrator.ts","../src/providers/utils.ts","../src/shared/prompt-timeout.ts","../src/utils/input.ts","../src/providers/errors.ts","../src/providers/policies/retry.ts","../src/providers/policies/timeout.ts","../src/shared/logging.ts","../src/providers/base.ts","../src/providers/gemini.ts","../src/providers/openai.ts","../src/providers/registry.ts","../src/service/AiImageGeneratorService.ts","../src/core/image-context-store.ts","../src/services/UserManager.ts","../src/shared/config.ts"],"sourcesContent":["import { Context } from 'koishi'\nimport path from 'node:path'\n\nimport { ChatLunaBridgeManager } from './bridge/chatluna/manager.js'\nimport { YesImBotBridgeManager } from './bridge/yesimbot/manager.js'\nimport { registerAllCommands } from './commands/index.js'\nimport { createImageGenerationHandlers } from './orchestrators/ImageGenerationOrchestrator.js'\nimport { createGeminiProvider } from './providers/gemini.js'\nimport { createOpenAIProvider } from './providers/openai.js'\nimport { ProviderRegistry } from './providers/registry.js'\nimport { AiImageGeneratorService } from './service/AiImageGeneratorService.js'\nimport { UserManager } from './services/UserManager.js'\nimport { Config as ConfigSchema } from './shared/config.js'\nimport type { Config as PluginConfig } from './shared/config.js'\nimport { PLUGIN_NAME } from './shared/constants.js'\n\n/**\n * V2 插件入口（aka-ai-image-generator） —— 仅图像生成。\n *\n * Phase 4 MVP 接线：\n *   - ProviderRegistry：模块级单例，注册 2 个协议优先 image Provider 工厂\n *   - UserManager：用户积分 / 限流 / 安全计数（cherry-pick 自 v1）\n *   - AiImageGeneratorService：核心服务（Provider 实例化 + 积分 + 用量 + 图像记忆）\n *   - ImageGenerationOrchestrator：MVP 编排（文生图 + 图生图，命令级超时）\n *   - 命令族：文生图 / 图生图 / 合成图 / 图像查询 / 图像账单\n *\n * 配置热重载：通过 ctx.scope.update 风格的 acceptor 处理；本入口在变更时同步\n * 更新闭包内的 currentConfig，并调用 `service.updateConfig(next)`。\n *\n * 后续阶段计划只保留在文档中，当前运行时代码不暴露未实现功能的配置项。\n *\n * 注：本插件**不包含视频生成**功能，相关代码 / 配置 / 文档全部不在 v2 范围内。\n */\nexport const name = PLUGIN_NAME\n\n// ChatLuna / YesImBot 可选依赖声明（不安装对应插件时仍可正常工作）\n// 声明 optional 可让 Koishi 在加载此插件前先加载已安装的 yesimbot / chatluna，\n// 避免首次启动时 ctx[\"yesimbot.tool\"] 尚未注册的时序问题。\n//\n// \"yesimbot\": yesimbot 插件根上下文（提供 ctx.yesimbot 命名空间，帮助加载时序）\n// \"yesimbot.tool\": YesImBot ToolService（register/unregister API，extensions/tools Map）\nexport const inject = {\n  optional: ['chatluna', 'yesimbot', 'yesimbot.tool'],\n} as const\n\n// 暴露给 Koishi 的配置类型与 Schema（与 shared/config.ts 中的运行期 interface 对齐）\nexport type Config = PluginConfig\nexport const Config = ConfigSchema\n\n// 模块级注册表实例（生命周期与插件模块一致）\nconst providerRegistry = new ProviderRegistry()\n\n// 内置 Provider 注册（image-only：协议优先，不注册供应商别名）\nproviderRegistry.register('openai', createOpenAIProvider)\nproviderRegistry.register('gemini', createGeminiProvider)\n\n\nexport function apply(ctx: Context, config: Config) {\n  const logger = ctx.logger(name)\n\n  // 1. UserManager —— 数据落盘目录走 ctx.baseDir/data/<plugin>\n  const dataDir = path.join(ctx.baseDir, 'data', name)\n  const userManager = new UserManager(dataDir, logger)\n\n  // 2. Service —— 注入 UserManager 与 ProviderRegistry\n  // Service 基类构造函数会自动注册到 ctx（super(ctx, 'aiImageGenerator', true)），\n  // 因此这里不需要再调用 ctx.plugin(service)。\n  const service = new AiImageGeneratorService(\n    ctx,\n    config,\n    userManager,\n    providerRegistry,\n  )\n\n  // 3. Orchestrator —— 闭包持有 currentConfig，热重载时由 acceptor 覆盖\n  let currentConfig = config\n  const handlers = createImageGenerationHandlers({\n    ctx,\n    service,\n    userManager,\n    logger,\n    getConfig: () => currentConfig,\n  })\n\n  // 4. 命令族\n  const commands = registerAllCommands({\n    ctx,\n    service,\n    handlers,\n    getConfig: () => currentConfig,\n  })\n\n  // 5. ChatLuna 桥接管理器\n  const chatLunaBridgeManager = new ChatLunaBridgeManager(\n    ctx,\n    service,\n    currentConfig,\n    logger,\n  )\n  // 等待 chatluna 服务可用后再同步（避免在 chatluna 尚未加载时过早调用导致工具无法注册）\n  ctx.inject(['chatluna'], async (ctx) => {\n    await chatLunaBridgeManager.sync(currentConfig.chatlunaEnabled)\n  })\n\n  // 6. YesImBot 桥接管理器\n  const yesimbotBridgeManager = new YesImBotBridgeManager(\n    ctx,\n    service,\n    currentConfig,\n    logger,\n  )\n  void yesimbotBridgeManager.sync(currentConfig.yesimbotEnabled)\n\n  // 7. 配置热重载兼容\n  ctx.accept((next: Config) => {\n    currentConfig = next\n    service.updateConfig(next)\n    commands.image.refreshStyleCommands()\n    chatLunaBridgeManager.updateConfig(next)\n    // 只在 chatluna 服务可用时同步（热重载场景）\n    if ((ctx as Context & { chatluna?: unknown }).chatluna) {\n      void chatLunaBridgeManager.sync(next.chatlunaEnabled)\n    }\n    yesimbotBridgeManager.updateConfig(next)\n    void yesimbotBridgeManager.sync(next.yesimbotEnabled)\n  })\n\n  // 8. 插件卸载时的清理\n  ctx.on('dispose' as any, async () => {\n    await chatLunaBridgeManager.dispose()\n    await yesimbotBridgeManager.dispose()\n  })\n\n  const registered = providerRegistry.list()\n  logger.info(\n    'plugin=%s phase=4 status=protocol-mvp-ready providers=%s count=%d commands=%s chatluna=%s yesimbot=%s',\n    name,\n    registered.join(',') || '<none>',\n    registered.length,\n    '文生图,图生图,合成图,图像查询,图像账单,图像充值,图像排行榜',\n    currentConfig.chatlunaEnabled ? 'enabled' : 'disabled',\n    currentConfig.yesimbotEnabled ? 'enabled' : 'disabled',\n  )\n}\n","/**\n * ChatLuna 工具定义（V2 积分制适配版）。\n *\n * 定义了在 ChatLuna 中注册的 5 个基础工具的 name、description、usage 和 inputSchema。\n * riskLevel 标记用于后续安全审查；当前版本所有图像生成工具均为 low。\n */\n\nexport interface AiGeneratorToolDefinition {\n  name: string\n  description: string\n  usage: string\n  riskLevel: 'low' | 'medium' | 'high'\n  inputSchema: Record<string, unknown>\n}\n\nexport const AI_GENERATOR_TOOL_DEFINITIONS: AiGeneratorToolDefinition[] = [\n  {\n    name: 'aigc_generate_image',\n    description: 'Generate one or more images from a natural-language prompt.',\n    usage:\n      'Use this for pure text-to-image requests. Prefer this when the user asks to generate a fresh image without referencing an existing one.',\n    riskLevel: 'low',\n    inputSchema: {\n      type: 'object',\n      properties: {\n        prompt: { type: 'string', description: 'Image generation prompt.' },\n        numImages: {\n          type: 'number',\n          minimum: 1,\n          maximum: 4,\n          description: 'Number of images to generate.',\n        },\n        aspectRatio: {\n          type: 'string',\n          enum: ['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'],\n        },\n        resolution: { type: 'string', enum: ['1k', '2k', '4k'] },\n        modelSuffix: {\n          type: 'string',\n          description: 'Optional configured model suffix.',\n        },\n      },\n      required: ['prompt'],\n      additionalProperties: false,\n    },\n  },\n  {\n    name: 'aigc_edit_image',\n    description:\n      'Edit an image using the current message image, quoted image, explicit image URLs, or the last generated image in the current room.',\n    usage:\n      'Use this when the user wants to modify an uploaded image, continue the previous generated image, or preserve the same subject while changing details.',\n    riskLevel: 'low',\n    inputSchema: {\n      type: 'object',\n      properties: {\n        prompt: { type: 'string', description: 'Editing prompt.' },\n        referenceMode: {\n          type: 'string',\n          enum: ['current_message', 'quoted_message', 'explicit', 'last_generated'],\n          description: 'Where to load reference images from.',\n        },\n        imageUrls: {\n          type: 'array',\n          items: { type: 'string' },\n          description: 'Explicit image URLs when referenceMode is explicit.',\n        },\n        numImages: {\n          type: 'number',\n          minimum: 1,\n          maximum: 4,\n          description: 'Number of images to generate.',\n        },\n        aspectRatio: {\n          type: 'string',\n          enum: ['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'],\n        },\n        resolution: { type: 'string', enum: ['1k', '2k', '4k'] },\n        modelSuffix: {\n          type: 'string',\n          description: 'Optional configured model suffix.',\n        },\n      },\n      required: ['prompt', 'referenceMode'],\n      additionalProperties: false,\n    },\n  },\n  {\n    name: 'aigc_apply_style_preset',\n    description:\n      'Apply a configured style preset to either a fresh generation or a referenced image.',\n    usage:\n      'Use this when a configured style command matches the user request better than free-form prompt writing.',\n    riskLevel: 'low',\n    inputSchema: {\n      type: 'object',\n      properties: {\n        stylePreset: {\n          type: 'string',\n          description: 'Configured style command name.',\n        },\n        styleQuery: {\n          type: 'string',\n          description:\n            'Natural-language style lookup query when the exact preset name is unknown.',\n        },\n        promptAdditions: {\n          type: 'string',\n          description: 'Optional extra prompt details.',\n        },\n        referenceMode: {\n          type: 'string',\n          enum: ['none', 'current_message', 'quoted_message', 'explicit', 'last_generated'],\n          description: 'Where to load reference images from.',\n        },\n        imageUrls: {\n          type: 'array',\n          items: { type: 'string' },\n          description: 'Explicit image URLs when referenceMode is explicit.',\n        },\n        numImages: {\n          type: 'number',\n          minimum: 1,\n          maximum: 4,\n          description: 'Number of images to generate.',\n        },\n        aspectRatio: {\n          type: 'string',\n          enum: ['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'],\n        },\n        resolution: { type: 'string', enum: ['1k', '2k', '4k'] },\n        modelSuffix: {\n          type: 'string',\n          description: 'Optional configured model suffix.',\n        },\n      },\n      anyOf: [{ required: ['stylePreset'] }, { required: ['styleQuery'] }],\n      additionalProperties: false,\n    },\n  },\n  {\n    name: 'aigc_get_quota',\n    description: 'Get the current user credit balance and generation statistics.',\n    usage:\n      'Use this when the user asks how many credits, daily free credits, or purchased credits remain.',\n    riskLevel: 'low',\n    inputSchema: {\n      type: 'object',\n      properties: {},\n      additionalProperties: false,\n    },\n  },\n  {\n    name: 'aigc_list_styles',\n    description: 'List configured style presets exposed by aka-ai-image-generator.',\n    usage: 'Use this when the user asks what style presets are available.',\n    riskLevel: 'low',\n    inputSchema: {\n      type: 'object',\n      properties: {},\n      additionalProperties: false,\n    },\n  },\n]\n","export const PLUGIN_NAME = 'aka-ai-image-generator'\nexport const CHATLUNA_BRIDGE_PLATFORM_NAME = 'aka-ai-image-generator-chatluna-bridge'\nexport const YESIMBOT_BRIDGE_EXTENSION_ID = 'aka-ai-image-generator'\nexport const COMMAND_TIMEOUT_SECONDS = 300\n\nexport const COMMANDS = {\n  IMG_TO_IMG: '图生图',\n  TXT_TO_IMG: '文生图',\n  COMPOSE_IMAGE: '合成图',\n  ADMIN_QUERY: '图像查询',\n  USAGE_RANKING: '图像排行榜',\n  ADMIN_RECHARGE: '图像充值',\n  ADMIN_BILL: '图像账单',\n  IMAGE_HELP: '图像指令',\n  PARAM_HELP: '图像参数',\n} as const\n","/**\n * ChatLuna 上下文注入（V2 积分制适配版）。\n *\n * 在 chatluna/before-chat 事件中注入 AIGC 上下文：\n * - 上一张图像的引用信息（[AIGC_CONTEXT]）\n * - 风格推荐候选（[AIGC_STYLE_CANDIDATES]）\n * - 同时注入到 promptVariables 中供模板使用\n *\n * 在 chatluna/clear-chat-history 事件中清除对应的图像上下文。\n *\n * 关键 V2 适配：\n * - AiImageGeneratorService 的 pruneConversationImageContexts / getConversationImageContext\n *   / clearConversationImageContext 方法名与 V1 一致，无需修改调用。\n * - matchStylePresets 返回 StyleMatchCandidate[]，与 V1 的接口兼容。\n */\n\nimport type { Context } from 'koishi'\n\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport type {\n  ChatLunaConfigAccessor,\n  ChatLunaHumanMessageLike,\n  ChatLunaPromptVariablesLike,\n  ChatLunaSessionLike,\n} from './types.js'\n\ntype Disposer = (() => void) | undefined\n\nexport function installChatLunaContextInjection(\n  ctx: Context,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n  logger: ReturnType<Context['logger']>,\n) {\n  const disposeBeforeChat = (ctx as Context & {\n    on: (name: string, listener: (...args: unknown[]) => unknown) => Disposer\n  }).on('chatluna/before-chat', async (...args: unknown[]) => {\n    const config = getConfig()\n    if (!config.chatlunaContextInjectionEnabled) return\n\n    aiGenerator.pruneConversationImageContexts(config.chatlunaContextTtlSeconds)\n\n    const [, messageArg, promptVariablesArg, conversationArg, sessionArg] = args\n    const message = asHumanMessage(messageArg)\n    const promptVariables = asPromptVariables(promptVariablesArg)\n    const session = asSession(sessionArg)\n\n    if (!message) return\n\n    const text = getMessageText(message) || getSessionText(session)\n    if (!text || hasAnyAiGeneratorContextBlock(text)) return\n\n    const conversationId = extractConversationId(\n      conversationArg,\n      promptVariables,\n      session,\n      aiGenerator,\n    )\n    const styleMatches = aiGenerator.matchStylePresets(text, 3)\n    const shouldInjectStyleCandidates = styleMatches.length > 0\n    const shouldInjectImageContext =\n      looksLikeImageFollowUp(text) && Boolean(conversationId)\n\n    if (!shouldInjectStyleCandidates && !shouldInjectImageContext) return\n\n    const context = conversationId\n      ? aiGenerator.getConversationImageContext(conversationId)\n      : undefined\n    const lastGenerated = context?.lastGenerated\n    const blocks: string[] = []\n\n    if (shouldInjectImageContext && conversationId && lastGenerated) {\n      blocks.push(\n        [\n          '[AIGC_CONTEXT]',\n          `conversationId: ${conversationId}`,\n          'lastGeneratedImage: available',\n          `lastPrompt: ${lastGenerated.prompt}`,\n          `stylePreset: ${lastGenerated.stylePreset || 'none'}`,\n          'instruction: If the user asks to continue or modify the previous image, prefer aigc_edit_image with referenceMode=last_generated.',\n          '[/AIGC_CONTEXT]',\n        ].join('\\n'),\n      )\n    }\n\n    if (shouldInjectStyleCandidates) {\n      blocks.push(formatStyleCandidatesBlock(styleMatches))\n    }\n\n    if (!blocks.length) return\n\n    const combinedBlock = blocks.join('\\n\\n')\n    const nextContent = prependContextBlockToMessage(text, combinedBlock)\n    setAugmentedMessageContent(message, message.content, combinedBlock, nextContent)\n\n    if (session) {\n      session.content = text\n    }\n\n    if (promptVariables) {\n      promptVariables.aiGeneratorContext = combinedBlock\n      promptVariables.aiGeneratorContextData = context\n      promptVariables.aiGeneratorStyleCandidates = styleMatches.map((item) => ({\n        commandName: item.style.commandName,\n        description: item.style.description || '',\n        aliases: item.style.aliases || [],\n        keywords: item.style.keywords || [],\n        category: item.style.category || '',\n        whenToUse: item.style.whenToUse || '',\n        score: item.score,\n        matchedTerms: item.matchedTerms,\n      }))\n      promptVariables.aiGeneratorPreferredStylePreset =\n        styleMatches[0]?.style.commandName || ''\n      promptVariables.input = nextContent\n      promptVariables.userInput = text\n      if (shouldInjectImageContext && lastGenerated) {\n        promptVariables.aiGeneratorReferenceRecommendation = 'last_generated'\n      }\n    }\n\n    logger.debug(\n      'aigc context injected for conversationId=%s with %s style candidates',\n      conversationId || 'n/a',\n      styleMatches.length,\n    )\n  })\n\n  const disposeClearHistory = (ctx as Context & {\n    on: (name: string, listener: (...args: unknown[]) => unknown) => Disposer\n  }).on('chatluna/clear-chat-history', (...args: unknown[]) => {\n    const conversationId = extractConversationId(\n      args[0],\n      asPromptVariables(args[1]),\n      asSession(args[2]),\n      aiGenerator,\n    )\n    if (!conversationId) return\n    aiGenerator.clearConversationImageContext(conversationId)\n    logger.debug('aigc image context cleared for conversationId=%s', conversationId)\n  })\n\n  return () => {\n    disposeBeforeChat?.()\n    disposeClearHistory?.()\n  }\n}\n\n// ---------------------------------------------------------------------------\n// 辅助函数（与 V1 一致，仅做 NodeNext 后缀适配）\n// ---------------------------------------------------------------------------\n\nfunction looksLikeImageFollowUp(text: string) {\n  const normalized = text.trim().toLowerCase()\n  if (!normalized) return false\n  return [\n    '上一张',\n    '上一幅',\n    '刚才那张',\n    '刚才那幅',\n    '继续改',\n    '继续做',\n    '继续生成',\n    '保持',\n    '同风格',\n    '参考上一张',\n    '基于上一张',\n    '沿用上一张',\n  ].some((pattern) => normalized.includes(pattern))\n}\n\nfunction extractConversationId(\n  conversationArg: unknown,\n  promptVariables: ChatLunaPromptVariablesLike | null,\n  session: ChatLunaSessionLike | null,\n  aiGenerator: AiImageGeneratorService,\n) {\n  const direct =\n    readConversationId(conversationArg) ||\n    readConversationId(promptVariables) ||\n    readConversationId(session)\n  const platform =\n    readPlatform(conversationArg) ||\n    readPlatform(promptVariables) ||\n    readPlatform(session)\n\n  if (direct) {\n    return aiGenerator.buildSessionConversationId({\n      conversationId: direct,\n      platform,\n    })\n  }\n\n  return aiGenerator.buildSessionConversationId(session as any)\n}\n\nfunction readConversationId(input: unknown) {\n  if (!input || typeof input !== 'object') return ''\n  const record = input as Record<string, unknown>\n  if (typeof record.conversationId === 'string' && record.conversationId.trim()) {\n    return record.conversationId.trim()\n  }\n  if (typeof record.conversation_id === 'string' && record.conversation_id.trim()) {\n    return record.conversation_id.trim()\n  }\n  if (typeof record.roomId === 'string' && record.roomId.trim()) {\n    return record.roomId.trim()\n  }\n  if (typeof record.room_id === 'string' && record.room_id.trim()) {\n    return record.room_id.trim()\n  }\n  return ''\n}\n\nfunction readPlatform(input: unknown) {\n  if (!input || typeof input !== 'object') return ''\n  const record = input as Record<string, unknown>\n  if (typeof record.platform === 'string' && record.platform.trim()) {\n    return record.platform.trim()\n  }\n  return ''\n}\n\nfunction asHumanMessage(input: unknown) {\n  return input && typeof input === 'object'\n    ? (input as ChatLunaHumanMessageLike)\n    : null\n}\n\nfunction asPromptVariables(input: unknown) {\n  return input && typeof input === 'object' && !Array.isArray(input)\n    ? (input as ChatLunaPromptVariablesLike)\n    : null\n}\n\nfunction asSession(input: unknown) {\n  return input && typeof input === 'object' ? (input as ChatLunaSessionLike) : null\n}\n\nfunction getMessageText(message: ChatLunaHumanMessageLike) {\n  return normalizeMessageContent(message.content)\n}\n\nfunction getSessionText(session?: ChatLunaSessionLike | null) {\n  return session && typeof session.content === 'string' ? session.content : ''\n}\n\nfunction setMessageText(message: ChatLunaHumanMessageLike, text: string) {\n  message.content = text\n}\n\nfunction setAugmentedMessageContent(\n  message: ChatLunaHumanMessageLike,\n  originalContent: unknown,\n  contextBlock: string,\n  fallbackText: string,\n) {\n  const prefix = `${contextBlock}\\n\\n`\n  if (typeof originalContent === 'string' || originalContent == null) {\n    setMessageText(message, fallbackText)\n    return\n  }\n\n  if (Array.isArray(originalContent)) {\n    message.content = [{ type: 'text', text: prefix }, ...originalContent]\n    return\n  }\n\n  setMessageText(message, fallbackText)\n}\n\nfunction normalizeMessageContent(content: unknown): string {\n  if (typeof content === 'string') return content\n  if (!Array.isArray(content)) return ''\n\n  const texts = content\n    .map((item) => {\n      if (typeof item === 'string') return item\n      if (!item || typeof item !== 'object') return ''\n\n      const part = item as { text?: unknown; type?: unknown; content?: unknown }\n      if (typeof part.text === 'string') return part.text\n      if (part.type === 'text' && typeof part.content === 'string') return part.content\n      return ''\n    })\n    .filter(Boolean)\n\n  return texts.join('\\n').trim()\n}\n\nfunction prependContextBlockToMessage(text: string, contextBlock: string) {\n  return `${contextBlock}\\n\\n${text}`\n}\n\nfunction hasAnyAiGeneratorContextBlock(text: string) {\n  return (\n    text.includes('[AIGC_CONTEXT]') ||\n    text.includes('[AIGC_STYLE_CANDIDATES]')\n  )\n}\n\nfunction formatStyleCandidatesBlock(\n  matches: ReturnType<AiImageGeneratorService['matchStylePresets']>,\n) {\n  const lines = ['[AIGC_STYLE_CANDIDATES]']\n  for (const [index, item] of matches.entries()) {\n    lines.push(`${index + 1}. ${item.style.commandName}`)\n    if (item.style.description) lines.push(`description: ${item.style.description}`)\n    if (item.style.aliases?.length)\n      lines.push(`aliases: ${item.style.aliases.join(', ')}`)\n    if (item.style.keywords?.length)\n      lines.push(`keywords: ${item.style.keywords.join(', ')}`)\n    if (item.style.whenToUse) lines.push(`whenToUse: ${item.style.whenToUse}`)\n    if (item.matchedTerms.length)\n      lines.push(`matchedTerms: ${item.matchedTerms.join(', ')}`)\n  }\n  lines.push(\n    'instruction: If the user seems to reference one of these configured styles, prefer aigc_apply_style_preset and pass stylePreset exactly, or pass styleQuery when uncertain.',\n  )\n  lines.push('[/AIGC_STYLE_CANDIDATES]')\n  return lines.join('\\n')\n}\n","/**\n * ChatLuna 运行时动态加载器（V2 移植版）。\n *\n * 通过 createRequire + 动态 import 双通道加载 koishi-plugin-chatluna\n * 和 @langchain/core/tools，避免将 ChatLuna 设为硬依赖。\n */\n\nimport { createRequire } from 'node:module'\nimport type { Context } from 'koishi'\n\nexport interface ChatLunaServiceLike {\n  installPlugin(plugin: unknown): Promise<void> | void\n  uninstallPlugin(plugin: unknown): void\n  getPlugin?(name: string): unknown\n}\n\nexport interface ChatLunaPluginLike {\n  registerTool(name: string, tool: unknown): void\n  dispose?(): Promise<void> | void\n}\n\nexport type ChatLunaPluginConstructor = new (\n  ctx: Context,\n  config: Record<string, never>,\n  platformName: string,\n  createConfigPool: boolean,\n) => ChatLunaPluginLike\n\nexport type StructuredToolConstructor = new (...args: any[]) => {\n  name?: string\n  description?: string\n  schema?: unknown\n  _call(\n    input: Record<string, unknown>,\n    runManager?: unknown,\n    config?: { configurable?: { session?: unknown } },\n  ): Promise<string>\n}\n\nconst runtimeRequire = createRequire(`${process.cwd()}/package.json`)\n\nexport async function loadChatLunaRuntime(): Promise<{\n  ChatLunaPlugin: ChatLunaPluginConstructor\n  StructuredTool: StructuredToolConstructor\n}> {\n  const [chatlunaModule, langchainToolsModule] = await Promise.all([\n    loadRuntimeModule('koishi-plugin-chatluna/services/chat'),\n    loadRuntimeModule('@langchain/core/tools'),\n  ])\n\n  const ChatLunaPlugin = chatlunaModule.ChatLunaPlugin as ChatLunaPluginConstructor | undefined\n  const StructuredTool = langchainToolsModule.StructuredTool as StructuredToolConstructor | undefined\n\n  if (!ChatLunaPlugin) {\n    throw new Error('ChatLunaPlugin export not found from koishi-plugin-chatluna/services/chat.')\n  }\n  if (!StructuredTool) {\n    throw new Error('StructuredTool export not found from @langchain/core/tools.')\n  }\n\n  return { ChatLunaPlugin, StructuredTool }\n}\n\nasync function loadRuntimeModule(specifier: string): Promise<Record<string, any>> {\n  try {\n    return runtimeRequire(specifier) as Record<string, any>\n  } catch (requireError) {\n    const dynamicImport = new Function('s', 'return import(s)') as (\n      target: string,\n    ) => Promise<Record<string, any>>\n    return dynamicImport(specifier).catch((importError) => {\n      const requireMessage =\n        requireError instanceof Error ? requireError.message : String(requireError)\n      const importMessage =\n        importError instanceof Error ? importError.message : String(importError)\n      throw new Error(\n        `failed to load runtime module \"${specifier}\"; require: ${requireMessage}; import: ${importMessage}`,\n      )\n    })\n  }\n}\n","/**\n * ChatLuna 工具运行时（V2 积分制适配版）。\n *\n * 关键适配点（vs V1）：\n * - 配额预检从次数制改为积分制：checkAndReserveQuota(userId, userName, cost: GenerationCost)\n * - 用量记录改为积分制：recordUsage(userId, userName, cmd, cost, platform, requestId)\n * - 模型路由从 provider/apiFormat 改为 supplier/protocol\n * - 配额消息术语从「次数」改为「积分」\n */\n\nimport { h } from 'koishi'\n\nimport { calculateGenerationCost, scaleGenerationCost } from '../../shared/billing.js'\nimport { AI_GENERATOR_TOOL_DEFINITIONS } from '../../shared/chatluna-tool-definitions.js'\nimport type { Config } from '../../shared/config.js'\nimport type {\n  ImageRequestContext,\n  ModelMappingConfig,\n  ResolvedStyleConfig,\n  StyleMatchCandidate,\n} from '../../shared/types.js'\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport type { StructuredToolConstructor } from './runtime.js'\nimport type { ChatLunaConfigAccessor, ChatLunaSessionLike } from './types.js'\n\n// ---------------------------------------------------------------------------\n// 基础工具实例工厂\n// ---------------------------------------------------------------------------\n\nexport function createChatLunaToolInstance(\n  StructuredTool: StructuredToolConstructor,\n  definition: (typeof AI_GENERATOR_TOOL_DEFINITIONS)[number],\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  return new (class extends StructuredTool {\n    name = definition.name\n    description = [\n      definition.description,\n      `Usage: ${definition.usage}`,\n      `Risk: ${definition.riskLevel}`,\n      `Input JSON schema: ${JSON.stringify(definition.inputSchema)}`,\n    ].join('\\n')\n    schema = definition.inputSchema\n\n    constructor() {\n      super({ verboseParsingErrors: true })\n    }\n\n    async _call(\n      input: Record<string, unknown>,\n      _runManager?: unknown,\n      runtimeConfig?: { configurable?: { session?: ChatLunaSessionLike } },\n    ) {\n      const session = runtimeConfig?.configurable?.session\n      if (!session?.userId) {\n        return formatToolError('会话无效，无法识别用户。')\n      }\n\n      try {\n        switch (definition.name) {\n          case 'aigc_generate_image':\n            return await runGenerateImageTool(input, session, aiGenerator, getConfig)\n          case 'aigc_edit_image':\n            return await runEditImageTool(input, session, aiGenerator, getConfig)\n          case 'aigc_apply_style_preset':\n            return await runStylePresetTool(input, session, aiGenerator, getConfig)\n          case 'aigc_get_quota':\n            return await runGetQuotaTool(session, aiGenerator)\n          case 'aigc_list_styles':\n            return formatToolJson({\n              items: aiGenerator.listStylePresets().map((style) => ({\n                commandName: style.commandName,\n                description: style.description || '',\n                groupName: style.groupName || '',\n                aliases: style.aliases || [],\n                keywords: style.keywords || [],\n                examples: style.examples || [],\n                category: style.category || '',\n                whenToUse: style.whenToUse || '',\n              })),\n            })\n          default:\n            return formatToolError(`unsupported tool: ${definition.name}`)\n        }\n      } catch (error) {\n        return formatToolError(error instanceof Error ? error.message : String(error))\n      }\n    }\n  })()\n}\n\n// ---------------------------------------------------------------------------\n// 工具执行函数\n// ---------------------------------------------------------------------------\n\nasync function runGenerateImageTool(\n  input: Record<string, unknown>,\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const prompt = expectString(input.prompt, 'prompt')\n    const config = getConfig()\n    const { requestContext, generationCost } = buildRequestContextAndCost(input, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId!,\n      session.username || session.userId!,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return formatToolError(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      [],\n      generationCost.numImages,\n      requestContext,\n    )\n    await sendGeneratedImages(session, images)\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: 'aigc_generate_image',\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId!,\n      session.username || session.userId!,\n      'aigc_generate_image',\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return formatToolJson({\n      ok: true,\n      imagesCount: images.length,\n      images: images.map(summarizeImageUrl),\n      creditSummary: usage?.summary\n        ? {\n            totalAvailable: aiGenerator.formatCredits(usage.summary.totalAvailable),\n            dailyFreeRemaining: aiGenerator.formatCredits(usage.summary.dailyFreeRemaining),\n            purchasedCredits: aiGenerator.formatCredits(usage.summary.purchasedCredits),\n          }\n        : undefined,\n    })\n  })\n}\n\nasync function runEditImageTool(\n  input: Record<string, unknown>,\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const prompt = expectString(input.prompt, 'prompt')\n    const referenceMode = expectString(input.referenceMode, 'referenceMode')\n    const conversationId = resolveSessionConversationId(session, aiGenerator)\n    const imageUrls = resolveReferenceImages(referenceMode, input, session, aiGenerator)\n    if (!imageUrls.length) {\n      return formatToolError('未能解析到参考图片。')\n    }\n\n    const config = getConfig()\n    const { requestContext, generationCost } = buildRequestContextAndCost(input, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId!,\n      session.username || session.userId!,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return formatToolError(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      imageUrls,\n      generationCost.numImages,\n      requestContext,\n    )\n    await sendGeneratedImages(session, images)\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      conversationId,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: 'aigc_edit_image',\n      parentRecordId:\n        referenceMode === 'last_generated' && conversationId\n          ? aiGenerator.getConversationImageContext(conversationId)?.lastGenerated?.id\n          : undefined,\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId!,\n      session.username || session.userId!,\n      'aigc_edit_image',\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return formatToolJson({\n      ok: true,\n      imagesCount: images.length,\n      images: images.map(summarizeImageUrl),\n      referenceMode,\n      creditSummary: usage?.summary\n        ? {\n            totalAvailable: aiGenerator.formatCredits(usage.summary.totalAvailable),\n            dailyFreeRemaining: aiGenerator.formatCredits(usage.summary.dailyFreeRemaining),\n          }\n        : undefined,\n    })\n  })\n}\n\nasync function runStylePresetTool(\n  input: Record<string, unknown>,\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const resolvedStyle = resolveRequestedStylePreset(input, aiGenerator)\n    if ('error' in resolvedStyle) {\n      return formatToolError(resolvedStyle.error)\n    }\n    const { preset, matches } = resolvedStyle\n\n    const promptAdditions =\n      typeof input.promptAdditions === 'string' ? input.promptAdditions.trim() : ''\n    const prompt = [preset.prompt, promptAdditions].filter(Boolean).join(' - ')\n    const referenceMode =\n      typeof input.referenceMode === 'string' ? input.referenceMode : 'none'\n    const imageUrls =\n      referenceMode === 'none'\n        ? []\n        : resolveReferenceImages(referenceMode, input, session, aiGenerator)\n\n    if (referenceMode !== 'none' && !imageUrls.length) {\n      return formatToolError('未能解析到参考图片。')\n    }\n\n    const config = getConfig()\n    const { requestContext, generationCost } = buildRequestContextAndCost(input, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId!,\n      session.username || session.userId!,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return formatToolError(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      imageUrls,\n      generationCost.numImages,\n      requestContext,\n    )\n    await sendGeneratedImages(session, images)\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: preset.commandName,\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId!,\n      session.username || session.userId!,\n      preset.commandName,\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return formatToolJson({\n      ok: true,\n      stylePreset: preset.commandName,\n      imagesCount: images.length,\n      images: images.map(summarizeImageUrl),\n      creditSummary: usage?.summary\n        ? {\n            totalAvailable: aiGenerator.formatCredits(usage.summary.totalAvailable),\n            dailyFreeRemaining: aiGenerator.formatCredits(usage.summary.dailyFreeRemaining),\n          }\n        : undefined,\n      styleMatches: matches.map((item) => ({\n        commandName: item.style.commandName,\n        score: item.score,\n        matchedTerms: item.matchedTerms,\n      })),\n    })\n  })\n}\n\nasync function runGetQuotaTool(\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n) {\n  const userId = session.userId\n  if (!userId) return formatToolError('会话无效，无法识别用户。')\n\n  const summary = await aiGenerator.getQuotaSummary(\n    userId,\n    session.username || session.author?.name || userId,\n  )\n  return formatToolJson({\n    userName: summary.userName || userId,\n    dailyFreeRemaining: aiGenerator.formatCredits(summary.dailyFreeRemaining),\n    purchasedCredits: aiGenerator.formatCredits(summary.purchasedCredits),\n    totalAvailable: aiGenerator.formatCredits(summary.totalAvailable),\n    totalImagesGenerated: summary.totalImagesGenerated,\n    totalConsumedCredits: aiGenerator.formatCredits(summary.totalConsumedCredits),\n    totalGrantedCredits: aiGenerator.formatCredits(summary.totalGrantedCredits),\n  })\n}\n\n// ---------------------------------------------------------------------------\n// 风格预设工具实例工厂\n// ---------------------------------------------------------------------------\n\nexport function createStylePresetToolInstance(\n  StructuredTool: StructuredToolConstructor,\n  style: ResolvedStyleConfig,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  const toolName = `aigc_style_${sanitizeToolName(style.commandName)}`\n  const description =\n    style.description || `Apply ${style.commandName} style to image generation`\n  const metadataLines = [\n    style.category ? `Category: ${style.category}` : '',\n    style.whenToUse ? `When to use: ${style.whenToUse}` : '',\n    style.aliases?.length ? `Aliases: ${style.aliases.join(', ')}` : '',\n    style.keywords?.length ? `Keywords: ${style.keywords.join(', ')}` : '',\n    style.examples?.length ? `Examples: ${style.examples.join(' | ')}` : '',\n  ].filter(Boolean)\n\n  return new (class extends StructuredTool {\n    name = toolName\n    description = [\n      description,\n      ...metadataLines,\n      `Usage: Use this when the user wants to apply the \"${style.commandName}\" style to generate or edit images.`,\n      `Risk: low`,\n      `Input JSON schema: ${JSON.stringify(stylePresetInputSchema)}`,\n    ].join('\\n')\n    schema = stylePresetInputSchema\n\n    constructor() {\n      super({ verboseParsingErrors: true })\n    }\n\n    async _call(\n      input: Record<string, unknown>,\n      _runManager?: unknown,\n      runtimeConfig?: { configurable?: { session?: ChatLunaSessionLike } },\n    ) {\n      const session = runtimeConfig?.configurable?.session\n      if (!session?.userId) {\n        return formatToolError('会话无效，无法识别用户。')\n      }\n\n      try {\n        return await runDynamicStyleTool(input, session, style, aiGenerator, getConfig)\n      } catch (error) {\n        return formatToolError(error instanceof Error ? error.message : String(error))\n      }\n    }\n  })()\n}\n\nconst stylePresetInputSchema = {\n  type: 'object',\n  properties: {\n    promptAdditions: {\n      type: 'string',\n      description: 'Optional extra prompt details.',\n    },\n    referenceMode: {\n      type: 'string',\n      enum: ['none', 'current_message', 'quoted_message', 'explicit', 'last_generated'],\n      description: 'Where to load reference images from.',\n    },\n    imageUrls: {\n      type: 'array',\n      items: { type: 'string' },\n      description: 'Explicit image URLs when referenceMode is explicit.',\n    },\n    numImages: { type: 'number', minimum: 1, maximum: 4 },\n    aspectRatio: { type: 'string', enum: ['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'] },\n    resolution: { type: 'string', enum: ['1k', '2k', '4k'] },\n    modelSuffix: {\n      type: 'string',\n      description: 'Optional configured model suffix.',\n    },\n  },\n  additionalProperties: false,\n} as const\n\nasync function runDynamicStyleTool(\n  input: Record<string, unknown>,\n  session: ChatLunaSessionLike,\n  style: ResolvedStyleConfig,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n) {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const promptAdditions =\n      typeof input.promptAdditions === 'string' ? input.promptAdditions.trim() : ''\n    const prompt = [style.prompt, promptAdditions].filter(Boolean).join(' - ')\n    const referenceMode =\n      typeof input.referenceMode === 'string' ? input.referenceMode : 'none'\n    const imageUrls =\n      referenceMode === 'none'\n        ? []\n        : resolveReferenceImages(referenceMode, input, session, aiGenerator)\n\n    if (referenceMode !== 'none' && !imageUrls.length) {\n      return formatToolError('未能解析到参考图片。')\n    }\n\n    const config = getConfig()\n    const { requestContext, generationCost } = buildRequestContextAndCost(input, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId!,\n      session.username || session.userId!,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return formatToolError(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      imageUrls,\n      generationCost.numImages,\n      requestContext,\n    )\n    await sendGeneratedImages(session, images)\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: style.commandName,\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId!,\n      session.username || session.userId!,\n      style.commandName,\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return formatToolJson({\n      ok: true,\n      stylePreset: style.commandName,\n      imagesCount: images.length,\n      images: images.map(summarizeImageUrl),\n      creditSummary: usage?.summary\n        ? {\n            totalAvailable: aiGenerator.formatCredits(usage.summary.totalAvailable),\n          }\n        : undefined,\n    })\n  })\n}\n\n// ---------------------------------------------------------------------------\n// 请求上下文 & 费用构建（V2 适配）\n// ---------------------------------------------------------------------------\n\nconst VALID_ASPECT_RATIOS = new Set(['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'])\nconst VALID_RESOLUTIONS = new Set(['1k', '2k', '4k'])\nconst CUSTOM_RESOLUTION_RE = /^\\d{3,5}x\\d{3,5}$/\n\nfunction buildRequestContextAndCost(\n  input: Record<string, unknown>,\n  config: Config,\n): { requestContext: ImageRequestContext; generationCost: ReturnType<typeof calculateGenerationCost> } {\n  let numImages = config.defaultNumImages || 1\n  if (typeof input.numImages === 'number' && Number.isFinite(input.numImages)) {\n    numImages = Math.max(1, Math.min(4, Math.round(input.numImages)))\n  }\n\n  const requestContext: ImageRequestContext = { numImages }\n\n  // aspectRatio\n  if (typeof input.aspectRatio === 'string' && VALID_ASPECT_RATIOS.has(input.aspectRatio)) {\n    requestContext.aspectRatio = input.aspectRatio as ImageRequestContext['aspectRatio']\n  }\n\n  // resolution\n  if (typeof input.resolution === 'string') {\n    const res = input.resolution.trim()\n    if (VALID_RESOLUTIONS.has(res) || CUSTOM_RESOLUTION_RE.test(res)) {\n      requestContext.resolution = res as ImageRequestContext['resolution']\n    }\n  }\n\n  // modelSuffix → 查找 modelMappings，填充 supplier / protocol / modelId\n  const modelSuffix = typeof input.modelSuffix === 'string' ? input.modelSuffix.trim() : ''\n  let modelMapping: ModelMappingConfig | undefined\n  if (modelSuffix) {\n    modelMapping = (config.modelMappings || []).find(\n      (item) => item.suffix === modelSuffix,\n    )\n  }\n\n  if (modelMapping) {\n    requestContext.supplier = modelMapping.supplier\n    requestContext.provider = modelMapping.protocol\n    if (modelMapping.modelId) {\n      requestContext.modelId = modelMapping.modelId\n    }\n  }\n\n  const generationCost = calculateGenerationCost({\n    numImages,\n    modelMapping,\n    config,\n  })\n\n  return { requestContext, generationCost }\n}\n\n// ---------------------------------------------------------------------------\n// 风格预设解析\n// ---------------------------------------------------------------------------\n\nfunction resolveRequestedStylePreset(\n  input: Record<string, unknown>,\n  aiGenerator: AiImageGeneratorService,\n):\n  | { preset: ResolvedStyleConfig; matches: StyleMatchCandidate[] }\n  | { error: string } {\n  const explicitStylePreset =\n    typeof input.stylePreset === 'string' ? input.stylePreset.trim() : ''\n  if (explicitStylePreset) {\n    const preset = aiGenerator.getStylePreset(explicitStylePreset)\n    if (!preset) {\n      return { error: `未找到风格预设：${explicitStylePreset}` }\n    }\n    return {\n      preset,\n      matches: [{ style: preset, score: 999, matchedTerms: [explicitStylePreset] }],\n    }\n  }\n\n  const styleQuery = typeof input.styleQuery === 'string' ? input.styleQuery.trim() : ''\n  if (!styleQuery) {\n    return { error: 'stylePreset 或 styleQuery 至少需要提供一个。' }\n  }\n\n  const matches = aiGenerator.matchStylePresets(styleQuery, 3)\n  if (!matches.length) {\n    return { error: `未找到与「${styleQuery}」匹配的风格预设。` }\n  }\n  const topMatch = matches[0]\n  if (!topMatch) {\n    return { error: `未找到与「${styleQuery}」匹配的风格预设。` }\n  }\n\n  return { preset: topMatch.style, matches }\n}\n\n// ---------------------------------------------------------------------------\n// 图片引用解析\n// ---------------------------------------------------------------------------\n\nfunction resolveReferenceImages(\n  referenceMode: string,\n  input: Record<string, unknown>,\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n): string[] {\n  if (referenceMode === 'explicit') {\n    return normalizeImageUrls(\n      Array.isArray(input.imageUrls)\n        ? input.imageUrls.filter(\n            (item): item is string => typeof item === 'string' && item.trim().length > 0,\n          )\n        : [],\n    )\n  }\n\n  if (referenceMode === 'last_generated') {\n    const conversationId = resolveSessionConversationId(session, aiGenerator)\n    if (!conversationId) return []\n    const lastGenerated = aiGenerator.getConversationImageContext(conversationId)\n      ?.lastGenerated\n    return lastGenerated ? [lastGenerated.imageUrl] : []\n  }\n\n  if (referenceMode === 'current_message') {\n    return parseImagesFromMessageContent(session.content)\n  }\n\n  if (referenceMode === 'quoted_message') {\n    return normalizeImageUrls([\n      ...parseImagesFromMessageContent(session.quote?.content),\n      ...(Array.isArray(session.quote?.elements)\n        ? h\n            .select(session.quote.elements as any[], 'img')\n            .map((img: any) => img.attrs?.src)\n        : []),\n    ])\n  }\n\n  return []\n}\n\nfunction parseImagesFromMessageContent(content: unknown): string[] {\n  if (typeof content === 'string' && content.trim()) {\n    return normalizeImageUrls(\n      h.select(h.parse(content), 'img').map((img: any) => img.attrs?.src),\n    )\n  }\n\n  if (Array.isArray(content)) {\n    return normalizeImageUrls(\n      h.select(content as any[], 'img').map((img: any) => img.attrs?.src),\n    )\n  }\n\n  return []\n}\n\n// ---------------------------------------------------------------------------\n// 工具函数\n// ---------------------------------------------------------------------------\n\nasync function sendGeneratedImages(session: ChatLunaSessionLike, images: string[]) {\n  if (typeof session.send !== 'function') return\n  for (const imageUrl of images) {\n    await Promise.resolve(session.send(h.image(imageUrl)))\n  }\n}\n\nfunction expectString(value: unknown, key: string): string {\n  if (typeof value !== 'string' || !value.trim()) {\n    throw new Error(`${key} is required.`)\n  }\n  return value.trim()\n}\n\nfunction formatToolError(message: string): string {\n  return formatToolJson({ ok: false, error: message })\n}\n\nfunction formatToolJson(value: unknown): string {\n  return JSON.stringify(value, null, 2)\n}\n\nfunction summarizeImageUrl(url: string): string {\n  if (url.startsWith('data:')) {\n    return '[base64_image]'\n  }\n  return url\n}\n\nfunction normalizeImageUrls(items: unknown[]): string[] {\n  return items\n    .filter((item): item is string => typeof item === 'string' && item.trim().length > 0)\n    .map((item) => item.trim())\n}\n\nfunction resolveSessionConversationId(\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n): string | undefined {\n  return aiGenerator.buildSessionConversationId(session as any)\n}\n\nasync function withImageTaskLock(\n  session: ChatLunaSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  work: () => Promise<string>,\n): Promise<string> {\n  const userId = session.userId\n  if (!userId) {\n    return formatToolError('会话无效，无法识别用户。')\n  }\n\n  const requestId = aiGenerator.userManager.startTask(userId)\n  if (!requestId) {\n    return formatToolError('您有一个图像处理任务正在进行中，请等待完成。')\n  }\n\n  try {\n    return await work()\n  } finally {\n    aiGenerator.userManager.endTask(userId, requestId)\n  }\n}\n\nfunction sanitizeToolName(name: string): string {\n  return name\n    .toLowerCase()\n    .replace(/[^a-z0-9_\\u4e00-\\u9fff]/g, '_')\n    .replace(/_{2,}/g, '_')\n    .replace(/^_|_$/g, '')\n}\n","import type { Config } from './config.js'\nimport type { ImageGenerationModifiers, ModelMappingConfig } from './types.js'\n\nexport interface GenerationCost {\n  totalCredits: number\n  creditCostPerImage: number\n  numImages: number\n  modelId?: string\n  modelSuffix?: string\n  costSource: 'default' | 'model-fixed'\n}\n\nexport interface CalculateGenerationCostParams {\n  numImages: number\n  modelMapping?: ModelMappingConfig\n  config: Config\n}\n\nexport function calculateGenerationCost(params: CalculateGenerationCostParams): GenerationCost {\n  const numImages = normalizePositiveInteger(params.numImages, 1)\n  const defaultCost = normalizeNonNegativeNumber(params.config.defaultCreditCostPerImage, 1)\n  const modelCost = normalizeOptionalNonNegativeNumber(params.modelMapping?.creditCostPerImage)\n  const creditCostPerImage = modelCost ?? defaultCost\n\n  return {\n    totalCredits: roundCredits(creditCostPerImage * numImages),\n    creditCostPerImage,\n    numImages,\n    ...(params.modelMapping?.modelId ? { modelId: params.modelMapping.modelId } : {}),\n    ...(params.modelMapping?.suffix ? { modelSuffix: params.modelMapping.suffix } : {}),\n    costSource: modelCost === undefined ? 'default' : 'model-fixed',\n  }\n}\n\nexport function calculateCostFromModifiers(\n  numImages: number,\n  modifiers: ImageGenerationModifiers | undefined,\n  config: Config,\n): GenerationCost {\n  return calculateGenerationCost({\n    numImages,\n    modelMapping: modifiers?.modelMapping,\n    config,\n  })\n}\n\nexport function scaleGenerationCost(cost: GenerationCost, actualImages: number): GenerationCost {\n  const numImages = normalizePositiveInteger(actualImages, 0)\n  return {\n    ...cost,\n    numImages,\n    totalCredits: roundCredits(cost.creditCostPerImage * numImages),\n  }\n}\n\nexport function formatCredits(value: number, unitName = '积分'): string {\n  const rounded = roundCredits(value)\n  return `${Number.isInteger(rounded) ? rounded.toFixed(0) : rounded.toFixed(2)} ${unitName}`\n}\n\nexport function roundCredits(value: number): number {\n  if (!Number.isFinite(value)) return 0\n  return Math.round(Math.max(0, value) * 100) / 100\n}\n\nfunction normalizePositiveInteger(value: number | undefined, fallback: number): number {\n  if (!Number.isFinite(value)) return fallback\n  return Math.max(0, Math.floor(value || fallback))\n}\n\nfunction normalizeNonNegativeNumber(value: number | undefined, fallback: number): number {\n  if (!Number.isFinite(value)) return fallback\n  return roundCredits(value ?? fallback)\n}\n\nfunction normalizeOptionalNonNegativeNumber(value: number | undefined): number | undefined {\n  if (!Number.isFinite(value)) return undefined\n  return roundCredits(value ?? 0)\n}\n","/**\n * ChatLuna 工具注册（V2 积分制适配版）。\n *\n * 将 AI_GENERATOR_TOOL_DEFINITIONS 中定义的基础工具 + 用户配置的风格预设\n * 逐个注册为 ChatLuna 可调用的 LangChain StructuredTool。\n */\n\nimport { AI_GENERATOR_TOOL_DEFINITIONS } from '../../shared/chatluna-tool-definitions.js'\nimport type { ResolvedStyleConfig } from '../../shared/types.js'\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport { createChatLunaToolInstance, createStylePresetToolInstance } from './tool-runtime.js'\nimport type { ChatLunaPluginLike, StructuredToolConstructor } from './runtime.js'\nimport type { ChatLunaConfigAccessor, ChatLunaSessionLike } from './types.js'\n\nexport function registerChatLunaTools(\n  plugin: ChatLunaPluginLike,\n  StructuredTool: StructuredToolConstructor,\n  aiGenerator: AiImageGeneratorService,\n  getConfig: ChatLunaConfigAccessor,\n  styles: ResolvedStyleConfig[] = [],\n) {\n  // 注册基础工具\n  for (const definition of AI_GENERATOR_TOOL_DEFINITIONS) {\n    plugin.registerTool(definition.name, {\n      selector() {\n        return true\n      },\n      authorization(session: ChatLunaSessionLike) {\n        return Boolean(session?.userId)\n      },\n      createTool() {\n        return createChatLunaToolInstance(\n          StructuredTool,\n          definition,\n          aiGenerator,\n          getConfig,\n        )\n      },\n    })\n  }\n\n  // 为用户配置的每个 style 注册独立工具\n  for (const style of styles) {\n    const toolName = `aigc_style_${sanitizeToolName(style.commandName)}`\n    plugin.registerTool(toolName, {\n      selector() {\n        return true\n      },\n      authorization(session: ChatLunaSessionLike) {\n        return Boolean(session?.userId)\n      },\n      createTool() {\n        return createStylePresetToolInstance(\n          StructuredTool,\n          style,\n          aiGenerator,\n          getConfig,\n        )\n      },\n    })\n  }\n}\n\nfunction sanitizeToolName(name: string): string {\n  return name\n    .toLowerCase()\n    .replace(/[^a-z0-9_\\u4e00-\\u9fff]/g, '_')\n    .replace(/_{2,}/g, '_')\n    .replace(/^_|_$/g, '')\n}\n","/**\n * ChatLuna 桥接管理器（V2 积分制适配版）。\n *\n * 负责：\n * - 动态加载 ChatLuna 运行时（koishi-plugin-chatluna + @langchain/core/tools）\n * - 注册 / 注销 ChatLuna 插件（工具 + 上下文注入）\n * - 同步 enabled/disabled 状态并处理热重载\n *\n * 关键 V2 适配：\n * - AiGeneratorService → AiImageGeneratorService\n * - listStylePresets() 返回 ResolvedStyleConfig[]\n * - CHATLUNA_BRIDGE_PLATFORM_NAME 在 constants.ts 中定义\n */\n\nimport type { Context } from 'koishi'\n\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport { AI_GENERATOR_TOOL_DEFINITIONS } from '../../shared/chatluna-tool-definitions.js'\nimport type { Config } from '../../shared/config.js'\nimport { CHATLUNA_BRIDGE_PLATFORM_NAME } from '../../shared/constants.js'\nimport { installChatLunaContextInjection } from './context-injection.js'\nimport { loadChatLunaRuntime } from './runtime.js'\nimport type { ChatLunaPluginLike, ChatLunaServiceLike } from './runtime.js'\nimport { registerChatLunaTools } from './tools.js'\n\nexport class ChatLunaBridgeManager {\n  private chatLunaPlugin?: ChatLunaPluginLike\n  private contextInjectionDispose?: () => void\n  private warnedUnavailable = false\n  private syncQueue: Promise<void> = Promise.resolve()\n  private readonly getConfig = () => this.config\n\n  constructor(\n    private readonly ctx: Context,\n    private readonly aiGenerator: AiImageGeneratorService,\n    private config: Config,\n    private readonly logger: ReturnType<Context['logger']>,\n  ) {}\n\n  updateConfig(config: Config) {\n    this.config = config\n  }\n\n  sync(enabled: boolean) {\n    this.syncQueue = this.syncQueue\n      .catch(() => {})\n      .then(async () => {\n        if (enabled) {\n          // 如果插件已经注册，先注销再重新注册，确保新增的 style 工具被加载\n          if (this.chatLunaPlugin) {\n            await this.disable()\n          }\n          await this.enable()\n        } else {\n          await this.disable()\n        }\n      })\n    return this.syncQueue\n  }\n\n  async dispose() {\n    await this.disable()\n  }\n\n  private async enable() {\n    const chatlunaService = this.getChatLunaService()\n    if (!chatlunaService) {\n      if (!this.warnedUnavailable) {\n        this.logger.warn(\n          'ChatLuna bridge enabled, but ChatLuna service is not available. Install and enable ChatLuna first.',\n        )\n        this.warnedUnavailable = true\n      }\n      return\n    }\n\n    if (this.config.chatlunaContextInjectionEnabled && !this.contextInjectionDispose) {\n      this.contextInjectionDispose = installChatLunaContextInjection(\n        this.ctx,\n        this.aiGenerator,\n        this.getConfig,\n        this.logger,\n      )\n    }\n    if (!this.config.chatlunaContextInjectionEnabled && this.contextInjectionDispose) {\n      this.contextInjectionDispose()\n      this.contextInjectionDispose = undefined\n    }\n\n    if (this.chatLunaPlugin) {\n      this.warnedUnavailable = false\n      return\n    }\n\n    const runtime = await loadChatLunaRuntime().catch((error) => {\n      if (!this.warnedUnavailable) {\n        const message = error instanceof Error ? error.message : String(error)\n        this.logger.warn(\n          'ChatLuna bridge enabled but runtime modules are unavailable: %s',\n          message,\n        )\n        this.warnedUnavailable = true\n      }\n      return null\n    })\n    if (!runtime) return\n\n    const existing = chatlunaService.getPlugin?.(CHATLUNA_BRIDGE_PLATFORM_NAME)\n    if (existing) {\n      this.logger.warn(\n        'ChatLuna plugin name \"%s\" is already in use, skip built-in bridge registration.',\n        CHATLUNA_BRIDGE_PLATFORM_NAME,\n      )\n      this.warnedUnavailable = true\n      return\n    }\n\n    const plugin = new runtime.ChatLunaPlugin(\n      this.ctx,\n      {},\n      CHATLUNA_BRIDGE_PLATFORM_NAME,\n      false,\n    )\n    const allStyles = this.aiGenerator.listStylePresets()\n    registerChatLunaTools(\n      plugin,\n      runtime.StructuredTool,\n      this.aiGenerator,\n      this.getConfig,\n      allStyles,\n    )\n\n    if (!chatlunaService.getPlugin?.(CHATLUNA_BRIDGE_PLATFORM_NAME)) {\n      await Promise.resolve(chatlunaService.installPlugin(plugin))\n    }\n\n    this.chatLunaPlugin = plugin\n    this.warnedUnavailable = false\n    this.logger.info(\n      'ChatLuna bridge enabled with %s base tools and %s style preset tools.',\n      AI_GENERATOR_TOOL_DEFINITIONS.length,\n      allStyles.length,\n    )\n  }\n\n  private async disable() {\n    this.contextInjectionDispose?.()\n    this.contextInjectionDispose = undefined\n\n    if (!this.chatLunaPlugin) return\n\n    const plugin = this.chatLunaPlugin\n    this.chatLunaPlugin = undefined\n\n    const chatlunaService = this.getChatLunaService()\n    try {\n      chatlunaService?.uninstallPlugin(plugin)\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error)\n      this.logger.warn('failed to uninstall ChatLuna bridge plugin: %s', message)\n    }\n\n    try {\n      await Promise.resolve(plugin.dispose?.())\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error)\n      this.logger.warn('failed to dispose ChatLuna bridge plugin: %s', message)\n    }\n\n    this.logger.info('ChatLuna bridge disabled.')\n  }\n\n  private getChatLunaService() {\n    const service = (this.ctx as Context & {\n      chatluna?: ChatLunaServiceLike\n    }).chatluna\n\n    if (!service) return null\n    if (\n      typeof service.installPlugin !== 'function' ||\n      typeof service.uninstallPlugin !== 'function'\n    ) {\n      return null\n    }\n\n    return service\n  }\n}\n","/**\n * YesImBot 工具定义（ToolService 格式）。\n *\n * 每个工具使用 Koishi Schema 定义 parameters（与 sticker-manager 一致），\n * 而非 AI SDK 的 Zod inputSchemaBuilder。\n */\n\nimport { Schema } from 'koishi'\n\nexport interface YesImBotToolDefinition {\n  name: string\n  description: string\n  parameters: Schema // Koishi Schema 对象\n  promptSnippet?: string\n  promptGuidelines?: string[]\n}\n\nexport const YESIMBOT_TOOL_DEFINITIONS: YesImBotToolDefinition[] = [\n  {\n    name: 'aigc_generate_image',\n    description:\n      '根据文字描述生成一张或多张 AI 图像。支持指定风格预设、图像数量、尺寸等参数。',\n    parameters: Schema.object({\n      prompt: Schema.string().required().description('图像描述文字，详细描述想要生成的图像内容'),\n      stylePreset: Schema.string().description('风格预设名称，如 \"anime\"、\"realistic\" 等'),\n      numImages: Schema.natural().min(1).max(4).default(1).description('生成图像数量'),\n      aspectRatio: Schema.string().description('宽高比，如 \"1:1\"、\"16:9\"、\"9:16\" 等'),\n    }),\n    promptSnippet: '使用 aigc_generate_image 工具生成图像',\n    promptGuidelines: [\n      '当用户要求生成、画、创建图像时使用此工具',\n      'prompt 参数应该详细描述图像内容，包括主体、风格、色彩、构图等',\n      '如果用户提到特定风格（如动漫、写实、水彩等），使用 stylePreset 参数',\n    ],\n  },\n  {\n    name: 'aigc_edit_image',\n    description: '基于参考图像和文字描述编辑或变换图像。',\n    parameters: Schema.object({\n      referenceImageUrl: Schema.string().required().description('参考图像的 URL'),\n      prompt: Schema.string().required().description('编辑指令或新的图像描述'),\n      stylePreset: Schema.string().description('风格预设名称'),\n      strength: Schema.number().min(0).max(1).default(0.5).description('编辑强度，0-1 之间'),\n    }),\n    promptSnippet: '使用 aigc_edit_image 工具编辑图像',\n    promptGuidelines: [\n      '当用户要求修改、编辑、变换已有图像时使用此工具',\n      '需要提供参考图像 URL（从上下文或用户消息中获取）',\n      'strength 参数控制编辑强度：接近 0 保留更多原图，接近 1 变化更大',\n    ],\n  },\n  {\n    name: 'aigc_apply_style_preset',\n    description: '将指定的风格预设应用到参考图像上，支持通过风格名称或关键词匹配。',\n    parameters: Schema.object({\n      stylePreset: Schema.string().description('精确的风格预设名称（命令名）'),\n      styleQuery: Schema.string().description('风格搜索关键词，用于模糊匹配风格预设'),\n      referenceMode: Schema.union([\n        Schema.const('none').description('不参考任何图像'),\n        Schema.const('current_message').description('参考当前消息中的图片'),\n        Schema.const('quoted_message').description('参考引用的消息中的图片'),\n        Schema.const('explicit').description('显式指定图片 URL'),\n        Schema.const('last_generated').description('参考上一张生成的图像'),\n      ]).default('none').description('参考图片来源'),\n      imageUrls: Schema.array(Schema.string()).description('显式参考图像 URL 列表'),\n      promptAdditions: Schema.string().description('额外的文字描述补充'),\n      numImages: Schema.natural().min(1).max(4).default(1).description('生成图像数量'),\n      aspectRatio: Schema.string().description('宽高比，如 \"1:1\"、\"16:9\"、\"9:16\"'),\n      resolution: Schema.string().description('分辨率，如 \"1k\"、\"2k\"、\"4k\"'),\n      modelSuffix: Schema.string().description('模型后缀'),\n    }),\n    promptSnippet: '使用 aigc_apply_style_preset 工具应用风格',\n    promptGuidelines: [\n      '当用户要求将某种风格应用到图像时使用此工具',\n      '先用 aigc_list_styles 查询可用风格，再用此工具生成',\n      'stylePreset 使用精确名称，styleQuery 用于模糊搜索',\n    ],\n  },\n  {\n    name: 'aigc_get_quota',\n    description: '查询当前用户的图像生成积分余额和使用统计。',\n    parameters: Schema.object({}),\n    promptSnippet: '使用 aigc_get_quota 工具查询积分',\n    promptGuidelines: [\n      '当用户询问剩余配额、积分、余额、使用统计时使用此工具',\n    ],\n  },\n  {\n    name: 'aigc_list_styles',\n    description: '列出所有可用的风格预设及其描述，支持关键词搜索过滤。',\n    parameters: Schema.object({\n      query: Schema.string().description('可选的搜索关键词，用于过滤风格'),\n    }),\n    promptSnippet: '使用 aigc_list_styles 工具列出风格',\n    promptGuidelines: [\n      '当用户询问有哪些风格、支持什么风格时使用此工具',\n      '可以使用 query 参数搜索特定类型的风格',\n    ],\n  },\n]\n","/**\n * YesImBot 工具运行时（ToolService 格式）。\n *\n * 将 YESIMBOT_TOOL_DEFINITIONS 中定义的工具转换为 ToolService 可执行的\n * ToolDefinition，提供 execute() 函数实现。\n *\n * 与 sticker-manager 的 @Tool 装饰器产生完全相同的 execute 签名和返回值格式。\n *\n * 关键适配点（vs 旧的 AI SDK 格式）：\n * 1. execute 签名：({ session, ...params }) => Promise<ToolExecuteResult>\n * 2. 返回值：{ status: \"success\"|\"error\", result|error }\n * 3. parameters 直接使用 Koishi Schema（非 Zod + jsonSchema 包装）\n * 4. 工具实例存入 Map<string, ToolDefinitionForToolService>\n */\n\nimport { h } from 'koishi'\n\nimport { calculateGenerationCost, scaleGenerationCost } from '../../shared/billing.js'\nimport type { Config } from '../../shared/config.js'\nimport type {\n  ImageRequestContext,\n  ModelMappingConfig,\n  ResolvedStyleConfig,\n  StyleMatchCandidate,\n} from '../../shared/types.js'\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport type {\n  ToolDefinitionForToolService,\n  ToolExecuteResult,\n  ToolSessionLike,\n} from './runtime.js'\nimport type { YesImBotToolDefinition } from './tool-definitions.js'\n\n// ---------------------------------------------------------------------------\n// Success / Failed 辅助函数（与 ToolService helpers.js 返回格式一致）\n// ---------------------------------------------------------------------------\n\nfunction Success(result: unknown, metadata?: unknown): ToolExecuteResult {\n  return { status: 'success', result, metadata }\n}\n\nfunction Failed(error: string | { name: string; message: string; retryable?: boolean }, metadata?: unknown): ToolExecuteResult {\n  if (typeof error === 'string') {\n    return { status: 'error', error: { name: 'ToolError', message: error }, metadata }\n  }\n  return { status: 'error', error, metadata }\n}\n\n// ---------------------------------------------------------------------------\n// 工具实例创建（构造 ToolDefinitionForToolService）\n// ---------------------------------------------------------------------------\n\nexport function createYesImBotToolForToolService(\n  definition: YesImBotToolDefinition,\n  aiGenerator: AiImageGeneratorService,\n  config: Config,\n  logger: (...args: any[]) => void,\n): ToolDefinitionForToolService {\n  const execute = async (args: { session: ToolSessionLike; [key: string]: unknown }): Promise<ToolExecuteResult> => {\n    const session = args.session\n\n    try {\n      switch (definition.name) {\n        case 'aigc_generate_image':\n          return await runGenerateImageTool(args, session, aiGenerator, config, logger)\n        case 'aigc_edit_image':\n          return await runEditImageTool(args, session, aiGenerator, config, logger)\n        case 'aigc_apply_style_preset':\n          return await runStylePresetTool(args, session, aiGenerator, config, logger)\n        case 'aigc_get_quota':\n          return await runGetQuotaTool(session, aiGenerator)\n        case 'aigc_list_styles':\n          return runListStylesTool(args, aiGenerator)\n        default:\n          return Failed(`unsupported tool: ${definition.name}`)\n      }\n    } catch (error) {\n      const message = error instanceof Error ? error.message : String(error)\n      logger('YesImBot tool execute failed: %s, error: %s', definition.name, message)\n      return Failed(message)\n    }\n  }\n\n  return {\n    name: definition.name,\n    description: definition.description,\n    parameters: definition.parameters,\n    execute,\n    promptSnippet: definition.promptSnippet,\n    promptGuidelines: definition.promptGuidelines,\n  }\n}\n\n// ---------------------------------------------------------------------------\n// 工具执行函数\n// ---------------------------------------------------------------------------\n\nasync function runGenerateImageTool(\n  args: Record<string, unknown>,\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  config: Config,\n  logger: (...args: any[]) => void,\n): Promise<ToolExecuteResult> {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const prompt = expectString(args.prompt, 'prompt')\n    const { requestContext, generationCost } = buildRequestContextAndCost(args, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId,\n      session.username || session.userId,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return Failed(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      [],\n      generationCost.numImages,\n      requestContext,\n    )\n\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: 'aigc_generate_image',\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId,\n      session.username || session.userId,\n      'aigc_generate_image',\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return Success({\n      message: `生成完成！共生成 ${images.length} 张图像。`,\n      images: images.map(summarizeImageUrl),\n      ...(usage?.summary\n        ? { remainingCredits: aiGenerator.formatCredits(usage.summary.totalAvailable) }\n        : {}),\n    })\n  })\n}\n\nasync function runEditImageTool(\n  args: Record<string, unknown>,\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  config: Config,\n  logger: (...args: any[]) => void,\n): Promise<ToolExecuteResult> {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const prompt = expectString(args.prompt, 'prompt')\n    const referenceMode =\n      typeof args.referenceMode === 'string' ? args.referenceMode : 'explicit'\n    const imageUrls = resolveReferenceImages(\n      referenceMode,\n      args,\n      session,\n      aiGenerator,\n    )\n    if (!imageUrls.length) {\n      return Failed('未能解析到参考图片。请提供图片 URL 或在消息中附带图片。')\n    }\n\n    const { requestContext, generationCost } = buildRequestContextAndCost(args, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId,\n      session.username || session.userId,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return Failed(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      imageUrls,\n      generationCost.numImages,\n      requestContext,\n    )\n\n    const conversationId = aiGenerator.buildSessionConversationId(session as any)\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      conversationId,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: 'aigc_edit_image',\n      parentRecordId:\n        referenceMode === 'last_generated' && conversationId\n          ? aiGenerator.getConversationImageContext(conversationId)?.lastGenerated?.id\n          : undefined,\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId,\n      session.username || session.userId,\n      'aigc_edit_image',\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return Success({\n      message: `编辑完成！共生成 ${images.length} 张图像。`,\n      images: images.map(summarizeImageUrl),\n      ...(usage?.summary\n        ? { remainingCredits: aiGenerator.formatCredits(usage.summary.totalAvailable) }\n        : {}),\n    })\n  })\n}\n\nasync function runStylePresetTool(\n  args: Record<string, unknown>,\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  config: Config,\n  logger: (...args: any[]) => void,\n): Promise<ToolExecuteResult> {\n  return withImageTaskLock(session, aiGenerator, async () => {\n    const resolvedStyle = resolveRequestedStylePreset(args, aiGenerator)\n    if ('error' in resolvedStyle) {\n      return Failed(resolvedStyle.error)\n    }\n    const { preset } = resolvedStyle\n\n    const promptAdditions =\n      typeof args.promptAdditions === 'string' ? args.promptAdditions.trim() : ''\n    const prompt = [preset.prompt, promptAdditions].filter(Boolean).join(' - ')\n    const referenceMode =\n      typeof args.referenceMode === 'string' ? args.referenceMode : 'none'\n    const imageUrls =\n      referenceMode === 'none'\n        ? []\n        : resolveReferenceImages(referenceMode, args, session, aiGenerator)\n\n    if (referenceMode !== 'none' && !imageUrls.length) {\n      return Failed('未能解析到参考图片。')\n    }\n\n    const { requestContext, generationCost } = buildRequestContextAndCost(args, config)\n\n    const reservation = await aiGenerator.checkAndReserveQuota(\n      session.userId,\n      session.username || session.userId,\n      generationCost,\n      session.platform || undefined,\n    )\n    if (!reservation.allowed) {\n      return Failed(reservation.message || '积分不足。')\n    }\n\n    const images = await aiGenerator.requestProviderImages(\n      prompt,\n      imageUrls,\n      generationCost.numImages,\n      requestContext,\n    )\n\n    aiGenerator.rememberGeneratedImages({\n      session: session as any,\n      imageUrls: images,\n      prompt,\n      requestContext,\n      stylePreset: preset.commandName,\n    })\n\n    const actualCost =\n      images.length > 0 ? scaleGenerationCost(generationCost, images.length) : generationCost\n    const usage = await aiGenerator.recordUsage(\n      session.userId,\n      session.username || session.userId,\n      preset.commandName,\n      actualCost,\n      session.platform || undefined,\n    )\n\n    return Success({\n      message: `已应用「${preset.commandName}」风格，生成 ${images.length} 张图像。`,\n      images: images.map(summarizeImageUrl),\n      ...(usage?.summary\n        ? { remainingCredits: aiGenerator.formatCredits(usage.summary.totalAvailable) }\n        : {}),\n    })\n  })\n}\n\nasync function runGetQuotaTool(\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n): Promise<ToolExecuteResult> {\n  const summary = await aiGenerator.getQuotaSummary(\n    session.userId,\n    session.username || session.userId,\n  )\n  return Success({\n    userName: summary.userName || session.userId,\n    dailyFreeRemaining: aiGenerator.formatCredits(summary.dailyFreeRemaining),\n    purchasedCredits: aiGenerator.formatCredits(summary.purchasedCredits),\n    totalAvailable: aiGenerator.formatCredits(summary.totalAvailable),\n    totalImagesGenerated: summary.totalImagesGenerated,\n    totalConsumedCredits: aiGenerator.formatCredits(summary.totalConsumedCredits),\n    totalGrantedCredits: aiGenerator.formatCredits(summary.totalGrantedCredits),\n  })\n}\n\nfunction runListStylesTool(\n  args: Record<string, unknown>,\n  aiGenerator: AiImageGeneratorService,\n): ToolExecuteResult {\n  const query = typeof args.query === 'string' ? args.query.trim() : ''\n  const allStyles = aiGenerator.listStylePresets()\n\n  let styles = allStyles\n  if (query) {\n    const matches = aiGenerator.matchStylePresets(query, 20)\n    styles = matches.map((m) => m.style)\n  }\n\n  if (!styles.length) {\n    return Success({\n      styles: [],\n      message: query ? `未找到匹配「${query}」的风格预设。` : '暂无可用风格预设。',\n    })\n  }\n\n  return Success({\n    styles: styles.map((s) => ({\n      commandName: s.commandName,\n      description: s.description || '',\n      category: s.category || '',\n    })),\n    message: query\n      ? `找到 ${styles.length} 个匹配「${query}」的风格预设`\n      : `共 ${styles.length} 个可用风格预设`,\n  })\n}\n\n// ---------------------------------------------------------------------------\n// 请求上下文 & 费用构建\n// ---------------------------------------------------------------------------\n\nconst VALID_ASPECT_RATIOS = new Set(['1:1', '4:3', '16:9', '9:16', '3:2', '2:3'])\nconst VALID_RESOLUTIONS = new Set(['1k', '2k', '4k'])\nconst CUSTOM_RESOLUTION_RE = /^\\d{3,5}x\\d{3,5}$/\n\nfunction buildRequestContextAndCost(\n  args: Record<string, unknown>,\n  config: Config,\n): { requestContext: ImageRequestContext; generationCost: ReturnType<typeof calculateGenerationCost> } {\n  let numImages = config.defaultNumImages || 1\n  if (typeof args.numImages === 'number' && Number.isFinite(args.numImages)) {\n    numImages = Math.max(1, Math.min(4, Math.round(args.numImages)))\n  }\n\n  const requestContext: ImageRequestContext = { numImages }\n\n  if (typeof args.aspectRatio === 'string' && VALID_ASPECT_RATIOS.has(args.aspectRatio)) {\n    requestContext.aspectRatio = args.aspectRatio as ImageRequestContext['aspectRatio']\n  }\n\n  if (typeof args.resolution === 'string') {\n    const res = args.resolution.trim()\n    if (VALID_RESOLUTIONS.has(res) || CUSTOM_RESOLUTION_RE.test(res)) {\n      requestContext.resolution = res as ImageRequestContext['resolution']\n    }\n  }\n\n  const modelSuffix = typeof args.modelSuffix === 'string' ? args.modelSuffix.trim() : ''\n  let modelMapping: ModelMappingConfig | undefined\n  if (modelSuffix) {\n    modelMapping = (config.modelMappings || []).find((item) => item.suffix === modelSuffix)\n  }\n\n  if (modelMapping) {\n    requestContext.supplier = modelMapping.supplier\n    requestContext.provider = modelMapping.protocol\n    if (modelMapping.modelId) {\n      requestContext.modelId = modelMapping.modelId\n    }\n  }\n\n  const generationCost = calculateGenerationCost({\n    numImages,\n    modelMapping,\n    config,\n  })\n\n  return { requestContext, generationCost }\n}\n\n// ---------------------------------------------------------------------------\n// 风格预设解析\n// ---------------------------------------------------------------------------\n\nfunction resolveRequestedStylePreset(\n  args: Record<string, unknown>,\n  aiGenerator: AiImageGeneratorService,\n):\n  | { preset: ResolvedStyleConfig; matches: StyleMatchCandidate[] }\n  | { error: string } {\n  const explicitStylePreset =\n    typeof args.stylePreset === 'string' ? args.stylePreset.trim() : ''\n  if (explicitStylePreset) {\n    const preset = aiGenerator.getStylePreset(explicitStylePreset)\n    if (!preset) {\n      return { error: `未找到风格预设: ${explicitStylePreset}` }\n    }\n    return {\n      preset,\n      matches: [{ style: preset, score: 999, matchedTerms: [explicitStylePreset] }],\n    }\n  }\n\n  const styleQuery = typeof args.styleQuery === 'string' ? args.styleQuery.trim() : ''\n  if (!styleQuery) {\n    return { error: 'stylePreset 或 styleQuery 至少需要提供一个。' }\n  }\n\n  const matches = aiGenerator.matchStylePresets(styleQuery, 3)\n  if (!matches.length) {\n    return { error: `未找到与「${styleQuery}」匹配的风格预设。` }\n  }\n  const topMatch = matches[0]\n  if (!topMatch) {\n    return { error: `未找到与「${styleQuery}」匹配的风格预设。` }\n  }\n\n  return { preset: topMatch.style, matches }\n}\n\n// ---------------------------------------------------------------------------\n// 图片引用解析\n// ---------------------------------------------------------------------------\n\nfunction resolveReferenceImages(\n  referenceMode: string,\n  args: Record<string, unknown>,\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n): string[] {\n  if (referenceMode === 'explicit') {\n    return normalizeImageUrls(\n      Array.isArray(args.imageUrls)\n        ? args.imageUrls.filter(\n            (item): item is string => typeof item === 'string' && item.trim().length > 0,\n          )\n        : [],\n    )\n  }\n\n  if (referenceMode === 'last_generated') {\n    const conversationId = aiGenerator.buildSessionConversationId(session as any)\n    if (!conversationId) return []\n    const lastGenerated = aiGenerator.getConversationImageContext(conversationId)?.lastGenerated\n    return lastGenerated ? [lastGenerated.imageUrl] : []\n  }\n\n  if (referenceMode === 'current_message') {\n    return parseImagesFromMessageContent(session.content)\n  }\n\n  return []\n}\n\nfunction parseImagesFromMessageContent(content: unknown): string[] {\n  if (typeof content === 'string' && content.trim()) {\n    return normalizeImageUrls(\n      h.select(h.parse(content), 'img').map((img: any) => img.attrs?.src),\n    )\n  }\n\n  if (Array.isArray(content)) {\n    return normalizeImageUrls(\n      h.select(content as any[], 'img').map((img: any) => img.attrs?.src),\n    )\n  }\n\n  return []\n}\n\nfunction summarizeImageUrl(url: string): string {\n  if (url.startsWith('data:')) {\n    return '[base64_image]'\n  }\n  return url\n}\n\n// ---------------------------------------------------------------------------\n// 工具函数\n// ---------------------------------------------------------------------------\n\nfunction expectString(value: unknown, key: string): string {\n  if (typeof value !== 'string' || !value.trim()) {\n    throw new Error(`${key} is required.`)\n  }\n  return value.trim()\n}\n\nfunction normalizeImageUrls(items: unknown[]): string[] {\n  return items\n    .filter((item): item is string => typeof item === 'string' && item.trim().length > 0)\n    .map((item) => item.trim())\n}\n\nasync function withImageTaskLock(\n  session: ToolSessionLike,\n  aiGenerator: AiImageGeneratorService,\n  work: () => Promise<ToolExecuteResult>,\n): Promise<ToolExecuteResult> {\n  const requestId = aiGenerator.userManager.startTask(session.userId)\n  if (!requestId) {\n    return Failed('您有一个图像处理任务正在进行中，请等待完成。')\n  }\n\n  try {\n    return await work()\n  } finally {\n    aiGenerator.userManager.endTask(session.userId, requestId)\n  }\n}\n","/**\n * YesImBot 扩展实例工厂（ToolService 格式）。\n *\n * 构造一个符合 ToolService.register() 要求的扩展实例，\n * 包含 metadata 和 tools Map，与 sticker-manager 的 @Extension/@Tool\n * 装饰器产生的结果一致。\n */\n\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport type { Config } from '../../shared/config.js'\nimport { YESIMBOT_BRIDGE_EXTENSION_ID } from '../../shared/constants.js'\nimport type {\n  ExtensionInstanceLike,\n  ExtensionMetadataLike,\n  ToolDefinitionForToolService,\n} from './runtime.js'\nimport { YESIMBOT_TOOL_DEFINITIONS } from './tool-definitions.js'\nimport { createYesImBotToolForToolService } from './tool-runtime.js'\n\nexport function createYesImBotExtensionInstance(\n  aiGenerator: AiImageGeneratorService,\n  config: Config,\n  logger: (...args: any[]) => void,\n): ExtensionInstanceLike {\n  const toolsToRegister = YESIMBOT_TOOL_DEFINITIONS.filter((def) => {\n    if (def.name === 'aigc_get_quota' && !config.yesimbotExposeQuotaTool) {\n      return false\n    }\n    if (def.name === 'aigc_list_styles' && !config.yesimbotExposeStyleListTool) {\n      return false\n    }\n    return true\n  })\n\n  const tools = new Map<string, ToolDefinitionForToolService>()\n  for (const definition of toolsToRegister) {\n    const toolInstance = createYesImBotToolForToolService(\n      definition,\n      aiGenerator,\n      config,\n      logger,\n    )\n    tools.set(toolInstance.name, toolInstance)\n    logger('YesImBot tool prepared: %s', definition.name)\n  }\n\n  const metadata: ExtensionMetadataLike = {\n    name: YESIMBOT_BRIDGE_EXTENSION_ID,\n    display: 'AI 图像生成',\n    description: '提供 AI 图像生成功能，包括文生图、图生图、风格应用、积分查询和风格列表。',\n    author: 'aka',\n    version: '1.0.0',\n  }\n\n  return { metadata, tools }\n}\n","/**\n * YesImBot 桥接管理器（ToolService 路径）。\n *\n * 负责：\n * - 获取 ctx[\"yesimbot.tool\"] (ToolService)\n * - 构造扩展实例（含 metadata + tools Map）\n * - 通过 toolService.register(instance, enabled, config) 注册工具\n * - 同步 enabled/disabled 状态并处理热重载\n *\n * 改造说明（0.8.5）：\n *   之前的实现错误地使用了 \"yesimbot.extension\" (ExtensionService) —\n *   该服务仅存在于 monorepo 的 core 中，npm 发布的 koishi-plugin-yesimbot@3.x\n *   根本不包含此服务。正确路径是 \"yesimbot.tool\" (ToolService)，\n *   与 sticker-manager 使用完全相同的注册方式。\n *\n * 与 sticker-manager 的差异：\n *   - sticker-manager 使用 @Extension/@Tool 装饰器自动注册\n *   - 本 bridge 手动构造 ExtensionInstanceLike 并调用 register()\n *   - 结果完全一致：extension.list 可见，LLM 可调用\n */\n\nimport type { Context } from 'koishi'\n\nimport type { AiImageGeneratorService } from '../../service/AiImageGeneratorService.js'\nimport type { Config } from '../../shared/config.js'\nimport { YESIMBOT_BRIDGE_EXTENSION_ID } from '../../shared/constants.js'\nimport type {\n  ExtensionInstanceLike,\n  ToolServiceLike,\n} from './runtime.js'\nimport { createYesImBotExtensionInstance } from './tools.js'\n\nexport class YesImBotBridgeManager {\n  private toolService: ToolServiceLike | null = null\n  private extensionInstance: ExtensionInstanceLike | null = null\n  private isRegistered = false\n  private warnedUnavailable = false\n  private syncQueue: Promise<void> = Promise.resolve()\n  private readyDispose: (() => void) | null = null\n\n  constructor(\n    private readonly ctx: Context,\n    private readonly aiGenerator: AiImageGeneratorService,\n    private config: Config,\n    private readonly logger: ReturnType<Context['logger']>,\n  ) {}\n\n  updateConfig(config: Config) {\n    this.config = config\n  }\n\n  sync(enabled: boolean) {\n    this.syncQueue = this.syncQueue\n      .catch(() => {})\n      .then(async () => {\n        if (enabled) {\n          this.logger.info('YesImBot bridge sync: enabled=true, starting enable()')\n          await this.enable()\n        } else {\n          this.logger.info('YesImBot bridge sync: enabled=false, skipping registration')\n          await this.disable()\n        }\n      })\n    return this.syncQueue\n  }\n\n  async dispose() {\n    if (this.readyDispose) {\n      this.readyDispose()\n      this.readyDispose = null\n    }\n    await this.disable()\n  }\n\n  private async enable() {\n    // 先清理之前的 ready 监听器（避免重入时重复注册）\n    if (this.readyDispose) {\n      this.readyDispose()\n      this.readyDispose = null\n    }\n    this.warnedUnavailable = false\n\n    // 1. 获取 ToolService（此时 YesImBot 的 start() 可能尚未完成，ToolService 可能为 null）\n    const toolService = this.getToolService()\n    if (toolService) {\n      this.logger.info('YesImBot ToolService found immediately, proceeding with registration')\n      await this.doRegister(toolService)\n      return\n    }\n\n    // 2. ToolService 尚未就绪 —— 通过 ctx.on(\"ready\") 等待所有插件初始化完毕后再重试。\n    //    这与 sticker-manager 的 @Extension 装饰器使用相同的 ctx.on(\"ready\", ...) 策略。\n    this.logger.info(\n      'YesImBot ToolService not ready yet (ctx[\"yesimbot.tool\"] is null). ' +\n      'Waiting for \"ready\" event (all plugins initialized) before retrying registration.',\n    )\n    this.readyDispose = this.ctx.on('ready', () => {\n      this.readyDispose = null\n      // ready 事件在同步回调中触发 —— 此时所有 Service.start() 已完成\n      const service = this.getToolService()\n      if (!service) {\n        this.logger.warn(\n          'YesImBot bridge: \"ready\" event fired but \"yesimbot.tool\" service still not available. ' +\n          'Make sure koishi-plugin-yesimbot is installed and enabled.',\n        )\n        this.warnedUnavailable = true\n        return\n      }\n      void this.doRegister(service)\n    })\n  }\n\n  private async doRegister(toolService: ToolServiceLike) {\n    // 如果已注册，跳过\n    if (this.isRegistered) {\n      this.logger.info('YesImBot bridge already registered, skipping re-registration')\n      return\n    }\n\n    // 创建扩展实例（以获取最新 config 和 style 列表）\n    this.logger.info('Creating YesImBot extension instance with %d tools configured',\n      this.config.yesimbotExposeQuotaTool !== false ? 'all' : 'filtered')\n    this.extensionInstance = createYesImBotExtensionInstance(\n      this.aiGenerator,\n      this.config,\n      (...args: any[]) => {\n        this.logger.info(`[yesimbot-bridge] ${args[0]}`, ...args.slice(1))\n      },\n    )\n    this.logger.info('Extension instance created with %d tools in tools Map',\n      this.extensionInstance.tools.size)\n\n    // 注册到 ToolService\n    this.logger.info(\n      'Calling toolService.register() for extension \"%s\" (display: \"%s\")',\n      this.extensionInstance.metadata.name,\n      this.extensionInstance.metadata.display,\n    )\n    toolService.register(this.extensionInstance, true)\n    this.toolService = toolService\n    this.isRegistered = true\n\n    this.logger.info(\n      'YesImBot bridge enabled. Extension \"%s\" registered in ToolService. ' +\n      'Run \"extension.list\" to verify.',\n      YESIMBOT_BRIDGE_EXTENSION_ID,\n    )\n  }\n\n  private async disable() {\n    if (!this.isRegistered || !this.toolService) {\n      return\n    }\n\n    this.toolService.unregister(YESIMBOT_BRIDGE_EXTENSION_ID)\n    this.toolService = null\n    this.extensionInstance = null\n    this.isRegistered = false\n\n    this.logger.info('YesImBot bridge disabled.')\n  }\n\n  private getToolService(): ToolServiceLike | null {\n    // \"yesimbot.tool\" 是 YesImBot 的 ToolService (services/extension/service.js)，\n    // 通过 super(ctx, \"yesimbot.tool\") 注册为 Koishi Service。\n    //\n    // inject.optional 中已声明 'yesimbot.tool'，Koishi Proxy 会放行此访问路径。\n    //\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const raw = (this.ctx as any)['yesimbot.tool']\n    if (!raw) {\n      this.logger.info(\n        'getToolService: ctx[\"yesimbot.tool\"] is null/undefined. ' +\n        'Is koishi-plugin-yesimbot installed and loaded before this plugin?',\n      )\n      return null\n    }\n\n    const service = raw as ToolServiceLike\n    if (\n      typeof service.register === 'function' &&\n      typeof service.unregister === 'function'\n    ) {\n      this.logger.info('getToolService: ctx[\"yesimbot.tool\"] found and verified (has register/unregister)')\n      return service\n    }\n\n    // 诊断：服务存在但 API 不匹配\n    this.logger.info(\n      'getToolService: ctx[\"yesimbot.tool\"] exists but lacks register/unregister. ' +\n      'typeof=%s keys=%s',\n      typeof raw,\n      Object.keys(raw).join(','),\n    )\n    return null\n  }\n}\n","import type { Context } from 'koishi'\n\nimport type { Config } from '../shared/config.js'\nimport { COMMANDS } from '../shared/constants.js'\n\nexport interface RegisterHelpCommandsParams {\n  ctx: Context\n  getConfig: () => Config\n}\n\nexport function registerHelpCommands(params: RegisterHelpCommandsParams) {\n  const { ctx, getConfig } = params\n\n  ctx.command(`${COMMANDS.IMAGE_HELP}`, '查看图像生成命令说明')\n    .action(() => buildImageHelp(getConfig()))\n\n  ctx.command(`${COMMANDS.PARAM_HELP}`, '查看图像生成参数说明')\n    .action(() => buildParameterHelp(getConfig()))\n}\n\nfunction buildImageHelp(config: Config): string {\n  const lines: string[] = [\n    '图像指令',\n    '',\n    '核心命令：',\n    `- ${COMMANDS.TXT_TO_IMG} <描述>｜根据文字描述生成图片`,\n    `- ${COMMANDS.IMG_TO_IMG} [图片] <描述>｜根据单张参考图修改图片`,\n    `- ${COMMANDS.COMPOSE_IMAGE} <描述>｜收集多张图片后按描述合成`,\n    '',\n    '快捷命令：',\n  ]\n\n  const styles = collectStyleRows(config)\n  if (styles.length) {\n    for (const style of styles) {\n      lines.push(`- ${style.commandName}｜${formatStyleMode(style.mode)}｜${style.description || 'Prompt 预设'}`)\n    }\n  } else {\n    lines.push('暂无，请在配置页 styles / styleGroups 中添加')\n  }\n\n  lines.push(\n    '',\n    `账户：${COMMANDS.ADMIN_QUERY} / ${COMMANDS.ADMIN_BILL}`,\n    `管理员：${COMMANDS.ADMIN_RECHARGE} / ${COMMANDS.USAGE_RANKING}`,\n    `参数可选项：发送 ${COMMANDS.PARAM_HELP} 查看`,\n  )\n  return lines.join('\\n')\n}\n\nfunction buildParameterHelp(config: Config): string {\n  const defaultNum = resolveCommandNum(config.defaultNumImages)\n  const lines: string[] = [\n    '图像参数',\n    '',\n    '通用参数：',\n    `- -n <数量>｜生成数量，1-4，默认 ${defaultNum}`,\n    '- -add <文本>｜追加生成要求',\n    '- -模型后缀｜临时切换模型',\n    '',\n    '尺寸：',\n    '- -1k / -2k / -4k｜预设分辨率',\n    '- -1024x1024｜自定义分辨率',\n    '',\n    '比例：',\n    '- -1:1 / -4:3 / -16:9 / -9:16 / -3:2 / -2:3｜画幅比例',\n    '',\n    '积分：',\n    `- 默认每张｜${config.defaultCreditCostPerImage ?? 1} ${config.creditUnitName || '积分'}`,\n    `- 每日免费｜${config.dailyFreeCredits ?? 0} ${config.creditUnitName || '积分'}`,\n    '- 受限模型仍需白名单或管理员权限；白名单不代表免费',\n  ]\n\n  const restrictedMappings = Array.isArray(config.modelMappings)\n    ? config.modelMappings.filter((mapping) => mapping?.suffix && mapping?.modelId && mapping.restricted)\n    : []\n\n  if (restrictedMappings.length) {\n    lines.push('', '受限模型：')\n    for (const mapping of restrictedMappings) {\n      lines.push(`- ${normalizeSuffixLabel(mapping.suffix)}｜${mapping.modelId}`)\n    }\n  }\n\n  return lines.join('\\n')\n}\n\nfunction normalizeSuffixLabel(value: string): string {\n  const trimmed = value.trim()\n  if (!trimmed) return '-'\n  return trimmed.startsWith('-') ? trimmed : `-${trimmed}`\n}\n\nfunction collectStyleRows(config: Config) {\n  const rows: Array<{ commandName: string; mode?: string; description?: string }> = []\n  const names = new Set<string>()\n  const push = (style: any) => {\n    if (!style?.commandName || !style?.prompt) return\n    if (names.has(style.commandName)) return\n    names.add(style.commandName)\n    rows.push({\n      commandName: style.commandName,\n      mode: style.mode,\n      description: style.description,\n    })\n  }\n\n  if (Array.isArray(config.styles)) {\n    for (const style of config.styles) push(style)\n  }\n  if (config.styleGroups && typeof config.styleGroups === 'object') {\n    for (const group of Object.values(config.styleGroups)) {\n      if (!group || !Array.isArray(group.prompts)) continue\n      for (const style of group.prompts) push(style)\n    }\n  }\n  return rows\n}\n\nfunction formatStyleMode(value?: string): string {\n  switch (value) {\n    case 'text-to-image':\n      return '文生图'\n    case 'compose-image':\n      return '合成图'\n    case 'image-to-image':\n    default:\n      return '图生图'\n  }\n}\n\nfunction resolveCommandNum(value: number | undefined): number {\n  if (!Number.isFinite(value)) return 1\n  return Math.min(4, Math.max(1, Math.floor(value || 1)))\n}\n","/**\n * 图像命令族：核心文生图 / 图生图 / 合成图、账户查询与 styles 快捷命令。\n *\n * 设计要点：\n * - 核心命令保持无前缀直呼格式，例如 `文生图` / `图生图` / `合成图` / `图像查询`。\n * - styles 命令由配置动态注册，按 `mode` 分发到对应生成链路。\n * - 模型选择优先级：用户显式模型后缀 > style 默认模型后缀 > 插件默认模型。\n */\n\nimport { h } from 'koishi'\nimport type { Argv, Command, Context, Session } from 'koishi'\n\nimport type { Config } from '../shared/config.js'\nimport { COMMANDS } from '../shared/constants.js'\nimport type { ImageGenerationHandlers } from '../orchestrators/ImageGenerationOrchestrator.js'\nimport type { AiImageGeneratorService } from '../service/AiImageGeneratorService.js'\nimport type {\n  ImageGenerationModifiers,\n  ModelMappingConfig,\n  ResolvedStyleConfig,\n  StyleMode,\n} from '../shared/types.js'\nimport type { CreditLedgerEventV2 } from '../services/UserManager.js'\nimport {\n  buildModelMappingIndex,\n  normalizeSuffix,\n  parseStyleCommandModifiers,\n} from '../utils/parser.js'\n\nexport interface RegisterImageCommandsParams {\n  ctx: Context\n  service: AiImageGeneratorService\n  handlers: ImageGenerationHandlers\n  getConfig: () => Config\n}\n\nexport interface RegisteredImageCommands {\n  refreshStyleCommands: () => void\n}\n\nexport function registerImageCommands(params: RegisterImageCommandsParams): RegisteredImageCommands {\n  const { ctx, service, handlers, getConfig } = params\n  const logger = ctx.logger('aka-ai-image-generator')\n\n  // ---------------------------------------------------------------------------\n  // 文生图：文生图 [-n 数量|-1k|-16:9|-add ...] <prompt:text>\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.TXT_TO_IMG} [prompt:text]`, '文生图')\n    .alias('t2i')\n    .option('num', '-n <num:number> 生成图片数量（1-4）')\n    .action(async (argv: Argv, prompt?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const modifiers = buildCommandModifiers(argv, undefined, config)\n      const access = service.checkModelAccess(session.userId || 'unknown', modifiers)\n      if (!access.allowed) return access.message || ['模型受限', '', '- 要求｜管理员或模型白名单'].join('\\n')\n\n      const setup = service.buildGenerationSetup(\n        resolveCommandNum(getCommandOptionNumber(argv, 'num'), config.defaultNumImages || 1),\n        modifiers,\n      )\n\n      return handlers.executeTextToImage(\n        session,\n        prompt,\n        setup.requestContext,\n        setup.displayInfo,\n      )\n    })\n\n  // ---------------------------------------------------------------------------\n  // 图生图：图生图 [-n 数量|-1k|-16:9|-add ...] [img] [prompt:text]\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.IMG_TO_IMG} [img] [prompt:text]`, '图生图')\n    .alias('i2i')\n    .option('num', '-n <num:number> 生成图片数量（1-4）')\n    .action(async (argv: Argv, img?: unknown, prompt?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const modifiers = buildCommandModifiers(argv, img, config)\n      const access = service.checkModelAccess(session.userId || 'unknown', modifiers)\n      if (!access.allowed) return access.message || ['模型受限', '', '- 要求｜管理员或模型白名单'].join('\\n')\n\n      const setup = service.buildGenerationSetup(\n        resolveCommandNum(getCommandOptionNumber(argv, 'num'), config.defaultNumImages || 1),\n        modifiers,\n      )\n\n      return handlers.executeImageToImage(\n        session,\n        img,\n        prompt,\n        setup.requestContext,\n        setup.displayInfo,\n      )\n    })\n\n  // ---------------------------------------------------------------------------\n  // 合成图：合成图 [-n 数量|-1k|-16:9|-add ...]\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.COMPOSE_IMAGE} [prompt:text]`, '合成多张图片')\n    .alias('compose-image')\n    .option('num', '-n <num:number> 生成图片数量（1-4）')\n    .action(async (argv: Argv, prompt?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const modifiers = buildCommandModifiers(argv, undefined, config)\n      const access = service.checkModelAccess(session.userId || 'unknown', modifiers)\n      if (!access.allowed) return access.message || ['模型受限', '', '- 要求｜管理员或模型白名单'].join('\\n')\n\n      const setup = service.buildGenerationSetup(\n        resolveCommandNum(getCommandOptionNumber(argv, 'num'), config.defaultNumImages || 1),\n        modifiers,\n      )\n\n      return handlers.executeComposeImage(\n        session,\n        prompt,\n        setup.requestContext,\n        setup.displayInfo,\n      )\n    })\n\n  const refreshStyleCommands = registerStyleCommands({\n    ctx,\n    service,\n    handlers,\n    getConfig,\n    logger,\n  })\n\n  // ---------------------------------------------------------------------------\n  // 账户查询：图像查询 / 图像查询 @用户\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.ADMIN_QUERY} [target:text]`, '查询图像积分与生成统计')\n    .action(async (argv: Argv, target?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const operatorId = session.userId || 'unknown'\n      const isAdmin = service.userManager.isAdmin(operatorId, config)\n      const targetUser = parseMentionTarget(target || session.content || '')\n\n      if (targetUser?.userId && !isAdmin) {\n        return ['权限不足', '', '- 命令｜图像查询', '- 要求｜管理员才能查询他人'].join('\\n')\n      }\n\n      const summary = targetUser?.userId\n        ? await service.getExistingUsageSummary(targetUser.userId)\n        : await service.getQuotaSummary(operatorId, session.username || session.author?.name || operatorId)\n\n      if (!summary) return [\n        '图像查询',\n        '',\n        `- 用户｜${targetUser?.userName || targetUser?.userId || operatorId}`,\n        '- 状态｜暂无图像积分数据',\n      ].join('\\n')\n\n      const lines = [\n        '图像查询',\n        '',\n        `- 用户｜${summary.userName || targetUser?.userName || targetUser?.userId || operatorId}`,\n        `- 今日免费｜${service.formatCredits(summary.dailyFreeRemaining)}`,\n        `- 已购余额｜${service.formatCredits(summary.purchasedCredits)}`,\n        `- 合计可用｜${service.formatCredits(summary.totalAvailable)}`,\n        `- 已生成｜${summary.totalImagesGenerated} 张`,\n        `- 历史消耗｜${service.formatCredits(summary.totalConsumedCredits)}`,\n        `- 累计充值｜${service.formatCredits(summary.totalGrantedCredits)}`,\n      ]\n      if (isAdmin && summary.estimatedCny !== undefined) {\n        lines.push(`- 余额估算｜约 ${summary.estimatedCny} 元`)\n      }\n      return lines.join('\\n')\n    })\n\n  // ---------------------------------------------------------------------------\n  // 管理员排行榜：图像排行榜 [-n 数量]\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.USAGE_RANKING}`, '管理员查看用户图像用量排行榜')\n    .option('num', '-n <num:number> 显示数量（1-50）')\n    .action(async (argv: Argv) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      if (!service.userManager.isAdmin(session.userId || 'unknown', config)) {\n        return ['权限不足', '', '- 命令｜图像排行榜', '- 要求｜管理员'].join('\\n')\n      }\n\n      const rows = await service.getUsageRanking(resolveRankingLimit(getCommandOptionNumber(argv, 'num')))\n      if (!rows.length) return ['图像排行榜', '', '- 状态｜暂无图像积分数据'].join('\\n')\n      return [\n        '图像排行榜',\n        '',\n        ...rows.map(row => `- ${row.userName}｜生成 ${row.totalImagesGenerated} 张｜消耗 ${service.formatCredits(row.totalConsumedCredits)}｜余额 ${service.formatCredits(row.totalAvailable)}`),\n      ].join('\\n')\n    })\n\n  // ---------------------------------------------------------------------------\n  // 管理员充值 / 余额修正：图像充值 @用户 100 [原因] / 图像充值 @用户 -10 [原因]\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.ADMIN_RECHARGE} [input:text]`, '管理员为用户充值或修正图像积分')\n    .action(async (argv: Argv, input?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      if (!service.userManager.isAdmin(session.userId || 'unknown', config)) {\n        return ['权限不足', '', '- 命令｜图像充值', '- 要求｜管理员'].join('\\n')\n      }\n\n      const parsed = parseCreditCommandInput(input || session.content || '', COMMANDS.ADMIN_RECHARGE)\n      if (!parsed.target?.userId || parsed.amount === undefined || parsed.amount === 0) {\n        return '请使用｜图像充值 @用户 积分 [原因]'\n      }\n\n      const operator = {\n        userId: session.userId || 'unknown',\n        userName: session.username || session.author?.name || session.userId || 'unknown',\n      }\n\n      if (parsed.amount > 0) {\n        const result = await service.grantCredits(\n          parsed.target.userId,\n          parsed.target.userName || parsed.target.userId,\n          parsed.amount,\n          parsed.reason || '管理员充值',\n          operator,\n        )\n        const summary = service.userManager.buildCreditSummary(result.userData, config)\n        return [\n          '图像充值完成',\n          '',\n          `- 用户｜${summary.userName}`,\n          `- 本次充值｜${service.formatCredits(result.ledgerEvent.amount)}`,\n          `- 已购余额｜${service.formatCredits(summary.purchasedCredits)}`,\n          `- 合计可用｜${service.formatCredits(summary.totalAvailable)}`,\n          `- 流水｜#${result.ledgerEvent.sequence}`,\n        ].join('\\n')\n      }\n\n      const requestedAdjustment = Math.abs(parsed.amount)\n      const result = await service.adjustCredits(\n        parsed.target.userId,\n        parsed.target.userName || parsed.target.userId,\n        requestedAdjustment,\n        parsed.reason || '管理员余额修正',\n        operator,\n      )\n      const summary = service.userManager.buildCreditSummary(result.userData, config)\n      if (!result.ledgerEvent) {\n        return [\n          '余额调整失败',\n          '',\n          `- 用户｜${summary.userName}`,\n          `- 请求调整｜-${service.formatCredits(result.requestedAmount)}`,\n          `- 实际调整｜-${service.formatCredits(result.deductedAmount)}`,\n          `- 原因｜用户已购余额不足`,\n          `- 已购余额｜${service.formatCredits(summary.purchasedCredits)}`,\n          `- 合计可用｜${service.formatCredits(summary.totalAvailable)}`,\n        ].join('\\n')\n      }\n\n      return [\n        result.isPartial ? '图像余额部分调整完成' : '图像余额调整完成',\n        '',\n        `- 用户｜${summary.userName}`,\n        `- 请求调整｜-${service.formatCredits(result.requestedAmount)}`,\n        `- 实际调整｜-${service.formatCredits(result.deductedAmount)}`,\n        `- 已购余额｜${service.formatCredits(summary.purchasedCredits)}`,\n        `- 合计可用｜${service.formatCredits(summary.totalAvailable)}`,\n        `- 流水｜#${result.ledgerEvent.sequence}`,\n      ].join('\\n')\n    })\n\n  // ---------------------------------------------------------------------------\n  // 账单查询：图像账单 / 图像账单 @用户 / 图像账单 --all\n  // ---------------------------------------------------------------------------\n  ctx.command(`${COMMANDS.ADMIN_BILL} [target:text]`, '查看图像积分流水')\n    .option('num', '-n <num:number> 显示数量（1-50）')\n    .option('all', '--all 显示全局最近流水（管理员）')\n    .action(async (argv: Argv, target?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const operatorId = session.userId || 'unknown'\n      const isAdmin = service.userManager.isAdmin(operatorId, config)\n      const targetUser = parseMentionTarget(target || session.content || '')\n      const showAll = getCommandOptionBoolean(argv, 'all')\n      const limit = resolveRankingLimit(getCommandOptionNumber(argv, 'num'))\n\n      if ((showAll || targetUser?.userId) && !isAdmin) {\n        return ['权限不足', '', '- 命令｜图像账单', '- 要求｜管理员才能查询他人或全局流水'].join('\\n')\n      }\n\n      const scopeUserId = showAll ? undefined : targetUser?.userId || operatorId\n      const scopeLabel = showAll\n        ? '- 范围｜全部用户'\n        : `- 用户｜${targetUser?.userName || targetUser?.userId || session.username || session.author?.name || operatorId}`\n      const events = await service.listLedgerEvents(scopeUserId, limit)\n      if (!events.length) return [\n        '图像账单',\n        '',\n        scopeLabel,\n        '- 状态｜暂无积分流水',\n      ].join('\\n')\n\n      return [\n        '图像账单',\n        '',\n        scopeLabel,\n        ...events.map(event => formatLedgerEvent(event, service.formatCredits.bind(service))),\n      ].join('\\n')\n    })\n\n  return { refreshStyleCommands }\n}\n\ninterface RegisterStyleCommandsParams extends RegisterImageCommandsParams {\n  logger: ReturnType<Context['logger']>\n}\n\nfunction registerStyleCommands(params: RegisterStyleCommandsParams): () => void {\n  const { logger } = params\n  let registeredCommands: Command[] = []\n\n  const refresh = () => {\n    for (const command of registeredCommands) command.dispose()\n    registeredCommands = []\n\n    const reservedNames = new Set<string>([\n      COMMANDS.TXT_TO_IMG,\n      COMMANDS.IMG_TO_IMG,\n      COMMANDS.COMPOSE_IMAGE,\n      COMMANDS.ADMIN_QUERY,\n      COMMANDS.USAGE_RANKING,\n      COMMANDS.ADMIN_RECHARGE,\n      COMMANDS.ADMIN_BILL,\n      COMMANDS.IMAGE_HELP,\n      COMMANDS.PARAM_HELP,\n    ])\n\n    for (const style of params.service.listStylePresets()) {\n      const command = registerStyleCommand(params, style, reservedNames)\n      if (command) registeredCommands.push(command)\n    }\n\n    logger.info('style 命令刷新完成', { count: registeredCommands.length })\n  }\n\n  refresh()\n  return refresh\n}\n\nfunction registerStyleCommand(\n  params: RegisterStyleCommandsParams,\n  style: ResolvedStyleConfig,\n  reservedNames: Set<string>,\n): Command | undefined {\n  const { ctx, service, handlers, getConfig, logger } = params\n  if (!style.commandName || !style.prompt) return undefined\n  if (reservedNames.has(style.commandName)) {\n    logger.warn('跳过与核心命令冲突的 style 命令', { commandName: style.commandName })\n    return undefined\n  }\n  reservedNames.add(style.commandName)\n\n  const command = ctx.command(`${style.commandName} [img] [prompt:text]`, style.description || 'Prompt 预设')\n    .option('num', '-n <num:number> 生成图片数量（1-4）')\n    .action(async (argv: Argv, img?: unknown, prompt?: string) => {\n      const session = argv.session\n      if (!session) return ''\n\n      const config = getConfig()\n      const modifiers = buildCommandModifiers(argv, img, config, style)\n      const access = service.checkModelAccess(session.userId || 'unknown', modifiers)\n      if (!access.allowed) return access.message || ['模型受限', '', '- 要求｜管理员或模型白名单'].join('\\n')\n\n      const setup = service.buildGenerationSetup(\n        resolveCommandNum(getCommandOptionNumber(argv, 'num'), config.defaultNumImages || 1),\n        modifiers,\n      )\n      const finalPrompt = mergePrompt(style.prompt, prompt, modifiers.customAdditions)\n      const mode = resolveStyleMode(style.mode)\n\n      if (mode === 'text-to-image') {\n        return handlers.executeTextToImage(\n          session,\n          finalPrompt,\n          setup.requestContext,\n          setup.displayInfo,\n          style.commandName,\n          style.commandName,\n        )\n      }\n      if (mode === 'compose-image') {\n        return handlers.executeComposeImage(\n          session,\n          finalPrompt,\n          setup.requestContext,\n          setup.displayInfo,\n          style.commandName,\n          style.commandName,\n        )\n      }\n      return handlers.executeImageToImage(\n        session,\n        img,\n        finalPrompt,\n        setup.requestContext,\n        setup.displayInfo,\n        style.commandName,\n        style.commandName,\n      )\n    })\n\n  logger.info('已注册 style 命令', {\n    commandName: style.commandName,\n    groupName: style.groupName || '',\n    mode: resolveStyleMode(style.mode),\n    modelSuffix: style.modelSuffix || '',\n  })\n  return command\n}\n\nfunction buildCommandModifiers(\n  argv: Argv,\n  imgParam: unknown,\n  config: Config,\n  style?: ResolvedStyleConfig,\n): ImageGenerationModifiers {\n  const modelIndex = buildModelMappingIndex(config.modelMappings)\n  const modifiers = parseStyleCommandModifiers(argv, imgParam, modelIndex)\n  if (!modifiers.modelMapping) {\n    const defaultMapping = resolveStyleModelMapping(style, modelIndex)\n    if (defaultMapping) modifiers.modelMapping = defaultMapping\n  }\n  return modifiers\n}\n\nfunction resolveStyleModelMapping(\n  style: ResolvedStyleConfig | undefined,\n  modelIndex: Map<string, ModelMappingConfig>,\n): ModelMappingConfig | undefined {\n  const key = normalizeSuffix(style?.modelSuffix)\n  return key ? modelIndex.get(key) : undefined\n}\n\nfunction resolveStyleMode(mode: StyleMode | undefined): StyleMode {\n  return mode || 'image-to-image'\n}\n\nfunction mergePrompt(\n  basePrompt: string,\n  prompt: string | undefined,\n  additions: string[] | undefined,\n): string {\n  return [basePrompt, prompt, ...(additions || [])]\n    .map(item => typeof item === 'string' ? item.trim() : '')\n    .filter(Boolean)\n    .join(' - ')\n}\n\nfunction parseMentionTarget(input: string): { userId: string; userName?: string } | undefined {\n  const elements = h.parse(input || '')\n  const at = h.select(elements, 'at')[0]\n  const id = at?.attrs?.id || at?.attrs?.user_id\n  if (!id || id === 'all') return undefined\n  const name = typeof at.attrs?.name === 'string' && at.attrs.name.trim()\n    ? at.attrs.name.trim()\n    : undefined\n  return {\n    userId: String(id),\n    ...(name !== undefined ? { userName: name } : {}),\n  }\n}\n\nfunction parseCreditCommandInput(input: string, commandName: string): {\n  target?: { userId: string; userName?: string }\n  amount?: number\n  reason?: string\n} {\n  const withoutCommand = String(input || '').replace(commandName, '').trim()\n  const target = parseMentionTarget(withoutCommand)\n  const withoutAtTags = withoutCommand.replace(/<at\\b[^>]*>/g, ' ').replace(/<at\\b[^>]*\\/>/g, ' ')\n  const amountMatch = withoutAtTags.match(/(?:^|\\s)([+-]?\\d+(?:\\.\\d+)?)(?:\\s|$)/)\n  const amount = amountMatch ? Number(amountMatch[1]) : undefined\n  const reason = amountMatch\n    ? withoutAtTags.slice((amountMatch.index || 0) + amountMatch[0].length).trim()\n    : ''\n  return {\n    ...(target ? { target } : {}),\n    ...(amount !== undefined && Number.isFinite(amount) ? { amount } : {}),\n    ...(reason ? { reason } : {}),\n  }\n}\n\nfunction formatLedgerEvent(event: CreditLedgerEventV2, formatCredits: (value: number) => string): string {\n  const time = typeof event.timestamp === 'string'\n    ? event.timestamp.replace('T', ' ').slice(0, 16)\n    : ''\n  const label = resolveLedgerTypeLabel(event.type)\n  const detail = event.generation?.numImages\n    ? `｜${event.generation.commandName || '生成'} ${event.generation.numImages} 张`\n    : ''\n  return `- #${event.sequence}｜${time}｜${event.userName || event.userId}｜${label} ${formatCredits(event.amount)}${detail}`\n}\n\nfunction resolveLedgerTypeLabel(type: CreditLedgerEventV2['type']): string {\n  switch (type) {\n    case 'grant': return '充值'\n    case 'consume': return '消费'\n    case 'refund': return '退款'\n    case 'adjust': return '调整'\n    case 'daily-reset': return '重置'\n    case 'migration': return '迁移'\n    default: return type || '流水'\n  }\n}\n\nfunction resolveRankingLimit(rawValue: number | undefined): number {\n  const value = typeof rawValue === 'number' && Number.isFinite(rawValue)\n    ? Math.floor(rawValue)\n    : 10\n  return Math.min(50, Math.max(1, value || 10))\n}\n\nfunction getCommandOptionNumber(argv: Argv, key: string): number | undefined {\n  const options = argv.options as Record<string, unknown> | undefined\n  const value = options?.[key]\n  return typeof value === 'number' ? value : undefined\n}\n\nfunction getCommandOptionBoolean(argv: Argv, key: string): boolean {\n  const options = argv.options as Record<string, unknown> | undefined\n  return options?.[key] === true\n}\n\nfunction resolveCommandNum(rawValue: number | undefined, fallback: number): number {\n  const value = typeof rawValue === 'number' && Number.isFinite(rawValue)\n    ? Math.floor(rawValue)\n    : Math.floor(fallback)\n  return Math.min(4, Math.max(1, value || 1))\n}\n\n","import { Argv, h } from 'koishi'\nimport type { ImageGenerationModifiers, ModelMappingConfig } from '../shared/types.js'\n\n/**\n * 规范化后缀名称\n */\nexport function normalizeSuffix(value?: string) {\n  return value?.replace(/^\\-+/, '').trim().toLowerCase()\n}\n\n/**\n * 构建模型映射索引\n */\nexport function buildModelMappingIndex(mappings?: ModelMappingConfig[]) {\n  const map = new Map<string, ModelMappingConfig>()\n  if (!Array.isArray(mappings)) return map\n  for (const mapping of mappings) {\n    const key = normalizeSuffix(mapping?.suffix)\n    if (!key || !mapping?.modelId) continue\n    map.set(key, mapping)\n  }\n  return map\n}\n\n/**\n * 解析风格命令修饰符\n */\nexport function parseStyleCommandModifiers(\n  argv: Argv,\n  imgParam: any,\n  modelMappingIndex: Map<string, ModelMappingConfig>\n): ImageGenerationModifiers {\n  // 优先从 session.content 解析原始文本，以支持被 Koishi 误吞的参数（如 -add, -4k）\n  const session = argv.session\n  let rawText = ''\n\n  if (session?.content) {\n    const elements = h.parse(session.content)\n    // 提取所有文本节点\n    rawText = h.select(elements, 'text').map((e: h) => e.attrs.content).join(' ')\n  }\n\n  // 如果没有获取到 rawText，回退到原来的逻辑\n  const argsList = rawText ? rawText.split(/\\s+/).filter(Boolean) : [...(argv.args || [])].map(arg => typeof arg === 'string' ? arg.trim() : '').filter(Boolean)\n\n  // 如果是回退逻辑，还需要处理 rest 和 imgParam\n  if (!rawText) {\n    const restStr = typeof argv.rest === 'string' ? argv.rest.trim() : ''\n    if (restStr) {\n      const restParts = restStr.split(/\\s+/).filter(Boolean)\n      argsList.push(...restParts)\n    }\n\n    if (imgParam && typeof imgParam === 'string' && !imgParam.startsWith('http') && !imgParam.startsWith('data:')) {\n      const imgParts = imgParam.split(/\\s+/).filter(Boolean)\n      argsList.push(...imgParts)\n    }\n  }\n\n  if (!argsList.length) return {}\n\n  const modifiers: ImageGenerationModifiers = { customAdditions: [] }\n  const flagCandidates: string[] = []\n\n  let index = 0\n  while (index < argsList.length) {\n    const token = argsList[index]\n    if (!token) {\n      index++\n      continue\n    }\n\n    const lower = token.toLowerCase()\n\n    // -add <文本...> 追加用户自定义段\n    if (lower === '-add') {\n      index++\n      const additionTokens: string[] = []\n      // 读取直到下一个以 - 开头的 flag 或结束\n      while (index < argsList.length) {\n        const nextToken = argsList[index]\n        if (!nextToken) {\n          index++\n          continue\n        }\n        // 如果是 flag (以 - 开头)，且不是 -add (防止重复)，且在 mapping 中存在或者是已知 flag\n        if (nextToken.startsWith('-')) {\n          // 检查是否是有效的 flag\n          const key = normalizeSuffix(nextToken)\n          if (key && modelMappingIndex.has(key)) break\n          if (nextToken.toLowerCase() === '-add') break\n        }\n        additionTokens.push(nextToken)\n        index++\n      }\n      if (additionTokens.length) {\n        modifiers.customAdditions!.push(additionTokens.join(' '))\n      }\n      continue\n    }\n\n    flagCandidates.push(token)\n    index++\n  }\n\n  // 解析已知的图像参数\n  const validResolutions = ['1k', '2k', '4k']\n  const validAspectRatios = ['1:1', '4:3', '16:9', '9:16', '3:2', '2:3']\n\n  // 正则表达式匹配自定义分辨率格式: 数字x数字 (如 1024x2048, 960x960)\n  const customResolutionRegex = /^\\d+x\\d+$/\n\n  for (const arg of flagCandidates) {\n    if (!arg.startsWith('-')) continue\n    const key = normalizeSuffix(arg)\n    if (!key) continue\n\n    // 检查是否是预设分辨率参数 (-1k, -2k, -4k)\n    if (validResolutions.includes(key)) {\n      modifiers.resolution = key as '1k' | '2k' | '4k'\n      continue\n    }\n\n    // 检查是否是自定义分辨率格式 (-1024x2048, -960x960 等)\n    if (customResolutionRegex.test(key)) {\n      modifiers.resolution = key as `${number}x${number}`\n      continue\n    }\n\n    // 检查是否是宽高比参数 (-1:1, -4:3, -16:9, -9:16, -3:2, -2:3)\n    if (validAspectRatios.includes(key)) {\n      modifiers.aspectRatio = key as '1:1' | '4:3' | '16:9' | '9:16' | '3:2' | '2:3'\n      continue\n    }\n\n    // 检查是否是模型映射\n    const mapping = modelMappingIndex.get(key)\n    if (mapping) {\n      modifiers.modelMapping = mapping\n      // 不break，继续解析其他参数\n    }\n  }\n\n  return modifiers\n}\n","/**\n * V2 命令族注册入口。\n *\n * 当前阶段注册图像核心命令、账户命令、管理员运营命令与帮助命令。\n */\n\nimport type { Context } from 'koishi'\n\nimport type { Config } from '../shared/config.js'\nimport type { ImageGenerationHandlers } from '../orchestrators/ImageGenerationOrchestrator.js'\nimport type { AiImageGeneratorService } from '../service/AiImageGeneratorService.js'\n\nimport { registerHelpCommands } from './help.js'\nimport { registerImageCommands } from './image.js'\nimport type { RegisteredImageCommands } from './image.js'\n\nexport interface RegisterAllCommandsParams {\n  ctx: Context\n  service: AiImageGeneratorService\n  handlers: ImageGenerationHandlers\n  getConfig: () => Config\n}\n\nexport interface RegisteredAllCommands {\n  image: RegisteredImageCommands\n}\n\nexport function registerAllCommands(params: RegisterAllCommandsParams): RegisteredAllCommands {\n  const image = registerImageCommands(params)\n  registerHelpCommands(params)\n  return { image }\n}\n","/**\n * ImageGenerationOrchestrator —— V2 MVP 简化版编排层。\n *\n * 与 v1 的差异：\n * - 当前阶段仅支持「文生图」与「图生图」两种核心流程。\n * - 移除 v1 中 `processComposeImageWithTimeout` / `processPresetImagesWithTimeout` 这类\n *   多分支 race 包装，改为单一线性 async/await + 顶层 Promise.race 处理超时。\n * - 不再依赖外部 `onRecordUserUsage` / `onGenerationFailure` 钩子；本编排器内部直接\n *   驱动 Service 的 `recordUsage` / 用户态封禁记录。\n * - Service 层 API 改名为 `aiImageGenerator`，所有调用通过 `AiImageGeneratorService`。\n */\n\nimport { h } from 'koishi'\nimport type { Context, Session } from 'koishi'\nimport { sanitizeString } from '../providers/utils.js'\n\nimport type { Config } from '../shared/config.js'\nimport { COMMAND_TIMEOUT_SECONDS } from '../shared/constants.js'\nimport {\n  formatPromptTimeoutError,\n  getPromptTimeoutMs,\n  getPromptTimeoutText,\n} from '../shared/prompt-timeout.js'\nimport type { GenerationCost } from '../shared/billing.js'\nimport type {\n  GenerationDisplayInfo,\n  ImageRequestContext,\n} from '../shared/types.js'\nimport type { AiImageGeneratorService } from '../service/AiImageGeneratorService.js'\nimport type { UserManager } from '../services/UserManager.js'\nimport {\n  collectImagesFromParamAndQuote,\n  parseMessageImagesAndText,\n} from '../utils/input.js'\n\nexport interface ExecuteGenerationOptions {\n  styleName: string\n  finalPrompt: string\n  imageUrls: string[]\n  numImages: number\n  requestContext?: ImageRequestContext\n  displayInfo?: GenerationDisplayInfo\n  generationCost?: GenerationCost\n  /** 用于 rememberGeneratedImages 的可选样式标记（如 '文生图' 关联的预设名） */\n  stylePreset?: string\n}\n\nexport interface CreateImageGenerationHandlersParams {\n  ctx: Context\n  service: AiImageGeneratorService\n  userManager: UserManager\n  logger: ReturnType<Context['logger']>\n  /** 始终返回最新 Config 引用（在热重载时由入口 acceptor 覆盖闭包） */\n  getConfig: () => Config\n}\n\nexport interface ImageGenerationHandlers {\n  /** 文生图主流程：从 session/prompt 取输入，校验并触发生成。 */\n  executeTextToImage(\n    session: Session,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName?: string,\n    stylePreset?: string,\n  ): Promise<string>\n\n  /** 图生图主流程：从 imgParam/quote/后续输入收集图片 + 描述，再触发生成。 */\n  executeImageToImage(\n    session: Session,\n    imgParam: unknown,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName?: string,\n    stylePreset?: string,\n  ): Promise<string>\n\n  /** 合成图主流程：收集多张图片，直到收到 prompt 文字后触发生成。 */\n  executeComposeImage(\n    session: Session,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName?: string,\n    stylePreset?: string,\n  ): Promise<string>\n\n}\n\nconst SECURITY_BLOCK_KEYWORDS = [\n  '安全',\n  '违规',\n  'content_policy',\n  'safety',\n  'blocked',\n  'safety_filter',\n]\n\nexport function createImageGenerationHandlers(\n  params: CreateImageGenerationHandlersParams,\n): ImageGenerationHandlers {\n  const { service, userManager, logger, getConfig } = params\n\n  // ---------------------------------------------------------------------------\n  // 内部工具\n  // ---------------------------------------------------------------------------\n\n  function isSecurityBlockError(error: unknown): boolean {\n    const message = error instanceof Error ? error.message : String(error ?? '')\n    const lower = message.toLowerCase()\n    return SECURITY_BLOCK_KEYWORDS.some((kw) => lower.includes(kw))\n  }\n\n  function sanitizeForLog(error: unknown): Record<string, unknown> {\n    if (error instanceof Error) {\n      return {\n        name: error.name,\n        message: sanitizeString(error.message),\n      }\n    }\n    return { value: sanitizeString(String(error ?? '')) }\n  }\n\n  function isGroupSession(session: Session): boolean {\n    return (session as Session & { isDirect?: boolean }).isDirect !== true && Boolean(session.guildId)\n  }\n\n  function formatUserScopedText(session: Session, message: string, userId: string, userName?: string): string {\n    if (!isGroupSession(session) || !userId || userId === 'unknown') return message\n    const displayName = sanitizeString((userName || userId).trim()) || userId\n    const [firstLine = '', ...restLines] = message.split('\\n')\n    const scopedFirstLine = `[${displayName}] ${firstLine}`.trimEnd()\n    return [scopedFirstLine, ...restLines].join('\\n')\n  }\n\n  async function sendFinalText(\n    session: Session,\n    message: string,\n    userId: string,\n    logLabel: string,\n    userName?: string,\n  ): Promise<string> {\n    try {\n      await session.send(formatUserScopedText(session, message, userId, userName))\n    } catch (sendError) {\n      logger.error(logLabel, {\n        userId,\n        ...sanitizeForLog(sendError),\n      })\n    }\n    return ''\n  }\n\n  /** 收集文生图输入：优先取参数；否则发起 prompt 等待用户输入。 */\n  async function collectTextInput(\n    session: Session,\n    initialPrompt: string | undefined,\n  ): Promise<{ prompt: string } | { error: string }> {\n    const config = getConfig()\n    const trimmed = typeof initialPrompt === 'string' ? initialPrompt.trim() : ''\n    if (trimmed) return { prompt: trimmed }\n\n    await session.send('请发送画面描述')\n    const msg = await session.prompt(getPromptTimeoutMs(config))\n    if (!msg) return { error: formatPromptTimeoutError(config) }\n\n    const parsed = parseMessageImagesAndText(msg)\n    if (parsed.images.length > 0) {\n      return { error: '输入不匹配｜文生图仅支持文字描述' }\n    }\n    if (!parsed.text) {\n      return { error: '已取消｜未检测到描述' }\n    }\n    return { prompt: parsed.text }\n  }\n\n  /** 收集图生图输入：先合并参数+引用图，必要时再 prompt 用户补充。 */\n  async function collectImageInput(\n    session: Session,\n    imgParam: unknown,\n    initialPrompt: string | undefined,\n  ): Promise<{ images: string[]; prompt: string } | { error: string }> {\n    const config = getConfig()\n    const collected: string[] = collectImagesFromParamAndQuote(session, imgParam)\n    let promptText = typeof initialPrompt === 'string' ? initialPrompt.trim() : ''\n\n    // 已有图片：直接使用，prompt 可由命令参数补全\n    if (collected.length > 0) {\n      if (collected.length > 1) {\n        return {\n          error: '输入不匹配｜图生图仅支持 1 张图片',\n        }\n      }\n      if (!promptText) {\n        await session.send('请发送图片修改描述')\n        const msg = await session.prompt(getPromptTimeoutMs(config))\n        if (!msg) return { error: formatPromptTimeoutError(config) }\n        const parsed = parseMessageImagesAndText(msg)\n        if (!parsed.text) return { error: '已取消｜未检测到描述' }\n        promptText = parsed.text\n      }\n      return { images: collected, prompt: promptText }\n    }\n\n    // 没有图片：循环等待用户上传图片+描述\n    await session.send(`请在 ${getPromptTimeoutText(config)}内发送 1 张图片`)\n    while (true) {\n      const msg = await session.prompt(getPromptTimeoutMs(config))\n      if (!msg) return { error: formatPromptTimeoutError(config) }\n\n      const parsed = parseMessageImagesAndText(msg)\n      if (parsed.images.length > 0) {\n        for (const img of parsed.images) {\n          if (img.attrs?.src) collected.push(img.attrs.src as string)\n        }\n        if (collected.length > 1) {\n          return { error: '输入不匹配｜图生图仅支持 1 张图片' }\n        }\n        if (parsed.text) promptText = parsed.text\n        if (!promptText) {\n          await session.send('请发送图片修改描述')\n          const msg2 = await session.prompt(getPromptTimeoutMs(config))\n          if (!msg2) return { error: formatPromptTimeoutError(config) }\n          const parsed2 = parseMessageImagesAndText(msg2)\n          if (!parsed2.text) return { error: '已取消｜未检测到描述' }\n          promptText = parsed2.text\n        }\n        return { images: collected, prompt: promptText }\n      }\n\n      if (parsed.text) {\n        return { error: '输入不匹配｜未检测到图片，请重新发起指令' }\n      }\n    }\n  }\n\n  /** 收集合成图输入：累计多张图片，直到收到 prompt 文字后执行。 */\n  async function collectComposeInput(\n    session: Session,\n    initialPrompt: string | undefined,\n  ): Promise<{ images: string[]; prompt: string } | { error: string }> {\n    const config = getConfig()\n    const collected: string[] = []\n    const initialPromptText = typeof initialPrompt === 'string' ? initialPrompt.trim() : ''\n\n    await session.send(`请在 ${getPromptTimeoutText(config)}内发送至少 2 张图片；发送合成描述后开始`)\n\n    while (true) {\n      const msg = await session.prompt(getPromptTimeoutMs(config))\n      if (!msg) return { error: formatPromptTimeoutError(config) }\n\n      const parsed = parseMessageImagesAndText(msg)\n      for (const img of parsed.images) {\n        if (img.attrs?.src && collected.length < 8) {\n          collected.push(img.attrs.src as string)\n        }\n      }\n\n      const promptText = parsed.text || initialPromptText\n      if (promptText) {\n        if (collected.length < 2) {\n          return { error: `图片不足｜至少需要 2 张，当前 ${collected.length} 张` }\n        }\n        return { images: collected, prompt: promptText }\n      }\n\n      if (collected.length >= 8) {\n        await session.send('已收到 8 张；已达上限，请发送合成描述')\n        continue\n      }\n\n      if (parsed.images.length > 0) {\n        await session.send(`已收到 ${collected.length} 张；继续发图或发送合成描述`)\n        continue\n      }\n\n      return { error: '已取消｜未检测到图片或描述' }\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // 核心生成流程\n  // ---------------------------------------------------------------------------\n\n  async function runGeneration(\n    session: Session,\n    options: ExecuteGenerationOptions,\n  ): Promise<string> {\n    const config = getConfig()\n    const userId = session.userId || 'unknown'\n    const userName = session.username || session.author?.name || userId\n    const platform = session.platform\n\n    const taskTtlMs = Math.max(COMMAND_TIMEOUT_SECONDS * 1000 + 60_000, (config.apiTimeout || 60) * 1000 * 4)\n    const requestId = userManager.startTask(userId, taskTtlMs)\n    if (!requestId) {\n      return formatUserScopedText(session, '任务进行中，请完成后再试', userId, userName)\n    }\n\n    const startedAt = Date.now()\n    const timeoutMs = COMMAND_TIMEOUT_SECONDS * 1000\n\n    // 顶层超时控制（命令级，与单次 HTTP 超时区分）\n    let timeoutFired = false\n    const checkTimeout = () => timeoutFired || Date.now() - startedAt > timeoutMs\n    const timeoutPromise = new Promise<never>((_, reject) => {\n      setTimeout(() => {\n        timeoutFired = true\n        reject(new Error(`命令执行超时（${COMMAND_TIMEOUT_SECONDS}秒）`))\n      }, timeoutMs)\n    })\n\n    try {\n      const estimatedCost = options.generationCost || service.calculateGenerationCost(options.numImages, options.requestContext)\n\n      // 1. 积分预检\n      const reservation = await service.checkAndReserveQuota(\n        userId,\n        userName,\n        estimatedCost,\n        platform,\n      )\n      if (!reservation.allowed) {\n        return formatUserScopedText(session, reservation.message || '额度不足｜无法继续生成', userId, userName)\n      }\n\n      // 2. 状态提示\n      const statusParts: string[] = []\n      if (options.displayInfo?.customAdditions?.length) {\n        statusParts.push(`- 追加｜${options.displayInfo.customAdditions.join('；')}`)\n      }\n      if (options.displayInfo?.modelId) {\n        const modelDesc = options.displayInfo.modelDescription || options.displayInfo.modelId\n        statusParts.push(`- 模型｜${modelDesc}`)\n      }\n      if (config.showCreditCostInResult) {\n        statusParts.push(`- 预计消耗｜${service.formatCredits(estimatedCost.totalCredits)}`)\n      }\n      const startMessage = statusParts.length\n        ? ['开始生成', '', `- 类型｜${options.styleName}`, ...statusParts].join('\\n')\n        : `开始生成｜${options.styleName}`\n      await session.send(formatUserScopedText(session, startMessage, userId, userName))\n\n      // 3. 流式回调：每生成一张就发送\n      const generatedImages: string[] = []\n      const onImageGenerated = async (\n        imageUrl: string,\n        index: number,\n        total: number,\n      ) => {\n        if (checkTimeout()) {\n          throw new Error('命令执行超时')\n        }\n        generatedImages.push(imageUrl)\n\n        try {\n          await session.send(h.image(imageUrl))\n        } catch (sendError) {\n          logger.error('发送图片失败', {\n            userId,\n            index: index + 1,\n            total,\n            ...sanitizeForLog(sendError),\n          })\n          throw sendError\n        }\n\n        if (total > 1 && index < total - 1) {\n          await new Promise((resolve) => setTimeout(resolve, 1000))\n        }\n      }\n\n      // 4. 实际调用 Provider（包在 race 中以兜住命令级超时）\n      const generationPromise = service.requestProviderImages(\n        options.finalPrompt,\n        options.imageUrls,\n        options.numImages,\n        options.requestContext,\n        onImageGenerated,\n      )\n\n      const allImages = await Promise.race([generationPromise, timeoutPromise])\n\n      // 5. 兜底：流式回调没触发时，统一发送\n      if (allImages && allImages.length > 0) {\n        for (const imageUrl of allImages) {\n          if (!generatedImages.includes(imageUrl)) {\n            try {\n              await session.send(h.image(imageUrl))\n              generatedImages.push(imageUrl)\n            } catch (sendError) {\n              logger.error('回退发送图片失败', {\n                userId,\n                ...sanitizeForLog(sendError),\n              })\n            }\n          }\n        }\n      }\n\n      // 6. 成功发送后按实际图片数扣费并记录用量\n      let usageResult: Awaited<ReturnType<AiImageGeneratorService['recordUsage']>> | undefined\n      if (generatedImages.length > 0) {\n        const actualCost = service.scaleGenerationCost(estimatedCost, generatedImages.length)\n        try {\n          usageResult = await service.recordUsage(\n            userId,\n            userName,\n            options.styleName,\n            actualCost,\n            platform,\n            requestId,\n          )\n        } catch (recordError) {\n          logger.error('记录用量失败', {\n            userId,\n            ...sanitizeForLog(recordError),\n          })\n          return sendFinalText(\n            session,\n            ['生成已完成但扣费记录失败', '', '- 建议｜联系管理员核对账单'].join('\\n'),\n            userId,\n            '发送扣费失败提示失败',\n            userName,\n          )\n        }\n      }\n\n      // 7. 记忆生成结果\n      if (generatedImages.length > 0) {\n        try {\n          service.rememberGeneratedImages({\n            session,\n            imageUrls: generatedImages,\n            prompt: options.finalPrompt,\n            source: 'generated',\n            ...(options.requestContext !== undefined\n              ? { requestContext: options.requestContext }\n              : {}),\n            ...(options.stylePreset !== undefined\n              ? { stylePreset: options.stylePreset }\n              : {}),\n          })\n        } catch (rememberError) {\n          logger.error('保存图像记忆失败', {\n            userId,\n            ...sanitizeForLog(rememberError),\n          })\n        }\n\n        // 可选：附带积分提示\n        // showCreditCostInResult 是总开关（\"生成完成后显示本次消耗和剩余积分\"）\n        // showQuotaInImageCommands 是子开关，在总开关开启时额外控制是否显示剩余积分明细\n        if (config.showCreditCostInResult) {\n          try {\n            const summary = usageResult?.summary || await service.getQuotaSummary(userId, userName)\n            const lines = [\n              '生成完成',\n              '',\n              `- 图片｜${generatedImages.length} 张`,\n              `- 本次消耗｜${service.formatCredits(usageResult?.consumedCredits ?? 0)}`,\n            ]\n            if (config.showQuotaInImageCommands) {\n              lines.push(\n                `- 今日免费｜${service.formatCredits(summary.dailyFreeRemaining)}`,\n                `- 已购余额｜${service.formatCredits(summary.purchasedCredits)}`,\n                `- 合计可用｜${service.formatCredits(summary.totalAvailable)}`,\n              )\n            }\n            return formatUserScopedText(session, lines.join('\\n'), userId, userName)\n          } catch {\n            return ''\n          }\n        }\n        return ''\n      }\n\n      return sendFinalText(\n        session,\n        ['生成失败', '', '- 原因｜未返回图片', '- 建议｜稍后重试或调整描述'].join('\\n'),\n        userId,\n        '发送生成失败提示失败',\n        userName,\n      )\n    } catch (error) {\n      logger.error('图像生成流程异常', {\n        userId,\n        styleName: options.styleName,\n        ...sanitizeForLog(error),\n      })\n\n      // 安全策略：内容审查相关错误记入 securityBlock\n      if (isSecurityBlockError(error)) {\n        try {\n          const result = await userManager.recordSecurityBlock(userId, config)\n          if (result.shouldWarn) {\n            return sendFinalText(\n              session,\n              ['内容安全拦截', '', '请调整描述后再试；多次触发会影响后续使用'].join('\\n'),\n              userId,\n              '发送内容安全拦截提示失败',\n              userName,\n            )\n          }\n        } catch (recordErr) {\n          logger.error('记录安全阻断失败', {\n            userId,\n            ...sanitizeForLog(recordErr),\n          })\n        }\n      }\n\n      const raw = error instanceof Error ? error.message : String(error)\n      const message = sanitizeString(raw)\n      return sendFinalText(\n        session,\n        ['生成失败', '', `- 原因｜${message}`].join('\\n'),\n        userId,\n        '发送生成失败提示失败',\n        userName,\n      )\n    } finally {\n      userManager.endTask(userId, requestId)\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // 对外 handlers\n  // ---------------------------------------------------------------------------\n\n  async function executeTextToImage(\n    session: Session,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName = '文生图',\n    stylePreset?: string,\n  ): Promise<string> {\n    const config = getConfig()\n    const collected = await collectTextInput(session, initialPrompt)\n    if ('error' in collected) return collected.error\n\n    const numImages = setupContext?.numImages || config.defaultNumImages || 1\n    return runGeneration(session, {\n      styleName,\n      finalPrompt: collected.prompt,\n      imageUrls: [],\n      numImages,\n      ...(setupContext !== undefined ? { requestContext: setupContext } : {}),\n      ...(displayInfo !== undefined ? { displayInfo } : {}),\n      generationCost: setupContext ? service.calculateGenerationCost(numImages, setupContext) : undefined,\n      ...(stylePreset !== undefined ? { stylePreset } : {}),\n    })\n  }\n\n  async function executeImageToImage(\n    session: Session,\n    imgParam: unknown,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName = '图生图',\n    stylePreset?: string,\n  ): Promise<string> {\n    const config = getConfig()\n    const collected = await collectImageInput(session, imgParam, initialPrompt)\n    if ('error' in collected) return collected.error\n\n    const numImages = setupContext?.numImages || config.defaultNumImages || 1\n    return runGeneration(session, {\n      styleName,\n      finalPrompt: collected.prompt,\n      imageUrls: collected.images,\n      numImages,\n      ...(setupContext !== undefined ? { requestContext: setupContext } : {}),\n      ...(displayInfo !== undefined ? { displayInfo } : {}),\n      generationCost: setupContext ? service.calculateGenerationCost(numImages, setupContext) : undefined,\n      ...(stylePreset !== undefined ? { stylePreset } : {}),\n    })\n  }\n\n  async function executeComposeImage(\n    session: Session,\n    initialPrompt: string | undefined,\n    setupContext?: ImageRequestContext,\n    displayInfo?: GenerationDisplayInfo,\n    styleName = '合成图',\n    stylePreset?: string,\n  ): Promise<string> {\n    const config = getConfig()\n    const collected = await collectComposeInput(session, initialPrompt)\n    if ('error' in collected) return collected.error\n\n    const numImages = setupContext?.numImages || config.defaultNumImages || 1\n    return runGeneration(session, {\n      styleName,\n      finalPrompt: collected.prompt,\n      imageUrls: collected.images,\n      numImages,\n      ...(setupContext !== undefined ? { requestContext: setupContext } : {}),\n      ...(displayInfo !== undefined ? { displayInfo } : {}),\n      generationCost: setupContext ? service.calculateGenerationCost(numImages, setupContext) : undefined,\n      ...(stylePreset !== undefined ? { stylePreset } : {}),\n    })\n  }\n\n  return {\n    executeTextToImage,\n    executeImageToImage,\n    executeComposeImage,\n  }\n}\n","import { Context } from 'koishi'\nimport Jimp from 'jimp'\n\n/**\n * 清理对象中的敏感信息（API KEY、密钥等）\n */\nexport function sanitizeError(error: any): any {\n  if (!error) return error\n\n  // Error 对象的 message/stack/name 多为不可枚举属性，需显式提取\n  if (error instanceof Error) {\n    return {\n      name: sanitizeString(error.name || 'Error'),\n      message: sanitizeString(error.message || ''),\n      stack: sanitizeString(error.stack || '')\n    }\n  }\n\n  // 如果是字符串，尝试清理其中的 API KEY\n  if (typeof error === 'string') {\n    return sanitizeString(error)\n  }\n\n  // 如果是数组，递归处理每个元素\n  if (Array.isArray(error)) {\n    return error.map(item => sanitizeError(item))\n  }\n\n  // 如果是对象，创建副本并清理敏感字段\n  if (typeof error === 'object') {\n    const sanitized: any = {}\n\n    for (const key in error) {\n      const lowerKey = key.toLowerCase()\n\n      // 跳过敏感字段\n      if (\n        lowerKey.includes('apikey') ||\n        lowerKey.includes('api_key') ||\n        lowerKey.includes('api-key') ||\n        lowerKey === 'key' ||\n        lowerKey === 'authorization' ||\n        lowerKey === 'token' ||\n        lowerKey === 'secret' ||\n        lowerKey === 'password'\n      ) {\n        sanitized[key] = '[REDACTED]'\n        continue\n      }\n\n      // 递归处理嵌套对象\n      sanitized[key] = sanitizeError(error[key])\n    }\n\n    return sanitized\n  }\n\n  return error\n}\n\n/**\n * 清理字符串中的 API KEY 模式\n */\nexport function sanitizeString(str: string): string {\n  if (typeof str !== 'string') return str\n\n  // 匹配常见的 API KEY 模式并替换\n  return str\n    // 标准格式（key=xxx, apikey=xxx 等）- 降低长度阈值到 10 字符\n    .replace(/key[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'key=\"[REDACTED]\"')\n    .replace(/apikey[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'apikey=\"[REDACTED]\"')\n    .replace(/api_key[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'api_key=\"[REDACTED]\"')\n    .replace(/api-key[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'api-key=\"[REDACTED]\"')\n    .replace(/x-api-key[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'x-api-key=\"[REDACTED]\"')\n\n    // Authorization 头\n    .replace(/authorization[\"'\\s:=]+(Bearer\\s+)?([a-zA-Z0-9_-]{10,})/gi, 'authorization=\"[REDACTED]\"')\n    .replace(/Bearer\\s+([a-zA-Z0-9_-]{10,})/gi, 'Bearer [REDACTED]')\n\n    // URL 中的 key 参数（?key=xxx 或 &key=xxx）\n    .replace(/([?&])key=([a-zA-Z0-9_-]{10,})/gi, '$1key=[REDACTED]')\n    .replace(/([?&])apikey=([a-zA-Z0-9_-]{10,})/gi, '$1apikey=[REDACTED]')\n    .replace(/([?&])api_key=([a-zA-Z0-9_-]{10,})/gi, '$1api_key=[REDACTED]')\n    .replace(/([?&])token=([a-zA-Z0-9_-]{10,})/gi, '$1token=[REDACTED]')\n    .replace(/([?&])access_token=([a-zA-Z0-9_-]{10,})/gi, '$1access_token=[REDACTED]')\n\n    // 常见云服务密钥模式\n    .replace(/sk-[a-zA-Z0-9]{20,}/gi, '[REDACTED-SK]')  // OpenAI 风格\n    .replace(/AIza[a-zA-Z0-9_-]{30,}/gi, '[REDACTED-GAPI]')  // Google API Key\n\n    // Secret 和 Password 字段\n    .replace(/secret[\"'\\s:=]+([a-zA-Z0-9_-]{10,})/gi, 'secret=\"[REDACTED]\"')\n    .replace(/password[\"'\\s:=]+([^\\s\"']{4,})/gi, 'password=\"[REDACTED]\"')\n}\n\n/**\n * 下载图片并转换为 Base64\n * 包含 MIME 类型检测和大小限制\n * 支持 Koishi 内部协议 URL (如 internal:lark/... internal:onebot/... 等)\n */\nexport async function downloadImageAsBase64(\n  ctx: Context,\n  url: string,\n  timeout: number,\n  logger: any,\n  maxSize: number = 10 * 1024 * 1024 // 默认最大 10MB\n): Promise<{ data: string, mimeType: string }> {\n  try {\n    let buffer: Buffer\n\n    // 检查是否为 Koishi 内部协议 URL（如 internal:lark/xxx, internal:onebot/xxx 等）\n    if (url.startsWith('internal:')) {\n      logger.debug('检测到 Koishi 内部协议 URL，使用 ctx.http.file() 获取', { url: url.substring(0, 80) })\n      try {\n        // 使用 ctx.http.file() 获取内部资源\n        // 这是 Koishi/Satori 处理内部资源引用的标准方式\n        const fileResult = await ctx.http.file(url, { timeout: timeout * 1000 })\n        // ctx.http.file() 返回 { data: ArrayBuffer, type: string, filename?: string }\n        buffer = Buffer.from(fileResult.data)\n        logger.info('Koishi 内部协议资源获取成功', {\n          url: url.substring(0, 80),\n          size: buffer.length,\n          type: fileResult.type\n        })\n      } catch (internalError: any) {\n        logger.error('Koishi 内部协议资源获取失败', {\n          url: url.substring(0, 80),\n          error: sanitizeError(internalError),\n          message: internalError?.message\n        })\n        throw new Error(`无法获取飞书/Lark 图片资源: ${internalError?.message || '未知错误'}`)\n      }\n    } else {\n      // 标准 HTTP/HTTPS URL\n      const response = await ctx.http.get(url, {\n        responseType: 'arraybuffer',\n        timeout: timeout * 1000,\n        headers: {\n          'Accept': 'image/*'\n        }\n      })\n      buffer = Buffer.from(response)\n    }\n    if (buffer.length > maxSize) {\n      throw new Error(`图片大小超过限制 (${(maxSize / 1024 / 1024).toFixed(1)}MB)`)\n    }\n\n    const base64 = buffer.toString('base64')\n\n    // 优先从 Buffer 的魔数检测 MIME 类型\n    let mimeType = 'image/jpeg' // 默认\n\n    // 简单的魔数检测\n    if (buffer.length > 4) {\n      if (buffer[0] === 0x89 && buffer[1] === 0x50 && buffer[2] === 0x4E && buffer[3] === 0x47) {\n        mimeType = 'image/png'\n      } else if (buffer[0] === 0xFF && buffer[1] === 0xD8 && buffer[2] === 0xFF) {\n        mimeType = 'image/jpeg'\n      } else if (buffer[0] === 0x47 && buffer[1] === 0x49 && buffer[2] === 0x46) {\n        mimeType = 'image/gif'\n      } else if (buffer[0] === 0x52 && buffer[1] === 0x49 && buffer[2] === 0x46 && buffer[3] === 0x46 &&\n        buffer[8] === 0x57 && buffer[9] === 0x45 && buffer[10] === 0x42 && buffer[11] === 0x50) {\n        mimeType = 'image/webp'\n      }\n    }\n\n    // 如果无法通过魔数检测，尝试使用后缀名\n    if (mimeType === 'image/jpeg') { // 如果仍是默认值，尝试优化\n      const urlLower = url.toLowerCase()\n      if (urlLower.endsWith('.png')) {\n        mimeType = 'image/png'\n      } else if (urlLower.endsWith('.webp')) {\n        mimeType = 'image/webp'\n      } else if (urlLower.endsWith('.gif')) {\n        mimeType = 'image/gif'\n      }\n    }\n\n    // 特殊处理 GIF：Gemini 不支持 GIF，转为 PNG（自动取第一帧）\n    if (mimeType === 'image/gif') {\n      try {\n        logger.debug('检测到 GIF 图片，正在转换为 PNG', { url })\n        const image = await Jimp.read(buffer)\n        const pngBuffer = await image.getBufferAsync(Jimp.MIME_PNG)\n\n        // 更新 base64 和 mimeType\n        const pngBase64 = pngBuffer.toString('base64')\n        logger.info('GIF 已转换为 PNG', {\n          originalSize: buffer.length,\n          newSize: pngBuffer.length,\n          width: image.getWidth(),\n          height: image.getHeight()\n        })\n\n        return { data: pngBase64, mimeType: 'image/png' }\n      } catch (conversionError: any) {\n        logger.warn('GIF 转换失败，尝试原样发送', { error: conversionError?.message })\n        // 如果转换失败，降级回原样发送（虽然可能会由于 API 不支持而失败）\n      }\n    }\n\n    logger.debug('图片下载并转换为Base64', { url, mimeType, size: base64.length })\n    return { data: base64, mimeType }\n  } catch (error: any) {\n    logger.error('下载图片失败', { url, error: sanitizeError(error) })\n\n    if (error?.message?.includes('图片大小超过限制')) {\n      throw error\n    }\n    throw new Error('下载图片失败，请检查图片链接是否有效')\n  }\n}\n","import type { Config } from './config.js'\n\nexport function getPromptTimeoutSeconds(config: Pick<Config, 'apiTimeout'>) {\n  return Math.max(1, Math.round(config.apiTimeout))\n}\n\nexport function getPromptTimeoutMs(config: Pick<Config, 'apiTimeout'>) {\n  return getPromptTimeoutSeconds(config) * 1000\n}\n\nexport function getPromptTimeoutText(config: Pick<Config, 'apiTimeout'>) {\n  return `${getPromptTimeoutSeconds(config)} 秒`\n}\n\nexport function formatPromptTimeoutError(config: Pick<Config, 'apiTimeout'>, suffix = '') {\n  return `等待超时｜${getPromptTimeoutText(config)}${suffix}`\n}\n","import { Session, h } from 'koishi'\n\nexport function collectImagesFromParamAndQuote(session: Session, imgParam: any): string[] {\n  const images: string[] = []\n\n  if (imgParam) {\n    if (typeof imgParam === 'object' && imgParam.attrs?.src) {\n      images.push(imgParam.attrs.src)\n    } else if (typeof imgParam === 'string') {\n      if (imgParam.startsWith('http') || imgParam.startsWith('data:')) {\n        images.push(imgParam)\n      }\n    }\n  }\n\n  if (session.quote?.elements) {\n    const quoteImages = h.select(session.quote.elements, 'img')\n    for (const img of quoteImages) {\n      if (img.attrs.src) images.push(img.attrs.src)\n    }\n  }\n\n  return images\n}\n\nexport function parseMessageImagesAndText(message: string) {\n  const elements = h.parse(message)\n  const images = h.select(elements, 'img')\n  const text = h.select(elements, 'text').map((e: h) => e.attrs.content).join(' ').trim()\n  return { images, text }\n}\n","/**\n * Provider 统一错误体系（Phase 2 / 7.4 节）\n *\n * 所有 Provider 子类抛出的错误都应包装为 ProviderError 的某个子类。\n * 上层（Service / Orchestrator）只需要：\n *   - 检查 instanceof ProviderError 判定是否来自 Provider 层\n *   - 检查 .retryable 判断是否值得重试\n *   - 读取 .code / .providerName 输出友好日志\n */\n\n/** 错误码：用于上层做精确判断（Schema 化错误处理） */\nexport type ProviderErrorCode =\n  | 'AUTHENTICATION'\n  | 'RATE_LIMIT'\n  | 'CONTENT_FILTER'\n  | 'TIMEOUT'\n  | 'PROVIDER_UNAVAILABLE'\n  | 'BAD_REQUEST'\n  | 'PARSE_ERROR'\n  | 'UNKNOWN'\n\nexport interface ProviderErrorOptions {\n  /** 出错的 Provider 名（如 'openai'） */\n  providerName?: string\n  /** 上游 HTTP 状态码（若有） */\n  statusCode?: number\n  /** 是否值得重试（默认按 code 判断） */\n  retryable?: boolean\n  /** 原始错误（保留 cause 链） */\n  cause?: unknown\n  /** 上下文键值对（log 用，不要包含密钥） */\n  context?: Record<string, unknown>\n}\n\n/**\n * Provider 层基础错误。\n * 业务代码不要直接 throw 该类，应使用具体子类。\n */\nexport class ProviderError extends Error {\n  readonly code: ProviderErrorCode\n  readonly providerName: string | undefined\n  readonly statusCode: number | undefined\n  readonly retryable: boolean\n  override readonly cause: unknown\n  readonly context: Record<string, unknown>\n\n  constructor(code: ProviderErrorCode, message: string, options: ProviderErrorOptions = {}) {\n    super(message)\n    this.name = 'ProviderError'\n    this.code = code\n    this.providerName = options.providerName\n    this.statusCode = options.statusCode\n    this.retryable = options.retryable ?? defaultRetryable(code)\n    this.cause = options.cause\n    this.context = options.context ?? {}\n  }\n\n  /** 转结构化日志对象（不含敏感字段） */\n  toLogObject(): Record<string, unknown> {\n    return {\n      name: this.name,\n      code: this.code,\n      message: this.message,\n      providerName: this.providerName,\n      statusCode: this.statusCode,\n      retryable: this.retryable,\n      context: this.context,\n    }\n  }\n}\n\n/** 401/403：API key 无效或权限不足 */\nexport class AuthenticationError extends ProviderError {\n  constructor(message: string, options: ProviderErrorOptions = {}) {\n    super('AUTHENTICATION', message, { retryable: false, ...options })\n    this.name = 'AuthenticationError'\n  }\n}\n\n/** 429：速率限制或配额耗尽 */\nexport class RateLimitError extends ProviderError {\n  /** 服务端建议的重试间隔（秒），若 header 中给出 */\n  readonly retryAfterSeconds: number | undefined\n\n  constructor(\n    message: string,\n    options: ProviderErrorOptions & { retryAfterSeconds?: number } = {}\n  ) {\n    super('RATE_LIMIT', message, { retryable: true, ...options })\n    this.name = 'RateLimitError'\n    this.retryAfterSeconds = options.retryAfterSeconds\n  }\n}\n\n/** 内容审核拦截（Provider 主动拒绝；用户行为问题，不应自动重试） */\nexport class ContentFilterError extends ProviderError {\n  constructor(message: string, options: ProviderErrorOptions = {}) {\n    super('CONTENT_FILTER', message, { retryable: false, ...options })\n    this.name = 'ContentFilterError'\n  }\n}\n\n/** 请求超时（含网络层和 API 业务超时） */\nexport class TimeoutError extends ProviderError {\n  /** 触发的超时阈值（秒） */\n  readonly timeoutSeconds: number | undefined\n\n  constructor(\n    message: string,\n    options: ProviderErrorOptions & { timeoutSeconds?: number } = {}\n  ) {\n    super('TIMEOUT', message, { retryable: true, ...options })\n    this.name = 'TimeoutError'\n    this.timeoutSeconds = options.timeoutSeconds\n  }\n}\n\n/** Provider 不可用：5xx、网络断开、DNS 失败等 */\nexport class ProviderUnavailableError extends ProviderError {\n  constructor(message: string, options: ProviderErrorOptions = {}) {\n    super('PROVIDER_UNAVAILABLE', message, { retryable: true, ...options })\n    this.name = 'ProviderUnavailableError'\n  }\n}\n\n/** 400/422：请求参数非法 */\nexport class BadRequestError extends ProviderError {\n  constructor(message: string, options: ProviderErrorOptions = {}) {\n    super('BAD_REQUEST', message, { retryable: false, ...options })\n    this.name = 'BadRequestError'\n  }\n}\n\n/** 响应格式异常（解析阶段抛出） */\nexport class ParseError extends ProviderError {\n  constructor(message: string, options: ProviderErrorOptions = {}) {\n    super('PARSE_ERROR', message, { retryable: false, ...options })\n    this.name = 'ParseError'\n  }\n}\n\n/**\n * 把任意错误归一化为 ProviderError 子类。\n *\n * - 已经是 ProviderError 子类时直接返回\n * - 含有 response.status 等字段的 HTTPError 按状态码映射\n * - 其他未知错误返回 ProviderError(code='UNKNOWN')\n */\nexport function normalizeProviderError(\n  error: unknown,\n  providerName?: string\n): ProviderError {\n  if (error instanceof ProviderError) return error\n\n  const err = error as\n    | (Error & {\n      response?: { status?: number; data?: unknown; headers?: unknown }\n      status?: number\n      code?: string\n      errno?: string | number\n      syscall?: string\n      hostname?: string\n      host?: string\n      address?: string\n      port?: string | number\n      cause?: unknown\n    })\n    | undefined\n\n  const message = err?.message ?? '未知错误'\n  const statusCode = err?.response?.status ?? err?.status\n\n  const baseOptions: ProviderErrorOptions = {\n    providerName,\n    statusCode,\n    cause: error,\n    context: buildErrorContext(error),\n  }\n\n  if (statusCode === 401 || statusCode === 403) {\n    return new AuthenticationError(message, baseOptions)\n  }\n  if (statusCode === 429) {\n    return new RateLimitError(message, baseOptions)\n  }\n  if (statusCode === 400 || statusCode === 422) {\n    return new BadRequestError(message, baseOptions)\n  }\n  if (typeof statusCode === 'number' && statusCode >= 500) {\n    return new ProviderUnavailableError(message, baseOptions)\n  }\n\n  // Node fetch / undici 网络层错误\n  const code = err?.code\n  if (\n    code === 'ETIMEDOUT' ||\n    code === 'ECONNABORTED' ||\n    /timeout/i.test(message)\n  ) {\n    return new TimeoutError(message, baseOptions)\n  }\n  if (\n    code === 'ECONNREFUSED' ||\n    code === 'ENOTFOUND' ||\n    code === 'EAI_AGAIN' ||\n    /fetch.*failed/i.test(message)\n  ) {\n    return new ProviderUnavailableError(message, baseOptions)\n  }\n  \n  return new ProviderError('UNKNOWN', message, baseOptions)\n}\n\nfunction buildErrorContext(error: unknown): Record<string, unknown> {\n  const context: Record<string, unknown> = {}\n  collectErrorContext(context, error, 'error')\n  return context\n}\n\nfunction collectErrorContext(context: Record<string, unknown>, error: unknown, prefix: string) {\n  if (!error || typeof error !== 'object') return\n\n  const err = error as {\n    name?: unknown\n    message?: unknown\n    code?: unknown\n    errno?: unknown\n    syscall?: unknown\n    hostname?: unknown\n    host?: unknown\n    address?: unknown\n    port?: unknown\n    status?: unknown\n    response?: { status?: unknown; data?: unknown }\n    cause?: unknown\n  }\n\n  for (const key of ['name', 'message', 'code', 'errno', 'syscall', 'hostname', 'host', 'address', 'port', 'status'] as const) {\n    const value = err[key]\n    if (typeof value === 'string' || typeof value === 'number') {\n      context[`${prefix}.${key}`] = sanitizeDiagnosticString(String(value))\n    }\n  }\n\n  if (typeof err.response?.status === 'number') {\n    context[`${prefix}.responseStatus`] = err.response.status\n  }\n  if (err.response?.data !== undefined) {\n    context[`${prefix}.responseData`] = truncateDiagnostic(sanitizeDiagnosticValue(err.response.data), 800)\n  }\n\n  if (err.cause && err.cause !== error) {\n    collectErrorContext(context, err.cause, `${prefix}.cause`)\n  }\n}\n\nfunction sanitizeDiagnosticValue(value: unknown): unknown {\n  if (typeof value === 'string') return sanitizeDiagnosticString(value)\n  if (!value || typeof value !== 'object') return value\n  if (Array.isArray(value)) return value.slice(0, 20).map(sanitizeDiagnosticValue)\n\n  const result: Record<string, unknown> = {}\n  for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n    const lower = key.toLowerCase()\n    if (lower.includes('authorization') || lower.includes('api-key') || lower.includes('apikey') || lower.includes('token') || lower.includes('secret') || lower.includes('password')) {\n      result[key] = '[REDACTED]'\n      continue\n    }\n    result[key] = sanitizeDiagnosticValue(item)\n  }\n  return result\n}\n\nfunction sanitizeDiagnosticString(value: string): string {\n  return value\n    .replace(/Bearer\\s+[A-Za-z0-9._~+\\-/=]+/gi, 'Bearer [REDACTED]')\n    .replace(/(api[_-]?key=)[^&\\s]+/gi, '$1[REDACTED]')\n    .replace(/(key=)[^&\\s]+/gi, '$1[REDACTED]')\n    .replace(/(token=)[^&\\s]+/gi, '$1[REDACTED]')\n}\n\nfunction truncateDiagnostic(value: unknown, max: number): string {\n  let text: string\n  try {\n    text = typeof value === 'string' ? value : JSON.stringify(value)\n  } catch {\n    text = String(value)\n  }\n  return text.length <= max ? text : `${text.slice(0, max)}…`\n}\n\nfunction defaultRetryable(code: ProviderErrorCode): boolean {\n  switch (code) {\n    case 'RATE_LIMIT':\n    case 'TIMEOUT':\n    case 'PROVIDER_UNAVAILABLE':\n      return true\n    case 'AUTHENTICATION':\n    case 'CONTENT_FILTER':\n    case 'BAD_REQUEST':\n    case 'PARSE_ERROR':\n      return false\n    default:\n      return false\n  }\n}\n","import { ProviderError, RateLimitError, normalizeProviderError } from '../errors.js'\n\n/**\n * 重试策略（7.11.2 节）\n *\n * 默认仅对 retryable 的 ProviderError 重试。其他错误类型直接向上抛。\n */\n\nexport interface RetryOptions {\n  /** 最大重试次数（不含首次调用），默认 2 */\n  maxRetries?: number\n  /** 初始退避（毫秒），默认 500 */\n  initialDelayMs?: number\n  /** 最大退避（毫秒），默认 8000 */\n  maxDelayMs?: number\n  /** 退避乘数，默认 2 */\n  backoffFactor?: number\n  /** 抖动比例（0~1），默认 0.2 */\n  jitter?: number\n  /** 自定义重试判定（覆盖默认行为） */\n  shouldRetry?: (error: ProviderError, attempt: number) => boolean\n  /** 每次重试前回调（用于日志） */\n  onRetry?: (error: ProviderError, attempt: number, delayMs: number) => void\n  /** Provider 名（normalizeProviderError 用） */\n  providerName?: string\n}\n\n/**\n * 用指数退避策略重试 fn。\n *\n * @example\n * const images = await withRetry(\n *   () => provider.callApi(...),\n *   { maxRetries: 3, providerName: 'openai' }\n * )\n */\nexport async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions = {}): Promise<T> {\n  const {\n    maxRetries = 2,\n    initialDelayMs = 500,\n    maxDelayMs = 8000,\n    backoffFactor = 2,\n    jitter = 0.2,\n    shouldRetry,\n    onRetry,\n    providerName,\n  } = options\n\n  let attempt = 0\n  let lastError: ProviderError | undefined\n\n  // attempt 包含首次：0 = 初次，1..maxRetries = 重试\n  while (attempt <= maxRetries) {\n    try {\n      return await fn()\n    } catch (rawError) {\n      const err = normalizeProviderError(rawError, providerName)\n      lastError = err\n\n      const canRetry = shouldRetry ? shouldRetry(err, attempt) : err.retryable\n      if (!canRetry || attempt >= maxRetries) {\n        throw err\n      }\n\n      // 计算下次退避：优先尊重 RateLimitError 的 retryAfterSeconds\n      let delayMs: number\n      if (err instanceof RateLimitError && err.retryAfterSeconds !== undefined) {\n        delayMs = err.retryAfterSeconds * 1000\n      } else {\n        const base = initialDelayMs * Math.pow(backoffFactor, attempt)\n        const capped = Math.min(base, maxDelayMs)\n        const jitterAmount = capped * jitter * (Math.random() * 2 - 1)\n        delayMs = Math.max(0, Math.round(capped + jitterAmount))\n      }\n\n      onRetry?.(err, attempt + 1, delayMs)\n\n      await sleep(delayMs)\n      attempt += 1\n    }\n  }\n\n  // 不应到达此处；为类型安全保留\n  throw lastError ?? new ProviderError('UNKNOWN', '重试逻辑出现未预期的退出', { providerName })\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","import { TimeoutError } from '../errors.js'\n\n/**\n * 超时策略（7.11.1 节）\n *\n * 提供与 AbortController 兼容的统一超时包装。所有 Provider 都应使用本工具，\n * 而非直接 setTimeout，避免出现\"超时但 promise 仍在 resolve\"的双触发问题。\n */\n\nexport interface WithTimeoutOptions {\n  /** 超时阈值（毫秒） */\n  timeoutMs: number\n  /** 超时错误信息（不含敏感内容） */\n  message?: string\n  /** 用于日志识别的 Provider 名 */\n  providerName?: string\n}\n\n/**\n * 用 timeout 包裹 promise；超时则抛出 TimeoutError。\n *\n * 注意：本函数不会取消底层的网络请求，只会让外层不再等待。如果需要取消，\n * 调用方应自行管理 AbortController（参见 withAbortableTimeout）。\n */\nexport function withTimeout<T>(promise: Promise<T>, options: WithTimeoutOptions): Promise<T> {\n  const { timeoutMs, message, providerName } = options\n\n  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n    return promise\n  }\n\n  let timer: ReturnType<typeof setTimeout> | undefined\n\n  const timeoutPromise = new Promise<never>((_, reject) => {\n    timer = setTimeout(() => {\n      reject(\n        new TimeoutError(message ?? `请求超时（${Math.round(timeoutMs / 1000)}秒）`, {\n          providerName,\n          timeoutSeconds: Math.round(timeoutMs / 1000),\n        })\n      )\n    }, timeoutMs)\n  })\n\n  return Promise.race([promise, timeoutPromise]).finally(() => {\n    if (timer !== undefined) clearTimeout(timer)\n  })\n}\n\n/**\n * 带 AbortController 的超时包装：超时时主动 abort，释放底层连接。\n *\n * @example\n * const ac = new AbortController()\n * const result = await withAbortableTimeout(\n *   (signal) => ctx.http.post(url, body, { signal }),\n *   { timeoutMs: 30_000 }\n * )\n */\nexport async function withAbortableTimeout<T>(\n  fn: (signal: AbortSignal) => Promise<T>,\n  options: WithTimeoutOptions\n): Promise<T> {\n  const { timeoutMs, message, providerName } = options\n  const ac = new AbortController()\n\n  if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n    return fn(ac.signal)\n  }\n\n  const timer = setTimeout(() => ac.abort(), timeoutMs)\n\n  try {\n    return await fn(ac.signal)\n  } catch (err) {\n    if (ac.signal.aborted) {\n      throw new TimeoutError(message ?? `请求超时（${Math.round(timeoutMs / 1000)}秒）`, {\n        providerName,\n        timeoutSeconds: Math.round(timeoutMs / 1000),\n        cause: err,\n      })\n    }\n    throw err\n  } finally {\n    clearTimeout(timer)\n  }\n}\n","export type LogLevel = 'simple' | 'detail' | 'info' | 'debug'\n\nexport function normalizeLogLevel(value: unknown): 'simple' | 'detail' {\n  return value === 'detail' || value === 'debug' ? 'detail' : 'simple'\n}\n\nexport function isDetailLogLevel(value: unknown): boolean {\n  return normalizeLogLevel(value) === 'detail'\n}\n","import type { Context, Logger } from 'koishi'\n\nimport {\n  AuthenticationError,\n  BadRequestError,\n  ContentFilterError,\n  ProviderError,\n  RateLimitError,\n  TimeoutError,\n  normalizeProviderError,\n} from './errors.js'\nimport { sanitizeError } from './utils.js'\nimport type {\n  BaseProviderOptions,\n  ImageGeneratedCallback,\n  ImageGenerationOptions,\n  ImageProvider,\n} from './types.js'\nimport { withRetry, type RetryOptions } from './policies/retry.js'\nimport { withTimeout } from './policies/timeout.js'\nimport { isDetailLogLevel, normalizeLogLevel } from '../shared/logging.js'\n\n/**\n * BaseImageProvider（7.2 节）\n *\n * 所有图像 Provider 子类的基类，统一负责：\n * - 构造参数管理\n * - 请求头构造\n * - 超时 / 重试 / 错误归一化\n * - 流式回调安全调用\n *\n * 子类只需要实现 generateImages() 即可。\n */\nexport abstract class BaseImageProvider implements ImageProvider {\n  /** Provider 标识，由子类设定 */\n  abstract readonly name: string\n\n  protected readonly ctx: Context\n  protected readonly logger: Logger\n  protected readonly apiKey: string\n  protected readonly modelId: string\n  protected readonly apiBase: string | undefined\n  protected readonly apiTimeoutSeconds: number\n  protected readonly logLevel: BaseProviderOptions['logLevel']\n  protected readonly extraHeaders: Record<string, string>\n\n  constructor(options: BaseProviderOptions) {\n    this.ctx = options.ctx\n    this.apiKey = options.apiKey\n    this.modelId = options.modelId\n    this.apiBase = options.apiBase?.replace(/\\/$/, '') || undefined\n    this.apiTimeoutSeconds = options.apiTimeout\n    this.logLevel = normalizeLogLevel(options.logLevel)\n    this.extraHeaders = options.extraHeaders ?? {}\n    this.logger = options.ctx.logger(options.loggerName ?? 'aka-ai-image-generator:provider')\n  }\n\n  abstract generateImages(\n    prompt: string,\n    imageUrls: string | string[],\n    numImages: number,\n    options?: ImageGenerationOptions,\n    onImageGenerated?: ImageGeneratedCallback\n  ): Promise<string[]>\n\n  // -------- 通用工具 --------\n\n  protected shouldLogDetail(): boolean {\n    return isDetailLogLevel(this.logLevel)\n  }\n\n  /** 构造常规 Bearer 鉴权头 */\n  protected buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n    return {\n      'Content-Type': 'application/json',\n      Authorization: `Bearer ${this.apiKey}`,\n      ...this.extraHeaders,\n      ...extra,\n    }\n  }\n\n  /** 获取以毫秒为单位的超时阈值 */\n  protected getTimeoutMs(): number {\n    return Math.max(0, this.apiTimeoutSeconds * 1000)\n  }\n\n  /**\n   * 用 timeout 包装 promise；超时抛 TimeoutError。\n   *\n   * 子类一般不必直接调用，可通过 callApi 的封装。\n   */\n  protected withTimeout<T>(promise: Promise<T>, message?: string): Promise<T> {\n    return withTimeout(promise, {\n      timeoutMs: this.getTimeoutMs(),\n      message,\n      providerName: this.name,\n    })\n  }\n\n  /**\n   * 在 retry + timeout 包装下执行一次 API 调用。\n   *\n   * @param fn 实际的 HTTP 请求执行体\n   * @param retryOptions 自定义重试配置（可省略）\n   */\n  protected async callApi<T>(\n    fn: () => Promise<T>,\n    retryOptions?: Omit<RetryOptions, 'providerName' | 'onRetry'>\n  ): Promise<T> {\n    return withRetry(\n      () =>\n        this.withTimeout(fn()).catch((err: unknown) => {\n          throw this.handleProviderError(err)\n        }),\n      {\n        providerName: this.name,\n        onRetry: (err, attempt, delayMs) => {\n          this.logger.warn(\n            'provider=%s event=retry attempt=%d delay_ms=%d code=%s status=%s retryable=%s message=%s context=%s',\n            this.name,\n            attempt,\n            delayMs,\n            err.code,\n            err.statusCode ?? '-',\n            err.retryable,\n            err.message,\n            safeStringify(err.context),\n          )\n        },\n        ...retryOptions,\n      }\n    )\n  }\n\n  /**\n   * 把异常归一化为 ProviderError 子类，并把内容审核类的关键字识别成 ContentFilterError。\n   * 子类如果需要识别更具体的错误码，可重写本方法。\n   */\n  protected handleProviderError(error: unknown): ProviderError {\n    const normalized = normalizeProviderError(error, this.name)\n\n    // 已经是具体子类则直接返回\n    if (\n      normalized instanceof AuthenticationError ||\n      normalized instanceof RateLimitError ||\n      normalized instanceof BadRequestError ||\n      normalized instanceof TimeoutError ||\n      normalized instanceof ContentFilterError\n    ) {\n      return normalized\n    }\n\n    // 内容审核兜底（不同 Provider 关键词不同；子类可覆盖）\n    if (isContentFilterMessage(normalized.message)) {\n      return new ContentFilterError(normalized.message, {\n        providerName: this.name,\n        statusCode: normalized.statusCode,\n        cause: normalized.cause,\n      })\n    }\n\n    return normalized\n  }\n\n  /**\n   * 流式回调安全包装：把回调失败转换为 Promise.reject，但不影响 Provider 内部状态。\n   */\n  protected async fireImageCallback(\n    onImageGenerated: ImageGeneratedCallback | undefined,\n    imageUrl: string,\n    index: number,\n    total: number\n  ): Promise<void> {\n    if (!onImageGenerated) return\n    try {\n      await onImageGenerated(imageUrl, index, total)\n    } catch (err) {\n      this.logger.error('provider=%s event=callback_failed index=%d total=%d error=%s', this.name, index, total, describeError(sanitizeError(err)))\n      throw err\n    }\n  }\n}\n\n// -------- internal helpers --------\n\nconst CONTENT_FILTER_KEYWORDS = [\n  'safety system',\n  'content_policy_violation',\n  'content policy',\n  'safety_violation',\n  'image_generation_user_error',\n  'inappropriate',\n  '违规',\n  '违反',\n  '内容审核',\n]\n\nfunction isContentFilterMessage(message: string): boolean {\n  const lower = message.toLowerCase()\n  return CONTENT_FILTER_KEYWORDS.some((kw) => lower.includes(kw.toLowerCase()))\n}\n\nfunction describeError(error: unknown): string {\n  if (error instanceof Error) return `${error.name}: ${error.message}`\n  if (typeof error === 'string') return error\n  try {\n    return JSON.stringify(error)\n  } catch {\n    return String(error)\n  }\n}\n\nfunction safeStringify(value: unknown): string {\n  try {\n    return JSON.stringify(value ?? {})\n  } catch {\n    return String(value)\n  }\n}\n","import type { Context } from 'koishi'\n\nimport { BaseImageProvider } from './base.js'\nimport {\n  BadRequestError,\n  ContentFilterError,\n  ParseError,\n  ProviderError,\n} from './errors.js'\nimport type {\n  BaseProviderOptions,\n  ImageGeneratedCallback,\n  ImageGenerationOptions,\n} from './types.js'\nimport { downloadImageAsBase64, sanitizeError, sanitizeString } from './utils.js'\n\n/**\n * GeminiProvider 配置\n *\n * 复用 BaseProviderOptions 的全部字段，无需额外字段。\n */\nexport type GeminiProviderOptions = BaseProviderOptions\n\n/**\n * Gemini 默认 base（官方端点）\n */\nconst DEFAULT_API_BASE = 'https://generativelanguage.googleapis.com'\n\n/**\n * resolution → Gemini 官方 imageConfig.imageSize 映射\n */\nconst RESOLUTION_IMAGE_SIZE_MAP: Record<string, string> = {\n  '1k': 'LOW',\n  '2k': 'MEDIUM',\n  '4k': '4K',\n}\n\n/**\n * resolution → 云雾（yunwu）等第三方 Gemini 兼容端 imageConfig.imageSize 映射\n *\n * 云雾原生接口使用数值字符串：512 / 1K / 2K / 4K\n */\nconst YUNWU_RESOLUTION_IMAGE_SIZE_MAP: Record<string, string> = {\n  '1k': '1K',\n  '2k': '2K',\n  '4k': '4K',\n}\n\n/**\n * GeminiProvider（v2 重写版）\n *\n * 端点：POST {apiBase}/v1beta/models/{modelId}:generateContent\n * 鉴权：URL params 携带 ?key=xxx（与官方一致）\n *\n * 关键能力：\n * - 兼容 Google Gemini 原生 generateContent 响应结构\n * - 仅在官方 Gemini API 或已知支持 imageConfig 的模型下发送 imageConfig\n * - 解析 inlineData / inline_data / fileData 三种结构\n * - 严格识别 promptFeedback.blockReason / candidate.finishReason 中的安全拦截\n */\nexport class GeminiProvider extends BaseImageProvider {\n  override readonly name = 'gemini'\n\n  override async generateImages(\n    prompt: string,\n    imageUrls: string | string[],\n    numImages: number,\n    options?: ImageGenerationOptions,\n    onImageGenerated?: ImageGeneratedCallback\n  ): Promise<string[]> {\n    const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]\n    const validUrls = urls.filter((url) => url && typeof url === 'string' && url.trim().length > 0)\n\n    if (this.shouldLogDetail()) {\n      this.logger.info(\n        'provider=%s event=generate_detail has_input=%s input_count=%d num=%d model=%s',\n        this.name,\n        validUrls.length > 0,\n        validUrls.length,\n        numImages,\n        this.modelId\n      )\n    }\n\n    // 下载所有输入图片并转换为 inline_data parts\n    const imageParts: Array<{ inline_data: { mime_type: string; data: string } }> = []\n    for (const url of validUrls) {\n      try {\n        const { data, mimeType } = await downloadImageAsBase64(\n          this.ctx,\n          url,\n          this.apiTimeoutSeconds,\n          this.logger\n        )\n        imageParts.push({ inline_data: { mime_type: mimeType, data } })\n      } catch (error) {\n        this.logger.error(\n          'provider=%s event=download_failed url=%s error=%s',\n          this.name,\n          truncate(url, 80),\n          JSON.stringify(sanitizeError(error)).slice(0, 200)\n        )\n        // 与 v1 行为一致：跳过失败图片，继续处理\n      }\n    }\n\n    const apiBase = this.apiBase ?? DEFAULT_API_BASE\n    const endpoint = `${apiBase}/v1beta/models/${this.modelId}:generateContent`\n    const isOfficialGeminiApi = apiBase.includes('generativelanguage.googleapis.com')\n    const supportsImageConfig = true\n\n    const generationConfig = this.buildGenerationConfig(options, isOfficialGeminiApi)\n    const safetySettings = buildSafetySettings()\n\n\n    const allImages: string[] = []\n\n    for (let i = 0; i < numImages; i++) {\n      const requestData = {\n        contents: [\n          {\n            role: 'user',\n            parts: [{ text: prompt }, ...imageParts],\n          },\n        ],\n        generationConfig,\n        safetySettings,\n      }\n\n      if (this.shouldLogDetail()) {\n        this.logger.info(\n          'provider=%s event=generate_request_detail current=%d total=%d endpoint=%s aspect=%s resolution=%s image_size=%s',\n          this.name,\n          i + 1,\n          numImages,\n          endpoint,\n          options?.aspectRatio ?? '-',\n          options?.resolution ?? '-',\n          (generationConfig.imageConfig as { imageSize?: string } | undefined)?.imageSize ?? '-'\n        )\n      }\n\n      try {\n        const response = await this.callApi<unknown>(() =>\n          (\n            this.ctx.http as unknown as {\n              post: (\n                url: string,\n                body: unknown,\n                opts: Record<string, unknown>\n              ) => Promise<unknown>\n            }\n          ).post(endpoint, requestData, {\n            headers: { 'Content-Type': 'application/json' },\n            params: { key: this.apiKey },\n            timeout: this.getTimeoutMs(),\n          })\n        )\n\n        const images = parseGeminiResponse(response, this.name, this.logger)\n        if (images.length === 0) {\n          this.logger.warn(\n            'provider=%s event=empty_response current=%d total=%d',\n            this.name,\n            i + 1,\n            numImages\n          )\n          continue\n        }\n\n        for (const url of images) {\n          const currentIndex = allImages.length\n          allImages.push(url)\n          await this.fireImageCallback(onImageGenerated, url, currentIndex, numImages)\n        }\n\n        this.logger.info(\n          'provider=%s event=generate_success current=%d total=%d images=%d',\n          this.name,\n          i + 1,\n          numImages,\n          images.length\n        )\n      } catch (error) {\n        const normalized = error instanceof ProviderError ? error : this.handleProviderError(error)\n\n        if (allImages.length > 0 && normalized.retryable === false) {\n          this.logger.warn(\n            'provider=%s event=partial_failed generated=%d requested=%d code=%s message=%s',\n            this.name,\n            allImages.length,\n            numImages,\n            normalized.code,\n            sanitizeString(normalized.message),\n          )\n          break\n        }\n        throw normalized\n      }\n    }\n\n    if (allImages.length === 0) {\n      throw new ParseError('未能从 Gemini API 生成图片，请检查 prompt 和模型配置', {\n        providerName: this.name,\n      })\n    }\n\n    return allImages\n  }\n\n  /**\n   * 构建 generationConfig。\n   *\n   * - 始终包含 responseModalities: ['TEXT', 'IMAGE']\n   * - 在官方 Gemini API 和云雾等兼容端点均发送 imageConfig（现代模型已支持）\n   * - 官方端点使用 LOW / MEDIUM / 4K；云雾等第三方使用 1K / 2K / 4K\n   */\n  private buildGenerationConfig(\n    options: ImageGenerationOptions | undefined,\n    isOfficialGeminiApi: boolean\n  ): Record<string, unknown> {\n    const generationConfig: Record<string, unknown> = {\n      responseModalities: ['TEXT', 'IMAGE'],\n    }\n\n    const imageConfig: Record<string, unknown> = {}\n\n    if (options?.aspectRatio) {\n      imageConfig.aspectRatio = options.aspectRatio\n    }\n\n    if (options?.resolution) {\n      const map = isOfficialGeminiApi\n        ? RESOLUTION_IMAGE_SIZE_MAP\n        : YUNWU_RESOLUTION_IMAGE_SIZE_MAP\n      const mapped = map[options.resolution]\n      if (mapped) {\n        imageConfig.imageSize = mapped\n      } else if (/^\\d+x\\d+$/.test(options.resolution)) {\n        this.logger.info(\n          'provider=%s event=custom_resolution_unsupported resolution=%s note=use_1k_2k_4k',\n          this.name,\n          options.resolution\n        )\n      }\n    }\n\n    if (Object.keys(imageConfig).length > 0) {\n      generationConfig.imageConfig = imageConfig\n    }\n    return generationConfig\n  }\n}\n\n// -------- 模块级工具 --------\n\n/**\n * 解析 Gemini 响应\n *\n * 支持的图像数据结构（按优先级）：\n * - candidate.content.parts[].inlineData.data + mimeType（驼峰）\n * - candidate.content.parts[].inline_data.data + mime_type（下划线）\n * - candidate.content.parts[].fileData.fileUri\n *\n * 抛出：\n * - ContentFilterError：promptFeedback.blockReason='SAFETY'/'RECITATION' 或 finishReason 同\n * - BadRequestError：blockReason='OTHER' 等明确表示请求异常\n * - ParseError：响应结构异常\n */\nfunction parseGeminiResponse(\n  rawResponse: unknown,\n  providerName: string,\n  logger: { debug: Function; warn: Function; error: Function; info?: Function }\n): string[] {\n  const response = (rawResponse ?? {}) as {\n    error?: { message?: string }\n    promptFeedback?: {\n      blockReason?: string\n      blockReasonMessage?: string\n      safetyRatings?: Array<{ category?: string; probability?: string }>\n    }\n    candidates?: Array<{\n      finishReason?: string\n      finishMessage?: string\n      content?: {\n        parts?: Array<{\n          inlineData?: { data?: string; mimeType?: string }\n          inline_data?: { data?: string; mime_type?: string }\n          fileData?: { fileUri?: string }\n          text?: string\n        }>\n      }\n      safetyRatings?: unknown\n    }>\n  }\n\n  if (!rawResponse || typeof rawResponse !== 'object') {\n    throw new ParseError('Gemini API 响应为空或格式异常', { providerName })\n  }\n\n  if (response.error) {\n    const safeMessage = sanitizeString(response.error.message ?? JSON.stringify(sanitizeError(response.error)))\n    if (isContentFilterText(safeMessage)) {\n      throw new ContentFilterError(safeMessage, { providerName })\n    }\n    throw new ProviderError('UNKNOWN', `Gemini API 错误: ${safeMessage}`, { providerName })\n  }\n\n  // promptFeedback：请求级阻断\n  if (response.promptFeedback?.blockReason) {\n    const reason = response.promptFeedback.blockReason\n    const detail = response.promptFeedback.blockReasonMessage\n    const ratings = (response.promptFeedback.safetyRatings ?? [])\n      .map((r) => `${r.category ?? '?'}:${r.probability ?? '?'}`)\n      .join(', ')\n\n    if (reason === 'SAFETY' || reason === 'RECITATION') {\n      const msg = `内容被安全策略阻止 (${reason})${detail ? `: ${detail}` : ''}${ratings ? ` [${ratings}]` : ''}`\n      throw new ContentFilterError(msg, { providerName })\n    }\n    if (reason === 'OTHER') {\n      const msg = `请求被阻止 (OTHER)${detail ? `: ${detail}` : ''}`\n      throw new BadRequestError(msg, { providerName })\n    }\n    throw new BadRequestError(`请求被阻止 (${reason})${detail ? `: ${detail}` : ''}`, {\n      providerName,\n    })\n  }\n\n  if (!Array.isArray(response.candidates) || response.candidates.length === 0) {\n    throw new ParseError('Gemini API 响应中没有 candidates 也没有 promptFeedback', {\n      providerName,\n    })\n  }\n\n  const images: string[] = []\n\n  for (const candidate of response.candidates) {\n    // finishReason 异常\n    const finishReason = candidate.finishReason\n    if (finishReason && finishReason !== 'STOP' && finishReason !== 'MAX_TOKENS') {\n      if (finishReason === 'SAFETY' || finishReason === 'RECITATION') {\n        const msg = `内容被阻止: ${finishReason}${candidate.finishMessage ? ` (${candidate.finishMessage})` : ''}`\n        throw new ContentFilterError(msg, { providerName })\n      }\n      // 其他异常 finishReason 且没有 parts 时报错；有 parts 则继续解析\n      const hasParts = !!candidate.content?.parts && candidate.content.parts.length > 0\n      if (!hasParts) {\n        const msg = `生成失败: ${finishReason}${candidate.finishMessage ? `, ${candidate.finishMessage}` : ''}`\n        logger.warn(\n          'provider=%s event=finish_reason_anomaly reason=%s detail=%s',\n          providerName,\n          finishReason,\n          candidate.finishMessage ?? '-'\n        )\n        throw new BadRequestError(msg, { providerName })\n      }\n    }\n\n    const parts = candidate.content?.parts ?? []\n    for (const part of parts) {\n      if (part.inlineData?.data) {\n        const mime = part.inlineData.mimeType ?? 'image/jpeg'\n        images.push(`data:${mime};base64,${part.inlineData.data}`)\n      } else if (part.inline_data?.data) {\n        const mime = part.inline_data.mime_type ?? 'image/jpeg'\n        images.push(`data:${mime};base64,${part.inline_data.data}`)\n      } else if (part.fileData?.fileUri) {\n        images.push(part.fileData.fileUri)\n      } else if (part.text) {\n        logger.warn(\n          'provider=%s event=text_part_only text=%s',\n          providerName,\n          truncate(part.text, 100)\n        )\n      }\n    }\n  }\n\n  return images\n}\n\nfunction isContentFilterText(message: string): boolean {\n  const lower = message.toLowerCase()\n  return (\n    lower.includes('safety') ||\n    lower.includes('content policy') ||\n    lower.includes('content_policy_violation') ||\n    lower.includes('blocked') ||\n    lower.includes('违规') ||\n    lower.includes('内容审核')\n  )\n}\n\nfunction truncate(value: string, max: number): string {\n  if (value.length <= max) return value\n  return `${value.slice(0, max)}…`\n}\n\n/**\n * 构建 Gemini safetySettings —— 全部 4 类阈值设为 BLOCK_NONE，与 v1 行为一致。\n */\nfunction buildSafetySettings(): Array<{ category: string; threshold: string }> {\n  return [\n    { category: 'HARM_CATEGORY_HARASSMENT', threshold: 'BLOCK_NONE' },\n    { category: 'HARM_CATEGORY_HATE_SPEECH', threshold: 'BLOCK_NONE' },\n    { category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', threshold: 'BLOCK_NONE' },\n    { category: 'HARM_CATEGORY_DANGEROUS_CONTENT', threshold: 'BLOCK_NONE' },\n  ]\n}\n\n/**\n * 工厂函数（注册表用）\n */\nexport function createGeminiProvider(\n  ctx: Context,\n  config: Record<string, unknown>\n): GeminiProvider {\n  return new GeminiProvider({\n    ctx,\n    apiKey: String(config.apiKey ?? ''),\n    modelId: String(config.modelId ?? ''),\n    apiBase: typeof config.apiBase === 'string' ? config.apiBase : undefined,\n    apiTimeout: Number.isFinite(config.apiTimeout as number) ? Number(config.apiTimeout) : 60,\n    logLevel: config.logLevel as BaseProviderOptions['logLevel'],\n    loggerName: 'aka-ai-image-generator:gemini',\n  })\n}\n","import type { Context } from 'koishi'\n\nimport { BaseImageProvider } from './base.js'\nimport { ContentFilterError, ParseError, ProviderError } from './errors.js'\nimport type {\n  BaseProviderOptions,\n  ImageGeneratedCallback,\n  ImageGenerationOptions,\n} from './types.js'\nimport { downloadImageAsBase64, sanitizeError, sanitizeString } from './utils.js'\n\n/**\n * OpenAI Provider 配置\n *\n * 复用 BaseProviderOptions 的全部字段，无需额外字段。\n */\nexport type OpenAIProviderOptions = BaseProviderOptions\n\n/**\n * GPT Image 模型最低超时（秒）。\n *\n * gpt-image-1 / gpt-image-2 等模型生成复杂图像通常需要 60-180+ 秒，\n * 因此即使用户配置了较短的 apiTimeout，也至少保证此下限。\n */\nconst GPT_IMAGE_MIN_TIMEOUT_SECONDS = 180\n\n/**\n * OpenAI Images API 默认 base。\n *\n * 服务层通常会显式传入 apiBase；此处保留官方 OpenAI 默认值作为 Provider 独立使用时的兜底。\n */\nconst DEFAULT_API_BASE = 'https://api.openai.com/v1'\n\n/**\n * 宽高比 → 尺寸映射（OpenAI Images 仅支持固定 size 字符串）\n */\nconst ASPECT_RATIO_SIZE_MAP: Record<string, string> = {\n  '1:1': '1024x1024',\n  '3:2': '1536x1024',\n  '2:3': '1024x1536',\n  '16:9': '2048x1152',\n  '9:16': '1152x2048',\n  '4:3': '1536x1024',\n}\n\ninterface OpenAIImagesResponse {\n  error?: { message?: string; type?: string; code?: string }\n  data?: Array<{\n    b64_json?: string\n    url?: string\n    revised_prompt?: string\n  }>\n}\n\n/**\n * OpenAIProvider（v2 重写版）\n *\n * 相比 v1：\n * - 继承 BaseImageProvider，复用 callApi / handleProviderError / 流式回调封装\n * - 错误统一归一化为 ProviderError 子类\n * - 不再持有 ProviderConfig；apiKey/modelId/apiBase/apiTimeout 全部由基类管理\n * - 仍保留 v1 关键能力：JSON+base64 优先 + FormData 回退、自定义分辨率、GPT Image 超时下限提升\n */\nexport class OpenAIProvider extends BaseImageProvider {\n  override readonly name: string = 'openai'\n\n  /** GPT Image 模型对超时的下限保护（秒） */\n  private getEffectiveTimeoutSeconds(): number {\n    const configured = this.apiTimeoutSeconds\n    const modelId = this.modelId.toLowerCase()\n    if (modelId.startsWith('gpt-image')) {\n      const effective = Math.max(configured, GPT_IMAGE_MIN_TIMEOUT_SECONDS)\n      if (effective !== configured) {\n        this.logger.info(\n          'provider=%s event=timeout_promoted configured=%d effective=%d model=%s',\n          this.name,\n          configured,\n          effective,\n          this.modelId\n        )\n      }\n      return effective\n    }\n    return configured\n  }\n\n  protected override getTimeoutMs(): number {\n    return Math.max(0, this.getEffectiveTimeoutSeconds() * 1000)\n  }\n\n  override async generateImages(\n    prompt: string,\n    imageUrls: string | string[],\n    numImages: number,\n    options?: ImageGenerationOptions,\n    onImageGenerated?: ImageGeneratedCallback\n  ): Promise<string[]> {\n    const urls = Array.isArray(imageUrls) ? imageUrls : [imageUrls]\n    const validUrls = urls.filter((url) => url && typeof url === 'string' && url.trim().length > 0)\n    const hasInputImages = validUrls.length > 0\n\n    if (this.shouldLogDetail()) {\n      this.logger.info(\n        'provider=%s event=generate_detail has_input=%s input_count=%d num=%d model=%s api_base=%s timeout_ms=%d auth=%s extra_headers=%s',\n        this.name,\n        hasInputImages,\n        validUrls.length,\n        numImages,\n        this.modelId,\n        this.getApiBase(),\n        this.getTimeoutMs(),\n        this.apiKey ? 'configured' : 'missing',\n        JSON.stringify(redactHeaders(this.extraHeaders)),\n      )\n    }\n\n    try {\n      if (hasInputImages) {\n        return await this.editImages(prompt, validUrls, numImages, options, onImageGenerated)\n      }\n      return await this.createImages(prompt, numImages, options, onImageGenerated)\n    } catch (error) {\n      const normalized = error instanceof ProviderError ? error : this.handleProviderError(error)\n      this.logger.error(\n        'provider=%s event=generate_failed code=%s status=%s retryable=%s message=%s context=%s',\n        this.name,\n        normalized.code,\n        normalized.statusCode ?? '-',\n        normalized.retryable,\n        sanitizeString(normalized.message),\n        JSON.stringify(sanitizeError(normalized.context)),\n      )\n      throw normalized\n    }\n  }\n\n  // -------- internal: size 解析 --------\n\n  private isCustomResolution(resolution?: string): boolean {\n    return typeof resolution === 'string' && /^\\d+x\\d+$/.test(resolution)\n  }\n\n  private getSize(options?: ImageGenerationOptions): string {\n    if (options?.resolution && this.isCustomResolution(options.resolution)) {\n      return options.resolution\n    }\n    return ASPECT_RATIO_SIZE_MAP[options?.aspectRatio ?? '1:1'] ?? '1024x1024'\n  }\n\n  private getApiBase(): string {\n    return normalizeV1Base(this.apiBase ?? DEFAULT_API_BASE)\n  }\n\n  // -------- 文生图 --------\n\n  private async createImages(\n    prompt: string,\n    numImages: number,\n    options?: ImageGenerationOptions,\n    onImageGenerated?: ImageGeneratedCallback\n  ): Promise<string[]> {\n    const apiBase = this.getApiBase()\n    const size = this.getSize(options)\n\n    if (options?.resolution && ['1k', '2k', '4k'].includes(options.resolution)) {\n      this.logger.info(\n        'provider=%s event=resolution_preset_ignored resolution=%s note=use_gemini_or_custom_size',\n        this.name,\n        options.resolution\n      )\n    }\n\n    const allImages: string[] = []\n\n    for (let i = 0; i < numImages; i++) {\n      const requestData = {\n        model: this.modelId,\n        prompt,\n        n: 1,\n        size,\n      }\n\n      if (this.shouldLogDetail()) {\n        this.logger.info(\n          'provider=%s event=create_detail current=%d total=%d url=%s model=%s size=%s timeout_ms=%d request=%s headers=%s',\n          this.name,\n          i + 1,\n          numImages,\n          `${apiBase}/images/generations`,\n          this.modelId,\n          size,\n          this.getTimeoutMs(),\n          JSON.stringify(redactRequestBody(requestData)),\n          JSON.stringify(redactHeaders(this.buildHeaders())),\n        )\n      }\n\n      try {\n        const response = await this.callApi<OpenAIImagesResponse>(() =>\n          (this.ctx.http as unknown as {\n            post: (url: string, body: unknown, opts: Record<string, unknown>) => Promise<OpenAIImagesResponse>\n          }).post(`${apiBase}/images/generations`, requestData, {\n            headers: this.buildHeaders(),\n            timeout: this.getTimeoutMs(),\n          })\n        )\n\n        const images = parseOpenAIImagesResponse(response)\n        if (images.length === 0) {\n          this.logger.warn(\n            'provider=%s event=create_empty_response current=%d total=%d',\n            this.name,\n            i + 1,\n            numImages\n          )\n          continue\n        }\n\n        for (const url of images) {\n          const currentIndex = allImages.length\n          allImages.push(url)\n          await this.fireImageCallback(onImageGenerated, url, currentIndex, numImages)\n        }\n\n        this.logger.info(\n          'provider=%s event=create_success current=%d total=%d',\n          this.name,\n          i + 1,\n          numImages\n        )\n      } catch (error) {\n        const normalized = error instanceof ProviderError ? error : this.handleProviderError(error)\n\n        // 已生成部分图片：返回已成功部分（保留 v1 行为）\n        if (allImages.length > 0 && normalized.retryable === false) {\n          this.logger.warn(\n            'provider=%s event=create_partial_failed generated=%d requested=%d code=%s',\n            this.name,\n            allImages.length,\n            numImages,\n            normalized.code\n          )\n          break\n        }\n        throw normalized\n      }\n    }\n\n    if (allImages.length === 0) {\n      throw new ParseError('未能生成任何图片', { providerName: this.name })\n    }\n    return allImages\n  }\n\n  // -------- 图生图（编辑） --------\n\n  private async editImages(\n    prompt: string,\n    imageUrls: string[],\n    numImages: number,\n    options?: ImageGenerationOptions,\n    onImageGenerated?: ImageGeneratedCallback\n  ): Promise<string[]> {\n    const apiBase = this.getApiBase()\n    const size = this.getSize(options)\n\n    if (this.shouldLogDetail()) {\n      this.logger.info(\n        'provider=%s event=edit_download_detail count=%d size=%s',\n        this.name,\n        imageUrls.length,\n        size\n      )\n    }\n\n    const imageDataList: Array<{ data: string; mimeType: string }> = []\n    for (const url of imageUrls) {\n      try {\n        const result = await downloadImageAsBase64(this.ctx, url, this.apiTimeoutSeconds, this.logger)\n        imageDataList.push(result)\n      } catch (error) {\n        this.logger.error(\n          'provider=%s event=download_failed url=%s error=%s',\n          this.name,\n          truncate(url, 80),\n          JSON.stringify(sanitizeError(error)).slice(0, 200)\n        )\n      }\n    }\n\n    if (imageDataList.length === 0) {\n      throw new ParseError('所有输入图片下载失败，无法进行图像编辑', {\n        providerName: this.name,\n      })\n    }\n\n    const allImages: string[] = []\n\n    for (let i = 0; i < numImages; i++) {\n      if (this.shouldLogDetail()) {\n        this.logger.info(\n          'provider=%s event=edit_detail current=%d total=%d url=%s model=%s size=%s input_count=%d timeout_ms=%d headers=%s',\n          this.name,\n          i + 1,\n          numImages,\n          `${apiBase}/images/edits`,\n          this.modelId,\n          size,\n          imageDataList.length,\n          this.getTimeoutMs(),\n          JSON.stringify(redactHeaders(this.buildHeaders())),\n        )\n      }\n\n      try {\n        const response = await this.callApi<OpenAIImagesResponse>(() =>\n          this.callEditApi(apiBase, prompt, size, imageDataList)\n        )\n\n        const images = parseOpenAIImagesResponse(response)\n        if (images.length === 0) {\n          this.logger.warn(\n            'provider=%s event=edit_empty_response current=%d total=%d',\n            this.name,\n            i + 1,\n            numImages\n          )\n          continue\n        }\n\n        for (const url of images) {\n          const currentIndex = allImages.length\n          allImages.push(url)\n          await this.fireImageCallback(onImageGenerated, url, currentIndex, numImages)\n        }\n\n        this.logger.info(\n          'provider=%s event=edit_success current=%d total=%d',\n          this.name,\n          i + 1,\n          numImages\n        )\n      } catch (error) {\n        const normalized = error instanceof ProviderError ? error : this.handleProviderError(error)\n        if (allImages.length > 0 && normalized.retryable === false) {\n          this.logger.warn(\n            'provider=%s event=edit_partial_failed generated=%d requested=%d code=%s',\n            this.name,\n            allImages.length,\n            numImages,\n            normalized.code\n          )\n          break\n        }\n        throw normalized\n      }\n    }\n\n    if (allImages.length === 0) {\n      throw new ParseError('未能生成任何图片', { providerName: this.name })\n    }\n    return allImages\n  }\n\n  /**\n   * 实际调用 /v1/images/edits：JSON + base64 优先，失败回退到 FormData multipart。\n   */\n  private async callEditApi(\n    apiBase: string,\n    prompt: string,\n    size: string,\n    imageDataList: Array<{ data: string; mimeType: string }>\n  ): Promise<OpenAIImagesResponse> {\n    const editUrl = `${apiBase}/images/edits`\n    const http = this.ctx.http as unknown as {\n      post: (url: string, body: unknown, opts: Record<string, unknown>) => Promise<OpenAIImagesResponse>\n    }\n\n    // 1) JSON + base64\n    try {\n      const imageInputs = imageDataList.map((img) => `data:${img.mimeType};base64,${img.data}`)\n      const requestData: Record<string, unknown> = {\n        model: this.modelId,\n        prompt,\n        n: 1,\n        size,\n        image: imageInputs.length === 1 ? imageInputs[0] : imageInputs,\n      }\n      if (this.shouldLogDetail()) {\n        this.logger.info(\n          'provider=%s event=edit_json_detail url=%s request=%s headers=%s',\n          this.name,\n          editUrl,\n          JSON.stringify(redactRequestBody(requestData)),\n          JSON.stringify(redactHeaders(this.buildHeaders())),\n        )\n      }\n      return await http.post(editUrl, requestData, {\n        headers: this.buildHeaders(),\n        timeout: this.getTimeoutMs(),\n      })\n    } catch (jsonError) {\n      // 2) FormData 回退\n      this.logger.warn(\n        'provider=%s event=edit_json_failed fallback=formdata error=%s',\n        this.name,\n        sanitizeString((jsonError as Error)?.message || '未知错误')\n      )\n\n      const formData = new FormData()\n      for (let idx = 0; idx < imageDataList.length; idx++) {\n        const img = imageDataList[idx]!\n        const blob = base64ToBlob(img.data, img.mimeType)\n        formData.append('image', blob, `image_${idx}.png`)\n      }\n      formData.append('prompt', prompt)\n      formData.append('model', this.modelId)\n      formData.append('n', '1')\n      formData.append('size', size)\n\n      if (this.shouldLogDetail()) {\n        this.logger.info(\n          'provider=%s event=edit_formdata_detail url=%s model=%s size=%s image_count=%d headers=%s',\n          this.name,\n          editUrl,\n          this.modelId,\n          size,\n          imageDataList.length,\n          JSON.stringify(redactHeaders(this.buildHeaders())),\n        )\n      }\n      return await http.post(editUrl, formData, {\n        headers: {\n          Authorization: `Bearer ${this.apiKey}`,\n        },\n        timeout: this.getTimeoutMs(),\n      })\n    }\n  }\n}\n\n// -------- 模块级工具 --------\n\nfunction parseOpenAIImagesResponse(response: OpenAIImagesResponse | undefined): string[] {\n  if (!response) {\n    throw new ParseError('OpenAI Images API 响应为空', { providerName: 'openai' })\n  }\n\n  if (response.error) {\n    const errMessage = sanitizeString(response.error.message ?? JSON.stringify(sanitizeError(response.error)))\n    if (isContentFilter(errMessage)) {\n      throw new ContentFilterError(errMessage, { providerName: 'openai' })\n    }\n    throw new ProviderError('UNKNOWN', `OpenAI Images API 错误: ${errMessage}`, {\n      providerName: 'openai',\n    })\n  }\n\n  const data = response.data\n  if (!Array.isArray(data)) return []\n\n  const images: string[] = []\n  for (const item of data) {\n    if (item.b64_json) {\n      const mimeType = 'image/png'\n      images.push(`data:${mimeType};base64,${item.b64_json}`)\n    } else if (item.url) {\n      images.push(item.url)\n    }\n  }\n  return images\n}\n\nfunction isContentFilter(message: string): boolean {\n  const lower = message.toLowerCase()\n  return (\n    lower.includes('safety system') ||\n    lower.includes('content_policy_violation') ||\n    lower.includes('content policy') ||\n    lower.includes('inappropriate') ||\n    lower.includes('违规') ||\n    lower.includes('内容审核')\n  )\n}\n\nfunction base64ToBlob(base64Data: string, mimeType: string): Blob {\n  const byteCharacters = atob(base64Data)\n  const byteNumbers = new Array(byteCharacters.length)\n  for (let i = 0; i < byteCharacters.length; i++) {\n    byteNumbers[i] = byteCharacters.charCodeAt(i)\n  }\n  const byteArray = new Uint8Array(byteNumbers)\n  return new Blob([byteArray], { type: mimeType })\n}\n\nfunction truncate(value: string, max: number): string {\n  if (value.length <= max) return value\n  return `${value.slice(0, max)}…`\n}\n\nfunction redactHeaders(headers: Record<string, string>): Record<string, string> {\n  const result: Record<string, string> = {}\n  for (const [key, value] of Object.entries(headers)) {\n    const lower = key.toLowerCase()\n    if (lower === 'authorization' || lower.includes('api-key') || lower.includes('apikey') || lower.includes('token') || lower.includes('secret')) {\n      result[key] = value ? '[REDACTED]' : ''\n    } else {\n      result[key] = truncate(value, 120)\n    }\n  }\n  return result\n}\n\nfunction redactRequestBody(body: Record<string, unknown>): Record<string, unknown> {\n  const result: Record<string, unknown> = {}\n  for (const [key, value] of Object.entries(body)) {\n    if (key === 'prompt' && typeof value === 'string') {\n      result.promptLength = value.length\n    } else if (key === 'image') {\n      result.image = describeImagePayload(value)\n    } else {\n      result[key] = value\n    }\n  }\n  return result\n}\n\nfunction describeImagePayload(value: unknown): unknown {\n  if (typeof value === 'string') return describeImageString(value)\n  if (Array.isArray(value)) return value.map(describeImageString)\n  return typeof value\n}\n\nfunction describeImageString(value: unknown): string {\n  if (typeof value !== 'string') return typeof value\n  if (value.startsWith('data:')) {\n    const commaIndex = value.indexOf(',')\n    const meta = commaIndex >= 0 ? value.slice(0, commaIndex) : 'data:*'\n    return `${meta},[base64 length=${Math.max(0, value.length - commaIndex - 1)}]`\n  }\n  return truncate(value, 120)\n}\n\n/**\n * 工厂函数（注册表用）。\n *\n * 期望 config 结构：\n * ```ts\n * {\n *   apiKey: string\n *   modelId: string\n *   apiBase?: string\n *   apiTimeout: number\n * }\n * ```\n */\nexport function createOpenAIProvider(\n  ctx: Context,\n  config: Record<string, unknown>\n): OpenAIProvider {\n  return new OpenAIProvider({\n    ctx,\n    apiKey: String(config.apiKey ?? ''),\n    modelId: String(config.modelId ?? ''),\n    apiBase: typeof config.apiBase === 'string' ? config.apiBase : undefined,\n    apiTimeout: Number.isFinite(config.apiTimeout as number)\n      ? Number(config.apiTimeout)\n      : 60,\n    logLevel: config.logLevel as BaseProviderOptions['logLevel'],\n    loggerName: 'aka-ai-image-generator:openai',\n    extraHeaders: isRecordOfStrings(config.extraHeaders) ? config.extraHeaders : undefined,\n  })\n}\n\nfunction normalizeV1Base(apiBase: string): string {\n  const trimmed = apiBase.replace(/\\/$/, '')\n  return trimmed.endsWith('/v1') ? trimmed : `${trimmed}/v1`\n}\n\nfunction isRecordOfStrings(value: unknown): value is Record<string, string> {\n  return !!value\n    && typeof value === 'object'\n    && !Array.isArray(value)\n    && Object.values(value).every((item) => typeof item === 'string')\n}\n","import type { Context } from 'koishi'\n\nimport type { ImageProvider, ProviderFactory } from './types.js'\n\n/**\n * Provider 注册表（7.11.4 节）\n *\n * 设计要点：\n * - 注册表实例是无状态的（只持有工厂引用）\n * - 实际 ImageProvider 实例通过 createProvider 即时构造，由调用方决定缓存策略\n * - 名字大小写不敏感\n *\n * 使用示例：\n * ```ts\n * const registry = new ProviderRegistry()\n * registry.register('openai', (ctx, cfg) => new OpenAIProvider({ ctx, ...cfg }))\n * const provider = registry.createProvider('openai', ctx, cfg)\n * ```\n */\nexport class ProviderRegistry {\n  private readonly factories = new Map<string, ProviderFactory>()\n\n  /**\n   * 注册一个 Provider 工厂。重复注册会覆盖前一次。\n   */\n  register(name: string, factory: ProviderFactory): void {\n    this.factories.set(normalize(name), factory)\n  }\n\n  /**\n   * 注销一个 Provider。\n   */\n  unregister(name: string): boolean {\n    return this.factories.delete(normalize(name))\n  }\n\n  /** 列出所有已注册 Provider 名（按注册顺序） */\n  list(): string[] {\n    return Array.from(this.factories.keys())\n  }\n\n  /** 是否已注册 */\n  has(name: string): boolean {\n    return this.factories.has(normalize(name))\n  }\n\n  /**\n   * 创建一个 Provider 实例。\n   *\n   * @throws 当 name 未注册时抛出\n   */\n  createProvider(\n    name: string,\n    ctx: Context,\n    config: Record<string, unknown>\n  ): ImageProvider {\n    const factory = this.factories.get(normalize(name))\n    if (!factory) {\n      throw new Error(\n        `Provider 未注册：'${name}'。可用：[${this.list().join(', ') || '<空>'}]`\n      )\n    }\n    return factory(ctx, config)\n  }\n}\n\nfunction normalize(name: string): string {\n  return name.trim().toLowerCase()\n}\n","/**\n * AiImageGeneratorService —— V2 服务层。\n *\n * 供应商语义 + 协议路由版本：配置页只暴露 OpenAI 兼容 / Gemini 官方 / GPT 官方。\n * 模型映射显式声明 supplier + protocol，运行时只保留 openai / gemini 两类 Provider。\n */\n\nimport type { Context, Session } from 'koishi'\nimport { Service } from 'koishi'\n\nimport type { Config, ProviderSettingsConfig } from '../shared/config.js'\nimport type { GenerationCost } from '../shared/billing.js'\nimport { calculateGenerationCost, formatCredits, scaleGenerationCost } from '../shared/billing.js'\nimport type {\n  GeneratedImageRecord,\n  GenerationDisplayInfo,\n  ImageGenerationModifiers,\n  ImageRequestContext,\n  ModelMappingConfig,\n  ImageProvider,\n  ProviderType,\n  ResolvedStyleConfig,\n  StyleConfig,\n  StyleMatchCandidate,\n} from '../shared/types.js'\nimport { PLUGIN_NAME } from '../shared/constants.js'\nimport { isDetailLogLevel, normalizeLogLevel } from '../shared/logging.js'\nimport { ImageContextStore } from '../core/image-context-store.js'\nimport type { ProviderRegistry } from '../providers/registry.js'\nimport type { ImageProvider as RuntimeImageProvider } from '../providers/types.js'\nimport type { CreditLedgerEventV2, CreditSummary } from '../services/UserManager.js'\nimport { UserManager } from '../services/UserManager.js'\n\ndeclare module 'koishi' {\n  interface Context {\n    aiImageGenerator: AiImageGeneratorService\n  }\n}\n\nexport interface RememberGeneratedImagesParams {\n  session?: Session | null\n  conversationId?: string\n  imageUrls: string[]\n  prompt: string\n  source?: GeneratedImageRecord['source']\n  requestContext?: ImageRequestContext\n  stylePreset?: string\n  parentRecordId?: string\n}\n\nexport interface UsageRecordingResult {\n  summary: CreditSummary\n  consumedCredits: number\n  freeUsed: number\n  purchasedUsed: number\n  isAdmin: boolean\n  isPermanentMember: boolean\n  isPlatformExempt: boolean\n  ledgerEvent?: CreditLedgerEventV2\n}\n\nexport interface ModelAccessCheckResult {\n  allowed: boolean\n  message?: string\n}\n\ninterface SessionConversationLike {\n  conversationId?: string\n  conversation_id?: string\n  roomId?: string\n  room_id?: string\n  platform?: string\n  channelId?: string\n  guildId?: string\n  userId?: string\n}\n\nconst DEFAULT_GEMINI_API_BASE = 'https://generativelanguage.googleapis.com'\nconst DEFAULT_OPENAI_API_BASE = 'https://api.openai.com/v1'\nconst DEFAULT_OPENAI_MODEL_ID = 'gpt-image-2'\nconst DEFAULT_CONTEXT_HISTORY_SIZE = 20\n\nexport class AiImageGeneratorService extends Service {\n  readonly userManager: UserManager\n  readonly imageContextStore: ImageContextStore\n\n  private pluginConfig: Config\n  private readonly pluginLogger: ReturnType<Context['logger']>\n  private readonly providerRegistry: ProviderRegistry\n  private styleDefinitions: ResolvedStyleConfig[]\n\n  constructor(\n    ctx: Context,\n    config: Config,\n    userManager: UserManager,\n    providerRegistry: ProviderRegistry,\n  ) {\n    super(ctx, 'aiImageGenerator', true)\n\n    this.pluginConfig = config\n    this.userManager = userManager\n    this.providerRegistry = providerRegistry\n    this.imageContextStore = new ImageContextStore()\n    this.pluginLogger = ctx.logger(PLUGIN_NAME)\n    this.styleDefinitions = this.collectStyleDefinitions(config)\n  }\n\n  // ---------------------------------------------------------------------------\n  // 配置 & 风格\n  // ---------------------------------------------------------------------------\n\n  updateConfig(config: Config) {\n    this.pluginConfig = config\n    this.styleDefinitions = this.collectStyleDefinitions(config)\n  }\n\n  getConfig(): Config {\n    return this.pluginConfig\n  }\n\n  // ---------------------------------------------------------------------------\n  // Provider 实例化\n  // ---------------------------------------------------------------------------\n\n  getProviderInstance(requestContext?: ImageRequestContext): RuntimeImageProvider {\n    const provider = this.resolveProvider(requestContext)\n    const factoryConfig = this.buildProviderFactoryConfig(provider, requestContext)\n    return this.providerRegistry.createProvider(provider, this.ctx, factoryConfig)\n  }\n\n  async requestProviderImages(\n    prompt: string,\n    imageUrls: string | string[],\n    numImages: number,\n    requestContext?: ImageRequestContext,\n    onImageGenerated?: (imageUrl: string, index: number, total: number) => void | Promise<void>,\n  ): Promise<string[]> {\n    const provider = this.resolveProvider(requestContext)\n    const supplier = this.resolveSupplier(requestContext)\n    const targetModelId = requestContext?.modelId\n    const effectiveModelId = targetModelId || this.resolveDefaultModelId(provider)\n    const factoryConfig = this.buildProviderFactoryConfig(provider, requestContext)\n    const imageOptions = {\n      resolution: requestContext?.resolution,\n      aspectRatio: requestContext?.aspectRatio,\n    }\n\n    const requestLog = {\n      supplier,\n      provider,\n      modelId: effectiveModelId || 'default',\n      modelSource: targetModelId ? 'requestContext' : 'providerDefault',\n      numImages,\n      imageUrlsCount: Array.isArray(imageUrls) ? imageUrls.length : (imageUrls ? 1 : 0),\n      ...imageOptions,\n    }\n\n    this.pluginLogger.info('requestProviderImages 调用', requestLog)\n\n    if (isDetailLogLevel(this.pluginConfig.logLevel)) {\n      this.pluginLogger.info('requestProviderImages 诊断', {\n        ...requestLog,\n        hasCallback: !!onImageGenerated,\n        promptLength: prompt.length,\n        apiBase: factoryConfig.apiBase || 'default',\n        apiKey: factoryConfig.apiKey ? 'configured' : 'missing',\n        extraHeaders: redactHeadersForLog(factoryConfig.extraHeaders),\n        timeout: factoryConfig.apiTimeout,\n      })\n    }\n\n    const providerInstance = this.providerRegistry.createProvider(provider, this.ctx, factoryConfig)\n    const result = await providerInstance.generateImages(\n      prompt,\n      imageUrls,\n      numImages,\n      imageOptions,\n      onImageGenerated,\n    )\n\n    this.pluginLogger.info('requestProviderImages 完成', {\n      supplier,\n      provider,\n      resultCount: result.length,\n    })\n\n    return result\n  }\n\n  // ---------------------------------------------------------------------------\n  // 会话上下文 / 图像记忆\n  // ---------------------------------------------------------------------------\n\n  buildSessionConversationId(session?: SessionConversationLike | Session | null): string | undefined {\n    if (!session) return undefined\n\n    const explicitConversationId = [\n      (session as SessionConversationLike).conversationId,\n      (session as SessionConversationLike).conversation_id,\n      (session as SessionConversationLike).roomId,\n      (session as SessionConversationLike).room_id,\n    ].find((value): value is string => typeof value === 'string' && value.trim().length > 0)\n\n    if (explicitConversationId) {\n      const platformPrefix = typeof session.platform === 'string' && session.platform.trim()\n        ? `${session.platform.trim()}:`\n        : ''\n      if (platformPrefix && explicitConversationId.startsWith(platformPrefix)) {\n        return explicitConversationId.trim()\n      }\n      return `${platformPrefix}${explicitConversationId.trim()}`\n    }\n\n    const base = session.channelId || session.guildId || session.userId\n    if (!base) return undefined\n\n    const platformPrefix = typeof session.platform === 'string' && session.platform.trim()\n      ? `${session.platform.trim()}:`\n      : ''\n    return `${platformPrefix}${base}`\n  }\n\n  rememberGeneratedImages(params: RememberGeneratedImagesParams): GeneratedImageRecord[] {\n    const conversationId = params.conversationId || this.buildSessionConversationId(params.session)\n    const userId = params.session?.userId || 'unknown'\n    if (!conversationId || !params.imageUrls.length) return []\n\n    const provider = this.resolveProvider(params.requestContext)\n    const supplier = this.resolveSupplier(params.requestContext)\n    const modelId = params.requestContext?.modelId || this.resolveDefaultModelId(provider)\n\n    const createdAt = Date.now()\n    const records: GeneratedImageRecord[] = params.imageUrls.map((imageUrl, index) => {\n      const record: GeneratedImageRecord = {\n        id: `${conversationId}:${createdAt}:${index}`,\n        conversationId,\n        userId,\n        createdAt,\n        source: params.source || 'generated',\n        imageUrl,\n        prompt: params.prompt,\n        normalizedPrompt: params.prompt.trim(),\n        supplier,\n        provider,\n        modelId: modelId || '',\n        ...(params.requestContext?.aspectRatio !== undefined\n          ? { aspectRatio: params.requestContext.aspectRatio }\n          : {}),\n        ...(params.requestContext?.resolution !== undefined\n          ? { resolution: params.requestContext.resolution }\n          : {}),\n        ...(params.stylePreset !== undefined ? { stylePreset: params.stylePreset } : {}),\n        ...(params.parentRecordId !== undefined ? { parentRecordId: params.parentRecordId } : {}),\n      }\n\n      this.imageContextStore.addGeneratedRecord(record, {\n        maxRecordsPerConversation: DEFAULT_CONTEXT_HISTORY_SIZE,\n      })\n      return record\n    })\n\n    return records\n  }\n\n  getConversationImageContext(conversationId: string) {\n    return this.imageContextStore.getConversationContext(conversationId)\n  }\n\n  clearConversationImageContext(conversationId: string) {\n    this.imageContextStore.clearConversation(conversationId)\n  }\n\n  pruneConversationImageContexts(ttlSeconds: number) {\n    this.imageContextStore.pruneExpired(ttlSeconds * 1000)\n  }\n\n  // ---------------------------------------------------------------------------\n  // 风格预设\n  // ---------------------------------------------------------------------------\n\n  listStylePresets(): ResolvedStyleConfig[] {\n    return this.styleDefinitions\n  }\n\n  getStylePreset(commandName: string): ResolvedStyleConfig | undefined {\n    const normalized = commandName.trim().toLowerCase()\n    return this.styleDefinitions.find((style) => {\n      if (style.commandName.trim().toLowerCase() === normalized) return true\n      return Array.isArray(style.aliases)\n        && style.aliases.some(alias => alias.trim().toLowerCase() === normalized)\n    })\n  }\n\n  matchStylePresets(query: string, limit = 3): StyleMatchCandidate[] {\n    const normalizedQuery = normalizeMatchText(query)\n    if (!normalizedQuery) return []\n\n    const queryTerms = buildQueryTerms(query)\n    const candidates: StyleMatchCandidate[] = []\n\n    for (const style of this.styleDefinitions) {\n      const matchedTerms = new Set<string>()\n      let score = 0\n\n      const addMatches = (value: string | undefined, weight: number) => {\n        const normalizedValue = normalizeMatchText(value)\n        if (!normalizedValue) return\n\n        if (normalizedValue === normalizedQuery) {\n          score += weight * 3\n          matchedTerms.add(value!.trim())\n          return\n        }\n\n        if (normalizedValue.includes(normalizedQuery) || normalizedQuery.includes(normalizedValue)) {\n          score += weight * 2\n          matchedTerms.add(value!.trim())\n        }\n\n        for (const term of queryTerms) {\n          if (term.length < 2) continue\n          if (normalizedValue.includes(term)) {\n            score += weight\n            matchedTerms.add(term)\n          }\n        }\n      }\n\n      addMatches(style.commandName, 10)\n      addMatches(style.description, 5)\n      addMatches(style.category, 5)\n      addMatches(style.whenToUse, 4)\n\n      for (const alias of style.aliases || []) addMatches(alias, 9)\n      for (const keyword of style.keywords || []) addMatches(keyword, 8)\n      for (const example of style.examples || []) addMatches(example, 6)\n\n      if (!score && style.prompt) {\n        const promptText = normalizeMatchText(style.prompt)\n        for (const term of queryTerms) {\n          if (term.length < 2) continue\n          if (promptText.includes(term)) {\n            score += 1\n            matchedTerms.add(term)\n          }\n        }\n      }\n\n      if (score > 0) {\n        candidates.push({\n          style,\n          score,\n          matchedTerms: Array.from(matchedTerms).slice(0, 6),\n        })\n      }\n    }\n\n    return candidates\n      .sort((a, b) => {\n        if (b.score !== a.score) return b.score - a.score\n        return a.style.commandName.localeCompare(b.style.commandName, 'zh-CN')\n      })\n      .slice(0, limit)\n  }\n\n  // ---------------------------------------------------------------------------\n  // 配额 & 用量\n  // ---------------------------------------------------------------------------\n\n  async getQuotaSummary(userId: string, userName: string): Promise<CreditSummary> {\n    const userData = await this.userManager.getUserData(userId, userName, this.pluginConfig)\n    return this.userManager.buildCreditSummary(userData, this.pluginConfig)\n  }\n\n  async getExistingUsageSummary(userId: string): Promise<CreditSummary | undefined> {\n    const userData = await this.userManager.getExistingUserData(userId)\n    if (!userData) return undefined\n    return this.userManager.buildCreditSummary(userData, this.pluginConfig)\n  }\n\n  async getUsageRanking(limit = 10) {\n    const users = await this.userManager.getAllUsers()\n    return Object.values(users)\n      .map(userData => this.userManager.buildCreditSummary(userData, this.pluginConfig))\n      .sort((a, b) => {\n        if (b.totalConsumedCredits !== a.totalConsumedCredits) return b.totalConsumedCredits - a.totalConsumedCredits\n        if (b.totalImagesGenerated !== a.totalImagesGenerated) return b.totalImagesGenerated - a.totalImagesGenerated\n        return a.userName.localeCompare(b.userName, 'zh-CN')\n      })\n      .slice(0, Math.min(50, Math.max(1, Math.floor(limit || 10))))\n  }\n\n  checkAndReserveQuota(userId: string, userName: string, cost: GenerationCost, platform?: string) {\n    return this.userManager.checkAndReserveQuota(\n      userId,\n      userName,\n      cost,\n      this.pluginConfig,\n      platform,\n    )\n  }\n\n  buildGenerationSetup(numImages: number, modifiers?: ImageGenerationModifiers) {\n    const requestContext: ImageRequestContext = { numImages }\n    const modelMapping = modifiers?.modelMapping\n    const generationCost = calculateGenerationCost({\n      numImages,\n      modelMapping,\n      config: this.pluginConfig,\n    })\n\n    if (modelMapping) {\n      const resolvedRoute = this.resolveModelRoute(modelMapping)\n      requestContext.supplier = resolvedRoute.supplier\n      requestContext.provider = resolvedRoute.protocol\n    }\n    if (modelMapping?.modelId) {\n      requestContext.modelId = modelMapping.modelId\n    }\n    if (modifiers?.resolution) {\n      requestContext.resolution = modifiers.resolution\n    }\n    if (modifiers?.aspectRatio) {\n      requestContext.aspectRatio = modifiers.aspectRatio\n    }\n\n    const displayInfo: GenerationDisplayInfo = {}\n    if (modifiers?.customAdditions?.length) {\n      displayInfo.customAdditions = modifiers.customAdditions\n    }\n    if (modelMapping?.modelId) {\n      displayInfo.modelId = modelMapping.modelId\n      displayInfo.modelDescription = modelMapping.suffix || modelMapping.modelId\n    }\n\n    return { requestContext, displayInfo, generationCost }\n  }\n\n  calculateGenerationCost(numImages: number, requestContext?: ImageRequestContext): GenerationCost {\n    const modelMapping = requestContext?.modelId\n      ? this.pluginConfig.modelMappings?.find(mapping => mapping.modelId === requestContext.modelId)\n      : undefined\n    return calculateGenerationCost({\n      numImages,\n      modelMapping,\n      config: this.pluginConfig,\n    })\n  }\n\n  scaleGenerationCost(cost: GenerationCost, actualImages: number): GenerationCost {\n    return scaleGenerationCost(cost, actualImages)\n  }\n\n  formatCredits(value: number): string {\n    return formatCredits(value, this.pluginConfig.creditUnitName)\n  }\n\n  checkModelAccess(userId: string, modifiers?: ImageGenerationModifiers): ModelAccessCheckResult {\n    const mapping = modifiers?.modelMapping\n    if (!mapping?.restricted) return { allowed: true }\n\n    if (this.userManager.isModelWhitelisted(userId, this.pluginConfig)) {\n      return { allowed: true }\n    }\n\n    return {\n      allowed: false,\n      message: buildRestrictedModelMessage(mapping),\n    }\n  }\n\n  async recordUsage(\n    userId: string,\n    userName: string,\n    commandName: string,\n    cost: GenerationCost,\n    platform?: string,\n    requestId?: string,\n  ): Promise<UsageRecordingResult> {\n    const isAdmin = this.userManager.isAdmin(userId, this.pluginConfig)\n    const isPermanentMember = this.userManager.isPermanentMember(userId, this.pluginConfig)\n    const isPlatformExempt = Boolean(\n      platform && this.pluginConfig.unlimitedPlatforms?.includes(platform),\n    )\n\n    if (isAdmin || isPermanentMember || isPlatformExempt || cost.totalCredits <= 0) {\n      const userData = await this.userManager.recordUsageOnly(userId, userName, commandName, cost.numImages, this.pluginConfig)\n      return {\n        summary: this.userManager.buildCreditSummary(userData, this.pluginConfig),\n        consumedCredits: 0,\n        freeUsed: 0,\n        purchasedUsed: 0,\n        isAdmin,\n        isPermanentMember,\n        isPlatformExempt,\n      }\n    }\n\n    const result = await this.userManager.consumeCredits(\n      userId,\n      userName,\n      commandName,\n      cost,\n      this.pluginConfig,\n      requestId,\n    )\n    return {\n      summary: this.userManager.buildCreditSummary(result.userData, this.pluginConfig),\n      consumedCredits: cost.totalCredits,\n      freeUsed: result.freeUsed,\n      purchasedUsed: result.purchasedUsed,\n      isAdmin: false,\n      isPermanentMember: false,\n      isPlatformExempt: false,\n      ...(result.ledgerEvent ? { ledgerEvent: result.ledgerEvent } : {}),\n    }\n  }\n\n  async grantCredits(\n    userId: string,\n    userName: string,\n    amount: number,\n    reason: string,\n    operator: { userId: string; userName: string },\n  ) {\n    return this.userManager.grantCredits(userId, userName, amount, reason, operator, this.pluginConfig)\n  }\n\n  async adjustCredits(\n    userId: string,\n    userName: string,\n    amount: number,\n    reason: string,\n    operator: { userId: string; userName: string },\n  ) {\n    return this.userManager.adjustCredits(userId, userName, amount, reason, operator, this.pluginConfig)\n  }\n\n  listLedgerEvents(userId?: string, limit = 10) {\n    return this.userManager.listLedgerEvents(userId, limit)\n  }\n\n  // ---------------------------------------------------------------------------\n  // Provider 路由 / 字段拼装\n  // ---------------------------------------------------------------------------\n\n  private resolveProvider(requestContext?: ImageRequestContext): ProviderType {\n    if (requestContext?.provider) return requestContext.provider\n    return this.resolveDefaultModelRoute().protocol\n  }\n\n  private resolveSupplier(requestContext?: ImageRequestContext): ImageProvider {\n    if (requestContext?.supplier) return requestContext.supplier\n    return this.resolveDefaultModelRoute().supplier\n  }\n\n  private resolveDefaultProvider(): ProviderType {\n    return this.resolveDefaultModelRoute().protocol\n  }\n\n  private resolveDefaultModelId(provider: ProviderType): string {\n    const firstMapping = this.getFirstModelMapping()\n    if (firstMapping?.modelId) return firstMapping.modelId\n    switch (provider) {\n      case 'openai':\n        return DEFAULT_OPENAI_MODEL_ID\n      case 'gemini':\n        return ''\n      default:\n        return ''\n    }\n  }\n\n  private resolveDefaultModelRoute(): { supplier: ImageProvider; protocol: ProviderType } {\n    const firstMapping = this.getFirstModelMapping()\n    if (firstMapping) return this.resolveModelRoute(firstMapping)\n    return { supplier: 'openai-compatible', protocol: 'openai' }\n  }\n\n  private resolveModelRoute(mapping: ModelMappingConfig): { supplier: ImageProvider; protocol: ProviderType } {\n    const protocol = mapping.protocol || mapping.provider || 'openai'\n    const supplier = mapping.supplier || this.inferLegacySupplier(protocol)\n    this.assertRouteSupported(supplier, protocol, mapping)\n    return { supplier, protocol }\n  }\n\n  private inferLegacySupplier(protocol: ProviderType): ImageProvider {\n    if (protocol !== 'gemini') return 'openai-compatible'\n\n    const settings = this.resolveProviderSettings()\n    if (settings.geminiOfficialApiKey) return 'gemini-official'\n    if (settings.openaiCompatibleApiKey || settings.openaiCompatibleApiBase) return 'openai-compatible'\n    return 'gemini-official'\n  }\n\n  private assertRouteSupported(\n    supplier: ImageProvider,\n    protocol: ProviderType,\n    mapping?: ModelMappingConfig,\n  ) {\n    const suffix = mapping?.suffix ? ` suffix=${mapping.suffix}` : ''\n    if (supplier === 'gemini-official' && protocol !== 'gemini') {\n      throw new Error(`模型映射配置错误｜gemini-official 只能使用 gemini 协议${suffix ? `｜${suffix.trim()}` : ''}`)\n    }\n    if (supplier === 'gpt-official' && protocol !== 'openai') {\n      throw new Error(`模型映射配置错误｜gpt-official 只能使用 openai 协议${suffix ? `｜${suffix.trim()}` : ''}`)\n    }\n  }\n\n  private getFirstModelMapping(): ModelMappingConfig | undefined {\n    const mappings = this.pluginConfig.modelMappings\n    if (Array.isArray(mappings) && mappings.length > 0) return mappings[0]\n    return undefined\n  }\n\n  private buildProviderFactoryConfig(\n    provider: ProviderType,\n    requestContext?: ImageRequestContext,\n  ): Record<string, unknown> {\n    const cfg = this.pluginConfig\n    const settings = this.resolveProviderSettings()\n    const targetModelId = requestContext?.modelId\n    const supplier = this.resolveSupplier(requestContext)\n    this.assertRouteSupported(supplier, provider)\n    const common = {\n      apiTimeout: cfg.apiTimeout,\n      logLevel: normalizeLogLevel(cfg.logLevel),\n    }\n\n    switch (supplier) {\n      case 'openai-compatible':\n        return {\n          ...common,\n          apiKey: settings.openaiCompatibleApiKey || '',\n          modelId: targetModelId || this.resolveDefaultModelId(provider),\n          apiBase: provider === 'gemini'\n            ? this.resolveOpenAICompatibleGeminiApiBase(settings)\n            : settings.openaiCompatibleApiBase || DEFAULT_OPENAI_API_BASE,\n          extraHeaders: settings.openaiCompatibleExtraHeaders || {},\n        }\n      case 'gpt-official':\n        return {\n          ...common,\n          apiKey: settings.gptOfficialApiKey || '',\n          modelId: targetModelId || this.resolveDefaultModelId('openai'),\n          apiBase: DEFAULT_OPENAI_API_BASE,\n          extraHeaders: {},\n        }\n      case 'gemini-official':\n        return {\n          ...common,\n          apiKey: settings.geminiOfficialApiKey || '',\n          modelId: targetModelId || this.resolveDefaultModelId('gemini'),\n          apiBase: DEFAULT_GEMINI_API_BASE,\n        }\n      default:\n        return { ...common }\n    }\n  }\n\n  private resolveOpenAICompatibleGeminiApiBase(settings: ProviderSettingsConfig): string {\n    if (settings.openaiCompatibleApiBase) {\n      const base = settings.openaiCompatibleApiBase.replace(/\\/$/, '')\n      // 云雾等第三方通常使用 /v1beta 路径，但如果 base 已含 /v1 则去掉 /v1 后缀\n      if (base.endsWith('/v1')) {\n        return base.replace(/\\/v1$/, '')\n      }\n      return base\n    }\n    return DEFAULT_GEMINI_API_BASE\n  }\n\n  private resolveProviderSettings(): ProviderSettingsConfig {\n    const cfg = this.pluginConfig\n    const nested = cfg.providerSettings || {}\n    return {\n      openaiCompatibleApiKey: nested.openaiCompatibleApiKey || cfg.openaiCompatibleApiKey,\n      openaiCompatibleApiBase: nested.openaiCompatibleApiBase || cfg.openaiCompatibleApiBase,\n      openaiCompatibleExtraHeaders: nested.openaiCompatibleExtraHeaders || cfg.openaiCompatibleExtraHeaders,\n      gptOfficialApiKey: nested.gptOfficialApiKey || cfg.gptOfficialApiKey,\n      geminiOfficialApiKey: nested.geminiOfficialApiKey || cfg.geminiOfficialApiKey,\n    }\n  }\n\n  // ---------------------------------------------------------------------------\n  // 内部工具：风格预设收集\n  // ---------------------------------------------------------------------------\n\n  private collectStyleDefinitions(config: Config): ResolvedStyleConfig[] {\n    const unique = new Map<string, ResolvedStyleConfig>()\n\n    const pushStyle = (style?: StyleConfig, groupName?: string) => {\n      if (!style?.commandName || !style?.prompt) return\n      if (unique.has(style.commandName)) {\n        this.pluginLogger.warn('检测到重复的风格命令名称，已跳过', {\n          commandName: style.commandName,\n          groupName,\n        })\n        return\n      }\n      unique.set(style.commandName, {\n        ...style,\n        ...(groupName !== undefined ? { groupName } : {}),\n      })\n    }\n\n    if (Array.isArray(config.styles)) {\n      for (const style of config.styles) {\n        pushStyle(style)\n      }\n    }\n\n    if (config.styleGroups && typeof config.styleGroups === 'object') {\n      for (const [groupName, group] of Object.entries(config.styleGroups)) {\n        if (!groupName || !group || !Array.isArray(group.prompts)) continue\n        for (const style of group.prompts) {\n          pushStyle(style, groupName)\n        }\n      }\n    }\n\n    return Array.from(unique.values())\n  }\n}\n\n// ---------------------------------------------------------------------------\n// 文件级私有工具\n// ---------------------------------------------------------------------------\n\nfunction normalizeMatchText(value?: string | null): string {\n  return String(value || '')\n    .trim()\n    .toLowerCase()\n    .replace(/\\s+/g, '')\n}\n\nfunction buildRestrictedModelMessage(mapping: ModelMappingConfig): string {\n  const suffix = mapping.suffix?.trim()\n  const suffixLabel = suffix\n    ? (suffix.startsWith('-') ? suffix : `-${suffix}`)\n    : '该模型'\n  return ['模型受限', '', `- 模型｜${suffixLabel}`, '- 要求｜管理员或模型白名单'].join('\\n')\n}\n\nfunction buildQueryTerms(query: string): string[] {\n  const raw = String(query || '')\n    .toLowerCase()\n    .trim()\n\n  const compact = raw.replace(/\\s+/g, '')\n  const splitTerms = raw\n    .split(/[\\s,，。；;、|/]+/)\n    .map(item => item.trim())\n    .filter(Boolean)\n\n  const unique = new Set<string>()\n  if (compact) unique.add(compact)\n  for (const term of splitTerms) {\n    unique.add(term.replace(/\\s+/g, ''))\n  }\n\n  return Array.from(unique)\n}\n\nfunction redactHeadersForLog(value: unknown): Record<string, string> | undefined {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined\n  const result: Record<string, string> = {}\n  for (const [key, item] of Object.entries(value as Record<string, unknown>)) {\n    if (typeof item !== 'string') continue\n    const lower = key.toLowerCase()\n    result[key] = lower === 'authorization'\n      || lower.includes('api-key')\n      || lower.includes('apikey')\n      || lower.includes('token')\n      || lower.includes('secret')\n      ? '[REDACTED]'\n      : item.slice(0, 120)\n  }\n  return result\n}\n","import type { ConversationImageContext, GeneratedImageRecord } from '../shared/types.js'\n\nexport interface AddImageRecordOptions {\n  maxRecordsPerConversation?: number\n}\n\n/**\n * 内存级会话图像上下文存储（cherry-pick 自 v1，仅做 NodeNext 后缀适配）。\n *\n * 用于：\n * - 记录最近一次生成的图像（lastGenerated）\n * - 维护会话级最近 N 条记录（recentRecords）\n * - 支持后续图像上下文追踪与调试\n */\nexport class ImageContextStore {\n  private readonly conversations = new Map<string, ConversationImageContext>()\n\n  getConversationContext(conversationId: string) {\n    return this.conversations.get(conversationId)\n  }\n\n  getLastGenerated(conversationId: string) {\n    return this.conversations.get(conversationId)?.lastGenerated\n  }\n\n  addGeneratedRecord(record: GeneratedImageRecord, options: AddImageRecordOptions = {}) {\n    const maxRecords = options.maxRecordsPerConversation ?? 20\n    const existing = this.conversations.get(record.conversationId)\n    const recentRecords = existing?.recentRecords ? [...existing.recentRecords] : []\n\n    recentRecords.unshift(record)\n    if (recentRecords.length > maxRecords) {\n      recentRecords.length = maxRecords\n    }\n\n    const nextContext: ConversationImageContext = {\n      conversationId: record.conversationId,\n      lastGenerated: record,\n      recentRecords,\n      pinnedStylePreset: existing?.pinnedStylePreset,\n      pinnedCharacterNotes: existing?.pinnedCharacterNotes,\n      lastUpdatedAt: record.createdAt,\n    }\n\n    this.conversations.set(record.conversationId, nextContext)\n    return nextContext\n  }\n\n  clearConversation(conversationId: string) {\n    this.conversations.delete(conversationId)\n  }\n\n  clearAll() {\n    this.conversations.clear()\n  }\n\n  pruneExpired(ttlMs: number, now = Date.now()) {\n    for (const [conversationId, context] of this.conversations.entries()) {\n      if (now - context.lastUpdatedAt > ttlMs) {\n        this.conversations.delete(conversationId)\n      }\n    }\n  }\n}\n","import { existsSync, mkdirSync, promises as fs } from 'fs'\nimport { dirname, join } from 'path'\nimport type { Config } from '../shared/config.js'\nimport type { GenerationCost } from '../shared/billing.js'\nimport { roundCredits } from '../shared/billing.js'\n\nclass AsyncLock {\n  private promise: Promise<void> = Promise.resolve()\n\n  async acquire<T>(fn: () => Promise<T>): Promise<T> {\n    const previousPromise = this.promise\n    let release: () => void\n    const nextPromise = new Promise<void>((resolve) => {\n      release = resolve\n    })\n\n    this.promise = nextPromise\n    await previousPromise\n    try {\n      return await fn()\n    } finally {\n      release!()\n    }\n  }\n}\n\nexport interface CreditBalanceV2 {\n  dailyFreeCreditsUsed: number\n  dailyFreeCreditsLimitSnapshot: number\n  dailyResetDate: string\n  purchasedCredits: number\n  totalGrantedCredits: number\n  totalConsumedCredits: number\n  totalRefundedCredits: number\n}\n\nexport interface UserStatisticsV2 {\n  totalImagesGenerated: number\n  totalGenerationRequests: number\n  totalFailedRequests: number\n  lastModelId?: string\n  lastProvider?: string\n}\n\nexport interface UserFlagsV2 {\n  isBlocked?: boolean\n  note?: string\n}\n\nexport interface UserAccountV2 {\n  userId: string\n  userName: string\n  createdAt: string\n  updatedAt: string\n  lastUsedAt?: string\n  balance: CreditBalanceV2\n  statistics: UserStatisticsV2\n  flags: UserFlagsV2\n}\n\nexport interface UsersStoreV2 {\n  schemaVersion: 2\n  createdAt: string\n  updatedAt: string\n  users: Record<string, UserAccountV2>\n  metadata: {\n    plugin: 'aka-ai-image-generator'\n    billingUnit: 'credit'\n    lastLedgerSequence: number\n  }\n}\n\nexport interface CreditBalanceSnapshotV2 {\n  dailyFreeRemaining: number\n  purchasedCredits: number\n  totalAvailable: number\n  totalGrantedCredits: number\n  totalConsumedCredits: number\n  totalRefundedCredits: number\n}\n\nexport interface CreditLedgerEventV2 {\n  schemaVersion: 2\n  sequence: number\n  id: string\n  timestamp: string\n  userId: string\n  userName: string\n  type: 'grant' | 'consume' | 'refund' | 'adjust' | 'daily-reset' | 'migration'\n  amount: number\n  balanceBefore: CreditBalanceSnapshotV2\n  balanceAfter: CreditBalanceSnapshotV2\n  reason: string\n  operator?: {\n    userId: string\n    userName: string\n  }\n  generation?: {\n    commandName: string\n    provider?: string\n    modelId?: string\n    modelSuffix?: string\n    numImages: number\n    creditCostPerImage: number\n    totalCredits: number\n    requestId?: string\n  }\n  metadata?: Record<string, unknown>\n}\n\nexport interface RechargeRecordV2 {\n  schemaVersion: 2\n  id: string\n  timestamp: string\n  userId: string\n  userName: string\n  amount: number\n  reason: string\n  operator: {\n    userId: string\n    userName: string\n  }\n  externalPaymentNote?: string\n  estimatedCny?: number\n  ledgerSequence: number\n}\n\nexport interface CreditSummary {\n  userId: string\n  userName: string\n  dailyFreeRemaining: number\n  purchasedCredits: number\n  totalAvailable: number\n  totalGrantedCredits: number\n  totalConsumedCredits: number\n  totalRefundedCredits: number\n  totalImagesGenerated: number\n  totalGenerationRequests: number\n  lastUsedAt?: string\n  estimatedCny?: number\n}\n\nexport interface CreditConsumeResult {\n  userData: UserAccountV2\n  ledgerEvent?: CreditLedgerEventV2\n  freeUsed: number\n  purchasedUsed: number\n  isExempt: boolean\n}\n\nexport class UserManager {\n  private dataDir: string\n  private usersFile: string\n  private usersBackupFile: string\n  private ledgerFile: string\n  private rechargeRecordsFile: string\n  private snapshotsDir: string\n  private logger: any\n  private dataLock = new AsyncLock()\n  private ledgerLock = new AsyncLock()\n\n  private usersCache: UsersStoreV2 | null = null\n  private activeTasks = new Map<string, { requestId: string; startedAt: number; expiresAt: number }>()\n  private rateLimitMap = new Map<string, number[]>()\n  private securityBlockMap = new Map<string, number[]>()\n  private securityWarningMap = new Map<string, boolean>()\n\n  constructor(baseDir: string, logger: any) {\n    this.logger = logger\n    this.dataDir = baseDir\n    this.usersFile = join(this.dataDir, 'users.v2.json')\n    this.usersBackupFile = join(this.dataDir, 'users.v2.json.backup')\n    this.ledgerFile = join(this.dataDir, 'credit-ledger.v2.jsonl')\n    this.rechargeRecordsFile = join(this.dataDir, 'recharge-records.v2.jsonl')\n    this.snapshotsDir = join(this.dataDir, 'snapshots')\n\n    if (!existsSync(this.dataDir)) mkdirSync(this.dataDir, { recursive: true })\n    if (!existsSync(this.snapshotsDir)) mkdirSync(this.snapshotsDir, { recursive: true })\n  }\n\n  startTask(userId: string, ttlMs = 10 * 60 * 1000): string | undefined {\n    this.cleanupExpiredTasks()\n    if (this.activeTasks.has(userId)) return undefined\n\n    const now = Date.now()\n    const requestId = `${now}-${Math.random().toString(36).slice(2, 10)}`\n    this.activeTasks.set(userId, {\n      requestId,\n      startedAt: now,\n      expiresAt: now + Math.max(60 * 1000, ttlMs),\n    })\n    return requestId\n  }\n\n  endTask(userId: string, requestId?: string) {\n    const task = this.activeTasks.get(userId)\n    if (!task) return\n    if (requestId && task.requestId !== requestId) return\n    this.activeTasks.delete(userId)\n  }\n\n  isTaskActive(userId: string): boolean {\n    this.cleanupExpiredTasks()\n    return this.activeTasks.has(userId)\n  }\n\n  private cleanupExpiredTasks() {\n    const now = Date.now()\n    for (const [userId, task] of this.activeTasks) {\n      if (task.expiresAt <= now) {\n        this.logger.warn('清理过期图像任务锁', {\n          userId,\n          requestId: task.requestId,\n          ageMs: now - task.startedAt,\n        })\n        this.activeTasks.delete(userId)\n      }\n    }\n  }\n\n  isAdmin(userId: string, config: Config): boolean {\n    return !!(config.adminUsers && config.adminUsers.includes(userId))\n  }\n\n  isPermanentMember(userId: string, config: Config): boolean {\n    return !!(config.permanentMembers && config.permanentMembers.includes(userId))\n  }\n\n  isModelWhitelisted(userId: string, config: Config): boolean {\n    return this.isAdmin(userId, config) || !!(config.modelWhitelistUsers && config.modelWhitelistUsers.includes(userId))\n  }\n\n  private createEmptyStore(): UsersStoreV2 {\n    const now = new Date().toISOString()\n    return {\n      schemaVersion: 2,\n      createdAt: now,\n      updatedAt: now,\n      users: {},\n      metadata: {\n        plugin: 'aka-ai-image-generator',\n        billingUnit: 'credit',\n        lastLedgerSequence: 0,\n      },\n    }\n  }\n\n  private async loadUsersStore(): Promise<UsersStoreV2> {\n    if (this.usersCache) return this.usersCache\n\n    return await this.dataLock.acquire(async () => {\n      if (this.usersCache) return this.usersCache\n\n      try {\n        if (existsSync(this.usersFile)) {\n          const data = await fs.readFile(this.usersFile, 'utf-8')\n          const parsed = JSON.parse(data)\n          this.usersCache = this.normalizeStore(parsed)\n          return this.usersCache\n        }\n      } catch (error) {\n        this.logger.error('读取用户积分数据失败', error)\n        if (existsSync(this.usersBackupFile)) {\n          try {\n            const backupData = await fs.readFile(this.usersBackupFile, 'utf-8')\n            this.logger.warn('从备份文件恢复用户积分数据')\n            this.usersCache = this.normalizeStore(JSON.parse(backupData))\n            return this.usersCache\n          } catch (backupError) {\n            this.logger.error('用户积分备份文件也损坏，使用空数据', backupError)\n          }\n        }\n      }\n\n      this.usersCache = this.createEmptyStore()\n      await this.saveUsersStoreInternal()\n      return this.usersCache\n    })\n  }\n\n  private normalizeStore(value: any): UsersStoreV2 {\n    const now = new Date().toISOString()\n    if (value?.schemaVersion === 2 && value.users && typeof value.users === 'object') {\n      return {\n        schemaVersion: 2,\n        createdAt: value.createdAt || now,\n        updatedAt: value.updatedAt || now,\n        users: value.users,\n        metadata: {\n          plugin: 'aka-ai-image-generator',\n          billingUnit: 'credit',\n          lastLedgerSequence: Number(value.metadata?.lastLedgerSequence || 0),\n        },\n      }\n    }\n    return this.createEmptyStore()\n  }\n\n  private async saveUsersStoreInternal(): Promise<void> {\n    if (!this.usersCache) return\n\n    this.usersCache.updatedAt = new Date().toISOString()\n    try {\n      if (existsSync(this.usersFile)) {\n        await fs.copyFile(this.usersFile, this.usersBackupFile)\n      }\n      await this.atomicWriteFile(this.usersFile, JSON.stringify(this.usersCache, null, 2))\n    } catch (error) {\n      this.logger.error('保存用户积分数据失败', error)\n      throw error\n    }\n  }\n\n  private async atomicWriteFile(path: string, content: string): Promise<void> {\n    await fs.mkdir(dirname(path), { recursive: true })\n    const tempFile = `${path}.tmp`\n    await fs.writeFile(tempFile, content, 'utf-8')\n    await fs.rename(tempFile, path)\n  }\n\n  private todayKey(): string {\n    return new Date().toISOString().slice(0, 10)\n  }\n\n  private createUserAccount(userId: string, userName: string, config?: Config): UserAccountV2 {\n    const now = new Date().toISOString()\n    return {\n      userId,\n      userName: userName || userId,\n      createdAt: now,\n      updatedAt: now,\n      balance: {\n        dailyFreeCreditsUsed: 0,\n        dailyFreeCreditsLimitSnapshot: roundCredits(config?.dailyFreeCredits ?? 0),\n        dailyResetDate: this.todayKey(),\n        purchasedCredits: 0,\n        totalGrantedCredits: 0,\n        totalConsumedCredits: 0,\n        totalRefundedCredits: 0,\n      },\n      statistics: {\n        totalImagesGenerated: 0,\n        totalGenerationRequests: 0,\n        totalFailedRequests: 0,\n      },\n      flags: {},\n    }\n  }\n\n  private ensureDailyReset(userData: UserAccountV2, config: Config): boolean {\n    const today = this.todayKey()\n    if (userData.balance.dailyResetDate === today) return false\n    userData.balance.dailyResetDate = today\n    userData.balance.dailyFreeCreditsUsed = 0\n    userData.balance.dailyFreeCreditsLimitSnapshot = roundCredits(config.dailyFreeCredits ?? 0)\n    userData.updatedAt = new Date().toISOString()\n    return true\n  }\n\n  async getUserData(userId: string, userName: string, config?: Config): Promise<UserAccountV2> {\n    await this.loadUsersStore()\n\n    if (!this.usersCache!.users[userId]) {\n      await this.dataLock.acquire(async () => {\n        if (this.usersCache!.users[userId]) return\n        this.usersCache!.users[userId] = this.createUserAccount(userId, userName, config)\n        await this.saveUsersStoreInternal()\n        this.logger.info('创建用户积分数据', { userId, userName })\n      })\n    }\n\n    return this.usersCache!.users[userId]!\n  }\n\n  async getExistingUserData(userId: string): Promise<UserAccountV2 | undefined> {\n    const store = await this.loadUsersStore()\n    return store.users[userId]\n  }\n\n  async getAllUsers(): Promise<Record<string, UserAccountV2>> {\n    const store = await this.loadUsersStore()\n    return store.users\n  }\n\n  checkRateLimit(userId: string, config: Config): { allowed: boolean, message?: string } {\n    const now = Date.now()\n    const userTimestamps = this.rateLimitMap.get(userId) || []\n    const windowStart = now - config.rateLimitWindow * 1000\n    const validTimestamps = userTimestamps.filter(timestamp => timestamp > windowStart)\n    this.rateLimitMap.set(userId, validTimestamps)\n\n    if (validTimestamps.length >= config.rateLimitMax) {\n      const oldest = validTimestamps[0] ?? now\n      return {\n        allowed: false,\n        message: `操作过于频繁，请 ${Math.ceil((oldest + config.rateLimitWindow * 1000 - now) / 1000)} 秒后再试`,\n      }\n    }\n\n    return { allowed: true }\n  }\n\n  updateRateLimit(userId: string): void {\n    const now = Date.now()\n    const userTimestamps = this.rateLimitMap.get(userId) || []\n    userTimestamps.push(now)\n    this.rateLimitMap.set(userId, userTimestamps)\n  }\n\n  async checkAndReserveQuota(\n    userId: string,\n    userName: string,\n    cost: GenerationCost,\n    config: Config,\n    platform?: string,\n  ): Promise<{ allowed: boolean; message?: string; reservationId?: string }> {\n    if (this.isAdmin(userId, config)) return { allowed: true, reservationId: 'admin' }\n    if (this.isPermanentMember(userId, config)) return { allowed: true, reservationId: 'permanent_member' }\n    if (platform && config.unlimitedPlatforms?.includes(platform)) return { allowed: true, reservationId: 'platform_exempt' }\n\n    const rateLimitCheck = this.checkRateLimit(userId, config)\n    if (!rateLimitCheck.allowed) return { ...rateLimitCheck }\n    this.updateRateLimit(userId)\n\n    await this.loadUsersStore()\n    const userData = await this.getUserData(userId, userName, config)\n\n    return await this.dataLock.acquire(async () => {\n      const cachedUserData = this.usersCache!.users[userId] || userData\n      const reset = this.ensureDailyReset(cachedUserData, config)\n      if (reset) await this.saveUsersStoreInternal()\n\n      const summary = this.buildCreditSummary(cachedUserData, config)\n      if (summary.totalAvailable < cost.totalCredits) {\n        return {\n          allowed: false,\n          message: [\n            '积分不足',\n            '',\n            `- 本次需要｜${cost.totalCredits} ${config.creditUnitName}`,\n            `- 今日免费｜${summary.dailyFreeRemaining} ${config.creditUnitName}`,\n            `- 已购余额｜${summary.purchasedCredits} ${config.creditUnitName}`,\n            `- 合计可用｜${summary.totalAvailable} ${config.creditUnitName}`,\n          ].join('\\n'),\n        }\n      }\n\n      const reservationId = `${userId}_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`\n      return { allowed: true, reservationId }\n    })\n  }\n\n  async recordUsageOnly(\n    userId: string,\n    userName: string,\n    commandName: string,\n    numImages: number,\n    config: Config,\n  ): Promise<UserAccountV2> {\n    await this.loadUsersStore()\n\n    return await this.dataLock.acquire(async () => {\n      let userData = this.usersCache!.users[userId]\n      if (!userData) {\n        userData = this.createUserAccount(userId, userName, config)\n        this.usersCache!.users[userId] = userData\n      }\n      this.ensureDailyReset(userData, config)\n      const now = new Date().toISOString()\n      userData.userName = userName || userData.userName\n      userData.updatedAt = now\n      userData.lastUsedAt = now\n      userData.statistics.totalImagesGenerated += Math.max(0, Math.floor(numImages || 0))\n      userData.statistics.totalGenerationRequests += 1\n      userData.statistics.lastModelId = commandName\n      await this.saveUsersStoreInternal()\n      return userData\n    })\n  }\n\n  async consumeCredits(\n    userId: string,\n    userName: string,\n    commandName: string,\n    cost: GenerationCost,\n    config: Config,\n    requestId?: string,\n  ): Promise<CreditConsumeResult> {\n    await this.loadUsersStore()\n\n    return await this.dataLock.acquire(async () => {\n      let userData = this.usersCache!.users[userId]\n      if (!userData) {\n        userData = this.createUserAccount(userId, userName, config)\n        this.usersCache!.users[userId] = userData\n      }\n\n      this.ensureDailyReset(userData, config)\n      const before = this.snapshotBalance(userData, config)\n      const now = new Date().toISOString()\n      const totalCredits = roundCredits(cost.totalCredits)\n\n      let remaining = totalCredits\n      const freeAvailable = this.getDailyFreeRemaining(userData, config)\n      const freeUsed = Math.min(freeAvailable, remaining)\n      if (freeUsed > 0) {\n        userData.balance.dailyFreeCreditsUsed = roundCredits(userData.balance.dailyFreeCreditsUsed + freeUsed)\n        remaining = roundCredits(remaining - freeUsed)\n      }\n\n      const purchasedUsed = Math.min(userData.balance.purchasedCredits, remaining)\n      if (purchasedUsed > 0) {\n        userData.balance.purchasedCredits = roundCredits(userData.balance.purchasedCredits - purchasedUsed)\n        remaining = roundCredits(remaining - purchasedUsed)\n      }\n\n      if (remaining > 0) {\n        throw new Error(`积分扣费失败｜余额不足｜缺少 ${remaining} ${config.creditUnitName}`)\n      }\n\n      userData.userName = userName || userData.userName\n      userData.updatedAt = now\n      userData.lastUsedAt = now\n      userData.balance.totalConsumedCredits = roundCredits(userData.balance.totalConsumedCredits + totalCredits)\n      userData.statistics.totalImagesGenerated += cost.numImages\n      userData.statistics.totalGenerationRequests += 1\n      if (cost.modelId) userData.statistics.lastModelId = cost.modelId\n\n      const event = this.buildLedgerEvent(userData, 'consume', totalCredits, before, this.snapshotBalance(userData, config), '图像生成扣费', {\n        generation: {\n          commandName,\n          modelId: cost.modelId,\n          modelSuffix: cost.modelSuffix,\n          numImages: cost.numImages,\n          creditCostPerImage: cost.creditCostPerImage,\n          totalCredits,\n          requestId,\n        },\n        metadata: {\n          costSource: cost.costSource,\n        },\n      })\n\n      await this.appendLedgerEvent(event)\n      await this.saveUsersStoreInternal()\n      return { userData, ledgerEvent: event, freeUsed, purchasedUsed, isExempt: false }\n    })\n  }\n\n  async grantCredits(\n    userId: string,\n    userName: string,\n    amount: number,\n    reason: string,\n    operator: { userId: string; userName: string },\n    config: Config,\n  ): Promise<{ userData: UserAccountV2; ledgerEvent: CreditLedgerEventV2; rechargeRecord: RechargeRecordV2 }> {\n    await this.loadUsersStore()\n    const normalizedAmount = roundCredits(amount)\n    if (normalizedAmount <= 0) throw new Error('充值积分必须大于 0')\n\n    return await this.dataLock.acquire(async () => {\n      let userData = this.usersCache!.users[userId]\n      if (!userData) {\n        userData = this.createUserAccount(userId, userName, config)\n        this.usersCache!.users[userId] = userData\n      }\n      this.ensureDailyReset(userData, config)\n      const before = this.snapshotBalance(userData, config)\n      userData.userName = userName || userData.userName\n      userData.balance.purchasedCredits = roundCredits(userData.balance.purchasedCredits + normalizedAmount)\n      userData.balance.totalGrantedCredits = roundCredits(userData.balance.totalGrantedCredits + normalizedAmount)\n      userData.updatedAt = new Date().toISOString()\n\n      const event = this.buildLedgerEvent(userData, 'grant', normalizedAmount, before, this.snapshotBalance(userData, config), reason || '管理员充值', { operator })\n      await this.appendLedgerEvent(event)\n\n      const rechargeRecord: RechargeRecordV2 = {\n        schemaVersion: 2,\n        id: `recharge-${event.id}`,\n        timestamp: event.timestamp,\n        userId,\n        userName: userData.userName,\n        amount: normalizedAmount,\n        reason: reason || '管理员充值',\n        operator,\n        ...(config.creditsPerCny ? { estimatedCny: roundCredits(normalizedAmount / config.creditsPerCny) } : {}),\n        ledgerSequence: event.sequence,\n      }\n      await this.appendJsonLine(this.rechargeRecordsFile, rechargeRecord)\n      await this.saveUsersStoreInternal()\n      return { userData, ledgerEvent: event, rechargeRecord }\n    })\n  }\n\n  async adjustCredits(\n    userId: string,\n    userName: string,\n    amount: number,\n    reason: string,\n    operator: { userId: string; userName: string },\n    config: Config,\n  ): Promise<{\n    userData: UserAccountV2\n    ledgerEvent?: CreditLedgerEventV2\n    requestedAmount: number\n    deductedAmount: number\n    isPartial: boolean\n  }> {\n    await this.loadUsersStore()\n    const normalizedAmount = roundCredits(amount)\n    if (normalizedAmount <= 0) throw new Error('调整积分必须大于 0')\n\n    return await this.dataLock.acquire(async () => {\n      let userData = this.usersCache!.users[userId]\n      if (!userData) {\n        userData = this.createUserAccount(userId, userName, config)\n        this.usersCache!.users[userId] = userData\n      }\n      this.ensureDailyReset(userData, config)\n      const before = this.snapshotBalance(userData, config)\n      const deduct = roundCredits(Math.min(userData.balance.purchasedCredits, normalizedAmount))\n      if (deduct <= 0) {\n        await this.saveUsersStoreInternal()\n        return {\n          userData,\n          requestedAmount: normalizedAmount,\n          deductedAmount: 0,\n          isPartial: true,\n        }\n      }\n\n      userData.balance.purchasedCredits = roundCredits(userData.balance.purchasedCredits - deduct)\n      userData.balance.totalConsumedCredits = roundCredits(userData.balance.totalConsumedCredits + deduct)\n      userData.updatedAt = new Date().toISOString()\n\n      const event = this.buildLedgerEvent(userData, 'adjust', deduct, before, this.snapshotBalance(userData, config), reason || '管理员余额修正', { operator })\n      await this.appendLedgerEvent(event)\n      await this.saveUsersStoreInternal()\n      return {\n        userData,\n        ledgerEvent: event,\n        requestedAmount: normalizedAmount,\n        deductedAmount: deduct,\n        isPartial: deduct < normalizedAmount,\n      }\n    })\n  }\n\n  async listLedgerEvents(userId?: string, limit = 10): Promise<CreditLedgerEventV2[]> {\n    try {\n      if (!existsSync(this.ledgerFile)) return []\n      const content = await fs.readFile(this.ledgerFile, 'utf-8')\n      const lines = content.split('\\n').map(line => line.trim()).filter(Boolean)\n      const rows: CreditLedgerEventV2[] = []\n      for (let index = lines.length - 1; index >= 0 && rows.length < limit; index--) {\n        try {\n          const event = JSON.parse(lines[index]!) as CreditLedgerEventV2\n          if (!userId || event.userId === userId) rows.push(event)\n        } catch (error) {\n          this.logger.warn('跳过损坏的积分流水行', { index, error })\n        }\n      }\n      return rows\n    } catch (error) {\n      this.logger.error('读取积分流水失败', error)\n      return []\n    }\n  }\n\n  buildCreditSummary(userData: UserAccountV2, config: Config): CreditSummary {\n    this.ensureDailyReset(userData, config)\n    const dailyFreeRemaining = this.getDailyFreeRemaining(userData, config)\n    const purchasedCredits = roundCredits(userData.balance.purchasedCredits)\n    const totalAvailable = roundCredits(dailyFreeRemaining + purchasedCredits)\n    const summary: CreditSummary = {\n      userId: userData.userId,\n      userName: userData.userName,\n      dailyFreeRemaining,\n      purchasedCredits,\n      totalAvailable,\n      totalGrantedCredits: roundCredits(userData.balance.totalGrantedCredits),\n      totalConsumedCredits: roundCredits(userData.balance.totalConsumedCredits),\n      totalRefundedCredits: roundCredits(userData.balance.totalRefundedCredits),\n      totalImagesGenerated: userData.statistics.totalImagesGenerated,\n      totalGenerationRequests: userData.statistics.totalGenerationRequests,\n      ...(userData.lastUsedAt ? { lastUsedAt: userData.lastUsedAt } : {}),\n    }\n    if (config.showEstimatedCny && config.creditsPerCny && config.creditsPerCny > 0) {\n      summary.estimatedCny = roundCredits(totalAvailable / config.creditsPerCny)\n    }\n    return summary\n  }\n\n  private getDailyFreeRemaining(userData: UserAccountV2, config: Config): number {\n    const limit = roundCredits(userData.balance.dailyFreeCreditsLimitSnapshot ?? config.dailyFreeCredits ?? 0)\n    return roundCredits(Math.max(0, limit - userData.balance.dailyFreeCreditsUsed))\n  }\n\n  private snapshotBalance(userData: UserAccountV2, config: Config): CreditBalanceSnapshotV2 {\n    const dailyFreeRemaining = this.getDailyFreeRemaining(userData, config)\n    const purchasedCredits = roundCredits(userData.balance.purchasedCredits)\n    return {\n      dailyFreeRemaining,\n      purchasedCredits,\n      totalAvailable: roundCredits(dailyFreeRemaining + purchasedCredits),\n      totalGrantedCredits: roundCredits(userData.balance.totalGrantedCredits),\n      totalConsumedCredits: roundCredits(userData.balance.totalConsumedCredits),\n      totalRefundedCredits: roundCredits(userData.balance.totalRefundedCredits),\n    }\n  }\n\n  private buildLedgerEvent(\n    userData: UserAccountV2,\n    type: CreditLedgerEventV2['type'],\n    amount: number,\n    balanceBefore: CreditBalanceSnapshotV2,\n    balanceAfter: CreditBalanceSnapshotV2,\n    reason: string,\n    extra: Partial<Pick<CreditLedgerEventV2, 'operator' | 'generation' | 'metadata'>> = {},\n  ): CreditLedgerEventV2 {\n    const sequence = (this.usersCache?.metadata.lastLedgerSequence || 0) + 1\n    if (this.usersCache) this.usersCache.metadata.lastLedgerSequence = sequence\n    const timestamp = new Date().toISOString()\n    return {\n      schemaVersion: 2,\n      sequence,\n      id: `ledger-${sequence}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n      timestamp,\n      userId: userData.userId,\n      userName: userData.userName,\n      type,\n      amount: roundCredits(amount),\n      balanceBefore,\n      balanceAfter,\n      reason,\n      ...(extra.operator ? { operator: extra.operator } : {}),\n      ...(extra.generation ? { generation: extra.generation } : {}),\n      ...(extra.metadata ? { metadata: extra.metadata } : {}),\n    }\n  }\n\n  private async appendLedgerEvent(event: CreditLedgerEventV2): Promise<void> {\n    await this.ledgerLock.acquire(async () => {\n      await this.appendJsonLine(this.ledgerFile, event)\n    })\n  }\n\n  private async appendJsonLine(path: string, value: unknown): Promise<void> {\n    await fs.mkdir(dirname(path), { recursive: true })\n    await fs.appendFile(path, `${JSON.stringify(value)}\\n`, 'utf-8')\n  }\n\n  async recordSecurityBlock(userId: string, config: Config): Promise<{ shouldWarn: boolean, shouldDeduct: boolean, blockCount: number }> {\n    if (!userId) return { shouldWarn: false, shouldDeduct: false, blockCount: 0 }\n    if (this.isAdmin(userId, config)) return { shouldWarn: false, shouldDeduct: false, blockCount: 0 }\n\n    const now = Date.now()\n    const windowMs = config.securityBlockWindow * 1000\n    const windowStart = now - windowMs\n\n    let blockTimestamps = this.securityBlockMap.get(userId) || []\n    blockTimestamps = blockTimestamps.filter(timestamp => timestamp > windowStart)\n    blockTimestamps.push(now)\n    this.securityBlockMap.set(userId, blockTimestamps)\n\n    const blockCount = blockTimestamps.length\n    const hasWarning = this.securityWarningMap.get(userId) || false\n\n    let shouldWarn = false\n    let shouldDeduct = false\n    if (blockCount >= config.securityBlockWarningThreshold && !hasWarning) {\n      this.securityWarningMap.set(userId, true)\n      shouldWarn = true\n    } else if (blockCount > config.securityBlockWarningThreshold) {\n      shouldDeduct = true\n    }\n\n    return { shouldWarn, shouldDeduct, blockCount }\n  }\n}\n","/**\n * V2 配置 Schema —— image-only，供应商语义 + 协议路由版本。\n *\n * 设计要点：\n * - 配置页顶层只暴露“OpenAI 兼容 / Gemini 官方 / GPT 官方”三类供应商入口。\n * - 每个供应商只负责凭证；模型统一在模型映射中配置。\n * - 模型映射显式配置 supplier（凭证入口）+ protocol（运行时协议通道）。\n * - 所有数值配置使用数字输入，不使用滑竿。\n */\nimport { Schema } from 'koishi'\nimport type {\n  ImageProvider,\n  ModelMappingConfig,\n  StyleConfig,\n  StyleGroupConfig,\n} from './types.js'\nimport type { LogLevel } from './logging.js'\n\n// ----------------------------------------------------------------------------\n// 运行期 Config interface\n// ----------------------------------------------------------------------------\n\nexport interface ProviderSettingsConfig {\n  // OpenAI-compatible 第三方站点\n  openaiCompatibleApiKey?: string\n  openaiCompatibleApiBase?: string\n  openaiCompatibleExtraHeaders?: Record<string, string>\n\n  // OpenAI 官方 GPT\n  gptOfficialApiKey?: string\n\n  // Gemini 官方\n  geminiOfficialApiKey?: string\n}\n\nconst SETUP_GUIDE = [\n  '首次配置：先填供应商凭证 → 检查模型映射与每张积分 → 按需配置快捷命令。',\n  '模型规则：模型映射第一条是默认模型；聊天命令可用 -后缀 临时切换模型。',\n  '计费规则：生成前按请求张数预检积分，生成后按成功发送图片数扣费。',\n  '',\n  '普通用户：',\n  '文生图 <描述>                     文字生成图片，例如：文生图 一只猫 -16:9',\n  '图生图 [图片] <描述>              单张参考图修改，例如：图生图 改成赛博朋克风格',\n  '合成图 <描述>                     收集多张图片后合成，例如：合成图 把人物放到海报里',\n  '图像查询                          查询自己的积分余额、已生成张数和历史消耗',\n  '图像账单 [-n 数量]                查询自己的最近积分流水',\n  '图像指令                          查看核心命令和快捷命令',\n  '图像参数                          查看 -n、尺寸、比例、模型后缀等参数',\n  '',\n  '管理员：',\n  '图像查询 @用户                    查询指定用户积分和统计',\n  '图像账单 @用户 [-n 数量]          查询指定用户最近流水',\n  '图像账单 --all [-n 数量]          查询全局最近流水',\n  '图像充值 @用户 积分 [原因]        给用户充值；积分为负数时作为余额修正',\n  '图像排行榜 [-n 数量]              查看用户生成和消耗排行',\n  '',\n  '常用参数：-n 1-4、-1k/-2k/-4k、-1:1/-4:3/-16:9/-9:16、-add 补充要求、-模型后缀。',\n  '权限说明：受限模型需要管理员或模型白名单；白名单不代表免费。管理员、永久会员和豁免平台跳过扣费与限流，但仍记录统计。',\n].join('\\n')\n\nexport interface Config {\n  // ── ⓪ 初始化说明 ──────────────────────────────────────────────────────────\n  setupGuide?: string\n\n  // ── ① 供应商凭证 ──────────────────────────────────────────────────────────\n  /** @deprecated 0.5.9 起不再使用全局 provider 单选，保留字段避免 Koishi 反序列化报错 */\n  provider?: ImageProvider\n  providerSettings?: ProviderSettingsConfig\n\n  // Legacy flat provider fields kept for runtime fallback when upgrading from <= 0.5.8.\n  openaiCompatibleApiKey?: string\n  openaiCompatibleApiBase?: string\n  openaiCompatibleExtraHeaders?: Record<string, string>\n  gptOfficialApiKey?: string\n  geminiOfficialApiKey?: string\n\n  // ── ② 图像生成 ────────────────────────────────────────────────────────────\n  styles: StyleConfig[]\n  styleGroups?: Record<string, StyleGroupConfig>\n  showQuotaInImageCommands: boolean\n  defaultNumImages: number\n\n  // ── ③ 模型映射 ────────────────────────────────────────────────────────────\n  modelMappings?: ModelMappingConfig[]\n\n  // ── ④ 积分计费 ────────────────────────────────────────────────────────────\n  creditUnitName: string\n  defaultCreditCostPerImage: number\n  dailyFreeCredits: number\n  showCreditCostInResult: boolean\n  creditsPerCny?: number\n  showEstimatedCny?: boolean\n  minRechargeCredits?: number\n  unlimitedPlatforms: string[]\n  rateLimitWindow: number\n  rateLimitMax: number\n\n  // ── ⑤ 安全策略 ────────────────────────────────────────────────────────────\n  securityBlockWindow: number\n  securityBlockWarningThreshold: number\n\n  // ── ⑥ 管理员设置 ──────────────────────────────────────────────────────────\n  adminUsers: string[]\n  permanentMembers: string[]\n  modelWhitelistUsers: string[]\n  logLevel: LogLevel\n\n  // ── ⑦ ChatLuna 集成 ───────────────────────────────────────────────────────\n  chatlunaEnabled: boolean\n  chatlunaContextInjectionEnabled: boolean\n  chatlunaExposeQuotaTool: boolean\n  chatlunaExposeStyleListTool: boolean\n  chatlunaContextHistorySize: number\n  chatlunaContextTtlSeconds: number\n  chatlunaPreferLastGeneratedInPrivateRoom: boolean\n\n  // ── ⑧ YesImBot 集成 ──────────────────────────────────────────────────────\n  yesimbotEnabled: boolean\n  yesimbotExposeQuotaTool: boolean\n  yesimbotExposeStyleListTool: boolean\n\n  // ── 通用 ──────────────────────────────────────────────────────────────────\n  apiTimeout: number\n}\n\n// ----------------------------------------------------------------------------\n// 子 Schema\n// ----------------------------------------------------------------------------\n\nconst StyleItemSchema = Schema.object({\n  commandName: Schema.string()\n    .required()\n    .description('命令名')\n    .role('table-cell', { width: 24 }),\n  mode: Schema.union([\n    Schema.const('text-to-image').description('文生图'),\n    Schema.const('image-to-image').description('图生图'),\n    Schema.const('compose-image').description('合成图'),\n  ])\n    .default('image-to-image')\n    .description('生成模式')\n    .role('table-cell', { width: 24 }),\n  modelSuffix: Schema.string()\n    .default('')\n    .description('生成模型')\n    .role('table-cell', { width: 24 }),\n  description: Schema.string()\n    .role('textarea', { rows: 2 })\n    .description('帮助说明'),\n  prompt: Schema.string()\n    .role('textarea', { rows: 6 })\n    .required()\n    .description('提示词'),\n})\n\nconst ProviderSettingsSchema = Schema.object({\n  openaiCompatibleApiKey: Schema.string()\n    .role('secret')\n    .default('')\n    .description('第三方 Key，用于云雾等兼容站点'),\n  openaiCompatibleApiBase: Schema.string()\n    .default('https://yunwu.ai/v1')\n    .description('第三方 Base，通常以 /v1 结尾'),\n  openaiCompatibleExtraHeaders: Schema.dict(Schema.string())\n    .default({})\n    .description('额外请求头；不需要时留空'),\n\n  gptOfficialApiKey: Schema.string()\n    .role('secret')\n    .default('')\n    .description('OpenAI Key，仅用于官方 OpenAI'),\n\n  geminiOfficialApiKey: Schema.string()\n    .role('secret')\n    .default('')\n    .description('Gemini Key，仅用于 Google 官方 Gemini'),\n})\n\n// 顶层供应商分组：不再使用单选 union，改为直接展示三个凭证区（默认收起）\nconst SupplierSchema = Schema.object({\n  providerSettings: ProviderSettingsSchema\n    .description('配置各供应商的 API Key 与接口地址')\n    .collapse(),\n}).description('🎨 供应商')\n\n// ----------------------------------------------------------------------------\n// 顶层 Schema\n// ----------------------------------------------------------------------------\n\nexport const Config = Schema.intersect([\n  // ⓪ 初始化说明（只读引导）\n  Schema.object({\n    setupGuide: Schema.string()\n      .role('textarea', { rows: 22 })\n      .default(SETUP_GUIDE)\n      .description('只读速查：首次配置顺序、聊天命令和管理员命令')\n      .disabled(),\n  }).description('📌 使用说明 / 命令速查'),\n\n  // ① 供应商（直接展示凭证，无单选）\n  SupplierSchema,\n\n  // ② 模型映射（先定义可用模型后缀，再供命令参数与 prompt 预设引用）\n  Schema.object({\n    modelMappings: Schema.array(\n      Schema.object({\n        suffix: Schema.string().required().description('命令名'),\n        modelId: Schema.string().required().description('模型 ID'),\n        supplier: Schema.union([\n          Schema.const('openai-compatible').description('第三方'),\n          Schema.const('gpt-official').description('OpenAI'),\n          Schema.const('gemini-official').description('Gemini'),\n        ])\n          .default('openai-compatible')\n          .description('供应商'),\n        protocol: Schema.union([\n          Schema.const('openai').description('OpenAI'),\n          Schema.const('gemini').description('Gemini'),\n        ])\n          .default('openai')\n          .description('接口格式'),\n        restricted: Schema.boolean()\n          .default(false)\n          .description('限制项'),\n        creditCostPerImage: Schema.number()\n          .default(1)\n          .min(0)\n          .max(100000)\n          .step(0.01)\n          .description('每张积分，支持小数'),\n      }).collapse()\n    )\n      .role('table')\n      .default([\n        {\n          suffix: 'gpt',\n          modelId: 'gpt-image-2',\n          supplier: 'gpt-official',\n          protocol: 'openai',\n          restricted: false,\n          creditCostPerImage: 1,\n        },\n        {\n          suffix: 'gemini',\n          modelId: 'gemini-3-pro-image-preview',\n          supplier: 'openai-compatible',\n          protocol: 'gemini',\n          restricted: false,\n          creditCostPerImage: 1,\n        },\n      ])\n      .description('模型路由；第一条为默认模型，快捷命令可通过模型后缀引用'),\n  }).description('🔀 模型映射').collapse(),\n\n  // ③ Prompt 预设 / 快捷命令\n  Schema.object({\n    styles: Schema.array(StyleItemSchema)\n      .role('table')\n      .default([\n        {\n          commandName: '变手办',\n          mode: 'image-to-image',\n          modelSuffix: '',\n          description: '图像风格转换',\n          prompt:\n            '将这张照片变成手办模型。在它后面放置一个印有图像主体的盒子，桌子上有一台电脑显示Blender建模过程。在盒子前面添加一个圆形塑料底座，角色手办站在上面。如果可能的话，将场景设置在室内',\n        },\n        {\n          commandName: '变写实',\n          mode: 'image-to-image',\n          modelSuffix: '',\n          description: '图像风格转换',\n          prompt:\n            '请根据用户提供的图片，在严格保持主体身份、外观特征与姿态不变的前提下，生成一张照片级真实感的超写实摄影作品。要求：1. 采用专业相机拍摄（如佳能EOS R5），使用85mm f/1.4人像镜头；2. 画面应具有照片级真实感、超现实主义风格和高细节表现；3. 使用自然光影营造真实氛围；4. 整体效果需像专业摄影棚拍摄的真实照片。',\n        },\n      ])\n      .description('直接注册为聊天命令的 Prompt 预设；重载配置后自动刷新'),\n    styleGroups: Schema.dict(\n      Schema.object({\n        prompts: Schema.array(StyleItemSchema)\n          .role('table')\n          .default([])\n          .description('本分组内的快捷命令预设'),\n      })\n    )\n      .role('table')\n      .default({})\n      .description('按分组管理快捷命令；重载配置后自动刷新'),\n  }).description('🧩 Prompt 预设 / 快捷命令'),\n\n  // ④ 管理员与运营\n  Schema.object({\n    adminUsers: Schema.array(Schema.string())\n      .default([])\n      .description('管理员用户 ID；可查询他人、充值或余额修正、查账并使用受限模型'),\n  }).description('👑 管理员与运营'),\n\n  // ⑤ 用户豁免与白名单\n  Schema.object({\n    permanentMembers: Schema.array(Schema.string())\n      .default([])\n      .description('跳过积分扣费和限流，但不自动获得受限模型权限'),\n    modelWhitelistUsers: Schema.array(Schema.string())\n      .default([])\n      .description('允许使用受限模型；不代表免费或管理员权限'),\n  }).description('🪪 用户豁免与白名单').collapse(),\n\n  // ⑥ 积分计费与限流\n  Schema.object({\n    creditUnitName: Schema.string()\n      .default('积分')\n      .description('聊天输出里的余额单位'),\n    defaultCreditCostPerImage: Schema.number()\n      .default(1)\n      .min(0)\n      .max(100000)\n      .step(0.01)\n      .description('模型未设置单价时，每张图消耗的积分，支持小数'),\n    dailyFreeCredits: Schema.number()\n      .default(5)\n      .min(0)\n      .max(100000)\n      .step(0.01)\n      .description('普通用户每天免费积分，支持小数'),\n    showCreditCostInResult: Schema.boolean()\n      .default(true)\n      .description('生成完成后显示本次消耗和剩余积分'),\n    creditsPerCny: Schema.number()\n      .default(0)\n      .min(0)\n      .max(100000)\n      .step(0.01)\n      .description('经营参考：1 元对应多少积分；0 表示不估算，支持小数'),\n    showEstimatedCny: Schema.boolean()\n      .default(false)\n      .description('管理员查询时显示余额估算金额'),\n    minRechargeCredits: Schema.number()\n      .default(0)\n      .min(0)\n      .max(1000000)\n      .step(0.01)\n      .description('充值提示用最低积分，支持小数；不限制管理员输入'),\n    unlimitedPlatforms: Schema.array(Schema.string())\n      .default(['lark'])\n      .description('这些平台跳过积分扣费和限流'),\n    rateLimitWindow: Schema.number()\n      .default(300)\n      .min(60)\n      .max(3600)\n      .step(30)\n      .description('限流统计窗口，单位秒'),\n    rateLimitMax: Schema.number()\n      .default(3)\n      .min(1)\n      .max(20)\n      .step(1)\n      .description('每个窗口内允许的请求次数'),\n  }).description('💳 积分计费与限流').collapse(),\n\n  // ⑥ 安全策略\n  Schema.object({\n    securityBlockWindow: Schema.number()\n      .default(600)\n      .min(60)\n      .max(3600)\n      .step(60)\n      .description('安全拦截统计窗口，单位秒'),\n    securityBlockWarningThreshold: Schema.number()\n      .default(3)\n      .min(1)\n      .max(10)\n      .step(1)\n      .description('窗口内触发多少次拦截后给出警示'),\n  }).description('🛡️ 安全策略').collapse(),\n\n  // ⑦ ChatLuna 集成（默认收起）\n  Schema.object({\n    chatlunaEnabled: Schema.boolean()\n      .default(false)\n      .description('启用后会在 ChatLuna 中注册图像生成工具，支持自然语言驱动生成'),\n    chatlunaContextInjectionEnabled: Schema.boolean()\n      .default(true)\n      .description('在 ChatLuna 对话开始前注入最近图像上下文，支持“继续上一张”等自然语言跟进'),\n    chatlunaExposeQuotaTool: Schema.boolean()\n      .default(true)\n      .description('是否暴露积分查询工具给 ChatLuna'),\n    chatlunaExposeStyleListTool: Schema.boolean()\n      .default(true)\n      .description('是否暴露风格列表工具给 ChatLuna'),\n    chatlunaContextHistorySize: Schema.number()\n      .default(20)\n      .min(1)\n      .max(100)\n      .step(1)\n      .description('每个 ChatLuna 会话保留的图像上下文条数'),\n    chatlunaContextTtlSeconds: Schema.number()\n      .default(86400)\n      .min(3600)\n      .max(604800)\n      .step(3600)\n      .description('图像上下文过期时间，单位秒；默认 24 小时'),\n    chatlunaPreferLastGeneratedInPrivateRoom: Schema.boolean()\n      .default(true)\n      .description('私有房间中自动将“上一张”等自然语言映射到最近生成的图像'),\n  }).description('💬 ChatLuna 集成').collapse(),\n\n  // ⑧ YesImBot 集成（默认收起）\n  Schema.object({\n    yesimbotEnabled: Schema.boolean()\n      .default(false)\n      .description('启用后会在 YesImBot 中注册 AI 图像生成工具，让 YesImBot 可以调用本插件的图像生成能力'),\n    yesimbotExposeQuotaTool: Schema.boolean()\n      .default(true)\n      .description('是否向 YesImBot 暴露积分查询工具'),\n    yesimbotExposeStyleListTool: Schema.boolean()\n      .default(true)\n      .description('是否向 YesImBot 暴露风格列表工具'),\n  }).description('🤖 YesImBot 集成').collapse(),\n\n  // ⚙️ 运行与诊断\n  Schema.object({\n    logLevel: Schema.union([\n      Schema.const('simple').description('simple'),\n      Schema.const('detail').description('detail'),\n    ])\n      .default('simple')\n      .description('日志级别；simple 记录关键流程，detail 增加脱敏请求诊断'),\n    showQuotaInImageCommands: Schema.boolean()\n      .default(true)\n      .description('生成完成后额外显示剩余积分明细（需先开启\"显示本次消耗\"）'),\n    defaultNumImages: Schema.number()\n      .default(1)\n      .min(1)\n      .max(4)\n      .step(1)\n      .description('未填写 -n 时默认生成的图片数量'),\n    apiTimeout: Schema.number()\n      .default(60)\n      .min(10)\n      .max(600)\n      .step(10)\n      .description('上游请求超时时间，单位秒'),\n  }).description('🧰 运行与诊断').collapse(),\n]) as unknown as Schema<Config>\n"],"mappings":"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","names":["name","sanitizeToolName","name","h","runGenerateImageTool","runEditImageTool","runStylePresetTool","runGetQuotaTool","withImageTaskLock","expectString","buildRequestContextAndCost","summarizeImageUrl","resolveReferenceImages","resolveRequestedStylePreset","VALID_ASPECT_RATIOS","VALID_RESOLUTIONS","CUSTOM_RESOLUTION_RE","normalizeImageUrls","parseImagesFromMessageContent","h","h","h","resolveCommandNum","result","summary","h","name","formatCredits","h","h","h","DEFAULT_API_BASE","truncate","name","providerRegistry","platformPrefix","path","Schema","Config","ctx"]}