const path = require('path') /** 与 fun/ai 各 execute 一致:统一走 nodejs/ai/ai.js */ const aiModule = require(path.join(__dirname, '../../../../ai/ai.js')) /** * @param {string} [model] 流程传入的 model;'doubao' 走豆包分支 * @param {{ openai: string, doubao: string }} actions openai 为 ai.run 名;doubao 为 doubao_ 前缀全名 */ function resolveModelAction (model, actions) { const mRaw = model != null ? String(model).trim() : '' const m = mRaw.toLowerCase() if (m === 'doubao') { return { action: actions.doubao, opts: {} } } const opts = {} if (mRaw) opts.model = mRaw return { action: actions.openai, opts } } function mergeRunOptions (opts, extraOpts) { const merged = { ...opts, ...(extraOpts || {}) } const out = {} for (const [k, v] of Object.entries(merged)) { if (v === undefined || v === null) continue if (k === 'model' && String(v).trim() === '') continue out[k] = v } return out } /** * @param {string} openaiAction * @param {string} doubaoAction 如 doubao_img2text * @param {unknown[]} runArgs ai.run 中位于 options 之前的参数 * @param {string} [model] * @param {Record} [extraOpts] 如 { timeoutMs } */ async function runWithModel (openaiAction, doubaoAction, runArgs, model, extraOpts) { const { action, opts } = resolveModelAction(model, { openai: openaiAction, doubao: doubaoAction }) const finalOpts = mergeRunOptions(opts, extraOpts) if (Object.keys(finalOpts).length === 0) { return aiModule.run(action, ...runArgs) } return aiModule.run(action, ...runArgs, finalOpts) } function resolveSavePath (savePath, folderPath) { if (!savePath || typeof savePath !== 'string') return null const trimmed = savePath.trim() if (path.isAbsolute(trimmed) || /^[A-Za-z]:/.test(trimmed)) return trimmed return folderPath ? path.join(folderPath, trimmed) : path.resolve(trimmed) } module.exports = { aiModule, resolveModelAction, runWithModel, resolveSavePath, }