@things-factory/labeling 9.1.19

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 (55) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/ENTITY_IMPLEMENTATION.md +351 -0
  3. package/INTEGRATION_COMPLETE.md +531 -0
  4. package/MIGRATION_GUIDE.md +310 -0
  5. package/README.md +551 -0
  6. package/REFACTORING_SUMMARY.md +212 -0
  7. package/UI_DOCUMENTATION.md +552 -0
  8. package/dist-client/index.d.ts +3 -0
  9. package/dist-client/index.js +9 -0
  10. package/dist-client/index.js.map +1 -0
  11. package/dist-client/pages/labeling-workflow-builder.d.ts +26 -0
  12. package/dist-client/pages/labeling-workflow-builder.js +636 -0
  13. package/dist-client/pages/labeling-workflow-builder.js.map +1 -0
  14. package/dist-client/pages/labeling-workflow-list.d.ts +24 -0
  15. package/dist-client/pages/labeling-workflow-list.js +495 -0
  16. package/dist-client/pages/labeling-workflow-list.js.map +1 -0
  17. package/dist-client/route.d.ts +1 -0
  18. package/dist-client/route.js +47 -0
  19. package/dist-client/route.js.map +1 -0
  20. package/dist-client/tsconfig.tsbuildinfo +1 -0
  21. package/dist-server/entities/index.d.ts +5 -0
  22. package/dist-server/entities/index.js +11 -0
  23. package/dist-server/entities/index.js.map +1 -0
  24. package/dist-server/index.d.ts +3 -0
  25. package/dist-server/index.js +7 -0
  26. package/dist-server/index.js.map +1 -0
  27. package/dist-server/route.d.ts +2 -0
  28. package/dist-server/route.js +6 -0
  29. package/dist-server/route.js.map +1 -0
  30. package/dist-server/service/index.d.ts +8 -0
  31. package/dist-server/service/index.js +21 -0
  32. package/dist-server/service/index.js.map +1 -0
  33. package/dist-server/service/labeling-workflow-service.d.ts +69 -0
  34. package/dist-server/service/labeling-workflow-service.js +521 -0
  35. package/dist-server/service/labeling-workflow-service.js.map +1 -0
  36. package/dist-server/service/labeling-workflow.d.ts +30 -0
  37. package/dist-server/service/labeling-workflow.js +119 -0
  38. package/dist-server/service/labeling-workflow.js.map +1 -0
  39. package/dist-server/service/workflow-execution-step.d.ts +28 -0
  40. package/dist-server/service/workflow-execution-step.js +115 -0
  41. package/dist-server/service/workflow-execution-step.js.map +1 -0
  42. package/dist-server/service/workflow-execution.d.ts +27 -0
  43. package/dist-server/service/workflow-execution.js +110 -0
  44. package/dist-server/service/workflow-execution.js.map +1 -0
  45. package/dist-server/tsconfig.tsbuildinfo +1 -0
  46. package/dist-server/types/workflow-types.d.ts +141 -0
  47. package/dist-server/types/workflow-types.js +488 -0
  48. package/dist-server/types/workflow-types.js.map +1 -0
  49. package/package.json +51 -0
  50. package/things-factory.config.js +11 -0
  51. package/translations/en.json +6 -0
  52. package/translations/ja.json +6 -0
  53. package/translations/ko.json +6 -0
  54. package/translations/ms.json +6 -0
  55. package/translations/zh.json +6 -0
