plugin-agent-orchestrator 1.0.13 → 1.0.14

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.
Files changed (251) hide show
  1. package/README.md +16 -291
  2. package/dist/client/AIEmployeesContext.d.ts +7 -0
  3. package/dist/client/OrchestratorSettings.d.ts +2 -1
  4. package/dist/client/index.js +1 -1
  5. package/dist/client/plugin.d.ts +1 -0
  6. package/dist/client/skill-hub/components/ExecutionHistory.d.ts +2 -0
  7. package/dist/client/skill-hub/components/ExecutionProgress.d.ts +20 -0
  8. package/dist/client/skill-hub/components/GitSkillImport.d.ts +7 -0
  9. package/dist/client/skill-hub/components/SkillEditor.d.ts +7 -0
  10. package/dist/client/skill-hub/components/SkillManager.d.ts +2 -0
  11. package/dist/client/skill-hub/components/SkillMetrics.d.ts +2 -0
  12. package/dist/client/skill-hub/components/SkillTestPanel.d.ts +7 -0
  13. package/dist/client/skill-hub/index.d.ts +10 -0
  14. package/dist/client/skill-hub/locale.d.ts +3 -0
  15. package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +19 -0
  16. package/dist/client/skill-hub/tools/SkillHubCard.d.ts +3 -0
  17. package/dist/client/skill-hub/utils/jsonFields.d.ts +3 -0
  18. package/dist/externalVersion.js +6 -6
  19. package/dist/node_modules/adm-zip/LICENSE +21 -0
  20. package/dist/node_modules/adm-zip/adm-zip.js +1 -0
  21. package/dist/node_modules/adm-zip/headers/entryHeader.js +377 -0
  22. package/dist/node_modules/adm-zip/headers/index.js +2 -0
  23. package/dist/node_modules/adm-zip/headers/mainHeader.js +130 -0
  24. package/dist/node_modules/adm-zip/methods/deflater.js +33 -0
  25. package/dist/node_modules/adm-zip/methods/index.js +3 -0
  26. package/dist/node_modules/adm-zip/methods/inflater.js +34 -0
  27. package/dist/node_modules/adm-zip/methods/zipcrypto.js +175 -0
  28. package/dist/node_modules/adm-zip/package.json +1 -0
  29. package/dist/node_modules/adm-zip/util/constants.js +142 -0
  30. package/dist/node_modules/adm-zip/util/decoder.js +5 -0
  31. package/dist/node_modules/adm-zip/util/errors.js +63 -0
  32. package/dist/node_modules/adm-zip/util/fattr.js +76 -0
  33. package/dist/node_modules/adm-zip/util/index.js +5 -0
  34. package/dist/node_modules/adm-zip/util/utils.js +339 -0
  35. package/dist/node_modules/adm-zip/zipEntry.js +405 -0
  36. package/dist/node_modules/adm-zip/zipFile.js +446 -0
  37. package/dist/node_modules/simple-git/dist/cjs/index.js +7399 -0
  38. package/dist/node_modules/simple-git/dist/esm/index.js +4745 -0
  39. package/dist/node_modules/simple-git/dist/esm/package.json +3 -0
  40. package/dist/node_modules/simple-git/dist/src/lib/api.d.ts +13 -0
  41. package/dist/node_modules/simple-git/dist/src/lib/args/log-format.d.ts +9 -0
  42. package/dist/node_modules/simple-git/dist/src/lib/errors/git-construct-error.d.ts +15 -0
  43. package/dist/node_modules/simple-git/dist/src/lib/errors/git-error.d.ts +30 -0
  44. package/dist/node_modules/simple-git/dist/src/lib/errors/git-plugin-error.d.ts +7 -0
  45. package/dist/node_modules/simple-git/dist/src/lib/errors/git-response-error.d.ts +32 -0
  46. package/dist/node_modules/simple-git/dist/src/lib/errors/task-configuration-error.d.ts +12 -0
  47. package/dist/node_modules/simple-git/dist/src/lib/git-factory.d.ts +15 -0
  48. package/dist/node_modules/simple-git/dist/src/lib/git-logger.d.ts +21 -0
  49. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch-delete.d.ts +5 -0
  50. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-branch.d.ts +2 -0
  51. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-commit.d.ts +2 -0
  52. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-diff-summary.d.ts +3 -0
  53. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-fetch.d.ts +2 -0
  54. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-list-log-summary.d.ts +6 -0
  55. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-merge.d.ts +11 -0
  56. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-move.d.ts +2 -0
  57. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-pull.d.ts +6 -0
  58. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-push.d.ts +4 -0
  59. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-messages.d.ts +5 -0
  60. package/dist/node_modules/simple-git/dist/src/lib/parsers/parse-remote-objects.d.ts +3 -0
  61. package/dist/node_modules/simple-git/dist/src/lib/plugins/abort-plugin.d.ts +3 -0
  62. package/dist/node_modules/simple-git/dist/src/lib/plugins/block-unsafe-operations-plugin.d.ts +3 -0
  63. package/dist/node_modules/simple-git/dist/src/lib/plugins/command-config-prefixing-plugin.d.ts +2 -0
  64. package/dist/node_modules/simple-git/dist/src/lib/plugins/completion-detection.plugin.d.ts +3 -0
  65. package/dist/node_modules/simple-git/dist/src/lib/plugins/custom-binary.plugin.d.ts +3 -0
  66. package/dist/node_modules/simple-git/dist/src/lib/plugins/error-detection.plugin.d.ts +7 -0
  67. package/dist/node_modules/simple-git/dist/src/lib/plugins/index.d.ts +11 -0
  68. package/dist/node_modules/simple-git/dist/src/lib/plugins/plugin-store.d.ts +11 -0
  69. package/dist/node_modules/simple-git/dist/src/lib/plugins/progress-monitor-plugin.d.ts +3 -0
  70. package/dist/node_modules/simple-git/dist/src/lib/plugins/simple-git-plugin.d.ts +48 -0
  71. package/dist/node_modules/simple-git/dist/src/lib/plugins/spawn-options-plugin.d.ts +3 -0
  72. package/dist/node_modules/simple-git/dist/src/lib/plugins/suffix-paths.plugin.d.ts +2 -0
  73. package/dist/node_modules/simple-git/dist/src/lib/plugins/timout-plugin.d.ts +3 -0
  74. package/dist/node_modules/simple-git/dist/src/lib/responses/BranchDeleteSummary.d.ts +12 -0
  75. package/dist/node_modules/simple-git/dist/src/lib/responses/BranchSummary.d.ts +14 -0
  76. package/dist/node_modules/simple-git/dist/src/lib/responses/CheckIgnore.d.ts +4 -0
  77. package/dist/node_modules/simple-git/dist/src/lib/responses/CleanSummary.d.ts +9 -0
  78. package/dist/node_modules/simple-git/dist/src/lib/responses/ConfigList.d.ts +13 -0
  79. package/dist/node_modules/simple-git/dist/src/lib/responses/DiffSummary.d.ts +10 -0
  80. package/dist/node_modules/simple-git/dist/src/lib/responses/FileStatusSummary.d.ts +9 -0
  81. package/dist/node_modules/simple-git/dist/src/lib/responses/GetRemoteSummary.d.ts +11 -0
  82. package/dist/node_modules/simple-git/dist/src/lib/responses/InitSummary.d.ts +9 -0
  83. package/dist/node_modules/simple-git/dist/src/lib/responses/MergeSummary.d.ts +16 -0
  84. package/dist/node_modules/simple-git/dist/src/lib/responses/PullSummary.d.ts +25 -0
  85. package/dist/node_modules/simple-git/dist/src/lib/responses/StatusSummary.d.ts +19 -0
  86. package/dist/node_modules/simple-git/dist/src/lib/responses/TagList.d.ts +7 -0
  87. package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor-chain.d.ts +25 -0
  88. package/dist/node_modules/simple-git/dist/src/lib/runners/git-executor.d.ts +14 -0
  89. package/dist/node_modules/simple-git/dist/src/lib/runners/promise-wrapped.d.ts +2 -0
  90. package/dist/node_modules/simple-git/dist/src/lib/runners/scheduler.d.ts +11 -0
  91. package/dist/node_modules/simple-git/dist/src/lib/runners/tasks-pending-queue.d.ts +23 -0
  92. package/dist/node_modules/simple-git/dist/src/lib/simple-git-api.d.ts +20 -0
  93. package/dist/node_modules/simple-git/dist/src/lib/task-callback.d.ts +2 -0
  94. package/dist/node_modules/simple-git/dist/src/lib/tasks/apply-patch.d.ts +3 -0
  95. package/dist/node_modules/simple-git/dist/src/lib/tasks/branch.d.ts +7 -0
  96. package/dist/node_modules/simple-git/dist/src/lib/tasks/change-working-directory.d.ts +2 -0
  97. package/dist/node_modules/simple-git/dist/src/lib/tasks/check-ignore.d.ts +2 -0
  98. package/dist/node_modules/simple-git/dist/src/lib/tasks/check-is-repo.d.ts +9 -0
  99. package/dist/node_modules/simple-git/dist/src/lib/tasks/checkout.d.ts +2 -0
  100. package/dist/node_modules/simple-git/dist/src/lib/tasks/clean.d.ts +25 -0
  101. package/dist/node_modules/simple-git/dist/src/lib/tasks/clone.d.ts +9 -0
  102. package/dist/node_modules/simple-git/dist/src/lib/tasks/commit.d.ts +4 -0
  103. package/dist/node_modules/simple-git/dist/src/lib/tasks/config.d.ts +8 -0
  104. package/dist/node_modules/simple-git/dist/src/lib/tasks/count-objects.d.ts +12 -0
  105. package/dist/node_modules/simple-git/dist/src/lib/tasks/diff-name-status.d.ts +12 -0
  106. package/dist/node_modules/simple-git/dist/src/lib/tasks/diff.d.ts +5 -0
  107. package/dist/node_modules/simple-git/dist/src/lib/tasks/fetch.d.ts +4 -0
  108. package/dist/node_modules/simple-git/dist/src/lib/tasks/first-commit.d.ts +2 -0
  109. package/dist/node_modules/simple-git/dist/src/lib/tasks/grep.d.ts +12 -0
  110. package/dist/node_modules/simple-git/dist/src/lib/tasks/hash-object.d.ts +5 -0
  111. package/dist/node_modules/simple-git/dist/src/lib/tasks/init.d.ts +3 -0
  112. package/dist/node_modules/simple-git/dist/src/lib/tasks/log.d.ts +32 -0
  113. package/dist/node_modules/simple-git/dist/src/lib/tasks/merge.d.ts +4 -0
  114. package/dist/node_modules/simple-git/dist/src/lib/tasks/move.d.ts +3 -0
  115. package/dist/node_modules/simple-git/dist/src/lib/tasks/pull.d.ts +3 -0
  116. package/dist/node_modules/simple-git/dist/src/lib/tasks/push.d.ts +9 -0
  117. package/dist/node_modules/simple-git/dist/src/lib/tasks/remote.d.ts +8 -0
  118. package/dist/node_modules/simple-git/dist/src/lib/tasks/reset.d.ts +11 -0
  119. package/dist/node_modules/simple-git/dist/src/lib/tasks/show.d.ts +2 -0
  120. package/dist/node_modules/simple-git/dist/src/lib/tasks/stash-list.d.ts +4 -0
  121. package/dist/node_modules/simple-git/dist/src/lib/tasks/status.d.ts +3 -0
  122. package/dist/node_modules/simple-git/dist/src/lib/tasks/sub-module.d.ts +5 -0
  123. package/dist/node_modules/simple-git/dist/src/lib/tasks/tag.d.ts +18 -0
  124. package/dist/node_modules/simple-git/dist/src/lib/tasks/task.d.ts +14 -0
  125. package/dist/node_modules/simple-git/dist/src/lib/tasks/version.d.ts +9 -0
  126. package/dist/node_modules/simple-git/dist/src/lib/types/handlers.d.ts +21 -0
  127. package/dist/node_modules/simple-git/dist/src/lib/types/index.d.ts +136 -0
  128. package/dist/node_modules/simple-git/dist/src/lib/types/tasks.d.ts +19 -0
  129. package/dist/node_modules/simple-git/dist/src/lib/utils/argument-filters.d.ts +14 -0
  130. package/dist/node_modules/simple-git/dist/src/lib/utils/exit-codes.d.ts +10 -0
  131. package/dist/node_modules/simple-git/dist/src/lib/utils/git-output-streams.d.ts +7 -0
  132. package/dist/node_modules/simple-git/dist/src/lib/utils/index.d.ts +8 -0
  133. package/dist/node_modules/simple-git/dist/src/lib/utils/line-parser.d.ts +15 -0
  134. package/dist/node_modules/simple-git/dist/src/lib/utils/simple-git-options.d.ts +2 -0
  135. package/dist/node_modules/simple-git/dist/src/lib/utils/task-options.d.ts +13 -0
  136. package/dist/node_modules/simple-git/dist/src/lib/utils/task-parser.d.ts +5 -0
  137. package/dist/node_modules/simple-git/dist/src/lib/utils/util.d.ts +47 -0
  138. package/dist/node_modules/simple-git/dist/typings/errors.d.ts +5 -0
  139. package/dist/node_modules/simple-git/dist/typings/index.d.ts +14 -0
  140. package/dist/node_modules/simple-git/dist/typings/response.d.ts +556 -0
  141. package/dist/node_modules/simple-git/dist/typings/simple-git.d.ts +1033 -0
  142. package/dist/node_modules/simple-git/dist/typings/types.d.ts +22 -0
  143. package/dist/node_modules/simple-git/node_modules/debug/package.json +64 -0
  144. package/dist/node_modules/simple-git/node_modules/debug/src/browser.js +272 -0
  145. package/dist/node_modules/simple-git/node_modules/debug/src/common.js +292 -0
  146. package/dist/node_modules/simple-git/node_modules/debug/src/index.js +10 -0
  147. package/dist/node_modules/simple-git/node_modules/debug/src/node.js +263 -0
  148. package/dist/node_modules/simple-git/package.json +1 -0
  149. package/dist/node_modules/simple-git/promise.js +17 -0
  150. package/dist/server/collections/agent-execution-spans.d.ts +9 -0
  151. package/dist/server/collections/agent-execution-spans.js +152 -0
  152. package/dist/server/collections/orchestrator-config.js +6 -0
  153. package/dist/server/collections/skill-definitions.d.ts +3 -0
  154. package/dist/server/collections/skill-definitions.js +158 -0
  155. package/dist/server/collections/skill-executions.d.ts +3 -0
  156. package/dist/server/collections/skill-executions.js +123 -0
  157. package/dist/server/collections/skill-worker-configs.d.ts +3 -0
  158. package/dist/server/collections/skill-worker-configs.js +115 -0
  159. package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +4 -0
  160. package/dist/server/migrations/20260423000000-add-progress-fields.js +69 -0
  161. package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +4 -0
  162. package/dist/server/migrations/20260425000000-add-interaction-schema.js +61 -0
  163. package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +4 -0
  164. package/dist/server/migrations/20260427000000-change-packages-to-text.js +70 -0
  165. package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +4 -0
  166. package/dist/server/migrations/20260427000001-change-other-json-to-text.js +80 -0
  167. package/dist/server/migrations/20260429000000-add-llm-fields.js +8 -0
  168. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +16 -0
  169. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.js +51 -0
  170. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +7 -0
  171. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.js +57 -0
  172. package/dist/server/plugin.d.ts +3 -0
  173. package/dist/server/plugin.js +37 -1
  174. package/dist/server/resources/tracing.js +154 -11
  175. package/dist/server/services/CodeValidator.d.ts +32 -0
  176. package/dist/server/services/CodeValidator.js +205 -0
  177. package/dist/server/services/ExecutionSpanService.d.ts +44 -0
  178. package/dist/server/services/ExecutionSpanService.js +104 -0
  179. package/dist/server/services/FileManager.d.ts +28 -0
  180. package/dist/server/services/FileManager.js +151 -0
  181. package/dist/server/services/SandboxRunner.d.ts +41 -0
  182. package/dist/server/services/SandboxRunner.js +167 -0
  183. package/dist/server/services/SkillManager.d.ts +6 -0
  184. package/dist/server/services/SkillManager.js +640 -0
  185. package/dist/server/services/SkillRepositoryService.d.ts +22 -0
  186. package/dist/server/services/SkillRepositoryService.js +157 -0
  187. package/dist/server/services/WorkerEnvManager.d.ts +26 -0
  188. package/dist/server/services/WorkerEnvManager.js +120 -0
  189. package/dist/server/skill-hub/actions/git-import.d.ts +21 -0
  190. package/dist/server/skill-hub/actions/git-import.js +413 -0
  191. package/dist/server/skill-hub/mcp/McpController.d.ts +15 -0
  192. package/dist/server/skill-hub/mcp/McpController.js +111 -0
  193. package/dist/server/skill-hub/plugin.d.ts +58 -0
  194. package/dist/server/skill-hub/plugin.js +694 -0
  195. package/dist/server/skill-hub/sandbox-config.json +6 -0
  196. package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +14 -0
  197. package/dist/server/skill-hub/tasks/SkillExecutionTask.js +267 -0
  198. package/dist/server/skill-hub/utils/json-fields.d.ts +7 -0
  199. package/dist/server/skill-hub/utils/json-fields.js +88 -0
  200. package/dist/server/tools/delegate-task.d.ts +4 -0
  201. package/dist/server/tools/delegate-task.js +606 -104
  202. package/dist/server/tools/skill-execute.d.ts +36 -0
  203. package/dist/server/tools/skill-execute.js +167 -0
  204. package/package.json +3 -1
  205. package/src/client/AIEmployeeSelect.tsx +1 -3
  206. package/src/client/AIEmployeesContext.tsx +28 -13
  207. package/src/client/OrchestratorSettings.tsx +43 -5
  208. package/src/client/RulesTab.tsx +253 -32
  209. package/src/client/TracingTab.tsx +277 -213
  210. package/src/client/plugin.tsx +39 -0
  211. package/src/client/skill-hub/components/ExecutionHistory.tsx +201 -0
  212. package/src/client/skill-hub/components/ExecutionProgress.tsx +55 -0
  213. package/src/client/skill-hub/components/GitSkillImport.tsx +555 -0
  214. package/src/client/skill-hub/components/SkillEditor.tsx +456 -0
  215. package/src/client/skill-hub/components/SkillManager.tsx +181 -0
  216. package/src/client/skill-hub/components/SkillMetrics.tsx +124 -0
  217. package/src/client/skill-hub/components/SkillTestPanel.tsx +144 -0
  218. package/src/client/skill-hub/index.tsx +75 -0
  219. package/src/client/skill-hub/locale.ts +16 -0
  220. package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +59 -0
  221. package/src/client/skill-hub/tools/SkillHubCard.tsx +78 -0
  222. package/src/client/skill-hub/utils/jsonFields.ts +37 -0
  223. package/src/server/collections/agent-execution-spans.ts +129 -0
  224. package/src/server/collections/orchestrator-config.ts +7 -0
  225. package/src/server/collections/skill-definitions.ts +128 -0
  226. package/src/server/collections/skill-executions.ts +94 -0
  227. package/src/server/collections/skill-worker-configs.ts +86 -0
  228. package/src/server/migrations/20260423000000-add-progress-fields.ts +50 -0
  229. package/src/server/migrations/20260425000000-add-interaction-schema.ts +35 -0
  230. package/src/server/migrations/20260427000000-change-packages-to-text.ts +47 -0
  231. package/src/server/migrations/20260427000001-change-other-json-to-text.ts +57 -0
  232. package/src/server/migrations/20260429000000-add-llm-fields.ts +9 -0
  233. package/src/server/migrations/20260429000000-fix-inputargs-json-to-text.ts +38 -0
  234. package/src/server/migrations/20260503000000-add-orchestrator-trace-fields.ts +32 -0
  235. package/src/server/plugin.ts +51 -3
  236. package/src/server/resources/tracing.ts +182 -15
  237. package/src/server/services/CodeValidator.ts +159 -0
  238. package/src/server/services/ExecutionSpanService.ts +106 -0
  239. package/src/server/services/FileManager.ts +144 -0
  240. package/src/server/services/SandboxRunner.ts +205 -0
  241. package/src/server/services/SkillManager.ts +623 -0
  242. package/src/server/services/SkillRepositoryService.ts +142 -0
  243. package/src/server/services/WorkerEnvManager.ts +113 -0
  244. package/src/server/skill-hub/actions/git-import.ts +486 -0
  245. package/src/server/skill-hub/mcp/McpController.ts +86 -0
  246. package/src/server/skill-hub/plugin.ts +771 -0
  247. package/src/server/skill-hub/sandbox-config.json +6 -0
  248. package/src/server/skill-hub/tasks/SkillExecutionTask.ts +297 -0
  249. package/src/server/skill-hub/utils/json-fields.ts +57 -0
  250. package/src/server/tools/delegate-task.ts +803 -127
  251. package/src/server/tools/skill-execute.ts +157 -0
