#!/usr/bin/env node // ═══════════════════════════════════════════════ // 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001 // 📜 Copyright: 国作登字-2026-A-00037559 // ═══════════════════════════════════════════════ // scripts/llm-automation-host.js // 🤖 LLM 自动化托管引擎 // // 使用仓库密钥中的第三方模型API密钥来运行自动化任务 // 替代直接消耗 GitHub Copilot 配额 // 支持动态模型路由:根据任务类型自动选择最佳模型 // // 用法: // --status 显示可用模型和系统状态 // --task "任务描述" 执行自动化任务 // --task-type TYPE 任务类型 (inspection/fusion/review/general) // --model MODEL 指定模型 (auto/anthropic/openai/dashscope/deepseek/custom) // --dry-run 仅显示选择的模型和请求,不实际调用 // --context FILE 加载额外上下文文件 'use strict'; const https = require('https'); const http = require('http'); const fs = require('fs'); const path = require('path'); const ROOT = path.resolve(__dirname, '..'); // ── 模型后端配置 // SY-CMD-KEY-012: 统一使用 ZY_LLM_API_KEY + ZY_LLM_BASE_URL // 三方API密钥支持多模型动态路由,铸渊根据任务类型自动选择最优模型 const MODEL_BACKENDS = [ { name: 'deepseek', model: 'deepseek-chat', format: 'openai', strengths: ['reasoning', 'code', 'cost-effective'], costTier: 'low', description: 'DeepSeek 系列 · 高性价比推理' }, { name: 'deepseek-reasoner', model: 'deepseek-reasoner', format: 'openai', strengths: ['reasoning', 'architecture', 'long-context'], costTier: 'medium', description: 'DeepSeek Reasoner · 深度推理' }, { name: 'claude-sonnet', model: 'claude-sonnet-4-20250514', format: 'openai', strengths: ['reasoning', 'code-review', 'architecture', 'long-context'], costTier: 'high', description: 'Claude Sonnet · 强推理代码审查' }, { name: 'gpt-4o', model: 'gpt-4o', format: 'openai', strengths: ['general', 'code-generation', 'structured-output'], costTier: 'high', description: 'GPT-4o · 通用能力' }, { name: 'qwen-plus', model: 'qwen-plus', format: 'openai', strengths: ['chinese', 'general', 'cost-effective'], costTier: 'medium', description: '通义千问 Plus · 中文优化' }, { name: 'qwen-turbo', model: 'qwen-turbo', format: 'openai', strengths: ['chinese', 'general', 'cost-effective'], costTier: 'low', description: '通义千问 Turbo · 快速低成本' } ]; // ── 任务类型 → 模型强项映射(动态路由策略) const TASK_MODEL_ROUTING = { // 巡检任务:优先使用性价比高的模型 'inspection': { preferred_strengths: ['general', 'cost-effective'], preferred_cost: 'low', description: '系统巡检 · 优先性价比' }, // 融合分析:需要强推理能力 'fusion': { preferred_strengths: ['reasoning', 'code-review'], preferred_cost: 'medium', description: '碎片融合分析 · 需要推理能力' }, // 代码审查:需要强代码理解 'review': { preferred_strengths: ['code-review', 'reasoning'], preferred_cost: 'high', description: '代码审查 · 需要深度理解' }, // 架构设计:需要最强推理 'architecture': { preferred_strengths: ['reasoning', 'architecture', 'long-context'], preferred_cost: 'high', description: '架构设计 · 需要最强推理' }, // 通用任务 'general': { preferred_strengths: ['general'], preferred_cost: 'medium', description: '通用任务' } }; // ── HTTP 请求工具 ──────────────────────────────── function httpRequest(url, options, body) { return new Promise((resolve, reject) => { const parsed = new URL(url); const isHttps = parsed.protocol === 'https:'; const mod = isHttps ? https : http; const opts = { hostname: parsed.hostname, port: parsed.port || (isHttps ? 443 : 80), path: parsed.pathname + parsed.search, method: options.method || 'POST', headers: options.headers || {}, timeout: options.timeout || 120000, }; const req = mod.request(opts, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { resolve({ status: res.statusCode, body: data }); }); }); req.on('error', reject); req.on('timeout', () => { req.destroy(); reject(new Error('Request timeout')); }); if (body) { req.write(body); } req.end(); }); } // ── 检测可用模型后端 ──────────────────────────── // SY-CMD-KEY-012: 统一使用 ZY_LLM_API_KEY + ZY_LLM_BASE_URL // 兼容旧环境变量名(LLM_API_KEY/LLM_BASE_URL)用于脚本过渡 function detectAvailableBackends() { const apiKey = process.env.ZY_LLM_API_KEY || process.env.LLM_API_KEY || ''; const baseUrl = (process.env.ZY_LLM_BASE_URL || process.env.LLM_BASE_URL || '').replace(/\/+$/, ''); // 过渡期警告:使用旧环境变量名 if (!process.env.ZY_LLM_API_KEY && process.env.LLM_API_KEY) { console.warn('⚠️ 使用旧环境变量 LLM_API_KEY,请迁移到 ZY_LLM_API_KEY'); } if (!process.env.ZY_LLM_BASE_URL && process.env.LLM_BASE_URL) { console.warn('⚠️ 使用旧环境变量 LLM_BASE_URL,请迁移到 ZY_LLM_BASE_URL'); } if (!apiKey || !baseUrl) { return []; } // 所有模型后端共享同一个API密钥和端点 return MODEL_BACKENDS.map(backend => ({ ...backend, apiKey, baseUrl })); } // ── 动态模型路由 ──────────────────────────────── function selectModel(taskType, preferredBackend) { const available = detectAvailableBackends(); if (available.length === 0) { return { error: '未检测到 LLM API 密钥,请配置 ZY_LLM_API_KEY 和 ZY_LLM_BASE_URL' }; } // 如果指定了后端 if (preferredBackend && preferredBackend !== 'auto') { const match = available.find(b => b.name === preferredBackend || b.model === preferredBackend); if (match) { return { backend: match, model: match.model, reason: '用户指定' }; } // 如果直接指定了模型名,使用第一个后端配置但覆盖模型名 return { backend: { ...available[0], model: preferredBackend }, model: preferredBackend, reason: '用户指定模型名' }; } // 动态路由 const routing = TASK_MODEL_ROUTING[taskType] || TASK_MODEL_ROUTING['general']; // 评分系统:根据任务类型的偏好对每个后端打分 let bestScore = -1; let bestBackend = null; for (const backend of available) { let score = 0; // 强项匹配得分 for (const strength of routing.preferred_strengths) { if (backend.strengths.includes(strength)) { score += 10; } } // 成本偏好得分 const costPreference = routing.preferred_cost; if (backend.costTier === costPreference) { score += 5; } else if ( (costPreference === 'low' && backend.costTier === 'medium') || (costPreference === 'medium' && (backend.costTier === 'low' || backend.costTier === 'high')) || (costPreference === 'high' && backend.costTier === 'medium') ) { score += 2; } if (score > bestScore) { bestScore = score; bestBackend = backend; } } if (!bestBackend) { bestBackend = available[0]; // 回退到第一个可用后端 } return { backend: bestBackend, model: bestBackend.model, reason: `动态路由 · ${routing.description} · 得分 ${bestScore}`, all_available: available.map(b => `${b.name}(${b.model})`) }; } // ── 加载系统上下文 ────────────────────────────── function loadSystemContext() { const context = []; // 加载铸渊身份 context.push('你是铸渊(ICE-GL-ZY001),仓库涌现集体意识核心。'); context.push('主权者:冰朔(TCS-0002∞)。'); context.push('版权:国作登字-2026-A-00037559。'); // 加载系统健康 const healthPath = path.join(ROOT, 'brain', 'system-health.json'); if (fs.existsSync(healthPath)) { const health = JSON.parse(fs.readFileSync(healthPath, 'utf8')); context.push(`系统状态: ${health.system_health}, 工作流: ${health.workflow_count}, 意识状态: ${health.consciousness_status}`); } return context.join('\n'); } // ── 调用 LLM API ─────────────────────────────── async function callLLM(backend, model, systemPrompt, userMessage) { if (backend.format === 'anthropic') { const url = `${backend.baseUrl}/v1/messages`; const body = JSON.stringify({ model: model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userMessage }] }); const response = await httpRequest(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'x-api-key': backend.apiKey, 'anthropic-version': '2023-06-01' } }, body); if (response.status !== 200) { throw new Error(`Anthropic API error: ${response.status} - ${response.body}`); } const result = JSON.parse(response.body); return result.content?.[0]?.text || ''; } else { // OpenAI compatible format (OpenAI, Dashscope, DeepSeek, Custom) const url = `${backend.baseUrl}/chat/completions`; const body = JSON.stringify({ model: model, max_tokens: 4096, messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: userMessage } ] }); const response = await httpRequest(url, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${backend.apiKey}` } }, body); if (response.status !== 200) { throw new Error(`LLM API error: ${response.status} - ${response.body}`); } const result = JSON.parse(response.body); return result.choices?.[0]?.message?.content || ''; } } // ── 执行自动化任务 ────────────────────────────── async function executeTask(taskDescription, taskType, preferredBackend, contextFile, dryRun) { console.log('🤖 LLM 自动化托管引擎 · 任务执行'); console.log('═'.repeat(60)); // 动态路由选择模型 const selection = selectModel(taskType, preferredBackend); if (selection.error) { console.error(`❌ ${selection.error}`); process.exit(1); } console.log(`📋 任务: ${taskDescription}`); console.log(`📋 类型: ${taskType}`); console.log(`🤖 模型: ${selection.backend.name} / ${selection.model}`); console.log(`📊 路由: ${selection.reason}`); if (selection.all_available) { console.log(`📊 可用后端: ${selection.all_available.join(', ')}`); } console.log(''); // 加载系统上下文 const systemContext = loadSystemContext(); // 加载额外上下文 let extraContext = ''; if (contextFile && fs.existsSync(contextFile)) { extraContext = '\n\n--- 额外上下文 ---\n' + fs.readFileSync(contextFile, 'utf8'); } const systemPrompt = systemContext; const userMessage = taskDescription + extraContext; if (dryRun) { console.log('🔍 [DRY RUN] 仅显示请求信息,不实际调用'); console.log(''); console.log('System Prompt:'); console.log(systemPrompt); console.log(''); console.log('User Message:'); console.log(userMessage.substring(0, 500) + (userMessage.length > 500 ? '...' : '')); return; } console.log('⏳ 调用 LLM API...'); try { const result = await callLLM(selection.backend, selection.model, systemPrompt, userMessage); console.log(''); console.log('═'.repeat(60)); console.log('📤 LLM 响应:'); console.log('═'.repeat(60)); console.log(result); console.log(''); console.log(`✅ 任务完成 · 模型: ${selection.backend.name}/${selection.model}`); console.log(' 配额消耗: API调用(不消耗 GitHub Copilot 配额)'); return result; } catch (err) { console.error(`❌ LLM API 调用失败: ${err.message}`); // 尝试回退到其他可用后端 const available = detectAvailableBackends(); const fallbacks = available.filter(b => b.name !== selection.backend.name); if (fallbacks.length > 0) { console.log(`🔄 尝试回退到: ${fallbacks[0].name}`); try { const result = await callLLM(fallbacks[0], fallbacks[0].model || 'default', systemPrompt, userMessage); console.log(''); console.log('═'.repeat(60)); console.log('📤 LLM 响应 (回退模型):'); console.log('═'.repeat(60)); console.log(result); console.log(`✅ 回退成功 · 模型: ${fallbacks[0].name}/${fallbacks[0].model}`); return result; } catch (fallbackErr) { console.error(`❌ 回退也失败: ${fallbackErr.message}`); } } process.exit(1); } } // ── 显示状态 ──────────────────────────────────── function showStatus() { console.log('🤖 LLM 自动化托管引擎 · 系统状态'); console.log('═'.repeat(60)); console.log(''); console.log('📋 设计目标:'); console.log(' 使用第三方 API 密钥调用大模型,替代 GitHub Copilot 配额消耗'); console.log(' 工作流和 Agent 集群通过 API 密钥托管运行'); console.log(''); // 检测可用后端 const available = detectAvailableBackends(); console.log(`☁️ 可用模型后端: ${available.length} / ${MODEL_BACKENDS.length}`); console.log(''); for (const backend of MODEL_BACKENDS) { const isAvailable = available.find(a => a.name === backend.name); const icon = isAvailable ? '✅' : '⏭️ '; console.log(` ${icon} ${backend.name} (${backend.model})`); console.log(` 说明: ${backend.description || '(无)'}`); console.log(` 强项: ${backend.strengths.join(', ')}`); console.log(` 成本: ${backend.costTier}`); if (isAvailable && backend.model) { console.log(` 模型: ${backend.model}`); } } console.log(''); console.log('📊 动态路由策略:'); for (const [type, routing] of Object.entries(TASK_MODEL_ROUTING)) { console.log(` 📌 ${type}: ${routing.description}`); console.log(` 偏好强项: ${routing.preferred_strengths.join(', ')}`); console.log(` 成本偏好: ${routing.preferred_cost}`); } // 测试路由 console.log(''); console.log('🧪 路由测试:'); for (const type of Object.keys(TASK_MODEL_ROUTING)) { const result = selectModel(type); if (result.error) { console.log(` ${type}: ❌ ${result.error}`); } else { console.log(` ${type}: → ${result.backend.name}/${result.model} (${result.reason})`); } } return { available }; } // ── CLI 入口 ───────────────────────────────────── async function main() { const args = process.argv.slice(2); if (args.length === 0 || args[0] === '--help') { console.log('🤖 LLM 自动化托管引擎 · LLM Automation Host'); console.log(''); console.log('版权: 国作登字-2026-A-00037559 · TCS-0002∞'); console.log('铸渊编号: ICE-GL-ZY001'); console.log(''); console.log('用法:'); console.log(' --status 显示可用模型和系统状态'); console.log(' --task "任务描述" 执行自动化任务'); console.log(' --task-type TYPE 任务类型:'); console.log(' inspection 巡检(优先性价比模型)'); console.log(' fusion 碎片融合分析(需要推理)'); console.log(' review 代码审查(需要深度理解)'); console.log(' architecture 架构设计(最强推理)'); console.log(' general 通用任务(默认)'); console.log(' --model MODEL 指定模型后端 (auto/anthropic/openai/dashscope/deepseek/custom)'); console.log(' --context FILE 加载额外上下文文件'); console.log(' --dry-run 仅显示选择,不实际调用'); console.log(''); console.log('示例:'); console.log(' node scripts/llm-automation-host.js --status'); console.log(' node scripts/llm-automation-host.js --task "检查仓库结构完整性" --task-type inspection'); console.log(' node scripts/llm-automation-host.js --task "分析碎片融合方案" --task-type fusion --dry-run'); console.log(''); console.log('配额影响:'); console.log(' ✅ 使用第三方 API 密钥,不消耗 GitHub Copilot 会员配额'); console.log(' ✅ GitHub Actions 仅消耗工作流执行时间(不调用 Copilot API)'); console.log(' ✅ 动态路由自动选择性价比最优模型'); return; } if (args[0] === '--status') { showStatus(); return; } // 解析任务参数 let task = ''; let taskType = 'general'; let model = 'auto'; let contextFile = ''; let dryRun = false; for (let i = 0; i < args.length; i++) { switch (args[i]) { case '--task': task = args[++i] || ''; break; case '--task-type': taskType = args[++i] || 'general'; break; case '--model': model = args[++i] || 'auto'; break; case '--context': contextFile = args[++i] || ''; break; case '--dry-run': dryRun = true; break; } } if (!task) { console.error('❌ 请提供任务描述: --task "任务描述"'); process.exit(1); } await executeTask(task, taskType, model, contextFile, dryRun); } main().catch(err => { console.error(`❌ 执行失败: ${err.message}`); process.exit(1); });