@@ -0,0 +1,521 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LabelingWorkflowService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const type_graphql_1 = require("type-graphql");
6
+ const typeorm_1 = require("typeorm");
7
+ const workflow_types_js_1 = require("../types/workflow-types.js");
8
+ const labeling_workflow_js_1 = require("./labeling-workflow.js");
9
+ const workflow_execution_js_1 = require("./workflow-execution.js");
10
+ const workflow_execution_step_js_1 = require("./workflow-execution-step.js");
11
+ const dataset_labeling_integration_js_1 = require("@things-factory/integration-label-studio/dist-server/service/dataset-labeling-integration.js");
12
+ const external_data_source_service_js_1 = require("@things-factory/integration-label-studio/dist-server/service/external-data-source-service.js");
13
+ const ai_prediction_service_js_1 = require("@things-factory/integration-label-studio/dist-server/service/ai-prediction-service.js");
14
+ /**
15
+ * Labeling Workflow Service
16
+ *
17
+ * Orchestrates end-to-end labeling workflows with multiple steps
18
+ *
19
+ * Features:
20
+ * - Define multi-step labeling workflows
21
+ * - Auto-execute workflows based on triggers
22
+ * - Track execution progress
23
+ * - Error handling and retry logic
24
+ * - Conditional execution
25
+ * - Database persistence with TypeORM
26
+ */
27
+ let LabelingWorkflowService = class LabelingWorkflowService {
28
+ constructor() {
29
+ // Service dependencies (lazy initialization)
30
+ this.datasetIntegration = null;
31
+ this.externalDataSource = null;
32
+ this.aiPredictionService = null;
33
+ }
34
+ getDatasetIntegration() {
35
+ if (!this.datasetIntegration) {
36
+ this.datasetIntegration = new dataset_labeling_integration_js_1.DatasetLabelingIntegration();
37
+ }
38
+ return this.datasetIntegration;
39
+ }
40
+ getExternalDataSource() {
41
+ if (!this.externalDataSource) {
42
+ this.externalDataSource = new external_data_source_service_js_1.ExternalDataSourceService();
43
+ }
44
+ return this.externalDataSource;
45
+ }
46
+ getAIPredictionService() {
47
+ if (!this.aiPredictionService) {
48
+ this.aiPredictionService = new ai_prediction_service_js_1.LabelStudioAIPredictionService();
49
+ }
50
+ return this.aiPredictionService;
51
+ }
52
+ /**
53
+ * Convert Entity to GraphQL Type
54
+ */
55
+ toWorkflowType(entity) {
56
+ return {
57
+ ...entity,
58
+ steps: JSON.parse(entity.steps)
59
+ };
60
+ }
61
+ toExecutionType(entity) {
62
+ return entity;
63
+ }
64
+ /**
65
+ * Create a new labeling workflow
66
+ */
67
+ async createLabelingWorkflow(input, context) {
68
+ console.log(`[Workflow] Creating workflow: ${input.name}`);
69
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
70
+ const workflow = workflowRepo.create({
71
+ domain: context.state.domain,
72
+ creator: context.state.user,
73
+ name: input.name,
74
+ description: input.description,
75
+ projectId: input.projectId,
76
+ triggerType: input.triggerType,
77
+ triggerConfig: input.triggerConfig,
78
+ steps: JSON.stringify(input.steps.map((step, index) => ({
79
+ name: step.name,
80
+ type: step.type,
81
+ config: step.config,
82
+ condition: step.condition,
83
+ continueOnError: step.continueOnError !== undefined ? step.continueOnError : true,
84
+ maxRetries: step.maxRetries,
85
+ order: index + 1
86
+ }))),
87
+ status: input.autoStart ? workflow_types_js_1.WorkflowStatus.Active : workflow_types_js_1.WorkflowStatus.Draft
88
+ });
89
+ await workflowRepo.save(workflow);
90
+ console.log(`[Workflow] Created workflow ${workflow.id} with ${input.steps.length} steps`);
91
+ return this.toWorkflowType(workflow);
92
+ }
93
+ /**
94
+ * Execute a workflow
95
+ */
96
+ async executeLabelingWorkflow(input, context) {
97
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
98
+ const workflow = await workflowRepo.findOne({
99
+ where: { id: input.workflowId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() }
100
+ });
101
+ if (!workflow) {
102
+ throw new Error(`Workflow not found: ${input.workflowId}`);
103
+ }
104
+ console.log(`[Workflow] Executing workflow: ${workflow.name} (${workflow.id})`);
105
+ const steps = JSON.parse(workflow.steps);
106
+ const executionRepo = (0, typeorm_1.getRepository)(workflow_execution_js_1.WorkflowExecution);
107
+ const execution = executionRepo.create({
108
+ domain: context.state.domain,
109
+ workflow,
110
+ workflowId: workflow.id,
111
+ workflowName: workflow.name,
112
+ status: 'running',
113
+ startedAt: new Date()
114
+ });
115
+ await executionRepo.save(execution);
116
+ // Create execution steps
117
+ const stepRepo = (0, typeorm_1.getRepository)(workflow_execution_step_js_1.WorkflowExecutionStep);
118
+ await Promise.all(steps.map((step, index) => stepRepo.save(stepRepo.create({
119
+ domain: context.state.domain,
120
+ execution,
121
+ executionId: execution.id,
122
+ stepName: step.name,
123
+ stepType: step.type,
124
+ order: index + 1,
125
+ status: 'pending'
126
+ }))));
127
+ // Execute asynchronously
128
+ this.executeWorkflowAsync(execution.id, workflow.id, steps, context, input.parameters).catch(error => {
129
+ console.error(`[Workflow] Execution failed:`, error);
130
+ });
131
+ return {
132
+ executionId: execution.id,
133
+ status: 'running',
134
+ summary: `Started execution of ${steps.length} steps`
135
+ };
136
+ }
137
+ /**
138
+ * Get workflow details
139
+ */
140
+ async labelingWorkflow(workflowId, context) {
141
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
142
+ const workflow = await workflowRepo.findOne({
143
+ where: { id: workflowId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() }
144
+ });
145
+ if (!workflow) {
146
+ throw new Error(`Workflow not found: ${workflowId}`);
147
+ }
148
+ return this.toWorkflowType(workflow);
149
+ }
150
+ /**
151
+ * List all workflows
152
+ */
153
+ async labelingWorkflows(projectId, context) {
154
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
155
+ const queryBuilder = workflowRepo
156
+ .createQueryBuilder('workflow')
157
+ .where('workflow.domain = :domain', { domain: context.state.domain.id })
158
+ .andWhere('workflow.deletedAt IS NULL');
159
+ if (projectId) {
160
+ queryBuilder.andWhere('workflow.projectId = :projectId', { projectId });
161
+ }
162
+ const [entities, total] = await queryBuilder.orderBy('workflow.createdAt', 'DESC').getManyAndCount();
163
+ const items = entities.map(e => this.toWorkflowType(e));
164
+ return { items, total };
165
+ }
166
+ /**
167
+ * Get execution status
168
+ */
169
+ async workflowExecution(executionId, context) {
170
+ const executionRepo = (0, typeorm_1.getRepository)(workflow_execution_js_1.WorkflowExecution);
171
+ const execution = await executionRepo.findOne({
172
+ where: { id: executionId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() },
173
+ relations: ['steps']
174
+ });
175
+ if (!execution) {
176
+ throw new Error(`Execution not found: ${executionId}`);
177
+ }
178
+ return this.toExecutionType(execution);
179
+ }
180
+ /**
181
+ * List executions for a workflow
182
+ */
183
+ async workflowExecutions(workflowId, context) {
184
+ const executionRepo = (0, typeorm_1.getRepository)(workflow_execution_js_1.WorkflowExecution);
185
+ const [entities, total] = await executionRepo.findAndCount({
186
+ where: { workflowId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() },
187
+ order: { startedAt: 'DESC' }
188
+ });
189
+ const items = entities.map(e => this.toExecutionType(e));
190
+ return { items, total };
191
+ }
192
+ /**
193
+ * Pause a workflow
194
+ */
195
+ async pauseLabelingWorkflow(workflowId, context) {
196
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
197
+ const workflow = await workflowRepo.findOne({
198
+ where: { id: workflowId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() }
199
+ });
200
+ if (!workflow) {
201
+ throw new Error(`Workflow not found: ${workflowId}`);
202
+ }
203
+ workflow.status = workflow_types_js_1.WorkflowStatus.Paused;
204
+ await workflowRepo.save(workflow);
205
+ console.log(`[Workflow] Paused workflow: ${workflow.name}`);
206
+ return this.toWorkflowType(workflow);
207
+ }
208
+ /**
209
+ * Resume a workflow
210
+ */
211
+ async resumeLabelingWorkflow(workflowId, context) {
212
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
213
+ const workflow = await workflowRepo.findOne({
214
+ where: { id: workflowId, domain: context.state.domain, deletedAt: (0, typeorm_1.IsNull)() }
215
+ });
216
+ if (!workflow) {
217
+ throw new Error(`Workflow not found: ${workflowId}`);
218
+ }
219
+ workflow.status = workflow_types_js_1.WorkflowStatus.Active;
220
+ await workflowRepo.save(workflow);
221
+ console.log(`[Workflow] Resumed workflow: ${workflow.name}`);
222
+ return this.toWorkflowType(workflow);
223
+ }
224
+ // ============================================================================
225
+ // Private Methods - Workflow Execution Engine
226
+ // ============================================================================
227
+ async executeWorkflowAsync(executionId, workflowId, steps, context, parametersJson) {
228
+ const startTime = Date.now();
229
+ const parameters = parametersJson ? JSON.parse(parametersJson) : {};
230
+ console.log(`[Workflow] Starting execution ${executionId}`);
231
+ const executionRepo = (0, typeorm_1.getRepository)(workflow_execution_js_1.WorkflowExecution);
232
+ const stepRepo = (0, typeorm_1.getRepository)(workflow_execution_step_js_1.WorkflowExecutionStep);
233
+ const workflowRepo = (0, typeorm_1.getRepository)(labeling_workflow_js_1.LabelingWorkflow);
234
+ const execution = await executionRepo.findOne({
235
+ where: { id: executionId },
236
+ relations: ['steps', 'workflow']
237
+ });
238
+ if (!execution) {
239
+ throw new Error(`Execution not found: ${executionId}`);
240
+ }
241
+ try {
242
+ for (const [index, workflowStep] of steps.entries()) {
243
+ const executionStep = execution.steps[index];
244
+ executionStep.status = 'running';
245
+ executionStep.startedAt = new Date();
246
+ await stepRepo.save(executionStep);
247
+ console.log(`[Workflow] Executing step ${index + 1}/${steps.length}: ${workflowStep.name}`);
248
+ try {
249
+ // Check condition if specified
250
+ if (workflowStep.condition) {
251
+ const conditionMet = this.evaluateCondition(workflowStep.condition, parameters);
252
+ if (!conditionMet) {
253
+ console.log(`[Workflow] Step ${workflowStep.name} condition not met, skipping`);
254
+ executionStep.status = 'skipped';
255
+ executionStep.completedAt = new Date();
256
+ await stepRepo.save(executionStep);
257
+ continue;
258
+ }
259
+ }
260
+ // Execute step
261
+ const stepConfig = JSON.parse(workflowStep.config);
262
+ const stepResult = await this.executeStep(workflowStep.type, stepConfig, execution.workflow.projectId, context, parameters);
263
+ executionStep.status = 'completed';
264
+ executionStep.output = JSON.stringify(stepResult);
265
+ executionStep.completedAt = new Date();
266
+ executionStep.durationMs = executionStep.completedAt.getTime() - executionStep.startedAt.getTime();
267
+ await stepRepo.save(executionStep);
268
+ console.log(`[Workflow] Step ${workflowStep.name} completed in ${executionStep.durationMs}ms`);
269
+ // Store step result in parameters for next steps
270
+ parameters[`step_${index}_result`] = stepResult;
271
+ }
272
+ catch (stepError) {
273
+ console.error(`[Workflow] Step ${workflowStep.name} failed:`, stepError);
274
+ executionStep.status = 'failed';
275
+ executionStep.error = stepError.message;
276
+ executionStep.completedAt = new Date();
277
+ executionStep.durationMs = executionStep.completedAt.getTime() - executionStep.startedAt.getTime();
278
+ await stepRepo.save(executionStep);
279
+ // Check if we should continue on error
280
+ if (!workflowStep.continueOnError) {
281
+ throw new Error(`Step ${workflowStep.name} failed: ${stepError.message}`);
282
+ }
283
+ console.log(`[Workflow] Continuing despite error (continueOnError=true)`);
284
+ }
285
+ }
286
+ // All steps completed
287
+ execution.status = 'completed';
288
+ execution.summary = this.generateExecutionSummary(execution.steps);
289
+ execution.completedAt = new Date();
290
+ execution.totalDurationMs = Date.now() - startTime;
291
+ await executionRepo.save(execution);
292
+ console.log(`[Workflow] Execution completed in ${execution.totalDurationMs}ms`);
293
+ // Update workflow status
294
+ const workflow = await workflowRepo.findOne({ where: { id: workflowId } });
295
+ if (workflow) {
296
+ workflow.lastExecutedAt = new Date();
297
+ if (workflow.triggerType === workflow_types_js_1.TriggerType.Schedule) {
298
+ // Calculate next execution time (simplified, needs proper cron parser)
299
+ // workflow.nextExecutionAt = ...
300
+ }
301
+ await workflowRepo.save(workflow);
302
+ }
303
+ }
304
+ catch (error) {
305
+ console.error(`[Workflow] Execution failed:`, error);
306
+ execution.status = 'failed';
307
+ execution.error = error.message;
308
+ execution.summary = `Failed: ${error.message}`;
309
+ execution.completedAt = new Date();
310
+ execution.totalDurationMs = Date.now() - startTime;
311
+ await executionRepo.save(execution);
312
+ }
313
+ }
314
+ async executeStep(stepType, config, projectId, context, parameters) {
315
+ switch (stepType) {
316
+ case workflow_types_js_1.WorkflowStepType.ImportData:
317
+ return await this.executeImportDataStep(config, projectId, context, parameters);
318
+ case workflow_types_js_1.WorkflowStepType.GeneratePredictions:
319
+ return await this.executeGeneratePredictionsStep(config, projectId, context, parameters);
320
+ case workflow_types_js_1.WorkflowStepType.WaitForAnnotations:
321
+ return await this.executeWaitForAnnotationsStep(config, projectId, context);
322
+ case workflow_types_js_1.WorkflowStepType.SyncAnnotations:
323
+ return await this.executeSyncAnnotationsStep(config, projectId, context, parameters);
324
+ case workflow_types_js_1.WorkflowStepType.ValidateQuality:
325
+ return await this.executeValidateQualityStep(config, projectId, context, parameters);
326
+ case workflow_types_js_1.WorkflowStepType.Notification:
327
+ return await this.executeNotificationStep(config, parameters);
328
+ default:
329
+ throw new Error(`Unknown step type: ${stepType}`);
330
+ }
331
+ }
332
+ async executeImportDataStep(config, projectId, context, parameters) {
333
+ if (config.sourceType === 'dataset') {
334
+ return await this.getDatasetIntegration().createLabelingTasksFromDataset({
335
+ projectId,
336
+ dataSetId: config.dataSetId,
337
+ imageField: config.imageField,
338
+ autoGeneratePredictions: config.autoGeneratePredictions || false,
339
+ limit: config.limit
340
+ }, context);
341
+ }
342
+ else {
343
+ return await this.getExternalDataSource().importFromExternalSource({
344
+ projectId,
345
+ source: {
346
+ sourceType: config.sourceType,
347
+ sourceUrl: config.sourceUrl,
348
+ authHeader: config.authHeader,
349
+ dataPath: config.dataPath
350
+ },
351
+ imageField: config.imageField,
352
+ limit: config.limit
353
+ }, context);
354
+ }
355
+ }
356
+ async executeGeneratePredictionsStep(config, projectId, context, parameters) {
357
+ const dataSetId = parameters.dataSetId || config.dataSetId;
358
+ if (!dataSetId) {
359
+ throw new Error('dataSetId required for GeneratePredictions step');
360
+ }
361
+ return await this.getDatasetIntegration().generatePredictionsForDataset({
362
+ dataSetId,
363
+ projectId,
364
+ modelId: config.modelId,
365
+ confidenceThreshold: config.confidenceThreshold,
366
+ forceRegenerate: config.forceRegenerate || false
367
+ }, context);
368
+ }
369
+ async executeWaitForAnnotationsStep(config, projectId, context) {
370
+ // This is a simplified implementation
371
+ // In production, this should poll or use webhooks
372
+ console.log(`[Workflow] WaitForAnnotations step - checking criteria`);
373
+ // TODO: Implement actual waiting/polling logic
374
+ return {
375
+ status: 'waiting',
376
+ message: 'WaitForAnnotations step - manual check required'
377
+ };
378
+ }
379
+ async executeSyncAnnotationsStep(config, projectId, context, parameters) {
380
+ const dataSetId = parameters.dataSetId || config.dataSetId;
381
+ if (!dataSetId) {
382
+ throw new Error('dataSetId required for SyncAnnotations step');
383
+ }
384
+ return await this.getDatasetIntegration().syncAnnotationsToDataset({
385
+ projectId,
386
+ dataSetId,
387
+ completedOnly: config.completedOnly !== false,
388
+ sinceDate: config.sinceDate
389
+ }, context);
390
+ }
391
+ async executeValidateQualityStep(config, projectId, context, parameters) {
392
+ console.log(`[Workflow] ValidateQuality step`);
393
+ // TODO: Implement quality validation logic
394
+ return {
395
+ status: 'validated',
396
+ message: 'Quality validation - not yet implemented'
397
+ };
398
+ }
399
+ async executeNotificationStep(config, parameters) {
400
+ console.log(`[Workflow] Notification step: ${config.message}`);
401
+ // TODO: Implement actual notification (email, webhook, etc.)
402
+ return {
403
+ status: 'sent',
404
+ message: config.message,
405
+ recipients: config.recipients
406
+ };
407
+ }
408
+ evaluateCondition(condition, parameters) {
409
+ // Simple condition evaluation
410
+ // In production, use a proper expression evaluator
411
+ try {
412
+ const conditionObj = JSON.parse(condition);
413
+ // Example: { "step_0_result.tasksCreated": { "$gt": 0 } }
414
+ // For now, always return true
415
+ return true;
416
+ }
417
+ catch (error) {
418
+ console.warn(`[Workflow] Failed to evaluate condition: ${condition}`);
419
+ return true;
420
+ }
421
+ }
422
+ generateExecutionSummary(steps) {
423
+ const completed = steps.filter(s => s.status === 'completed').length;
424
+ const failed = steps.filter(s => s.status === 'failed').length;
425
+ const skipped = steps.filter(s => s.status === 'skipped').length;
426
+ return `Completed ${completed}/${steps.length} steps (${failed} failed, ${skipped} skipped)`;
427
+ }
428
+ };
429
+ exports.LabelingWorkflowService = LabelingWorkflowService;
430
+ tslib_1.__decorate([
431
+ (0, type_graphql_1.Mutation)(returns => workflow_types_js_1.LabelingWorkflow, {
432
+ description: 'Create a new labeling workflow'
433
+ }),
434
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "mutation")'),
435
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('input')),
436
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
437
+ tslib_1.__metadata("design:type", Function),
438
+ tslib_1.__metadata("design:paramtypes", [workflow_types_js_1.CreateWorkflowRequest, Object]),
439
+ tslib_1.__metadata("design:returntype", Promise)
440
+ ], LabelingWorkflowService.prototype, "createLabelingWorkflow", null);
441
+ tslib_1.__decorate([
442
+ (0, type_graphql_1.Mutation)(returns => workflow_types_js_1.WorkflowExecutionResult, {
443
+ description: 'Execute a labeling workflow'
444
+ }),
445
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "mutation")'),
446
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('input')),
447
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
448
+ tslib_1.__metadata("design:type", Function),
449
+ tslib_1.__metadata("design:paramtypes", [workflow_types_js_1.ExecuteWorkflowRequest, Object]),
450
+ tslib_1.__metadata("design:returntype", Promise)
451
+ ], LabelingWorkflowService.prototype, "executeLabelingWorkflow", null);
452
+ tslib_1.__decorate([
453
+ (0, type_graphql_1.Query)(returns => workflow_types_js_1.LabelingWorkflow, {
454
+ description: 'Get labeling workflow details'
455
+ }),
456
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "query")'),
457
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('workflowId')),
458
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
459
+ tslib_1.__metadata("design:type", Function),
460
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
461
+ tslib_1.__metadata("design:returntype", Promise)
462
+ ], LabelingWorkflowService.prototype, "labelingWorkflow", null);
463
+ tslib_1.__decorate([
464
+ (0, type_graphql_1.Query)(returns => workflow_types_js_1.LabelingWorkflowList, {
465
+ description: 'List all labeling workflows'
466
+ }),
467
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "query")'),
468
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('projectId', type => type_graphql_1.Int, { nullable: true })),
469
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
470
+ tslib_1.__metadata("design:type", Function),
471
+ tslib_1.__metadata("design:paramtypes", [Number, Object]),
472
+ tslib_1.__metadata("design:returntype", Promise)
473
+ ], LabelingWorkflowService.prototype, "labelingWorkflows", null);
474
+ tslib_1.__decorate([
475
+ (0, type_graphql_1.Query)(returns => workflow_types_js_1.WorkflowExecution, {
476
+ description: 'Get workflow execution status'
477
+ }),
478
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "query")'),
479
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('executionId')),
480
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
481
+ tslib_1.__metadata("design:type", Function),
482
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
483
+ tslib_1.__metadata("design:returntype", Promise)
484
+ ], LabelingWorkflowService.prototype, "workflowExecution", null);
485
+ tslib_1.__decorate([
486
+ (0, type_graphql_1.Query)(returns => workflow_types_js_1.WorkflowExecutionList, {
487
+ description: 'List executions for a workflow'
488
+ }),
489
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "query")'),
490
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('workflowId')),
491
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
492
+ tslib_1.__metadata("design:type", Function),
493
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
494
+ tslib_1.__metadata("design:returntype", Promise)
495
+ ], LabelingWorkflowService.prototype, "workflowExecutions", null);
496
+ tslib_1.__decorate([
497
+ (0, type_graphql_1.Mutation)(returns => workflow_types_js_1.LabelingWorkflow, {
498
+ description: 'Pause a workflow'
499
+ }),
500
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "mutation")'),
501
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('workflowId')),
502
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
503
+ tslib_1.__metadata("design:type", Function),
504
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
505
+ tslib_1.__metadata("design:returntype", Promise)
506
+ ], LabelingWorkflowService.prototype, "pauseLabelingWorkflow", null);
507
+ tslib_1.__decorate([
508
+ (0, type_graphql_1.Mutation)(returns => workflow_types_js_1.LabelingWorkflow, {
509
+ description: 'Resume a paused workflow'
510
+ }),
511
+ (0, type_graphql_1.Directive)('@privilege(category: "labeling", privilege: "mutation")'),
512
+ tslib_1.__param(0, (0, type_graphql_1.Arg)('workflowId')),
513
+ tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
514
+ tslib_1.__metadata("design:type", Function),
515
+ tslib_1.__metadata("design:paramtypes", [String, Object]),
516
+ tslib_1.__metadata("design:returntype", Promise)
517
+ ], LabelingWorkflowService.prototype, "resumeLabelingWorkflow", null);
518
+ exports.LabelingWorkflowService = LabelingWorkflowService = tslib_1.__decorate([
519
+ (0, type_graphql_1.Resolver)()
520
+ ], LabelingWorkflowService);
521
+ //# sourceMappingURL=labeling-workflow-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labeling-workflow-service.js","sourceRoot":"","sources":["../../server/service/labeling-workflow-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Resolver, Query, Mutation, Arg, Ctx, Int, Directive } from 'type-graphql'\nimport { getRepository, IsNull } from 'typeorm'\nimport {\n CreateWorkflowRequest,\n ExecuteWorkflowRequest,\n WorkflowExecutionResult,\n LabelingWorkflow as LabelingWorkflowType,\n WorkflowExecution as WorkflowExecutionType,\n LabelingWorkflowList,\n WorkflowExecutionList,\n WorkflowStatus,\n WorkflowStepType,\n TriggerType,\n WorkflowStep\n} from '../types/workflow-types.js'\nimport { LabelingWorkflow as LabelingWorkflowEntity } from './labeling-workflow.js'\nimport { WorkflowExecution as WorkflowExecutionEntity } from './workflow-execution.js'\nimport { WorkflowExecutionStep as WorkflowExecutionStepEntity } from './workflow-execution-step.js'\nimport { DatasetLabelingIntegration } from '@things-factory/integration-label-studio/dist-server/service/dataset-labeling-integration.js'\nimport { ExternalDataSourceService } from '@things-factory/integration-label-studio/dist-server/service/external-data-source-service.js'\nimport { LabelStudioAIPredictionService } from '@things-factory/integration-label-studio/dist-server/service/ai-prediction-service.js'\n\n/**\n * Labeling Workflow Service\n *\n * Orchestrates end-to-end labeling workflows with multiple steps\n *\n * Features:\n * - Define multi-step labeling workflows\n * - Auto-execute workflows based on triggers\n * - Track execution progress\n * - Error handling and retry logic\n * - Conditional execution\n * - Database persistence with TypeORM\n */\n@Resolver()\nexport class LabelingWorkflowService {\n // Service dependencies (lazy initialization)\n private datasetIntegration: DatasetLabelingIntegration | null = null\n private externalDataSource: ExternalDataSourceService | null = null\n private aiPredictionService: LabelStudioAIPredictionService | null = null\n\n private getDatasetIntegration(): DatasetLabelingIntegration {\n if (!this.datasetIntegration) {\n this.datasetIntegration = new DatasetLabelingIntegration()\n }\n return this.datasetIntegration\n }\n\n private getExternalDataSource(): ExternalDataSourceService {\n if (!this.externalDataSource) {\n this.externalDataSource = new ExternalDataSourceService()\n }\n return this.externalDataSource\n }\n\n private getAIPredictionService(): LabelStudioAIPredictionService {\n if (!this.aiPredictionService) {\n this.aiPredictionService = new LabelStudioAIPredictionService()\n }\n return this.aiPredictionService\n }\n\n /**\n * Convert Entity to GraphQL Type\n */\n private toWorkflowType(entity: LabelingWorkflowEntity): LabelingWorkflowType {\n return {\n ...entity,\n steps: JSON.parse(entity.steps)\n } as LabelingWorkflowType\n }\n\n private toExecutionType(entity: WorkflowExecutionEntity): WorkflowExecutionType {\n return entity as any as WorkflowExecutionType\n }\n\n /**\n * Create a new labeling workflow\n */\n @Mutation(returns => LabelingWorkflowType, {\n description: 'Create a new labeling workflow'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"mutation\")')\n async createLabelingWorkflow(\n @Arg('input') input: CreateWorkflowRequest,\n @Ctx() context: ResolverContext\n ): Promise<LabelingWorkflowType> {\n console.log(`[Workflow] Creating workflow: ${input.name}`)\n\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n\n const workflow = workflowRepo.create({\n domain: context.state.domain,\n creator: context.state.user,\n name: input.name,\n description: input.description,\n projectId: input.projectId,\n triggerType: input.triggerType,\n triggerConfig: input.triggerConfig,\n steps: JSON.stringify(\n input.steps.map((step, index) => ({\n name: step.name,\n type: step.type,\n config: step.config,\n condition: step.condition,\n continueOnError: step.continueOnError !== undefined ? step.continueOnError : true,\n maxRetries: step.maxRetries,\n order: index + 1\n }))\n ),\n status: input.autoStart ? WorkflowStatus.Active : WorkflowStatus.Draft\n })\n\n await workflowRepo.save(workflow)\n\n console.log(`[Workflow] Created workflow ${workflow.id} with ${input.steps.length} steps`)\n\n return this.toWorkflowType(workflow)\n }\n\n /**\n * Execute a workflow\n */\n @Mutation(returns => WorkflowExecutionResult, {\n description: 'Execute a labeling workflow'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"mutation\")')\n async executeLabelingWorkflow(\n @Arg('input') input: ExecuteWorkflowRequest,\n @Ctx() context: ResolverContext\n ): Promise<WorkflowExecutionResult> {\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n const workflow = await workflowRepo.findOne({\n where: { id: input.workflowId, domain: context.state.domain, deletedAt: IsNull() }\n })\n\n if (!workflow) {\n throw new Error(`Workflow not found: ${input.workflowId}`)\n }\n\n console.log(`[Workflow] Executing workflow: ${workflow.name} (${workflow.id})`)\n\n const steps = JSON.parse(workflow.steps) as WorkflowStep[]\n\n const executionRepo = getRepository(WorkflowExecutionEntity)\n const execution = executionRepo.create({\n domain: context.state.domain,\n workflow,\n workflowId: workflow.id,\n workflowName: workflow.name,\n status: 'running',\n startedAt: new Date()\n })\n\n await executionRepo.save(execution)\n\n // Create execution steps\n const stepRepo = getRepository(WorkflowExecutionStepEntity)\n await Promise.all(\n steps.map((step, index) =>\n stepRepo.save(\n stepRepo.create({\n domain: context.state.domain,\n execution,\n executionId: execution.id,\n stepName: step.name,\n stepType: step.type,\n order: index + 1,\n status: 'pending'\n })\n )\n )\n )\n\n // Execute asynchronously\n this.executeWorkflowAsync(execution.id, workflow.id, steps, context, input.parameters).catch(error => {\n console.error(`[Workflow] Execution failed:`, error)\n })\n\n return {\n executionId: execution.id,\n status: 'running',\n summary: `Started execution of ${steps.length} steps`\n }\n }\n\n /**\n * Get workflow details\n */\n @Query(returns => LabelingWorkflowType, {\n description: 'Get labeling workflow details'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"query\")')\n async labelingWorkflow(\n @Arg('workflowId') workflowId: string,\n @Ctx() context: ResolverContext\n ): Promise<LabelingWorkflowType> {\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n const workflow = await workflowRepo.findOne({\n where: { id: workflowId, domain: context.state.domain, deletedAt: IsNull() }\n })\n\n if (!workflow) {\n throw new Error(`Workflow not found: ${workflowId}`)\n }\n\n return this.toWorkflowType(workflow)\n }\n\n /**\n * List all workflows\n */\n @Query(returns => LabelingWorkflowList, {\n description: 'List all labeling workflows'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"query\")')\n async labelingWorkflows(\n @Arg('projectId', type => Int, { nullable: true }) projectId: number,\n @Ctx() context: ResolverContext\n ): Promise<LabelingWorkflowList> {\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n const queryBuilder = workflowRepo\n .createQueryBuilder('workflow')\n .where('workflow.domain = :domain', { domain: context.state.domain.id })\n .andWhere('workflow.deletedAt IS NULL')\n\n if (projectId) {\n queryBuilder.andWhere('workflow.projectId = :projectId', { projectId })\n }\n\n const [entities, total] = await queryBuilder.orderBy('workflow.createdAt', 'DESC').getManyAndCount()\n const items = entities.map(e => this.toWorkflowType(e))\n\n return { items, total }\n }\n\n /**\n * Get execution status\n */\n @Query(returns => WorkflowExecutionType, {\n description: 'Get workflow execution status'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"query\")')\n async workflowExecution(\n @Arg('executionId') executionId: string,\n @Ctx() context: ResolverContext\n ): Promise<WorkflowExecutionType> {\n const executionRepo = getRepository(WorkflowExecutionEntity)\n const execution = await executionRepo.findOne({\n where: { id: executionId, domain: context.state.domain, deletedAt: IsNull() },\n relations: ['steps']\n })\n\n if (!execution) {\n throw new Error(`Execution not found: ${executionId}`)\n }\n\n return this.toExecutionType(execution)\n }\n\n /**\n * List executions for a workflow\n */\n @Query(returns => WorkflowExecutionList, {\n description: 'List executions for a workflow'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"query\")')\n async workflowExecutions(\n @Arg('workflowId') workflowId: string,\n @Ctx() context: ResolverContext\n ): Promise<WorkflowExecutionList> {\n const executionRepo = getRepository(WorkflowExecutionEntity)\n const [entities, total] = await executionRepo.findAndCount({\n where: { workflowId, domain: context.state.domain, deletedAt: IsNull() },\n order: { startedAt: 'DESC' }\n })\n\n const items = entities.map(e => this.toExecutionType(e))\n return { items, total }\n }\n\n /**\n * Pause a workflow\n */\n @Mutation(returns => LabelingWorkflowType, {\n description: 'Pause a workflow'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"mutation\")')\n async pauseLabelingWorkflow(\n @Arg('workflowId') workflowId: string,\n @Ctx() context: ResolverContext\n ): Promise<LabelingWorkflowType> {\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n const workflow = await workflowRepo.findOne({\n where: { id: workflowId, domain: context.state.domain, deletedAt: IsNull() }\n })\n\n if (!workflow) {\n throw new Error(`Workflow not found: ${workflowId}`)\n }\n\n workflow.status = WorkflowStatus.Paused\n await workflowRepo.save(workflow)\n\n console.log(`[Workflow] Paused workflow: ${workflow.name}`)\n\n return this.toWorkflowType(workflow)\n }\n\n /**\n * Resume a workflow\n */\n @Mutation(returns => LabelingWorkflowType, {\n description: 'Resume a paused workflow'\n })\n @Directive('@privilege(category: \"labeling\", privilege: \"mutation\")')\n async resumeLabelingWorkflow(\n @Arg('workflowId') workflowId: string,\n @Ctx() context: ResolverContext\n ): Promise<LabelingWorkflowType> {\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n const workflow = await workflowRepo.findOne({\n where: { id: workflowId, domain: context.state.domain, deletedAt: IsNull() }\n })\n\n if (!workflow) {\n throw new Error(`Workflow not found: ${workflowId}`)\n }\n\n workflow.status = WorkflowStatus.Active\n await workflowRepo.save(workflow)\n\n console.log(`[Workflow] Resumed workflow: ${workflow.name}`)\n\n return this.toWorkflowType(workflow)\n }\n\n // ============================================================================\n // Private Methods - Workflow Execution Engine\n // ============================================================================\n\n private async executeWorkflowAsync(\n executionId: string,\n workflowId: string,\n steps: WorkflowStep[],\n context: ResolverContext,\n parametersJson?: string\n ): Promise<void> {\n const startTime = Date.now()\n const parameters = parametersJson ? JSON.parse(parametersJson) : {}\n\n console.log(`[Workflow] Starting execution ${executionId}`)\n\n const executionRepo = getRepository(WorkflowExecutionEntity)\n const stepRepo = getRepository(WorkflowExecutionStepEntity)\n const workflowRepo = getRepository(LabelingWorkflowEntity)\n\n const execution = await executionRepo.findOne({\n where: { id: executionId },\n relations: ['steps', 'workflow']\n })\n\n if (!execution) {\n throw new Error(`Execution not found: ${executionId}`)\n }\n\n try {\n for (const [index, workflowStep] of steps.entries()) {\n const executionStep = execution.steps[index]\n executionStep.status = 'running'\n executionStep.startedAt = new Date()\n await stepRepo.save(executionStep)\n\n console.log(`[Workflow] Executing step ${index + 1}/${steps.length}: ${workflowStep.name}`)\n\n try {\n // Check condition if specified\n if (workflowStep.condition) {\n const conditionMet = this.evaluateCondition(workflowStep.condition, parameters)\n if (!conditionMet) {\n console.log(`[Workflow] Step ${workflowStep.name} condition not met, skipping`)\n executionStep.status = 'skipped'\n executionStep.completedAt = new Date()\n await stepRepo.save(executionStep)\n continue\n }\n }\n\n // Execute step\n const stepConfig = JSON.parse(workflowStep.config)\n const stepResult = await this.executeStep(\n workflowStep.type,\n stepConfig,\n execution.workflow.projectId,\n context,\n parameters\n )\n\n executionStep.status = 'completed'\n executionStep.output = JSON.stringify(stepResult)\n executionStep.completedAt = new Date()\n executionStep.durationMs = executionStep.completedAt.getTime() - executionStep.startedAt.getTime()\n await stepRepo.save(executionStep)\n\n console.log(`[Workflow] Step ${workflowStep.name} completed in ${executionStep.durationMs}ms`)\n\n // Store step result in parameters for next steps\n parameters[`step_${index}_result`] = stepResult\n } catch (stepError) {\n console.error(`[Workflow] Step ${workflowStep.name} failed:`, stepError)\n\n executionStep.status = 'failed'\n executionStep.error = stepError.message\n executionStep.completedAt = new Date()\n executionStep.durationMs = executionStep.completedAt.getTime() - executionStep.startedAt.getTime()\n await stepRepo.save(executionStep)\n\n // Check if we should continue on error\n if (!workflowStep.continueOnError) {\n throw new Error(`Step ${workflowStep.name} failed: ${stepError.message}`)\n }\n\n console.log(`[Workflow] Continuing despite error (continueOnError=true)`)\n }\n }\n\n // All steps completed\n execution.status = 'completed'\n execution.summary = this.generateExecutionSummary(execution.steps)\n execution.completedAt = new Date()\n execution.totalDurationMs = Date.now() - startTime\n await executionRepo.save(execution)\n\n console.log(`[Workflow] Execution completed in ${execution.totalDurationMs}ms`)\n\n // Update workflow status\n const workflow = await workflowRepo.findOne({ where: { id: workflowId } })\n if (workflow) {\n workflow.lastExecutedAt = new Date()\n if (workflow.triggerType === TriggerType.Schedule) {\n // Calculate next execution time (simplified, needs proper cron parser)\n // workflow.nextExecutionAt = ...\n }\n await workflowRepo.save(workflow)\n }\n } catch (error) {\n console.error(`[Workflow] Execution failed:`, error)\n\n execution.status = 'failed'\n execution.error = error.message\n execution.summary = `Failed: ${error.message}`\n execution.completedAt = new Date()\n execution.totalDurationMs = Date.now() - startTime\n await executionRepo.save(execution)\n }\n }\n\n private async executeStep(\n stepType: WorkflowStepType,\n config: any,\n projectId: number,\n context: ResolverContext,\n parameters: any\n ): Promise<any> {\n switch (stepType) {\n case WorkflowStepType.ImportData:\n return await this.executeImportDataStep(config, projectId, context, parameters)\n\n case WorkflowStepType.GeneratePredictions:\n return await this.executeGeneratePredictionsStep(config, projectId, context, parameters)\n\n case WorkflowStepType.WaitForAnnotations:\n return await this.executeWaitForAnnotationsStep(config, projectId, context)\n\n case WorkflowStepType.SyncAnnotations:\n return await this.executeSyncAnnotationsStep(config, projectId, context, parameters)\n\n case WorkflowStepType.ValidateQuality:\n return await this.executeValidateQualityStep(config, projectId, context, parameters)\n\n case WorkflowStepType.Notification:\n return await this.executeNotificationStep(config, parameters)\n\n default:\n throw new Error(`Unknown step type: ${stepType}`)\n }\n }\n\n private async executeImportDataStep(\n config: any,\n projectId: number,\n context: ResolverContext,\n parameters: any\n ): Promise<any> {\n if (config.sourceType === 'dataset') {\n return await this.getDatasetIntegration().createLabelingTasksFromDataset(\n {\n projectId,\n dataSetId: config.dataSetId,\n imageField: config.imageField,\n autoGeneratePredictions: config.autoGeneratePredictions || false,\n limit: config.limit\n },\n context\n )\n } else {\n return await this.getExternalDataSource().importFromExternalSource(\n {\n projectId,\n source: {\n sourceType: config.sourceType,\n sourceUrl: config.sourceUrl,\n authHeader: config.authHeader,\n dataPath: config.dataPath\n },\n imageField: config.imageField,\n limit: config.limit\n },\n context\n )\n }\n }\n\n private async executeGeneratePredictionsStep(\n config: any,\n projectId: number,\n context: ResolverContext,\n parameters: any\n ): Promise<any> {\n const dataSetId = parameters.dataSetId || config.dataSetId\n\n if (!dataSetId) {\n throw new Error('dataSetId required for GeneratePredictions step')\n }\n\n return await this.getDatasetIntegration().generatePredictionsForDataset(\n {\n dataSetId,\n projectId,\n modelId: config.modelId,\n confidenceThreshold: config.confidenceThreshold,\n forceRegenerate: config.forceRegenerate || false\n },\n context\n )\n }\n\n private async executeWaitForAnnotationsStep(config: any, projectId: number, context: ResolverContext): Promise<any> {\n // This is a simplified implementation\n // In production, this should poll or use webhooks\n console.log(`[Workflow] WaitForAnnotations step - checking criteria`)\n\n // TODO: Implement actual waiting/polling logic\n return {\n status: 'waiting',\n message: 'WaitForAnnotations step - manual check required'\n }\n }\n\n private async executeSyncAnnotationsStep(\n config: any,\n projectId: number,\n context: ResolverContext,\n parameters: any\n ): Promise<any> {\n const dataSetId = parameters.dataSetId || config.dataSetId\n\n if (!dataSetId) {\n throw new Error('dataSetId required for SyncAnnotations step')\n }\n\n return await this.getDatasetIntegration().syncAnnotationsToDataset(\n {\n projectId,\n dataSetId,\n completedOnly: config.completedOnly !== false,\n sinceDate: config.sinceDate\n },\n context\n )\n }\n\n private async executeValidateQualityStep(\n config: any,\n projectId: number,\n context: ResolverContext,\n parameters: any\n ): Promise<any> {\n console.log(`[Workflow] ValidateQuality step`)\n\n // TODO: Implement quality validation logic\n return {\n status: 'validated',\n message: 'Quality validation - not yet implemented'\n }\n }\n\n private async executeNotificationStep(config: any, parameters: any): Promise<any> {\n console.log(`[Workflow] Notification step: ${config.message}`)\n\n // TODO: Implement actual notification (email, webhook, etc.)\n return {\n status: 'sent',\n message: config.message,\n recipients: config.recipients\n }\n }\n\n private evaluateCondition(condition: string, parameters: any): boolean {\n // Simple condition evaluation\n // In production, use a proper expression evaluator\n try {\n const conditionObj = JSON.parse(condition)\n // Example: { \"step_0_result.tasksCreated\": { \"$gt\": 0 } }\n // For now, always return true\n return true\n } catch (error) {\n console.warn(`[Workflow] Failed to evaluate condition: ${condition}`)\n return true\n }\n }\n\n private generateExecutionSummary(steps: WorkflowExecutionStepEntity[]): string {\n const completed = steps.filter(s => s.status === 'completed').length\n const failed = steps.filter(s => s.status === 'failed').length\n const skipped = steps.filter(s => s.status === 'skipped').length\n\n return `Completed ${completed}/${steps.length} steps (${failed} failed, ${skipped} skipped)`\n }\n}\n"]}
@@ -0,0 +1,30 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ import { User } from '@things-factory/auth-base';
3
+ import { WorkflowExecution } from './workflow-execution.js';
4
+ import { WorkflowStatus, TriggerType } from '../types/workflow-types.js';
5
+ /**
6
+ * LabelingWorkflow Entity
7
+ *
8
+ * Represents a labeling workflow definition with multiple steps.
9
+ * Stores workflow configuration, steps, and trigger settings.
10
+ */
11
+ export declare class LabelingWorkflow {
12
+ id: string;
13
+ domain?: Domain;
14
+ domainId?: string;
15
+ creator?: User;
16
+ creatorId?: string;
17
+ name: string;
18
+ description?: string;
19
+ projectId: number;
20
+ triggerType: TriggerType;
21
+ triggerConfig?: string;
22
+ steps: string;
23
+ status: WorkflowStatus;
24
+ lastExecutedAt?: Date;
25
+ nextExecutionAt?: Date;
26
+ executions?: WorkflowExecution[];
27
+ createdAt: Date;
28
+ updatedAt: Date;
29
+ deletedAt?: Date;
30
+ }