plugin-agent-orchestrator 1.0.17 → 1.0.18

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 (139) hide show
  1. package/dist/client/AIEmployeeSelect.d.ts +11 -0
  2. package/dist/client/AIEmployeesContext.d.ts +30 -0
  3. package/dist/client/AgentRunsTab.d.ts +2 -0
  4. package/dist/client/HarnessProfilesTab.d.ts +2 -0
  5. package/dist/client/OrchestratorSettings.d.ts +3 -0
  6. package/dist/client/RulesTab.d.ts +2 -0
  7. package/dist/client/TracingTab.d.ts +2 -0
  8. package/dist/client/index.d.ts +1 -0
  9. package/dist/client/index.js +1 -1
  10. package/dist/client/plugin.d.ts +6 -0
  11. package/dist/client/skill-hub/components/ExecutionHistory.d.ts +2 -0
  12. package/dist/client/skill-hub/components/ExecutionProgress.d.ts +20 -0
  13. package/dist/client/skill-hub/components/GitSkillImport.d.ts +7 -0
  14. package/dist/client/skill-hub/components/LoopSettings.d.ts +2 -0
  15. package/dist/client/skill-hub/components/SkillEditor.d.ts +7 -0
  16. package/dist/client/skill-hub/components/SkillManager.d.ts +2 -0
  17. package/dist/client/skill-hub/components/SkillMetrics.d.ts +2 -0
  18. package/dist/client/skill-hub/components/SkillTestPanel.d.ts +7 -0
  19. package/dist/client/skill-hub/index.d.ts +11 -0
  20. package/dist/client/skill-hub/locale.d.ts +3 -0
  21. package/dist/client/skill-hub/tools/InteractionSchemasProvider.d.ts +6 -0
  22. package/dist/client/skill-hub/tools/SkillHubCard.d.ts +3 -0
  23. package/dist/client/skill-hub/tools/loopTemplates.d.ts +22 -0
  24. package/dist/client/skill-hub/tools/registerSkillLoopCards.d.ts +1 -0
  25. package/dist/client/skill-hub/utils/jsonFields.d.ts +3 -0
  26. package/dist/client/tools/PlanApprovalCard.d.ts +3 -0
  27. package/dist/client/tools/registerOrchestratorCards.d.ts +1 -0
  28. package/dist/externalVersion.js +6 -6
  29. package/dist/index.d.ts +2 -0
  30. package/dist/server/collections/agent-execution-spans.d.ts +9 -0
  31. package/dist/server/collections/agent-harness-profiles.d.ts +2 -0
  32. package/dist/server/collections/agent-harness-profiles.js +89 -0
  33. package/dist/server/collections/agent-loop-events.d.ts +2 -0
  34. package/dist/server/collections/agent-loop-events.js +101 -0
  35. package/dist/server/collections/agent-loop-runs.d.ts +2 -0
  36. package/dist/server/collections/agent-loop-runs.js +188 -0
  37. package/dist/server/collections/agent-loop-steps.d.ts +2 -0
  38. package/dist/server/collections/agent-loop-steps.js +174 -0
  39. package/dist/server/collections/orchestrator-config.d.ts +2 -0
  40. package/dist/server/collections/orchestrator-config.js +7 -0
  41. package/dist/server/collections/orchestrator-logs.d.ts +8 -0
  42. package/dist/server/collections/skill-definitions.d.ts +3 -0
  43. package/dist/server/collections/skill-executions.d.ts +3 -0
  44. package/dist/server/collections/skill-executions.js +12 -0
  45. package/dist/server/collections/skill-loop-configs.d.ts +3 -0
  46. package/dist/server/collections/skill-loop-configs.js +94 -0
  47. package/dist/server/collections/skill-worker-configs.d.ts +3 -0
  48. package/dist/server/index.d.ts +1 -0
  49. package/dist/server/migrations/20260423000000-add-progress-fields.d.ts +4 -0
  50. package/dist/server/migrations/20260425000000-add-interaction-schema.d.ts +4 -0
  51. package/dist/server/migrations/20260427000000-add-tracing-detail-fields.d.ts +7 -0
  52. package/dist/server/migrations/20260427000000-change-packages-to-text.d.ts +4 -0
  53. package/dist/server/migrations/20260427000001-change-other-json-to-text.d.ts +4 -0
  54. package/dist/server/migrations/20260429000000-add-llm-fields.d.ts +7 -0
  55. package/dist/server/migrations/20260429000000-fix-inputargs-json-to-text.d.ts +16 -0
  56. package/dist/server/migrations/20260503000000-add-orchestrator-trace-fields.d.ts +7 -0
  57. package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.d.ts +7 -0
  58. package/dist/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.js +55 -0
  59. package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.d.ts +12 -0
  60. package/dist/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.js +162 -0
  61. package/dist/server/plugin.d.ts +16 -0
  62. package/dist/server/plugin.js +13 -0
  63. package/dist/server/resources/agent-loop.d.ts +3 -0
  64. package/dist/server/resources/agent-loop.js +205 -0
  65. package/dist/server/resources/tracing.d.ts +7 -0
  66. package/dist/server/services/AgentHarness.d.ts +42 -0
  67. package/dist/server/services/AgentHarness.js +565 -0
  68. package/dist/server/services/AgentLoopController.d.ts +205 -0
  69. package/dist/server/services/AgentLoopController.js +940 -0
  70. package/dist/server/services/AgentLoopRepository.d.ts +20 -0
  71. package/dist/server/services/AgentLoopRepository.js +210 -0
  72. package/dist/server/services/AgentLoopService.d.ts +149 -0
  73. package/dist/server/services/AgentLoopService.js +133 -0
  74. package/dist/server/services/AgentPlanValidator.d.ts +4 -0
  75. package/dist/server/services/AgentPlanValidator.js +99 -0
  76. package/dist/server/services/AgentPlannerService.d.ts +8 -0
  77. package/dist/server/services/AgentPlannerService.js +119 -0
  78. package/dist/server/services/AgentRegistryService.d.ts +13 -0
  79. package/dist/server/services/AgentRegistryService.js +178 -0
  80. package/dist/server/services/CodeValidator.d.ts +32 -0
  81. package/dist/server/services/ExecutionSpanService.d.ts +46 -0
  82. package/dist/server/services/FileManager.d.ts +28 -0
  83. package/dist/server/services/SandboxRunner.d.ts +41 -0
  84. package/dist/server/services/SkillManager.d.ts +6 -0
  85. package/dist/server/services/SkillRepositoryService.d.ts +22 -0
  86. package/dist/server/services/WorkerEnvManager.d.ts +26 -0
  87. package/dist/server/skill-hub/actions/git-import.d.ts +21 -0
  88. package/dist/server/skill-hub/mcp/McpController.d.ts +15 -0
  89. package/dist/server/skill-hub/plugin.d.ts +61 -0
  90. package/dist/server/skill-hub/plugin.js +137 -54
  91. package/dist/server/skill-hub/tasks/SkillExecutionTask.d.ts +16 -0
  92. package/dist/server/skill-hub/utils/json-fields.d.ts +7 -0
  93. package/dist/server/tools/agent-loop.d.ts +235 -0
  94. package/dist/server/tools/agent-loop.js +406 -0
  95. package/dist/server/tools/delegate-task.d.ts +19 -0
  96. package/dist/server/tools/delegate-task.js +19 -368
  97. package/dist/server/tools/external-rag-search.d.ts +42 -0
  98. package/dist/server/tools/orchestrator-plan.d.ts +205 -0
  99. package/dist/server/tools/orchestrator-plan.js +291 -0
  100. package/dist/server/tools/skill-execute.d.ts +36 -0
  101. package/dist/server/tools/skill-execute.js +2 -0
  102. package/package.json +1 -1
  103. package/src/client/AgentRunsTab.tsx +764 -0
  104. package/src/client/HarnessProfilesTab.tsx +247 -0
  105. package/src/client/OrchestratorSettings.tsx +40 -2
  106. package/src/client/RulesTab.tsx +103 -6
  107. package/src/client/plugin.tsx +27 -54
  108. package/src/client/skill-hub/components/LoopSettings.tsx +331 -0
  109. package/src/client/skill-hub/index.tsx +51 -75
  110. package/src/client/skill-hub/tools/InteractionSchemasProvider.tsx +56 -16
  111. package/src/client/skill-hub/tools/SkillHubCard.tsx +35 -4
  112. package/src/client/skill-hub/tools/loopTemplates.ts +52 -0
  113. package/src/client/skill-hub/tools/registerSkillLoopCards.ts +58 -0
  114. package/src/client/tools/PlanApprovalCard.tsx +175 -0
  115. package/src/client/tools/registerOrchestratorCards.ts +7 -0
  116. package/src/server/collections/agent-harness-profiles.ts +59 -0
  117. package/src/server/collections/agent-loop-events.ts +71 -0
  118. package/src/server/collections/agent-loop-runs.ts +158 -0
  119. package/src/server/collections/agent-loop-steps.ts +144 -0
  120. package/src/server/collections/orchestrator-config.ts +7 -0
  121. package/src/server/collections/skill-executions.ts +63 -51
  122. package/src/server/collections/skill-loop-configs.ts +65 -0
  123. package/src/server/migrations/20260524000000-add-agent-loop-fields-to-skill-executions.ts +30 -0
  124. package/src/server/migrations/20260524001000-add-plan-approval-and-harness-profiles.ts +142 -0
  125. package/src/server/plugin.ts +15 -0
  126. package/src/server/resources/agent-loop.ts +183 -0
  127. package/src/server/services/AgentHarness.ts +663 -0
  128. package/src/server/services/AgentLoopController.ts +1128 -0
  129. package/src/server/services/AgentLoopRepository.ts +194 -0
  130. package/src/server/services/AgentLoopService.ts +161 -0
  131. package/src/server/services/AgentPlanValidator.ts +73 -0
  132. package/src/server/services/AgentPlannerService.ts +93 -0
  133. package/src/server/services/AgentRegistryService.ts +169 -0
  134. package/src/server/services/ExecutionSpanService.ts +2 -0
  135. package/src/server/skill-hub/plugin.ts +881 -771
  136. package/src/server/tools/agent-loop.ts +399 -0
  137. package/src/server/tools/delegate-task.ts +23 -485
  138. package/src/server/tools/orchestrator-plan.ts +279 -0
  139. package/src/server/tools/skill-execute.ts +68 -64
