plugin-agent-orchestrator 1.0.1 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ /**
3
+ * Reusable Select component for AI Employees.
4
+ * P3 FIX: Uses shared AIEmployeesContext instead of making its own API call.
5
+ */
6
+ export declare const AIEmployeeSelect: React.FC<{
7
+ value?: string;
8
+ onChange?: (value: string) => void;
9
+ exclude?: string;
10
+ placeholder?: string;
11
+ }>;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ interface AIEmployeeInfo {
3
+ username: string;
4
+ nickname: string;
5
+ about?: string;
6
+ }
7
+ interface AIEmployeesContextType {
8
+ employees: AIEmployeeInfo[];
9
+ employeeMap: Map<string, string>;
10
+ loading: boolean;
11
+ }
12
+ /**
13
+ * P3 FIX: Shared context provider that fetches aiEmployees once
14
+ * and shares the data across RulesTab, TracingTab, and AIEmployeeSelect.
15
+ */
16
+ export declare const AIEmployeesProvider: React.FC<{
17
+ children: React.ReactNode;
18
+ }>;
19
+ /**
20
+ * Hook to access shared AI employees data.
21
+ */
22
+ export declare const useAIEmployees: () => AIEmployeesContextType;
23
+ export {};
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const OrchestratorSettings: React.FC;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const RulesTab: React.FC;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const TracingTab: React.FC;
@@ -0,0 +1 @@
1
+ export { default } from './plugin';
@@ -1 +1,10 @@
1
- !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("plugin-agent-orchestrator",["react","@nocobase/client","@ant-design/icons","antd"],t):"object"==typeof exports?exports["plugin-agent-orchestrator"]=t(require("react"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):e["plugin-agent-orchestrator"]=t(e.react,e["@nocobase/client"],e["@ant-design/icons"],e.antd)}(self,function(e,t,n,r){return function(){"use strict";var a={482:function(e){e.exports=n},772:function(e){e.exports=t},721:function(e){e.exports=r},156:function(t){t.exports=e}},o={};function l(e){var t=o[e];if(void 0!==t)return t.exports;var n=o[e]={exports:{}};return a[e](n,n.exports,l),n.exports}l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,{a:t}),t},l.d=function(e,t){for(var n in t)l.o(t,n)&&!l.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return!function(){l.r(i),l.d(i,{default:function(){return T}});var e=l(772),t=l(156),n=l.n(t),r=l(721),a=l(482),o=(0,t.createContext)({employees:[],employeeMap:new Map,loading:!1}),u=function(t){var r=t.children,a=(0,e.useRequest)({url:"aiEmployees:list",params:{pageSize:200}}),l=a.data,i=a.loading,u=n().useMemo(function(){var e=((null==l?void 0:l.data)||[]).map(function(e){var t;return{username:e.username,nickname:e.nickname||e.username,about:null==(t=e.about)?void 0:t.substring(0,80)}}),t=new Map,n=!0,r=!1,a=void 0;try{for(var o,u=e[Symbol.iterator]();!(n=(o=u.next()).done);n=!0){var c=o.value;t.set(c.username,c.nickname)}}catch(e){r=!0,a=e}finally{try{n||null==u.return||u.return()}finally{if(r)throw a}}return{employees:e,employeeMap:t,loading:i}},[l,i]);return n().createElement(o.Provider,{value:u},r)},c=function(){return(0,t.useContext)(o)},s=function(e){var t=e.value,a=e.onChange,o=e.exclude,l=e.placeholder,i=c(),u=i.employees,s=i.loading,d=n().useMemo(function(){return u.filter(function(e){return!o||e.username!==o}).map(function(e){return{label:e.nickname,value:e.username,description:e.about}})},[u,o]);return n().createElement(r.Select,{loading:s,options:d,value:t,onChange:a,placeholder:void 0===l?"Select AI Employee...":l,showSearch:!0,filterOption:function(e,t){var n,r;return(null!=(n=null==t?void 0:t.label)?n:"").toString().toLowerCase().includes(e.toLowerCase())||(null!=(r=null==t?void 0:t.value)?r:"").toString().toLowerCase().includes(e.toLowerCase())},optionRender:function(e){return n().createElement("div",null,n().createElement("div",{style:{fontWeight:500}},e.label),e.data.description&&n().createElement("div",{style:{fontSize:12,color:"#888"}},e.data.description))}})};function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}function m(e,t,n,r,a,o,l){try{var i=e[o](l),u=i.value}catch(e){n(e);return}i.done?t(u):Promise.resolve(u).then(r,a)}function f(e){return function(){var t=this,n=arguments;return new Promise(function(r,a){var o=e.apply(t,n);function l(e){m(o,r,a,l,i,"next",e)}function i(e){m(o,r,a,l,i,"throw",e)}l(void 0)})}}function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n,r,a=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var o=[],l=!0,i=!1;try{for(a=a.call(e);!(l=(n=a.next()).done)&&(o.push(n.value),!t||o.length!==t);l=!0);}catch(e){i=!0,r=e}finally{try{l||null==a.return||a.return()}finally{if(i)throw r}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return d(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return d(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function y(e,t){var n,r,a,o,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:i(0),throw:i(1),return:i(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(o){return function(i){var u=[o,i];if(n)throw TypeError("Generator is already executing.");for(;l;)try{if(n=1,r&&(a=2&u[0]?r.return:u[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,u[1])).done)return a;switch(r=0,a&&(u=[2&u[0],a.value]),u[0]){case 0:case 1:a=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,r=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!a||u[1]>a[0]&&u[1]<a[3])){l.label=u[1];break}if(6===u[0]&&l.label<a[1]){l.label=a[1],a=u;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(u);break}a[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],r=0}finally{n=a=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}var h=r.Typography.Text,g=function(){var o,l,i=(0,e.useAPIClient)(),u=p((0,t.useState)(!1),2),d=u[0],m=u[1],g=p((0,t.useState)(null),2),b=g[0],v=g[1],E=p(r.Form.useForm(),1)[0],w=(0,e.useRequest)({url:"orchestratorConfig:list",params:{sort:["-createdAt"]}}),S=w.data,x=w.loading,k=w.refresh,A=c().employeeMap,C=function(e){v(e),e?E.setFieldsValue(e):(E.resetFields(),E.setFieldsValue({enabled:!0,maxDepth:1,timeout:12e4})),m(!0)},O=function(){m(!1),v(null)},I=(o=f(function(e){var t,n,a,o,l,u;return y(this,function(c){switch(c.label){case 0:if(e.leaderUsername===e.subAgentUsername)return r.message.error("Leader and Sub-Agent cannot be the same employee."),[2];c.label=1;case 1:if(c.trys.push([1,6,,7]),!b)return[3,3];return[4,i.request({url:"orchestratorConfig:update",method:"put",params:{filterByTk:b.id},data:e})];case 2:return c.sent(),r.message.success("Rule updated"),[3,5];case 3:return[4,i.request({url:"orchestratorConfig:create",method:"post",data:e})];case 4:c.sent(),r.message.success("Rule created"),c.label=5;case 5:return O(),k(),[3,7];case 6:return u=(null==(t=c.sent())||null==(l=t.response)||null==(o=l.data)||null==(a=o.errors)||null==(n=a[0])?void 0:n.message)||t.message,r.message.error("Save failed: ".concat(u)),[3,7];case 7:return[2]}})}),function(e){return o.apply(this,arguments)}),T=(l=f(function(e){var t;return y(this,function(n){switch(n.label){case 0:return n.trys.push([0,2,,3]),[4,i.request({url:"orchestratorConfig:destroy",method:"delete",params:{filterByTk:e}})];case 1:return n.sent(),r.message.success("Rule deleted"),k(),[3,3];case 2:return t=n.sent(),r.message.error("Delete failed: ".concat(t.message)),[3,3];case 3:return[2]}})}),function(e){return l.apply(this,arguments)}),D=[{title:"Leader (Orchestrator)",dataIndex:"leaderUsername",key:"leaderUsername",render:function(e){return n().createElement(r.Tag,{color:"blue"},A.get(e)||e)}},{title:"",key:"arrow",width:50,render:function(){return n().createElement(a.SwapRightOutlined,{style:{color:"#999",fontSize:18}})}},{title:"Sub-Agent",dataIndex:"subAgentUsername",key:"subAgentUsername",render:function(e){return n().createElement(r.Tag,{color:"green"},A.get(e)||e)}},{title:"Max Depth",dataIndex:"maxDepth",key:"maxDepth",width:100,render:function(e){return null!=e?e:1}},{title:"Timeout",dataIndex:"timeout",key:"timeout",width:100,render:function(e){return"".concat(((null!=e?e:12e4)/1e3).toFixed(0),"s")}},{title:"Enabled",dataIndex:"enabled",key:"enabled",width:80,render:function(e,t){var a;return n().createElement(r.Switch,{checked:e,size:"small",onChange:(a=f(function(e){return y(this,function(n){switch(n.label){case 0:return[4,i.request({url:"orchestratorConfig:update",method:"put",params:{filterByTk:t.id},data:{enabled:e}})];case 1:return n.sent(),k(),[2]}})}),function(e){return a.apply(this,arguments)})})}},{title:"Actions",key:"actions",width:160,render:function(e,t){return n().createElement(r.Space,null,n().createElement(r.Button,{type:"link",size:"small",icon:n().createElement(a.EditOutlined,null),onClick:function(){return C(t)}},"Edit"),n().createElement(r.Popconfirm,{title:"Delete this rule?",onConfirm:function(){return T(t.id)}},n().createElement(r.Button,{type:"link",size:"small",danger:!0,icon:n().createElement(a.DeleteOutlined,null)},"Delete")))}}],M=r.Form.useWatch("leaderUsername",E);return n().createElement("div",null,n().createElement(r.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"Orchestration Rules",description:n().createElement(h,{type:"secondary"},"Configure which AI Employees can act as Leaders (Orchestrators) and which ones they can delegate tasks to. Each rule creates a callable tool for the Leader to invoke the Sub-Agent.")}),n().createElement(r.Card,{bordered:!1},n().createElement("div",{style:{marginBottom:16,display:"flex",justifyContent:"flex-end"}},n().createElement(r.Button,{type:"primary",icon:n().createElement(a.PlusOutlined,null),onClick:function(){return C()}},"New Rule")),n().createElement(r.Table,{rowKey:"id",loading:x,dataSource:(null==S?void 0:S.data)||[],columns:D,pagination:{hideOnSinglePage:!0,pageSize:20},size:"middle"})),n().createElement(r.Drawer,{title:b?"Edit Orchestration Rule":"New Orchestration Rule",width:480,onClose:O,open:d,styles:{body:{paddingBottom:80}},extra:n().createElement(r.Space,null,n().createElement(r.Button,{onClick:O},"Cancel"),n().createElement(r.Button,{onClick:function(){return E.submit()},type:"primary"},"Save"))},n().createElement(r.Form,{form:E,layout:"vertical",onFinish:I},n().createElement(r.Form.Item,{name:"leaderUsername",label:"Leader (Orchestrator)",rules:[{required:!0,message:"Please select a Leader"}],tooltip:"The AI Employee that will be able to delegate tasks to the Sub-Agent"},n().createElement(s,{placeholder:"Select Leader AI Employee..."})),n().createElement(r.Form.Item,{name:"subAgentUsername",label:"Sub-Agent",rules:[{required:!0,message:"Please select a Sub-Agent"}],tooltip:"The AI Employee that will receive delegated tasks"},n().createElement(s,{placeholder:"Select Sub-Agent AI Employee...",exclude:M})),n().createElement(r.Form.Item,{name:"maxDepth",label:"Max Delegation Depth",tooltip:"How many layers of delegation are allowed (1 = leader calls sub-agent, sub-agent cannot delegate further)"},n().createElement(r.InputNumber,{min:1,max:3,style:{width:"100%"}})),n().createElement(r.Form.Item,{name:"timeout",label:"Timeout (ms)",tooltip:"Maximum time in milliseconds for the sub-agent to complete its task"},n().createElement(r.InputNumber,{min:1e4,max:6e5,step:1e4,style:{width:"100%"}})),n().createElement(r.Form.Item,{name:"enabled",label:"Enabled",valuePropName:"checked"},n().createElement(r.Switch,null)))))};function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n<t;n++)r[n]=e[n];return r}var v=r.Typography.Text,E=r.Typography.Paragraph,w=function(){var o,l,i=(o=(0,t.useState)(null),function(e){if(Array.isArray(e))return e}(o)||function(e,t){var n,r,a=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var o=[],l=!0,i=!1;try{for(a=a.call(e);!(l=(n=a.next()).done)&&(o.push(n.value),o.length!==t);l=!0);}catch(e){i=!0,r=e}finally{try{l||null==a.return||a.return()}finally{if(i)throw r}}return o}}(o,2)||function(e,t){if(e){if("string"==typeof e)return b(e,2);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return b(e,t)}}(o,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),u=i[0],s=i[1],d=(0,e.useRequest)({url:"orchestratorTracing:list",params:{sort:["-createdAt"],pageSize:50}}),m=d.data,f=d.loading,p=d.refresh,y=c().employeeMap,h=[{title:"Time",dataIndex:"createdAt",key:"createdAt",width:170,render:function(e){return e?new Date(e).toLocaleString():"-"}},{title:"Sub-Agent",dataIndex:"subAgentUsername",key:"subAgentUsername",render:function(e){return n().createElement(r.Tag,{color:"green"},y.get(e)||e)}},{title:"Task",dataIndex:"task",key:"task",render:function(e){return n().createElement(v,{ellipsis:!0,style:{maxWidth:280}},(null==e?void 0:e.substring(0,100))||"-")}},{title:"Status",dataIndex:"status",key:"status",width:90,render:function(e){return n().createElement(r.Tag,{icon:"success"===e?n().createElement(a.CheckCircleOutlined,null):n().createElement(a.CloseCircleOutlined,null),color:"success"===e?"success":"error"},e)}},{title:"Duration",dataIndex:"durationMs",key:"durationMs",width:90,render:function(e){return e?e>=1e3?"".concat((e/1e3).toFixed(1),"s"):"".concat(e,"ms"):"-"}},{title:"Depth",dataIndex:"depth",key:"depth",width:60,render:function(e){return null!=e?e:0}},{title:"",key:"actions",width:80,render:function(e,t){return n().createElement(r.Button,{type:"link",size:"small",icon:n().createElement(a.EyeOutlined,null),onClick:function(){return s(t)}},"Detail")}}];return n().createElement("div",null,n().createElement(r.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"Swarm Tracing",description:n().createElement(v,{type:"secondary"},"View delegation execution logs. Each row represents one sub-agent invocation triggered by a Leader's tool call.")}),n().createElement(r.Card,{bordered:!1},n().createElement("div",{style:{marginBottom:16,display:"flex",justifyContent:"flex-end"}},n().createElement(r.Button,{onClick:p},"Refresh")),n().createElement(r.Table,{rowKey:"id",loading:f,dataSource:(null==m?void 0:m.data)||[],columns:h,pagination:{hideOnSinglePage:!0,pageSize:20},size:"middle",locale:{emptyText:n().createElement(r.Empty,{description:"No delegation executions yet"})}})),n().createElement(r.Drawer,{title:"Delegation Detail",width:640,onClose:function(){return s(null)},open:!!u},u&&n().createElement(n().Fragment,null,n().createElement(r.Descriptions,{column:1,bordered:!0,size:"small",style:{marginBottom:16}},n().createElement(r.Descriptions.Item,{label:"Status"},n().createElement(r.Tag,{icon:"success"===u.status?n().createElement(a.CheckCircleOutlined,null):n().createElement(a.CloseCircleOutlined,null),color:"success"===u.status?"success":"error"},u.status)),n().createElement(r.Descriptions.Item,{label:"Sub-Agent"},n().createElement(r.Tag,{color:"green"},y.get(u.subAgentUsername)||u.subAgentUsername)),n().createElement(r.Descriptions.Item,{label:"Tool"},n().createElement(v,{code:!0},u.toolName)),n().createElement(r.Descriptions.Item,{label:"Depth"},null!=(l=u.depth)?l:0),n().createElement(r.Descriptions.Item,{label:"Duration"},u.durationMs?u.durationMs>=1e3?"".concat((u.durationMs/1e3).toFixed(1),"s"):"".concat(u.durationMs,"ms"):"-"),n().createElement(r.Descriptions.Item,{label:"Time"},u.createdAt?new Date(u.createdAt).toLocaleString():"-")),n().createElement(r.Card,{title:"Task",size:"small",style:{marginBottom:16}},n().createElement(E,{style:{whiteSpace:"pre-wrap",margin:0,fontSize:13}},u.task||"No task description")),n().createElement(r.Card,{title:"Result",size:"small",style:{marginBottom:16,borderColor:"success"===u.status?"#b7eb8f":"#ffa39e"}},n().createElement(E,{style:{whiteSpace:"pre-wrap",margin:0,fontSize:13},ellipsis:{rows:20,expandable:!0}},u.result||u.error||"No result")),u.error&&n().createElement(r.Card,{title:"Error",size:"small",style:{borderColor:"#ffa39e"}},n().createElement(E,{type:"danger",style:{whiteSpace:"pre-wrap",margin:0,fontSize:13}},u.error)))))},S=function(){return n().createElement(u,null,n().createElement("div",{style:{padding:"0 24px 24px"}},n().createElement(r.Tabs,{defaultActiveKey:"rules",items:[{key:"rules",label:n().createElement("span",null,n().createElement(a.ApartmentOutlined,null)," Orchestration Rules"),children:n().createElement(g,null)},{key:"tracing",label:n().createElement("span",null,n().createElement(a.MonitorOutlined,null)," Swarm Tracing"),children:n().createElement(w,null)}]})))};function x(e,t,n,r,a,o,l){try{var i=e[o](l),u=i.value}catch(e){n(e);return}i.done?t(u):Promise.resolve(u).then(r,a)}function k(e,t,n){return(k=I()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var a=new(Function.bind.apply(e,r));return n&&C(a,n.prototype),a}).apply(null,arguments)}function A(e){return(A=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function C(e,t){return(C=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function O(e){var t="function"==typeof Map?new Map:void 0;return(O=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return k(e,arguments,A(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),C(n,e)})(e)}function I(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(I=function(){return!!e})()}var T=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function n(){var e,t;if(!(this instanceof n))throw TypeError("Cannot call a class as a function");return e=n,t=arguments,e=A(e),function(e,t){var n;if(t&&("object"==((n=t)&&"undefined"!=typeof Symbol&&n.constructor===Symbol?"symbol":typeof n)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,I()?Reflect.construct(e,t||[],A(this).constructor):e.apply(this,t))}return n.prototype=Object.create(e&&e.prototype,{constructor:{value:n,writable:!0,configurable:!0}}),e&&C(n,e),t=[{key:"load",value:function(){var e,t=this;return(e=function(){return function(e,t){var n,r,a,o,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:i(0),throw:i(1),return:i(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(o){return function(i){var u=[o,i];if(n)throw TypeError("Generator is already executing.");for(;l;)try{if(n=1,r&&(a=2&u[0]?r.return:u[0]?r.throw||((a=r.return)&&a.call(r),0):r.next)&&!(a=a.call(r,u[1])).done)return a;switch(r=0,a&&(u=[2&u[0],a.value]),u[0]){case 0:case 1:a=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,r=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!a||u[1]>a[0]&&u[1]<a[3])){l.label=u[1];break}if(6===u[0]&&l.label<a[1]){l.label=a[1],a=u;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(u);break}a[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],r=0}finally{n=a=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}(this,function(e){return t.app.pluginSettingsManager.add("ai.orchestrator",{title:"Agent Orchestrator",icon:"ApartmentOutlined",Component:S}),[2]})},function(){var t=this,n=arguments;return new Promise(function(r,a){var o=e.apply(t,n);function l(e){x(o,r,a,l,i,"next",e)}function i(e){x(o,r,a,l,i,"throw",e)}l(void 0)})})()}}],function(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}(n.prototype,t),n}(O(e.Plugin))}(),i}()});
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):"function"==typeof define&&define.amd?define("plugin-agent-orchestrator",["react","@nocobase/client","@ant-design/icons","antd"],t):"object"==typeof exports?exports["plugin-agent-orchestrator"]=t(require("react"),require("@nocobase/client"),require("@ant-design/icons"),require("antd")):e["plugin-agent-orchestrator"]=t(e.react,e["@nocobase/client"],e["@ant-design/icons"],e.antd)}(self,function(e,t,r,n){return function(){"use strict";var a={482:function(e){e.exports=r},772:function(e){e.exports=t},721:function(e){e.exports=n},156:function(t){t.exports=e}},o={};function l(e){var t=o[e];if(void 0!==t)return t.exports;var r=o[e]={exports:{}};return a[e](r,r.exports,l),r.exports}l.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return l.d(t,{a:t}),t},l.d=function(e,t){for(var r in t)l.o(t,r)&&!l.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},l.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},l.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var i={};return!function(){l.r(i),l.d(i,{default:function(){return T}});var e=l(772),t=l(156),r=l.n(t),n=l(721),a=l(482),o=(0,t.createContext)({employees:[],employeeMap:new Map,loading:!1}),u=function(t){var n=t.children,a=(0,e.useRequest)({url:"aiEmployees:list",params:{pageSize:200}}),l=a.data,i=a.loading,u=r().useMemo(function(){var e=((null==l?void 0:l.data)||[]).map(function(e){var t;return{username:e.username,nickname:e.nickname||e.username,about:null==(t=e.about)?void 0:t.substring(0,80)}}),t=new Map,r=!0,n=!1,a=void 0;try{for(var o,u=e[Symbol.iterator]();!(r=(o=u.next()).done);r=!0){var c=o.value;t.set(c.username,c.nickname)}}catch(e){n=!0,a=e}finally{try{r||null==u.return||u.return()}finally{if(n)throw a}}return{employees:e,employeeMap:t,loading:i}},[l,i]);return r().createElement(o.Provider,{value:u},n)},c=function(){return(0,t.useContext)(o)},s=function(e){var t=e.value,a=e.onChange,o=e.exclude,l=e.placeholder,i=c(),u=i.employees,s=i.loading,d=r().useMemo(function(){return u.filter(function(e){return!o||e.username!==o}).map(function(e){return{label:e.nickname,value:e.username,description:e.about}})},[u,o]);return r().createElement(n.Select,{loading:s,options:d,value:t,onChange:a,placeholder:void 0===l?"Select AI Employee...":l,showSearch:!0,filterOption:function(e,t){var r,n;return(null!=(r=null==t?void 0:t.label)?r:"").toString().toLowerCase().includes(e.toLowerCase())||(null!=(n=null==t?void 0:t.value)?n:"").toString().toLowerCase().includes(e.toLowerCase())},optionRender:function(e){return r().createElement("div",null,r().createElement("div",{style:{fontWeight:500}},e.label),e.data.description&&r().createElement("div",{style:{fontSize:12,color:"#888"}},e.data.description))}})};function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function m(e,t,r,n,a,o,l){try{var i=e[o](l),u=i.value}catch(e){r(e);return}i.done?t(u):Promise.resolve(u).then(n,a)}function f(e){return function(){var t=this,r=arguments;return new Promise(function(n,a){var o=e.apply(t,r);function l(e){m(o,n,a,l,i,"next",e)}function i(e){m(o,n,a,l,i,"throw",e)}l(void 0)})}}function p(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r,n,a=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var o=[],l=!0,i=!1;try{for(a=a.call(e);!(l=(r=a.next()).done)&&(o.push(r.value),!t||o.length!==t);l=!0);}catch(e){i=!0,n=e}finally{try{l||null==a.return||a.return()}finally{if(i)throw n}}return o}}(e,t)||function(e,t){if(e){if("string"==typeof e)return d(e,t);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return d(e,t)}}(e,t)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function y(e,t){var r,n,a,o,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:i(0),throw:i(1),return:i(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(o){return function(i){var u=[o,i];if(r)throw TypeError("Generator is already executing.");for(;l;)try{if(r=1,n&&(a=2&u[0]?n.return:u[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,u[1])).done)return a;switch(n=0,a&&(u=[2&u[0],a.value]),u[0]){case 0:case 1:a=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,n=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!a||u[1]>a[0]&&u[1]<a[3])){l.label=u[1];break}if(6===u[0]&&l.label<a[1]){l.label=a[1],a=u;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(u);break}a[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],n=0}finally{r=a=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}var h=n.Typography.Text,g=function(){var o,l,i=(0,e.useAPIClient)(),u=p((0,t.useState)(!1),2),d=u[0],m=u[1],g=p((0,t.useState)(null),2),b=g[0],v=g[1],E=p(n.Form.useForm(),1)[0],w=(0,e.useRequest)({url:"orchestratorConfig:list",params:{sort:["-createdAt"]}}),S=w.data,x=w.loading,k=w.refresh,A=c().employeeMap,C=function(e){v(e),e?E.setFieldsValue(e):(E.resetFields(),E.setFieldsValue({enabled:!0,maxDepth:1,timeout:12e4})),m(!0)},O=function(){m(!1),v(null)},I=(o=f(function(e){var t,r,a,o,l,u;return y(this,function(c){switch(c.label){case 0:if(e.leaderUsername===e.subAgentUsername)return n.message.error("Leader and Sub-Agent cannot be the same employee."),[2];c.label=1;case 1:if(c.trys.push([1,6,,7]),!b)return[3,3];return[4,i.request({url:"orchestratorConfig:update",method:"put",params:{filterByTk:b.id},data:e})];case 2:return c.sent(),n.message.success("Rule updated"),[3,5];case 3:return[4,i.request({url:"orchestratorConfig:create",method:"post",data:e})];case 4:c.sent(),n.message.success("Rule created"),c.label=5;case 5:return O(),k(),[3,7];case 6:return u=(null==(t=c.sent())||null==(l=t.response)||null==(o=l.data)||null==(a=o.errors)||null==(r=a[0])?void 0:r.message)||t.message,n.message.error("Save failed: ".concat(u)),[3,7];case 7:return[2]}})}),function(e){return o.apply(this,arguments)}),T=(l=f(function(e){var t;return y(this,function(r){switch(r.label){case 0:return r.trys.push([0,2,,3]),[4,i.request({url:"orchestratorConfig:destroy",method:"delete",params:{filterByTk:e}})];case 1:return r.sent(),n.message.success("Rule deleted"),k(),[3,3];case 2:return t=r.sent(),n.message.error("Delete failed: ".concat(t.message)),[3,3];case 3:return[2]}})}),function(e){return l.apply(this,arguments)}),D=[{title:"Leader (Orchestrator)",dataIndex:"leaderUsername",key:"leaderUsername",render:function(e){return r().createElement(n.Tag,{color:"blue"},A.get(e)||e)}},{title:"",key:"arrow",width:50,render:function(){return r().createElement(a.SwapRightOutlined,{style:{color:"#999",fontSize:18}})}},{title:"Sub-Agent",dataIndex:"subAgentUsername",key:"subAgentUsername",render:function(e){return r().createElement(n.Tag,{color:"green"},A.get(e)||e)}},{title:"Max Depth",dataIndex:"maxDepth",key:"maxDepth",width:100,render:function(e){return null!=e?e:1}},{title:"Timeout",dataIndex:"timeout",key:"timeout",width:100,render:function(e){return"".concat(((null!=e?e:12e4)/1e3).toFixed(0),"s")}},{title:"Enabled",dataIndex:"enabled",key:"enabled",width:80,render:function(e,t){var a;return r().createElement(n.Switch,{checked:e,size:"small",onChange:(a=f(function(e){return y(this,function(r){switch(r.label){case 0:return[4,i.request({url:"orchestratorConfig:update",method:"put",params:{filterByTk:t.id},data:{enabled:e}})];case 1:return r.sent(),k(),[2]}})}),function(e){return a.apply(this,arguments)})})}},{title:"Actions",key:"actions",width:160,render:function(e,t){return r().createElement(n.Space,null,r().createElement(n.Button,{type:"link",size:"small",icon:r().createElement(a.EditOutlined,null),onClick:function(){return C(t)}},"Edit"),r().createElement(n.Popconfirm,{title:"Delete this rule?",onConfirm:function(){return T(t.id)}},r().createElement(n.Button,{type:"link",size:"small",danger:!0,icon:r().createElement(a.DeleteOutlined,null)},"Delete")))}}],M=n.Form.useWatch("leaderUsername",E);return r().createElement("div",null,r().createElement(n.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"Orchestration Rules",description:r().createElement(h,{type:"secondary"},"Configure which AI Employees can act as Leaders (Orchestrators) and which ones they can delegate tasks to. Each rule creates a callable tool for the Leader to invoke the Sub-Agent.")}),r().createElement(n.Card,{bordered:!1},r().createElement("div",{style:{marginBottom:16,display:"flex",justifyContent:"flex-end"}},r().createElement(n.Button,{type:"primary",icon:r().createElement(a.PlusOutlined,null),onClick:function(){return C()}},"New Rule")),r().createElement(n.Table,{rowKey:"id",loading:x,dataSource:(null==S?void 0:S.data)||[],columns:D,pagination:{hideOnSinglePage:!0,pageSize:20},size:"middle"})),r().createElement(n.Drawer,{title:b?"Edit Orchestration Rule":"New Orchestration Rule",width:480,onClose:O,open:d,styles:{body:{paddingBottom:80}},extra:r().createElement(n.Space,null,r().createElement(n.Button,{onClick:O},"Cancel"),r().createElement(n.Button,{onClick:function(){return E.submit()},type:"primary"},"Save"))},r().createElement(n.Form,{form:E,layout:"vertical",onFinish:I},r().createElement(n.Form.Item,{name:"leaderUsername",label:"Leader (Orchestrator)",rules:[{required:!0,message:"Please select a Leader"}],tooltip:"The AI Employee that will be able to delegate tasks to the Sub-Agent"},r().createElement(s,{placeholder:"Select Leader AI Employee..."})),r().createElement(n.Form.Item,{name:"subAgentUsername",label:"Sub-Agent",rules:[{required:!0,message:"Please select a Sub-Agent"}],tooltip:"The AI Employee that will receive delegated tasks"},r().createElement(s,{placeholder:"Select Sub-Agent AI Employee...",exclude:M})),r().createElement(n.Form.Item,{name:"maxDepth",label:"Max Delegation Depth",tooltip:"How many layers of delegation are allowed (1 = leader calls sub-agent, sub-agent cannot delegate further)"},r().createElement(n.InputNumber,{min:1,max:3,style:{width:"100%"}})),r().createElement(n.Form.Item,{name:"timeout",label:"Timeout (ms)",tooltip:"Maximum time in milliseconds for the sub-agent to complete its task"},r().createElement(n.InputNumber,{min:1e4,max:6e5,step:1e4,style:{width:"100%"}})),r().createElement(n.Form.Item,{name:"enabled",label:"Enabled",valuePropName:"checked"},r().createElement(n.Switch,null)))))};function b(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}var v=n.Typography.Text,E=n.Typography.Paragraph,w=function(){var o,l,i=(o=(0,t.useState)(null),function(e){if(Array.isArray(e))return e}(o)||function(e,t){var r,n,a=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=a){var o=[],l=!0,i=!1;try{for(a=a.call(e);!(l=(r=a.next()).done)&&(o.push(r.value),o.length!==t);l=!0);}catch(e){i=!0,n=e}finally{try{l||null==a.return||a.return()}finally{if(i)throw n}}return o}}(o,2)||function(e,t){if(e){if("string"==typeof e)return b(e,2);var r=Object.prototype.toString.call(e).slice(8,-1);if("Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r)return Array.from(r);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return b(e,t)}}(o,2)||function(){throw TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),u=i[0],s=i[1],d=(0,e.useRequest)({url:"orchestratorTracing:list",params:{sort:["-createdAt"],pageSize:50}}),m=d.data,f=d.loading,p=d.refresh,y=c().employeeMap,h=[{title:"Time",dataIndex:"createdAt",key:"createdAt",width:170,render:function(e){return e?new Date(e).toLocaleString():"-"}},{title:"Sub-Agent",dataIndex:"subAgentUsername",key:"subAgentUsername",render:function(e){return r().createElement(n.Tag,{color:"green"},y.get(e)||e)}},{title:"Task",dataIndex:"task",key:"task",render:function(e){return r().createElement(v,{ellipsis:!0,style:{maxWidth:280}},(null==e?void 0:e.substring(0,100))||"-")}},{title:"Status",dataIndex:"status",key:"status",width:90,render:function(e){return r().createElement(n.Tag,{icon:"success"===e?r().createElement(a.CheckCircleOutlined,null):r().createElement(a.CloseCircleOutlined,null),color:"success"===e?"success":"error"},e)}},{title:"Duration",dataIndex:"durationMs",key:"durationMs",width:90,render:function(e){return e?e>=1e3?"".concat((e/1e3).toFixed(1),"s"):"".concat(e,"ms"):"-"}},{title:"Depth",dataIndex:"depth",key:"depth",width:60,render:function(e){return null!=e?e:0}},{title:"",key:"actions",width:80,render:function(e,t){return r().createElement(n.Button,{type:"link",size:"small",icon:r().createElement(a.EyeOutlined,null),onClick:function(){return s(t)}},"Detail")}}];return r().createElement("div",null,r().createElement(n.Alert,{type:"info",showIcon:!0,style:{marginBottom:16},message:"Swarm Tracing",description:r().createElement(v,{type:"secondary"},"View delegation execution logs. Each row represents one sub-agent invocation triggered by a Leader's tool call.")}),r().createElement(n.Card,{bordered:!1},r().createElement("div",{style:{marginBottom:16,display:"flex",justifyContent:"flex-end"}},r().createElement(n.Button,{onClick:p},"Refresh")),r().createElement(n.Table,{rowKey:"id",loading:f,dataSource:Array.isArray(null==m?void 0:m.data)?m.data:Array.isArray(m)?m:[],columns:h,pagination:{hideOnSinglePage:!0,pageSize:20},size:"middle",locale:{emptyText:r().createElement(n.Empty,{description:"No delegation executions yet"})}})),r().createElement(n.Drawer,{title:"Delegation Detail",width:640,onClose:function(){return s(null)},open:!!u},u&&r().createElement(r().Fragment,null,r().createElement(n.Descriptions,{column:1,bordered:!0,size:"small",style:{marginBottom:16}},r().createElement(n.Descriptions.Item,{label:"Status"},r().createElement(n.Tag,{icon:"success"===u.status?r().createElement(a.CheckCircleOutlined,null):r().createElement(a.CloseCircleOutlined,null),color:"success"===u.status?"success":"error"},u.status)),r().createElement(n.Descriptions.Item,{label:"Sub-Agent"},r().createElement(n.Tag,{color:"green"},y.get(u.subAgentUsername)||u.subAgentUsername)),r().createElement(n.Descriptions.Item,{label:"Tool"},r().createElement(v,{code:!0},u.toolName)),r().createElement(n.Descriptions.Item,{label:"Depth"},null!=(l=u.depth)?l:0),r().createElement(n.Descriptions.Item,{label:"Duration"},u.durationMs?u.durationMs>=1e3?"".concat((u.durationMs/1e3).toFixed(1),"s"):"".concat(u.durationMs,"ms"):"-"),r().createElement(n.Descriptions.Item,{label:"Time"},u.createdAt?new Date(u.createdAt).toLocaleString():"-")),r().createElement(n.Card,{title:"Task",size:"small",style:{marginBottom:16}},r().createElement(E,{style:{whiteSpace:"pre-wrap",margin:0,fontSize:13}},u.task||"No task description")),r().createElement(n.Card,{title:"Result",size:"small",style:{marginBottom:16,borderColor:"success"===u.status?"#b7eb8f":"#ffa39e"}},r().createElement(E,{style:{whiteSpace:"pre-wrap",margin:0,fontSize:13},ellipsis:{rows:20,expandable:!0}},u.result||u.error||"No result")),u.error&&r().createElement(n.Card,{title:"Error",size:"small",style:{borderColor:"#ffa39e"}},r().createElement(E,{type:"danger",style:{whiteSpace:"pre-wrap",margin:0,fontSize:13}},u.error)))))},S=function(){return r().createElement(u,null,r().createElement("div",{style:{padding:"0 24px 24px"}},r().createElement(n.Tabs,{defaultActiveKey:"rules",items:[{key:"rules",label:r().createElement("span",null,r().createElement(a.ApartmentOutlined,null)," Orchestration Rules"),children:r().createElement(g,null)},{key:"tracing",label:r().createElement("span",null,r().createElement(a.MonitorOutlined,null)," Swarm Tracing"),children:r().createElement(w,null)}]})))};function x(e,t,r,n,a,o,l){try{var i=e[o](l),u=i.value}catch(e){r(e);return}i.done?t(u):Promise.resolve(u).then(n,a)}function k(e,t,r){return(k=I()?Reflect.construct:function(e,t,r){var n=[null];n.push.apply(n,t);var a=new(Function.bind.apply(e,n));return r&&C(a,r.prototype),a}).apply(null,arguments)}function A(e){return(A=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function C(e,t){return(C=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}function O(e){var t="function"==typeof Map?new Map:void 0;return(O=function(e){if(null===e||-1===Function.toString.call(e).indexOf("[native code]"))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,r)}function r(){return k(e,arguments,A(this).constructor)}return r.prototype=Object.create(e.prototype,{constructor:{value:r,enumerable:!1,writable:!0,configurable:!0}}),C(r,e)})(e)}function I(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){}))}catch(e){}return(I=function(){return!!e})()}var T=function(e){var t;if("function"!=typeof e&&null!==e)throw TypeError("Super expression must either be null or a function");function r(){var e,t;if(!(this instanceof r))throw TypeError("Cannot call a class as a function");return e=r,t=arguments,e=A(e),function(e,t){var r;if(t&&("object"==((r=t)&&"undefined"!=typeof Symbol&&r.constructor===Symbol?"symbol":typeof r)||"function"==typeof t))return t;if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(this,I()?Reflect.construct(e,t||[],A(this).constructor):e.apply(this,t))}return r.prototype=Object.create(e&&e.prototype,{constructor:{value:r,writable:!0,configurable:!0}}),e&&C(r,e),t=[{key:"load",value:function(){var e,t=this;return(e=function(){return function(e,t){var r,n,a,o,l={label:0,sent:function(){if(1&a[0])throw a[1];return a[1]},trys:[],ops:[]};return o={next:i(0),throw:i(1),return:i(2)},"function"==typeof Symbol&&(o[Symbol.iterator]=function(){return this}),o;function i(o){return function(i){var u=[o,i];if(r)throw TypeError("Generator is already executing.");for(;l;)try{if(r=1,n&&(a=2&u[0]?n.return:u[0]?n.throw||((a=n.return)&&a.call(n),0):n.next)&&!(a=a.call(n,u[1])).done)return a;switch(n=0,a&&(u=[2&u[0],a.value]),u[0]){case 0:case 1:a=u;break;case 4:return l.label++,{value:u[1],done:!1};case 5:l.label++,n=u[1],u=[0];continue;case 7:u=l.ops.pop(),l.trys.pop();continue;default:if(!(a=(a=l.trys).length>0&&a[a.length-1])&&(6===u[0]||2===u[0])){l=0;continue}if(3===u[0]&&(!a||u[1]>a[0]&&u[1]<a[3])){l.label=u[1];break}if(6===u[0]&&l.label<a[1]){l.label=a[1],a=u;break}if(a&&l.label<a[2]){l.label=a[2],l.ops.push(u);break}a[2]&&l.ops.pop(),l.trys.pop();continue}u=t.call(e,l)}catch(e){u=[6,e],n=0}finally{r=a=0}if(5&u[0])throw u[1];return{value:u[0]?u[1]:void 0,done:!0}}}}(this,function(e){return t.app.pluginSettingsManager.add("ai.orchestrator",{title:"Agent Orchestrator",icon:"ApartmentOutlined",Component:S}),[2]})},function(){var t=this,r=arguments;return new Promise(function(n,a){var o=e.apply(t,r);function l(e){x(o,n,a,l,i,"next",e)}function i(e){x(o,n,a,l,i,"throw",e)}l(void 0)})})()}}],function(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}(r.prototype,t),r}(O(e.Plugin))}(),i}()});
@@ -0,0 +1,5 @@
1
+ import { Plugin } from '@nocobase/client';
2
+ export declare class PluginAgentOrchestratorClient extends Plugin {
3
+ load(): Promise<void>;
4
+ }
5
+ export default PluginAgentOrchestratorClient;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  module.exports = {
2
11
  "react": "18.2.0",
3
12
  "@nocobase/client": "2.0.41",
@@ -0,0 +1,2 @@
1
+ export * from './server';
2
+ export { default } from './server';
package/dist/index.js CHANGED
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __create = Object.create;
2
11
  var __defProp = Object.defineProperty;
3
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("@nocobase/database").CollectionOptions;
2
+ export default _default;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __defProp = Object.defineProperty;
2
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Stores delegation execution logs for Swarm Tracing (Phase 5).
3
+ *
4
+ * Since createReactAgent doesn't create aiConversation records,
5
+ * we log delegation events to a dedicated table for observability.
6
+ */
7
+ declare const _default: import("@nocobase/database").CollectionOptions;
8
+ export default _default;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __defProp = Object.defineProperty;
2
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -0,0 +1 @@
1
+ export { default } from './plugin';
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __create = Object.create;
2
11
  var __defProp = Object.defineProperty;
3
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -0,0 +1,11 @@
1
+ import { Plugin } from '@nocobase/server';
2
+ export declare class PluginAgentOrchestratorServer extends Plugin {
3
+ afterAdd(): Promise<void>;
4
+ beforeLoad(): Promise<void>;
5
+ load(): Promise<void>;
6
+ install(): Promise<void>;
7
+ afterEnable(): Promise<void>;
8
+ afterDisable(): Promise<void>;
9
+ remove(): Promise<void>;
10
+ }
11
+ export default PluginAgentOrchestratorServer;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __create = Object.create;
2
11
  var __defProp = Object.defineProperty;
3
12
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -0,0 +1,7 @@
1
+ import { Plugin } from '@nocobase/server';
2
+ /**
3
+ * Custom resource for the Swarm Tracing admin UI (Phase 5).
4
+ * Queries the dedicated orchestratorLogs collection instead of
5
+ * filtering aiConversations by JSONB (P2 fix: DB-engine agnostic).
6
+ */
7
+ export declare function registerTracingResource(plugin: Plugin): void;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __defProp = Object.defineProperty;
2
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Creates one dynamic tool per configured sub-agent for a given leader.
3
+ * Uses Strategy B (Per-SubAgent Tool): each sub-agent becomes a separate tool
4
+ * with its own name and description, making LLM tool selection natural.
5
+ *
6
+ * Architecture:
7
+ * - Uses createReactAgent (public LangGraph API) for agent execution
8
+ * - Uses plugin-ai's getLLMService() for LLM model resolution
9
+ * - Uses core app.aiManager.toolsManager.listTools() for tool resolution
10
+ * (same manager that AIEmployee uses — see ai-employee.ts:1286)
11
+ * - Depth enforcement via ctx metadata tracking
12
+ * - Per-leader scoping via invoke-time check (core ToolsOptions has no
13
+ * leaderUsername field, so scoping is enforced in the invoke callback)
14
+ */
15
+ export declare function createDelegateToolsProvider(plugin: any): (register: any) => Promise<void>;
@@ -1,3 +1,12 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
1
10
  var __defProp = Object.defineProperty;
2
11
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
12
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -203,7 +212,7 @@ ${context}` : `Task: ${task}`;
203
212
  }
204
213
  }
205
214
  async function logDelegation(ctx, plugin, data) {
206
- var _a, _b, _c, _d, _e;
215
+ var _a, _b, _c, _d;
207
216
  try {
208
217
  const logsRepo = plugin.db.getRepository("orchestratorLogs");
209
218
  if (!logsRepo) return;
@@ -212,13 +221,13 @@ async function logDelegation(ctx, plugin, data) {
212
221
  leaderUsername: data.leaderUsername,
213
222
  subAgentUsername: data.subAgentUsername,
214
223
  toolName: `delegate_to_${data.subAgentUsername}`,
215
- task: data.task.substring(0, 2e3),
216
- result: data.result.substring(0, 5e3),
224
+ task: (data.task || "").substring(0, 2e3),
225
+ result: (data.result || "").substring(0, 5e3),
217
226
  status: data.status,
218
227
  depth: data.depth,
219
228
  durationMs: data.durationMs,
220
- error: (_a = data.error) == null ? void 0 : _a.substring(0, 2e3),
221
- userId: ((_c = (_b = ctx.auth) == null ? void 0 : _b.user) == null ? void 0 : _c.id) || ((_e = (_d = ctx.state) == null ? void 0 : _d.currentUser) == null ? void 0 : _e.id)
229
+ error: (data.error || "").substring(0, 2e3),
230
+ userId: ((_b = (_a = ctx.auth) == null ? void 0 : _a.user) == null ? void 0 : _b.id) || ((_d = (_c = ctx.state) == null ? void 0 : _c.currentUser) == null ? void 0 : _d.id)
222
231
  }
223
232
  });
224
233
  } catch (e) {
@@ -226,25 +235,28 @@ async function logDelegation(ctx, plugin, data) {
226
235
  }
227
236
  }
228
237
  async function executeAgent(executor, systemPrompt, task, signal) {
229
- const streamOptions = { recursionLimit: 50, streamMode: "messages" };
238
+ const config = { recursionLimit: 50 };
230
239
  if (signal) {
231
- streamOptions.signal = signal;
240
+ config.signal = signal;
232
241
  }
233
- const stream = await executor.stream(
242
+ const finalState = await executor.invoke(
234
243
  {
235
244
  messages: [new import_messages.SystemMessage(systemPrompt), new import_messages.HumanMessage(task)]
236
245
  },
237
- streamOptions
246
+ config
238
247
  );
239
- let aiContentCache = "";
240
- for await (const chunk of stream) {
241
- if (signal == null ? void 0 : signal.aborted) break;
242
- const [message] = chunk;
243
- if (message.getType() === "ai" && message.content) {
244
- aiContentCache += message.content.toString();
245
- }
248
+ const messages = (finalState == null ? void 0 : finalState.messages) || [];
249
+ const lastAIMessage = [...messages].reverse().find((m) => m.getType() === "ai");
250
+ if (!lastAIMessage || !lastAIMessage.content) {
251
+ return "";
252
+ }
253
+ if (typeof lastAIMessage.content === "string") {
254
+ return lastAIMessage.content;
255
+ }
256
+ if (Array.isArray(lastAIMessage.content)) {
257
+ return lastAIMessage.content.map((c) => c.text || JSON.stringify(c)).join("\n");
246
258
  }
247
- return aiContentCache || "";
259
+ return String(lastAIMessage.content);
248
260
  }
249
261
  function createTimeout(ms, agentName, abortController) {
250
262
  return new Promise(
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName.zh-CN": "代理协调器",
5
5
  "displayName.vi-VN": "Điều phối Agent",
6
6
  "description": "Hierarchical Multi-Agent orchestration for NocoBase AI Employees. Enables Leader agents to delegate tasks to Sub-Agent employees without modifying core plugin-ai.",
7
- "version": "1.0.1",
7
+ "version": "1.0.6",
8
8
  "license": "Apache-2.0",
9
9
  "main": "dist/server/index.js",
10
10
  "keywords": [
@@ -5,37 +5,21 @@ import { RulesTab } from './RulesTab';
5
5
  import { TracingTab } from './TracingTab';
6
6
  import { AIEmployeesProvider } from './AIEmployeesContext';
7
7
 
8
- /**
9
- * Main settings page for the Agent Orchestrator plugin.
10
- * Contains two tabs:
11
- * - Rules: Configure which AI Employees can delegate tasks to others
12
- * - Tracing: View and debug delegation execution logs
13
- *
14
- * P3 FIX: Wraps with AIEmployeesProvider so both tabs share one API call.
15
- */
16
8
  export const OrchestratorSettings: React.FC = () => {
17
9
  return (
18
10
  <AIEmployeesProvider>
19
11
  <div style={{ padding: '0 24px 24px' }}>
20
- <Tabs
12
+ <Tabs
21
13
  defaultActiveKey="rules"
22
14
  items={[
23
15
  {
24
16
  key: 'rules',
25
- label: (
26
- <span>
27
- <ApartmentOutlined /> Orchestration Rules
28
- </span>
29
- ),
17
+ label: <span><ApartmentOutlined /> Orchestration Rules</span>,
30
18
  children: <RulesTab />,
31
19
  },
32
20
  {
33
21
  key: 'tracing',
34
- label: (
35
- <span>
36
- <MonitorOutlined /> Swarm Tracing
37
- </span>
38
- ),
22
+ label: <span><MonitorOutlined /> Swarm Tracing</span>,
39
23
  children: <TracingTab />,
40
24
  },
41
25
  ]}
@@ -14,21 +14,15 @@ import {
14
14
  EyeOutlined,
15
15
  CheckCircleOutlined,
16
16
  CloseCircleOutlined,
17
- ClockCircleOutlined,
18
17
  } from '@ant-design/icons';
19
18
  import { useRequest } from '@nocobase/client';
20
19
  import { useAIEmployees } from './AIEmployeesContext';
21
20
 
22
21
  const { Text, Paragraph } = Typography;
23
22
 
24
- /**
25
- * Phase 5: Swarm Tracing page.
26
- * Displays delegation execution logs from the orchestratorLogs collection.
27
- */
28
23
  export const TracingTab: React.FC = () => {
29
24
  const [selectedLog, setSelectedLog] = useState<any>(null);
30
25
 
31
- // Fetch delegation logs
32
26
  const { data, loading, refresh } = useRequest({
33
27
  url: 'orchestratorTracing:list',
34
28
  params: {
@@ -37,7 +31,6 @@ export const TracingTab: React.FC = () => {
37
31
  },
38
32
  });
39
33
 
40
- // P3 FIX: Use shared context instead of duplicate API call
41
34
  const { employeeMap } = useAIEmployees();
42
35
 
43
36
  const columns = [
@@ -136,7 +129,7 @@ export const TracingTab: React.FC = () => {
136
129
  <Table
137
130
  rowKey="id"
138
131
  loading={loading}
139
- dataSource={(data as any)?.data || []}
132
+ dataSource={Array.isArray((data as any)?.data) ? (data as any).data : (Array.isArray(data) ? data : [])}
140
133
  columns={columns}
141
134
  pagination={{ hideOnSinglePage: true, pageSize: 20 }}
142
135
  size="middle"
@@ -144,7 +137,6 @@ export const TracingTab: React.FC = () => {
144
137
  />
145
138
  </Card>
146
139
 
147
- {/* Detail drawer */}
148
140
  <Drawer
149
141
  title="Delegation Detail"
150
142
  width={640}
@@ -186,9 +178,7 @@ export const TracingTab: React.FC = () => {
186
178
  </Descriptions>
187
179
 
188
180
  <Card title="Task" size="small" style={{ marginBottom: 16 }}>
189
- <Paragraph
190
- style={{ whiteSpace: 'pre-wrap', margin: 0, fontSize: 13 }}
191
- >
181
+ <Paragraph style={{ whiteSpace: 'pre-wrap', margin: 0, fontSize: 13 }}>
192
182
  {selectedLog.task || 'No task description'}
193
183
  </Paragraph>
194
184
  </Card>
@@ -322,12 +322,12 @@ async function logDelegation(
322
322
  leaderUsername: data.leaderUsername,
323
323
  subAgentUsername: data.subAgentUsername,
324
324
  toolName: `delegate_to_${data.subAgentUsername}`,
325
- task: data.task.substring(0, 2000),
326
- result: data.result.substring(0, 5000),
325
+ task: (data.task || '').substring(0, 2000),
326
+ result: (data.result || '').substring(0, 5000),
327
327
  status: data.status,
328
328
  depth: data.depth,
329
329
  durationMs: data.durationMs,
330
- error: data.error?.substring(0, 2000),
330
+ error: (data.error || '').substring(0, 2000),
331
331
  userId: ctx.auth?.user?.id || ctx.state?.currentUser?.id,
332
332
  },
333
333
  });
@@ -338,8 +338,8 @@ async function logDelegation(
338
338
 
339
339
  /**
340
340
  * Execute the agent and extract the final AI message content.
341
- * Uses stream mode to collect all chunks, similar to plugin-sub-agent.
342
- * Accepts an AbortSignal so the stream can be cancelled on timeout.
341
+ * Uses executor.invoke to get the final state cleanly, avoiding chunk parsing issues.
342
+ * Accepts an AbortSignal so the execution can be cancelled on timeout.
343
343
  */
344
344
  async function executeAgent(
345
345
  executor: any,
@@ -347,31 +347,39 @@ async function executeAgent(
347
347
  task: string,
348
348
  signal?: AbortSignal,
349
349
  ): Promise<string> {
350
- const streamOptions: any = { recursionLimit: 50, streamMode: 'messages' };
350
+ const config: any = { recursionLimit: 50 };
351
351
  if (signal) {
352
- streamOptions.signal = signal;
352
+ config.signal = signal;
353
353
  }
354
354
 
355
- const stream = await executor.stream(
355
+ const finalState = await executor.invoke(
356
356
  {
357
357
  messages: [new SystemMessage(systemPrompt), new HumanMessage(task)],
358
358
  },
359
- streamOptions,
359
+ config,
360
360
  );
361
361
 
362
- let aiContentCache = '';
362
+ // finalState.messages contains the entire conversation history of this delegation
363
+ const messages = finalState?.messages || [];
364
+
365
+ // Find the last AI message in the chain
366
+ const lastAIMessage = [...messages].reverse().find(m => m.getType() === 'ai');
363
367
 
364
- for await (const chunk of stream) {
365
- // Check abort between chunks
366
- if (signal?.aborted) break;
368
+ if (!lastAIMessage || !lastAIMessage.content) {
369
+ return '';
370
+ }
367
371
 
368
- const [message] = chunk;
369
- if (message.getType() === 'ai' && message.content) {
370
- aiContentCache += message.content.toString();
371
- }
372
+ if (typeof lastAIMessage.content === 'string') {
373
+ return lastAIMessage.content;
374
+ }
375
+
376
+ if (Array.isArray(lastAIMessage.content)) {
377
+ return lastAIMessage.content
378
+ .map((c: any) => c.text || JSON.stringify(c))
379
+ .join('\n');
372
380
  }
373
381
 
374
- return aiContentCache || '';
382
+ return String(lastAIMessage.content);
375
383
  }
376
384
 
377
385
  /**