@solidxai/core 0.1.13-beta.3 → 0.1.13-beta.4

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 (131) hide show
  1. package/dist/commands/seed.command.d.ts +2 -0
  2. package/dist/commands/seed.command.d.ts.map +1 -1
  3. package/dist/commands/seed.command.js +21 -0
  4. package/dist/commands/seed.command.js.map +1 -1
  5. package/dist/entities/workflow-trigger-execution.entity.js +1 -1
  6. package/dist/entities/workflow-trigger-execution.entity.js.map +1 -1
  7. package/dist/index.d.ts +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/index.js.map +1 -1
  11. package/dist/interfaces.d.ts +1 -0
  12. package/dist/interfaces.d.ts.map +1 -1
  13. package/dist/interfaces.js.map +1 -1
  14. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  15. package/dist/seeders/module-metadata-seeder.service.js +44 -27
  16. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  17. package/dist/seeders/seed-data/solid-core-metadata.json +80 -67
  18. package/dist/services/workflow/nodes/execution-fail.node.d.ts +6 -0
  19. package/dist/services/workflow/nodes/execution-fail.node.d.ts.map +1 -0
  20. package/dist/services/workflow/nodes/execution-fail.node.js +81 -0
  21. package/dist/services/workflow/nodes/execution-fail.node.js.map +1 -0
  22. package/dist/services/workflow/nodes/for-each.node.d.ts +2 -0
  23. package/dist/services/workflow/nodes/for-each.node.d.ts.map +1 -1
  24. package/dist/services/workflow/nodes/for-each.node.js +114 -5
  25. package/dist/services/workflow/nodes/for-each.node.js.map +1 -1
  26. package/dist/services/workflow/nodes/if.node.d.ts.map +1 -1
  27. package/dist/services/workflow/nodes/if.node.js +7 -0
  28. package/dist/services/workflow/nodes/if.node.js.map +1 -1
  29. package/dist/services/workflow/nodes/log-write.node.d.ts.map +1 -1
  30. package/dist/services/workflow/nodes/log-write.node.js +2 -0
  31. package/dist/services/workflow/nodes/log-write.node.js.map +1 -1
  32. package/dist/services/workflow/nodes/loop-until.node.d.ts +12 -0
  33. package/dist/services/workflow/nodes/loop-until.node.d.ts.map +1 -0
  34. package/dist/services/workflow/nodes/loop-until.node.js +281 -0
  35. package/dist/services/workflow/nodes/loop-until.node.js.map +1 -0
  36. package/dist/services/workflow/nodes/parallel.node.d.ts.map +1 -1
  37. package/dist/services/workflow/nodes/parallel.node.js +7 -0
  38. package/dist/services/workflow/nodes/parallel.node.js.map +1 -1
  39. package/dist/services/workflow/nodes/sequential.node.d.ts.map +1 -1
  40. package/dist/services/workflow/nodes/sequential.node.js +7 -0
  41. package/dist/services/workflow/nodes/sequential.node.js.map +1 -1
  42. package/dist/services/workflow/nodes/switch.node.d.ts.map +1 -1
  43. package/dist/services/workflow/nodes/switch.node.js +7 -0
  44. package/dist/services/workflow/nodes/switch.node.js.map +1 -1
  45. package/dist/services/workflow/workflow-definition-validator.service.d.ts.map +1 -1
  46. package/dist/services/workflow/workflow-definition-validator.service.js +5 -2
  47. package/dist/services/workflow/workflow-definition-validator.service.js.map +1 -1
  48. package/dist/services/workflow/workflow-expression.service.d.ts.map +1 -1
  49. package/dist/services/workflow/workflow-expression.service.js +5 -0
  50. package/dist/services/workflow/workflow-expression.service.js.map +1 -1
  51. package/dist/services/workflow/workflow-node-registry.service.d.ts +2 -1
  52. package/dist/services/workflow/workflow-node-registry.service.d.ts.map +1 -1
  53. package/dist/services/workflow/workflow-node-registry.service.js +7 -0
  54. package/dist/services/workflow/workflow-node-registry.service.js.map +1 -1
  55. package/dist/services/workflow/workflow-runtime.service.d.ts +8 -0
  56. package/dist/services/workflow/workflow-runtime.service.d.ts.map +1 -1
  57. package/dist/services/workflow/workflow-runtime.service.js +197 -32
  58. package/dist/services/workflow/workflow-runtime.service.js.map +1 -1
  59. package/dist/solid-core.module.d.ts.map +1 -1
  60. package/dist/solid-core.module.js +4 -0
  61. package/dist/solid-core.module.js.map +1 -1
  62. package/dist/types/workflow-dsl.types.d.ts +14 -0
  63. package/dist/types/workflow-dsl.types.d.ts.map +1 -1
  64. package/dist/types/workflow-dsl.types.js.map +1 -1
  65. package/dist-tests/api/authenticate.spec.js +119 -0
  66. package/dist-tests/api/authenticate.spec.js.map +1 -0
  67. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  68. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  69. package/dist-tests/api/ping.spec.js +21 -0
  70. package/dist-tests/api/ping.spec.js.map +1 -0
  71. package/dist-tests/helpers/auth.js +41 -0
  72. package/dist-tests/helpers/auth.js.map +1 -0
  73. package/dist-tests/helpers/env.js +11 -0
  74. package/dist-tests/helpers/env.js.map +1 -0
  75. package/docs/agent-builder/notebook-lm-prompt-for-agent-builder.md +136 -0
  76. package/docs/agent-builder/team-ready-note-agent-builder.md +305 -0
  77. package/docs/agent-hub-grooming.md +301 -0
  78. package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +438 -0
  79. package/docs/dashboards/dashboard-curl-smoke-tests.txt +146 -0
  80. package/docs/dashboards/delete-legacy-dashboard-metadata.sql +172 -0
  81. package/docs/datasource-introspection-ddl-analysis.md +326 -0
  82. package/docs/datasource-introspection-implementation-plan.md +306 -0
  83. package/docs/grouping-enhancements.md +89 -0
  84. package/docs/java-spring/README.md +3 -0
  85. package/docs/java-spring/solid-core-module-deep-dive-report.md +1317 -0
  86. package/docs/module-package-import-handoff.md +691 -0
  87. package/docs/seed-changes.md +65 -0
  88. package/docs/test-data-workflow.md +200 -0
  89. package/docs/type-declaration-import-issue.md +24 -0
  90. package/docs/workflow/business-automation-example-notes.md +309 -0
  91. package/docs/workflow/control-flow-node-addition-sop.md +324 -0
  92. package/docs/workflow/data-engineering-pipeline-example-notes.md +330 -0
  93. package/docs/workflow/foreach-example-notes.md +187 -0
  94. package/docs/workflow/hello-world-example-notes.md +271 -0
  95. package/docs/workflow/kestra-concepts-plugins-blueprints.md +315 -0
  96. package/docs/workflow/loop-until-example-notes.md +198 -0
  97. package/docs/workflow/microservices-and-apis-example-notes.md +264 -0
  98. package/docs/workflow/samples.md +25 -0
  99. package/docs/workflow/what-is-kestra.md +79 -0
  100. package/docs/workflow/workflow-core-module-handoff-summary.md +191 -0
  101. package/docs/workflow/workflow-module-brd.md +185 -0
  102. package/docs/workflow/workflow-module-domain-model.md +252 -0
  103. package/docs/workflow/workflow-module-metadata-dsl.md +302 -0
  104. package/docs/workflow/workflow-module-technical-spec.md +293 -0
  105. package/docs/workflow/workflow-node-type-contracts.md +635 -0
  106. package/docs/workflow/workflow-node-ui-metadata-contract.md +1262 -0
  107. package/docs/workflow/workflow-solidx-model-field-spec.md +284 -0
  108. package/package.json +1 -1
  109. package/src/commands/seed.command.ts +19 -0
  110. package/src/entities/workflow-trigger-execution.entity.ts +1 -1
  111. package/src/index.ts +2 -0
  112. package/src/interfaces.ts +1 -0
  113. package/src/seeders/module-metadata-seeder.service.ts +50 -36
  114. package/src/seeders/seed-data/solid-core-metadata.json +80 -67
  115. package/src/services/workflow/nodes/execution-fail.node.ts +82 -0
  116. package/src/services/workflow/nodes/for-each.node.ts +140 -6
  117. package/src/services/workflow/nodes/if.node.ts +7 -0
  118. package/src/services/workflow/nodes/log-write.node.ts +2 -0
  119. package/src/services/workflow/nodes/loop-until.node.ts +343 -0
  120. package/src/services/workflow/nodes/parallel.node.ts +7 -0
  121. package/src/services/workflow/nodes/sequential.node.ts +7 -0
  122. package/src/services/workflow/nodes/switch.node.ts +7 -0
  123. package/src/services/workflow/workflow-definition-validator.service.ts +5 -2
  124. package/src/services/workflow/workflow-expression.service.ts +5 -0
  125. package/src/services/workflow/workflow-node-registry.service.ts +11 -0
  126. package/src/services/workflow/workflow-runtime.service.ts +274 -39
  127. package/src/solid-core.module.ts +4 -0
  128. package/src/types/workflow-dsl.types.ts +43 -0
  129. package/.claude/settings.local.json +0 -16
  130. package/CLAUDE.md +0 -26
  131. package/src/services/1.js +0 -6
