feat: 添加swarms团队编排功能并优化agent委派系统
- 引入AgentTeamOrchestrator支持多agent协同任务执行 - 增加第三方swarms库依赖并配置git协议替换以改善包管理 - 扩展DelegationManager支持团队任务调度和进度跟踪 - 实现中文bigram分词算法提升中文任务检索准确性 - 调整A2AClient和DelegationManager超时时间从30秒增至600秒 - 优化AgentRunResult状态判断逻辑增加有意义摘要检测 - 修改Dockerfile配置npm仓库镜像地址和git协议映射 - 更新CLI命令行接口支持网关端口配置传递 - 调整提供者超时配置机制增强请求稳定性 - 移除过时的support_group字段简化agent描述符结构 - 增强错误处理和进度事件报告机制改进用户体验
This commit is contained in:
@ -31,6 +31,7 @@ import type {
|
||||
UiMcpServerDescriptor,
|
||||
WsEvent,
|
||||
} from '@/types';
|
||||
import { getCurrentAppLocale, pickAppText } from '@/lib/i18n/core';
|
||||
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL?.trim();
|
||||
const WS_URL = process.env.NEXT_PUBLIC_WS_URL?.trim();
|
||||
@ -90,9 +91,10 @@ function withTimeout(
|
||||
signal?: AbortSignal,
|
||||
timeoutMs: number = REQUEST_TIMEOUT_MS
|
||||
): { signal: AbortSignal; cleanup: () => void } {
|
||||
const locale = getCurrentAppLocale();
|
||||
const controller = new AbortController();
|
||||
const timeoutId = globalThis.setTimeout(() => {
|
||||
controller.abort(new DOMException('请求超时', 'AbortError'));
|
||||
controller.abort(new DOMException(pickAppText(locale, '请求超时', 'Request timed out'), 'AbortError'));
|
||||
}, timeoutMs);
|
||||
|
||||
const forwardAbort = () => controller.abort(signal?.reason);
|
||||
@ -154,6 +156,7 @@ function authHeaders(includeJsonContentType: boolean = true): Record<string, str
|
||||
}
|
||||
|
||||
async function fetchJSON<T>(path: string, options?: FetchJsonOptions): Promise<T> {
|
||||
const locale = getCurrentAppLocale();
|
||||
const mergedHeaders = {
|
||||
...authHeaders(),
|
||||
...(options?.headers as Record<string, string> | undefined),
|
||||
@ -170,7 +173,7 @@ async function fetchJSON<T>(path: string, options?: FetchJsonOptions): Promise<T
|
||||
} catch (error) {
|
||||
cleanup();
|
||||
if (error instanceof DOMException && error.name === 'AbortError') {
|
||||
throw new Error('请求超时');
|
||||
throw new Error(pickAppText(locale, '请求超时', 'Request timed out'));
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
@ -191,7 +194,7 @@ async function fetchJSON<T>(path: string, options?: FetchJsonOptions): Promise<T
|
||||
} catch {
|
||||
// keep raw text
|
||||
}
|
||||
throw new Error(`接口错误 ${res.status}: ${detail}`);
|
||||
throw new Error(`${pickAppText(locale, '接口错误', 'API error')} ${res.status}: ${detail}`);
|
||||
}
|
||||
return res.json();
|
||||
}
|
||||
@ -262,6 +265,7 @@ export function streamMessage(
|
||||
onError: (error: string) => void
|
||||
): () => void {
|
||||
const controller = new AbortController();
|
||||
const locale = getCurrentAppLocale();
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
@ -273,7 +277,7 @@ export function streamMessage(
|
||||
});
|
||||
|
||||
if (!res.ok || !res.body) {
|
||||
onError(`HTTP 错误 ${res.status}`);
|
||||
onError(`${pickAppText(locale, 'HTTP 错误', 'HTTP error')} ${res.status}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -308,7 +312,7 @@ export function streamMessage(
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.name !== 'AbortError') {
|
||||
onError(err.message || '流式请求失败');
|
||||
onError(err.message || pickAppText(locale, '流式请求失败', 'Streaming request failed'));
|
||||
}
|
||||
}
|
||||
})();
|
||||
@ -1059,8 +1063,9 @@ export async function uploadFile(
|
||||
sessionId: string = 'web:default',
|
||||
onProgress?: (percent: number) => void
|
||||
): Promise<FileAttachment> {
|
||||
const locale = getCurrentAppLocale();
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
throw new Error('文件过大(最大 50MB)');
|
||||
throw new Error(pickAppText(locale, '文件过大(最大 50MB)', 'File is too large (max 50MB)'));
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
@ -1086,11 +1091,11 @@ export async function uploadFile(
|
||||
const data = JSON.parse(xhr.responseText);
|
||||
resolve(data);
|
||||
} else {
|
||||
reject(new Error(`上传失败:${xhr.status}`));
|
||||
reject(new Error(`${pickAppText(locale, '上传失败', 'Upload failed')}: ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = () => reject(new Error('上传失败'));
|
||||
xhr.onerror = () => reject(new Error(pickAppText(locale, '上传失败', 'Upload failed')));
|
||||
xhr.send(formData);
|
||||
});
|
||||
|
||||
@ -1142,8 +1147,9 @@ export async function uploadToWorkspace(
|
||||
dirPath: string = '',
|
||||
onProgress?: (percent: number) => void
|
||||
): Promise<WorkspaceItem> {
|
||||
const locale = getCurrentAppLocale();
|
||||
if (file.size > MAX_FILE_SIZE) {
|
||||
throw new Error('文件过大(最大 50MB)');
|
||||
throw new Error(pickAppText(locale, '文件过大(最大 50MB)', 'File is too large (max 50MB)'));
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
@ -1168,11 +1174,11 @@ export async function uploadToWorkspace(
|
||||
if (xhr.status >= 200 && xhr.status < 300) {
|
||||
resolve(JSON.parse(xhr.responseText));
|
||||
} else {
|
||||
reject(new Error(`上传失败:${xhr.status}`));
|
||||
reject(new Error(`${pickAppText(locale, '上传失败', 'Upload failed')}: ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
|
||||
xhr.onerror = () => reject(new Error('上传失败'));
|
||||
xhr.onerror = () => reject(new Error(pickAppText(locale, '上传失败', 'Upload failed')));
|
||||
xhr.send(formData);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user