@@ -15,16 +15,32 @@ import {
15
15
  Alert,
16
16
  Collapse,
17
17
  Empty,
18
- Input,
19
18
  Select,
20
19
  } from 'antd';
21
- import { PlusOutlined, EditOutlined, DeleteOutlined, SwapRightOutlined } from '@ant-design/icons';
20
+ import {
21
+ PlusOutlined,
22
+ EditOutlined,
23
+ DeleteOutlined,
24
+ SwapRightOutlined,
25
+ WarningOutlined,
26
+ ThunderboltOutlined,
27
+ } from '@ant-design/icons';
22
28
  import { useAPIClient, useRequest } from '@nocobase/client';
23
29
  import { AIEmployeeSelect } from './AIEmployeeSelect';
24
30
  import { useAIEmployees } from './AIEmployeesContext';
25
31
 
26
32
  const { Text } = Typography;
27
33
 
34
+ /**
35
+ * Mirrors server-side `sanitizeToolPart` in delegate-task.ts so we can compute
36
+ * the expected delegation tool names here and detect when the leader hasn't
37
+ * added them to its skillSettings.
38
+ */
39
+ const sanitizeToolPart = (value: string) => (value || '').replace(/[^a-zA-Z0-9_-]/g, '_');
40
+ const expectedDelegateToolName = (leader: string, sub: string) =>
41
+ `delegate_${sanitizeToolPart(leader)}_to_${sanitizeToolPart(sub)}`;
42
+ const expectedDispatchToolName = (leader: string) => `dispatch_subagents_${sanitizeToolPart(leader)}`;
43
+
28
44
  export const RulesTab: React.FC = () => {
29
45
  const api = useAPIClient();
30
46
  const [visible, setVisible] = useState(false);
@@ -39,31 +55,91 @@ export const RulesTab: React.FC = () => {
39
55
  });