@@ -161,7 +161,11 @@ export class WorkflowRuntimeService {
161
161
  const execution = existingExecution
162
162
  ? await this.writer.startExecution(existingExecution, effectiveRequest)
163
163
  : await this.writer.createExecution(definition, effectiveRequest);
164
- const nodeCount = this.countNodes(definitionDsl.nodes);
164
+ const nodeCount = this.countNodes([
165
+ ...(definitionDsl.nodes ?? []),
166
+ ...(definitionDsl.errors ?? []),
167
+ ...(definitionDsl.finally ?? []),
168
+ ]);
165
169
  const outputs: Record<string, any> = {};
166
170
  const runtimeContext: WorkflowRuntimeContext = {
167
171
  execution,
@@ -175,26 +179,52 @@ export class WorkflowRuntimeService {
175
179
  },
176
180
  };
177
181
 
182
+ this.logger.log(
183
+ `Starting workflow execution ${execution.executionIdentifier} for ${definition.key} with ${nodeCount} node(s).`,
184
+ );
185
+ await this.writer.writeLog(execution, undefined, {
186
+ level: 'info',
187
+ eventType: 'execution.started',
188
+ message: `Workflow execution started for ${definition.key}.`,
189
+ metadata: {
190
+ executionIdentifier: execution.executionIdentifier,
191
+ workflowKey: definition.key,
192
+ triggerType: execution.triggerType,
193
+ nodeCount,
194
+ inputKeys: Object.keys(runtimeContext.input ?? {}),
195
+ variableKeys: Object.keys(runtimeContext.variables ?? {}),
196
+ },
197
+ }, this.nextLogSequence(runtimeContext));
198
+
199
+ let executionError: unknown;
200
+
178
201
  try {
179
- this.logger.log(
180
- `Starting workflow execution ${execution.executionIdentifier} for ${definition.key} with ${nodeCount} node(s).`,
181
- );
202
+ await this.runNodes(definitionDsl.nodes, runtimeContext);
203
+ } catch (error) {
204
+ executionError = error;
205
+ await this.runGlobalErrorHandlers(definitionDsl, runtimeContext, error);
206
+ }
207
+
208
+ try {
209
+ await this.runFinallyHandlers(definitionDsl, runtimeContext);
210
+ } catch (finallyError) {
182
211
  await this.writer.writeLog(execution, undefined, {
183
- level: 'info',
184
- eventType: 'execution.started',
185
- message: `Workflow execution started for ${definition.key}.`,
212
+ level: 'error',
213
+ eventType: 'finally.failed',
214
+ message: `Finally handler failed: ${this.errorMessage(finallyError)}.`,
215
+ context: this.summarizeError(finallyError),
186
216
  metadata: {
187
- executionIdentifier: execution.executionIdentifier,
188
- workflowKey: definition.key,
189
- triggerType: execution.triggerType,
190
- nodeCount,
191
- inputKeys: Object.keys(runtimeContext.input ?? {}),
192
- variableKeys: Object.keys(runtimeContext.variables ?? {}),
217
+ originalError: executionError
218
+ ? this.summarizeError(executionError)
219
+ : undefined,
193
220
  },
194
221
  }, this.nextLogSequence(runtimeContext));
222
+ if (!executionError) {
223
+ executionError = finallyError;
224
+ }
225
+ }
195
226
 
196
- await this.runNodes(definitionDsl.nodes, runtimeContext);
197
-
227
+ if (!executionError) {
198
228
  const completed = await this.writer.completeExecution(execution, outputs);
199
229
 
200
230
  this.logger.log(
@@ -212,26 +242,26 @@ export class WorkflowRuntimeService {
212
242
  }, this.nextLogSequence(runtimeContext));
213
243
 
214
244
  return this.toResponse(completed);
215
- } catch (error) {
216
- const failed = await this.writer.failExecution(execution, error);
245
+ }
217
246
 
218
- this.logger.error(
219
- `Failed workflow execution ${failed.executionIdentifier} for ${definition.key}: ${failed.errorSummary}`,
220
- error instanceof Error ? error.stack : undefined,
221
- );
222
- await this.writer.writeLog(failed, undefined, {
223
- level: 'error',
224
- eventType: 'execution.failed',
225
- message: failed.errorSummary,
226
- context: this.summarizeError(error),
227
- metadata: {
228
- executionIdentifier: failed.executionIdentifier,
229
- durationMs: failed.durationMs,
230
- },
231
- }, this.nextLogSequence(runtimeContext));
247
+ const failed = await this.writer.failExecution(execution, executionError);
232
248
 
233
- return this.toResponse(failed);
234
- }
249
+ this.logger.error(
250
+ `Failed workflow execution ${failed.executionIdentifier} for ${definition.key}: ${failed.errorSummary}`,
251
+ executionError instanceof Error ? executionError.stack : undefined,
252
+ );
253
+ await this.writer.writeLog(failed, undefined, {
254
+ level: 'error',
255
+ eventType: 'execution.failed',
256
+ message: failed.errorSummary,
257
+ context: this.summarizeError(executionError),
258
+ metadata: {
259
+ executionIdentifier: failed.executionIdentifier,
260
+ durationMs: failed.durationMs,
261
+ },
262
+ }, this.nextLogSequence(runtimeContext));
263
+
264
+ return this.toResponse(failed);
235
265
  }
