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,6 +1,14 @@
1
1
  import { z } from 'zod';
2
2
  import { AgentLoopPlanStepInput, AgentLoopService } from '../services/AgentLoopService';
3
3
  import { getOrchestratorTraceContext, setOrchestratorTraceContext } from '../services/ExecutionSpanService';
4
+ import {
5
+ currentUserId,
6
+ resolveSessionId,
7
+ resolveMessageId,
8
+ normalizeEmployeeUsername,
9
+ resolveLeaderUsername,
10
+ valuesFromCtx,
11
+ } from '../utils/ctx-utils';
4
12
 
5
13
  const stepSchema = z.object({
6
14
  id: z.string().optional(),
@@ -34,52 +42,6 @@ function toolResult(status: 'success' | 'error', payload: any) {
34
42
  };
35
43
  }
36
44
 
37
- function valuesFromCtx(ctx: any) {
38
- return ctx?.action?.params?.values || {};
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
45
  function setLoopTraceContext(ctx: any, snapshot: any, step?: any) {
84
46
  if (!ctx || !snapshot?.run) return;
85
47
  const existing: any = getOrchestratorTraceContext(ctx) || {};
@@ -139,7 +101,7 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
139
101
  metadata: args.metadata,
140
102
  plan: planFromArgs(args.plan),
141
103
  });
142
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
104
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
143
105
  return toolResult('success', snapshot);
144
106
  } catch (error: any) {
145
107
  return toolResult('error', error?.message || String(error));
@@ -152,12 +114,11 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
152
114
  defaultPermission: 'ALLOW' as const,
153
115
  introduction: {
154
116
  title: 'Agent Loop - Status',
155
- about: 'Read the current run, steps, and next executable step.',
117
+ about: 'Read the current run, steps, and next executable steps.',
156
118
  },
157
119
  definition: {
158
120
  name: 'agent_loop_status',
159
- description:
160
- 'Fetch an agent loop run. Call this before executing the next step so subsequent skill/tool calls can be linked to the current loop step.',
121
+ description: 'Fetch an agent loop run. Call this to check which steps are ready for execution.',
161
122
  schema: z.object({
162
123
  runId: z.union([z.string(), z.number()]),
163
124
  }),
@@ -165,7 +126,7 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
165
126
  invoke: async (ctx: any, args: any) => {
166
127
  try {
167
128
  const snapshot = await service.getRunSnapshot(args.runId);
168
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
129
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
169
130
  return toolResult('success', snapshot);
170
131
  } catch (error: any) {
171
132
  return toolResult('error', error?.message || String(error));
@@ -212,18 +173,18 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
212
173
  agentExecutionSpanId: args.agentExecutionSpanId,
213
174
  metadata: args.metadata,
214
175
  });
215
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
176
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
216
177
  } else if (args.status === 'failed') {
217
178
  snapshot = await service.failStep(args.stepId, args.error || 'Step failed.', {
218
179
  userId: currentUserId(ctx),
219
180
  metadata: args.metadata,
220
181
  });
221
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
182
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
222
183
  } else {
223
184
  snapshot = await service.skipStep(args.stepId, args.reason || 'Skipped.', {
224
185
  userId: currentUserId(ctx),
225
186
  });
226
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
187
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
227
188
  }
228
189
  return toolResult('success', snapshot);
229
190
  } catch (error: any) {
@@ -258,7 +219,7 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
258
219
  userId: currentUserId(ctx),
259
220
  });
260
221
  const snapshot = await service.getRunSnapshot(args.runId);
261
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
222
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
262
223
  return toolResult('success', snapshot);
263
224
  } catch (error: any) {
264
225
  return toolResult('error', error?.message || String(error));
@@ -289,7 +250,7 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
289
250
  reason: args.reason,
290
251
  userId: currentUserId(ctx),
291
252
  });
292
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
253
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
293
254
  return toolResult('success', snapshot);
294
255
  } catch (error: any) {
295
256
  return toolResult('error', error?.message || String(error));
@@ -324,7 +285,7 @@ export function createAgentLoopTools(plugin: any, service: AgentLoopService) {
324
285
  userId: currentUserId(ctx),
325
286
  ctx,
326
287
  });
327
- setLoopTraceContext(ctx, snapshot, snapshot.nextStep);
288
+ setLoopTraceContext(ctx, snapshot, snapshot.nextSteps?.[0]);
328
289
  return toolResult('success', snapshot);
