sa2kit 3.3.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. package/dist/{chunk-LGVPFYPR.mjs → chunk-4H3SGG3T.mjs} +27 -3
  2. package/dist/chunk-4H3SGG3T.mjs.map +1 -0
  3. package/dist/{chunk-KVYHCGRY.js → chunk-7Z3XR2Y4.js} +552 -263
  4. package/dist/chunk-7Z3XR2Y4.js.map +1 -0
  5. package/dist/{chunk-5H2FICSO.js → chunk-LBMUIWJR.js} +27 -3
  6. package/dist/chunk-LBMUIWJR.js.map +1 -0
  7. package/dist/chunk-XPY45Y75.js +1143 -0
  8. package/dist/chunk-XPY45Y75.js.map +1 -0
  9. package/dist/{chunk-YIRPPMCN.mjs → chunk-XSTMLLJV.mjs} +474 -198
  10. package/dist/chunk-XSTMLLJV.mjs.map +1 -0
  11. package/dist/chunk-ZJLS5JU5.mjs +1090 -0
  12. package/dist/chunk-ZJLS5JU5.mjs.map +1 -0
  13. package/dist/common/aiApi/client/index.d.mts +71 -0
  14. package/dist/common/aiApi/client/index.d.ts +71 -0
  15. package/dist/common/aiApi/client/index.js +165 -0
  16. package/dist/common/aiApi/client/index.js.map +1 -0
  17. package/dist/common/aiApi/client/index.mjs +151 -0
  18. package/dist/common/aiApi/client/index.mjs.map +1 -0
  19. package/dist/common/aiApi/index.d.mts +184 -0
  20. package/dist/common/aiApi/index.d.ts +184 -0
  21. package/dist/common/aiApi/index.js +217 -0
  22. package/dist/common/aiApi/index.mjs +4 -0
  23. package/dist/common/aiApi/server/index.d.mts +3 -0
  24. package/dist/common/aiApi/server/index.d.ts +3 -0
  25. package/dist/common/aiApi/server/index.js +217 -0
  26. package/dist/common/aiApi/server/index.mjs +4 -0
  27. package/dist/common/auth/server/index.js +8 -8
  28. package/dist/common/auth/server/index.mjs +2 -2
  29. package/dist/common/components/index.js +176 -177
  30. package/dist/common/components/index.mjs +1 -2
  31. package/dist/common/config/bootstrap/index.d.mts +24 -0
  32. package/dist/common/config/bootstrap/index.d.ts +24 -0
  33. package/dist/common/config/bootstrap/index.js +15 -15
  34. package/dist/common/config/bootstrap/index.mjs +1 -1
  35. package/dist/common/config/server/index.js +14 -14
  36. package/dist/common/config/server/index.mjs +1 -1
  37. package/dist/common/index.js +2 -3
  38. package/dist/common/index.mjs +1 -2
  39. package/dist/index.d.mts +314 -154
  40. package/dist/index.d.ts +314 -154
  41. package/dist/index.js +1055 -369
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +1005 -360
  44. package/dist/index.mjs.map +1 -1
  45. package/dist/types-CiqMQ-uu.d.mts +166 -0
  46. package/dist/types-CiqMQ-uu.d.ts +166 -0
  47. package/package.json +15 -50
  48. package/dist/chunk-3R6JHA6D.js +0 -120
  49. package/dist/chunk-3R6JHA6D.js.map +0 -1
  50. package/dist/chunk-4PJM4752.js +0 -4
  51. package/dist/chunk-4PJM4752.js.map +0 -1
  52. package/dist/chunk-5H2FICSO.js.map +0 -1
  53. package/dist/chunk-7PMT4L4I.js +0 -324
  54. package/dist/chunk-7PMT4L4I.js.map +0 -1
  55. package/dist/chunk-FY2X3LYR.mjs +0 -3
  56. package/dist/chunk-FY2X3LYR.mjs.map +0 -1
  57. package/dist/chunk-GS4SAW25.mjs +0 -116
  58. package/dist/chunk-GS4SAW25.mjs.map +0 -1
  59. package/dist/chunk-HL4H2HF6.js +0 -279
  60. package/dist/chunk-HL4H2HF6.js.map +0 -1
  61. package/dist/chunk-IJIQUMAK.mjs +0 -272
  62. package/dist/chunk-IJIQUMAK.mjs.map +0 -1
  63. package/dist/chunk-KVYHCGRY.js.map +0 -1
  64. package/dist/chunk-LGVPFYPR.mjs.map +0 -1
  65. package/dist/chunk-MMDSZIXD.mjs +0 -286
  66. package/dist/chunk-MMDSZIXD.mjs.map +0 -1
  67. package/dist/chunk-N2O3OX5Y.mjs +0 -243
  68. package/dist/chunk-N2O3OX5Y.mjs.map +0 -1
  69. package/dist/chunk-RRQ2X26Z.js +0 -106
  70. package/dist/chunk-RRQ2X26Z.js.map +0 -1
  71. package/dist/chunk-RVNQI6BI.js +0 -249
  72. package/dist/chunk-RVNQI6BI.js.map +0 -1
  73. package/dist/chunk-UJUWDF7M.mjs +0 -336
  74. package/dist/chunk-UJUWDF7M.mjs.map +0 -1
  75. package/dist/chunk-VCKXK6V5.js +0 -345
  76. package/dist/chunk-VCKXK6V5.js.map +0 -1
  77. package/dist/chunk-VIEXDTNF.mjs +0 -100
  78. package/dist/chunk-VIEXDTNF.mjs.map +0 -1
  79. package/dist/chunk-YIRPPMCN.mjs.map +0 -1
  80. package/dist/common/ai/llm/core/index.d.mts +0 -70
  81. package/dist/common/ai/llm/core/index.d.ts +0 -70
  82. package/dist/common/ai/llm/core/index.js +0 -54
  83. package/dist/common/ai/llm/core/index.mjs +0 -5
  84. package/dist/common/ai/llm/electron/index.d.mts +0 -6
  85. package/dist/common/ai/llm/electron/index.d.ts +0 -6
  86. package/dist/common/ai/llm/electron/index.js +0 -67
  87. package/dist/common/ai/llm/electron/index.mjs +0 -10
  88. package/dist/common/ai/llm/index.d.mts +0 -3
  89. package/dist/common/ai/llm/index.d.ts +0 -3
  90. package/dist/common/ai/llm/index.js +0 -54
  91. package/dist/common/ai/llm/index.js.map +0 -1
  92. package/dist/common/ai/llm/index.mjs +0 -5
  93. package/dist/common/ai/llm/index.mjs.map +0 -1
  94. package/dist/common/ai/llm/miniapp/index.d.mts +0 -6
  95. package/dist/common/ai/llm/miniapp/index.d.ts +0 -6
  96. package/dist/common/ai/llm/miniapp/index.js +0 -59
  97. package/dist/common/ai/llm/miniapp/index.js.map +0 -1
  98. package/dist/common/ai/llm/miniapp/index.mjs +0 -6
  99. package/dist/common/ai/llm/miniapp/index.mjs.map +0 -1
  100. package/dist/common/ai/llm/rn/index.d.mts +0 -6
  101. package/dist/common/ai/llm/rn/index.d.ts +0 -6
  102. package/dist/common/ai/llm/rn/index.js +0 -59
  103. package/dist/common/ai/llm/rn/index.js.map +0 -1
  104. package/dist/common/ai/llm/rn/index.mjs +0 -6
  105. package/dist/common/ai/llm/rn/index.mjs.map +0 -1
  106. package/dist/common/ai/llm/ui/electron/index.d.mts +0 -5
  107. package/dist/common/ai/llm/ui/electron/index.d.ts +0 -5
  108. package/dist/common/ai/llm/ui/electron/index.js +0 -22
  109. package/dist/common/ai/llm/ui/electron/index.js.map +0 -1
  110. package/dist/common/ai/llm/ui/electron/index.mjs +0 -9
  111. package/dist/common/ai/llm/ui/electron/index.mjs.map +0 -1
  112. package/dist/common/ai/llm/ui/miniapp/index.d.mts +0 -9
  113. package/dist/common/ai/llm/ui/miniapp/index.d.ts +0 -9
  114. package/dist/common/ai/llm/ui/miniapp/index.js +0 -14
  115. package/dist/common/ai/llm/ui/miniapp/index.js.map +0 -1
  116. package/dist/common/ai/llm/ui/miniapp/index.mjs +0 -5
  117. package/dist/common/ai/llm/ui/miniapp/index.mjs.map +0 -1
  118. package/dist/common/ai/llm/ui/rn/index.d.mts +0 -9
  119. package/dist/common/ai/llm/ui/rn/index.d.ts +0 -9
  120. package/dist/common/ai/llm/ui/rn/index.js +0 -14
  121. package/dist/common/ai/llm/ui/rn/index.js.map +0 -1
  122. package/dist/common/ai/llm/ui/rn/index.mjs +0 -5
  123. package/dist/common/ai/llm/ui/rn/index.mjs.map +0 -1
  124. package/dist/common/ai/llm/ui/web/index.d.mts +0 -15
  125. package/dist/common/ai/llm/ui/web/index.d.ts +0 -15
  126. package/dist/common/ai/llm/ui/web/index.js +0 -21
  127. package/dist/common/ai/llm/ui/web/index.js.map +0 -1
  128. package/dist/common/ai/llm/ui/web/index.mjs +0 -8
  129. package/dist/common/ai/llm/ui/web/index.mjs.map +0 -1
  130. package/dist/common/ai/llm/web/index.d.mts +0 -6
  131. package/dist/common/ai/llm/web/index.d.ts +0 -6
  132. package/dist/common/ai/llm/web/index.js +0 -66
  133. package/dist/common/ai/llm/web/index.js.map +0 -1
  134. package/dist/common/ai/llm/web/index.mjs +0 -9
  135. package/dist/common/ai/llm/web/index.mjs.map +0 -1
  136. package/dist/types-B2rs_jq1.d.mts +0 -38
  137. package/dist/types-DgACCUpT.d.ts +0 -122
  138. package/dist/types-DwS2Eg0q.d.ts +0 -38
  139. package/dist/types-LU_BGSzk.d.mts +0 -122
  140. /package/dist/common/{ai/llm/core → aiApi}/index.js.map +0 -0
  141. /package/dist/common/{ai/llm/core → aiApi}/index.mjs.map +0 -0
  142. /package/dist/common/{ai/llm/electron → aiApi/server}/index.js.map +0 -0
  143. /package/dist/common/{ai/llm/electron → aiApi/server}/index.mjs.map +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/common/aiApi/types.ts","../src/common/aiApi/resolveConfig.ts","../src/common/aiApi/requestJson.ts","../src/common/aiApi/callChat.ts","../src/common/aiApi/callCompletion.ts","../src/common/aiApi/modelHeuristics.ts","../src/common/aiApi/visionMessageFormats.ts","../src/common/aiApi/audioStrategy.ts","../src/common/aiApi/audioUtils.ts","../src/common/aiApi/multimodalMessageFormats.ts","../src/common/aiApi/imageUtils.ts","../src/common/aiApi/mediaUtils.ts","../src/common/aiApi/transcribeAudio.ts","../src/common/aiApi/callMultimodalChat.ts","../src/common/aiApi/jsonUtils.ts","../src/common/aiApi/listModels.ts","../src/common/aiApi/taskRegistry.ts","../src/common/aiApi/runTask.ts","../src/common/aiApi/tasks/coreLlmCompletion.ts","../src/common/aiApi/tasks/coreStructuredMultimodal.ts","../src/common/aiApi/tasks/coreConnectivityTest.ts","../src/common/aiApi/registerCoreTasks.ts"],"names":["DEFAULT_TEXT_MODEL","bytes","ALLOWED_MIME","estimateBase64ByteLength","joinUrl"],"mappings":"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","file":"chunk-ZJLS5JU5.mjs","sourcesContent":["/** 音频处理策略:native=chat 内嵌音频,stt=先转写再 chat,auto=按模型能力自动选择(失败时 STT 回退) */\nexport type AudioStrategy = 'native' | 'stt' | 'auto';\n\n/** 连接配置(调用方可显式传入,或与 env 合并) */\nexport interface AiConnectionSettings {\n apiKey: string;\n baseUrl: string;\n model?: string;\n textModel?: string;\n visionModel?: string;\n audioModel?: string;\n audioStrategy?: AudioStrategy;\n timeoutMs?: number;\n maxImageBytes?: number;\n maxAudioBytes?: number;\n}\n\n/** 客户端/请求可携带的 AI 连接配置(字段均可选,用于覆盖环境变量) */\nexport type AiClientSettings = Partial<AiConnectionSettings>;\n\n/** 解析后的完整连接配置 */\nexport interface AiConnectionConfig extends AiConnectionSettings {\n textModel: string;\n visionModel: string;\n audioModel: string;\n audioStrategy: AudioStrategy;\n timeoutMs: number;\n maxImageBytes: number;\n maxAudioBytes: number;\n}\n\n/** 统一 AI 任务请求 */\nexport interface AiApiRunRequest<TInput = unknown> {\n taskId: string;\n input: TInput;\n options?: AiTaskRunOptions;\n clientSettings?: AiClientSettings;\n}\n\nexport interface AiTaskRunOptions {\n model?: string;\n temperature?: number;\n maxTokens?: number;\n}\n\n/** 统一 AI 任务响应 */\nexport interface AiApiResponse<TData = unknown> {\n success: boolean;\n taskId: string;\n data?: TData;\n error?: AiApiErrorBody;\n meta?: AiApiResponseMeta;\n}\n\nexport interface AiApiErrorBody {\n code: AiApiErrorCode;\n message: string;\n details?: unknown;\n}\n\nexport type AiApiErrorCode =\n | 'UNAUTHORIZED'\n | 'INVALID_INPUT'\n | 'TASK_NOT_FOUND'\n | 'AI_CONFIG_MISSING'\n | 'AI_REQUEST_FAILED'\n | 'AI_PARSE_FAILED'\n | 'PAYLOAD_TOO_LARGE'\n | 'UNSUPPORTED_MEDIA';\n\nexport interface AiApiResponseMeta {\n model: string;\n latencyMs: number;\n provider?: string;\n confidence?: number;\n rawSummary?: string;\n}\n\n/** 多模态图片输入(base64) */\nexport interface AiImageInput {\n base64: string;\n mimeType: string;\n}\n\n/** 多模态音频输入(base64) */\nexport interface AiAudioInput {\n base64: string;\n mimeType: string;\n}\n\nexport type AiMediaKind = 'image' | 'audio';\n\nexport interface AiImageMediaInput extends AiImageInput {\n kind: 'image';\n}\n\nexport interface AiAudioMediaInput extends AiAudioInput {\n kind: 'audio';\n}\n\nexport type AiMediaInput = AiImageMediaInput | AiAudioMediaInput;\n\n/** 通用文本补全任务输入 */\nexport interface TextCompletionInput {\n systemPrompt?: string;\n userPrompt: string;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n /** 显式连接配置,优先级高于 clientSettings / 环境变量 */\n connection?: AiClientSettings;\n}\n\n/** 通用文本补全任务输出 */\nexport interface TextCompletionOutput {\n content: string;\n rawText: string;\n}\n\n/** 通用结构化多模态任务输入 */\nexport interface StructuredMultimodalInput {\n systemPrompt: string;\n userPrompt: string;\n media?: AiMediaInput[];\n jsonSchemaHint?: string;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n audioStrategy?: AudioStrategy;\n connection?: AiClientSettings;\n}\n\n/** 通用结构化多模态任务输出 */\nexport interface StructuredMultimodalOutput {\n json: Record<string, unknown>;\n rawText: string;\n}\n\nexport const CORE_LLM_COMPLETION_TASK_ID = 'core.llmCompletion';\nexport const CORE_STRUCTURED_MULTIMODAL_TASK_ID = 'core.structuredMultimodal';\nexport const CORE_CONNECTIVITY_TEST_TASK_ID = 'core.connectivityTest';\n\nexport interface ConnectivityTestOutput {\n ok: boolean;\n reply: string;\n}\n\nexport interface AiModelsListRequest {\n clientSettings?: AiClientSettings;\n}\n\nexport interface AiModelsListResponse {\n success: boolean;\n models: string[];\n visionModels: string[];\n suggestedVisionModel?: string;\n error?: {\n code: string;\n message: string;\n };\n}\n\nexport interface AiTaskContext {\n requestId?: string;\n userId?: string | number;\n clientSettings?: AiClientSettings;\n}\n\nexport interface AiTaskDefinition<TInput = unknown, TOutput = unknown> {\n id: string;\n description?: string;\n validateInput: (input: unknown) => TInput;\n execute: (\n input: TInput,\n ctx: AiTaskContext\n ) => Promise<{\n data: TOutput;\n meta?: Partial<AiApiResponseMeta>;\n }>;\n}\n\nexport interface MultimodalChatParams {\n systemPrompt: string;\n userPrompt: string;\n media?: AiMediaInput[];\n model?: string;\n temperature?: number;\n maxTokens?: number;\n jsonMode?: boolean;\n audioStrategy?: AudioStrategy;\n connection?: AiClientSettings;\n}\n\nexport interface MultimodalChatResult {\n content: string;\n model: string;\n raw: unknown;\n /** auto/native/stt 实际采用的音频处理方式 */\n audioHandling?: 'none' | 'native' | 'stt';\n /** STT 或 native 失败回退时的转写文本 */\n transcriptions?: string[];\n}\n","import type { AiClientSettings, AiConnectionConfig, AudioStrategy } from './types';\n\nconst DEFAULT_BASE_URL = 'https://api.openai.com/v1';\nconst DEFAULT_TEXT_MODEL = 'gpt-4o-mini';\nconst DEFAULT_VISION_MODEL = 'gpt-4o-mini';\nconst DEFAULT_AUDIO_MODEL = 'whisper-1';\nconst DEFAULT_AUDIO_STRATEGY: AudioStrategy = 'auto';\nconst DEFAULT_TIMEOUT_MS = 60_000;\nconst DEFAULT_MAX_IMAGE_BYTES = 5 * 1024 * 1024;\nconst DEFAULT_MAX_AUDIO_BYTES = 25 * 1024 * 1024;\n\nfunction readEnv(name: string): string {\n if (typeof process === 'undefined' || !process.env) {\n return '';\n }\n return process.env[name]?.trim() ?? '';\n}\n\n/**\n * 合并连接配置:显式 connection > clientSettings > 环境变量。\n * 缺少 apiKey 时返回 null。\n */\nexport function resolveAiConnectionConfig(\n ...sources: Array<AiClientSettings | undefined>\n): AiConnectionConfig | null {\n const merged: AiClientSettings = {};\n for (const source of sources) {\n if (!source) continue;\n Object.assign(merged, source);\n }\n\n const envApiKey = readEnv('AI_API_KEY') || readEnv('OPENAI_API_KEY');\n const apiKey = merged.apiKey?.trim() || envApiKey;\n if (!apiKey) {\n return null;\n }\n\n const baseUrl =\n merged.baseUrl?.trim() || readEnv('AI_BASE_URL') || DEFAULT_BASE_URL;\n const visionModel =\n merged.visionModel?.trim() ||\n readEnv('AI_VISION_MODEL') ||\n merged.model?.trim() ||\n DEFAULT_VISION_MODEL;\n const textModel =\n merged.textModel?.trim() ||\n readEnv('AI_TEXT_MODEL') ||\n merged.model?.trim() ||\n visionModel ||\n DEFAULT_TEXT_MODEL;\n\n const audioModel =\n merged.audioModel?.trim() || readEnv('AI_AUDIO_MODEL') || DEFAULT_AUDIO_MODEL;\n const envAudioStrategy = readEnv('AI_AUDIO_STRATEGY') as AudioStrategy | '';\n const audioStrategy: AudioStrategy =\n merged.audioStrategy ?? (envAudioStrategy || DEFAULT_AUDIO_STRATEGY);\n\n return {\n apiKey,\n baseUrl,\n model: merged.model?.trim() || textModel,\n textModel,\n visionModel,\n audioModel,\n audioStrategy,\n timeoutMs: merged.timeoutMs ?? Number(readEnv('AI_TIMEOUT_MS') || DEFAULT_TIMEOUT_MS),\n maxImageBytes:\n merged.maxImageBytes ?? Number(readEnv('AI_MAX_IMAGE_BYTES') || DEFAULT_MAX_IMAGE_BYTES),\n maxAudioBytes:\n merged.maxAudioBytes ?? Number(readEnv('AI_MAX_AUDIO_BYTES') || DEFAULT_MAX_AUDIO_BYTES),\n };\n}\n\nexport function requireAiConnectionConfig(\n ...sources: Array<AiClientSettings | undefined>\n): AiConnectionConfig {\n const config = resolveAiConnectionConfig(...sources);\n if (!config) {\n throw new Error('未配置 AI API Key,请传入 connection / clientSettings 或设置环境变量 AI_API_KEY');\n }\n return config;\n}\n","import type { RequestAdapter } from '../request';\n\nexport type JsonRequestOptions = {\n url: string;\n method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';\n headers?: Record<string, string>;\n body?: unknown;\n timeoutMs?: number;\n requestAdapter?: RequestAdapter;\n};\n\nexport async function requestJson<T>(options: JsonRequestOptions): Promise<T> {\n const { url, method = 'POST', headers = {}, body, timeoutMs, requestAdapter } = options;\n\n if (requestAdapter) {\n return requestAdapter.request<T>({\n url,\n method,\n headers,\n body,\n });\n }\n\n const controller = timeoutMs ? new AbortController() : undefined;\n const timeoutId = timeoutMs\n ? setTimeout(() => {\n controller?.abort();\n }, timeoutMs)\n : undefined;\n\n try {\n const response = await fetch(url, {\n method,\n headers,\n body: body !== undefined ? JSON.stringify(body) : undefined,\n signal: controller?.signal,\n });\n\n const text = await response.text();\n let data: unknown = null;\n\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n data = text;\n }\n }\n\n if (!response.ok) {\n const record = data as { error?: { message?: string } | string; message?: string } | null;\n const errorMessage =\n (typeof record?.error === 'object' ? record.error?.message : record?.error) ||\n record?.message ||\n `Request failed with status ${response.status}`;\n const error = new Error(String(errorMessage));\n (error as Error & { status?: number; data?: unknown }).status = response.status;\n (error as Error & { status?: number; data?: unknown }).data = data;\n throw error;\n }\n\n return data as T;\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n}\n","import type { RequestAdapter } from '../request';\nimport { requestJson } from './requestJson';\n\nexport const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';\nexport const DEFAULT_TEXT_MODEL = 'gpt-4o-mini';\n\nexport type ChatRole = 'system' | 'user' | 'assistant';\n\nexport interface ChatMessage {\n role: ChatRole;\n content: string;\n}\n\nexport interface CallChatOptions {\n /** OpenAI 兼容 API Base URL */\n baseUrl: string;\n /** API Key */\n apiKey: string;\n model?: string;\n systemPrompt?: string;\n userPrompt?: string;\n messages?: ChatMessage[];\n temperature?: number;\n maxTokens?: number;\n topP?: number;\n stop?: string | string[];\n timeoutMs?: number;\n requestAdapter?: RequestAdapter;\n}\n\nexport interface ChatUsage {\n promptTokens?: number;\n completionTokens?: number;\n totalTokens?: number;\n}\n\nexport interface CallChatResult {\n content: string;\n model: string;\n usage?: ChatUsage;\n raw?: unknown;\n}\n\ntype OpenAIChatResponse = {\n id?: string;\n model?: string;\n choices?: Array<{ message?: { content?: string | null } }>;\n usage?: {\n prompt_tokens?: number;\n completion_tokens?: number;\n total_tokens?: number;\n };\n};\n\nfunction joinUrl(base: string, path: string): string {\n return `${base.replace(/\\/+$/, '')}/${path.replace(/^\\/+/, '')}`;\n}\n\nfunction resolveMessages(input: {\n systemPrompt?: string;\n userPrompt?: string;\n messages?: ChatMessage[];\n}): ChatMessage[] {\n if (input.messages?.length) {\n return input.messages;\n }\n\n const messages: ChatMessage[] = [];\n if (input.systemPrompt?.trim()) {\n messages.push({ role: 'system', content: input.systemPrompt.trim() });\n }\n if (input.userPrompt?.trim()) {\n messages.push({ role: 'user', content: input.userPrompt.trim() });\n }\n return messages;\n}\n\n/**\n * OpenAI 兼容文本对话:外部传入 URL、Key、提示词,返回模型生成内容。\n */\nexport async function callChat(options: CallChatOptions): Promise<CallChatResult> {\n const {\n baseUrl,\n apiKey,\n model,\n systemPrompt,\n userPrompt,\n messages,\n temperature,\n maxTokens,\n topP,\n stop,\n timeoutMs = 60_000,\n requestAdapter,\n } = options;\n\n if (!baseUrl?.trim()) {\n throw new Error('baseUrl 为必填');\n }\n if (!apiKey?.trim()) {\n throw new Error('apiKey 为必填');\n }\n\n const resolvedMessages = resolveMessages({ systemPrompt, userPrompt, messages });\n if (!resolvedMessages.length) {\n throw new Error('userPrompt 或 messages 至少提供一项');\n }\n\n const resolvedModel = model?.trim() || DEFAULT_TEXT_MODEL;\n const payload: Record<string, unknown> = {\n model: resolvedModel,\n messages: resolvedMessages,\n };\n\n if (temperature !== undefined) payload.temperature = temperature;\n if (maxTokens !== undefined) payload.max_tokens = maxTokens;\n if (topP !== undefined) payload.top_p = topP;\n if (stop !== undefined) payload.stop = stop;\n\n const raw = await requestJson<OpenAIChatResponse>({\n url: joinUrl(baseUrl.trim(), 'chat/completions'),\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${apiKey.trim()}`,\n },\n body: payload,\n timeoutMs,\n requestAdapter,\n });\n\n const content = raw.choices?.[0]?.message?.content ?? '';\n const usage = raw.usage\n ? {\n promptTokens: raw.usage.prompt_tokens,\n completionTokens: raw.usage.completion_tokens,\n totalTokens: raw.usage.total_tokens,\n }\n : undefined;\n\n return {\n content,\n model: raw.model ?? resolvedModel,\n usage,\n raw,\n };\n}\n","import { callChat } from './callChat';\nimport { requireAiConnectionConfig } from './resolveConfig';\nimport type { AiClientSettings } from './types';\n\nexport interface CallCompletionParams {\n systemPrompt?: string;\n userPrompt: string;\n model?: string;\n temperature?: number;\n maxTokens?: number;\n connection?: AiClientSettings;\n}\n\nexport interface CallCompletionResult {\n content: string;\n model: string;\n raw?: unknown;\n}\n\n/**\n * 文本补全:连接信息与提示词均由调用方传入(或通过 connection 合并 env)。\n */\nexport async function callCompletion(\n params: CallCompletionParams,\n clientSettings?: AiClientSettings\n): Promise<CallCompletionResult> {\n const config = requireAiConnectionConfig(params.connection, clientSettings);\n const model = params.model || config.textModel;\n\n const result = await callChat({\n baseUrl: config.baseUrl,\n apiKey: config.apiKey,\n model,\n systemPrompt: params.systemPrompt,\n userPrompt: params.userPrompt,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n timeoutMs: config.timeoutMs,\n });\n\n return {\n content: result.content,\n model: result.model || model,\n raw: result.raw,\n };\n}\n","/** 非对话类模型 ID 片段(embedding、语音等) */\nconst NON_CHAT_PATTERNS = [\n /embed/i,\n /whisper/i,\n /tts/i,\n /dall-e/i,\n /moderation/i,\n /realtime/i,\n /audio/i,\n /transcrib/i,\n /sora/i,\n];\n\n/** 常见支持视觉输入的模型 ID 特征 */\nconst VISION_HINT_PATTERNS = [\n /^gpt-4o/i,\n /^gpt-4-turbo/i,\n /^gpt-4-vision/i,\n /^gpt-4\\.1/i,\n /claude-3/i,\n /gemini.*(pro|flash|vision)/i,\n /qwen.*vl/i,\n /vision/i,\n /-vl/i,\n /llava/i,\n /doubao.*vision/i,\n /glm-4v/i,\n /internvl/i,\n /pixtral/i,\n /deepseek-vl/i,\n];\n\n/** 自动选择视觉模型时的优先级(精确或前缀匹配) */\nconst PREFERRED_VISION_MODELS = [\n 'gpt-4o-mini',\n 'gpt-4o',\n 'gpt-4-turbo',\n 'gpt-4-vision-preview',\n 'gpt-4.1-mini',\n 'gpt-4.1',\n 'claude-3-5-sonnet-latest',\n 'claude-3-5-haiku-latest',\n 'gemini-2.0-flash',\n 'gemini-1.5-flash',\n 'gemini-1.5-pro',\n 'qwen-vl-max',\n 'qwen2-vl-72b-instruct',\n];\n\nfunction isChatModel(id: string): boolean {\n return !NON_CHAT_PATTERNS.some((pattern) => pattern.test(id));\n}\n\n/** 常见支持 chat 内嵌音频输入的模型 ID 特征(OpenAI 兼容) */\nconst NATIVE_AUDIO_CHAT_PATTERNS = [\n /^gpt-4o/i,\n /^gpt-4-turbo/i,\n /^gpt-4\\.1/i,\n /gemini-2\\.0/i,\n /gemini-1\\.5/i,\n];\n\n/** STT 模型 ID 特征 */\nconst STT_MODEL_PATTERNS = [/whisper/i, /transcrib/i, /sensevoice/i, /paraformer/i];\n\nexport function isLikelyNativeAudioChatModel(id: string): boolean {\n const trimmed = id.trim();\n if (!trimmed) return false;\n if (STT_MODEL_PATTERNS.some((pattern) => pattern.test(trimmed))) return false;\n return NATIVE_AUDIO_CHAT_PATTERNS.some((pattern) => pattern.test(trimmed));\n}\n\nexport function isLikelySttModel(id: string): boolean {\n return STT_MODEL_PATTERNS.some((pattern) => pattern.test(id.trim()));\n}\n\nexport function filterSttModels(modelIds: string[]): string[] {\n return modelIds.filter(isLikelySttModel).sort((a, b) => a.localeCompare(b));\n}\n\nconst PREFERRED_STT_MODELS = ['whisper-1', 'whisper-large-v3', 'whisper-large-v3-turbo'];\n\nexport function pickDefaultSttModel(modelIds: string[], current?: string): string | undefined {\n const sttModels = filterSttModels(modelIds);\n if (sttModels.length === 0) return undefined;\n\n const trimmedCurrent = current?.trim();\n if (trimmedCurrent && sttModels.includes(trimmedCurrent)) {\n return trimmedCurrent;\n }\n\n for (const preferred of PREFERRED_STT_MODELS) {\n const match = sttModels.find((id) => id === preferred || id.startsWith(`${preferred}-`));\n if (match) return match;\n }\n\n return sttModels[0];\n}\n\nexport function isLikelyVisionModel(id: string): boolean {\n return VISION_HINT_PATTERNS.some((pattern) => pattern.test(id));\n}\n\n/** 明确不支持图片的对话模型 */\nconst TEXT_ONLY_MODEL_PATTERNS = [\n /^deepseek-chat/i,\n /^deepseek-reasoner/i,\n /^deepseek-r1/i,\n /^deepseek-v[34](?!.*vl)/i,\n /^gpt-3\\.5/i,\n /^o1-mini/i,\n /^o3-mini/i,\n];\n\nexport function isKnownTextOnlyModel(id: string): boolean {\n const trimmed = id.trim();\n if (!trimmed) return false;\n return TEXT_ONLY_MODEL_PATTERNS.some((pattern) => pattern.test(trimmed));\n}\n\nexport function filterChatModels(modelIds: string[]): string[] {\n return modelIds.filter(isChatModel).sort((a, b) => a.localeCompare(b));\n}\n\nexport function filterVisionModels(modelIds: string[]): string[] {\n return filterChatModels(modelIds)\n .filter((id) => isLikelyVisionModel(id) && !isKnownTextOnlyModel(id))\n .sort((a, b) => a.localeCompare(b));\n}\n\nfunction matchesPreferred(modelId: string, preferred: string): boolean {\n return modelId === preferred || modelId.startsWith(`${preferred}-`);\n}\n\n/** 从可用模型中挑选默认视觉模型 */\nexport function pickDefaultVisionModel(\n modelIds: string[],\n current?: string\n): string | undefined {\n const visionModels = filterVisionModels(modelIds);\n if (visionModels.length === 0) return undefined;\n\n const trimmedCurrent = current?.trim();\n if (trimmedCurrent && visionModels.includes(trimmedCurrent)) {\n return trimmedCurrent;\n }\n\n for (const preferred of PREFERRED_VISION_MODELS) {\n const match = visionModels.find((id) => matchesPreferred(id, preferred));\n if (match) return match;\n }\n\n return visionModels[0];\n}\n","import { isKnownTextOnlyModel, isLikelyVisionModel } from './modelHeuristics';\n\nexport type VisionMessageFormat = 'openai' | 'ollama';\n\nexport function detectVisionMessageFormat(baseUrl: string): VisionMessageFormat {\n const normalized = baseUrl.toLowerCase();\n if (\n normalized.includes('ollama') ||\n normalized.includes(':11434') ||\n normalized.includes('11434/')\n ) {\n return 'ollama';\n }\n return 'openai';\n}\n\nexport function assertVisionCapableModel(\n modelId: string,\n options?: { baseUrl?: string; hasImages?: boolean }\n): void {\n if (!options?.hasImages) return;\n\n const model = modelId.trim();\n if (!model) {\n throw new Error('识图需要选择视觉模型,请在 AI 设置中配置');\n }\n\n const format = options.baseUrl ? detectVisionMessageFormat(options.baseUrl) : 'openai';\n\n if (format === 'ollama') return;\n\n if (isKnownTextOnlyModel(model)) {\n throw new Error(\n `当前模型「${model}」不支持图片输入。请改用视觉模型,例如 gpt-4o-mini、qwen-vl-max、gemini-1.5-flash、deepseek-vl 等(DeepSeek 文本模型无法识图)。`\n );\n }\n\n if (!isLikelyVisionModel(model)) {\n throw new Error(\n `模型「${model}」可能不支持图片识图。请在 AI 设置中选择名称含 vl、vision、gpt-4o、gemini 等标识的视觉模型。`\n );\n }\n}\n\nexport function isImageUrlVariantError(message: string): boolean {\n return (\n /unknown variant [`']?image_url[`']?/i.test(message) ||\n /expected [`']?text[`']?/i.test(message) ||\n /does not support.*image/i.test(message)\n );\n}\n\nexport function toVisionApiErrorMessage(rawMessage: string, modelId: string): string {\n if (isImageUrlVariantError(rawMessage)) {\n return `当前模型「${modelId}」不接受图片请求(${rawMessage})。请更换为支持识图的视觉模型。`;\n }\n return rawMessage;\n}\n\nexport { isKnownTextOnlyModel, isLikelyVisionModel } from './modelHeuristics';\n","import { detectVisionMessageFormat } from './visionMessageFormats';\nimport { isLikelyNativeAudioChatModel } from './modelHeuristics';\nimport type { AudioStrategy } from './types';\n\nexport type ResolvedAudioHandling = 'none' | 'native' | 'stt';\n\nexport function resolveAudioHandling(options: {\n hasAudio: boolean;\n strategy: AudioStrategy;\n model: string;\n baseUrl: string;\n}): ResolvedAudioHandling {\n if (!options.hasAudio) {\n return 'none';\n }\n\n if (options.strategy === 'stt') {\n return 'stt';\n }\n\n if (options.strategy === 'native') {\n return 'native';\n }\n\n // auto:Ollama 等本地栈通常无 chat 内嵌音频 → STT\n if (detectVisionMessageFormat(options.baseUrl) === 'ollama') {\n return 'stt';\n }\n\n if (isLikelyNativeAudioChatModel(options.model)) {\n return 'native';\n }\n\n return 'stt';\n}\n\nexport function isAudioInputError(message: string): boolean {\n return (\n /input_audio/i.test(message) ||\n /unknown variant [`']?input_audio[`']?/i.test(message) ||\n /does not support.*audio/i.test(message) ||\n /audio input/i.test(message) ||\n /invalid audio/i.test(message)\n );\n}\n\nexport function appendTranscriptionsToPrompt(\n userPrompt: string,\n transcriptions: string[]\n): string {\n if (transcriptions.length === 0) {\n return userPrompt;\n }\n\n const blocks = transcriptions.map((text, index) => {\n const label = transcriptions.length === 1 ? '[语音转写]' : `[语音转写 ${index + 1}]`;\n return `${label}\\n${text.trim()}`;\n });\n\n const joined = blocks.join('\\n\\n');\n const trimmedPrompt = userPrompt.trim();\n return trimmedPrompt ? `${trimmedPrompt}\\n\\n${joined}` : joined;\n}\n","import type { AiAudioInput } from './types';\n\nconst ALLOWED_MIME = new Set([\n 'audio/wav',\n 'audio/x-wav',\n 'audio/mpeg',\n 'audio/mp3',\n 'audio/mp4',\n 'audio/webm',\n 'audio/ogg',\n 'audio/flac',\n]);\n\nconst MIME_TO_FORMAT: Record<string, string> = {\n 'audio/wav': 'wav',\n 'audio/x-wav': 'wav',\n 'audio/mpeg': 'mp3',\n 'audio/mp3': 'mp3',\n 'audio/mp4': 'mp4',\n 'audio/webm': 'webm',\n 'audio/ogg': 'ogg',\n 'audio/flac': 'flac',\n};\n\nexport function mimeToAudioFormat(mimeType: string): string {\n return MIME_TO_FORMAT[mimeType] ?? mimeType.split('/').pop() ?? 'wav';\n}\n\nexport function assertValidAudioInput(\n audio: AiAudioInput,\n maxAudioBytes = 25 * 1024 * 1024\n): void {\n if (!audio.base64?.trim()) {\n throw new Error('音频数据不能为空');\n }\n if (!ALLOWED_MIME.has(audio.mimeType)) {\n throw new Error(`不支持的音频格式: ${audio.mimeType}`);\n }\n\n const byteLength = estimateBase64ByteLength(audio.base64);\n if (byteLength > maxAudioBytes) {\n throw new Error(`音频过大,最大 ${Math.round(maxAudioBytes / 1024 / 1024)}MB`);\n }\n}\n\nfunction estimateBase64ByteLength(base64: string): number {\n if (typeof Buffer !== 'undefined') {\n return Buffer.byteLength(base64, 'base64');\n }\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.floor((base64.length * 3) / 4) - padding;\n}\n\nexport async function fileToAiAudioInput(file: File): Promise<AiAudioInput> {\n const buffer = await file.arrayBuffer();\n if (typeof Buffer !== 'undefined') {\n return {\n base64: Buffer.from(buffer).toString('base64'),\n mimeType: file.type || 'audio/wav',\n };\n }\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let index = 0; index < bytes.length; index += 1) {\n binary += String.fromCharCode(bytes[index]!);\n }\n return { base64: btoa(binary), mimeType: file.type || 'audio/wav' };\n}\n\nexport function base64ToBlob(base64: string, mimeType: string): Blob {\n if (typeof Buffer !== 'undefined') {\n const bytes = Buffer.from(base64, 'base64');\n return new Blob([bytes], { type: mimeType });\n }\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return new Blob([bytes], { type: mimeType });\n}\n","import { mimeToAudioFormat } from './audioUtils';\nimport type { AiMediaInput } from './types';\nimport {\n assertVisionCapableModel,\n detectVisionMessageFormat,\n type VisionMessageFormat,\n} from './visionMessageFormats';\n\nexport type { VisionMessageFormat };\n\nexport function buildMultimodalMessages(options: {\n systemPrompt: string;\n userPrompt: string;\n images: AiMediaInput[];\n nativeAudios: AiMediaInput[];\n format: VisionMessageFormat;\n}): Array<Record<string, unknown>> {\n const { systemPrompt, userPrompt, images, nativeAudios, format } = options;\n const hasImages = images.length > 0;\n const hasNativeAudio = nativeAudios.length > 0;\n\n if (format === 'ollama' && hasImages) {\n return [\n { role: 'system', content: systemPrompt },\n {\n role: 'user',\n content: userPrompt,\n images: images.map((image) => image.base64),\n },\n ];\n }\n\n const userContent: Array<Record<string, unknown>> = [{ type: 'text', text: userPrompt }];\n\n for (const image of images) {\n userContent.push({\n type: 'image_url',\n image_url: {\n url: `data:${image.mimeType};base64,${image.base64}`,\n },\n });\n }\n\n for (const audio of nativeAudios) {\n userContent.push({\n type: 'input_audio',\n input_audio: {\n data: audio.base64,\n format: mimeToAudioFormat(audio.mimeType),\n },\n });\n }\n\n const useStructuredContent = hasImages || hasNativeAudio;\n\n return [\n { role: 'system', content: systemPrompt },\n { role: 'user', content: useStructuredContent ? userContent : userPrompt },\n ];\n}\n\nexport function assertMultimodalCapableModel(\n modelId: string,\n options: { baseUrl?: string; hasImages?: boolean; hasNativeAudio?: boolean }\n): void {\n assertVisionCapableModel(modelId, {\n baseUrl: options.baseUrl,\n hasImages: options.hasImages,\n });\n\n if (!options.hasNativeAudio) return;\n\n const format = options.baseUrl ? detectVisionMessageFormat(options.baseUrl) : 'openai';\n if (format === 'ollama') {\n throw new Error('当前 Ollama 连接不支持 chat 内嵌音频,请改用 audioStrategy: \"stt\" 或 \"auto\"');\n }\n}\n\nexport {\n detectVisionMessageFormat,\n assertVisionCapableModel,\n isImageUrlVariantError,\n toVisionApiErrorMessage,\n} from './visionMessageFormats';\n\nexport { isLikelyNativeAudioChatModel, isLikelyVisionModel } from './modelHeuristics';\n","import type { AiImageInput } from './types';\n\nconst ALLOWED_MIME = new Set(['image/jpeg', 'image/png', 'image/webp', 'image/gif']);\n\nexport function assertValidImageInput(image: AiImageInput, maxImageBytes = 5 * 1024 * 1024): void {\n if (!image.base64?.trim()) {\n throw new Error('图片数据不能为空');\n }\n if (!ALLOWED_MIME.has(image.mimeType)) {\n throw new Error(`不支持的图片格式: ${image.mimeType}`);\n }\n\n const byteLength = estimateBase64ByteLength(image.base64);\n if (byteLength > maxImageBytes) {\n throw new Error(`图片过大,最大 ${Math.round(maxImageBytes / 1024 / 1024)}MB`);\n }\n}\n\nfunction estimateBase64ByteLength(base64: string): number {\n if (typeof Buffer !== 'undefined') {\n return Buffer.byteLength(base64, 'base64');\n }\n const padding = base64.endsWith('==') ? 2 : base64.endsWith('=') ? 1 : 0;\n return Math.floor((base64.length * 3) / 4) - padding;\n}\n\nexport async function fileToAiImageInput(file: File): Promise<AiImageInput> {\n const buffer = await file.arrayBuffer();\n if (typeof Buffer !== 'undefined') {\n return {\n base64: Buffer.from(buffer).toString('base64'),\n mimeType: file.type || 'image/jpeg',\n };\n }\n const bytes = new Uint8Array(buffer);\n let binary = '';\n for (let index = 0; index < bytes.length; index += 1) {\n binary += String.fromCharCode(bytes[index]!);\n }\n const base64 = btoa(binary);\n return { base64, mimeType: file.type || 'image/jpeg' };\n}\n","import type { AiMediaInput } from './types';\nimport { assertValidAudioInput } from './audioUtils';\nimport { assertValidImageInput } from './imageUtils';\n\nexport function splitMediaByKind(media: AiMediaInput[]): {\n images: AiMediaInput[];\n audios: AiMediaInput[];\n} {\n const images: AiMediaInput[] = [];\n const audios: AiMediaInput[] = [];\n for (const item of media) {\n if (item.kind === 'image') {\n images.push(item);\n } else {\n audios.push(item);\n }\n }\n return { images, audios };\n}\n\nexport function assertValidMultimodalMedia(\n media: AiMediaInput[] | undefined,\n limits: { maxImageBytes: number; maxAudioBytes: number; maxImages?: number; maxAudios?: number }\n): AiMediaInput[] {\n const items = media ?? [];\n const { images, audios } = splitMediaByKind(items);\n\n const maxImages = limits.maxImages ?? 8;\n const maxAudios = limits.maxAudios ?? 4;\n\n if (images.length > maxImages) {\n throw new Error(`图片数量过多,最多 ${maxImages} 张`);\n }\n if (audios.length > maxAudios) {\n throw new Error(`音频数量过多,最多 ${maxAudios} 段`);\n }\n\n for (const image of images) {\n assertValidImageInput(\n { base64: image.base64, mimeType: image.mimeType },\n limits.maxImageBytes\n );\n }\n for (const audio of audios) {\n assertValidAudioInput(\n { base64: audio.base64, mimeType: audio.mimeType },\n limits.maxAudioBytes\n );\n }\n\n return items;\n}\n","import { base64ToBlob, mimeToAudioFormat } from './audioUtils';\nimport type { AiAudioInput, AiConnectionConfig } from './types';\n\nfunction joinUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, '')}/${path.replace(/^\\/+/, '')}`;\n}\n\ntype TranscriptionResponse = {\n text?: string;\n error?: { message?: string };\n};\n\nexport interface TranscribeAudioOptions {\n audio: AiAudioInput;\n config: AiConnectionConfig;\n model?: string;\n language?: string;\n}\n\nexport async function transcribeAudio(options: TranscribeAudioOptions): Promise<string> {\n const { audio, config, model, language } = options;\n const sttModel = model?.trim() || config.audioModel;\n const blob = base64ToBlob(audio.base64, audio.mimeType);\n const extension = mimeToAudioFormat(audio.mimeType);\n const form = new FormData();\n\n form.append('file', blob, `audio.${extension}`);\n form.append('model', sttModel);\n if (language?.trim()) {\n form.append('language', language.trim());\n }\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), config.timeoutMs);\n\n try {\n const response = await fetch(joinUrl(config.baseUrl, 'audio/transcriptions'), {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n },\n body: form,\n signal: controller.signal,\n });\n\n const text = await response.text();\n let data: unknown = null;\n if (text) {\n try {\n data = JSON.parse(text);\n } catch {\n data = text;\n }\n }\n\n if (!response.ok) {\n const record = data as { error?: { message?: string } | string; message?: string } | null;\n const errorMessage =\n (typeof record?.error === 'object' ? record.error?.message : record?.error) ||\n record?.message ||\n `STT 请求失败 (${response.status})`;\n throw new Error(String(errorMessage));\n }\n\n if (typeof data === 'string') {\n return data.trim();\n }\n\n const parsed = data as TranscriptionResponse;\n return (parsed.text ?? '').trim();\n } finally {\n clearTimeout(timeoutId);\n }\n}\n\nexport async function transcribeAudios(\n audios: AiAudioInput[],\n config: AiConnectionConfig,\n model?: string\n): Promise<string[]> {\n const results: string[] = [];\n for (const audio of audios) {\n results.push(await transcribeAudio({ audio, config, model }));\n }\n return results;\n}\n","import { appendTranscriptionsToPrompt, isAudioInputError, resolveAudioHandling } from './audioStrategy';\nimport {\n assertMultimodalCapableModel,\n buildMultimodalMessages,\n detectVisionMessageFormat,\n toVisionApiErrorMessage,\n} from './multimodalMessageFormats';\nimport { assertValidMultimodalMedia, splitMediaByKind } from './mediaUtils';\nimport { requireAiConnectionConfig } from './resolveConfig';\nimport { requestJson } from './requestJson';\nimport { transcribeAudios } from './transcribeAudio';\nimport type {\n AiAudioInput,\n AiClientSettings,\n AiMediaInput,\n MultimodalChatParams,\n MultimodalChatResult,\n} from './types';\n\nfunction joinUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, '')}/${path.replace(/^\\/+/, '')}`;\n}\n\ntype OpenAiChatResponse = {\n model?: string;\n choices?: Array<{ message?: { content?: string } }>;\n error?: { message?: string };\n};\n\nasync function requestMultimodalChat(options: {\n config: ReturnType<typeof requireAiConnectionConfig>;\n model: string;\n messages: Array<Record<string, unknown>>;\n temperature?: number;\n maxTokens?: number;\n jsonMode?: boolean;\n}): Promise<{ content: string; model: string; raw: unknown }> {\n const payload: Record<string, unknown> = {\n model: options.model,\n messages: options.messages,\n temperature: options.temperature ?? 0.2,\n };\n\n if (options.maxTokens !== undefined) {\n payload.max_tokens = options.maxTokens;\n }\n if (options.jsonMode) {\n payload.response_format = { type: 'json_object' };\n }\n\n const raw = await requestJson<OpenAiChatResponse>({\n url: joinUrl(options.config.baseUrl, 'chat/completions'),\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${options.config.apiKey}`,\n },\n body: payload,\n timeoutMs: options.config.timeoutMs,\n });\n\n return {\n content: raw.choices?.[0]?.message?.content ?? '',\n model: raw.model ?? options.model,\n raw,\n };\n}\n\nfunction toAudioInputs(audios: AiMediaInput[]): AiAudioInput[] {\n return audios.map((audio) => ({ base64: audio.base64, mimeType: audio.mimeType }));\n}\n\n/**\n * OpenAI 兼容多模态对话:文本 + 可选图片/语音。\n * audioStrategy=auto 时:优先 chat 内嵌音频(native),失败或未支持则 STT 转写后走文本 chat。\n */\nexport async function callMultimodalChat(\n params: MultimodalChatParams,\n clientSettings?: AiClientSettings\n): Promise<MultimodalChatResult> {\n const config = requireAiConnectionConfig(params.connection, clientSettings);\n const media = assertValidMultimodalMedia(params.media, {\n maxImageBytes: config.maxImageBytes,\n maxAudioBytes: config.maxAudioBytes,\n });\n const { images, audios } = splitMediaByKind(media);\n const hasImages = images.length > 0;\n const hasAudio = audios.length > 0;\n\n const model =\n params.model ||\n (hasImages ? config.visionModel : hasAudio ? config.visionModel : config.textModel);\n const strategy = params.audioStrategy ?? config.audioStrategy;\n const format = detectVisionMessageFormat(config.baseUrl);\n let audioHandling = resolveAudioHandling({\n hasAudio,\n strategy,\n model,\n baseUrl: config.baseUrl,\n });\n\n let userPrompt = params.userPrompt;\n let transcriptions: string[] | undefined;\n let nativeAudios: AiMediaInput[] = [];\n\n if (audioHandling === 'stt' && hasAudio) {\n transcriptions = await transcribeAudios(toAudioInputs(audios), config);\n userPrompt = appendTranscriptionsToPrompt(userPrompt, transcriptions);\n } else if (audioHandling === 'native' && hasAudio) {\n nativeAudios = audios;\n }\n\n assertMultimodalCapableModel(model, {\n baseUrl: config.baseUrl,\n hasImages,\n hasNativeAudio: nativeAudios.length > 0,\n });\n\n const messages = buildMultimodalMessages({\n systemPrompt: params.systemPrompt,\n userPrompt,\n images,\n nativeAudios,\n format,\n });\n\n try {\n const result = await requestMultimodalChat({\n config,\n model,\n messages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n jsonMode: params.jsonMode,\n });\n\n return {\n ...result,\n audioHandling,\n transcriptions,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'AI 请求失败';\n\n if (\n audioHandling === 'native' &&\n hasAudio &&\n strategy === 'auto' &&\n isAudioInputError(message)\n ) {\n transcriptions = await transcribeAudios(toAudioInputs(audios), config);\n userPrompt = appendTranscriptionsToPrompt(params.userPrompt, transcriptions);\n audioHandling = 'stt';\n\n const fallbackMessages = buildMultimodalMessages({\n systemPrompt: params.systemPrompt,\n userPrompt,\n images,\n nativeAudios: [],\n format,\n });\n\n const result = await requestMultimodalChat({\n config,\n model,\n messages: fallbackMessages,\n temperature: params.temperature,\n maxTokens: params.maxTokens,\n jsonMode: params.jsonMode,\n });\n\n return {\n ...result,\n audioHandling,\n transcriptions,\n };\n }\n\n throw new Error(toVisionApiErrorMessage(message, model));\n }\n}\n","export function extractJsonObject(text: string): Record<string, unknown> {\n const trimmed = text.trim();\n if (!trimmed) {\n throw new Error('模型返回为空');\n }\n\n try {\n const parsed = JSON.parse(trimmed);\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n } catch {\n // fall through\n }\n\n const fenced = trimmed.match(/```(?:json)?\\s*([\\s\\S]*?)```/i);\n if (fenced?.[1]) {\n const parsed = JSON.parse(fenced[1].trim());\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n }\n\n const start = trimmed.indexOf('{');\n const end = trimmed.lastIndexOf('}');\n if (start >= 0 && end > start) {\n const parsed = JSON.parse(trimmed.slice(start, end + 1));\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>;\n }\n }\n\n throw new Error('无法解析模型 JSON 输出');\n}\n","import { requestJson } from './requestJson';\nimport { resolveAiConnectionConfig } from './resolveConfig';\nimport type { AiClientSettings } from './types';\nimport {\n filterChatModels,\n filterVisionModels,\n pickDefaultVisionModel,\n} from './modelHeuristics';\n\nfunction joinUrl(baseUrl: string, path: string): string {\n return `${baseUrl.replace(/\\/+$/, '')}/${path.replace(/^\\/+/, '')}`;\n}\n\ninterface OpenAiModelListResponse {\n data?: Array<{ id?: string }>;\n models?: Array<{ id?: string } | string>;\n error?: { message?: string };\n}\n\nfunction parseModelIds(raw: OpenAiModelListResponse): string[] {\n if (Array.isArray(raw.data)) {\n return raw.data.map((item) => item.id).filter((id): id is string => Boolean(id));\n }\n if (Array.isArray(raw.models)) {\n return raw.models\n .map((item) => (typeof item === 'string' ? item : item.id))\n .filter((id): id is string => Boolean(id));\n }\n return [];\n}\n\nexport interface ListModelsResult {\n models: string[];\n visionModels: string[];\n suggestedVisionModel?: string;\n}\n\nexport async function listOpenAiCompatibleModels(\n clientSettings?: AiClientSettings,\n currentVisionModel?: string\n): Promise<ListModelsResult> {\n const config = resolveAiConnectionConfig(clientSettings);\n if (!config) {\n throw new Error('未配置 AI API Key,请在设置中填写或配置服务端环境变量');\n }\n\n const raw = await requestJson<OpenAiModelListResponse>({\n url: joinUrl(config.baseUrl, 'models'),\n method: 'GET',\n headers: {\n Authorization: `Bearer ${config.apiKey}`,\n },\n timeoutMs: config.timeoutMs,\n });\n\n const modelIds = parseModelIds(raw);\n if (modelIds.length === 0) {\n throw new Error('接口未返回可用模型');\n }\n\n const models = filterChatModels(modelIds);\n const visionModels = filterVisionModels(modelIds);\n const suggestedVisionModel = pickDefaultVisionModel(modelIds, currentVisionModel);\n\n return { models, visionModels, suggestedVisionModel };\n}\n","import type { AiTaskDefinition } from './types';\n\nconst registry = new Map<string, AiTaskDefinition>();\n\nexport function registerAiTask<TInput, TOutput>(task: AiTaskDefinition<TInput, TOutput>): void {\n if (registry.has(task.id)) {\n console.warn(`[aiApi] task \"${task.id}\" already registered, skipping duplicate`);\n return;\n }\n registry.set(task.id, task as AiTaskDefinition);\n}\n\nexport function getAiTask(taskId: string): AiTaskDefinition | undefined {\n return registry.get(taskId);\n}\n\nexport function listAiTasks(): string[] {\n return Array.from(registry.keys());\n}\n\nexport function clearAiTasksForTest(): void {\n registry.clear();\n}\n","import { resolveAiConnectionConfig } from './resolveConfig';\nimport { getAiTask } from './taskRegistry';\nimport type { AiClientSettings, AiApiResponse, AiTaskContext } from './types';\n\nfunction extractInputConnection(input: unknown): AiClientSettings | undefined {\n if (!input || typeof input !== 'object') return undefined;\n const connection = (input as { connection?: AiClientSettings }).connection;\n return connection && typeof connection === 'object' ? connection : undefined;\n}\n\nexport async function runAiTask<TData = unknown>(\n taskId: string,\n input: unknown,\n ctx: AiTaskContext = {}\n): Promise<AiApiResponse<TData>> {\n const started = Date.now();\n\n if (!resolveAiConnectionConfig(extractInputConnection(input), ctx.clientSettings)) {\n return {\n success: false,\n taskId,\n error: {\n code: 'AI_CONFIG_MISSING',\n message: '未配置 AI API Key,请传入 clientSettings.connection 或设置环境变量 AI_API_KEY',\n },\n };\n }\n\n const task = getAiTask(taskId);\n if (!task) {\n return {\n success: false,\n taskId,\n error: {\n code: 'TASK_NOT_FOUND',\n message: `未注册的任务: ${taskId}`,\n },\n };\n }\n\n try {\n const validated = task.validateInput(input);\n const result = await task.execute(validated, ctx);\n\n return {\n success: true,\n taskId,\n data: result.data as TData,\n meta: {\n model: result.meta?.model ?? 'unknown',\n latencyMs: Date.now() - started,\n provider: result.meta?.provider ?? 'openai-compatible',\n confidence: result.meta?.confidence,\n rawSummary: result.meta?.rawSummary,\n },\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : 'AI 任务执行失败';\n const code = classifyError(message);\n\n return {\n success: false,\n taskId,\n error: { code, message },\n meta: {\n model: 'unknown',\n latencyMs: Date.now() - started,\n },\n };\n }\n}\n\nfunction classifyError(message: string) {\n if (message.includes('未配置') || message.includes('AI_API_KEY') || message.includes('apiKey')) {\n return 'AI_CONFIG_MISSING' as const;\n }\n if (message.includes('图片') || message.includes('格式')) {\n return message.includes('过大') ? ('PAYLOAD_TOO_LARGE' as const) : ('UNSUPPORTED_MEDIA' as const);\n }\n if (message.includes('解析') || message.includes('JSON')) {\n return 'AI_PARSE_FAILED' as const;\n }\n if (message.includes('必填') || message.includes('无效')) {\n return 'INVALID_INPUT' as const;\n }\n return 'AI_REQUEST_FAILED' as const;\n}\n","import type { AiTaskDefinition, TextCompletionInput, TextCompletionOutput } from '../types';\nimport { callCompletion } from '../callCompletion';\nimport { CORE_LLM_COMPLETION_TASK_ID } from '../types';\n\nfunction isTextCompletionInput(input: unknown): input is TextCompletionInput {\n if (!input || typeof input !== 'object') return false;\n const value = input as TextCompletionInput;\n return typeof value.userPrompt === 'string' && value.userPrompt.trim().length > 0;\n}\n\nexport const coreLlmCompletionTask: AiTaskDefinition<TextCompletionInput, TextCompletionOutput> = {\n id: CORE_LLM_COMPLETION_TASK_ID,\n description: '通用文本补全:system/user 提示词 → 模型文本',\n validateInput(input) {\n if (!isTextCompletionInput(input)) {\n throw new Error('userPrompt 为必填');\n }\n return input;\n },\n async execute(input, ctx) {\n const result = await callCompletion(\n {\n systemPrompt: input.systemPrompt,\n userPrompt: input.userPrompt,\n model: input.model,\n temperature: input.temperature,\n maxTokens: input.maxTokens,\n connection: input.connection,\n },\n ctx.clientSettings\n );\n\n return {\n data: {\n content: result.content,\n rawText: result.content,\n },\n meta: {\n model: result.model,\n provider: 'openai-compatible',\n },\n };\n },\n};\n","import type {\n AiTaskDefinition,\n StructuredMultimodalInput,\n StructuredMultimodalOutput,\n} from '../types';\nimport { callMultimodalChat } from '../callMultimodalChat';\nimport { extractJsonObject } from '../jsonUtils';\nimport { assertValidMultimodalMedia } from '../mediaUtils';\nimport { resolveAiConnectionConfig } from '../resolveConfig';\nimport { CORE_STRUCTURED_MULTIMODAL_TASK_ID } from '../types';\n\nfunction isStructuredMultimodalInput(input: unknown): input is StructuredMultimodalInput {\n if (!input || typeof input !== 'object') return false;\n const value = input as StructuredMultimodalInput;\n return typeof value.systemPrompt === 'string' && typeof value.userPrompt === 'string';\n}\n\nexport const coreStructuredMultimodalTask: AiTaskDefinition<\n StructuredMultimodalInput,\n StructuredMultimodalOutput\n> = {\n id: CORE_STRUCTURED_MULTIMODAL_TASK_ID,\n description: '通用结构化多模态任务:文本 + 可选图片/语音 → JSON',\n validateInput(input) {\n if (!isStructuredMultimodalInput(input)) {\n throw new Error('systemPrompt 与 userPrompt 为必填');\n }\n const config = resolveAiConnectionConfig(input.connection);\n assertValidMultimodalMedia(input.media, {\n maxImageBytes: config?.maxImageBytes ?? 5 * 1024 * 1024,\n maxAudioBytes: config?.maxAudioBytes ?? 25 * 1024 * 1024,\n });\n return input;\n },\n async execute(input, ctx) {\n const schemaHint = input.jsonSchemaHint\n ? `\\n\\n请严格输出 JSON 对象,结构参考:\\n${input.jsonSchemaHint}`\n : '\\n\\n请严格输出 JSON 对象,不要包含 Markdown 代码块。';\n\n const result = await callMultimodalChat(\n {\n systemPrompt: input.systemPrompt,\n userPrompt: `${input.userPrompt}${schemaHint}`,\n media: input.media,\n model: input.model,\n temperature: input.temperature ?? 0.2,\n maxTokens: input.maxTokens,\n jsonMode: true,\n audioStrategy: input.audioStrategy,\n connection: input.connection,\n },\n ctx.clientSettings\n );\n\n const json = extractJsonObject(result.content);\n\n return {\n data: {\n json,\n rawText: result.content,\n },\n meta: {\n model: result.model,\n provider: 'openai-compatible',\n rawSummary: result.audioHandling\n ? `audio=${result.audioHandling}`\n : undefined,\n },\n };\n },\n};\n","import type { AiTaskDefinition, ConnectivityTestOutput } from '../types';\nimport { callChat } from '../callChat';\nimport { extractJsonObject } from '../jsonUtils';\nimport { resolveAiConnectionConfig } from '../resolveConfig';\nimport { CORE_CONNECTIVITY_TEST_TASK_ID } from '../types';\n\nexport const coreConnectivityTestTask: AiTaskDefinition<Record<string, never>, ConnectivityTestOutput> =\n {\n id: CORE_CONNECTIVITY_TEST_TASK_ID,\n description: '测试 AI API 连通性(轻量文本请求)',\n validateInput() {\n return {};\n },\n async execute(_input, ctx) {\n const config = resolveAiConnectionConfig(ctx.clientSettings);\n if (!config) {\n throw new Error('未配置 AI API Key');\n }\n\n const result = await callChat({\n baseUrl: config.baseUrl,\n apiKey: config.apiKey,\n model: config.textModel,\n systemPrompt: 'You are a connectivity probe. Reply with JSON only.',\n userPrompt: 'Return JSON: {\"ok\":true,\"reply\":\"OK\"}',\n temperature: 0,\n maxTokens: 32,\n timeoutMs: config.timeoutMs,\n });\n\n let ok = false;\n let reply = result.content.trim();\n\n try {\n const json = extractJsonObject(result.content);\n ok = json.ok === true || json.ok === 'true';\n reply = String(json.reply ?? result.content).trim();\n } catch {\n ok = /ok/i.test(result.content);\n }\n\n if (!ok && !reply) {\n throw new Error('模型未返回有效响应');\n }\n\n return {\n data: { ok: true, reply: reply || 'OK' },\n meta: {\n model: result.model,\n provider: 'openai-compatible',\n },\n };\n },\n };\n","import { registerAiTask } from './taskRegistry';\nimport { coreLlmCompletionTask } from './tasks/coreLlmCompletion';\nimport { coreStructuredMultimodalTask } from './tasks/coreStructuredMultimodal';\nimport { coreConnectivityTestTask } from './tasks/coreConnectivityTest';\n\nlet registered = false;\n\n/** 注册内置通用 AI 任务(幂等) */\nexport function registerCoreAiTasks(): void {\n if (registered) return;\n registerAiTask(coreLlmCompletionTask);\n registerAiTask(coreStructuredMultimodalTask);\n registerAiTask(coreConnectivityTestTask);\n registered = true;\n}\n\n/** 别名:确保 core 任务已注册 */\nexport const ensureCoreAiTasksRegistered = registerCoreAiTasks;\n\nexport function resetCoreAiTasksForTest(): void {\n registered = false;\n}\n"]}
@@ -0,0 +1,71 @@
1
+ import { A as AiClientSettings, a as AiApiResponse, b as AiModelsListResponse, c as AudioStrategy } from '../../../types-CiqMQ-uu.mjs';
2
+
3
+ declare class AiApiClientError extends Error {
4
+ readonly code?: string | undefined;
5
+ readonly response?: AiApiResponse | undefined;
6
+ constructor(message: string, code?: string | undefined, response?: AiApiResponse | undefined);
7
+ }
8
+ interface AiApiClientOptions {
9
+ /** 默认 POST /api/ai/run,宿主应用可覆盖 */
10
+ runEndpoint?: string;
11
+ fetchImpl?: typeof fetch;
12
+ }
13
+ /**
14
+ * 通过 HTTP 调用宿主暴露的 AI 任务入口(如 Next.js route)。
15
+ * 连接配置可通过请求体 clientSettings 传入,或从 localStorage 读取。
16
+ */
17
+ declare function runAiTask<TInput, TOutput>(taskId: string, input: TInput, options?: {
18
+ signal?: AbortSignal;
19
+ clientSettings?: AiClientSettings;
20
+ runEndpoint?: string;
21
+ fetchImpl?: typeof fetch;
22
+ }): Promise<AiApiResponse<TOutput>>;
23
+ declare function runAiTaskOrThrow<TInput, TOutput>(taskId: string, input: TInput, options?: {
24
+ signal?: AbortSignal;
25
+ clientSettings?: AiClientSettings;
26
+ runEndpoint?: string;
27
+ fetchImpl?: typeof fetch;
28
+ }): Promise<TOutput>;
29
+ declare function createAiTaskRunner<TInput, TOutput>(taskId: string, options?: AiApiClientOptions): (input: TInput, runOptions?: {
30
+ signal?: AbortSignal;
31
+ clientSettings?: AiClientSettings;
32
+ }) => Promise<TOutput>;
33
+ declare const aiApiClient: {
34
+ run: typeof runAiTask;
35
+ runOrThrow: typeof runAiTaskOrThrow;
36
+ createRunner: typeof createAiTaskRunner;
37
+ };
38
+
39
+ declare function fetchAiModels(clientSettings?: AiClientSettings, options?: {
40
+ signal?: AbortSignal;
41
+ modelsEndpoint?: string;
42
+ fetchImpl?: typeof fetch;
43
+ }): Promise<AiModelsListResponse>;
44
+
45
+ declare function useAiTask<TInput, TOutput>(taskId: string): {
46
+ execute: (input: TInput, options?: {
47
+ signal?: AbortSignal;
48
+ clientSettings?: AiClientSettings;
49
+ }) => Promise<AiApiResponse<TOutput>>;
50
+ loading: boolean;
51
+ error: string | null;
52
+ result: AiApiResponse<TOutput> | null;
53
+ reset: () => void;
54
+ };
55
+
56
+ interface AiApiSettings {
57
+ apiKey: string;
58
+ baseUrl: string;
59
+ visionModel: string;
60
+ textModel?: string;
61
+ audioModel?: string;
62
+ audioStrategy?: AudioStrategy;
63
+ }
64
+ declare const DEFAULT_AI_API_SETTINGS: AiApiSettings;
65
+ declare const AI_API_SETTINGS_STORAGE_KEY = "ai-api-settings";
66
+ declare function loadAiApiSettings(storageKey?: string): AiApiSettings;
67
+ declare function saveAiApiSettings(settings: AiApiSettings, storageKey?: string): void;
68
+ declare function toClientSettings(settings: AiApiSettings): AiClientSettings | undefined;
69
+ declare function pickClientSettingsFromStorage(storageKey?: string): AiClientSettings | undefined;
70
+
71
+ export { AI_API_SETTINGS_STORAGE_KEY, AiApiClientError, type AiApiClientOptions, type AiApiSettings, DEFAULT_AI_API_SETTINGS, aiApiClient, createAiTaskRunner, fetchAiModels, loadAiApiSettings, pickClientSettingsFromStorage, runAiTask, runAiTaskOrThrow, saveAiApiSettings, toClientSettings, useAiTask };
@@ -0,0 +1,71 @@
1
+ import { A as AiClientSettings, a as AiApiResponse, b as AiModelsListResponse, c as AudioStrategy } from '../../../types-CiqMQ-uu.js';
2
+
3
+ declare class AiApiClientError extends Error {
4
+ readonly code?: string | undefined;
5
+ readonly response?: AiApiResponse | undefined;
6
+ constructor(message: string, code?: string | undefined, response?: AiApiResponse | undefined);
7
+ }
8
+ interface AiApiClientOptions {
9
+ /** 默认 POST /api/ai/run,宿主应用可覆盖 */
10
+ runEndpoint?: string;
11
+ fetchImpl?: typeof fetch;
12
+ }
13
+ /**
14
+ * 通过 HTTP 调用宿主暴露的 AI 任务入口(如 Next.js route)。
15
+ * 连接配置可通过请求体 clientSettings 传入,或从 localStorage 读取。
16
+ */
17
+ declare function runAiTask<TInput, TOutput>(taskId: string, input: TInput, options?: {
18
+ signal?: AbortSignal;
19
+ clientSettings?: AiClientSettings;
20
+ runEndpoint?: string;
21
+ fetchImpl?: typeof fetch;
22
+ }): Promise<AiApiResponse<TOutput>>;
23
+ declare function runAiTaskOrThrow<TInput, TOutput>(taskId: string, input: TInput, options?: {
24
+ signal?: AbortSignal;
25
+ clientSettings?: AiClientSettings;
26
+ runEndpoint?: string;
27
+ fetchImpl?: typeof fetch;
28
+ }): Promise<TOutput>;
29
+ declare function createAiTaskRunner<TInput, TOutput>(taskId: string, options?: AiApiClientOptions): (input: TInput, runOptions?: {
30
+ signal?: AbortSignal;
31
+ clientSettings?: AiClientSettings;
32
+ }) => Promise<TOutput>;
33
+ declare const aiApiClient: {
34
+ run: typeof runAiTask;
35
+ runOrThrow: typeof runAiTaskOrThrow;
36
+ createRunner: typeof createAiTaskRunner;
37
+ };
38
+
39
+ declare function fetchAiModels(clientSettings?: AiClientSettings, options?: {
40
+ signal?: AbortSignal;
41
+ modelsEndpoint?: string;
42
+ fetchImpl?: typeof fetch;
43
+ }): Promise<AiModelsListResponse>;
44
+
45
+ declare function useAiTask<TInput, TOutput>(taskId: string): {
46
+ execute: (input: TInput, options?: {
47
+ signal?: AbortSignal;
48
+ clientSettings?: AiClientSettings;
49
+ }) => Promise<AiApiResponse<TOutput>>;
50
+ loading: boolean;
51
+ error: string | null;
52
+ result: AiApiResponse<TOutput> | null;
53
+ reset: () => void;
54
+ };
55
+
56
+ interface AiApiSettings {
57
+ apiKey: string;
58
+ baseUrl: string;
59
+ visionModel: string;
60
+ textModel?: string;
61
+ audioModel?: string;
62
+ audioStrategy?: AudioStrategy;
63
+ }
64
+ declare const DEFAULT_AI_API_SETTINGS: AiApiSettings;
65
+ declare const AI_API_SETTINGS_STORAGE_KEY = "ai-api-settings";
66
+ declare function loadAiApiSettings(storageKey?: string): AiApiSettings;
67
+ declare function saveAiApiSettings(settings: AiApiSettings, storageKey?: string): void;
68
+ declare function toClientSettings(settings: AiApiSettings): AiClientSettings | undefined;
69
+ declare function pickClientSettingsFromStorage(storageKey?: string): AiClientSettings | undefined;
70
+
71
+ export { AI_API_SETTINGS_STORAGE_KEY, AiApiClientError, type AiApiClientOptions, type AiApiSettings, DEFAULT_AI_API_SETTINGS, aiApiClient, createAiTaskRunner, fetchAiModels, loadAiApiSettings, pickClientSettingsFromStorage, runAiTask, runAiTaskOrThrow, saveAiApiSettings, toClientSettings, useAiTask };
@@ -0,0 +1,165 @@
1
+ 'use strict';
2
+
3
+ require('../../../chunk-NSBPE2FW.js');
4
+ var react = require('react');
5
+
6
+ // src/common/aiApi/client/settingsCore.ts
7
+ var DEFAULT_AI_API_SETTINGS = {
8
+ apiKey: "",
9
+ baseUrl: "https://api.openai.com/v1",
10
+ visionModel: "gpt-4o-mini",
11
+ textModel: "gpt-4o-mini",
12
+ audioModel: "whisper-1",
13
+ audioStrategy: "auto"
14
+ };
15
+ var AI_API_SETTINGS_STORAGE_KEY = "ai-api-settings";
16
+ function loadAiApiSettings(storageKey = AI_API_SETTINGS_STORAGE_KEY) {
17
+ if (typeof window === "undefined") return DEFAULT_AI_API_SETTINGS;
18
+ try {
19
+ const raw = localStorage.getItem(storageKey);
20
+ if (!raw) return DEFAULT_AI_API_SETTINGS;
21
+ return { ...DEFAULT_AI_API_SETTINGS, ...JSON.parse(raw) };
22
+ } catch {
23
+ return DEFAULT_AI_API_SETTINGS;
24
+ }
25
+ }
26
+ function saveAiApiSettings(settings, storageKey = AI_API_SETTINGS_STORAGE_KEY) {
27
+ if (typeof window === "undefined") return;
28
+ localStorage.setItem(storageKey, JSON.stringify(settings));
29
+ }
30
+ function toClientSettings(settings) {
31
+ const client = {};
32
+ if (settings.apiKey.trim()) client.apiKey = settings.apiKey.trim();
33
+ if (settings.baseUrl.trim()) client.baseUrl = settings.baseUrl.trim();
34
+ const visionModel = settings.visionModel.trim();
35
+ const textModel = settings.textModel?.trim() || visionModel;
36
+ const audioModel = settings.audioModel?.trim();
37
+ if (visionModel) client.visionModel = visionModel;
38
+ if (textModel) client.textModel = textModel;
39
+ if (audioModel) client.audioModel = audioModel;
40
+ if (settings.audioStrategy) client.audioStrategy = settings.audioStrategy;
41
+ return Object.keys(client).length > 0 ? client : void 0;
42
+ }
43
+ function pickClientSettingsFromStorage(storageKey = AI_API_SETTINGS_STORAGE_KEY) {
44
+ return toClientSettings(loadAiApiSettings(storageKey));
45
+ }
46
+
47
+ // src/common/aiApi/client/aiApiClient.ts
48
+ var AiApiClientError = class extends Error {
49
+ constructor(message, code, response) {
50
+ super(message);
51
+ this.code = code;
52
+ this.response = response;
53
+ this.name = "AiApiClientError";
54
+ }
55
+ };
56
+ async function runAiTask(taskId, input, options) {
57
+ const fetchFn = options?.fetchImpl ?? fetch;
58
+ const endpoint = options?.runEndpoint ?? "/api/ai/run";
59
+ const clientSettings = options?.clientSettings ?? pickClientSettingsFromStorage();
60
+ const payload = {
61
+ taskId,
62
+ input,
63
+ ...clientSettings ? { clientSettings } : {}
64
+ };
65
+ const response = await fetchFn(endpoint, {
66
+ method: "POST",
67
+ credentials: "include",
68
+ headers: { "Content-Type": "application/json" },
69
+ body: JSON.stringify(payload),
70
+ signal: options?.signal
71
+ });
72
+ const data = await response.json();
73
+ return data;
74
+ }
75
+ async function runAiTaskOrThrow(taskId, input, options) {
76
+ const result = await runAiTask(taskId, input, options);
77
+ if (!result.success || result.data === void 0) {
78
+ throw new AiApiClientError(
79
+ result.error?.message ?? "AI \u4EFB\u52A1\u5931\u8D25",
80
+ result.error?.code,
81
+ result
82
+ );
83
+ }
84
+ return result.data;
85
+ }
86
+ function createAiTaskRunner(taskId, options) {
87
+ return (input, runOptions) => runAiTaskOrThrow(taskId, input, {
88
+ ...runOptions,
89
+ runEndpoint: options?.runEndpoint,
90
+ fetchImpl: options?.fetchImpl
91
+ });
92
+ }
93
+ var aiApiClient = {
94
+ run: runAiTask,
95
+ runOrThrow: runAiTaskOrThrow,
96
+ createRunner: createAiTaskRunner
97
+ };
98
+
99
+ // src/common/aiApi/client/fetchModels.ts
100
+ async function fetchAiModels(clientSettings, options) {
101
+ const fetchFn = options?.fetchImpl ?? fetch;
102
+ const endpoint = options?.modelsEndpoint ?? "/api/ai/models";
103
+ const response = await fetchFn(endpoint, {
104
+ method: "POST",
105
+ credentials: "include",
106
+ headers: { "Content-Type": "application/json" },
107
+ body: JSON.stringify({ clientSettings }),
108
+ signal: options?.signal
109
+ });
110
+ return await response.json();
111
+ }
112
+ function useAiTask(taskId) {
113
+ const [loading, setLoading] = react.useState(false);
114
+ const [error, setError] = react.useState(null);
115
+ const [result, setResult] = react.useState(null);
116
+ const execute = react.useCallback(
117
+ async (input, options) => {
118
+ setLoading(true);
119
+ setError(null);
120
+ try {
121
+ const response = await runAiTask(taskId, input, options);
122
+ setResult(response);
123
+ if (!response.success) {
124
+ setError(response.error?.message ?? "AI \u4EFB\u52A1\u5931\u8D25");
125
+ }
126
+ return response;
127
+ } catch (err) {
128
+ const message = err instanceof Error ? err.message : "AI \u4EFB\u52A1\u5931\u8D25";
129
+ setError(message);
130
+ const failed = {
131
+ success: false,
132
+ taskId,
133
+ error: { code: "AI_REQUEST_FAILED", message }
134
+ };
135
+ setResult(failed);
136
+ return failed;
137
+ } finally {
138
+ setLoading(false);
139
+ }
140
+ },
141
+ [taskId]
142
+ );
143
+ const reset = react.useCallback(() => {
144
+ setLoading(false);
145
+ setError(null);
146
+ setResult(null);
147
+ }, []);
148
+ return { execute, loading, error, result, reset };
149
+ }
150
+
151
+ exports.AI_API_SETTINGS_STORAGE_KEY = AI_API_SETTINGS_STORAGE_KEY;
152
+ exports.AiApiClientError = AiApiClientError;
153
+ exports.DEFAULT_AI_API_SETTINGS = DEFAULT_AI_API_SETTINGS;
154
+ exports.aiApiClient = aiApiClient;
155
+ exports.createAiTaskRunner = createAiTaskRunner;
156
+ exports.fetchAiModels = fetchAiModels;
157
+ exports.loadAiApiSettings = loadAiApiSettings;
158
+ exports.pickClientSettingsFromStorage = pickClientSettingsFromStorage;
159
+ exports.runAiTask = runAiTask;
160
+ exports.runAiTaskOrThrow = runAiTaskOrThrow;
161
+ exports.saveAiApiSettings = saveAiApiSettings;
162
+ exports.toClientSettings = toClientSettings;
163
+ exports.useAiTask = useAiTask;
164
+ //# sourceMappingURL=index.js.map
165
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/common/aiApi/client/settingsCore.ts","../../../../src/common/aiApi/client/aiApiClient.ts","../../../../src/common/aiApi/client/fetchModels.ts","../../../../src/common/aiApi/client/hooks/useAiTask.ts"],"names":["useState","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import type { AiClientSettings, AudioStrategy } from '../types';\n\nexport interface AiApiSettings {\n apiKey: string;\n baseUrl: string;\n visionModel: string;\n textModel?: string;\n audioModel?: string;\n audioStrategy?: AudioStrategy;\n}\n\nexport const DEFAULT_AI_API_SETTINGS: AiApiSettings = {\n apiKey: '',\n baseUrl: 'https://api.openai.com/v1',\n visionModel: 'gpt-4o-mini',\n textModel: 'gpt-4o-mini',\n audioModel: 'whisper-1',\n audioStrategy: 'auto',\n};\n\nexport const AI_API_SETTINGS_STORAGE_KEY = 'ai-api-settings';\n\nexport function loadAiApiSettings(storageKey = AI_API_SETTINGS_STORAGE_KEY): AiApiSettings {\n if (typeof window === 'undefined') return DEFAULT_AI_API_SETTINGS;\n try {\n const raw = localStorage.getItem(storageKey);\n if (!raw) return DEFAULT_AI_API_SETTINGS;\n return { ...DEFAULT_AI_API_SETTINGS, ...JSON.parse(raw) };\n } catch {\n return DEFAULT_AI_API_SETTINGS;\n }\n}\n\nexport function saveAiApiSettings(\n settings: AiApiSettings,\n storageKey = AI_API_SETTINGS_STORAGE_KEY\n): void {\n if (typeof window === 'undefined') return;\n localStorage.setItem(storageKey, JSON.stringify(settings));\n}\n\nexport function toClientSettings(settings: AiApiSettings): AiClientSettings | undefined {\n const client: AiClientSettings = {};\n if (settings.apiKey.trim()) client.apiKey = settings.apiKey.trim();\n if (settings.baseUrl.trim()) client.baseUrl = settings.baseUrl.trim();\n const visionModel = settings.visionModel.trim();\n const textModel = settings.textModel?.trim() || visionModel;\n const audioModel = settings.audioModel?.trim();\n if (visionModel) client.visionModel = visionModel;\n if (textModel) client.textModel = textModel;\n if (audioModel) client.audioModel = audioModel;\n if (settings.audioStrategy) client.audioStrategy = settings.audioStrategy;\n return Object.keys(client).length > 0 ? client : undefined;\n}\n\nexport function pickClientSettingsFromStorage(\n storageKey = AI_API_SETTINGS_STORAGE_KEY\n): AiClientSettings | undefined {\n return toClientSettings(loadAiApiSettings(storageKey));\n}\n","import type { AiApiResponse, AiApiRunRequest, AiClientSettings } from '../types';\nimport { pickClientSettingsFromStorage } from './settingsCore';\n\nexport class AiApiClientError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly response?: AiApiResponse\n ) {\n super(message);\n this.name = 'AiApiClientError';\n }\n}\n\nexport interface AiApiClientOptions {\n /** 默认 POST /api/ai/run,宿主应用可覆盖 */\n runEndpoint?: string;\n fetchImpl?: typeof fetch;\n}\n\n/**\n * 通过 HTTP 调用宿主暴露的 AI 任务入口(如 Next.js route)。\n * 连接配置可通过请求体 clientSettings 传入,或从 localStorage 读取。\n */\nexport async function runAiTask<TInput, TOutput>(\n taskId: string,\n input: TInput,\n options?: {\n signal?: AbortSignal;\n clientSettings?: AiClientSettings;\n runEndpoint?: string;\n fetchImpl?: typeof fetch;\n }\n): Promise<AiApiResponse<TOutput>> {\n const fetchFn = options?.fetchImpl ?? fetch;\n const endpoint = options?.runEndpoint ?? '/api/ai/run';\n const clientSettings = options?.clientSettings ?? pickClientSettingsFromStorage();\n\n const payload: AiApiRunRequest<TInput> = {\n taskId,\n input,\n ...(clientSettings ? { clientSettings } : {}),\n };\n\n const response = await fetchFn(endpoint, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: options?.signal,\n });\n\n const data = (await response.json()) as AiApiResponse<TOutput>;\n return data;\n}\n\nexport async function runAiTaskOrThrow<TInput, TOutput>(\n taskId: string,\n input: TInput,\n options?: {\n signal?: AbortSignal;\n clientSettings?: AiClientSettings;\n runEndpoint?: string;\n fetchImpl?: typeof fetch;\n }\n): Promise<TOutput> {\n const result = await runAiTask<TInput, TOutput>(taskId, input, options);\n if (!result.success || result.data === undefined) {\n throw new AiApiClientError(\n result.error?.message ?? 'AI 任务失败',\n result.error?.code,\n result\n );\n }\n return result.data;\n}\n\nexport function createAiTaskRunner<TInput, TOutput>(\n taskId: string,\n options?: AiApiClientOptions\n) {\n return (\n input: TInput,\n runOptions?: { signal?: AbortSignal; clientSettings?: AiClientSettings }\n ) =>\n runAiTaskOrThrow<TInput, TOutput>(taskId, input, {\n ...runOptions,\n runEndpoint: options?.runEndpoint,\n fetchImpl: options?.fetchImpl,\n });\n}\n\nexport const aiApiClient = {\n run: runAiTask,\n runOrThrow: runAiTaskOrThrow,\n createRunner: createAiTaskRunner,\n};\n","import type { AiClientSettings, AiModelsListResponse } from '../types';\n\nexport async function fetchAiModels(\n clientSettings?: AiClientSettings,\n options?: { signal?: AbortSignal; modelsEndpoint?: string; fetchImpl?: typeof fetch }\n): Promise<AiModelsListResponse> {\n const fetchFn = options?.fetchImpl ?? fetch;\n const endpoint = options?.modelsEndpoint ?? '/api/ai/models';\n\n const response = await fetchFn(endpoint, {\n method: 'POST',\n credentials: 'include',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ clientSettings }),\n signal: options?.signal,\n });\n\n return (await response.json()) as AiModelsListResponse;\n}\n","'use client';\n\nimport { useCallback, useState } from 'react';\nimport type { AiClientSettings, AiApiResponse } from '../../types';\nimport { runAiTask } from '../aiApiClient';\n\nexport function useAiTask<TInput, TOutput>(taskId: string) {\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [result, setResult] = useState<AiApiResponse<TOutput> | null>(null);\n\n const execute = useCallback(\n async (\n input: TInput,\n options?: { signal?: AbortSignal; clientSettings?: AiClientSettings }\n ) => {\n setLoading(true);\n setError(null);\n try {\n const response = await runAiTask<TInput, TOutput>(taskId, input, options);\n setResult(response);\n if (!response.success) {\n setError(response.error?.message ?? 'AI 任务失败');\n }\n return response;\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI 任务失败';\n setError(message);\n const failed: AiApiResponse<TOutput> = {\n success: false,\n taskId,\n error: { code: 'AI_REQUEST_FAILED', message },\n };\n setResult(failed);\n return failed;\n } finally {\n setLoading(false);\n }\n },\n [taskId]\n );\n\n const reset = useCallback(() => {\n setLoading(false);\n setError(null);\n setResult(null);\n }, []);\n\n return { execute, loading, error, result, reset };\n}\n"]}