This commit is contained in:
1 parent
96b3f0af37
commit
71fc502a92
2 files changed
+104
No files matched your search
@@ -891,6 +891,10 @@ export const adminAPI = {
|
||||
getAgentToolPolicy: (id: string) => get<any>(`/admin/agents/${id}/tool-policy`),
|
||||
setAgentToolPolicy: (id: string, toolPolicy: any) => put<any>(`/admin/agents/${id}/tool-policy`, { tool_policy: toolPolicy }),
|
||||
|
||||
// Phase 3.3: 多 Agent 编排图 (orchestration)
|
||||
getAgentOrchestration: (id: string) => get<any>(`/admin/agents/${id}/orchestration`),
|
||||
setAgentOrchestration: (id: string, orchestration: any) => put<any>(`/admin/agents/${id}/orchestration`, { orchestration }),
|
||||
|
||||
getAdminAvailableSkills: (params?: any) => {
|
||||
|
||||
const query = params ? '?' + Object.entries(params).filter(([_, v]) => v !== undefined && v !== '').map(([k, v]) => `${k}=${v}`).join('&') : '';
|
||||
|
||||
@@ -109,6 +109,9 @@ const Agents: React.FC = () => {
|
||||
const [availableMcps, setAvailableMcps] = useState<any[]>([]);
|
||||
// Tool policy (sandbox) — null means disabled / no policy
|
||||
const [toolPolicy, setToolPolicy] = useState<any>(null);
|
||||
// Phase 3.3: orchestration graph editor (JSON text + error)
|
||||
const [orchestrationText, setOrchestrationText] = useState<string>('');
|
||||
const [orchestrationError, setOrchestrationError] = useState<string>('');
|
||||
|
||||
// Toast
|
||||
const [toast, setToast] = useState<{ msg: string; type: 'success' | 'error' } | null>(null);
|
||||
@@ -195,6 +198,8 @@ const Agents: React.FC = () => {
|
||||
reasoning_enabled: false,
|
||||
});
|
||||
setToolPolicy(null);
|
||||
setOrchestrationText('');
|
||||
setOrchestrationError('');
|
||||
setShowModal(true);
|
||||
};
|
||||
|
||||
@@ -203,6 +208,7 @@ const Agents: React.FC = () => {
|
||||
setEditingAgent(agent);
|
||||
await loadAvailable();
|
||||
await openEditLoadPolicy(agent.id);
|
||||
await openEditLoadOrchestration(agent.id);
|
||||
|
||||
const cfg = agent.config || {};
|
||||
setForm({
|
||||
@@ -231,6 +237,17 @@ const Agents: React.FC = () => {
|
||||
setToolPolicy(null);
|
||||
}
|
||||
};
|
||||
// Phase 3.3: 载入已有编排图
|
||||
const openEditLoadOrchestration = async (agentId: string) => {
|
||||
try {
|
||||
const oRes = await adminAPI.getAgentOrchestration(agentId) as any;
|
||||
const og = oRes?.data?.orchestration;
|
||||
setOrchestrationText(og ? JSON.stringify(og, null, 2) : '');
|
||||
setOrchestrationError('');
|
||||
} catch {
|
||||
setOrchestrationText('');
|
||||
}
|
||||
};
|
||||
const openDetail = async (agent: Agent) => {
|
||||
setDetailAgent(agent);
|
||||
setShowDetail(true);
|
||||
@@ -716,6 +733,89 @@ const Agents: React.FC = () => {
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{editingAgent && (
|
||||
<div style={{ gridColumn: '1 / -1' }}>
|
||||
<hr style={{ border: 'none', borderTop: '1px solid #E5E7EB', margin: '16px 0' }} />
|
||||
<div style={{ fontWeight: 600, marginBottom: 8 }}>🕸️ 多 Agent 编排图 (orchestration)</div>
|
||||
<div style={{ fontSize: 12, color: '#6B7280', marginBottom: 8 }}>
|
||||
用有向图描述多个智能体的协作:节点类型 llm / local / external / reduce,边 from→to 表示数据流。留空表示不启用编排(走原对话逻辑)。
|
||||
</div>
|
||||
<textarea
|
||||
className="admin-form-input"
|
||||
rows={14}
|
||||
style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', fontSize: 12, whiteSpace: 'pre', overflowWrap: 'normal', width: '100%' }}
|
||||
value={orchestrationText}
|
||||
spellCheck={false}
|
||||
onChange={e => { setOrchestrationText(e.target.value); setOrchestrationError(''); }}
|
||||
placeholder={'{\n "nodes": [{"id":"router","type":"llm"},{"id":"worker","type":"local","agent_id":"子智能体ID"},{"id":"summary","type":"reduce"}],\n "edges": [{"from":"router","to":"worker"},{"from":"worker","to":"summary"}]\n}'}
|
||||
/>
|
||||
{orchestrationError && (
|
||||
<div style={{ color: '#DC2626', fontSize: 12, marginTop: 6, whiteSpace: 'pre-wrap' }}>{orchestrationError}</div>
|
||||
)}
|
||||
<div style={{ display: 'flex', gap: 8, marginTop: 8, flexWrap: 'wrap' }}>
|
||||
<button
|
||||
className="admin-btn"
|
||||
onClick={() => {
|
||||
try {
|
||||
const parsed = orchestrationText.trim() ? JSON.parse(orchestrationText) : null;
|
||||
setOrchestrationText(parsed ? JSON.stringify(parsed, null, 2) : '');
|
||||
setOrchestrationError('');
|
||||
} catch (e: any) {
|
||||
setOrchestrationError('JSON 格式错误: ' + (e.message || e));
|
||||
}
|
||||
}}
|
||||
>格式化</button>
|
||||
<button
|
||||
className="admin-btn"
|
||||
onClick={() => {
|
||||
const tpl = {
|
||||
nodes: [
|
||||
{ id: 'router', type: 'llm', system_prompt: '判断用户意图并路由到合适的处理智能体。' },
|
||||
{ id: 'worker', type: 'local', agent_id: '在此填入子智能体ID' },
|
||||
{ id: 'summary', type: 'reduce', system_prompt: '汇总各子任务结果,输出面向用户的最终答复。' },
|
||||
],
|
||||
edges: [
|
||||
{ from: 'router', to: 'worker' },
|
||||
{ from: 'worker', to: 'summary' },
|
||||
],
|
||||
};
|
||||
setOrchestrationText(JSON.stringify(tpl, null, 2));
|
||||
setOrchestrationError('');
|
||||
}}
|
||||
>填入示例</button>
|
||||
<button
|
||||
className="admin-btn primary"
|
||||
onClick={async () => {
|
||||
try {
|
||||
const text = orchestrationText.trim();
|
||||
const parsed = text ? JSON.parse(text) : null;
|
||||
await adminAPI.setAgentOrchestration(editingAgent!.id, parsed);
|
||||
setOrchestrationError('');
|
||||
showToast('编排图已保存');
|
||||
} catch (e: any) {
|
||||
const msg = e?.response?.data?.detail || e?.message || String(e);
|
||||
setOrchestrationError('保存失败: ' + msg);
|
||||
}
|
||||
}}
|
||||
>保存编排图</button>
|
||||
{orchestrationText.trim() && (
|
||||
<button
|
||||
className="admin-btn"
|
||||
onClick={async () => {
|
||||
try {
|
||||
await adminAPI.setAgentOrchestration(editingAgent!.id, null);
|
||||
setOrchestrationText('');
|
||||
setOrchestrationError('');
|
||||
showToast('编排图已清除');
|
||||
} catch (e: any) {
|
||||
setOrchestrationError('清除失败: ' + (e?.message || e));
|
||||
}
|
||||
}}
|
||||
>清除编排</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="admin-btn" onClick={() => setShowModal(false)}>取消</button>
|
||||
|
||||
Reference in new issue
Block a user