@outputai/core 0.10.1-next.b7b2fbe.0 → 0.10.1-next.bf95a6f.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.
Files changed (99) hide show
  1. package/package.json +13 -7
  2. package/src/bus.js +58 -20
  3. package/src/bus.spec.js +135 -77
  4. package/src/consts.js +7 -3
  5. package/src/errors.d.ts +12 -2
  6. package/src/errors.js +17 -3
  7. package/src/errors.spec.js +19 -0
  8. package/src/helpers/activity_options.js +21 -0
  9. package/src/helpers/activity_options.spec.js +55 -0
  10. package/src/helpers/error_serializer.js +236 -0
  11. package/src/helpers/error_serializer.spec.js +413 -0
  12. package/src/helpers/errors.js +23 -14
  13. package/src/helpers/errors.spec.js +31 -75
  14. package/src/helpers/fetch.js +1 -38
  15. package/src/helpers/fetch.spec.js +1 -39
  16. package/src/helpers/function.js +13 -0
  17. package/src/helpers/function.spec.js +23 -1
  18. package/src/helpers/object.js +48 -35
  19. package/src/helpers/object.spec.js +123 -75
  20. package/src/helpers/redact.js +51 -0
  21. package/src/helpers/redact.spec.js +66 -0
  22. package/src/helpers/string.js +10 -0
  23. package/src/helpers/string.spec.js +36 -1
  24. package/src/hooks/index.d.ts +76 -78
  25. package/src/hooks/index.js +57 -49
  26. package/src/hooks/index.spec.js +104 -105
  27. package/src/hooks/pending_hooks.js +24 -0
  28. package/src/hooks/pending_hooks.spec.js +62 -0
  29. package/src/interface/evaluator.d.ts +10 -9
  30. package/src/interface/evaluator.js +1 -6
  31. package/src/interface/evaluator.spec.js +10 -10
  32. package/src/interface/index.js +2 -1
  33. package/src/interface/step.d.ts +16 -15
  34. package/src/interface/step.js +1 -6
  35. package/src/interface/step.spec.js +10 -10
  36. package/src/interface/validations/index.js +33 -53
  37. package/src/interface/validations/index.spec.js +25 -17
  38. package/src/interface/webhook.js +1 -2
  39. package/src/interface/webhook.spec.js +25 -19
  40. package/src/interface/workflow.d.ts +25 -18
  41. package/src/interface/workflow.js +64 -85
  42. package/src/interface/workflow.spec.js +220 -226
  43. package/src/interface/workflow_activity_options.js +2 -5
  44. package/src/interface/workflow_utils.d.ts +15 -0
  45. package/src/interface/workflow_utils.js +19 -0
  46. package/src/interface/workflow_utils.spec.js +82 -1
  47. package/src/sdk/helpers/objects.d.ts +24 -19
  48. package/src/sdk/runtime/events.d.ts +4 -6
  49. package/src/sdk/runtime/events.js +2 -15
  50. package/src/sdk/runtime/events.spec.js +14 -92
  51. package/src/temporal/client.js +47 -0
  52. package/src/temporal/client.spec.js +124 -0
  53. package/src/temporal/index.d.ts +32 -0
  54. package/src/temporal/index.js +1 -0
  55. package/src/tracing/trace_engine.js +9 -11
  56. package/src/tracing/trace_engine.spec.js +67 -28
  57. package/src/worker/catalog_workflow/catalog_job.js +3 -3
  58. package/src/worker/catalog_workflow/catalog_job.spec.js +1 -1
  59. package/src/worker/configs.js +0 -3
  60. package/src/worker/global_functions.js +2 -2
  61. package/src/worker/global_functions.spec.js +3 -3
  62. package/src/worker/index.js +24 -11
  63. package/src/worker/index.spec.js +36 -16
  64. package/src/worker/interceptors/activity.js +34 -21
  65. package/src/worker/interceptors/activity.spec.js +77 -172
  66. package/src/worker/interceptors/workflow.js +58 -16
  67. package/src/worker/interceptors/workflow.spec.js +183 -56
  68. package/src/worker/loader/activities.js +56 -40
  69. package/src/worker/loader/activities.spec.js +21 -22
  70. package/src/worker/loader/workflows.js +16 -3
  71. package/src/worker/loader/workflows.spec.js +36 -5
  72. package/src/worker/log_hooks.js +22 -19
  73. package/src/worker/log_hooks.spec.js +14 -6
  74. package/src/worker/sinks.js +8 -8
  75. package/src/worker/sinks.spec.js +9 -9
  76. package/src/worker/telemetry.js +2 -1
  77. package/src/worker/temporal_logger.js +33 -0
  78. package/src/worker/temporal_logger.spec.js +90 -0
  79. package/src/worker/webpack_loaders/consts.js +6 -0
  80. package/src/worker/webpack_loaders/tools.js +1 -146
  81. package/src/worker/webpack_loaders/tools.spec.js +0 -23
  82. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.js +24 -32
  83. package/src/worker/webpack_loaders/workflow_rewriter/collect_target_imports.spec.js +82 -279
  84. package/src/worker/webpack_loaders/workflow_rewriter/index.mjs +6 -7
  85. package/src/worker/webpack_loaders/workflow_rewriter/index.spec.js +57 -119
  86. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.js +88 -0
  87. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_activity_calls.spec.js +165 -0
  88. package/src/worker/webpack_loaders/workflow_validator/index.mjs +96 -29
  89. package/src/worker/webpack_loaders/workflow_validator/index.spec.js +110 -583
  90. package/src/worker/webpack_loaders/{npm_workflow_export_resolve.js → workflow_validator/npm_workflow_export_resolve.js} +1 -1
  91. package/src/worker/webpack_loaders/{npm_workflow_export_resolve.spec.js → workflow_validator/npm_workflow_export_resolve.spec.js} +1 -1
  92. package/src/helpers/aggregations.js +0 -44
  93. package/src/helpers/aggregations.spec.js +0 -92
  94. package/src/tracing/tools/utils.js +0 -42
  95. package/src/tracing/tools/utils.spec.js +0 -83
  96. package/src/worker/proxy.js +0 -20
  97. package/src/worker/proxy.spec.js +0 -51
  98. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.js +0 -193
  99. package/src/worker/webpack_loaders/workflow_rewriter/rewrite_fn_bodies.spec.js +0 -123