40
56
 
41
57
  const { data: llmServicesData, loading: llmLoading } = useRequest({
42
- url: 'llmServices:list',
43
- params: {
44
- filter: { enabled: true },
45
- },
58
+ url: 'ai:listAllEnabledModels',
46
59
  });
47
60
 
48
61
  const llmServices = React.useMemo(() => {
49
- return (llmServicesData as any)?.data || [];
62
+ const raw = (llmServicesData as any)?.data ?? llmServicesData;
63
+ if (Array.isArray(raw)) return raw;
64
+ return Array.isArray(raw?.data) ? raw.data : [];
50
65
  }, [llmServicesData]);
51
66
 
52
67
  // P3 FIX: Use shared context instead of duplicate API call
53
- const { employeeMap } = useAIEmployees();
68
+ const { employeeMap, skillsMap, refresh: refreshEmployees } = useAIEmployees();
54
69
  const rules = React.useMemo(() => {
55
70
  const rows = (data as any)?.data;
56
71
  return Array.isArray(rows) ? rows : [];
57
72
  }, [data]);
58
73
 
74
+ const handleAddSkillToEmployee = async (employeeUsername: string, toolName: string) => {
75
+ try {
76
+ // Re-fetch the leader to merge its current skills (skillsMap may be stale).
77
+ const leaderResp = await api.request({
78
+ url: 'aiEmployees:get',
79
+ params: { filterByTk: employeeUsername },
80
+ });
81
+ const leader = (leaderResp as any)?.data?.data;
82
+ if (!leader) {
83
+ message.error('Could not load AI employee.');
84
+ return;
85
+ }
86
+ const existing = Array.isArray(leader.skillSettings?.skills) ? leader.skillSettings.skills : [];
87
+ if (existing.some((s: any) => (typeof s === 'string' ? s : s?.name) === toolName)) {
88
+ message.info('Skill already present.');
89
+ await refreshEmployees();
90
+ return;
91
+ }
92
+ const nextSkills = [...existing, { name: toolName, autoCall: false }];
93
+ await api.request({
94
+ url: 'aiEmployees:update',
95
+ method: 'put',
96
+ params: { filterByTk: employeeUsername },
97
+ data: { skillSettings: { ...(leader.skillSettings || {}), skills: nextSkills } },
98
+ });
99
+ message.success(`Added "${toolName}" to ${employeeUsername}'s skills.`);
100
+ await refreshEmployees();
101
+ } catch (e: any) {
102
+ message.error(`Auto-assign failed: ${e?.message || 'unknown error'}`);
103
+ }
104
+ };
105
+
106
+ const handleAutoAssignSkill = async (record: any) => {
107
+ await handleAddSkillToEmployee(
108
+ record.leaderUsername,
109
+ expectedDelegateToolName(record.leaderUsername, record.subAgentUsername),
110
+ );
111
+ };
112
+
113
+ const handleAutoAssignDispatchSkill = async (leaderUsername: string) => {
114
+ await handleAddSkillToEmployee(leaderUsername, expectedDispatchToolName(leaderUsername));
115
+ };
116
+
117
+ const subAgentLeaderCount = React.useMemo(() => {
118
+ const counts = new Map<string, Set<string>>();
119
+ for (const rule of rules) {
120
+ const set = counts.get(rule.subAgentUsername) || new Set<string>();
121
+ set.add(rule.leaderUsername);
122
+ counts.set(rule.subAgentUsername, set);
123
+ }
124
+ return counts;
125
+ }, [rules]);
126
+
127
+ const aliasConflicts = React.useMemo(() => {
128
+ return Array.from(subAgentLeaderCount.entries())
129
+ .filter(([, leaders]) => leaders.size > 1)
130
+ .map(([sub, leaders]) => ({ sub, leaders: Array.from(leaders) }));
131
+ }, [subAgentLeaderCount]);
132
+
59
133
  const groupedRules = React.useMemo(() => {
60
134
  const groups = new Map<string, any[]>();
61
135
  for (const rule of rules) {
62
136
  const key = rule.leaderUsername || 'unknown';
63
- if (!groups.has(key)) {
64
- groups.set(key, []);
137
+ let items = groups.get(key);
138
+ if (!items) {
139
+ items = [];
140
+ groups.set(key, items);
65
141
  }
66
- groups.get(key)!.push(rule);
142
+ items.push(rule);
67
143
  }
68
144
 
69
145
  return Array.from(groups.entries()).map(([leaderUsername, items]) => ({
@@ -78,7 +154,7 @@ export const RulesTab: React.FC = () => {
78
154
  form.setFieldsValue(record);
79
155
  } else {
80
156
  form.resetFields();
81
- form.setFieldsValue({ enabled: true, maxDepth: 1, timeout: 120000 });
157
+ form.setFieldsValue({ enabled: true, maxDepth: 1, timeout: 120000, recursionLimit: 50 });
82
158
  }
83
159
  setVisible(true);
84
160
  };
@@ -139,9 +215,7 @@ export const RulesTab: React.FC = () => {
139
215
  title: 'Leader (Orchestrator)',
140
216
  dataIndex: 'leaderUsername',
141
217
  key: 'leaderUsername',
142
- render: (username: string) => (
143
- <Tag color="blue">{employeeMap.get(username) || username}</Tag>
144
- ),
218
+ render: (username: string) => <Tag color="blue">{employeeMap.get(username) || username}</Tag>,
145
219
  },
146
220
  {
147
221
  title: '',
@@ -153,9 +227,7 @@ export const RulesTab: React.FC = () => {
153
227
  title: 'Sub-Agent',
154
228
  dataIndex: 'subAgentUsername',
155
229
  key: 'subAgentUsername',
156
- render: (username: string) => (
157
- <Tag color="green">{employeeMap.get(username) || username}</Tag>
158
- ),
230
+ render: (username: string) => <Tag color="green">{employeeMap.get(username) || username}</Tag>,
159
231
  },
160
232
  {
161
233
  title: 'Max Depth',
@@ -177,16 +249,22 @@ export const RulesTab: React.FC = () => {
177
249
  width: 140,
178
250
  render: (_: any, record: any) => {
179
251
  if (record.llmService && record.model) {
180
- const svc = llmServices.find((s: any) => s.name === record.llmService);
181
- const svcName = svc ? svc.title : record.llmService;
252
+ const svc = llmServices.find((s: any) => s.llmService === record.llmService);
253
+ const svcName = svc ? svc.llmServiceTitle : record.llmService;
182
254
  return (
183
255
  <Space direction="vertical" size={0}>
184
256
  <Text style={{ fontSize: 12 }}>{svcName}</Text>
185
- <Text type="secondary" style={{ fontSize: 12 }}>{record.model}</Text>
257
+ <Text type="secondary" style={{ fontSize: 12 }}>
258
+ {record.model}
259
+ </Text>
186
260
  </Space>
187
261
  );
188
262
  }
189
- return <Text type="secondary" style={{ fontSize: 12 }}>Inherited</Text>;
263
+ return (
264
+ <Text type="secondary" style={{ fontSize: 12 }}>
265
+ Inherited
266
+ </Text>
267
+ );
190
268
  },
191
269
  },
192
270
  {
@@ -210,6 +288,41 @@ export const RulesTab: React.FC = () => {
210
288
  />
211
289
  ),
212
290
  },
291
+ {
292
+ title: 'Skill',
293
+ key: 'skill',
294
+ width: 150,
295
+ render: (_: any, record: any) => {
296
+ const expected = expectedDelegateToolName(record.leaderUsername, record.subAgentUsername);
297
+ const leaderSkills = skillsMap.get(record.leaderUsername);
298
+ if (!leaderSkills) {
299
+ return (
300
+ <Text type="secondary" style={{ fontSize: 12 }}>
301
+
302
+ </Text>
303
+ );
304
+ }
305
+ const present = leaderSkills.has(expected);
306
+ if (present) {
307
+ return <Tag color="success">Assigned</Tag>;
308
+ }
309
+ return (
310
+ <Space size={4}>
311
+ <Tag icon={<WarningOutlined />} color="warning">
312
+ Missing
313
+ </Tag>
314
+ <Button
315
+ type="link"
316
+ size="small"
317
+ icon={<ThunderboltOutlined />}
318
+ onClick={() => handleAutoAssignSkill(record)}
319
+ >
320
+ Auto-add
321
+ </Button>
322
+ </Space>
323
+ );
324
+ },
325
+ },
213
326
  {
214
327
  title: 'Actions',
215
328
  key: 'actions',
@@ -231,6 +344,28 @@ export const RulesTab: React.FC = () => {
231
344
 
232
345
  const leaderUsername = Form.useWatch('leaderUsername', form);
233
346
 
347
+ const missingSkillCount = React.useMemo(() => {
348
+ return rules.reduce((acc: number, r: any) => {
349
+ const leaderSkills = skillsMap.get(r.leaderUsername);
350
+ if (!leaderSkills) return acc;
351
+ const expected = expectedDelegateToolName(r.leaderUsername, r.subAgentUsername);
352
+ return leaderSkills.has(expected) ? acc : acc + 1;
353
+ }, 0);
354
+ }, [rules, skillsMap]);
355
+
356
+ const missingDispatchSkills = React.useMemo(() => {
357
+ return groupedRules
358
+ .map((group) => {
359
+ const leaderSkills = skillsMap.get(group.leaderUsername);
360
+ if (!leaderSkills) return null;
361
+ const toolName = expectedDispatchToolName(group.leaderUsername);
362
+ return leaderSkills.has(toolName)
363
+ ? null
364
+ : { leaderUsername: group.leaderUsername, toolName, count: group.items.length };
365
+ })
366
+ .filter(Boolean) as Array<{ leaderUsername: string; toolName: string; count: number }>;
367
+ }, [groupedRules, skillsMap]);
368
+
234
369
  return (
235
370
  <div>
236
371
  <Alert
@@ -246,6 +381,79 @@ export const RulesTab: React.FC = () => {
246
381
  }
247
382
  />
248
383
 
384
+ {missingSkillCount > 0 && (
385
+ <Alert
386
+ type="warning"
387
+ showIcon
388
+ style={{ marginBottom: 16 }}
389
+ message={`${missingSkillCount} rule${missingSkillCount > 1 ? 's' : ''} missing required skill assignment`}
390
+ description={
391
+ <Text type="secondary">
392
+ The Leader employee hasn&apos;t added the corresponding{' '}
393
+ <Text code>delegate_&lt;leader&gt;_to_&lt;sub&gt;</Text> tool to its skillSettings, so the LLM cannot
394
+ actually call these sub-agents. Use the <b>Auto-add</b> button in the Skill column to fix.
395
+ </Text>
396
+ }
397
+ />
398
+ )}
399
+
400
+ {missingDispatchSkills.length > 0 && (
401
+ <Alert
402
+ type="warning"
403
+ showIcon
404
+ style={{ marginBottom: 16 }}
405
+ message={`${missingDispatchSkills.length} leader${
406
+ missingDispatchSkills.length > 1 ? 's' : ''
407
+ } missing dispatch skill assignment`}
408
+ description={
409
+ <Space direction="vertical" size={6}>
410
+ <Text type="secondary">
411
+ The fan-out tool lets a Leader dispatch multiple independent sub-tasks in one call. Add it to the
412
+ Leader&apos;s skills to enable the new multi-agent flow.
413
+ </Text>
414
+ {missingDispatchSkills.map(({ leaderUsername, toolName, count }) => (
415
+ <Space key={leaderUsername} size={8} wrap>
416
+ <Tag color="blue">{employeeMap.get(leaderUsername) || leaderUsername}</Tag>
417
+ <Text type="secondary">
418
+ {count} sub-agent{count > 1 ? 's' : ''}
419
+ </Text>
420
+ <Text code>{toolName}</Text>
421
+ <Button
422
+ type="link"
423
+ size="small"
424
+ icon={<ThunderboltOutlined />}
425
+ onClick={() => handleAutoAssignDispatchSkill(leaderUsername)}
426
+ >
427
+ Auto-add
428
+ </Button>
429
+ </Space>
430
+ ))}
431
+ </Space>
432
+ }
433
+ />
434
+ )}
435
+
436
+ {aliasConflicts.length > 0 && (
437
+ <Alert
438
+ type="warning"
439
+ showIcon
440
+ style={{ marginBottom: 16 }}
441
+ message="Legacy delegate_to_<sub> alias is no longer registered for these sub-agents"
442
+ description={
443
+ <Space direction="vertical" size={2}>
444
+ {aliasConflicts.map(({ sub, leaders }) => (
445
+ <Text key={sub} type="secondary">
446
+ <Tag color="green">{employeeMap.get(sub) || sub}</Tag>
447
+ has multiple leaders ({leaders.map((l) => employeeMap.get(l) || l).join(', ')}). The legacy alias is
448
+ dropped to avoid ambiguity — leaders must use <Text code>delegate_&lt;leader&gt;_to_&lt;sub&gt;</Text>{' '}
449
+ in their skills.
450
+ </Text>
451
+ ))}
452
+ </Space>
453
+ }
454
+ />
455
+ )}
456
+
249
457
  <Card bordered={false}>
250
458
  <div style={{ marginBottom: 16, display: 'flex', justifyContent: 'flex-end' }}>
251
459
  <Button type="primary" icon={<PlusOutlined />} onClick={() => handleOpen()}>
@@ -261,7 +469,12 @@ export const RulesTab: React.FC = () => {
261
469
  label: (
262
470
  <Space>
263
471
  <Tag color="blue">{employeeMap.get(group.leaderUsername) || group.leaderUsername}</Tag>
264
- <Text type="secondary">{group.items.length} sub-agent{group.items.length > 1 ? 's' : ''}</Text>
472
+ <Text type="secondary">
473
+ {group.items.length} sub-agent{group.items.length > 1 ? 's' : ''}
474
+ </Text>
475
+ {missingDispatchSkills.some((item) => item.leaderUsername === group.leaderUsername) && (
476
+ <Tag color="warning">Dispatch missing</Tag>
477
+ )}
265
478
  </Space>
266
479
  ),
267
480
  children: (
@@ -320,10 +533,7 @@ export const RulesTab: React.FC = () => {
320
533
  rules={[{ required: true, message: 'Please select a Sub-Agent' }]}
321
534
  tooltip="The AI Employee that will receive delegated tasks"
322
535
  >
323
- <AIEmployeeSelect
324
- placeholder="Select Sub-Agent AI Employee..."
325
- exclude={leaderUsername}
326
- />
536
+ <AIEmployeeSelect placeholder="Select Sub-Agent AI Employee..." exclude={leaderUsername} />
327
537
  </Form.Item>
328
538
 
329
539
  <Form.Item
@@ -342,6 +552,14 @@ export const RulesTab: React.FC = () => {
342
552
  <InputNumber min={10000} max={600000} step={10000} style={{ width: '100%' }} />
343
553
  </Form.Item>
344
554
 
555
+ <Form.Item
556
+ name="recursionLimit"
557
+ label="Recursion Limit"
558
+ tooltip="Max LangGraph reasoning steps per delegation. Higher = more complex multi-step tasks; lower = stricter cap on token usage. Default 50."
559
+ >
560
+ <InputNumber min={5} max={200} step={5} style={{ width: '100%' }} />
561
+ </Form.Item>
562
+
345
563
  <Form.Item
346
564
  name="llmService"
347
565
  label="Override LLM Service"
@@ -350,9 +568,10 @@ export const RulesTab: React.FC = () => {
350
568
  <Select
351
569
  allowClear
352
570
  placeholder="Inherit from Leader"
571
+ loading={llmLoading}
353
572
  options={llmServices.map((svc: any) => ({
354
- label: svc.title || svc.name,
355
- value: svc.name,
573
+ label: svc.llmServiceTitle || svc.llmService,
574
+ value: svc.llmService,
356
575
  }))}
357
576
  onChange={() => form.setFieldValue('model', undefined)}
358
577
  />
@@ -364,9 +583,11 @@ export const RulesTab: React.FC = () => {
364
583
  >
365
584
  {() => {
366
585
  const selectedServiceId = form.getFieldValue('llmService');
367
- const selectedService = llmServices.find((s: any) => s.name === selectedServiceId);
368
- const availableModels = selectedService?.enabledModels?.models || [];
369
-
586
+ const selectedService = llmServices.find((s: any) => s.llmService === selectedServiceId);
587
+ const availableModels = Array.isArray(selectedService?.enabledModels)
588
+ ? selectedService.enabledModels
589
+ : [];
590
+
370
591
  return (
371
592
  <Form.Item
372
593
  name="model"