/** * Runtime Resolver — 从配置推断运行时参数 * * 输入:agent 定义 + client 定义(camelCase,来自 _rowToClientConfig) * 输出:protocol, transport, launcherType, launcherConfig * * 纯函数,无状态,无 DB 依赖。 * * 推断规则: * protocol = client.acpProtocol (claude → claude-stream, 其余 → acp) * transport = deploy === 'local' ? 'pipe' : 'websocket' * launcher = { local: 'process', remote: 'none' }[deploy] */ /** * 推断运行时参数 * * @param {object} agent - { type, client, deploy, ... } * @param {object} client - { name, command, acpArgs, acpProtocol, ... } * @returns {{ * protocol: string, * transport: string, * launcherType: string, * command: string, * args: string[], * launcherConfig: object * }} */ function resolve(agent, client) { if (!client) { throw new Error(`[RuntimeResolver] agent "${agent.name}" 没有关联 client`); } const deploy = agent.deploy || 'local'; // ── 推断 protocol ── // 优先使用 agent 配置中的 protocol(per-agent 可覆盖),再用 client 级别默认 const protocol = agent.protocol || client.acpProtocol || 'acp'; // ── 推断 transport ── const transport = deploy === 'local' ? 'pipe' : 'websocket'; // ── 推断 launcher type ── const launcherTypeMap = { local: 'process', remote: 'none' }; const launcherType = launcherTypeMap[deploy]; if (!launcherType) { throw new Error(`[RuntimeResolver] 未知 deploy 类型: ${deploy}`); } // ── 构建 launcher config(给 factory.js 用)── const launcherConfig = buildLauncherConfig(client, deploy); return { protocol, transport, launcherType, command: client.command, args: client.acpArgs || [], launcherConfig, }; } /** * 构建 launcher config(兼容 factory.js 的 createConnection 参数格式) */ function buildLauncherConfig(client, deploy) { switch (deploy) { case 'local': return { type: 'process', command: client.command, args: client.acpArgs || [], }; case 'remote': return { type: 'none', url: client.remoteUrl, }; default: throw new Error(`[RuntimeResolver] 未知 deploy: ${deploy}`); } } module.exports = { resolve, buildLauncherConfig };