plugin-agent-orchestrator 1.0.20 → 1.0.22

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 (158) hide show
  1. package/dist/client/index.js +1 -1
  2. package/dist/externalVersion.js +6 -6
  3. package/dist/server/collections/agent-execution-spans.js +24 -0
  4. package/dist/server/collections/agent-loop-runs.js +36 -0
  5. package/dist/server/collections/orchestrator-config.js +14 -0
  6. package/dist/server/migrations/20260601000000-add-token-fields.js +101 -0
  7. package/dist/server/plugin.js +56 -0
  8. package/dist/server/resources/agent-loop.js +33 -25
  9. package/dist/server/resources/tracing.js +5 -8
  10. package/dist/server/services/AgentHarness.js +56 -90
  11. package/dist/server/services/AgentLoopController.js +164 -125
  12. package/dist/server/services/AgentLoopRepository.js +16 -34
  13. package/dist/server/services/AgentLoopService.js +7 -1
  14. package/dist/server/services/AgentPlannerService.js +5 -25
  15. package/dist/server/services/AgentRegistryService.js +34 -24
  16. package/dist/server/services/CircuitBreaker.js +120 -0
  17. package/dist/server/services/ContextAggregator.js +201 -0
  18. package/dist/server/services/ExecutionSpanService.js +2 -5
  19. package/dist/server/services/RunEventBus.js +73 -0
  20. package/dist/server/services/TokenTracker.js +173 -0
  21. package/dist/server/tools/agent-loop.js +30 -63
  22. package/dist/server/tools/delegate-task.js +14 -72
  23. package/dist/server/tools/orchestrator-plan.js +10 -47
  24. package/dist/server/types.js +24 -0
  25. package/dist/server/utils/ctx-utils.js +152 -0
  26. package/dist/server/utils/logging.js +86 -0
  27. package/package.json +44 -44
  28. package/src/client/AgentRunsTab.tsx +764 -764
  29. package/src/client/HarnessProfilesTab.tsx +247 -247
  30. package/src/client/OrchestratorSettings.tsx +106 -106
  31. package/src/client/RulesTab.tsx +716 -716
  32. package/src/client/hooks/useRunEventStream.ts +76 -0
  33. package/src/client/index.tsx +2 -1
  34. package/src/client/plugin.tsx +27 -27
  35. package/src/client/skill-hub/components/LoopSettings.tsx +331 -331
  36. package/src/client/skill-hub/index.tsx +51 -51
  37. package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +99 -99
  38. package/src/client/skill-hub/tools/SkillHubCard.tsx +109 -109
  39. package/src/client/skill-hub/tools/loopTemplates.ts +52 -52
  40. package/src/client/skill-hub/tools/registerSkillLoopCards.ts +58 -58
  41. package/src/client/tools/PlanApprovalCard.tsx +175 -175
  42. package/src/client/tools/registerOrchestratorCards.ts +7 -7
  43. package/src/server/__tests__/agent-loop-controller.test.ts +375 -0
  44. package/src/server/__tests__/circuit-breaker.test.ts +169 -0
  45. package/src/server/__tests__/context-aggregator.test.ts +222 -0
  46. package/src/server/__tests__/parallel-execution.test.ts +318 -0
  47. package/src/server/__tests__/smoke.test.ts +120 -0
  48. package/src/server/collections/agent-execution-spans.ts +24 -0
  49. package/src/server/collections/agent-harness-profiles.ts +59 -59
  50. package/src/server/collections/agent-loop-events.ts +71 -71
  51. package/src/server/collections/agent-loop-runs.ts +38 -1
  52. package/src/server/collections/agent-loop-steps.ts +144 -144
  53. package/src/server/collections/orchestrator-config.ts +14 -0
  54. package/src/server/collections/skill-executions.ts +106 -106
  55. package/src/server/collections/skill-loop-configs.ts +65 -65
  56. package/src/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.ts +30 -30
  57. package/src/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.ts +142 -142
  58. package/src/server/migrations/20260601000000-add-token-fields.ts +89 -0
  59. package/src/server/plugin.ts +68 -0
  60. package/src/server/resources/agent-loop.ts +21 -12
  61. package/src/server/resources/tracing.ts +3 -7
  62. package/src/server/services/AgentHarness.ts +78 -116
  63. package/src/server/services/AgentLoopController.ts +197 -122
  64. package/src/server/services/AgentLoopRepository.ts +9 -25
  65. package/src/server/services/AgentLoopService.ts +13 -1
  66. package/src/server/services/AgentPlanValidator.ts +73 -73
  67. package/src/server/services/AgentPlannerService.ts +2 -25
  68. package/src/server/services/AgentRegistryService.ts +40 -31
  69. package/src/server/services/CircuitBreaker.ts +116 -0
  70. package/src/server/services/ContextAggregator.ts +239 -0
  71. package/src/server/services/ExecutionSpanService.ts +2 -4
  72. package/src/server/services/RunEventBus.ts +45 -0
  73. package/src/server/services/TokenTracker.ts +209 -0
  74. package/src/server/skill-hub/plugin.ts +898 -898
  75. package/src/server/skill-hub/tasks/SkillExecutionTask.ts +460 -460
  76. package/src/server/tools/agent-loop.ts +18 -57
  77. package/src/server/tools/delegate-task.ts +11 -93
  78. package/src/server/tools/orchestrator-plan.ts +26 -50
  79. package/src/server/tools/skill-execute.ts +160 -160
  80. package/src/server/types.ts +55 -0
  81. package/src/server/utils/ctx-utils.ts +118 -0
  82. package/src/server/utils/logging.ts +63 -0
  83. package/dist/client/AIEmployeeSelect.d.ts +0 -11
  84. package/dist/client/AIEmployeesContext.d.ts +0 -30
  85. package/dist/client/AgentRunsTab.d.ts +0 -2
  86. package/dist/client/HarnessProfilesTab.d.ts +0 -2
  87. package/dist/client/OrchestratorSettings.d.ts +0 -3
  88. package/dist/client/RulesTab.d.ts +0 -2
  89. package/dist/client/TracingTab.d.ts +0 -2
  90. package/dist/client/index.d.ts +0 -1
  91. package/dist/client/plugin.d.ts +0 -6
  92. package/dist/client/skill-hub/components/ExecutionHistory.d.ts +0 -2
  93. package/dist/client/skill-hub/components/ExecutionProgress.d.ts +0 -20
  94. package/dist/client/skill-hub/components/GitSkillImport.d.ts +0 -7
  95. package/dist/client/skill-hub/components/LoopSettings.d.ts +0 -2
  96. package/dist/client/skill-hub/components/SkillEditor.d.ts +0 -7
  97. package/dist/client/skill-hub/components/SkillManager.d.ts +0 -2
  98. package/dist/client/skill-hub/components/SkillMetrics.d.ts +0 -2
  99. package/dist/client/skill-hub/components/SkillTestPanel.d.ts +0 -7
  100. package/dist/client/skill-hub/index.d.ts +0 -11
  101. package/dist/client/skill-hub/locale.d.ts +0 -3
  102. package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +0 -6
  103. package/dist/client/skill-hub/tools/SkillHubCard.d.ts +0 -3
  104. package/dist/client/skill-hub/tools/loopTemplates.d.ts +0 -22
  105. package/dist/client/skill-hub/tools/registerSkillLoopCards.d.ts +0 -1
  106. package/dist/client/skill-hub/utils/jsonFields.d.ts +0 -3
  107. package/dist/client/tools/PlanApprovalCard.d.ts +0 -3
  108. package/dist/client/tools/registerOrchestratorCards.d.ts +0 -1
  109. package/dist/index.d.ts +0 -2
  110. package/dist/server/collections/agent-execution-spans.d.ts +0 -9
  111. package/dist/server/collections/agent-harness-profiles.d.ts +0 -2
  112. package/dist/server/collections/agent-loop-events.d.ts +0 -2
  113. package/dist/server/collections/agent-loop-runs.d.ts +0 -2
  114. package/dist/server/collections/agent-loop-steps.d.ts +0 -2
  115. package/dist/server/collections/orchestrator-config.d.ts +0 -2
  116. package/dist/server/collections/orchestrator-logs.d.ts +0 -8
  117. package/dist/server/collections/skill-definitions.d.ts +0 -3
  118. package/dist/server/collections/skill-executions.d.ts +0 -3
  119. package/dist/server/collections/skill-loop-configs.d.ts +0 -3
  120. package/dist/server/collections/skill-worker-configs.d.ts +0 -3
  121. package/dist/server/index.d.ts +0 -1
  122. package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +0 -4
  123. package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +0 -4
  124. package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +0 -7
  125. package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +0 -4
  126. package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +0 -4
  127. package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +0 -7
  128. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +0 -16
  129. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +0 -7
  130. package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.d.ts +0 -7
  131. package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.d.ts +0 -12
  132. package/dist/server/plugin.d.ts +0 -16
  133. package/dist/server/resources/agent-loop.d.ts +0 -3
  134. package/dist/server/resources/tracing.d.ts +0 -7
  135. package/dist/server/services/AgentHarness.d.ts +0 -42
  136. package/dist/server/services/AgentLoopController.d.ts +0 -205
  137. package/dist/server/services/AgentLoopRepository.d.ts +0 -20
  138. package/dist/server/services/AgentLoopService.d.ts +0 -149
  139. package/dist/server/services/AgentPlanValidator.d.ts +0 -4
  140. package/dist/server/services/AgentPlannerService.d.ts +0 -8
  141. package/dist/server/services/AgentRegistryService.d.ts +0 -13
  142. package/dist/server/services/CodeValidator.d.ts +0 -32
  143. package/dist/server/services/ExecutionSpanService.d.ts +0 -46
  144. package/dist/server/services/FileManager.d.ts +0 -28
  145. package/dist/server/services/SandboxRunner.d.ts +0 -41
  146. package/dist/server/services/SkillManager.d.ts +0 -6
  147. package/dist/server/services/SkillRepositoryService.d.ts +0 -22
  148. package/dist/server/services/WorkerEnvManager.d.ts +0 -26
  149. package/dist/server/skill-hub/actions/git-import.d.ts +0 -21
  150. package/dist/server/skill-hub/mcp/McpController.d.ts +0 -15
  151. package/dist/server/skill-hub/plugin.d.ts +0 -61
  152. package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +0 -16
  153. package/dist/server/skill-hub/utils/json-fields.d.ts +0 -7
  154. package/dist/server/tools/agent-loop.d.ts +0 -235
  155. package/dist/server/tools/delegate-task.d.ts +0 -19
  156. package/dist/server/tools/external-rag-search.d.ts +0 -42
  157. package/dist/server/tools/orchestrator-plan.d.ts +0 -205
  158. package/dist/server/tools/skill-execute.d.ts +0 -36
