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:
2026-04-14 14:34:23 +08:00
parent fee9007da6
commit cdfc222c9f
85 changed files with 5443 additions and 1392 deletions

View File

@ -40,10 +40,13 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { pickAppText } from '@/lib/i18n/core';
import { useAppI18n } from '@/lib/i18n/provider';
import { useChatStore } from '@/lib/store';
import type { CronJob } from '@/types';
export default function CronPage() {
const { locale } = useAppI18n();
const sessionId = useChatStore((s) => s.sessionId);
const [jobs, setJobs] = useState<CronJob[]>([]);
const [loading, setLoading] = useState(true);
@ -58,7 +61,7 @@ export default function CronPage() {
const data = await listCronJobs(true);
setJobs(data);
} catch (err: any) {
setError(err.message || '加载任务失败');
setError(err.message || pickAppText(locale, '加载任务失败', 'Failed to load jobs'));
} finally {
setLoading(false);
}
@ -138,16 +141,16 @@ export default function CronPage() {
<div className="flex items-center justify-between">
<h1 className="text-2xl font-bold flex items-center gap-2">
<Clock className="w-6 h-6" />
{pickAppText(locale, '定时任务', 'Scheduled tasks')}
</h1>
<div className="flex items-center gap-2">
<Button onClick={loadJobs} variant="outline" size="sm">
<RefreshCw className="w-4 h-4 mr-2" />
{pickAppText(locale, '刷新', 'Refresh')}
</Button>
<Button onClick={() => setShowAdd(true)} size="sm">
<Plus className="w-4 h-4 mr-2" />
{pickAppText(locale, '新建任务', 'New job')}
</Button>
</div>
</div>
@ -178,21 +181,21 @@ export default function CronPage() {
{jobs.length === 0 ? (
<div className="py-12 text-center text-muted-foreground">
<Clock className="w-10 h-10 mx-auto mb-3 opacity-30" />
<p className="font-medium"></p>
<p className="text-sm mt-1"></p>
<p className="font-medium">{pickAppText(locale, '暂无定时任务', 'No scheduled tasks yet')}</p>
<p className="text-sm mt-1">{pickAppText(locale, '新建一个任务,让智能体按计划自动执行。', 'Create a job to let the agent run on a schedule.')}</p>
</div>
) : (
<Table>
<TableHeader>
<TableRow>
<TableHead className="w-16"></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead></TableHead>
<TableHead className="w-24"></TableHead>
<TableHead className="w-16">{pickAppText(locale, '启用', 'Enabled')}</TableHead>
<TableHead>{pickAppText(locale, '名称', 'Name')}</TableHead>
<TableHead>{pickAppText(locale, '计划', 'Schedule')}</TableHead>
<TableHead>{pickAppText(locale, '消息', 'Message')}</TableHead>
<TableHead>{pickAppText(locale, '上次运行', 'Last run')}</TableHead>
<TableHead>{pickAppText(locale, '下次运行', 'Next run')}</TableHead>
<TableHead>{pickAppText(locale, '状态', 'Status')}</TableHead>
<TableHead className="w-24">{pickAppText(locale, '操作', 'Actions')}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
@ -238,7 +241,7 @@ export default function CronPage() {
)}
{job.last_status === 'error' && (
<Badge variant="destructive" className="text-xs">
{pickAppText(locale, '错误', 'Error')}
</Badge>
)}
{!job.last_status && (
@ -254,7 +257,7 @@ export default function CronPage() {
size="icon"
className="h-7 w-7"
onClick={() => handleRun(job.id)}
title="立即执行"
title={pickAppText(locale, '立即执行', 'Run now')}
>
<Play className="w-3.5 h-3.5" />
</Button>
@ -263,7 +266,7 @@ export default function CronPage() {
size="icon"
className="h-7 w-7 text-destructive hover:text-destructive"
onClick={() => handleDelete(job.id)}
title="删除"
title={pickAppText(locale, '删除', 'Delete')}
>
<Trash2 className="w-3.5 h-3.5" />
</Button>
@ -294,6 +297,7 @@ function AddJobForm({
}) => void;
onCancel: () => void;
}) {
const { locale } = useAppI18n();
const [name, setName] = useState('');
const [message, setMessage] = useState('');
const [scheduleType, setScheduleType] = useState<'every' | 'cron'>('every');
@ -317,7 +321,7 @@ function AddJobForm({
<Card>
<CardHeader className="pb-4">
<div className="flex items-center justify-between">
<CardTitle className="text-base"></CardTitle>
<CardTitle className="text-base">{pickAppText(locale, '新建定时任务', 'New scheduled task')}</CardTitle>
<Button variant="ghost" size="icon" className="h-7 w-7" onClick={onCancel}>
<X className="w-4 h-4" />
</Button>
@ -327,16 +331,16 @@ function AddJobForm({
<form onSubmit={handleSubmit} className="space-y-4">
<div className="grid grid-cols-2 gap-4">
<div className="space-y-2">
<Label htmlFor="name"></Label>
<Label htmlFor="name">{pickAppText(locale, '任务名称', 'Job name')}</Label>
<Input
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="例如:日报汇总"
placeholder={pickAppText(locale, '例如:日报汇总', 'Example: daily summary')}
/>
</div>
<div className="space-y-2">
<Label htmlFor="schedule-type"></Label>
<Label htmlFor="schedule-type">{pickAppText(locale, '调度类型', 'Schedule type')}</Label>
<Select
value={scheduleType}
onValueChange={(v) => setScheduleType(v as 'every' | 'cron')}
@ -345,8 +349,8 @@ function AddJobForm({
<SelectValue />
</SelectTrigger>
<SelectContent>
<SelectItem value="every"> N </SelectItem>
<SelectItem value="cron">Cron </SelectItem>
<SelectItem value="every">{pickAppText(locale, '固定间隔(每 N 秒)', 'Fixed interval (every N seconds)')}</SelectItem>
<SelectItem value="cron">{pickAppText(locale, 'Cron 表达式', 'Cron expression')}</SelectItem>
</SelectContent>
</Select>
</div>
@ -354,7 +358,7 @@ function AddJobForm({
{scheduleType === 'every' ? (
<div className="space-y-2">
<Label htmlFor="every"></Label>
<Label htmlFor="every">{pickAppText(locale, '间隔(秒)', 'Interval (seconds)')}</Label>
<Input
id="every"
type="number"
@ -365,15 +369,15 @@ function AddJobForm({
/>
<p className="text-xs text-muted-foreground">
{parseInt(everySeconds, 10) >= 3600
? `${Math.floor(parseInt(everySeconds, 10) / 3600)} 小时 ${Math.floor((parseInt(everySeconds, 10) % 3600) / 60)}`
? pickAppText(locale, `${Math.floor(parseInt(everySeconds, 10) / 3600)} 小时 ${Math.floor((parseInt(everySeconds, 10) % 3600) / 60)}`, `About ${Math.floor(parseInt(everySeconds, 10) / 3600)}h ${Math.floor((parseInt(everySeconds, 10) % 3600) / 60)}m`)
: parseInt(everySeconds, 10) >= 60
? `${Math.floor(parseInt(everySeconds, 10) / 60)}${parseInt(everySeconds, 10) % 60}`
? pickAppText(locale, `${Math.floor(parseInt(everySeconds, 10) / 60)}${parseInt(everySeconds, 10) % 60}`, `About ${Math.floor(parseInt(everySeconds, 10) / 60)}m ${parseInt(everySeconds, 10) % 60}s`)
: ''}
</p>
</div>
) : (
<div className="space-y-2">
<Label htmlFor="cron">Cron </Label>
<Label htmlFor="cron">{pickAppText(locale, 'Cron 表达式', 'Cron expression')}</Label>
<Input
id="cron"
value={cronExpr}
@ -381,31 +385,31 @@ function AddJobForm({
placeholder="0 9 * * *"
/>
<p className="text-xs text-muted-foreground">
{pickAppText(locale, '格式:分钟 小时 日 月 周', 'Format: minute hour day month weekday')}
</p>
</div>
)}
<div className="space-y-2">
<Label htmlFor="message"></Label>
<Label htmlFor="message">{pickAppText(locale, '发送给智能体的消息', 'Message for the agent')}</Label>
<Input
id="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="例如:检查我的邮件并生成摘要"
placeholder={pickAppText(locale, '例如:检查我的邮件并生成摘要', 'Example: check my email and generate a summary')}
/>
<p className="text-xs text-muted-foreground">
Web <code className="bg-muted px-1 py-0.5 rounded">{targetSessionKey}</code>
{pickAppText(locale, '任务结果会自动回写到当前 Web 会话:', 'Results are written back to the current web session:')} <code className="bg-muted px-1 py-0.5 rounded">{targetSessionKey}</code>
</p>
</div>
<div className="flex justify-end gap-2">
<Button type="button" variant="outline" onClick={onCancel}>
{pickAppText(locale, '取消', 'Cancel')}
</Button>
<Button type="submit" disabled={!name.trim() || !message.trim()}>
<Plus className="w-4 h-4 mr-2" />
{pickAppText(locale, '创建任务', 'Create job')}
</Button>
</div>
</form>