236
266
 
237
267
  async getExecutionStatus(executionId: number): Promise<WorkflowExecutionResponse> {
@@ -363,17 +393,19 @@ export class WorkflowRuntimeService {
363
393
  nodes: WorkflowNodeDefinition[],
364
394
  context: WorkflowRuntimeContext,
365
395
  ): Promise<Record<string, any>> {
396
+ const nodeOutputs: Record<string, any> = {};
397
+
366
398
  for (const node of nodes ?? []) {
367
- await this.runNode(node, context);
399
+ nodeOutputs[node.id] = await this.runNode(node, context);
368
400
  }
369
401
 
370
- return context.outputs;
402
+ return nodeOutputs;
371
403
  }
372
404
 
373
405
  private async runNode(
374
406
  node: WorkflowNodeDefinition,
375
407
  context: WorkflowRuntimeContext,
376
- ): Promise<void> {
408
+ ): Promise<Record<string, any>> {
377
409
  const inputPayload = {
378
410
  configuration: node.configuration,
379
411
  input: context.input,
@@ -400,7 +432,7 @@ export class WorkflowRuntimeService {
400
432
  message: `Skipped disabled node ${node.id}.`,
401
433
  metadata: this.nodeLogMetadata(node, context, step),
402
434
  }, this.nextLogSequence(context));
403
- return;
435
+ return context.outputs[node.id];
404
436
  }
405
437
 
406
438
  try {
@@ -444,7 +476,7 @@ export class WorkflowRuntimeService {
444
476
  });
445
477
 
446
478
  const output = result.output ?? {};
447
- context.outputs[node.id] = output;
479
+ context.outputs[node.id] = this.getRuntimeContextOutput(node, output);
448
480
 
449
481
  for (const artifact of result.artifacts ?? []) {
450
482
  await this.writer.writeArtifact(context.execution, step, artifact);
@@ -472,6 +504,8 @@ export class WorkflowRuntimeService {
472
504
  artifactCount: result.artifacts?.length ?? 0,
473
505
  },
474
506
  }, this.nextLogSequence(context));