@@ -1,110 +1,89 @@
1
1
  // THIS RUNS IN THE TEMPORAL'S SANDBOX ENVIRONMENT
2
- import { proxyActivities, inWorkflowContext, executeChild, workflowInfo, uuid4, ParentClosePolicy } from '@temporalio/workflow';
2
+ import { proxyActivities, inWorkflowContext, executeChild, workflowInfo, uuid4, ParentClosePolicy, upsertMemo } from '@temporalio/workflow';
3
3
  import { WorkflowValidator } from './validations/index.js';
4
4
  import { toUrlSafeBase64 } from '#helpers/string';
5
5
  import { WorkflowContext } from '#helpers/workflow_context';
6
- import { TraceInfo } from '#helpers/trace_info';
7
6
  import { deepMerge } from '#helpers/object';
8
7
  import { defaultOptions } from './workflow_activity_options.js';
9
8
  import { createWorkflow } from '#helpers/component';
10
- import {
11
- ACTIVITY_GET_TRACE_DESTINATIONS,
12
- METADATA_ACCESS_SYMBOL,
13
- SHARED_STEP_PREFIX,
14
- WORKFLOW_WRAPPER_VERSION_FIELD
15
- } from '#consts';
9
+ import { enforceActivityOptions } from '#helpers/activity_options';
10
+ import { FatalError } from '#errors';
11
+ import * as C from '#consts';
16
12
 
