sa2kit 3.7.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/dist/{chunk-ZJLS5JU5.mjs → chunk-6KD4CD7O.mjs} +7 -16
  2. package/dist/chunk-6KD4CD7O.mjs.map +1 -0
  3. package/dist/chunk-GJVEYCS4.js +12 -0
  4. package/dist/chunk-GJVEYCS4.js.map +1 -0
  5. package/dist/chunk-PPV4IEWR.mjs +8 -0
  6. package/dist/chunk-PPV4IEWR.mjs.map +1 -0
  7. package/dist/{chunk-XPY45Y75.js → chunk-VVHFMAE7.js} +9 -21
  8. package/dist/chunk-VVHFMAE7.js.map +1 -0
  9. package/dist/common/aiApi/client/index.d.mts +66 -4
  10. package/dist/common/aiApi/client/index.d.ts +66 -4
  11. package/dist/common/aiApi/client/index.js +360 -15
  12. package/dist/common/aiApi/client/index.js.map +1 -1
  13. package/dist/common/aiApi/client/index.mjs +345 -11
  14. package/dist/common/aiApi/client/index.mjs.map +1 -1
  15. package/dist/common/aiApi/index.d.mts +2 -2
  16. package/dist/common/aiApi/index.d.ts +2 -2
  17. package/dist/common/aiApi/index.js +63 -62
  18. package/dist/common/aiApi/index.mjs +2 -1
  19. package/dist/common/aiApi/server/index.d.mts +1 -1
  20. package/dist/common/aiApi/server/index.d.ts +1 -1
  21. package/dist/common/aiApi/server/index.js +63 -62
  22. package/dist/common/aiApi/server/index.mjs +2 -1
  23. package/dist/index.d.mts +9 -1
  24. package/dist/index.d.ts +9 -1
  25. package/dist/index.js +3 -9
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +3 -9
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/{types-CiqMQ-uu.d.mts → types-DgbG0Of-.d.mts} +9 -1
  30. package/dist/{types-CiqMQ-uu.d.ts → types-DgbG0Of-.d.ts} +9 -1
  31. package/package.json +1 -1
  32. package/dist/chunk-XPY45Y75.js.map +0 -1
  33. package/dist/chunk-ZJLS5JU5.mjs.map +0 -1
@@ -1,7 +1,4 @@
1
- // src/common/aiApi/types.ts
2
- var CORE_LLM_COMPLETION_TASK_ID = "core.llmCompletion";
3
- var CORE_STRUCTURED_MULTIMODAL_TASK_ID = "core.structuredMultimodal";
4
- var CORE_CONNECTIVITY_TEST_TASK_ID = "core.connectivityTest";
1
+ import { CORE_LLM_COMPLETION_TASK_ID, CORE_STRUCTURED_MULTIMODAL_TASK_ID, CORE_CONNECTIVITY_TEST_TASK_ID } from './chunk-PPV4IEWR.mjs';
5
2
 
6
3
  // src/common/aiApi/resolveConfig.ts
7
4
  var DEFAULT_BASE_URL = "https://api.openai.com/v1";
@@ -1043,23 +1040,17 @@ var coreConnectivityTestTask = {
1043
1040
  baseUrl: config.baseUrl,
1044
1041
  apiKey: config.apiKey,
1045
1042
  model: config.textModel,
1046
- systemPrompt: "You are a connectivity probe. Reply with JSON only.",
1047
- userPrompt: 'Return JSON: {"ok":true,"reply":"OK"}',
1043
+ systemPrompt: "You are a connectivity probe. Reply briefly.",
1044
+ userPrompt: "Say OK",
1048
1045
  temperature: 0,
1049
1046
  maxTokens: 32,
1050
1047
  timeoutMs: config.timeoutMs
1051
1048
  });
1052
- let ok = false;
1053
1049
  let reply = result.content.trim();
1054
1050
  try {
1055
1051
  const json = extractJsonObject(result.content);
1056
- ok = json.ok === true || json.ok === "true";
1057
- reply = String(json.reply ?? result.content).trim();
1052
+ reply = String(json.reply ?? json.message ?? result.content).trim();
1058
1053
  } catch {
1059
- ok = /ok/i.test(result.content);
1060
- }
1061
- if (!ok && !reply) {
1062
- throw new Error("\u6A21\u578B\u672A\u8FD4\u56DE\u6709\u6548\u54CD\u5E94");
1063
1054
  }