507
+
508
+ return output;
475
509
  } catch (error) {
476
510
  await this.writer.failStep(step, error);
477
511
 
@@ -486,7 +520,7 @@ export class WorkflowRuntimeService {
486
520
  context: this.summarizeError(error),
487
521
  metadata: this.nodeLogMetadata(node, context, step),
488
522
  }, this.nextLogSequence(context));
489
- return;
523
+ return context.outputs[node.id];
490
524
  }
491
525
 
492
526
  await this.writer.writeLog(context.execution, step, {
@@ -496,10 +530,158 @@ export class WorkflowRuntimeService {
496
530
  context: this.summarizeError(error),
497
531
  metadata: this.nodeLogMetadata(node, context, step),
498
532
  }, this.nextLogSequence(context));
533
+ await this.runLocalErrorHandlers(node, context, error);
499
534
  throw error;
500
535
  }
501
536
  }
502
537
 
538
+ private async runGlobalErrorHandlers(
539
+ definitionDsl: WorkflowDefinitionDsl,
540
+ context: WorkflowRuntimeContext,
541
+ error: unknown,
542
+ ): Promise<void> {
543
+ const errorNodes = definitionDsl.errors ?? [];
544
+ if (!errorNodes.length) {
545
+ return;
546
+ }
547
+
548
+ await this.runErrorHandlers(
549
+ errorNodes,
550
+ context,
551
+ error,
552
+ 'global',
553
+ undefined,
554
+ undefined,
555
+ );
556
+ }
557
+
558
+ private async runFinallyHandlers(
559
+ definitionDsl: WorkflowDefinitionDsl,
560
+ context: WorkflowRuntimeContext,
561
+ ): Promise<void> {
562
+ const finallyNodes = definitionDsl.finally ?? [];
563
+ if (!finallyNodes.length) {
564
+ return;
565
+ }
566
+
567
+ await this.writer.writeLog(context.execution, undefined, {
568
+ level: 'info',
569
+ eventType: 'finally.started',
570
+ message: 'Running workflow finally handlers.',
571
+ metadata: {
572
+ handlerNodeCount: finallyNodes.length,
573
+ },
574
+ }, this.nextLogSequence(context));
575
+
576
+ await this.runNodes(finallyNodes, context);
577
+
578
+ await this.writer.writeLog(context.execution, undefined, {
579
+ level: 'info',
580
+ eventType: 'finally.completed',
581
+ message: 'Workflow finally handlers completed.',
582
+ metadata: {
583
+ handlerNodeCount: finallyNodes.length,
584
+ },
585
+ }, this.nextLogSequence(context));
586
+ }
587
+
588
+ private async runLocalErrorHandlers(
589
+ node: WorkflowNodeDefinition,
590
+ context: WorkflowRuntimeContext,
591
+ error: unknown,
592
+ ): Promise<void> {
593
+ const errorNodes = node.errors ?? [];
594
+ if (!errorNodes.length) {
595
+ return;
596
+ }
597
+
598
+ await this.runErrorHandlers(
599
+ errorNodes,
600
+ context,
601
+ error,
602
+ 'local',
603
+ node.id,
604
+ context.stepExecution?.stepExecutionKey,
605
+ );
606
+ }
607
+
608
+ private async runErrorHandlers(
609
+ errorNodes: WorkflowNodeDefinition[],
610
+ context: WorkflowRuntimeContext,
611
+ error: unknown,
612
+ scope: 'global' | 'local',
613
+ sourceNodeId?: string,
614
+ sourceStepExecutionKey?: string,
615
+ ): Promise<void> {
616
+ const errorContext = this.buildErrorContext(error, sourceNodeId, sourceStepExecutionKey);
617
+
618
+ await this.writer.writeLog(context.execution, undefined, {
619
+ level: 'warn',
620
+ eventType: `error-handler.${scope}.started`,
621
+ message:
622
+ scope === 'global'
623
+ ? 'Running workflow-level error handlers.'
624
+ : `Running local error handlers for node ${sourceNodeId}.`,
625
+ context: errorContext,
626
+ metadata: {
627
+ sourceNodeId,
628
+ sourceStepExecutionKey,
629
+ handlerNodeCount: errorNodes.length,
630
+ },
631
+ }, this.nextLogSequence(context));
632
+
633
+ try {
634
+ await this.runNodes(errorNodes, {
635
+ ...context,
636
+ error: errorContext,
637
+ parentNodeId: sourceNodeId ?? context.parentNodeId,
638
+ parentStepExecutionKey:
639
+ sourceStepExecutionKey ?? context.parentStepExecutionKey,
640
+ });
641
+ } catch (handlerError) {
642
+ await this.writer.writeLog(context.execution, undefined, {
643
+ level: 'error',
644
+ eventType: `error-handler.${scope}.failed`,
645
+ message: `Error handler failed: ${this.errorMessage(handlerError)}.`,
646
+ context: this.summarizeError(handlerError),
647
+ metadata: {
648
+ originalError: errorContext,
649
+ sourceNodeId,
650
+ sourceStepExecutionKey,
651
+ },
652
+ }, this.nextLogSequence(context));
653
+ return;
654
+ }
655
+
656
+ await this.writer.writeLog(context.execution, undefined, {
657
+ level: 'info',
658
+ eventType: `error-handler.${scope}.completed`,
659
+ message:
660
+ scope === 'global'
661
+ ? 'Workflow-level error handlers completed.'
662
+ : `Local error handlers completed for node ${sourceNodeId}.`,
663
+ context: errorContext,
664
+ metadata: {
665
+ sourceNodeId,
666
+ sourceStepExecutionKey,
667
+ },
668
+ }, this.nextLogSequence(context));
669
+ }
670
+
671
+ private buildErrorContext(
672
+ error: unknown,
673
+ nodeId?: string,
674
+ stepExecutionKey?: string,
675
+ ): Record<string, any> {
676
+ const summary = this.summarizeError(error);
677
+ return {
678
+ ...summary,
679
+ message: this.errorMessage(error),
680
+ nodeId,
681
+ stepExecutionKey,
682
+ };
683
+ }
684
+
503
685
  private assertDefinitionYaml(value: any): WorkflowDefinitionDsl {
504
686
  if (!value || typeof value !== 'string') {
505
687
  throw new BadRequestException(
@@ -627,6 +809,7 @@ export class WorkflowRuntimeService {
627
809
  ...(node.then ?? []),
628
810
  ...(node.else ?? []),
629
811
  ...(node.defaults ?? []),
812
+ ...(node.errors ?? []),
630
813
  ...Object.values(node.cases ?? {}).flat(),
631
814
  ];
632
815
 
@@ -660,6 +843,58 @@ export class WorkflowRuntimeService {
660
843
  };
661
844
  }
662
845
 
846
+ private getRuntimeContextOutput(
847
+ node: WorkflowNodeDefinition,
848
+ output: Record<string, any>,
849
+ ): Record<string, any> {
850
+ const hiddenOutputPaths =
851
+ this.registry
852
+ .getMetadata(node.type)
853
+ .authoring?.outputs?.filter(
854
+ (definition) => definition.includeInRuntimeContext === false,
855
+ )
856
+ .map((definition) => definition.path ?? definition.key)
857
+ .filter(Boolean) ?? [];
858
+
859
+ if (!hiddenOutputPaths.length || !output || typeof output !== 'object') {
860
+ return output;
861
+ }
862
+
863
+ const runtimeOutput = this.cloneOutput(output);
864
+ hiddenOutputPaths.forEach((path) => {
865
+ this.deletePath(runtimeOutput, path);
866
+ });
867
+
868
+ return runtimeOutput;
869
+ }
870
+
871
+ private cloneOutput(output: Record<string, any>): Record<string, any> {
872
+ if (typeof structuredClone === 'function') {
873
+ return structuredClone(output);
874
+ }
875
+
876
+ return JSON.parse(JSON.stringify(output));
877
+ }
878
+
879
+ private deletePath(target: Record<string, any>, path: string) {
880
+ const parts = path.split('.').filter(Boolean);
881
+ if (!parts.length) {
882
+ return;
883
+ }
884
+
885
+ let cursor: any = target;
886
+ for (let index = 0; index < parts.length - 1; index += 1) {
887
+ cursor = cursor?.[parts[index]];
888
+ if (!cursor || typeof cursor !== 'object') {
889
+ return;
890
+ }
891
+ }
892
+
893
+ if (cursor && typeof cursor === 'object') {
894
+ delete cursor[parts[parts.length - 1]];
895
+ }
896
+ }
897
+
663
898
  private summarizeValue(value: any): any {
664
899
  if (Array.isArray(value)) {
665
900
  return {
@@ -441,10 +441,12 @@ import { WorkflowInvocationService } from './services/workflow/workflow-invocati
441
441
  import { WorkflowNodeRegistryService } from './services/workflow/workflow-node-registry.service';
442
442
  import { WorkflowRuntimeService } from './services/workflow/workflow-runtime.service';
443
443
  import { WorkflowScheduledTriggerJobService } from './services/workflow/workflow-scheduled-trigger.job';
444
+ import { ExecutionFailNode } from './services/workflow/nodes/execution-fail.node';
444
445
  import { ForEachNode } from './services/workflow/nodes/for-each.node';
445
446
  import { HttpRequestNode } from './services/workflow/nodes/http-request.node';
446
447
  import { IfNode } from './services/workflow/nodes/if.node';
447
448
  import { LogWriteNode } from './services/workflow/nodes/log-write.node';
449
+ import { LoopUntilNode } from './services/workflow/nodes/loop-until.node';
448
450
  import { ParallelNode } from './services/workflow/nodes/parallel.node';
449
451
  import { RuntimePythonNode } from './services/workflow/nodes/runtime-python.node';
450
452
  import { SequentialNode } from './services/workflow/nodes/sequential.node';
@@ -947,10 +949,12 @@ import { SwitchNode } from './services/workflow/nodes/switch.node';
947
949
  WorkflowDefinitionValidatorService,
948
950
  WorkflowNodeRegistryService,
949
951
  WorkflowScheduledTriggerJobService,
952
+ ExecutionFailNode,
950
953
  LogWriteNode,
951
954
  HttpRequestNode,
952
955
  IfNode,
953
956
  ForEachNode,
957
+ LoopUntilNode,
954
958
  ParallelNode,
955
959
  RuntimePythonNode,
956
960
  SequentialNode,
@@ -200,6 +200,9 @@ export interface WorkflowNodeDefinition {
200
200
  /** Child nodes executed when no `switch.cases` entry matches the switch value. */
201
201
  defaults?: WorkflowNodeDefinition[];
202
202
 
203
+ /** Child nodes executed when this node or its child subtree fails. */
204
+ errors?: WorkflowNodeDefinition[];
205
+
203
206
  /**
204
207
  * Named child-node collections for `switch`.
205
208
  *
@@ -287,6 +290,12 @@ export interface WorkflowDefinitionDsl {
287
290
  /** Optional workflow triggers that can create executions. */
288
291
  triggers?: WorkflowTriggerDefinition[];
289
292
 
293
+ /** Workflow-level error handler nodes executed sequentially when execution fails. */
294
+ errors?: WorkflowNodeDefinition[];
295
+
296
+ /** Workflow-level cleanup nodes executed sequentially after success or failure. */
297
+ finally?: WorkflowNodeDefinition[];
298
+
290
299
  /** Workflow-level custom annotations for tooling. */
291
300
  metadata?: Record<string, any>;
292
301
  }
@@ -578,6 +587,13 @@ export interface WorkflowNodeOutputDefinition {
578
587
  /** Whether the output is expected on successful execution. */
579
588
  required?: boolean;
580
589
 
590
+ /**
591
+ * Whether this output is added to `outputs.<nodeId>` for downstream expressions.
592
+ * Defaults to true. Set false for observability-only outputs that should be
593
+ * stored on the step execution but not suggested or exposed to later nodes.
594
+ */
595
+ includeInRuntimeContext?: boolean;
596
+
581
597
  /** Optional machine schema for this output value. */
582
598
  schema?: Record<string, any>;
583
599
  }
@@ -867,6 +883,21 @@ export interface WorkflowExpressionResolver {
867
883
  resolveExpression(expression: string, context: WorkflowRuntimeContext): any;
868
884
  }
869
885
 
886
+ /** Loop context exposed to expressions for nested itemized controls. */
887
+ export interface WorkflowLoopContext {
888
+ /** Current item for this loop frame. */
889
+ item: any;
890
+
891
+ /** Zero-based iteration index for this loop frame. */
892
+ index: number;
893
+
894
+ /** Loop control node id. */
895
+ nodeId?: string;
896
+
897
+ /** Loop control step execution key. */
898
+ stepExecutionKey?: string;
899
+ }
900
+
870
901
  /** Runtime context shared by workflow execution and node execution. */
871
902
  export interface WorkflowRuntimeContext {
872
903
  /** Parent workflow execution entity. */
@@ -905,6 +936,18 @@ export interface WorkflowRuntimeContext {
905
936
  /** Current item index for itemized/iterative control nodes. */
906
937
  index?: number;
907
938
 
939
+ /** Nearest parent loop frame, when inside nested loop children. */
940
+ parent?: WorkflowLoopContext;
941
+
942
+ /** Parent loop frames, nearest first. */
943
+ parents?: WorkflowLoopContext[];
944
+
945
+ /** Loop frames from outermost to innermost, including the current loop. */
946
+ loops?: WorkflowLoopContext[];
947
+
948
+ /** Current error context when executing an error handler. */
949
+ error?: any;
950
+
908
951
  /** Parent control node id when executing nested child nodes. */
909
952
  parentNodeId?: string;
910
953
 
@@ -1,16 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(node -e:*)",
5
- "WebFetch(domain:docs.solidxai.com)",
6
- "WebFetch(domain:github.com)",
7
- "Read(//Users/oswald/projects/Solid_Starters/solidctl/**)",
8
- "Read(//Users/oswald/projects/Solid_Starters/**)",
9
- "Bash(find /Users/oswald/projects/Solid_Starters/solid-core-module -type d -name migration* -o -name *database*)",
10
- "Bash(node verify-imports.js)"
11
- ],
12
- "additionalDirectories": [
13
- "/Users/oswald/projects/Solid_Starters/solidctl"
14
- ]
15
- }
16
- }
package/CLAUDE.md DELETED
@@ -1,26 +0,0 @@
1
- # This is the SolidX API project.
2
- This is included as a dependency in consuming projects.
3
-
4
- # SolidX UI
5
- # The corresponding UI project is at the below path:
6
- /Users/oswald/projects/Solid_Starters/solid-core-ui
7
-
8
- # SolidX Docs
9
- # The documentation project is at the below path:
10
- /Users/oswald/projects/solidxai-docs
11
-
12
- # SolidX Agent
13
- # The agent project which has the skills for helping users configure, build and use SolidX is at the below path:
14
- /Users/oswald/projects/Solid_Starters/agent
15
-
16
- # SolidX Control Plane Commands
17
- # The control plane commands for managing SolidX instances are in the below path:
18
- /Users/oswald/projects/Solid_Starters/solidctl
19
-
20
- # Testing reference project
21
- # This is the reference library management project that is used for testing and development of SolidX features. It is located at the below path:
22
- /Users/oswald/projects/Solid_Starters/solid-library-management
23
-
24
- # Code Builder project
25
- # This is the project that contains the code builder which generates code based on user input and templates. It is located at the below path:
26
- /Users/oswald/projects/Solid_Starters/solid-code-builder
package/src/services/1.js DELETED
@@ -1,6 +0,0 @@
1
- 1. Do i need to create a storeStreams method for aws service too?
2
- - Handle later
3
- 2. queues handling -> if queues is enabled by default, i.e triggerExport(exportTransactionEntity.id).
4
- - startExport should either return the data or return the transaction id
5
- 3. How to handle scenarios wherein, nested related exist.(do i need to only get the userkey)
6
- - show the userKey