@memberjunction/ai-prompts 3.4.0 → 4.1.0
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/README.md +155 -3104
- package/dist/AIPromptRunner.d.ts +540 -2
- package/dist/AIPromptRunner.d.ts.map +1 -1
- package/dist/AIPromptRunner.js +1156 -232
- package/dist/AIPromptRunner.js.map +1 -1
- package/dist/ExecutionPlanner.d.ts +116 -1
- package/dist/ExecutionPlanner.d.ts.map +1 -1
- package/dist/ExecutionPlanner.js +171 -40
- package/dist/ExecutionPlanner.js.map +1 -1
- package/dist/ParallelExecution.d.ts +178 -1
- package/dist/ParallelExecution.d.ts.map +1 -1
- package/dist/ParallelExecution.js +1 -2
- package/dist/ParallelExecutionCoordinator.d.ts +182 -3
- package/dist/ParallelExecutionCoordinator.d.ts.map +1 -1
- package/dist/ParallelExecutionCoordinator.js +304 -79
- package/dist/ParallelExecutionCoordinator.js.map +1 -1
- package/dist/__tests__/AIPromptRunner.failover.test.d.ts +21 -0
- package/dist/__tests__/AIPromptRunner.failover.test.d.ts.map +1 -1
- package/dist/__tests__/AIPromptRunner.failover.test.js +92 -6
- package/dist/__tests__/AIPromptRunner.failover.test.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -19
- package/dist/index.js.map +1 -1
- package/package.json +21 -20
|
@@ -1,33 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.ParallelExecutionCoordinator = void 0;
|
|
27
|
-
const core_1 = require("@memberjunction/core");
|
|
28
|
-
const global_1 = require("@memberjunction/global");
|
|
29
|
-
const ai_1 = require("@memberjunction/ai");
|
|
30
|
-
const aiengine_1 = require("@memberjunction/aiengine");
|
|
1
|
+
import { LogError, LogStatus, Metadata } from '@memberjunction/core';
|
|
2
|
+
import { MJGlobal } from '@memberjunction/global';
|
|
3
|
+
import { BaseLLM, ChatParams, ChatMessageRole, GetAIAPIKey } from '@memberjunction/ai';
|
|
4
|
+
import { AIEngine } from '@memberjunction/aiengine';
|
|
5
|
+
/**
|
|
6
|
+
* Helper class for tracking parallel execution progress
|
|
7
|
+
*/
|
|
31
8
|
class ParallelProgressTracker {
|
|
32
9
|
constructor(totalTasks, totalGroups, progressCallbacks) {
|
|
33
10
|
this.completedTasks = 0;
|
|
@@ -72,6 +49,7 @@ class ParallelProgressTracker {
|
|
|
72
49
|
else {
|
|
73
50
|
this.failedTasks++;
|
|
74
51
|
}
|
|
52
|
+
// Send task completion update if enabled
|
|
75
53
|
if (this.progressCallbacks?.getStreamingConfig()?.enabled) {
|
|
76
54
|
const config = this.progressCallbacks.getStreamingConfig();
|
|
77
55
|
if (config.callbacks?.OnTaskComplete) {
|
|
@@ -103,23 +81,53 @@ class ParallelProgressTracker {
|
|
|
103
81
|
}
|
|
104
82
|
}
|
|
105
83
|
}
|
|
106
|
-
|
|
84
|
+
/**
|
|
85
|
+
* Coordinates parallel execution of AI prompt tasks across multiple models and execution groups.
|
|
86
|
+
*
|
|
87
|
+
* This class manages the complex orchestration of:
|
|
88
|
+
* - Grouping tasks by execution group
|
|
89
|
+
* - Sequential execution of groups with parallel execution within groups
|
|
90
|
+
* - Result aggregation and selection
|
|
91
|
+
* - Error handling and partial result collection
|
|
92
|
+
* - Performance monitoring and metrics collection
|
|
93
|
+
* - Real-time progress tracking and streaming updates
|
|
94
|
+
*/
|
|
95
|
+
export class ParallelExecutionCoordinator {
|
|
96
|
+
/**
|
|
97
|
+
* Creates a new parallel execution coordinator with default configuration.
|
|
98
|
+
*/
|
|
107
99
|
constructor() {
|
|
108
|
-
this._metadata = new
|
|
100
|
+
this._metadata = new Metadata();
|
|
109
101
|
this._defaultConfig = {
|
|
110
102
|
maxConcurrentExecutions: 5,
|
|
111
|
-
taskTimeoutMS: 30000,
|
|
103
|
+
taskTimeoutMS: 30000, // 30 seconds
|
|
112
104
|
failFast: false,
|
|
113
105
|
collectPartialResults: true,
|
|
114
106
|
maxRetries: 3,
|
|
115
107
|
retryDelayMS: 1000,
|
|
116
108
|
};
|
|
117
109
|
}
|
|
118
|
-
|
|
110
|
+
/**
|
|
111
|
+
* Executes multiple tasks in parallel according to their execution groups.
|
|
112
|
+
*
|
|
113
|
+
* Tasks are grouped by their executionGroup property and executed sequentially by group.
|
|
114
|
+
* Within each group, tasks are executed in parallel up to the concurrency limit.
|
|
115
|
+
*
|
|
116
|
+
* @param tasks - Array of execution tasks to process
|
|
117
|
+
* @param config - Optional configuration to override defaults
|
|
118
|
+
* @param parentPromptRunId - Optional parent prompt run ID for hierarchical logging
|
|
119
|
+
* @param cancellationToken - Optional cancellation token to abort execution
|
|
120
|
+
* @param progressCallbacks - Optional callbacks for progress tracking
|
|
121
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
122
|
+
* @returns Promise<ParallelExecutionResult> - Aggregated results from all executions
|
|
123
|
+
*/
|
|
124
|
+
async executeTasksInParallel(params, tasks, config, parentPromptRunId, cancellationToken, progressCallbacks, // Using interface to avoid circular dependency
|
|
125
|
+
agentRunId) {
|
|
119
126
|
const startTime = new Date();
|
|
120
127
|
const executionConfig = { ...this._defaultConfig, ...config };
|
|
128
|
+
// Check for cancellation at the start
|
|
121
129
|
if (cancellationToken?.aborted) {
|
|
122
|
-
|
|
130
|
+
LogStatus('Parallel execution cancelled before starting');
|
|
123
131
|
return {
|
|
124
132
|
success: false,
|
|
125
133
|
taskResults: [],
|
|
@@ -134,22 +142,27 @@ class ParallelExecutionCoordinator {
|
|
|
134
142
|
endTime: new Date(),
|
|
135
143
|
};
|
|
136
144
|
}
|
|
137
|
-
|
|
145
|
+
LogStatus(`Starting parallel execution of ${tasks.length} tasks with config: ${JSON.stringify(executionConfig)}`);
|
|
138
146
|
try {
|
|
147
|
+
// Propagate cancellation token to all tasks
|
|
139
148
|
if (cancellationToken) {
|
|
140
149
|
tasks.forEach((task) => {
|
|
141
150
|
task.cancellationToken = cancellationToken;
|
|
142
151
|
});
|
|
143
152
|
}
|
|
153
|
+
// Group tasks by execution group
|
|
144
154
|
const executionGroups = this.groupTasksByExecutionGroup(tasks);
|
|
155
|
+
// Initialize progress tracker
|
|
145
156
|
const progressTracker = new ParallelProgressTracker(tasks.length, executionGroups.length, progressCallbacks);
|
|
157
|
+
// Execute groups sequentially, tasks within groups in parallel
|
|
146
158
|
const allResults = await this.executeGroupsSequentially(params, executionGroups, executionConfig, parentPromptRunId, cancellationToken, progressTracker, agentRunId);
|
|
159
|
+
// Aggregate results and calculate metrics
|
|
147
160
|
const result = this.aggregateResults(allResults, startTime, new Date());
|
|
148
|
-
|
|
161
|
+
LogStatus(`Parallel execution completed: ${result.successCount}/${tasks.length} tasks successful, ${result.failureCount} failed, ${result.cancelledCount} cancelled`);
|
|
149
162
|
return result;
|
|
150
163
|
}
|
|
151
164
|
catch (error) {
|
|
152
|
-
|
|
165
|
+
LogError(`Parallel execution failed: ${error.message}`);
|
|
153
166
|
return {
|
|
154
167
|
success: false,
|
|
155
168
|
taskResults: [],
|
|
@@ -165,6 +178,17 @@ class ParallelExecutionCoordinator {
|
|
|
165
178
|
};
|
|
166
179
|
}
|
|
167
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Selects the best result from multiple parallel execution results.
|
|
183
|
+
*
|
|
184
|
+
* Uses various strategies to determine which result should be considered
|
|
185
|
+
* the "best" output from the parallel executions.
|
|
186
|
+
*
|
|
187
|
+
* @param results - Array of successful execution results to choose from
|
|
188
|
+
* @param config - Configuration for result selection method
|
|
189
|
+
* @param parentPromptRunId - Optional parent prompt run ID for hierarchical logging
|
|
190
|
+
* @returns Promise<ExecutionTaskResult | null> - The selected best result, or null if none suitable
|
|
191
|
+
*/
|
|
168
192
|
async selectBestResult(results, config, parentPromptRunId, cancellationToken) {
|
|
169
193
|
if (results.length === 0) {
|
|
170
194
|
return null;
|
|
@@ -172,7 +196,7 @@ class ParallelExecutionCoordinator {
|
|
|
172
196
|
if (results.length === 1) {
|
|
173
197
|
return results[0];
|
|
174
198
|
}
|
|
175
|
-
|
|
199
|
+
LogStatus(`Selecting best result from ${results.length} candidates using method: ${config.method}`);
|
|
176
200
|
switch (config.method) {
|
|
177
201
|
case 'First':
|
|
178
202
|
return this.selectFirstResult(results);
|
|
@@ -183,12 +207,20 @@ class ParallelExecutionCoordinator {
|
|
|
183
207
|
case 'Consensus':
|
|
184
208
|
return this.selectConsensusResult(results);
|
|
185
209
|
default:
|
|
186
|
-
|
|
210
|
+
LogError(`Unknown result selection method: ${config.method}`);
|
|
187
211
|
return results[0];
|
|
188
212
|
}
|
|
189
213
|
}
|
|
214
|
+
/**
|
|
215
|
+
* Groups execution tasks by their execution group number.
|
|
216
|
+
* Tasks with the same group number will be executed in parallel.
|
|
217
|
+
*
|
|
218
|
+
* @param tasks - Array of tasks to group
|
|
219
|
+
* @returns ExecutionGroup[] - Sorted array of execution groups
|
|
220
|
+
*/
|
|
190
221
|
groupTasksByExecutionGroup(tasks) {
|
|
191
222
|
const groupMap = new Map();
|
|
223
|
+
// Group tasks by execution group number
|
|
192
224
|
for (const task of tasks) {
|
|
193
225
|
const groupNumber = task.executionGroup;
|
|
194
226
|
if (!groupMap.has(groupNumber)) {
|
|
@@ -196,23 +228,39 @@ class ParallelExecutionCoordinator {
|
|
|
196
228
|
}
|
|
197
229
|
groupMap.get(groupNumber).push(task);
|
|
198
230
|
}
|
|
231
|
+
// Convert to ExecutionGroup array and sort by group number
|
|
199
232
|
const groups = [];
|
|
200
233
|
for (const [groupNumber, groupTasks] of groupMap) {
|
|
234
|
+
// Sort tasks within group by priority (higher priority first)
|
|
201
235
|
groupTasks.sort((a, b) => b.priority - a.priority);
|
|
202
236
|
groups.push({
|
|
203
237
|
groupNumber,
|
|
204
238
|
tasks: groupTasks,
|
|
205
239
|
});
|
|
206
240
|
}
|
|
241
|
+
// Sort groups by group number (execute in ascending order)
|
|
207
242
|
groups.sort((a, b) => a.groupNumber - b.groupNumber);
|
|
208
|
-
|
|
243
|
+
LogStatus(`Grouped ${tasks.length} tasks into ${groups.length} execution groups`);
|
|
209
244
|
return groups;
|
|
210
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Executes execution groups sequentially, with parallel execution within each group.
|
|
248
|
+
*
|
|
249
|
+
* @param groups - Array of execution groups to process
|
|
250
|
+
* @param config - Execution configuration
|
|
251
|
+
* @param parentPromptRunId - Optional parent prompt run ID for tracking
|
|
252
|
+
* @param cancellationToken - Optional cancellation token to abort execution
|
|
253
|
+
* @param progressTracker - Progress tracker for monitoring execution
|
|
254
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
255
|
+
* @returns Promise<ExecutionTaskResult[]> - All task results from all groups
|
|
256
|
+
*/
|
|
211
257
|
async executeGroupsSequentially(params, groups, config, parentPromptRunId, cancellationToken, progressTracker, agentRunId) {
|
|
212
258
|
const allResults = [];
|
|
213
259
|
for (const group of groups) {
|
|
260
|
+
// Check for cancellation before each group
|
|
214
261
|
if (cancellationToken?.aborted) {
|
|
215
|
-
|
|
262
|
+
LogStatus(`Group execution cancelled at group ${group.groupNumber}`);
|
|
263
|
+
// Create cancelled results for remaining tasks
|
|
216
264
|
const cancelledResults = group.tasks.map((task) => ({
|
|
217
265
|
task,
|
|
218
266
|
success: false,
|
|
@@ -225,27 +273,43 @@ class ParallelExecutionCoordinator {
|
|
|
225
273
|
allResults.push(...cancelledResults);
|
|
226
274
|
break;
|
|
227
275
|
}
|
|
228
|
-
|
|
276
|
+
LogStatus(`Executing group ${group.groupNumber} with ${group.tasks.length} tasks`);
|
|
277
|
+
// Update progress tracker for current group
|
|
229
278
|
progressTracker?.updateProgress(group.groupNumber);
|
|
230
279
|
const groupResults = await this.executeGroupInParallel(params, group, config, parentPromptRunId, cancellationToken, progressTracker, agentRunId);
|
|
231
280
|
allResults.push(...groupResults);
|
|
281
|
+
// Check if we should fail fast
|
|
232
282
|
if (config.failFast && groupResults.some((r) => !r.success)) {
|
|
233
283
|
const failedTasks = groupResults.filter((r) => !r.success);
|
|
234
|
-
|
|
284
|
+
LogError(`Failing fast due to ${failedTasks.length} failed tasks in group ${group.groupNumber}`);
|
|
235
285
|
break;
|
|
236
286
|
}
|
|
237
287
|
}
|
|
238
288
|
return allResults;
|
|
239
289
|
}
|
|
290
|
+
/**
|
|
291
|
+
* Executes all tasks within a single execution group in parallel.
|
|
292
|
+
*
|
|
293
|
+
* @param group - The execution group to process
|
|
294
|
+
* @param config - Execution configuration
|
|
295
|
+
* @param parentPromptRunId - Optional parent prompt run ID for tracking
|
|
296
|
+
* @param cancellationToken - Optional cancellation token to abort execution
|
|
297
|
+
* @param progressTracker - Progress tracker for monitoring execution
|
|
298
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
299
|
+
* @returns Promise<ExecutionTaskResult[]> - Results from all tasks in the group
|
|
300
|
+
*/
|
|
240
301
|
async executeGroupInParallel(params, group, config, parentPromptRunId, cancellationToken, progressTracker, agentRunId) {
|
|
241
302
|
const maxConcurrent = Math.min(config.maxConcurrentExecutions, group.tasks.length);
|
|
242
303
|
const results = [];
|
|
243
304
|
const executing = [];
|
|
244
305
|
let taskIndex = 0;
|
|
245
306
|
let executionOrder = 0;
|
|
307
|
+
// Process tasks with concurrency limit
|
|
246
308
|
while (taskIndex < group.tasks.length || executing.length > 0) {
|
|
309
|
+
// Check for cancellation
|
|
247
310
|
if (cancellationToken?.aborted) {
|
|
248
|
-
|
|
311
|
+
LogStatus(`Task execution cancelled in group ${group.groupNumber}`);
|
|
312
|
+
// Cancel remaining tasks
|
|
249
313
|
while (taskIndex < group.tasks.length) {
|
|
250
314
|
const task = group.tasks[taskIndex++];
|
|
251
315
|
results.push({
|
|
@@ -260,16 +324,20 @@ class ParallelExecutionCoordinator {
|
|
|
260
324
|
}
|
|
261
325
|
break;
|
|
262
326
|
}
|
|
327
|
+
// Start new tasks up to concurrency limit
|
|
263
328
|
while (executing.length < maxConcurrent && taskIndex < group.tasks.length) {
|
|
264
329
|
const task = group.tasks[taskIndex++];
|
|
265
330
|
progressTracker?.addActiveTask(task.taskId);
|
|
266
331
|
const execution = this.executeTask(params, task, config, parentPromptRunId, executionOrder++, agentRunId);
|
|
267
332
|
executing.push(execution);
|
|
268
333
|
}
|
|
334
|
+
// Wait for at least one task to complete
|
|
269
335
|
if (executing.length > 0) {
|
|
270
336
|
const result = await Promise.race(executing);
|
|
271
337
|
results.push(result);
|
|
338
|
+
// Notify progress tracker of task completion
|
|
272
339
|
progressTracker?.taskCompleted(result);
|
|
340
|
+
// Remove completed task from executing array
|
|
273
341
|
const completedIndex = executing.findIndex((p) => p === Promise.resolve(result));
|
|
274
342
|
if (completedIndex !== -1) {
|
|
275
343
|
executing.splice(completedIndex, 1);
|
|
@@ -278,17 +346,29 @@ class ParallelExecutionCoordinator {
|
|
|
278
346
|
}
|
|
279
347
|
const successfulResults = results.filter((r) => r.success);
|
|
280
348
|
const cancelledResults = results.filter((r) => r.cancelled);
|
|
281
|
-
|
|
349
|
+
LogStatus(`Group ${group.groupNumber} completed: ${successfulResults.length}/${results.length} successful, ${cancelledResults.length} cancelled`);
|
|
282
350
|
return results;
|
|
283
351
|
}
|
|
352
|
+
/**
|
|
353
|
+
* Executes a single task with retry logic and timeout handling.
|
|
354
|
+
*
|
|
355
|
+
* @param task - The execution task to process
|
|
356
|
+
* @param config - Execution configuration
|
|
357
|
+
* @param parentPromptRunId - Optional parent prompt run ID for hierarchical logging
|
|
358
|
+
* @param executionOrder - Execution order for this task
|
|
359
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
360
|
+
* @returns Promise<ExecutionTaskResult> - Result of the task execution
|
|
361
|
+
*/
|
|
284
362
|
async executeTask(params, task, config, parentPromptRunId, executionOrder, agentRunId) {
|
|
285
363
|
const startTime = new Date();
|
|
286
364
|
let lastError = null;
|
|
365
|
+
// Attempt execution with retries
|
|
287
366
|
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
|
|
288
367
|
try {
|
|
368
|
+
// Check for cancellation before each attempt
|
|
289
369
|
if (task.cancellationToken?.aborted) {
|
|
290
370
|
const endTime = new Date();
|
|
291
|
-
|
|
371
|
+
LogStatus(`Task ${task.taskId} cancelled before attempt ${attempt + 1}`);
|
|
292
372
|
return {
|
|
293
373
|
task,
|
|
294
374
|
success: false,
|
|
@@ -300,8 +380,9 @@ class ParallelExecutionCoordinator {
|
|
|
300
380
|
};
|
|
301
381
|
}
|
|
302
382
|
if (attempt > 0) {
|
|
383
|
+
// Apply retry delay
|
|
303
384
|
await this.delay(config.retryDelayMS * attempt);
|
|
304
|
-
|
|
385
|
+
LogStatus(`Retrying task ${task.taskId}, attempt ${attempt + 1}/${config.maxRetries + 1}`);
|
|
305
386
|
}
|
|
306
387
|
const result = await this.executeSingleTask(params, task, config.taskTimeoutMS, parentPromptRunId, executionOrder, agentRunId);
|
|
307
388
|
result.startTime = startTime;
|
|
@@ -310,12 +391,14 @@ class ParallelExecutionCoordinator {
|
|
|
310
391
|
}
|
|
311
392
|
catch (error) {
|
|
312
393
|
lastError = error;
|
|
313
|
-
|
|
394
|
+
LogError(`Task ${task.taskId} attempt ${attempt + 1} failed: ${error.message}`);
|
|
395
|
+
// Don't retry if this was the last attempt
|
|
314
396
|
if (attempt === config.maxRetries) {
|
|
315
397
|
break;
|
|
316
398
|
}
|
|
317
399
|
}
|
|
318
400
|
}
|
|
401
|
+
// All attempts failed
|
|
319
402
|
const endTime = new Date();
|
|
320
403
|
return {
|
|
321
404
|
task,
|
|
@@ -326,23 +409,39 @@ class ParallelExecutionCoordinator {
|
|
|
326
409
|
endTime,
|
|
327
410
|
};
|
|
328
411
|
}
|
|
412
|
+
/**
|
|
413
|
+
* Executes a single task without retry logic.
|
|
414
|
+
*
|
|
415
|
+
* @param task - The execution task to process
|
|
416
|
+
* @param timeoutMS - Timeout for the execution in milliseconds
|
|
417
|
+
* @param parentPromptRunId - Optional parent prompt run ID for hierarchical logging
|
|
418
|
+
* @param executionOrder - Execution order for this task
|
|
419
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
420
|
+
* @returns Promise<ExecutionTaskResult> - Result of the task execution
|
|
421
|
+
*/
|
|
329
422
|
async executeSingleTask(params, task, timeoutMS, parentPromptRunId, executionOrder, agentRunId) {
|
|
423
|
+
// TODO: This will need to integrate with AIPromptRunner's execution logic
|
|
424
|
+
// For now, implementing a simplified version
|
|
330
425
|
const startTime = new Date();
|
|
331
426
|
let childPromptRun = null;
|
|
332
427
|
try {
|
|
428
|
+
// Create child prompt run log if parent ID is provided
|
|
333
429
|
if (parentPromptRunId) {
|
|
334
430
|
childPromptRun = await this.createChildPromptRun(task, startTime, parentPromptRunId, executionOrder, agentRunId);
|
|
335
431
|
}
|
|
432
|
+
// Create LLM instance using vendor-specific driver class if available
|
|
336
433
|
const driverClass = task.vendorDriverClass || task.model.DriverClass;
|
|
337
434
|
const apiName = task.vendorApiName || task.model.APIName;
|
|
338
435
|
if (!driverClass) {
|
|
339
436
|
throw new Error(`No driver class available for model ${task.model.Name}. Vendor selection may have failed.`);
|
|
340
437
|
}
|
|
341
|
-
const apiKey =
|
|
342
|
-
const llm =
|
|
343
|
-
|
|
438
|
+
const apiKey = GetAIAPIKey(driverClass, params.apiKeys, params.verbose);
|
|
439
|
+
const llm = MJGlobal.Instance.ClassFactory.CreateInstance(BaseLLM, driverClass, apiKey);
|
|
440
|
+
// Prepare chat parameters
|
|
441
|
+
const innerParams = new ChatParams();
|
|
344
442
|
innerParams.model = apiName;
|
|
345
443
|
innerParams.cancellationToken = task.cancellationToken;
|
|
444
|
+
// Configure streaming if enabled in task
|
|
346
445
|
if (task.streamingConfig?.enabled && task.streamingConfig.callbacks?.OnContent) {
|
|
347
446
|
innerParams.streaming = true;
|
|
348
447
|
innerParams.streamingCallbacks = {
|
|
@@ -351,12 +450,17 @@ class ParallelExecutionCoordinator {
|
|
|
351
450
|
OnError: task.streamingConfig.callbacks.OnError,
|
|
352
451
|
};
|
|
353
452
|
}
|
|
453
|
+
// Build message array with rendered prompt and conversation messages
|
|
354
454
|
innerParams.messages = this.buildMessageArray(task.renderedPrompt, task.conversationMessages, task.templateMessageRole || 'system');
|
|
455
|
+
// Apply model-specific parameters if available
|
|
355
456
|
if (task.modelParameters) {
|
|
356
457
|
Object.assign(params, task.modelParameters);
|
|
357
458
|
}
|
|
459
|
+
// Execute with timeout and cancellation support
|
|
358
460
|
const racePromises = [llm.ChatCompletion(innerParams)];
|
|
461
|
+
// Add timeout promise
|
|
359
462
|
racePromises.push(new Promise((_, reject) => setTimeout(() => reject(new Error('Task execution timeout')), timeoutMS)));
|
|
463
|
+
// Add cancellation promise if cancellation token is available
|
|
360
464
|
if (task.cancellationToken) {
|
|
361
465
|
racePromises.push(new Promise((_, reject) => {
|
|
362
466
|
if (task.cancellationToken.aborted) {
|
|
@@ -372,6 +476,7 @@ class ParallelExecutionCoordinator {
|
|
|
372
476
|
const modelResult = (await Promise.race(racePromises));
|
|
373
477
|
const endTime = new Date();
|
|
374
478
|
const executionTimeMS = endTime.getTime() - startTime.getTime();
|
|
479
|
+
// Update child prompt run with results
|
|
375
480
|
if (childPromptRun) {
|
|
376
481
|
await this.updateChildPromptRun(childPromptRun, modelResult, endTime, executionTimeMS);
|
|
377
482
|
}
|
|
@@ -384,13 +489,15 @@ class ParallelExecutionCoordinator {
|
|
|
384
489
|
modelResult,
|
|
385
490
|
startTime,
|
|
386
491
|
endTime,
|
|
387
|
-
promptRun: childPromptRun,
|
|
492
|
+
promptRun: childPromptRun, // Include the child prompt run in the result
|
|
388
493
|
};
|
|
389
494
|
}
|
|
390
495
|
catch (error) {
|
|
391
496
|
const endTime = new Date();
|
|
392
497
|
const executionTimeMS = endTime.getTime() - startTime.getTime();
|
|
498
|
+
// Check if this was a cancellation error
|
|
393
499
|
const isCancelled = error.message.includes('cancelled');
|
|
500
|
+
// Update child prompt run with error if it exists
|
|
394
501
|
if (childPromptRun) {
|
|
395
502
|
childPromptRun.CompletedAt = endTime;
|
|
396
503
|
childPromptRun.ExecutionTimeMS = executionTimeMS;
|
|
@@ -399,6 +506,7 @@ class ParallelExecutionCoordinator {
|
|
|
399
506
|
childPromptRun.Result = `ERROR: ${error.message}`;
|
|
400
507
|
await childPromptRun.Save();
|
|
401
508
|
}
|
|
509
|
+
// Return cancelled result instead of throwing if this was a cancellation
|
|
402
510
|
if (isCancelled) {
|
|
403
511
|
return {
|
|
404
512
|
task,
|
|
@@ -414,12 +522,21 @@ class ParallelExecutionCoordinator {
|
|
|
414
522
|
throw new Error(`Task execution failed: ${error.message}`);
|
|
415
523
|
}
|
|
416
524
|
}
|
|
525
|
+
/**
|
|
526
|
+
* Aggregates individual task results into a comprehensive parallel execution result.
|
|
527
|
+
*
|
|
528
|
+
* @param taskResults - Array of all task execution results
|
|
529
|
+
* @param startTime - Start time of the parallel execution
|
|
530
|
+
* @param endTime - End time of the parallel execution
|
|
531
|
+
* @returns ParallelExecutionResult - Aggregated results with metrics
|
|
532
|
+
*/
|
|
417
533
|
aggregateResults(taskResults, startTime, endTime) {
|
|
418
534
|
const groupResults = new Map();
|
|
419
535
|
const errors = [];
|
|
420
536
|
let totalTokensUsed = 0;
|
|
421
537
|
let successCount = 0;
|
|
422
538
|
let cancelledCount = 0;
|
|
539
|
+
// Group results and calculate metrics
|
|
423
540
|
for (const result of taskResults) {
|
|
424
541
|
const groupNumber = result.task.executionGroup;
|
|
425
542
|
if (!groupResults.has(groupNumber)) {
|
|
@@ -453,37 +570,63 @@ class ParallelExecutionCoordinator {
|
|
|
453
570
|
endTime,
|
|
454
571
|
};
|
|
455
572
|
}
|
|
573
|
+
/**
|
|
574
|
+
* Selects the first successful result from the array.
|
|
575
|
+
*
|
|
576
|
+
* @param results - Array of successful results to choose from
|
|
577
|
+
* @returns ExecutionTaskResult - The first result in the array
|
|
578
|
+
*/
|
|
456
579
|
selectFirstResult(results) {
|
|
457
580
|
return results[0];
|
|
458
581
|
}
|
|
582
|
+
/**
|
|
583
|
+
* Selects a random result from the array.
|
|
584
|
+
*
|
|
585
|
+
* @param results - Array of successful results to choose from
|
|
586
|
+
* @returns ExecutionTaskResult - A randomly selected result
|
|
587
|
+
*/
|
|
459
588
|
selectRandomResult(results) {
|
|
460
589
|
const randomIndex = Math.floor(Math.random() * results.length);
|
|
461
590
|
return results[randomIndex];
|
|
462
591
|
}
|
|
592
|
+
/**
|
|
593
|
+
* Uses an AI prompt to select the best result from multiple options.
|
|
594
|
+
*
|
|
595
|
+
* @param results - Array of successful results to choose from
|
|
596
|
+
* @param selectorPromptId - ID of the prompt to use for selection
|
|
597
|
+
* @param parentPromptRunId - Optional parent prompt run ID for hierarchical logging
|
|
598
|
+
* @returns Promise<ExecutionTaskResult> - The AI-selected best result with all results ranked
|
|
599
|
+
*/
|
|
463
600
|
async selectResultWithPrompt(results, selectorPromptId, parentPromptRunId, _cancellationToken) {
|
|
464
601
|
try {
|
|
465
|
-
|
|
466
|
-
await
|
|
467
|
-
|
|
602
|
+
// Import AIPromptRunner here to avoid circular dependency
|
|
603
|
+
const { AIPromptRunner } = await import('./AIPromptRunner.js');
|
|
604
|
+
// Load the judge prompt from AIEngine
|
|
605
|
+
await AIEngine.Instance.Config(false);
|
|
606
|
+
const judgePrompt = AIEngine.Instance.Prompts.find((p) => p.ID === selectorPromptId);
|
|
468
607
|
if (!judgePrompt) {
|
|
469
|
-
|
|
470
|
-
return results[0];
|
|
608
|
+
LogError(`Judge prompt with ID ${selectorPromptId} not found`);
|
|
609
|
+
return results[0]; // Fallback to first result
|
|
471
610
|
}
|
|
611
|
+
// Prepare the data for the judge prompt
|
|
472
612
|
const judgeData = this.formatResultsForJudge(results);
|
|
613
|
+
// Create conversation messages for the judge
|
|
473
614
|
const conversationMessages = [
|
|
474
615
|
{
|
|
475
|
-
role:
|
|
616
|
+
role: ChatMessageRole.system,
|
|
476
617
|
content: 'You are an expert AI judge tasked with ranking multiple AI responses to determine the best one. Analyze each response for quality, accuracy, completeness, and relevance to the original prompt.',
|
|
477
618
|
},
|
|
478
619
|
{
|
|
479
|
-
role:
|
|
620
|
+
role: ChatMessageRole.user,
|
|
480
621
|
content: JSON.stringify(judgeData, null, 2),
|
|
481
622
|
},
|
|
482
623
|
];
|
|
624
|
+
// Create a ResultSelector prompt run log entry if parent ID is provided
|
|
483
625
|
let resultSelectorPromptRun = null;
|
|
484
626
|
if (parentPromptRunId) {
|
|
485
627
|
resultSelectorPromptRun = await this.createResultSelectorPromptRun(judgePrompt, judgeData, parentPromptRunId, results.length);
|
|
486
628
|
}
|
|
629
|
+
// Execute the judge prompt
|
|
487
630
|
const judgeRunner = new AIPromptRunner();
|
|
488
631
|
const judgeStartTime = Date.now();
|
|
489
632
|
const judgeResult = await judgeRunner.ExecutePrompt({
|
|
@@ -493,6 +636,7 @@ class ParallelExecutionCoordinator {
|
|
|
493
636
|
});
|
|
494
637
|
const judgeEndTime = Date.now();
|
|
495
638
|
const judgeExecutionTimeMS = judgeEndTime - judgeStartTime;
|
|
639
|
+
// Update the result selector prompt run with the result
|
|
496
640
|
if (resultSelectorPromptRun && judgeResult.promptRun) {
|
|
497
641
|
resultSelectorPromptRun.CompletedAt = new Date(judgeEndTime);
|
|
498
642
|
resultSelectorPromptRun.ExecutionTimeMS = judgeExecutionTimeMS;
|
|
@@ -504,31 +648,41 @@ class ParallelExecutionCoordinator {
|
|
|
504
648
|
await resultSelectorPromptRun.Save();
|
|
505
649
|
}
|
|
506
650
|
if (!judgeResult.success || !judgeResult.rawResult) {
|
|
507
|
-
|
|
508
|
-
return results[0];
|
|
651
|
+
LogError(`Judge prompt execution failed: ${judgeResult.errorMessage}`);
|
|
652
|
+
return results[0]; // Fallback to first result
|
|
509
653
|
}
|
|
654
|
+
// Parse the judge's decision
|
|
510
655
|
const rankings = this.parseJudgeResult(judgeResult.rawResult);
|
|
511
656
|
if (!rankings || rankings.length === 0) {
|
|
512
|
-
|
|
513
|
-
return results[0];
|
|
657
|
+
LogError('Failed to parse judge rankings');
|
|
658
|
+
return results[0]; // Fallback to first result
|
|
514
659
|
}
|
|
660
|
+
// Apply rankings to results
|
|
515
661
|
this.applyRankingsToResults(results, rankings);
|
|
662
|
+
// Store judge metadata for later use
|
|
516
663
|
const bestCandidateId = rankings.find((r) => r.rank === 1)?.candidateId;
|
|
517
664
|
const bestResultIndex = results.findIndex((r) => r.task.taskId === bestCandidateId);
|
|
518
665
|
const bestResult = bestResultIndex >= 0 ? results[bestResultIndex] : results[0];
|
|
666
|
+
// Add judge metadata to the best result
|
|
519
667
|
bestResult.judgeMetadata = {
|
|
520
668
|
judgePromptId: selectorPromptId,
|
|
521
669
|
judgeExecutionTimeMS,
|
|
522
670
|
judgeTokensUsed: judgeResult.tokensUsed,
|
|
523
671
|
};
|
|
524
|
-
|
|
672
|
+
LogStatus(`Judge selected candidate ${bestCandidateId} as the best result`);
|
|
525
673
|
return bestResult;
|
|
526
674
|
}
|
|
527
675
|
catch (error) {
|
|
528
|
-
|
|
529
|
-
return results[0];
|
|
676
|
+
LogError(`Error in AI judge selection: ${error.message}`);
|
|
677
|
+
return results[0]; // Fallback to first result
|
|
530
678
|
}
|
|
531
679
|
}
|
|
680
|
+
/**
|
|
681
|
+
* Formats execution results for the judge prompt.
|
|
682
|
+
*
|
|
683
|
+
* @param results - Array of execution results to format
|
|
684
|
+
* @returns Structured data for judge evaluation
|
|
685
|
+
*/
|
|
532
686
|
formatResultsForJudge(results) {
|
|
533
687
|
return {
|
|
534
688
|
originalPrompt: results[0]?.task.renderedPrompt || 'Original prompt not available',
|
|
@@ -547,8 +701,15 @@ class ParallelExecutionCoordinator {
|
|
|
547
701
|
},
|
|
548
702
|
};
|
|
549
703
|
}
|
|
704
|
+
/**
|
|
705
|
+
* Parses the judge's result to extract rankings.
|
|
706
|
+
*
|
|
707
|
+
* @param judgeResult - Raw result from the judge prompt
|
|
708
|
+
* @returns Array of ranking objects or null if parsing fails
|
|
709
|
+
*/
|
|
550
710
|
parseJudgeResult(judgeResult) {
|
|
551
711
|
try {
|
|
712
|
+
// Try to extract JSON from the result (in case there's extra text)
|
|
552
713
|
const jsonMatch = judgeResult.match(/\{[\s\S]*\}/);
|
|
553
714
|
const jsonString = jsonMatch ? jsonMatch[0] : judgeResult;
|
|
554
715
|
const parsed = JSON.parse(jsonString);
|
|
@@ -559,14 +720,20 @@ class ParallelExecutionCoordinator {
|
|
|
559
720
|
rationale: ranking.rationale || 'No rationale provided',
|
|
560
721
|
}));
|
|
561
722
|
}
|
|
562
|
-
|
|
723
|
+
LogError('Judge result does not contain valid rankings array');
|
|
563
724
|
return null;
|
|
564
725
|
}
|
|
565
726
|
catch (error) {
|
|
566
|
-
|
|
727
|
+
LogError(`Failed to parse judge result: ${error.message}`);
|
|
567
728
|
return null;
|
|
568
729
|
}
|
|
569
730
|
}
|
|
731
|
+
/**
|
|
732
|
+
* Applies rankings to execution task results.
|
|
733
|
+
*
|
|
734
|
+
* @param results - Array of execution results to rank
|
|
735
|
+
* @param rankings - Rankings from the judge
|
|
736
|
+
*/
|
|
570
737
|
applyRankingsToResults(results, rankings) {
|
|
571
738
|
for (const result of results) {
|
|
572
739
|
const ranking = rankings.find((r) => r.candidateId === result.task.taskId);
|
|
@@ -576,7 +743,14 @@ class ParallelExecutionCoordinator {
|
|
|
576
743
|
}
|
|
577
744
|
}
|
|
578
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* Selects the result that appears most frequently (consensus).
|
|
748
|
+
*
|
|
749
|
+
* @param results - Array of successful results to choose from
|
|
750
|
+
* @returns ExecutionTaskResult - The most common result
|
|
751
|
+
*/
|
|
579
752
|
selectConsensusResult(results) {
|
|
753
|
+
// Group results by their content
|
|
580
754
|
const resultGroups = new Map();
|
|
581
755
|
for (const result of results) {
|
|
582
756
|
const key = result.rawResult || '';
|
|
@@ -585,41 +759,62 @@ class ParallelExecutionCoordinator {
|
|
|
585
759
|
}
|
|
586
760
|
resultGroups.get(key).push(result);
|
|
587
761
|
}
|
|
762
|
+
// Find the group with the most results
|
|
588
763
|
let largestGroup = [];
|
|
589
764
|
for (const group of resultGroups.values()) {
|
|
590
765
|
if (group.length > largestGroup.length) {
|
|
591
766
|
largestGroup = group;
|
|
592
767
|
}
|
|
593
768
|
}
|
|
769
|
+
// Return the first result from the largest group
|
|
594
770
|
return largestGroup[0];
|
|
595
771
|
}
|
|
772
|
+
/**
|
|
773
|
+
* Builds the message array combining rendered prompt with conversation messages
|
|
774
|
+
*/
|
|
596
775
|
buildMessageArray(renderedPrompt, conversationMessages, templateMessageRole = 'system') {
|
|
597
776
|
const messages = [];
|
|
777
|
+
// Add rendered template as system or user message if not 'none'
|
|
598
778
|
if (renderedPrompt && templateMessageRole !== 'none') {
|
|
599
779
|
messages.push({
|
|
600
|
-
role: templateMessageRole === 'system' ?
|
|
780
|
+
role: templateMessageRole === 'system' ? ChatMessageRole.system : ChatMessageRole.user,
|
|
601
781
|
content: renderedPrompt,
|
|
602
782
|
});
|
|
603
783
|
}
|
|
784
|
+
// Add conversation messages if provided
|
|
604
785
|
if (conversationMessages && conversationMessages.length > 0) {
|
|
605
786
|
messages.push(...conversationMessages);
|
|
606
787
|
}
|
|
788
|
+
// If no conversation messages and no rendered prompt as user message,
|
|
789
|
+
// add a default user message to ensure we have at least one user message
|
|
607
790
|
if ((!conversationMessages || conversationMessages.length === 0) && templateMessageRole !== 'user' && renderedPrompt) {
|
|
791
|
+
// If we only have a system message, we need a user message too
|
|
608
792
|
if (templateMessageRole === 'system') {
|
|
609
793
|
messages.push({
|
|
610
|
-
role:
|
|
794
|
+
role: ChatMessageRole.user,
|
|
611
795
|
content: 'Please proceed with the above instructions.',
|
|
612
796
|
});
|
|
613
797
|
}
|
|
614
798
|
}
|
|
615
799
|
else if ((!conversationMessages || conversationMessages.length === 0) && !renderedPrompt) {
|
|
800
|
+
// Fallback: if no conversation and no rendered prompt, add a basic user message
|
|
616
801
|
messages.push({
|
|
617
|
-
role:
|
|
802
|
+
role: ChatMessageRole.user,
|
|
618
803
|
content: 'Hello',
|
|
619
804
|
});
|
|
620
805
|
}
|
|
621
806
|
return messages;
|
|
622
807
|
}
|
|
808
|
+
/**
|
|
809
|
+
* Creates a child AIPromptRun entity for individual parallel execution tracking.
|
|
810
|
+
*
|
|
811
|
+
* @param task - The execution task
|
|
812
|
+
* @param startTime - When the execution started
|
|
813
|
+
* @param parentPromptRunId - ID of the parent prompt run
|
|
814
|
+
* @param executionOrder - Execution order within the parallel group
|
|
815
|
+
* @param agentRunId - Optional agent run ID to link prompt executions to parent agent run
|
|
816
|
+
* @returns Promise<AIPromptRunEntityExtended> - The created child prompt run
|
|
817
|
+
*/
|
|
623
818
|
async createChildPromptRun(task, startTime, parentPromptRunId, executionOrder, agentRunId) {
|
|
624
819
|
try {
|
|
625
820
|
const promptRun = await this._metadata.GetEntityObject('MJ: AI Prompt Runs', task.contextUser);
|
|
@@ -632,18 +827,23 @@ class ParallelExecutionCoordinator {
|
|
|
632
827
|
if (executionOrder !== undefined) {
|
|
633
828
|
promptRun.ExecutionOrder = executionOrder;
|
|
634
829
|
}
|
|
830
|
+
// Set AgentRunID if provided for agent-prompt execution tracking
|
|
635
831
|
if (agentRunId) {
|
|
636
832
|
promptRun.AgentRunID = agentRunId;
|
|
637
833
|
}
|
|
834
|
+
// Set vendor ID from task if available (use task vendor ID which comes from vendor selection)
|
|
638
835
|
if (task.vendorId) {
|
|
639
836
|
promptRun.VendorID = task.vendorId;
|
|
640
837
|
}
|
|
641
838
|
else if (task.promptModel?.VendorID) {
|
|
839
|
+
// Fallback to prompt model vendor if task vendor not set
|
|
642
840
|
promptRun.VendorID = task.promptModel.VendorID;
|
|
643
841
|
}
|
|
842
|
+
// Set configuration ID from task if available
|
|
644
843
|
if (task.configurationId) {
|
|
645
844
|
promptRun.ConfigurationID = task.configurationId;
|
|
646
845
|
}
|
|
846
|
+
// Store the input data/context as JSON in Messages field
|
|
647
847
|
const messagesData = {
|
|
648
848
|
renderedPrompt: task.renderedPrompt,
|
|
649
849
|
conversationMessages: task.conversationMessages,
|
|
@@ -654,16 +854,24 @@ class ParallelExecutionCoordinator {
|
|
|
654
854
|
const saveResult = await promptRun.Save();
|
|
655
855
|
if (!saveResult) {
|
|
656
856
|
const error = `Failed to save child AIPromptRun: ${promptRun.LatestResult?.Message || 'Unknown error'}`;
|
|
657
|
-
|
|
857
|
+
LogError(error);
|
|
658
858
|
throw new Error(error);
|
|
659
859
|
}
|
|
660
860
|
return promptRun;
|
|
661
861
|
}
|
|
662
862
|
catch (error) {
|
|
663
|
-
|
|
863
|
+
LogError(`Error creating child prompt run record: ${error.message}`);
|
|
664
864
|
throw error;
|
|
665
865
|
}
|
|
666
866
|
}
|
|
867
|
+
/**
|
|
868
|
+
* Updates a child AIPromptRun entity with execution results.
|
|
869
|
+
*
|
|
870
|
+
* @param promptRun - The child prompt run entity to update
|
|
871
|
+
* @param modelResult - The result from the AI model
|
|
872
|
+
* @param endTime - When the execution completed
|
|
873
|
+
* @param executionTimeMS - Total execution time in milliseconds
|
|
874
|
+
*/
|
|
667
875
|
async updateChildPromptRun(promptRun, modelResult, endTime, executionTimeMS) {
|
|
668
876
|
try {
|
|
669
877
|
promptRun.CompletedAt = endTime;
|
|
@@ -671,6 +879,7 @@ class ParallelExecutionCoordinator {
|
|
|
671
879
|
promptRun.Success = modelResult.success;
|
|
672
880
|
if (modelResult.success) {
|
|
673
881
|
promptRun.Result = modelResult.data?.choices?.[0]?.message?.content || '';
|
|
882
|
+
// Extract token usage if available
|
|
674
883
|
if (modelResult.data?.usage) {
|
|
675
884
|
promptRun.TokensUsed = modelResult.data.usage.totalTokens;
|
|
676
885
|
promptRun.TokensPrompt = modelResult.data.usage.promptTokens;
|
|
@@ -683,22 +892,33 @@ class ParallelExecutionCoordinator {
|
|
|
683
892
|
}
|
|
684
893
|
const saveResult = await promptRun.Save();
|
|
685
894
|
if (!saveResult) {
|
|
686
|
-
|
|
895
|
+
LogError(`Failed to update child AIPromptRun with results: ${promptRun.LatestResult?.Message || 'Unknown error'}`);
|
|
687
896
|
}
|
|
688
897
|
}
|
|
689
898
|
catch (error) {
|
|
690
|
-
|
|
899
|
+
LogError(`Error updating child prompt run: ${error.message}`);
|
|
691
900
|
}
|
|
692
901
|
}
|
|
902
|
+
/**
|
|
903
|
+
* Creates a ResultSelector AIPromptRun entity for judge execution tracking.
|
|
904
|
+
*
|
|
905
|
+
* @param judgePrompt - The judge prompt being executed
|
|
906
|
+
* @param judgeData - The data being sent to the judge
|
|
907
|
+
* @param parentPromptRunId - ID of the parent prompt run
|
|
908
|
+
* @param executionOrder - Execution order within the parallel group
|
|
909
|
+
* @returns Promise<AIPromptRunEntityExtended> - The created result selector prompt run
|
|
910
|
+
*/
|
|
693
911
|
async createResultSelectorPromptRun(judgePrompt, judgeData, parentPromptRunId, executionOrder) {
|
|
694
912
|
try {
|
|
695
913
|
const promptRun = await this._metadata.GetEntityObject('MJ: AI Prompt Runs');
|
|
696
914
|
promptRun.NewRecord();
|
|
697
915
|
promptRun.PromptID = judgePrompt.ID;
|
|
916
|
+
// We don't have a specific model ID for the judge yet, it will be set by AIPromptRunner
|
|
698
917
|
promptRun.RunAt = new Date();
|
|
699
918
|
promptRun.RunType = 'ResultSelector';
|
|
700
919
|
promptRun.ParentID = parentPromptRunId;
|
|
701
920
|
promptRun.ExecutionOrder = executionOrder;
|
|
921
|
+
// Store the judge data as JSON in Messages field
|
|
702
922
|
promptRun.Messages = JSON.stringify({
|
|
703
923
|
judgeData,
|
|
704
924
|
candidateCount: Array.isArray(judgeData.candidates)
|
|
@@ -708,19 +928,24 @@ class ParallelExecutionCoordinator {
|
|
|
708
928
|
const saveResult = await promptRun.Save();
|
|
709
929
|
if (!saveResult) {
|
|
710
930
|
const error = `Failed to save ResultSelector AIPromptRun: ${promptRun.LatestResult?.Message || 'Unknown error'}`;
|
|
711
|
-
|
|
931
|
+
LogError(error);
|
|
712
932
|
throw new Error(error);
|
|
713
933
|
}
|
|
714
934
|
return promptRun;
|
|
715
935
|
}
|
|
716
936
|
catch (error) {
|
|
717
|
-
|
|
937
|
+
LogError(`Error creating result selector prompt run record: ${error.message}`);
|
|
718
938
|
throw error;
|
|
719
939
|
}
|
|
720
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* Creates a delay for the specified number of milliseconds.
|
|
943
|
+
*
|
|
944
|
+
* @param ms - Number of milliseconds to delay
|
|
945
|
+
* @returns Promise<void> - Promise that resolves after the delay
|
|
946
|
+
*/
|
|
721
947
|
delay(ms) {
|
|
722
948
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
723
949
|
}
|
|
724
950
|
}
|
|
725
|
-
exports.ParallelExecutionCoordinator = ParallelExecutionCoordinator;
|
|
726
951
|
//# sourceMappingURL=ParallelExecutionCoordinator.js.map
|