@@ -1,160 +1,160 @@
1
- import { parseJsonText } from '../skill-hub/utils/json-fields';
2
-
3
- export function createSkillExecuteTool(plugin: any) {
4
- return {
5
- scope: 'CUSTOM',
6
- execution: 'backend',
7
- defaultPermission: 'ASK',
8
-
9
- introduction: {
10
- title: 'Skill Hub - Universal Skill Executor',
11
- about:
12
- 'A universal gateway to execute predefined specialized skills (data processing, complex calculations, file generation, etc.) inside a secure Python/Node.js sandbox.',
13
- },
14
-
15
- definition: {
16
- name: 'skill_hub_execute',
17
- description: `A universal gateway to execute various predefined specialized skills (e.g., data transformation, calculations, document/presentation generation) in an isolated sandbox.
18
- HOW TO USE THIS TOOL:
19
- 1. If you don't know the exact 'skillName' or its required 'input' schema, first call this tool with { "action": "list" } to discover all available skills.
20
- 2. For complex workflow skills, call { "action": "describe", "skillName": "<exact_skill_name>" } to load the full instructions before execution.
21
- 3. To run a skill, call this tool with { "action": "execute", "skillName": "<exact_skill_name>", "input": { <parameters> } }.
22
- CRITICAL: Do NOT guess or hallucinate the 'input' object. You MUST strictly provide the parameters matching the JSON schema defined for that specific skill.
23
- The skill's output may contain text results, structured JSON data, or download URLs for generated files.
24
- IMPORTANT: If the skill returns file download URLs, you MUST format them as clickable Markdown links (e.g., [Download filename.ext](/api/attachments/...)) in your final response to the user.`,
25
- schema: {
26
- type: 'object',
27
- properties: {
28
- action: {
29
- type: 'string',
30
- enum: ['list', 'describe', 'execute'],
31
- description: '"list" to see available skills, "describe" to load full instructions, "execute" to run one',
32
- },
33
- skillName: {
34
- type: 'string',
35
- description: 'Skill name (required for "execute" action)',
36
- },
37
- input: {
38
- type: 'object',
39
- description: 'Input parameters matching the skill inputSchema',
40
- },
41
- },
42
- required: ['action'],
43
- },
44
- },
45
-
46
- async invoke(ctx: any, args: Record<string, any>, _id?: string) {
47
- plugin.app.logger.info(`[skill-execute] Tool invoked with action: ${args.action}, skillName: ${args.skillName}`);
48
-
49
- // Action: list available skills
50
- if (args.action === 'list') {
51
- const skills = await plugin.db.getRepository('skillDefinitions').find({
52
- filter: { enabled: true },
53
- fields: ['name', 'title', 'description', 'language', 'inputSchema', 'instructions', 'storageType'],
54
- });
55
-
56
- const skillList = skills.map((s: any) => ({
57
- name: s.get('name'),
58
- title: s.get('title'),
59
- description: s.get('description'),
60
- language: s.get('language'),
61
- inputSchema: parseJsonText(s.get('inputSchema'), null),
62
- hasInstructions: !!s.get('instructions') || s.get('storageType') === 'plugin',
63
- storageType: s.get('storageType'),
64
- }));
65
-
66
- return {
67
- status: 'success',
68
- content: JSON.stringify({ skills: skillList }),
69
- };
70
- }
71
-
72
- // Action: describe one skill with full workflow instructions
73
- if (args.action === 'describe') {
74
- if (!args.skillName) {
75
- return { status: 'error', content: 'Missing skillName parameter' };
76
- }
77
-
78
- const skill = await plugin.db.getRepository('skillDefinitions').findOne({
79
- filter: { name: args.skillName, enabled: true },
80
- });
81
-
82
- if (!skill) {
83
- return {
84
- status: 'error',
85
- content: `Skill "${args.skillName}" not found or disabled`,
86
- };
87
- }
88
-
89
- const instructions =
90
- typeof plugin.getSkillInstructions === 'function'
91
- ? await plugin.getSkillInstructions(skill)
92
- : skill.get('instructions');
93
-
94
- return {
95
- status: 'success',
96
- content: JSON.stringify({
97
- name: skill.get('name'),
98
- title: skill.get('title'),
99
- description: skill.get('description'),
100
- language: skill.get('language'),
101
- inputSchema: parseJsonText(skill.get('inputSchema'), null),
102
- packages: parseJsonText(skill.get('packages'), []),
103
- storageType: skill.get('storageType'),
104
- storageUrl: skill.get('storageUrl'),
105
- instructions,
106
- }),
107
- };
108
- }
109
-
110
- // Action: execute skill
111
- if (args.action === 'execute') {
112
- if (!args.skillName) {
113
- return { status: 'error', content: 'Missing skillName parameter' };
114
- }
115
-
116
- const skill = await plugin.db.getRepository('skillDefinitions').findOne({
117
- filter: { name: args.skillName, enabled: true },
118
- });
119
-
120
- if (!skill) {
121
- return {
122
- status: 'error',
123
- content: `Skill "${args.skillName}" not found or disabled`,
124
- };
125
- }
126
-
127
- try {
128
- const result = await plugin.executeSkill(skill, args.input || {}, ctx);
129
-
130
- return {
131
- status: result.status === 'succeeded' ? 'success' : 'error',
132
- content: JSON.stringify({
133
- message:
134
- result.status === 'succeeded'
135
- ? `Executed successfully. ${result.files?.length || 0} file(s) generated.`
136
- : `Failed: ${result.stderr}`,
137
- stdout: result.stdout,
138
- stderr: result.stderr,
139
- files: result.files,
140
- execId: result.execId,
141
- agentLoopRunId: result.agentLoopRunId,
142
- agentLoopStepId: result.agentLoopStepId,
143
- durationMs: result.durationMs,
144
- }),
145
- };
146
- } catch (error) {
147
- return {
148
- status: 'error',
149
- content: `Execution error: ${error instanceof Error ? error.message : String(error)}`,
150
- };
151
- }
152
- }
153
-
154
- return {
155
- status: 'error',
156
- content: `Unknown action "${args.action}". Use "list", "describe", or "execute".`,
157
- };
158
- },
159
- };
160
- }
1
+ import { parseJsonText } from '../skill-hub/utils/json-fields';
2
+
3
+ export function createSkillExecuteTool(plugin: any) {
4
+ return {
5
+ scope: 'CUSTOM',
6
+ execution: 'backend',
7
+ defaultPermission: 'ASK',
8
+
9
+ introduction: {
10
+ title: 'Skill Hub - Universal Skill Executor',
11
+ about:
12
+ 'A universal gateway to execute predefined specialized skills (data processing, complex calculations, file generation, etc.) inside a secure Python/Node.js sandbox.',
13
+ },
14
+
15
+ definition: {
16
+ name: 'skill_hub_execute',
17
+ description: `A universal gateway to execute various predefined specialized skills (e.g., data transformation, calculations, document/presentation generation) in an isolated sandbox.
18
+ HOW TO USE THIS TOOL:
19
+ 1. If you don't know the exact 'skillName' or its required 'input' schema, first call this tool with { "action": "list" } to discover all available skills.
20
+ 2. For complex workflow skills, call { "action": "describe", "skillName": "<exact_skill_name>" } to load the full instructions before execution.
21
+ 3. To run a skill, call this tool with { "action": "execute", "skillName": "<exact_skill_name>", "input": { <parameters> } }.
22
+ CRITICAL: Do NOT guess or hallucinate the 'input' object. You MUST strictly provide the parameters matching the JSON schema defined for that specific skill.
23
+ The skill's output may contain text results, structured JSON data, or download URLs for generated files.
24
+ IMPORTANT: If the skill returns file download URLs, you MUST format them as clickable Markdown links (e.g., [Download filename.ext](/api/attachments/...)) in your final response to the user.`,
25
+ schema: {
26
+ type: 'object',
27
+ properties: {
28
+ action: {
29
+ type: 'string',
30
+ enum: ['list', 'describe', 'execute'],
31
+ description: '"list" to see available skills, "describe" to load full instructions, "execute" to run one',
32
+ },
33
+ skillName: {
34
+ type: 'string',
35
+ description: 'Skill name (required for "execute" action)',
36
+ },
37
+ input: {
38
+ type: 'object',
39
+ description: 'Input parameters matching the skill inputSchema',
40
+ },
41
+ },
42
+ required: ['action'],
43
+ },
44
+ },
45
+
46
+ async invoke(ctx: any, args: Record<string, any>, _id?: string) {
47
+ plugin.app.logger.info(`[skill-execute] Tool invoked with action: ${args.action}, skillName: ${args.skillName}`);
48
+
49
+ // Action: list available skills
50
+ if (args.action === 'list') {
51
+ const skills = await plugin.db.getRepository('skillDefinitions').find({
52
+ filter: { enabled: true },
53
+ fields: ['name', 'title', 'description', 'language', 'inputSchema', 'instructions', 'storageType'],
54
+ });
55
+
56
+ const skillList = skills.map((s: any) => ({
57
+ name: s.get('name'),
58
+ title: s.get('title'),
59
+ description: s.get('description'),
60
+ language: s.get('language'),
61
+ inputSchema: parseJsonText(s.get('inputSchema'), null),
62
+ hasInstructions: !!s.get('instructions') || s.get('storageType') === 'plugin',
63
+ storageType: s.get('storageType'),
64
+ }));
65
+
66
+ return {
67
+ status: 'success',
68
+ content: JSON.stringify({ skills: skillList }),
69
+ };
70
+ }
71
+
72
+ // Action: describe one skill with full workflow instructions
73
+ if (args.action === 'describe') {
74
+ if (!args.skillName) {
75
+ return { status: 'error', content: 'Missing skillName parameter' };
76
+ }
77
+
78
+ const skill = await plugin.db.getRepository('skillDefinitions').findOne({
79
+ filter: { name: args.skillName, enabled: true },
80
+ });
81
+
82
+ if (!skill) {
83
+ return {
84
+ status: 'error',
85
+ content: `Skill "${args.skillName}" not found or disabled`,
86
+ };
87
+ }
88
+
89
+ const instructions =
90
+ typeof plugin.getSkillInstructions === 'function'
91
+ ? await plugin.getSkillInstructions(skill)
92
+ : skill.get('instructions');
93
+
94
+ return {
95
+ status: 'success',
96
+ content: JSON.stringify({
97
+ name: skill.get('name'),
98
+ title: skill.get('title'),
99
+ description: skill.get('description'),
100
+ language: skill.get('language'),
101
+ inputSchema: parseJsonText(skill.get('inputSchema'), null),
102
+ packages: parseJsonText(skill.get('packages'), []),
103
+ storageType: skill.get('storageType'),
104
+ storageUrl: skill.get('storageUrl'),
105
+ instructions,
106
+ }),
107
+ };
108
+ }
109
+
110
+ // Action: execute skill
111
+ if (args.action === 'execute') {
112
+ if (!args.skillName) {
113
+ return { status: 'error', content: 'Missing skillName parameter' };
114
+ }
115
+
116
+ const skill = await plugin.db.getRepository('skillDefinitions').findOne({
117
+ filter: { name: args.skillName, enabled: true },
118
+ });
119
+
120
+ if (!skill) {
121
+ return {
122
+ status: 'error',
123
+ content: `Skill "${args.skillName}" not found or disabled`,
124
+ };
125
+ }
126
+
127
+ try {
128
+ const result = await plugin.executeSkill(skill, args.input || {}, ctx);
129
+
130
+ return {
131
+ status: result.status === 'succeeded' ? 'success' : 'error',
132
+ content: JSON.stringify({
133
+ message:
134
+ result.status === 'succeeded'
135
+ ? `Executed successfully. ${result.files?.length || 0} file(s) generated.`
136
+ : `Failed: ${result.stderr}`,
137
+ stdout: result.stdout,
138
+ stderr: result.stderr,
139
+ files: result.files,
140
+ execId: result.execId,
141
+ agentLoopRunId: result.agentLoopRunId,
142
+ agentLoopStepId: result.agentLoopStepId,
143
+ durationMs: result.durationMs,
144
+ }),
145
+ };
146
+ } catch (error) {
147
+ return {
148
+ status: 'error',
149
+ content: `Execution error: ${error instanceof Error ? error.message : String(error)}`,
150
+ };
151
+ }
152
+ }
153
+
154
+ return {
155
+ status: 'error',
156
+ content: `Unknown action "${args.action}". Use "list", "describe", or "execute".`,
157
+ };
158
+ },
159
+ };
160
+ }
@@ -0,0 +1,55 @@
1
+ // ── Shared types for Agent Orchestrator ──────────────────────────────────
2
+
3
+ export interface TokenUsage {
4
+ inputTokens: number;
5
+ outputTokens: number;
6
+ totalTokens: number;
7
+ cost: number;
8
+ }
9
+
10
+ export interface BudgetConfig {
11
+ budgetMaxTokens?: number;
12
+ budgetMaxCost?: number;
13
+ }
14
+
15
+ export interface BudgetCheckResult {
16
+ allowed: boolean;
17
+ reason?: string;
18
+ }
19
+
20
+ export interface CircuitState {
21
+ failures: number;
22
+ lastFailureTime: number;
23
+ state: 'closed' | 'open' | 'half-open';
24
+ }
25
+
26
+ export interface TraceEvent {
27
+ type: string;
28
+ at: string;
29
+ title: string;
30
+ content?: string;
31
+ toolName?: string;
32
+ args?: any;
33
+ status?: string;
34
+ }
35
+
36
+ export interface DelegationLogData {
37
+ id?: number | string;
38
+ leaderUsername: string;
39
+ subAgentUsername: string;
40
+ toolName: string;
41
+ task: string;
42
+ context?: string;
43
+ result: string;
44
+ status: string;
45
+ depth: number;
46
+ durationMs: number;
47
+ error?: string;
48
+ trace?: TraceEvent[];
49
+ messages?: any[];
50
+ userId?: number | string;
51
+ }
52
+
53
+ export type CtxSnapshot = {
54
+ userId?: number;
55
+ };
@@ -0,0 +1,118 @@
1
+ // ── Shared context/state utility functions ─────────────────────────────
2
+
3
+ /** Normalize a record to a plain JS object. */
4
+ export function toPlain(record: any) {
5
+ return record?.toJSON?.() || record;
6
+ }
7
+
8
+ /** Coerce a value to a plain object (JSON parse if needed). */
9
+ export function asObject(value: any) {
10
+ if (value && typeof value === 'object' && !Array.isArray(value)) return value;
11
+ if (typeof value === 'string' && value.trim()) {
12
+ try {
13
+ const parsed = JSON.parse(value);
14
+ return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : {};
15
+ } catch {
16
+ return {};
17
+ }
18
+ }
19
+ return {};
20
+ }
21
+
22
+ /** Coerce value to array. */
23
+ export function asArray(value: any): any[] {
24
+ return Array.isArray(value) ? value : [];
25
+ }
26
+
27
+ /** Trim text to max length with ellipsis suffix. */
28
+ export function trimText(value: any, max = 50000) {
29
+ let text = '';
30
+ if (typeof value === 'string') {
31
+ text = value;
32
+ } else if (value != null) {
33
+ try {
34
+ text = JSON.stringify(value);
35
+ } catch {
36
+ text = String(value);
37
+ }
38
+ }
39
+ return text.length > max ? `${text.slice(0, max)}\n...[truncated]` : text;
40
+ }
41
+
42
+ /** Get the current user id from ctx. */
43
+ export function currentUserId(ctx: any) {
44
+ return ctx?.state?.currentUser?.id || ctx?.auth?.user?.id;
45
+ }
46
+
47
+ /** Get action params values from ctx. */
48
+ export function valuesFromCtx(ctx: any) {
49
+ return ctx?.action?.params?.values || ctx?.request?.body || {};
50
+ }
51
+
52
+ /** Normalize raw employee username input (string | object → string | null). */
53
+ export function normalizeEmployeeUsername(raw: any) {
54
+ if (!raw) return null;
55
+ if (typeof raw === 'string') return raw;
56
+ return raw.username || raw.aiEmployeeUsername || raw.name || null;
57
+ }
58
+
59
+ /** Resolve session id from args or ctx. */
60
+ export function resolveSessionId(ctx: any, args: any) {
61
+ const v = valuesFromCtx(ctx);
62
+ return args?.sessionId || v.sessionId || ctx?.action?.params?.sessionId || ctx?.state?.sessionId;
63
+ }
64
+
65
+ /** Resolve message id from args or ctx. */
66
+ export function resolveMessageId(ctx: any, args: any) {
67
+ const v = valuesFromCtx(ctx);
68
+ return args?.messageId || v.messageId || ctx?.action?.params?.messageId;
69
+ }
70
+
71
+ /** Resolve leader employee username from args, ctx state, or conversation record. */
72
+ export async function resolveLeaderUsername(ctx: any, plugin: any, args: any) {
73
+ const v = valuesFromCtx(ctx);
74
+ const direct = normalizeEmployeeUsername(
75
+ args?.leaderUsername ||
76
+ ctx?._currentAIEmployee ||
77
+ ctx?.state?.currentAIEmployee ||
78
+ ctx?.runtime?.context?.currentAIEmployee ||
79
+ v.aiEmployee,
80
+ );
81
+ if (direct) return direct;
82
+
83
+ const sessionId = resolveSessionId(ctx, args);
84
+ if (!sessionId) return undefined;
85
+ try {
86
+ const repo = ctx?.db?.getRepository?.('aiConversations') || plugin.db.getRepository('aiConversations');
87
+ const conversation = await repo.findOne({ filter: { sessionId } });
88
+ return normalizeEmployeeUsername(conversation?.aiEmployeeUsername || conversation?.get?.('aiEmployeeUsername'));
89
+ } catch {
90
+ return undefined;
91
+ }
92
+ }
93
+
94
+ /** Snapshot ctx user id for later use (avoids stale ctx). */
95
+ export function captureCtxSnapshot(ctx: any): { userId?: number } {
96
+ let userId: number | undefined;
97
+ try {
98
+ userId = ctx?.auth?.user?.id || ctx?.state?.currentUser?.id;
99
+ } catch {
100
+ // ctx already disposed
101
+ }
102
+ return { userId };
103
+ }
104
+
105
+ /** Normalize step type to a known value. */
106
+ export function normalizeStepType(value: any) {
107
+ return ['reasoning', 'skill', 'tool', 'sub_agent', 'verification'].includes(value) ? value : 'tool';
108
+ }
109
+
110
+ /** Normalize plan key from step input. */
111
+ export function normalizePlanKey(step: any, index: number) {
112
+ return String(step.planKey || step.key || step.id || `step_${index + 1}`);
113
+ }
114
+
115
+ /** Now ISO string. */
116
+ export function nowIso() {
117
+ return new Date().toISOString();
118
+ }
@@ -0,0 +1,63 @@
1
+ // ── Shared logging for delegation events ───────────────────────────────
2
+
3
+ import { DelegationLogData } from '../types';
4
+ import { trimText, toPlain } from './ctx-utils';
5
+
6
+ /**
7
+ * Log (or update) a delegation event in the orchestratorLogs collection.
8
+ * Used by both delegate-task.ts and AgentHarness.ts.
9
+ */
10
+ export async function logDelegation(ctx: any, plugin: any, data: DelegationLogData) {
11
+ try {
12
+ const logsRepo = plugin.db.getRepository('orchestratorLogs');
13
+ if (!logsRepo) {
14
+ plugin.app.log?.warn?.('[AgentOrchestrator] orchestratorLogs repository not found — skipping log');
15
+ return null;
16
+ }
17
+
18
+ let userId: number | string | undefined = data.userId;
19
+ if (userId == null) {
20
+ try {
21
+ userId = ctx?.auth?.user?.id || ctx?.state?.currentUser?.id;
22
+ } catch {
23
+ // ctx lifecycle ended
24
+ }
25
+ }
26
+
27
+ const values = {
28
+ leaderUsername: data.leaderUsername,
29
+ subAgentUsername: data.subAgentUsername,
30
+ toolName: data.toolName,
31
+ task: trimText(data.task, 10000),
32
+ context: trimText(data.context || '', 10000),
33
+ result: trimText(data.result || '', 50000),
34
+ status: data.status,
35
+ depth: data.depth,
36
+ durationMs: data.durationMs,
37
+ error: trimText(data.error || '', 10000),
38
+ trace: data.trace || [],
39
+ messages: data.messages || [],
40
+ userId,
41
+ updatedAt: new Date(),
42
+ };
43
+
44
+ if (data.id) {
45
+ await logsRepo.update({
46
+ filterByTk: data.id,
47
+ values,
48
+ });
49
+ return { id: data.id };
50
+ }
51
+
52
+ const record = await logsRepo.create({
53
+ values: {
54
+ ...values,
55
+ createdAt: new Date(),
56
+ },
57
+ });
58
+ return toPlain(record);
59
+ } catch (e) {
60
+ plugin.app.log?.warn?.('[AgentOrchestrator] Failed to log delegation event', e);
61
+ return null;
62
+ }
63
+ }
@@ -1,11 +0,0 @@
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
- }>;
@@ -1,30 +0,0 @@
1
- import React from 'react';
2
- interface AIEmployeeInfo {
3
- username: string;
4
- nickname: string;
5
- about?: string;
6
- skills: string[];
7
- }
8
- interface AIEmployeesContextType {
9
- employees: AIEmployeeInfo[];
10
- employeeMap: Map<string, string>;
11
- skillsMap: Map<string, Set<string>>;
12
- loading: boolean;
13
- refresh: () => void;
14
- }
15
- /**
16
- * P3 FIX: Shared context provider that fetches aiEmployees once
17
- * and shares the data across RulesTab, TracingTab, and AIEmployeeSelect.
18
- *
19
- * Also exposes each employee's configured skills so RulesTab can warn when
20
- * a delegation rule exists but the leader hasn't added the corresponding
21
- * delegate_<leader>_to_<sub> tool to its skillSettings.
22
- */
23
- export declare const AIEmployeesProvider: React.FC<{
24
- children: React.ReactNode;
25
- }>;
26
- /**
27
- * Hook to access shared AI employees data.
28
- */
29
- export declare const useAIEmployees: () => AIEmployeesContextType;
30
- export {};
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const AgentRunsTab: React.FC;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const HarnessProfilesTab: React.FC;
@@ -1,3 +0,0 @@
1
- import React from 'react';
2
- declare const OrchestratorSettings: React.FC;
3
- export { OrchestratorSettings };
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const RulesTab: React.FC;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const TracingTab: React.FC;
@@ -1 +0,0 @@
1
- export { default } from './plugin';
@@ -1,6 +0,0 @@
1
- import { Plugin } from '@nocobase/client';
2
- export declare class PluginAgentOrchestratorClient extends Plugin {
3
- load(): Promise<void>;
4
- private registerSkillUiCards;
5
- }
6
- export default PluginAgentOrchestratorClient;
@@ -1,2 +0,0 @@
1
- import React from 'react';
2
- export declare const ExecutionHistory: React.FC;
@@ -1,20 +0,0 @@
1
- import React from 'react';
2
- interface ExecutionProgressProps {
3
- execId: string;
4
- skillName: string;
5
- percent: number;
6
- log: string;
7
- }
8
- /**
9
- * Progress component rendered inside chat UI when receiving
10
- * SSE custom event: {action: "skillProgress", body: {...}}
11
- *
12
- * Usage in chat message renderer:
13
- * ```
14
- * if (event.action === 'skillProgress') {
15
- * return <ExecutionProgress {...event.body} />;
16
- * }
17
- * ```
18
- */
19
- export declare const ExecutionProgress: React.FC<ExecutionProgressProps>;
20
- export {};
@@ -1,7 +0,0 @@
1
- import React from 'react';
2
- interface GitSkillImportProps {
3
- open: boolean;
4
- onClose: (synced?: boolean) => void;
5
- }
6
- export declare const GitSkillImport: React.FC<GitSkillImportProps>;
7
- export {};