/** * API 客户端 * 封装与后端的 HTTP 通信 */ import * as https from 'https'; import * as http from 'http'; import { URL } from 'url'; import { getApiUrl, getConfig } from '../config/settings'; import type { ToolCallResult, AnswerRequest, ToolResultResponse, AnswerResponse, ToolConfirmResponse } from '../types/api'; /** * HTTP 请求选项 */ interface RequestOptions { method: 'GET' | 'POST' | 'PUT' | 'DELETE'; headers?: Record; body?: unknown; timeout?: number; } /** * 发送 HTTP 请求 */ async function request(path: string, options: RequestOptions): Promise { const url = new URL(getApiUrl(path)); const { timeout } = getConfig(); const isHttps = url.protocol === 'https:'; const httpModule = isHttps ? https : http; const requestOptions: http.RequestOptions = { hostname: url.hostname, port: url.port || (isHttps ? 443 : 80), path: url.pathname + url.search, method: options.method, headers: { 'Content-Type': 'application/json', ...options.headers }, timeout: options.timeout || timeout }; return new Promise((resolve, reject) => { const req = httpModule.request(requestOptions, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const json = JSON.parse(data); if (res.statusCode && res.statusCode >= 200 && res.statusCode < 300) { resolve(json as T); } else { reject(new Error(json.error || json.message || `HTTP ${res.statusCode}`)); } } catch (e) { reject(new Error(`解析响应失败: ${data}`)); } }); }); req.on('error', (error) => { reject(error); }); req.on('timeout', () => { req.destroy(); reject(new Error('请求超时')); }); if (options.body) { req.write(JSON.stringify(options.body)); } req.end(); }); } /** * 提交工具执行结果 * POST /api/tool/result */ export async function submitToolResult(result: ToolCallResult): Promise { console.log(`[API] 提交工具结果: callId=${result.id}`); return request('/api/tool/result', { method: 'POST', body: result }); } /** * 提交用户回答 * POST /api/task/answer */ export async function submitAnswer(answer: AnswerRequest): Promise { console.log(`[API] 提交用户回答: askId=${answer.askId}`); return request('/api/task/answer', { method: 'POST', body: answer }); } /** * 提交工具确认响应(Ask 模式) * POST /api/tool/confirm */ export async function submitToolConfirm(response: ToolConfirmResponse): Promise { console.log(`[API] 提交工具确认: confirmId=${response.confirmId}, approved=${response.approved}`); return request('/api/tool/confirm', { method: 'POST', body: response }); } /** * 健康检查 * GET /api/dialog/health */ export async function healthCheck(): Promise<{ status: string }> { return request<{ status: string }>('/api/dialog/health', { method: 'GET', timeout: 5000 }); } /** * 创建成功的工具结果 */ export function createSuccessResult(id: number, text: string): ToolCallResult { return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text }], isError: false } }; } /** * 创建业务错误的工具结果(如编译失败) */ export function createBusinessErrorResult(id: number, errorMessage: string): ToolCallResult { return { jsonrpc: '2.0', id, result: { content: [{ type: 'text', text: errorMessage }], isError: true } }; } /** * 创建系统错误的工具结果 */ export function createSystemErrorResult(id: number, code: number, message: string): ToolCallResult { return { jsonrpc: '2.0', id, error: { code, message } }; }