329
290
  } catch (error: any) {
330
291
  return toolResult('error', error?.message || String(error));
@@ -12,6 +12,9 @@ import {
12
12
  getOrchestratorTraceContext,
13
13
  setOrchestratorTraceContext,
14
14
  } from '../services/ExecutionSpanService';
15
+ import { captureCtxSnapshot, normalizeEmployeeUsername, trimText as truncateText, nowIso } from '../utils/ctx-utils';
16
+ import { logDelegation as sharedLogDelegation } from '../utils/logging';
17
+ import { CtxSnapshot, TraceEvent } from '../types';
15
18
 
16
19
  /**
17
20
  * Maximum delegation depth key stored in ctx metadata.
@@ -31,16 +34,6 @@ const MAX_DISPATCH_TASKS = 20;
31
34
  /** OpenAI/Anthropic tool-name limit. Names exceeding this are silently rejected by providers. */
32
35
  const MAX_TOOL_NAME_LENGTH = 64;
33
36
 
34
- type TraceEvent = {
35
- type: string;
36
- at: string;
37
- title: string;
38
- content?: string;
39
- toolName?: string;
40
- args?: any;
41
- status?: string;
42
- };
43
-
44
37
  type AgentExecutionResult = {
45
38
  content: string;
46
39
  messages: any[];
@@ -437,31 +430,6 @@ function createDispatchToolOptions(
437
430
  };
438
431
  }
439
432
 
440
- type CtxSnapshot = {
441
- userId?: number;
442
- };
443
-
444
- /**
445
- * Read the few ctx fields we depend on once, before kicking off the long-running
446
- * sub-agent. Avoids "ctx is destroyed" or stale-state issues when we later
447
- * write the orchestratorLogs row from inside the agent's execution promise.
448
- */
449
- function captureCtxSnapshot(ctx: Context): CtxSnapshot {
450
- let userId: number | undefined;
451
- try {
452
- userId = (ctx as any).auth?.user?.id || (ctx as any).state?.currentUser?.id;
453
- } catch {
454
- // ctx already disposed — nothing to capture.
455
- }
456
- return { userId };
457
- }
458
-
459
- function normalizeEmployeeUsername(raw: any) {
460
- if (!raw) return null;
461
- if (typeof raw === 'string') return raw;
462
- return raw.username || raw.aiEmployeeUsername || raw.name || null;
463
- }
464
-
465
433
  async function resolveCallingEmployee(ctx: Context, plugin: any) {
466
434
  const values = (ctx as any).action?.params?.values || {};
467
435
  const raw =
@@ -488,15 +456,6 @@ async function resolveCallingEmployee(ctx: Context, plugin: any) {
488
456
  }
489
457
  }
490
458
 
491
- function truncateText(value: any, maxLen: number) {
492
- const text = typeof value === 'string' ? value : value == null ? '' : JSON.stringify(value);
493
- return text.length > maxLen ? `${text.slice(0, maxLen)}\n...[truncated]` : text;
494
- }
495
-
496
- function nowIso() {
497
- return new Date().toISOString();
498
- }
499
-
500
459
  function hasModelSettings(value: any): value is { llmService: string; model: string } {
501
460
  return Boolean(value?.llmService && value?.model);
502
461
  }
@@ -889,55 +848,14 @@ async function logDelegation(
889
848
  snapshot?: CtxSnapshot;
890
849
  },
891
850
  ) {
892
- try {
893
- const logsRepo = plugin.db.getRepository('orchestratorLogs');
894
- if (!logsRepo) {
895
- plugin.app.log.warn('[AgentOrchestrator] orchestratorLogs repository not found — skipping log');
896
- return;
897
- }
898
-
899
- let userId: number | undefined = data.snapshot?.userId;
900
- if (userId == null) {
901
- try {
902
- userId = ctx.auth?.user?.id || ctx.state?.currentUser?.id;
903
- } catch {
904
- // ctx lifecycle ended
905
- }
906
- }
907
-
908
- const values = {
909
- leaderUsername: data.leaderUsername,
910
- subAgentUsername: data.subAgentUsername,
911
- toolName: data.toolName,
912
- task: truncateText(data.task, 10000),
913
- context: truncateText(data.context || '', 10000),
914
- result: truncateText(data.result || '', 50000),
915
- status: data.status,
916
- depth: data.depth,
917
- durationMs: data.durationMs,
918
- error: truncateText(data.error || '', 10000),
919
- trace: data.trace || [],
920
- messages: data.messages || [],
921
- userId,
922
- updatedAt: new Date(),
923
- };
924
-
925
- if (data.id) {
926
- await logsRepo.update({
927
- filterByTk: data.id,
928
- values,
929
- });
930
- return { id: data.id };
851
+ // Capture userId from snapshot or ctx
852
+ let userId: number | string | undefined = data.snapshot?.userId;
853
+ if (userId == null) {
854
+ try {
855
+ userId = (ctx as any).auth?.user?.id || (ctx as any).state?.currentUser?.id;
856
+ } catch {
857
+ // ctx lifecycle ended
931
858
  }
932
-
933
- const record = await logsRepo.create({
934
- values: {
935
- ...values,
936
- createdAt: new Date(),
937
- },
938
- });
939
- return record?.toJSON?.() || record;
940
- } catch (e) {
941
- plugin.app.log.warn('[AgentOrchestrator] Failed to log delegation event', e);
942
859
  }
860
+ return sharedLogDelegation(ctx, plugin, { ...data, userId });
943
861
  }
@@ -1,5 +1,13 @@
1
1
  import { z } from 'zod';
2
2
  import { AgentLoopPlanStepInput, AgentLoopService } from '../services/AgentLoopService';
3
+ import {
4
+ currentUserId,
5
+ resolveSessionId,
6
+ resolveMessageId,
7
+ normalizeEmployeeUsername,
8
+ resolveLeaderUsername,
9
+ valuesFromCtx,
10
+ } from '../utils/ctx-utils';
3
11
 
4
12
  const stepSchema = z.object({
5
13
  id: z.string().optional(),
@@ -34,52 +42,6 @@ function toolResult(status: 'success' | 'error', payload: any) {
34
42
  };
35
43
  }
36
44
 
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
45
  function summarizePlan(steps: any[]) {
84
46
  return (steps || []).map((step) => ({
85
47
  id: step.id,
@@ -100,7 +62,12 @@ function inferTargetAgent(args: any) {
100
62
  return subAgentStep?.target;
101
63
  }
102
64
 
103
- async function resolveHarnessTag(plugin: any, leaderUsername: string | undefined, targetAgent: string | undefined, args: any) {
65
+ async function resolveHarnessTag(
66
+ plugin: any,
67
+ leaderUsername: string | undefined,
68
+ targetAgent: string | undefined,
69
+ args: any,
70
+ ) {
104
71
  const direct = String(args?.harnessTag || args?.metadata?.harnessTag || '').trim();
105
72
  if (direct) return direct;
106
73
  if (!leaderUsername || !targetAgent) return 'default';
@@ -139,10 +106,17 @@ export function createOrchestratorPlanTools(plugin: any, service: AgentLoopServi
139
106
  .union([z.string(), z.number()])
140
107
  .optional()
141
108
  .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.'),
109
+ leaderUsername: z
110
+ .string()
111
+ .optional()
112
+ .describe('Leader AI employee username. Usually omit; inferred from chat.'),
143
113
  sessionId: z.string().optional(),
144
114
  messageId: z.string().optional(),
145
- harnessTag: z.string().optional().default('default').describe('Harness profile tag, for example default, safe, or file-heavy.'),
115
+ harnessTag: z
116
+ .string()
117
+ .optional()
118
+ .default('default')
119
+ .describe('Harness profile tag, for example default, safe, or file-heavy.'),
146
120
  targetAgent: z.string().optional().describe('Optional sub-agent username for generated fallback plans.'),
147
121
  plannerModel: z.string().optional(),
148
122
  policy: policySchema,
@@ -150,7 +124,9 @@ export function createOrchestratorPlanTools(plugin: any, service: AgentLoopServi
150
124
  plan: z
151
125
  .array(stepSchema)
152
126
  .optional()
153
- .describe('Draft plan steps. Tool/sub_agent steps should include target. Dependencies must reference planKey values.'),
127
+ .describe(
128
+ 'Draft plan steps. Tool/sub_agent steps should include target. Dependencies must reference planKey values.',
129
+ ),
154
130
  }),
155
131
  },
156
132
  invoke: async (ctx: any, args: any) => {