@@ -0,0 +1,279 @@
1
+ import { z } from 'zod';
2
+ import { AgentLoopPlanStepInput, AgentLoopService } from '../services/AgentLoopService';
3
+
4
+ const stepSchema = z.object({
5
+ id: z.string().optional(),
6
+ key: z.string().optional(),
7
+ planKey: z.string().optional(),
8
+ parentStepId: z.union([z.string(), z.number()]).optional(),
9
+ title: z.string().optional(),
10
+ description: z.string().optional(),
11
+ type: z.enum(['reasoning', 'skill', 'tool', 'sub_agent', 'verification']).optional(),
12
+ target: z.string().optional(),
13
+ input: z.any().optional(),
14
+ dependsOn: z.array(z.string()).optional(),
15
+ dependencyPolicy: z.enum(['require_success', 'allow_skipped']).optional(),
16
+ maxAttempts: z.number().int().min(1).max(10).optional(),
17
+ metadata: z.any().optional(),
18
+ });
19
+
20
+ const policySchema = z
21
+ .object({
22
+ maxIterations: z.number().int().min(1).max(100).optional(),
23
+ maxStepAttempts: z.number().int().min(1).max(10).optional(),
24
+ allowReplan: z.boolean().optional(),
25
+ requireVerification: z.boolean().optional(),
26
+ stopOnApprovalRequired: z.boolean().optional(),
27
+ })
28
+ .optional();
29
+
30
+ function toolResult(status: 'success' | 'error', payload: any) {
31
+ return {
32
+ status,
33
+ content: typeof payload === 'string' ? payload : JSON.stringify(payload),
34
+ };
35
+ }
36
+
37
+ function valuesFromCtx(ctx: any) {
38
+ return ctx?.action?.params?.values || ctx?.request?.body || {};
39
+ }
40
+
41
+ function currentUserId(ctx: any) {
42
+ return ctx?.state?.currentUser?.id || ctx?.auth?.user?.id;
43
+ }
44
+
45
+ function resolveSessionId(ctx: any, args: any) {
46
+ const values = valuesFromCtx(ctx);
47
+ return args?.sessionId || values.sessionId || ctx?.action?.params?.sessionId || ctx?.state?.sessionId;
48
+ }
49
+
50
+ function resolveMessageId(ctx: any, args: any) {
51
+ const values = valuesFromCtx(ctx);
52
+ return args?.messageId || values.messageId || ctx?.action?.params?.messageId;
53
+ }
54
+
55
+ function normalizeEmployeeUsername(raw: any) {
56
+ if (!raw) return null;
57
+ if (typeof raw === 'string') return raw;
58
+ return raw.username || raw.aiEmployeeUsername || raw.name || null;
59
+ }
60
+
61
+ async function resolveLeaderUsername(ctx: any, plugin: any, args: any) {
62
+ const values = valuesFromCtx(ctx);
63
+ const direct = normalizeEmployeeUsername(
64
+ args?.leaderUsername ||
65
+ ctx?._currentAIEmployee ||
66
+ ctx?.state?.currentAIEmployee ||
67
+ ctx?.runtime?.context?.currentAIEmployee ||
68
+ values.aiEmployee,
69
+ );
70
+ if (direct) return direct;
71
+
72
+ const sessionId = resolveSessionId(ctx, args);
73
+ if (!sessionId) return undefined;
74
+ try {
75
+ const repo = ctx?.db?.getRepository?.('aiConversations') || plugin.db.getRepository('aiConversations');
76
+ const conversation = await repo.findOne({ filter: { sessionId } });
77
+ return normalizeEmployeeUsername(conversation?.aiEmployeeUsername || conversation?.get?.('aiEmployeeUsername'));
78
+ } catch {
79
+ return undefined;
80
+ }
81
+ }
82
+
83
+ function summarizePlan(steps: any[]) {
84
+ return (steps || []).map((step) => ({
85
+ id: step.id,
86
+ planKey: step.planKey,
87
+ title: step.title,
88
+ description: step.description,
89
+ type: step.type,
90
+ target: step.target,
91
+ dependsOn: step.dependsOn || [],
92
+ status: step.status,
93
+ }));
94
+ }
95
+
96
+ function inferTargetAgent(args: any) {
97
+ if (args?.targetAgent) return args.targetAgent;
98
+ const plan = Array.isArray(args?.plan) ? args.plan : [];
99
+ const subAgentStep = plan.find((step: any) => step?.type === 'sub_agent' && step?.target);
100
+ return subAgentStep?.target;
101
+ }
102
+
103
+ async function resolveHarnessTag(plugin: any, leaderUsername: string | undefined, targetAgent: string | undefined, args: any) {
104
+ const direct = String(args?.harnessTag || args?.metadata?.harnessTag || '').trim();
105
+ if (direct) return direct;
106
+ if (!leaderUsername || !targetAgent) return 'default';
107
+ try {
108
+ const repo = plugin.db.getRepository('orchestratorConfig');
109
+ const config = await repo.findOne({
110
+ filter: {
111
+ leaderUsername,
112
+ subAgentUsername: targetAgent,
113
+ enabled: true,
114
+ },
115
+ });
116
+ return config?.harnessTag || config?.get?.('harnessTag') || 'default';
117
+ } catch {
118
+ return 'default';
119
+ }
120
+ }
121
+
122
+ export function createOrchestratorPlanTools(plugin: any, service: AgentLoopService) {
123
+ return [
124
+ {
125
+ scope: 'CUSTOM' as const,
126
+ execution: 'backend' as const,
127
+ defaultPermission: 'ALLOW' as const,
128
+ introduction: {
129
+ title: 'Orchestrator - Plan Goal',
130
+ about: 'Create a draft plan and pause for explicit user approval before execution.',
131
+ },
132
+ definition: {
133
+ name: 'orchestrator_plan_goal',
134
+ description:
135
+ 'Create or revise a persistent orchestrator run in waiting_plan_approval state. Use this before any multi-step/sub-agent execution. Provide a concrete plan with small executable steps and stable planKey dependencies whenever possible. Pass runId only when revising after user-requested changes. This tool does not execute the plan.',
136
+ schema: z.object({
137
+ goal: z.string().min(1).describe('The user goal to complete.'),
138
+ runId: z
139
+ .union([z.string(), z.number()])
140
+ .optional()
141
+ .describe('Existing run id to revise after the user requested plan changes. Omit for a new run.'),
142
+ leaderUsername: z.string().optional().describe('Leader AI employee username. Usually omit; inferred from chat.'),
143
+ sessionId: z.string().optional(),
144
+ messageId: z.string().optional(),
145
+ harnessTag: z.string().optional().default('default').describe('Harness profile tag, for example default, safe, or file-heavy.'),
146
+ targetAgent: z.string().optional().describe('Optional sub-agent username for generated fallback plans.'),
147
+ plannerModel: z.string().optional(),
148
+ policy: policySchema,
149
+ metadata: z.any().optional(),
150
+ plan: z
151
+ .array(stepSchema)
152
+ .optional()
153
+ .describe('Draft plan steps. Tool/sub_agent steps should include target. Dependencies must reference planKey values.'),
154
+ }),
155
+ },
156
+ invoke: async (ctx: any, args: any) => {
157
+ try {
158
+ const leaderUsername = await resolveLeaderUsername(ctx, plugin, args);
159
+ const targetAgent = inferTargetAgent(args);
160
+ const harnessTag = await resolveHarnessTag(plugin, leaderUsername, targetAgent, args);
161
+ const detail = await service.planGoal({
162
+ goal: args.goal,
163
+ runId: args.runId,
164
+ leaderUsername,
165
+ sessionId: resolveSessionId(ctx, args),
166
+ messageId: resolveMessageId(ctx, args),
167
+ userId: currentUserId(ctx),
168
+ policy: args.policy,
169
+ metadata: args.metadata,
170
+ plan: Array.isArray(args.plan) ? (args.plan as AgentLoopPlanStepInput[]) : undefined,
171
+ plannerModel: args.plannerModel,
172
+ harnessTag,
173
+ targetAgent,
174
+ });
175
+ return toolResult('success', {
176
+ run: detail.run,
177
+ plan: summarizePlan(detail.steps),
178
+ approval: {
179
+ required: true,
180
+ nextTool: 'orchestrator_execute_plan',
181
+ args: {
182
+ runId: detail.run.id,
183
+ planVersion: detail.run.planVersion || 1,
184
+ plan: summarizePlan(detail.steps),
185
+ },
186
+ },
187
+ });
188
+ } catch (error: any) {
189
+ return toolResult('error', error?.message || String(error));
190
+ }
191
+ },
192
+ },
193
+ {
194
+ scope: 'CUSTOM' as const,
195
+ execution: 'backend' as const,
196
+ defaultPermission: 'ASK' as const,
197
+ introduction: {
198
+ title: 'Orchestrator - Execute Approved Plan',
199
+ about: 'Execute a draft plan only after the user approves the plan card.',
200
+ },
201
+ definition: {
202
+ name: 'orchestrator_execute_plan',
203
+ description:
204
+ 'Execute a run created by orchestrator_plan_goal. This tool must be called with the runId after the user reviews the plan. The UI will ask the user to accept or reject the plan before invoke runs.',
205
+ schema: z.object({
206
+ runId: z.union([z.string(), z.number()]).describe('The agentLoopRuns id returned by orchestrator_plan_goal.'),
207
+ planVersion: z.number().int().optional(),
208
+ plan: z.array(stepSchema).optional().describe('Optional copy of the displayed plan for the approval UI.'),
209
+ reason: z.string().optional(),
210
+ }),
211
+ },
212
+ invoke: async (ctx: any, args: any) => {
213
+ try {
214
+ const detail = await service.approvePlanAndExecute(args.runId, {
215
+ userId: currentUserId(ctx),
216
+ ctx,
217
+ reason: args.reason,
218
+ });
219
+ return toolResult('success', detail);
220
+ } catch (error: any) {
221
+ return toolResult('error', error?.message || String(error));
222
+ }
223
+ },
224
+ },
225
+ {
226
+ scope: 'CUSTOM' as const,
227
+ execution: 'backend' as const,
228
+ defaultPermission: 'ALLOW' as const,
229
+ introduction: {
230
+ title: 'Orchestrator - Status',
231
+ about: 'Read a run, its plan steps, events, and linked traces.',
232
+ },
233
+ definition: {
234
+ name: 'orchestrator_status',
235
+ description: 'Read the current status of an orchestrator run without mutating it.',
236
+ schema: z.object({
237
+ runId: z.union([z.string(), z.number()]),
238
+ }),
239
+ },
240
+ invoke: async (_ctx: any, args: any) => {
241
+ try {
242
+ return toolResult('success', await service.getRunDetail(args.runId));
243
+ } catch (error: any) {
244
+ return toolResult('error', error?.message || String(error));
245
+ }
246
+ },
247
+ },
248
+ {
249
+ scope: 'CUSTOM' as const,
250
+ execution: 'backend' as const,
251
+ defaultPermission: 'ASK' as const,
252
+ introduction: {
253
+ title: 'Orchestrator - Cancel Run',
254
+ about: 'Cancel an orchestrator run with user approval.',
255
+ },
256
+ definition: {
257
+ name: 'orchestrator_cancel',
258
+ description: 'Cancel an orchestrator run. This mutates run state and therefore requires user approval.',
259
+ schema: z.object({
260
+ runId: z.union([z.string(), z.number()]),
261
+ reason: z.string().optional(),
262
+ }),
263
+ },
264
+ invoke: async (ctx: any, args: any) => {
265
+ try {
266
+ return toolResult(
267
+ 'success',
268
+ await service.cancelRun(args.runId, {
269
+ reason: args.reason,
270
+ userId: currentUserId(ctx),
271
+ }),
272
+ );
273
+ } catch (error: any) {
274
+ return toolResult('error', error?.message || String(error));
275
+ }
276
+ },
277
+ },
278
+ ];
279
+ }
@@ -1,29 +1,30 @@
1
1
  import { parseJsonText } from '../skill-hub/utils/json-fields';
