feat: LLM 调用日志 + ModelSelector 优化 + devtools.bat 编码修复
- 新增 call_log.go: 全局环形缓冲区记录每次 LLM 调用(模型/Token/耗时/错误) - OpenAIProvider.doChat/ChatStreamWithTools 自动记录调用日志 - ai-core 暴露 GET /api/v1/llm-calls 端点, DevTools 代理 + UI 面板 - ModelSelector.envProvider 改为单例缓存, 避免重复创建 HTTP Client - 新增 PurposeToolCalling 适配器, 后台思考工具调用走专用路由 - envFallback 超时 120s→180s, 显式设置 MaxRetries - devtools.bat 全英文, 解决 Windows CMD GBK 编码乱码问题 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,7 @@ import { processManager } from './process-manager.js';
|
||||
import { performanceMonitor } from './performance.js';
|
||||
import { SERVICES, DEVTOOLS_PORT, LOGS_DIR, logFile, GATEWAY_URL, TOOL_ENGINE_URL, ADMIN_USERNAME, ADMIN_PASSWORD } from './config.js';
|
||||
|
||||
const AI_CORE_URL = process.env.AI_CORE_URL || 'http://localhost:8081';
|
||||
const MEMORY_SERVICE_URL = process.env.MEMORY_SERVICE_URL || 'http://localhost:8091';
|
||||
const VOICE_SERVICE_URL = process.env.VOICE_SERVICE_URL || 'http://localhost:8093';
|
||||
const PLATFORM_BRIDGE_URL = process.env.PLATFORM_BRIDGE_URL || 'http://localhost:8095';
|
||||
@@ -168,6 +169,31 @@ async function proxyToGateway(path, opts = {}) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 代理请求到 AI-Core
|
||||
*/
|
||||
async function proxyToAICore(path, opts = {}) {
|
||||
const url = `${AI_CORE_URL}${path}`;
|
||||
try {
|
||||
const resp = await fetch(url, {
|
||||
...opts,
|
||||
headers: { 'Content-Type': 'application/json', ...opts.headers },
|
||||
signal: AbortSignal.timeout(10000),
|
||||
});
|
||||
const body = await resp.json().catch(() => null);
|
||||
return { status: resp.status, body };
|
||||
} catch (err) {
|
||||
return {
|
||||
status: 502,
|
||||
body: {
|
||||
error: `AI-Core 不可达: ${err.message}`,
|
||||
errorType: 'ai_core_unreachable',
|
||||
hint: 'AI-Core 服务未启动,请先在「服务管理」面板中启动 AI-Core',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ========== REST API 路由 ==========
|
||||
|
||||
// ---- 健康检查 ----
|
||||
@@ -1003,6 +1029,13 @@ app.get('/api/voice/health', async (_req, res) => {
|
||||
res.status(result.status).json(result.body);
|
||||
});
|
||||
|
||||
// GET /api/llm-calls — LLM 调用日志 (代理到 AI-Core)
|
||||
app.get('/api/llm-calls', async (req, res) => {
|
||||
const limit = parseInt(req.query.limit) || 50;
|
||||
const result = await proxyToAICore(`/api/v1/llm-calls?limit=${Math.min(limit, 500)}`);
|
||||
res.status(result.status).json(result.body);
|
||||
});
|
||||
|
||||
/**
|
||||
* 代理请求到 Memory-Service
|
||||
* @param {string} path - Memory-Service API 路径
|
||||
|
||||
Reference in New Issue
Block a user