17
13
  /**
18
- * Create a new workflow and return a wrapper function around its fn handler
14
+ * Add a global dispatcher function to be used to invoke activities.
15
+ * This will replace direct activity invocation in the user code by the webpack loader.
16
+ *
17
+ * Important: Keep this as a configurable global assignment (configurable=true, enumerable=true),
18
+ * so Temporal's reusable VM can delete it when switching workflow scopes.
19
19
  */
20
+ const createGlobalDispatcher = ( { runId, workflowType, activities } ) => {
21
+ const dispatcher = async ( activityType, ...args ) => activities[`${workflowType}#${activityType}`]( ...args );
22
+ dispatcher.runId = runId;
23
+ globalThis[C.INVOKE_ACTIVITY_SYMBOL] = dispatcher;
24
+ };
25
+
26
+ /** Validate if the global dispatcher wasn't set by another workflow, indicating global context contamination. */
27
+ const checkGlobalContextContamination = runId => {
28
+ const globalContextRunId = globalThis?.[C.INVOKE_ACTIVITY_SYMBOL]?.runId;
29
+ if ( globalContextRunId && globalContextRunId !== runId ) {
30
+ throw new FatalError( 'Contamination of the workflow Node global context.' +
31
+ ` Var "globalThis[${String( C.INVOKE_ACTIVITY_SYMBOL )}]" was set by another workflow (${globalContextRunId})` );
32
+ }
33
+ };
34
+
35
+ /** Create a new workflow and return a wrapper function around its fn handler */
20
36
  export function workflow( { name, description, inputSchema, outputSchema, fn, options = {}, aliases = [] } ) {
21
37
  WorkflowValidator.validateDefinition( { name, description, inputSchema, outputSchema, fn, options, aliases } );
22
38
 
23
- const { disableTrace, activityOptions } = deepMerge( defaultOptions, options );
24
39
  const validator = new WorkflowValidator( { name, inputSchema, outputSchema } );
25
40
 
26
- return createWorkflow( {
27
- name,
28
- description,
29
- inputSchema,
30
- outputSchema,
31
- options,
32
- aliases,
33
- handler: async ( input, extra = {} ) => {
34
- validator.validateInvocationOptions( extra );
35
-
36
- // this returns a plain function, for example, in unit tests
37
- if ( !inWorkflowContext() ) {
38
- validator.validateInput( input );
39
- const output = await fn( input, deepMerge( WorkflowContext.build(), extra?.context ) );
40
- validator.validateOutput( output );
41
- return output;
42
- }
43
-
44
- const { workflowId, memo, root } = workflowInfo();
41
+ const handler = async ( input, rawInvocationOptions = {} ) => {
42
+ const invocationOptions = validator.parseInvocationOptions( rawInvocationOptions );
45
43
 
46
- // if the stack already includes this workflowId, means the workflow() function was called
47
- // from within a running workflow, meaning it is suppose to start a child workflow
48
- const isChild = Array.isArray( memo.stack ) ? memo.stack.includes( workflowId ) : false;
49
-
50
- if ( isChild ) {
51
- const result = await executeChild( name, {
52
- args: undefined === input ? [] : [ input ],
53
- workflowId: `${workflowId}-${toUrlSafeBase64( uuid4() )}`,
54
- parentClosePolicy: ParentClosePolicy[extra?.detached ? 'ABANDON' : 'TERMINATE'],
55
- memo: {
56
- ...memo, // Preserve memo and mix activityOptions, if provided
57
- ...( extra?.activityOptions && {
58
- activityOptions: deepMerge( memo?.activityOptions ?? {}, extra?.activityOptions )
59
- } )
60
- }
61
- } );
62
- return result.output;
63
- }
44
+ // If called outside Temporal workflow context, just execute the handler function
45
+ if ( !inWorkflowContext() ) {
46
+ return validator.parseOutput(
47
+ await fn( validator.parseInput( input ), deepMerge( WorkflowContext.build(), invocationOptions?.context ) )
48
+ );
49
+ }
64
50
 
65
- const isRoot = !root;
51
+ const { workflowId, runId, memo, root } = workflowInfo();
52
+ const isRoot = !root;
66
53
 
67
- memo.stack = [ ...memo.stack ?? [], workflowId ];
68
- // Parent options have prevalence on nested calls, child will be overwritten
69
- memo.activityOptions = deepMerge( activityOptions, memo.activityOptions );
70
- // Trace info is only added in the root and only when trace is not disabled
71
- if ( isRoot && !disableTrace ) {
72
- memo.traceInfo = TraceInfo.build();
73
- }
54
+ checkGlobalContextContamination( runId );
74
55
 
75
- const steps = proxyActivities( memo.activityOptions );
76
- const traceDestinations = isRoot && {
77
- trace: {
78
- destinations: disableTrace ? {} : ( await steps[ACTIVITY_GET_TRACE_DESTINATIONS]( memo.traceInfo ) ).output ?? {}
79
- }
80
- };
56
+ // If the parent workflow already installed the activity dispatcher, it means that calls to workflow() will trigger child workflows
57
+ const isChildWorkflowCall = !!globalThis[C.INVOKE_ACTIVITY_SYMBOL];
58
+ if ( isChildWorkflowCall ) {
59
+ const parentClosePolicy = ParentClosePolicy[invocationOptions?.detached ? 'ABANDON' : 'TERMINATE'];
60
+ const childWorkflowId = `${workflowId}-${toUrlSafeBase64( uuid4() )}`;
61
+ const args = [ input, { activityOptions: invocationOptions?.activityOptions } ];
62
+ return executeChild( name, { args, workflowId: childWorkflowId, parentClosePolicy, memo } );
63
+ }
81
64
 
82
- try {
83
- validator.validateInput( input );
65
+ // Resolve the activity options: invocation options > definition options > parent options > default options, then enforce final SDK options
66
+ const activityOptions = enforceActivityOptions( deepMerge(
67
+ defaultOptions.activityOptions, // default
68
+ memo?.activityOptions, // parent options
69
+ options?.activityOptions, // definition options
70
+ invocationOptions.activityOptions // invocation options
71
+ ) );
84
72
 
85
- // Creates an activity caller based on a prefix
86
- const createCaller = prefix => async ( t, ...args ) => ( await steps[`${prefix}#${t}`]( ...args ) ).output;
73
+ const activities = proxyActivities( activityOptions );
74
+ createGlobalDispatcher( { runId, workflowType: name, activities } );
87
75
 
88
- // This are functions used by the AST to replace direct activity (step/evaluator) calls
89
- const dispatchers = {
90
- invokeStep: createCaller( name ),
91
- invokeSharedStep: createCaller( SHARED_STEP_PREFIX ),
92
- invokeEvaluator: createCaller( name ),
93
- invokeSharedEvaluator: createCaller( SHARED_STEP_PREFIX )
94
- };
76
+ upsertMemo( {
77
+ activityOptions, // Resolved activity options are added to memo so child workflow executions can continue the policy chain
78
+ ...( isRoot && memo.traceInfo && {
79
+ trace: await activities[C.ACTIVITY_GET_TRACE_DESTINATIONS]( memo.traceInfo )
80
+ } )
81
+ } );
95
82
 
96
- // The workflow function execution with "this" set with the dispatchers
97
- const output = await fn.call( dispatchers, input, WorkflowContext.build() );
98
- validator.validateOutput( output );
83
+ return validator.parseOutput(
84
+ await fn( validator.parseInput( input ), WorkflowContext.build() )
85
+ );
86
+ };
99
87
 
100
- return { [WORKFLOW_WRAPPER_VERSION_FIELD]: 1, output, ...traceDestinations };
101
- } catch ( error ) {
102
- if ( traceDestinations ) {
103
- // Append the trace destinations so it is carried to interceptor
104
- error[METADATA_ACCESS_SYMBOL] = traceDestinations;
105
- }
106
- throw error;
107
- }
108
- }
109
- } );
88
+ return createWorkflow( { name, description, inputSchema, outputSchema, options, aliases, handler } );
110
89
  }