2
2
 
3
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: 'A universal gateway to execute predefined specialized skills (data processing, complex calculations, file generation, etc.) inside a secure Python/Node.js sandbox.',
12
- },
13
-
14
- definition: {
15
- name: 'skill_hub_execute',
16
- description: `A universal gateway to execute various predefined specialized skills (e.g., data transformation, calculations, document/presentation generation) in an isolated sandbox.
17
- HOW TO USE THIS TOOL:
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:
18
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.
19
20
  2. For complex workflow skills, call { "action": "describe", "skillName": "<exact_skill_name>" } to load the full instructions before execution.
20
21
  3. To run a skill, call this tool with { "action": "execute", "skillName": "<exact_skill_name>", "input": { <parameters> } }.
21
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.
22
23
  The skill's output may contain text results, structured JSON data, or download URLs for generated files.
23
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.`,
24
- schema: {
25
- type: 'object',
26
- properties: {
25
+ schema: {
26
+ type: 'object',
27
+ properties: {
27
28
  action: {
28
29
  type: 'string',
29
30
  enum: ['list', 'describe', 'execute'],
@@ -44,7 +45,7 @@ IMPORTANT: If the skill returns file download URLs, you MUST format them as clic
44
45
 
45
46
  async invoke(ctx: any, args: Record<string, any>, _id?: string) {
46
47
  plugin.app.logger.info(`[skill-execute] Tool invoked with action: ${args.action}, skillName: ${args.skillName}`);
47
-
48
+
48
49
  // Action: list available skills
49
50
  if (args.action === 'list') {
50
51
  const skills = await plugin.db.getRepository('skillDefinitions').find({
@@ -61,10 +62,10 @@ IMPORTANT: If the skill returns file download URLs, you MUST format them as clic
61
62
  hasInstructions: !!s.get('instructions') || s.get('storageType') === 'plugin',
62
63
  storageType: s.get('storageType'),
63
64
  }));
64
-
65
- return {
66
- status: 'success',
67
- content: JSON.stringify({ skills: skillList }),
65
+
66
+ return {
67
+ status: 'success',
68
+ content: JSON.stringify({ skills: skillList }),
68
69
  };
69
70
  }
70
71
 
@@ -85,9 +86,10 @@ IMPORTANT: If the skill returns file download URLs, you MUST format them as clic
85
86
  };
86
87
  }
87
88
 
88
- const instructions = typeof plugin.getSkillInstructions === 'function'
89
- ? await plugin.getSkillInstructions(skill)
90
- : skill.get('instructions');
89
+ const instructions =
90
+ typeof plugin.getSkillInstructions === 'function'
91
+ ? await plugin.getSkillInstructions(skill)
92
+ : skill.get('instructions');
91
93
 
92
94
  return {
93
95
  status: 'success',
@@ -104,53 +106,55 @@ IMPORTANT: If the skill returns file download URLs, you MUST format them as clic
104
106
  }),
105
107
  };
106
108
  }
107
-
108
- // Action: execute skill
109
- if (args.action === 'execute') {
110
- if (!args.skillName) {
111
- return { status: 'error', content: 'Missing skillName parameter' };
112
- }
113
-
114
- const skill = await plugin.db.getRepository('skillDefinitions').findOne({
115
- filter: { name: args.skillName, enabled: true },
116
- });
117
-
118
- if (!skill) {
119
- return {
120
- status: 'error',
121
- content: `Skill "${args.skillName}" not found or disabled`,
122
- };
123
- }
124
-
125
- try {
126
- const result = await plugin.executeSkill(skill, args.input || {}, ctx);
127
-
128
- return {
129
- status: result.status === 'succeeded' ? 'success' : 'error',
130
- content: JSON.stringify({
131
- message:
132
- result.status === 'succeeded'
133
- ? `Executed successfully. ${result.files?.length || 0} file(s) generated.`
134
- : `Failed: ${result.stderr}`,
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}`,
135
137
  stdout: result.stdout,
136
138
  stderr: result.stderr,
137
139
  files: result.files,
138
140
  execId: result.execId,
141
+ agentLoopRunId: result.agentLoopRunId,
142
+ agentLoopStepId: result.agentLoopStepId,
139
143
  durationMs: result.durationMs,
140
144
  }),
141
145
  };
142
- } catch (error) {
143
- return {
144
- status: 'error',
145
- content: `Execution error: ${error instanceof Error ? error.message : String(error)}`,
146
- };
147
- }
148
- }
149
-
146
+ } catch (error) {
147
+ return {
148
+ status: 'error',
149
+ content: `Execution error: ${error instanceof Error ? error.message : String(error)}`,
150
+ };
151
+ }
152
+ }
153
+
150
154
  return {
151
155
  status: 'error',
152
156
  content: `Unknown action "${args.action}". Use "list", "describe", or "execute".`,
153
157
  };
154
- },
155
- };
156
- }
158
+ },
159
+ };
160
+ }