plugin-agent-orchestrator 1.0.21 → 1.0.23
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.
- package/client-v2.d.ts +2 -0
- package/client-v2.js +1 -0
- package/dist/client/index.js +1 -1
- package/dist/client-v2/214.723affb37c13bf7a.js +10 -0
- package/dist/client-v2/264.0533912e6c5ea2d7.js +10 -0
- package/dist/client-v2/41.1805b2edfaa4afe2.js +10 -0
- package/dist/client-v2/418.5ae055abf141820e.js +10 -0
- package/dist/client-v2/619.d99d3c9e61c99064.js +10 -0
- package/dist/client-v2/70.a15d7fcec7c41768.js +10 -0
- package/dist/client-v2/892.72db4161511c8a16.js +10 -0
- package/dist/client-v2/926.87f660b670d85bcc.js +10 -0
- package/dist/client-v2/index.js +10 -0
- package/dist/externalVersion.js +7 -6
- package/dist/locale/en-US.json +7 -0
- package/dist/locale/vi-VN.json +7 -0
- package/dist/locale/zh-CN.json +27 -0
- package/dist/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.js +63 -0
- package/dist/server/plugin.js +41 -1
- package/dist/server/services/AgentHarness.js +52 -27
- package/dist/server/services/AgentLoopController.js +8 -2
- package/dist/server/services/AgentLoopService.js +1 -1
- package/dist/server/services/AgentRegistryService.js +53 -42
- package/dist/server/services/CircuitBreaker.js +7 -2
- package/dist/server/services/CodeValidator.js +48 -14
- package/dist/server/services/SandboxRunner.js +18 -14
- package/dist/server/skill-hub/plugin.js +44 -17
- package/dist/server/tools/delegate-task.js +7 -2
- package/dist/server/tools/skill-execute.js +33 -2
- package/dist/server/utils/ai-manager.js +51 -0
- package/dist/server/utils/ctx-utils.js +11 -0
- package/dist/server/utils/skill-settings.js +122 -0
- package/package.json +49 -45
- package/src/client/AIEmployeesContext.tsx +51 -14
- package/src/client/AgentRunsTab.tsx +767 -764
- package/src/client/HarnessProfilesTab.tsx +254 -247
- package/src/client/RulesTab.tsx +780 -716
- package/src/client/TracingTab.tsx +1 -0
- package/src/client/plugin.tsx +34 -27
- package/src/client/skill-hub/components/GitSkillImport.tsx +10 -3
- package/src/client/skill-hub/components/SkillMetrics.tsx +157 -124
- package/src/client/skill-hub/index.tsx +58 -51
- package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +132 -99
- package/src/client/skill-hub/tools/registerSkillLoopCards.ts +71 -58
- package/src/client/tools/registerOrchestratorCards.ts +17 -7
- package/src/client-v2/components/AIEmployeeSelect.tsx +47 -0
- package/src/client-v2/components/AIEmployeesContext.tsx +110 -0
- package/src/client-v2/components/AgentRunsTab.tsx +767 -0
- package/src/client-v2/components/HarnessProfilesTab.tsx +254 -0
- package/src/client-v2/components/RulesTab.tsx +782 -0
- package/src/client-v2/components/TracingTab.tsx +432 -0
- package/src/client-v2/hooks/useApiRequest.ts +114 -0
- package/src/client-v2/pages/AgentRunsPage.tsx +13 -0
- package/src/client-v2/pages/ExecutionHistoryPage.tsx +10 -0
- package/src/client-v2/pages/HarnessProfilesPage.tsx +10 -0
- package/src/client-v2/pages/LoopSettingsPage.tsx +10 -0
- package/src/client-v2/pages/RulesPage.tsx +13 -0
- package/src/client-v2/pages/SkillDefinitionsPage.tsx +10 -0
- package/src/client-v2/pages/SkillMetricsPage.tsx +10 -0
- package/src/client-v2/pages/TracingPage.tsx +13 -0
- package/src/client-v2/plugin.tsx +70 -0
- package/src/client-v2/skill-hub/components/ExecutionHistory.tsx +196 -0
- package/src/client-v2/skill-hub/components/FileLinkList.tsx +37 -0
- package/src/client-v2/skill-hub/components/GitSkillImport.tsx +539 -0
- package/src/client-v2/skill-hub/components/LoopSettings.tsx +331 -0
- package/src/client-v2/skill-hub/components/SkillEditor.tsx +453 -0
- package/src/client-v2/skill-hub/components/SkillManager.tsx +174 -0
- package/src/client-v2/skill-hub/components/SkillMetrics.tsx +157 -0
- package/src/client-v2/skill-hub/components/SkillTestPanel.tsx +135 -0
- package/src/client-v2/skill-hub/locale.ts +13 -0
- package/src/client-v2/skill-hub/tools/loopTemplates.ts +52 -0
- package/src/client-v2/skill-hub/utils/jsonFields.ts +41 -0
- package/src/client-v2/utils/jsonFields.ts +41 -0
- package/src/locale/en-US.json +7 -0
- package/src/locale/vi-VN.json +7 -0
- package/src/locale/zh-CN.json +27 -0
- package/src/server/__tests__/agent-registry-service.test.ts +147 -0
- package/src/server/__tests__/code-validator.test.ts +63 -0
- package/src/server/__tests__/skill-execute.test.ts +33 -0
- package/src/server/__tests__/skill-settings.test.ts +63 -0
- package/src/server/migrations/20260615000000-normalize-ai-employee-tool-bindings.ts +39 -0
- package/src/server/plugin.ts +68 -12
- package/src/server/services/AgentHarness.ts +49 -22
- package/src/server/services/AgentLoopController.ts +17 -6
- package/src/server/services/AgentLoopService.ts +1 -1
- package/src/server/services/AgentPlannerService.ts +10 -0
- package/src/server/services/AgentRegistryService.ts +89 -47
- package/src/server/services/CircuitBreaker.ts +10 -0
- package/src/server/services/CodeValidator.ts +237 -159
- package/src/server/services/SandboxRunner.ts +203 -189
- package/src/server/skill-hub/plugin.ts +933 -898
- package/src/server/tools/delegate-task.ts +12 -9
- package/src/server/tools/skill-execute.ts +194 -160
- package/src/server/utils/ai-manager.ts +24 -0
- package/src/server/utils/ctx-utils.ts +14 -0
- package/src/server/utils/skill-settings.ts +116 -0
- package/dist/client/AIEmployeeSelect.d.ts +0 -11
- package/dist/client/AIEmployeesContext.d.ts +0 -30
- package/dist/client/AgentRunsTab.d.ts +0 -2
- package/dist/client/HarnessProfilesTab.d.ts +0 -2
- package/dist/client/OrchestratorSettings.d.ts +0 -3
- package/dist/client/RulesTab.d.ts +0 -2
- package/dist/client/TracingTab.d.ts +0 -2
- package/dist/client/hooks/useRunEventStream.d.ts +0 -22
- package/dist/client/index.d.ts +0 -2
- package/dist/client/plugin.d.ts +0 -6
- package/dist/client/skill-hub/components/ExecutionHistory.d.ts +0 -2
- package/dist/client/skill-hub/components/ExecutionProgress.d.ts +0 -20
- package/dist/client/skill-hub/components/GitSkillImport.d.ts +0 -7
- package/dist/client/skill-hub/components/LoopSettings.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillEditor.d.ts +0 -7
- package/dist/client/skill-hub/components/SkillManager.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillMetrics.d.ts +0 -2
- package/dist/client/skill-hub/components/SkillTestPanel.d.ts +0 -7
- package/dist/client/skill-hub/index.d.ts +0 -11
- package/dist/client/skill-hub/locale.d.ts +0 -3
- package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +0 -6
- package/dist/client/skill-hub/tools/SkillHubCard.d.ts +0 -3
- package/dist/client/skill-hub/tools/loopTemplates.d.ts +0 -22
- package/dist/client/skill-hub/tools/registerSkillLoopCards.d.ts +0 -1
- package/dist/client/skill-hub/utils/jsonFields.d.ts +0 -3
- package/dist/client/tools/PlanApprovalCard.d.ts +0 -3
- package/dist/client/tools/registerOrchestratorCards.d.ts +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/server/collections/agent-execution-spans.d.ts +0 -9
- package/dist/server/collections/agent-harness-profiles.d.ts +0 -2
- package/dist/server/collections/agent-loop-events.d.ts +0 -2
- package/dist/server/collections/agent-loop-runs.d.ts +0 -2
- package/dist/server/collections/agent-loop-steps.d.ts +0 -2
- package/dist/server/collections/orchestrator-config.d.ts +0 -2
- package/dist/server/collections/orchestrator-logs.d.ts +0 -8
- package/dist/server/collections/skill-definitions.d.ts +0 -3
- package/dist/server/collections/skill-executions.d.ts +0 -3
- package/dist/server/collections/skill-loop-configs.d.ts +0 -3
- package/dist/server/collections/skill-worker-configs.d.ts +0 -3
- package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +0 -4
- package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +0 -4
- package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +0 -7
- package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +0 -4
- package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +0 -4
- package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +0 -7
- package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +0 -16
- package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +0 -7
- package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.d.ts +0 -7
- package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.d.ts +0 -12
- package/dist/server/migrations/20260601000000-add-token-fields.d.ts +0 -7
- package/dist/server/plugin.d.ts +0 -16
- package/dist/server/resources/agent-loop.d.ts +0 -3
- package/dist/server/resources/tracing.d.ts +0 -7
- package/dist/server/services/AgentHarness.d.ts +0 -44
- package/dist/server/services/AgentLoopController.d.ts +0 -218
- package/dist/server/services/AgentLoopRepository.d.ts +0 -20
- package/dist/server/services/AgentLoopService.d.ts +0 -159
- package/dist/server/services/AgentPlanValidator.d.ts +0 -4
- package/dist/server/services/AgentPlannerService.d.ts +0 -8
- package/dist/server/services/AgentRegistryService.d.ts +0 -21
- package/dist/server/services/CircuitBreaker.d.ts +0 -40
- package/dist/server/services/CodeValidator.d.ts +0 -32
- package/dist/server/services/ContextAggregator.d.ts +0 -45
- package/dist/server/services/ExecutionSpanService.d.ts +0 -46
- package/dist/server/services/FileManager.d.ts +0 -28
- package/dist/server/services/RunEventBus.d.ts +0 -9
- package/dist/server/services/SandboxRunner.d.ts +0 -41
- package/dist/server/services/SkillManager.d.ts +0 -6
- package/dist/server/services/SkillRepositoryService.d.ts +0 -22
- package/dist/server/services/TokenTracker.d.ts +0 -62
- package/dist/server/services/WorkerEnvManager.d.ts +0 -26
- package/dist/server/skill-hub/actions/git-import.d.ts +0 -21
- package/dist/server/skill-hub/mcp/McpController.d.ts +0 -15
- package/dist/server/skill-hub/plugin.d.ts +0 -61
- package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +0 -16
- package/dist/server/skill-hub/utils/json-fields.d.ts +0 -7
- package/dist/server/tools/agent-loop.d.ts +0 -235
- package/dist/server/tools/delegate-task.d.ts +0 -19
- package/dist/server/tools/external-rag-search.d.ts +0 -42
- package/dist/server/tools/orchestrator-plan.d.ts +0 -205
- package/dist/server/tools/skill-execute.d.ts +0 -36
- package/dist/server/types.d.ts +0 -47
- package/dist/server/utils/ctx-utils.d.ts +0 -30
- package/dist/server/utils/logging.d.ts +0 -6
- /package/{dist/server/index.d.ts → src/client-v2/index.tsx} +0 -0
|
@@ -6,7 +6,7 @@ import { createReactAgent } from '@langchain/langgraph/prebuilt';
|
|
|
6
6
|
import { DynamicStructuredTool } from '@langchain/core/tools';
|
|
7
7
|
import { HumanMessage, SystemMessage } from '@langchain/core/messages';
|
|
8
8
|
import type PluginAIServer from '@nocobase/plugin-ai/dist/server';
|
|
9
|
-
import type { ToolsEntry } from '@nocobase/ai';
|
|
9
|
+
import type { ToolsEntry, ToolsRuntime } from '@nocobase/ai';
|
|
10
10
|
import {
|
|
11
11
|
ExecutionSpanService,
|
|
12
12
|
getOrchestratorTraceContext,
|
|
@@ -39,10 +39,11 @@ type AgentExecutionResult = {
|
|
|
39
39
|
messages: any[];
|
|
40
40
|
};
|
|
41
41
|
|
|
42
|
-
type
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
type ToolRuntimeInput = string | ToolsRuntime | undefined;
|
|
43
|
+
|
|
44
|
+
function getToolCallId(runtime: ToolRuntimeInput) {
|
|
45
|
+
return typeof runtime === 'string' ? runtime : runtime?.toolCallId;
|
|
46
|
+
}
|
|
46
47
|
|
|
47
48
|
function sanitizeToolPart(value: string) {
|
|
48
49
|
return (value || '').replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
@@ -154,7 +155,8 @@ function createDelegateToolOptions(
|
|
|
154
155
|
.describe('Optional additional context to help the sub-agent understand the task better.'),
|
|
155
156
|
}),
|
|
156
157
|
},
|
|
157
|
-
invoke: async (ctx: Context, args: { task: string; context?: string },
|
|
158
|
+
invoke: async (ctx: Context, args: { task: string; context?: string }, runtime?: ToolRuntimeInput) => {
|
|
159
|
+
const id = getToolCallId(runtime) || `delegate-${Date.now()}`;
|
|
158
160
|
const callingEmployee = await resolveCallingEmployee(ctx, plugin);
|
|
159
161
|
if (!callingEmployee) {
|
|
160
162
|
await logDelegation(ctx, plugin, {
|
|
@@ -312,8 +314,9 @@ function createDispatchToolOptions(
|
|
|
312
314
|
invoke: async (
|
|
313
315
|
ctx: Context,
|
|
314
316
|
args: { tasks: Array<{ subAgent: string; task: string; context?: string }> },
|
|
315
|
-
|
|
317
|
+
runtime?: ToolRuntimeInput,
|
|
316
318
|
) => {
|
|
319
|
+
const id = getToolCallId(runtime) || `dispatch-${Date.now()}`;
|
|
317
320
|
const callingEmployee = await resolveCallingEmployee(ctx, plugin);
|
|
318
321
|
if (!callingEmployee) {
|
|
319
322
|
const distinctSubs = Array.from(new Set((args.tasks ?? []).map((t) => t.subAgent).filter(Boolean)));
|
|
@@ -706,9 +709,9 @@ export function invalidateDelegateToolsCache() {
|
|
|
706
709
|
*
|
|
707
710
|
* Tool resolution uses the CORE toolsManager (app.aiManager.toolsManager) —
|
|
708
711
|
* the same manager that AIEmployee.getToolsMap() uses (see ai-employee.ts:1286).
|
|
709
|
-
* This ensures tool names in skillSettings.
|
|
712
|
+
* This ensures tool names in skillSettings.tools[].name match correctly.
|
|
710
713
|
*
|
|
711
|
-
* skillSettings.
|
|
714
|
+
* skillSettings.tools shape:
|
|
712
715
|
* { name: string, autoCall: boolean }[]
|
|
713
716
|
*/
|
|
714
717
|
async function invokeDelegateTask(
|
|
@@ -1,160 +1,194 @@
|
|
|
1
|
-
import { parseJsonText } from '../skill-hub/utils/json-fields';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
}
|
|
1
|
+
import { parseJsonText } from '../skill-hub/utils/json-fields';
|
|
2
|
+
import type { ToolsRuntime } from '@nocobase/ai';
|
|
3
|
+
|
|
4
|
+
type ToolRuntimeInput = string | ToolsRuntime | undefined;
|
|
5
|
+
|
|
6
|
+
function normalizeRuntime(runtime: ToolRuntimeInput): ToolsRuntime | undefined {
|
|
7
|
+
if (!runtime) return undefined;
|
|
8
|
+
if (typeof runtime === 'string') {
|
|
9
|
+
return { toolCallId: runtime, writer: () => {} };
|
|
10
|
+
}
|
|
11
|
+
return runtime;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function createSkillExecuteTool(plugin: any) {
|
|
15
|
+
return {
|
|
16
|
+
scope: 'CUSTOM',
|
|
17
|
+
execution: 'backend',
|
|
18
|
+
// Intentionally fixed to ASK. This is the universal gateway: a single tool
|
|
19
|
+
// whose `execute` action can run ANY enabled skill by name, so the
|
|
20
|
+
// per-skill `autoCall` flag cannot be honored here — the harness decides
|
|
21
|
+
// approval from `defaultPermission` before invoke, when the target skill is
|
|
22
|
+
// not yet known. The per-skill dynamic tools (`skill_hub_<name>`) are the
|
|
23
|
+
// fast path that respect `autoCall: true → ALLOW`. Keeping the generic
|
|
24
|
+
// gateway on ASK is deliberate defense-in-depth, not an oversight.
|
|
25
|
+
defaultPermission: 'ASK',
|
|
26
|
+
|
|
27
|
+
introduction: {
|
|
28
|
+
title: 'Skill Hub - Universal Skill Executor',
|
|
29
|
+
about:
|
|
30
|
+
'A universal gateway to execute predefined specialized skills (data processing, complex calculations, file generation, etc.) inside a secure Python/Node.js sandbox.',
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
definition: {
|
|
34
|
+
name: 'skill_hub_execute',
|
|
35
|
+
description: `A universal gateway to execute various predefined specialized skills (e.g., data transformation, calculations, document/presentation generation) in an isolated sandbox.
|
|
36
|
+
HOW TO USE THIS TOOL:
|
|
37
|
+
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.
|
|
38
|
+
2. For complex workflow skills, call { "action": "describe", "skillName": "<exact_skill_name>" } to load the full instructions before execution.
|
|
39
|
+
3. To run a skill, call this tool with { "action": "execute", "skillName": "<exact_skill_name>", "input": { <parameters> } }.
|
|
40
|
+
CRITICAL: Do NOT guess or hallucinate the 'input' object. You MUST strictly provide the parameters matching the JSON schema defined for that specific skill.
|
|
41
|
+
The skill's output may contain text results, structured JSON data, or download URLs for generated files.
|
|
42
|
+
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.`,
|
|
43
|
+
schema: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
action: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
enum: ['list', 'describe', 'execute'],
|
|
49
|
+
description: '"list" to see available skills, "describe" to load full instructions, "execute" to run one',
|
|
50
|
+
},
|
|
51
|
+
skillName: {
|
|
52
|
+
type: 'string',
|
|
53
|
+
description: 'Skill name (required for "execute" action)',
|
|
54
|
+
},
|
|
55
|
+
input: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
description: 'Input parameters matching the skill inputSchema',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
required: ['action'],
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
async invoke(ctx: any, args: Record<string, any>, runtime?: ToolRuntimeInput) {
|
|
65
|
+
plugin.app.logger.info(`[skill-execute] Tool invoked with action: ${args.action}, skillName: ${args.skillName}`);
|
|
66
|
+
|
|
67
|
+
// Action: list available skills
|
|
68
|
+
if (args.action === 'list') {
|
|
69
|
+
const skills = await plugin.db.getRepository('skillDefinitions').find({
|
|
70
|
+
filter: { enabled: true },
|
|
71
|
+
fields: ['name', 'title', 'description', 'language', 'inputSchema', 'instructions', 'storageType'],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const skillList = skills.map((s: any) => ({
|
|
75
|
+
name: s.get('name'),
|
|
76
|
+
title: s.get('title'),
|
|
77
|
+
description: s.get('description'),
|
|
78
|
+
language: s.get('language'),
|
|
79
|
+
inputSchema: parseJsonText(s.get('inputSchema'), null),
|
|
80
|
+
hasInstructions: !!s.get('instructions') || s.get('storageType') === 'plugin',
|
|
81
|
+
storageType: s.get('storageType'),
|
|
82
|
+
}));
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
status: 'success',
|
|
86
|
+
content: JSON.stringify({ skills: skillList }),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Action: describe one skill with full workflow instructions
|
|
91
|
+
if (args.action === 'describe') {
|
|
92
|
+
if (!args.skillName) {
|
|
93
|
+
return { status: 'error', content: 'Missing skillName parameter' };
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const skill = await plugin.db.getRepository('skillDefinitions').findOne({
|
|
97
|
+
filter: { name: args.skillName, enabled: true },
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
if (!skill) {
|
|
101
|
+
return {
|
|
102
|
+
status: 'error',
|
|
103
|
+
content: `Skill "${args.skillName}" not found or disabled`,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const instructions =
|
|
108
|
+
typeof plugin.getSkillInstructions === 'function'
|
|
109
|
+
? await plugin.getSkillInstructions(skill)
|
|
110
|
+
: skill.get('instructions');
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
status: 'success',
|
|
114
|
+
content: JSON.stringify({
|
|
115
|
+
name: skill.get('name'),
|
|
116
|
+
title: skill.get('title'),
|
|
117
|
+
description: skill.get('description'),
|
|
118
|
+
language: skill.get('language'),
|
|
119
|
+
inputSchema: parseJsonText(skill.get('inputSchema'), null),
|
|
120
|
+
packages: parseJsonText(skill.get('packages'), []),
|
|
121
|
+
storageType: skill.get('storageType'),
|
|
122
|
+
storageUrl: skill.get('storageUrl'),
|
|
123
|
+
instructions,
|
|
124
|
+
}),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Action: execute skill
|
|
129
|
+
if (args.action === 'execute') {
|
|
130
|
+
if (!args.skillName) {
|
|
131
|
+
return { status: 'error', content: 'Missing skillName parameter' };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const skill = await plugin.db.getRepository('skillDefinitions').findOne({
|
|
135
|
+
filter: { name: args.skillName, enabled: true },
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
if (!skill) {
|
|
139
|
+
return {
|
|
140
|
+
status: 'error',
|
|
141
|
+
content: `Skill "${args.skillName}" not found or disabled`,
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
try {
|
|
146
|
+
const normalizedRuntime = normalizeRuntime(runtime);
|
|
147
|
+
const previousRuntime = ctx.runtime;
|
|
148
|
+
if (normalizedRuntime) {
|
|
149
|
+
ctx.runtime = normalizedRuntime;
|
|
150
|
+
}
|
|
151
|
+
let result;
|
|
152
|
+
try {
|
|
153
|
+
result = await plugin.executeSkill(skill, args.input || {}, ctx);
|
|
154
|
+
} finally {
|
|
155
|
+
if (normalizedRuntime) {
|
|
156
|
+
if (previousRuntime === undefined) {
|
|
157
|
+
delete ctx.runtime;
|
|
158
|
+
} else {
|
|
159
|
+
ctx.runtime = previousRuntime;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
status: result.status === 'succeeded' ? 'success' : 'error',
|
|
166
|
+
content: JSON.stringify({
|
|
167
|
+
message:
|
|
168
|
+
result.status === 'succeeded'
|
|
169
|
+
? `Executed successfully. ${result.files?.length || 0} file(s) generated.`
|
|
170
|
+
: `Failed: ${result.stderr}`,
|
|
171
|
+
stdout: result.stdout,
|
|
172
|
+
stderr: result.stderr,
|
|
173
|
+
files: result.files,
|
|
174
|
+
execId: result.execId,
|
|
175
|
+
agentLoopRunId: result.agentLoopRunId,
|
|
176
|
+
agentLoopStepId: result.agentLoopStepId,
|
|
177
|
+
durationMs: result.durationMs,
|
|
178
|
+
}),
|
|
179
|
+
};
|
|
180
|
+
} catch (error) {
|
|
181
|
+
return {
|
|
182
|
+
status: 'error',
|
|
183
|
+
content: `Execution error: ${error instanceof Error ? error.message : String(error)}`,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
status: 'error',
|
|
190
|
+
content: `Unknown action "${args.action}". Use "list", "describe", or "execute".`,
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single accessor for the core AI tools manager.
|
|
3
|
+
*
|
|
4
|
+
* plugin-ai exposes the tools manager at `app.aiManager.toolsManager`, and the
|
|
5
|
+
* same instance is reachable via `pluginAI.ai.toolsManager`. Mixing the two
|
|
6
|
+
* access paths risks registering tools on one object while resolving them on
|
|
7
|
+
* another if the wiring ever diverges. Every orchestrator call site goes
|
|
8
|
+
* through this helper so registration and resolution always share one manager.
|
|
9
|
+
*/
|
|
10
|
+
export function getAIToolsManager(app: any) {
|
|
11
|
+
const toolsManager = app?.aiManager?.toolsManager;
|
|
12
|
+
if (!toolsManager) {
|
|
13
|
+
throw new Error(
|
|
14
|
+
'[AgentOrchestrator] app.aiManager.toolsManager is not available. ' +
|
|
15
|
+
'Ensure @nocobase/plugin-ai is enabled and loaded before plugin-agent-orchestrator.',
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
return toolsManager;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Same accessor, but returns undefined instead of throwing (best-effort call sites). */
|
|
22
|
+
export function tryGetAIToolsManager(app: any) {
|
|
23
|
+
return app?.aiManager?.toolsManager;
|
|
24
|
+
}
|
|
@@ -44,6 +44,20 @@ export function currentUserId(ctx: any) {
|
|
|
44
44
|
return ctx?.state?.currentUser?.id || ctx?.auth?.user?.id;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Whether the current request is made by an admin/root user.
|
|
49
|
+
* Mirrors the owner/admin check used by skillHub:download so list/get
|
|
50
|
+
* scoping and file access stay consistent.
|
|
51
|
+
*/
|
|
52
|
+
export function isAdminUser(ctx: any): boolean {
|
|
53
|
+
const roles = ctx?.state?.currentUser?.roles || ctx?.auth?.user?.roles;
|
|
54
|
+
if (!Array.isArray(roles)) return false;
|
|
55
|
+
return roles.some((r: any) => {
|
|
56
|
+
const name = typeof r === 'string' ? r : r?.name;
|
|
57
|
+
return name === 'root' || name === 'admin';
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
47
61
|
/** Get action params values from ctx. */
|
|
48
62
|
export function valuesFromCtx(ctx: any) {
|
|
49
63
|
return ctx?.action?.params?.values || ctx?.request?.body || {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export type EmployeeToolBinding = {
|
|
2
|
+
name: string;
|
|
3
|
+
autoCall?: boolean;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
type RecordLike = Record<string, unknown>;
|
|
7
|
+
|
|
8
|
+
function isRecord(value: unknown): value is RecordLike {
|
|
9
|
+
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isOrchestratorToolName(name: string) {
|
|
13
|
+
return (
|
|
14
|
+
name === 'orchestrator_plan_goal' ||
|
|
15
|
+
name === 'orchestrator_execute_plan' ||
|
|
16
|
+
name === 'orchestrator_status' ||
|
|
17
|
+
name === 'orchestrator_cancel' ||
|
|
18
|
+
name === 'external_rag_search' ||
|
|
19
|
+
name === 'skill_hub_execute' ||
|
|
20
|
+
name.startsWith('delegate_') ||
|
|
21
|
+
name.startsWith('dispatch_subagents_') ||
|
|
22
|
+
name.startsWith('skill_hub_') ||
|
|
23
|
+
name.startsWith('browser_') ||
|
|
24
|
+
name.startsWith('drawio-')
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function toToolBinding(value: unknown): EmployeeToolBinding | null {
|
|
29
|
+
if (typeof value === 'string') {
|
|
30
|
+
const name = value.trim();
|
|
31
|
+
return name ? { name, autoCall: false } : null;
|
|
32
|
+
}
|
|
33
|
+
if (!isRecord(value) || typeof value.name !== 'string') {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
const name = value.name.trim();
|
|
37
|
+
if (!name) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
return {
|
|
41
|
+
name,
|
|
42
|
+
autoCall: value.autoCall === true,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function addToolBinding(toolsByName: Map<string, EmployeeToolBinding>, binding: EmployeeToolBinding | null) {
|
|
47
|
+
if (!binding) return;
|
|
48
|
+
if (!toolsByName.has(binding.name)) {
|
|
49
|
+
toolsByName.set(binding.name, binding);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function normalizeAIEmployeeSkillSettings(value: unknown): {
|
|
54
|
+
changed: boolean;
|
|
55
|
+
skillSettings: RecordLike & { skills: string[]; tools: EmployeeToolBinding[] };
|
|
56
|
+
} {
|
|
57
|
+
const source = isRecord(value) ? value : {};
|
|
58
|
+
const toolsByName = new Map<string, EmployeeToolBinding>();
|
|
59
|
+
const nextSkills: string[] = [];
|
|
60
|
+
let changed = false;
|
|
61
|
+
|
|
62
|
+
const sourceTools = source.tools;
|
|
63
|
+
if (Array.isArray(sourceTools)) {
|
|
64
|
+
for (const item of sourceTools) {
|
|
65
|
+
const binding = toToolBinding(item);
|
|
66
|
+
if (binding) {
|
|
67
|
+
addToolBinding(toolsByName, binding);
|
|
68
|
+
if (typeof item === 'string') {
|
|
69
|
+
changed = true;
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
changed = true;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const sourceSkills = source.skills;
|
|
78
|
+
if (Array.isArray(sourceSkills)) {
|
|
79
|
+
for (const item of sourceSkills) {
|
|
80
|
+
if (typeof item === 'string') {
|
|
81
|
+
const name = item.trim();
|
|
82
|
+
if (!name) {
|
|
83
|
+
changed = true;
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
if (isOrchestratorToolName(name)) {
|
|
87
|
+
addToolBinding(toolsByName, { name, autoCall: false });
|
|
88
|
+
changed = true;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
nextSkills.push(name);
|
|
92
|
+
if (name !== item) {
|
|
93
|
+
changed = true;
|
|
94
|
+
}
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const legacyToolBinding = toToolBinding(item);
|
|
99
|
+
if (legacyToolBinding) {
|
|
100
|
+
addToolBinding(toolsByName, legacyToolBinding);
|
|
101
|
+
}
|
|
102
|
+
changed = true;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const normalized = {
|
|
107
|
+
...source,
|
|
108
|
+
skills: nextSkills,
|
|
109
|
+
tools: Array.from(toolsByName.values()),
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
return {
|
|
113
|
+
changed,
|
|
114
|
+
skillSettings: normalized,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
@@ -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 {};
|