1064
1055
  return {
1065
1056
  data: { ok: true, reply: reply || "OK" },
@@ -1085,6 +1076,6 @@ function resetCoreAiTasksForTest() {
1085
1076
  registered = false;
1086
1077
  }
1087
1078
 
1088
- export { CORE_CONNECTIVITY_TEST_TASK_ID, CORE_LLM_COMPLETION_TASK_ID, CORE_STRUCTURED_MULTIMODAL_TASK_ID, DEFAULT_OPENAI_BASE_URL, DEFAULT_TEXT_MODEL2 as DEFAULT_TEXT_MODEL, appendTranscriptionsToPrompt, assertMultimodalCapableModel, assertValidAudioInput, assertValidImageInput, assertValidMultimodalMedia, assertVisionCapableModel, base64ToBlob, buildMultimodalMessages, callChat, callCompletion, callMultimodalChat, clearAiTasksForTest, coreConnectivityTestTask, coreLlmCompletionTask, coreStructuredMultimodalTask, detectVisionMessageFormat, ensureCoreAiTasksRegistered, extractJsonObject, fileToAiAudioInput, fileToAiImageInput, filterChatModels, filterSttModels, filterVisionModels, getAiTask, isAudioInputError, isImageUrlVariantError, isKnownTextOnlyModel, isLikelyNativeAudioChatModel, isLikelySttModel, isLikelyVisionModel, listAiTasks, listOpenAiCompatibleModels, mimeToAudioFormat, pickDefaultSttModel, pickDefaultVisionModel, registerAiTask, registerCoreAiTasks, requestJson, requireAiConnectionConfig, resetCoreAiTasksForTest, resolveAiConnectionConfig, resolveAudioHandling, runAiTask, splitMediaByKind, toVisionApiErrorMessage, transcribeAudio, transcribeAudios };
1089
- //# sourceMappingURL=chunk-ZJLS5JU5.mjs.map
1090
- //# sourceMappingURL=chunk-ZJLS5JU5.mjs.map
1079
+ export { DEFAULT_OPENAI_BASE_URL, DEFAULT_TEXT_MODEL2 as DEFAULT_TEXT_MODEL, appendTranscriptionsToPrompt, assertMultimodalCapableModel, assertValidAudioInput, assertValidImageInput, assertValidMultimodalMedia, assertVisionCapableModel, base64ToBlob, buildMultimodalMessages, callChat, callCompletion, callMultimodalChat, clearAiTasksForTest, coreConnectivityTestTask, coreLlmCompletionTask, coreStructuredMultimodalTask, detectVisionMessageFormat, ensureCoreAiTasksRegistered, extractJsonObject, fileToAiAudioInput, fileToAiImageInput, filterChatModels, filterSttModels, filterVisionModels, getAiTask, isAudioInputError, isImageUrlVariantError, isKnownTextOnlyModel, isLikelyNativeAudioChatModel, isLikelySttModel, isLikelyVisionModel, listAiTasks, listOpenAiCompatibleModels, mimeToAudioFormat, pickDefaultSttModel, pickDefaultVisionModel, registerAiTask, registerCoreAiTasks, requestJson, requireAiConnectionConfig, resetCoreAiTasksForTest, resolveAiConnectionConfig, resolveAudioHandling, runAiTask, splitMediaByKind, toVisionApiErrorMessage, transcribeAudio, transcribeAudios };
1080
+ //# sourceMappingURL=chunk-6KD4CD7O.mjs.map
1081
+ //# sourceMappingURL=chunk-6KD4CD7O.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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-6KD4CD7O.mjs","sourcesContent":["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 briefly.',\n userPrompt: 'Say OK',\n temperature: 0,\n maxTokens: 32,\n timeoutMs: config.timeoutMs,\n });\n\n // HTTP 请求成功即视为连通;尽量解析回复内容用于展示\n let reply = result.content.trim();\n\n try {\n const json = extractJsonObject(result.content);\n reply = String(json.reply ?? json.message ?? result.content).trim();\n } catch {\n // 非 JSON 回复也接受\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,12 @@
1
+ 'use strict';
2
+
3
+ // src/common/aiApi/types.ts
4
+ var CORE_LLM_COMPLETION_TASK_ID = "core.llmCompletion";
5
+ var CORE_STRUCTURED_MULTIMODAL_TASK_ID = "core.structuredMultimodal";
6
+ var CORE_CONNECTIVITY_TEST_TASK_ID = "core.connectivityTest";
7
+
8
+ exports.CORE_CONNECTIVITY_TEST_TASK_ID = CORE_CONNECTIVITY_TEST_TASK_ID;
9
+ exports.CORE_LLM_COMPLETION_TASK_ID = CORE_LLM_COMPLETION_TASK_ID;
10
+ exports.CORE_STRUCTURED_MULTIMODAL_TASK_ID = CORE_STRUCTURED_MULTIMODAL_TASK_ID;
11
+ //# sourceMappingURL=chunk-GJVEYCS4.js.map
12
+ //# sourceMappingURL=chunk-GJVEYCS4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/common/aiApi/types.ts"],"names":[],"mappings":";;;AA0IO,IAAM,2BAAA,GAA8B;AACpC,IAAM,kCAAA,GAAqC;AAC3C,IAAM,8BAAA,GAAiC","file":"chunk-GJVEYCS4.js","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\n/** GET /api/ai/config 响应(宿主实现,不暴露 apiKey) */\nexport interface AiServerConfigStatus {\n serverConfigured: boolean;\n baseUrl?: string;\n visionModel?: string;\n textModel?: string;\n error?: 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"]}
@@ -0,0 +1,8 @@
1
+ // src/common/aiApi/types.ts
2
+ var CORE_LLM_COMPLETION_TASK_ID = "core.llmCompletion";
3
+ var CORE_STRUCTURED_MULTIMODAL_TASK_ID = "core.structuredMultimodal";
4
+ var CORE_CONNECTIVITY_TEST_TASK_ID = "core.connectivityTest";
5
+
6
+ export { CORE_CONNECTIVITY_TEST_TASK_ID, CORE_LLM_COMPLETION_TASK_ID, CORE_STRUCTURED_MULTIMODAL_TASK_ID };
7
+ //# sourceMappingURL=chunk-PPV4IEWR.mjs.map
8
+ //# sourceMappingURL=chunk-PPV4IEWR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/common/aiApi/types.ts"],"names":[],"mappings":";AA0IO,IAAM,2BAAA,GAA8B;AACpC,IAAM,kCAAA,GAAqC;AAC3C,IAAM,8BAAA,GAAiC","file":"chunk-PPV4IEWR.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\n/** GET /api/ai/config 响应(宿主实现,不暴露 apiKey) */\nexport interface AiServerConfigStatus {\n serverConfigured: boolean;\n baseUrl?: string;\n visionModel?: string;\n textModel?: string;\n error?: 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"]}
@@ -1,9 +1,6 @@
1
1
  'use strict';
2
2
 
3
- // src/common/aiApi/types.ts
4
- var CORE_LLM_COMPLETION_TASK_ID = "core.llmCompletion";
5
- var CORE_STRUCTURED_MULTIMODAL_TASK_ID = "core.structuredMultimodal";
6
- var CORE_CONNECTIVITY_TEST_TASK_ID = "core.connectivityTest";
3
+ var chunkGJVEYCS4_js = require('./chunk-GJVEYCS4.js');
7
4
 
8
5
  // src/common/aiApi/resolveConfig.ts
9
6
  var DEFAULT_BASE_URL = "https://api.openai.com/v1";
@@ -942,7 +939,7 @@ function isTextCompletionInput(input) {
942
939
  return typeof value.userPrompt === "string" && value.userPrompt.trim().length > 0;
943
940
  }
944
941
  var coreLlmCompletionTask = {
945
- id: CORE_LLM_COMPLETION_TASK_ID,
942
+ id: chunkGJVEYCS4_js.CORE_LLM_COMPLETION_TASK_ID,
946
943
  description: "\u901A\u7528\u6587\u672C\u8865\u5168\uFF1Asystem/user \u63D0\u793A\u8BCD \u2192 \u6A21\u578B\u6587\u672C",
947
944
  validateInput(input) {
948
945
  if (!isTextCompletionInput(input)) {
@@ -982,7 +979,7 @@ function isStructuredMultimodalInput(input) {
982
979
  return typeof value.systemPrompt === "string" && typeof value.userPrompt === "string";
983
980
  }
984
981
  var coreStructuredMultimodalTask = {
985
- id: CORE_STRUCTURED_MULTIMODAL_TASK_ID,
982
+ id: chunkGJVEYCS4_js.CORE_STRUCTURED_MULTIMODAL_TASK_ID,
986
983
  description: "\u901A\u7528\u7ED3\u6784\u5316\u591A\u6A21\u6001\u4EFB\u52A1\uFF1A\u6587\u672C + \u53EF\u9009\u56FE\u7247/\u8BED\u97F3 \u2192 JSON",
987
984
  validateInput(input) {
988
985
  if (!isStructuredMultimodalInput(input)) {
@@ -1031,7 +1028,7 @@ ${input.jsonSchemaHint}` : "\n\n\u8BF7\u4E25\u683C\u8F93\u51FA JSON \u5BF9\u8C61
1031
1028
 
1032
1029
  // src/common/aiApi/tasks/coreConnectivityTest.ts
1033
1030
  var coreConnectivityTestTask = {
1034
- id: CORE_CONNECTIVITY_TEST_TASK_ID,
1031
+ id: chunkGJVEYCS4_js.CORE_CONNECTIVITY_TEST_TASK_ID,
1035
1032
  description: "\u6D4B\u8BD5 AI API \u8FDE\u901A\u6027\uFF08\u8F7B\u91CF\u6587\u672C\u8BF7\u6C42\uFF09",
1036
1033
  validateInput() {
1037
1034
  return {};
@@ -1045,23 +1042,17 @@ var coreConnectivityTestTask = {
1045
1042
  baseUrl: config.baseUrl,
1046
1043
  apiKey: config.apiKey,
1047
1044
  model: config.textModel,
1048
- systemPrompt: "You are a connectivity probe. Reply with JSON only.",
1049
- userPrompt: 'Return JSON: {"ok":true,"reply":"OK"}',
1045
+ systemPrompt: "You are a connectivity probe. Reply briefly.",
1046
+ userPrompt: "Say OK",
1050
1047
  temperature: 0,
1051
1048
  maxTokens: 32,
1052
1049
  timeoutMs: config.timeoutMs
1053
1050
  });
1054
- let ok = false;
1055
1051
  let reply = result.content.trim();
1056
1052
  try {
1057
1053
  const json = extractJsonObject(result.content);
1058
- ok = json.ok === true || json.ok === "true";
1059
- reply = String(json.reply ?? result.content).trim();
1054
+ reply = String(json.reply ?? json.message ?? result.content).trim();
1060
1055
  } catch {
1061
- ok = /ok/i.test(result.content);
1062
- }
1063
- if (!ok && !reply) {
1064
- throw new Error("\u6A21\u578B\u672A\u8FD4\u56DE\u6709\u6548\u54CD\u5E94");
1065
1056
  }
1066
1057
  return {
1067
1058
  data: { ok: true, reply: reply || "OK" },
@@ -1087,9 +1078,6 @@ function resetCoreAiTasksForTest() {
1087
1078
  registered = false;
1088
1079
  }
1089
1080
 
1090
- exports.CORE_CONNECTIVITY_TEST_TASK_ID = CORE_CONNECTIVITY_TEST_TASK_ID;
1091
- exports.CORE_LLM_COMPLETION_TASK_ID = CORE_LLM_COMPLETION_TASK_ID;
1092
- exports.CORE_STRUCTURED_MULTIMODAL_TASK_ID = CORE_STRUCTURED_MULTIMODAL_TASK_ID;
1093
1081
  exports.DEFAULT_OPENAI_BASE_URL = DEFAULT_OPENAI_BASE_URL;
1094
1082
  exports.DEFAULT_TEXT_MODEL = DEFAULT_TEXT_MODEL2;
1095
1083
  exports.appendTranscriptionsToPrompt = appendTranscriptionsToPrompt;
@@ -1139,5 +1127,5 @@ exports.splitMediaByKind = splitMediaByKind;
1139
1127
  exports.toVisionApiErrorMessage = toVisionApiErrorMessage;
1140
1128
  exports.transcribeAudio = transcribeAudio;
1141
1129
  exports.transcribeAudios = transcribeAudios;
1142
- //# sourceMappingURL=chunk-XPY45Y75.js.map
1143
- //# sourceMappingURL=chunk-XPY45Y75.js.map
1130
+ //# sourceMappingURL=chunk-VVHFMAE7.js.map
1131
+ //# sourceMappingURL=chunk-VVHFMAE7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../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","CORE_LLM_COMPLETION_TASK_ID","CORE_STRUCTURED_MULTIMODAL_TASK_ID","CORE_CONNECTIVITY_TEST_TASK_ID"],"mappings":"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","file":"chunk-VVHFMAE7.js","sourcesContent":["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 briefly.',\n userPrompt: 'Say OK',\n temperature: 0,\n maxTokens: 32,\n timeoutMs: config.timeoutMs,\n });\n\n // HTTP 请求成功即视为连通;尽量解析回复内容用于展示\n let reply = result.content.trim();\n\n try {\n const json = extractJsonObject(result.content);\n reply = String(json.reply ?? json.message ?? result.content).trim();\n } catch {\n // 非 JSON 回复也接受\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"]}