arvo-event-handler 2.3.1 → 3.0.1

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 (78) hide show
  1. package/dist/AbstractArvoEventHandler/index.d.ts +1 -1
  2. package/dist/ArvoEventHandler/helpers.d.ts +40 -6
  3. package/dist/ArvoEventHandler/helpers.js +40 -6
  4. package/dist/ArvoEventHandler/index.d.ts +78 -49
  5. package/dist/ArvoEventHandler/index.js +151 -81
  6. package/dist/ArvoEventHandler/types.d.ts +25 -2
  7. package/dist/ArvoMachine/createMachine.d.ts +208 -0
  8. package/dist/ArvoMachine/createMachine.js +283 -0
  9. package/dist/ArvoMachine/index.d.ts +93 -0
  10. package/dist/ArvoMachine/index.js +160 -0
  11. package/dist/ArvoMachine/types.d.ts +194 -0
  12. package/dist/ArvoMachine/utils.d.ts +40 -0
  13. package/dist/ArvoMachine/utils.js +70 -0
  14. package/dist/ArvoOrchestrator/error.d.ts +16 -0
  15. package/dist/ArvoOrchestrator/error.js +43 -0
  16. package/dist/ArvoOrchestrator/factory.d.ts +28 -0
  17. package/dist/ArvoOrchestrator/factory.js +56 -0
  18. package/dist/ArvoOrchestrator/index.d.ts +69 -0
  19. package/dist/ArvoOrchestrator/index.js +597 -0
  20. package/dist/ArvoOrchestrator/types.d.ts +98 -0
  21. package/dist/ArvoResumable/factory.d.ts +50 -0
  22. package/dist/ArvoResumable/factory.js +70 -0
  23. package/dist/ArvoResumable/index.d.ts +141 -0
  24. package/dist/ArvoResumable/index.js +694 -0
  25. package/dist/ArvoResumable/types.d.ts +147 -0
  26. package/dist/ArvoResumable/types.js +2 -0
  27. package/dist/MachineExecutionEngine/index.d.ts +29 -0
  28. package/dist/MachineExecutionEngine/index.js +132 -0
  29. package/dist/MachineExecutionEngine/interface.d.ts +14 -0
  30. package/dist/MachineExecutionEngine/interface.js +2 -0
  31. package/dist/MachineExecutionEngine/types.d.ts +14 -0
  32. package/dist/MachineExecutionEngine/types.js +2 -0
  33. package/dist/MachineMemory/Simple.d.ts +51 -0
  34. package/dist/MachineMemory/Simple.js +158 -0
  35. package/dist/MachineMemory/TelemetredSimple.d.ts +51 -0
  36. package/dist/MachineMemory/TelemetredSimple.js +230 -0
  37. package/dist/MachineMemory/interface.d.ts +57 -0
  38. package/dist/MachineMemory/interface.js +2 -0
  39. package/dist/MachineMemory/utils.d.ts +1 -0
  40. package/dist/MachineMemory/utils.js +18 -0
  41. package/dist/MachineRegistry/index.d.ts +37 -0
  42. package/dist/MachineRegistry/index.js +87 -0
  43. package/dist/MachineRegistry/interface.d.ts +21 -0
  44. package/dist/MachineRegistry/interface.js +2 -0
  45. package/dist/SyncEventResource/index.d.ts +110 -0
  46. package/dist/SyncEventResource/index.js +280 -0
  47. package/dist/SyncEventResource/types.d.ts +2 -0
  48. package/dist/SyncEventResource/types.js +2 -0
  49. package/dist/index.d.ts +26 -8
  50. package/dist/index.js +39 -16
  51. package/dist/utils/SimpleEventBroker/helper.d.ts +166 -0
  52. package/dist/utils/SimpleEventBroker/helper.js +276 -0
  53. package/dist/utils/SimpleEventBroker/index.d.ts +96 -0
  54. package/dist/utils/SimpleEventBroker/index.js +259 -0
  55. package/dist/utils/SimpleEventBroker/types.d.ts +6 -0
  56. package/dist/utils/SimpleEventBroker/types.js +2 -0
  57. package/dist/utils/SimpleEventBroker/utils.d.ts +1 -0
  58. package/dist/utils/SimpleEventBroker/utils.js +10 -0
  59. package/dist/{utils.d.ts → utils/index.d.ts} +3 -36
  60. package/dist/utils/index.js +91 -0
  61. package/dist/utils/object/index.d.ts +37 -0
  62. package/dist/utils/object/index.js +63 -0
  63. package/package.json +6 -12
  64. package/dist/ArvoEventRouter/helpers.d.ts +0 -19
  65. package/dist/ArvoEventRouter/helpers.js +0 -22
  66. package/dist/ArvoEventRouter/index.d.ts +0 -89
  67. package/dist/ArvoEventRouter/index.js +0 -267
  68. package/dist/ArvoEventRouter/types.d.ts +0 -36
  69. package/dist/ArvoEventRouter/utils.d.ts +0 -29
  70. package/dist/ArvoEventRouter/utils.js +0 -42
  71. package/dist/MultiArvoEventHandler/helpers.d.ts +0 -48
  72. package/dist/MultiArvoEventHandler/helpers.js +0 -56
  73. package/dist/MultiArvoEventHandler/index.d.ts +0 -68
  74. package/dist/MultiArvoEventHandler/index.js +0 -205
  75. package/dist/MultiArvoEventHandler/types.d.ts +0 -64
  76. package/dist/utils.js +0 -190
  77. /package/dist/{ArvoEventRouter → ArvoMachine}/types.js +0 -0
  78. /package/dist/{MultiArvoEventHandler → ArvoOrchestrator}/types.js +0 -0
@@ -1,14 +1,21 @@
1
1
  import type { Span, SpanOptions } from '@opentelemetry/api';
2
- import type { ArvoContract, ArvoEvent, ArvoSemanticVersion, CreateArvoEvent, VersionedArvoContract } from 'arvo-core';
2
+ import type { ArvoContract, ArvoEvent, ArvoSemanticVersion, CreateArvoEvent, InferArvoEvent, VersionedArvoContract } from 'arvo-core';
3
3
  import type { z } from 'zod';
4
4
  /**
5
5
  * Represents the input for an ArvoEvent handler function.
6
6
  */
7
7
  export type ArvoEventHandlerFunctionInput<TContract extends VersionedArvoContract<any, any>> = {
8
8
  /** The ArvoEvent object. */
9
- event: ArvoEvent<z.infer<TContract['accepts']['schema']>, Record<string, any>, TContract['accepts']['type']>;
9
+ event: InferArvoEvent<ArvoEvent<z.infer<TContract['accepts']['schema']>, Record<string, any>, TContract['accepts']['type']>>;
10
10
  /** The source field data of the handler */
11
11
  source: string;
12
+ /** The domain information for handling the event */
13
+ domain: {
14
+ self: string | null;
15
+ event: string | null;
16
+ };
17
+ /** The contract used in the processing */
18
+ contract: TContract;
12
19
  /** The OpenTelemetry span */
13
20
  span: Span;
14
21
  };
@@ -27,6 +34,22 @@ export type ArvoEventHandlerFunctionOutput<TContract extends VersionedArvoContra
27
34
  executionunits?: number;
28
35
  /** Optional extensions for the event. */
29
36
  __extensions?: Record<string, string | number | boolean>;
37
+ /**
38
+ * The event domain configuration for multi-domain broadcasting.
39
+ *
40
+ * **Domain Broadcasting Rules:**
41
+ * - Each element in the array creates a separate ArvoEvent instance
42
+ * - `undefined` elements resolve using inheritance: `event.domain ?? contract.domain ?? null`
43
+ * - Duplicate domains are automatically removed to prevent redundant events
44
+ * - Omitting this field (or setting to `undefined`) defaults to `[null]`
45
+ *
46
+ * **Domain Broadcasting Patterns:**
47
+ * - `['domain1', 'domain2']` → Creates 2 events for different processing contexts
48
+ * - `['analytics', undefined, 'audit']` → Creates events for analytics, inherited context, and audit
49
+ * - `[null]` → Creates single event with no domain routing (standard processing)
50
+ * - `undefined` (or omitted) → Creates single event with `domain: null`
51
+ */
52
+ domain?: (string | undefined | null)[];
30
53
  };
31
54
  }[keyof TContract['emits']];
32
55
  /**
@@ -0,0 +1,208 @@
1
+ import { type ArvoOrchestratorEventTypeGen, type InferVersionedArvoContract, type VersionedArvoContract } from 'arvo-core';
2
+ import { type ActionFunction, type MachineConfig, type MachineContext, type MetaObject, type ParameterizedObject, type SetupTypes } from 'xstate';
3
+ import type { z } from 'zod';
4
+ import ArvoMachine from '.';
5
+ import type { EnqueueArvoEventActionParam, ExtractOrchestratorType, InferServiceContract, ToParameterizedObject, ToProvidedActor } from './types';
6
+ /**
7
+ * Establishes the foundation for creating Arvo-compatible state machines.
8
+ *
9
+ * This function configures the core elements of an Arvo state machine, including
10
+ * built-in actions like `enqueueArvoEvent`, and enforces Arvo-specific constraints
11
+ * to ensure compatibility with the Arvo event-driven system.
12
+ *
13
+ * @param param - Configuration object for the machine setup
14
+ * @returns An object containing the `createMachine` function
15
+ * @throws {Error} If 'actors', 'delays', or reserved action names are used in the configuration
16
+ *
17
+ * @description
18
+ * `setupArvoMachine` is a crucial function in the Arvo ecosystem, designed to create
19
+ * synchronous state machine orchestrations for Arvo's event-driven architecture.
20
+ * It builds upon XState, providing a tailored implementation that:
21
+ *
22
+ * 1. Enforces synchronous behavior to maintain predictable state transitions
23
+ * 3. Implements Arvo-specific constraints and features
24
+ *
25
+ * Key features:
26
+ * - Synchronous execution: Ensures deterministic behavior in event-driven systems
27
+ * - Built-in actions: Includes `enqueueArvoEvent` for Arvo event handling
28
+ * - Constraint checking: Prevents usage of asynchronous features like 'actors' or 'delays'
29
+ *
30
+ * @remarks
31
+ * While `setupArvoMachine` is based on XState's `setup` and `createMachine` functions,
32
+ * it includes Arvo-specific modifications and restrictions. For a deeper understanding
33
+ * of the underlying XState concepts, refer to the official XState documentation:
34
+ * - XState setup: https://stately.ai/docs/setup
35
+ * - XState createMachine: https://stately.ai/docs/machines
36
+ *
37
+ * @example
38
+ * Here's a comprehensive example demonstrating how to use `setupArvoMachine`:
39
+ *
40
+ * ```typescript
41
+ * import { setupArvoMachine } from 'arvo-xstate'
42
+ * import { createArvoOrchestratorContract, ArvoErrorSchema, createArvoContract } from 'arvo-core'
43
+ * import { z } from 'zod'
44
+ *
45
+ * // Define the LLM orchestrator contract
46
+ * const llmContract = createArvoOrchestratorContract({
47
+ * uri: `#/orchestrators/llm/`,
48
+ * type: 'llm',
49
+ * versions: {
50
+ * '0.0.1': {
51
+ * init: z.object({
52
+ * request: z.string(),
53
+ * llm: z.enum(['gpt-4', 'gpt-4o']),
54
+ * }),
55
+ * complete: z.object({
56
+ * response: z.string(),
57
+ * })
58
+ * }
59
+ * }
60
+ * })
61
+ *
62
+ * // Define the OpenAI service contract
63
+ * const openAiContract = createArvoContract({
64
+ * uri: `#/services/openai`,
65
+ * type: 'com.openai.completions',
66
+ * versions: {
67
+ * '0.0.1': {
68
+ * accepts: z.object({
69
+ * request: z.string()
70
+ * }),
71
+ * emits: {
72
+ * 'evt.openai.completions.success': z.object({
73
+ * response: z.string(),
74
+ * })
75
+ * }
76
+ * }
77
+ * }
78
+ * })
79
+ *
80
+ * const machineId = 'machineV100'
81
+ *
82
+ * // Set up the Arvo machine
83
+ * const llmMachine = setupArvoMachine({
84
+ * contracts: {
85
+ * self: llmContract.version('0.0.1'),
86
+ * services: {
87
+ * openAiContract.version('0.0.1'),
88
+ * }
89
+ * },
90
+ * types: {
91
+ * context: {} as {
92
+ * request: string,
93
+ * llm: string,
94
+ * response: string | null,
95
+ * errors: z.infer<typeof ArvoErrorSchema>[]
96
+ * },
97
+ * tags: {} as 'pending' | 'success' | 'error',
98
+ * },
99
+ * actions: {
100
+ * log: ({context, event}) => console.log({context, event})
101
+ * },
102
+ * guards: {
103
+ * isValid: ({context, event}) => Boolean(context.request)
104
+ * }
105
+ * }).createMachine({
106
+ * id: machineId,
107
+ * context: ({input}) => ({
108
+ * request: input.request,
109
+ * llm: input.llm,
110
+ * response: null,
111
+ * errors: [],
112
+ * }),
113
+ * initial: 'validate',
114
+ * states: {
115
+ * validate: {
116
+ * always: [
117
+ * {
118
+ * guard: 'isValid',
119
+ * target: 'llm',
120
+ * },
121
+ * {
122
+ * target: 'error',
123
+ * }
124
+ * ]
125
+ * },
126
+ * llm: {
127
+ * entry: [
128
+ * {
129
+ * type: 'log',
130
+ * },
131
+ * emit(({context}) => ({
132
+ * type: 'com.openai.completions',
133
+ * data: {
134
+ * request: context.request,
135
+ * },
136
+ * }))
137
+ * ],
138
+ * on: {
139
+ * 'evt.openai.completions.success': {
140
+ * actions: [
141
+ * assign({response: ({event}) => event.response})
142
+ * ],
143
+ * target: 'done'
144
+ * },
145
+ * 'sys.com.openai.completions.error': {
146
+ * actions: [
147
+ * assign({errors: ({context, event}) => [...context.errors, event.body]})
148
+ * ],
149
+ * target: 'error'
150
+ * }
151
+ * }
152
+ * },
153
+ * done: {
154
+ * type: 'final'
155
+ * },
156
+ * error: {
157
+ * type: 'final'
158
+ * },
159
+ * }
160
+ * });
161
+ * ```
162
+ *
163
+ * This example demonstrates:
164
+ * 1. Defining Arvo contracts for the orchestrator and a service
165
+ * 2. Setting up an Arvo machine with contracts, types, actions, and guards
166
+ * 3. Creating a machine with states for validation, LLM interaction, and error handling
167
+ * 4. Using XState features like `emit` bound with Arvo contracts for event emitting and event handling via transitions
168
+ */
169
+ export declare function setupArvoMachine<TContext extends MachineContext, TSelfContract extends VersionedArvoContract<any, any>, TServiceContracts extends Record<string, VersionedArvoContract<any, any>>, TActions extends Record<string, ParameterizedObject['params'] | undefined> = {}, TGuards extends Record<string, ParameterizedObject['params'] | undefined> = {}, TTag extends string = string, TMeta extends MetaObject = MetaObject>(param: {
170
+ schemas?: unknown;
171
+ contracts: {
172
+ self: TSelfContract;
173
+ services: TServiceContracts;
174
+ };
175
+ types?: Omit<SetupTypes<TContext, InferServiceContract<TServiceContracts>['events'], {}, TTag, InferVersionedArvoContract<TSelfContract>['accepts']['data'], InferVersionedArvoContract<TSelfContract>['emits'][ReturnType<typeof ArvoOrchestratorEventTypeGen.complete<ExtractOrchestratorType<TSelfContract['accepts']['type']>>>]['data'], InferServiceContract<TServiceContracts>['emitted'], TMeta>, 'input' | 'output' | 'children' | 'emitted'>;
176
+ actions?: {
177
+ [K in keyof TActions]: ActionFunction<TContext, InferServiceContract<TServiceContracts>['events'], InferServiceContract<TServiceContracts>['events'], TActions[K], never, ToParameterizedObject<TActions>, ToParameterizedObject<TGuards>, never, InferServiceContract<TServiceContracts>['emitted']>;
178
+ };
179
+ guards?: {
180
+ [K in keyof TGuards]: (args: {
181
+ context: TContext;
182
+ event: InferServiceContract<TServiceContracts>['events'];
183
+ }, params: TGuards[K]) => boolean;
184
+ };
185
+ }): {
186
+ createMachine: <const TConfig extends MachineConfig<TContext, InferServiceContract<TServiceContracts>["events"], ToProvidedActor<{}, {}>, ToParameterizedObject<TActions & {
187
+ enqueueArvoEvent: EnqueueArvoEventActionParam;
188
+ }>, ToParameterizedObject<TGuards>, never, TTag, InferVersionedArvoContract<TSelfContract>["accepts"], z.input<TSelfContract["emits"][ReturnType<typeof ArvoOrchestratorEventTypeGen.complete<ExtractOrchestratorType<TSelfContract["accepts"]["type"]>>>]>, InferServiceContract<TServiceContracts>["emitted"], TMeta>>(config: TConfig & {
189
+ id: string;
190
+ version?: TSelfContract["version"];
191
+ }) => ArvoMachine<string, TSelfContract["version"], TSelfContract, TServiceContracts, import("xstate").StateMachine<TContext, { [K in keyof TServiceContracts]: import("./types").InferEmittableEventsFromVersionedArvoContract<TServiceContracts[K]>; }[keyof TServiceContracts], {}, never, import("xstate").IsNever<TActions & {
192
+ enqueueArvoEvent: EnqueueArvoEventActionParam;
193
+ }> extends true ? never : import("xstate").Values<{ [K_1 in (keyof TActions & string) | "enqueueArvoEvent"]: {
194
+ type: K_1;
195
+ params: (TActions & {
196
+ enqueueArvoEvent: EnqueueArvoEventActionParam;
197
+ })[K_1];
198
+ }; }>, import("xstate").IsNever<TGuards> extends true ? never : import("xstate").Values<{ [K_2 in keyof TGuards & string]: {
199
+ type: K_2;
200
+ params: TGuards[K_2];
201
+ }; }>, never, {} | {
202
+ [x: string]: {} | any | {
203
+ [x: string]: {} | any | any;
204
+ };
205
+ } | {
206
+ [x: string]: {} | any | any;
207
+ }, TTag, TSelfContract["accepts"]["schema"]["_output"], { [K_3 in string & keyof TSelfContract["emits"]]: import("arvo-core").InferArvoEvent<import("arvo-core").ArvoEvent<TSelfContract["emits"][K_3]["_output"], Record<string, any>, K_3>>; }[`arvo.orc.${ExtractOrchestratorType<TSelfContract["accepts"]["type"]>}.done`]["data"], { [K_4 in keyof TServiceContracts]: EnqueueArvoEventActionParam<z.input<TServiceContracts[K_4]["accepts"]["schema"]>, TServiceContracts[K_4]["accepts"]["type"], Record<string, string | number | boolean | null>>; }[keyof TServiceContracts], TMeta, any>>;
208
+ };
@@ -0,0 +1,283 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
14
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
15
+ if (ar || !(i in from)) {
16
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
17
+ ar[i] = from[i];
18
+ }
19
+ }
20
+ return to.concat(ar || Array.prototype.slice.call(from));
21
+ };
22
+ var __importDefault = (this && this.__importDefault) || function (mod) {
23
+ return (mod && mod.__esModule) ? mod : { "default": mod };
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.setupArvoMachine = setupArvoMachine;
27
+ var arvo_core_1 = require("arvo-core");
28
+ var xstate_1 = require("xstate");
29
+ var _1 = __importDefault(require("."));
30
+ var object_1 = require("../utils/object");
31
+ var utils_1 = require("./utils");
32
+ var uuid_1 = require("uuid");
33
+ /**
34
+ * Establishes the foundation for creating Arvo-compatible state machines.
35
+ *
36
+ * This function configures the core elements of an Arvo state machine, including
37
+ * built-in actions like `enqueueArvoEvent`, and enforces Arvo-specific constraints
38
+ * to ensure compatibility with the Arvo event-driven system.
39
+ *
40
+ * @param param - Configuration object for the machine setup
41
+ * @returns An object containing the `createMachine` function
42
+ * @throws {Error} If 'actors', 'delays', or reserved action names are used in the configuration
43
+ *
44
+ * @description
45
+ * `setupArvoMachine` is a crucial function in the Arvo ecosystem, designed to create
46
+ * synchronous state machine orchestrations for Arvo's event-driven architecture.
47
+ * It builds upon XState, providing a tailored implementation that:
48
+ *
49
+ * 1. Enforces synchronous behavior to maintain predictable state transitions
50
+ * 3. Implements Arvo-specific constraints and features
51
+ *
52
+ * Key features:
53
+ * - Synchronous execution: Ensures deterministic behavior in event-driven systems
54
+ * - Built-in actions: Includes `enqueueArvoEvent` for Arvo event handling
55
+ * - Constraint checking: Prevents usage of asynchronous features like 'actors' or 'delays'
56
+ *
57
+ * @remarks
58
+ * While `setupArvoMachine` is based on XState's `setup` and `createMachine` functions,
59
+ * it includes Arvo-specific modifications and restrictions. For a deeper understanding
60
+ * of the underlying XState concepts, refer to the official XState documentation:
61
+ * - XState setup: https://stately.ai/docs/setup
62
+ * - XState createMachine: https://stately.ai/docs/machines
63
+ *
64
+ * @example
65
+ * Here's a comprehensive example demonstrating how to use `setupArvoMachine`:
66
+ *
67
+ * ```typescript
68
+ * import { setupArvoMachine } from 'arvo-xstate'
69
+ * import { createArvoOrchestratorContract, ArvoErrorSchema, createArvoContract } from 'arvo-core'
70
+ * import { z } from 'zod'
71
+ *
72
+ * // Define the LLM orchestrator contract
73
+ * const llmContract = createArvoOrchestratorContract({
74
+ * uri: `#/orchestrators/llm/`,
75
+ * type: 'llm',
76
+ * versions: {
77
+ * '0.0.1': {
78
+ * init: z.object({
79
+ * request: z.string(),
80
+ * llm: z.enum(['gpt-4', 'gpt-4o']),
81
+ * }),
82
+ * complete: z.object({
83
+ * response: z.string(),
84
+ * })
85
+ * }
86
+ * }
87
+ * })
88
+ *
89
+ * // Define the OpenAI service contract
90
+ * const openAiContract = createArvoContract({
91
+ * uri: `#/services/openai`,
92
+ * type: 'com.openai.completions',
93
+ * versions: {
94
+ * '0.0.1': {
95
+ * accepts: z.object({
96
+ * request: z.string()
97
+ * }),
98
+ * emits: {
99
+ * 'evt.openai.completions.success': z.object({
100
+ * response: z.string(),
101
+ * })
102
+ * }
103
+ * }
104
+ * }
105
+ * })
106
+ *
107
+ * const machineId = 'machineV100'
108
+ *
109
+ * // Set up the Arvo machine
110
+ * const llmMachine = setupArvoMachine({
111
+ * contracts: {
112
+ * self: llmContract.version('0.0.1'),
113
+ * services: {
114
+ * openAiContract.version('0.0.1'),
115
+ * }
116
+ * },
117
+ * types: {
118
+ * context: {} as {
119
+ * request: string,
120
+ * llm: string,
121
+ * response: string | null,
122
+ * errors: z.infer<typeof ArvoErrorSchema>[]
123
+ * },
124
+ * tags: {} as 'pending' | 'success' | 'error',
125
+ * },
126
+ * actions: {
127
+ * log: ({context, event}) => console.log({context, event})
128
+ * },
129
+ * guards: {
130
+ * isValid: ({context, event}) => Boolean(context.request)
131
+ * }
132
+ * }).createMachine({
133
+ * id: machineId,
134
+ * context: ({input}) => ({
135
+ * request: input.request,
136
+ * llm: input.llm,
137
+ * response: null,
138
+ * errors: [],
139
+ * }),
140
+ * initial: 'validate',
141
+ * states: {
142
+ * validate: {
143
+ * always: [
144
+ * {
145
+ * guard: 'isValid',
146
+ * target: 'llm',
147
+ * },
148
+ * {
149
+ * target: 'error',
150
+ * }
151
+ * ]
152
+ * },
153
+ * llm: {
154
+ * entry: [
155
+ * {
156
+ * type: 'log',
157
+ * },
158
+ * emit(({context}) => ({
159
+ * type: 'com.openai.completions',
160
+ * data: {
161
+ * request: context.request,
162
+ * },
163
+ * }))
164
+ * ],
165
+ * on: {
166
+ * 'evt.openai.completions.success': {
167
+ * actions: [
168
+ * assign({response: ({event}) => event.response})
169
+ * ],
170
+ * target: 'done'
171
+ * },
172
+ * 'sys.com.openai.completions.error': {
173
+ * actions: [
174
+ * assign({errors: ({context, event}) => [...context.errors, event.body]})
175
+ * ],
176
+ * target: 'error'
177
+ * }
178
+ * }
179
+ * },
180
+ * done: {
181
+ * type: 'final'
182
+ * },
183
+ * error: {
184
+ * type: 'final'
185
+ * },
186
+ * }
187
+ * });
188
+ * ```
189
+ *
190
+ * This example demonstrates:
191
+ * 1. Defining Arvo contracts for the orchestrator and a service
192
+ * 2. Setting up an Arvo machine with contracts, types, actions, and guards
193
+ * 3. Creating a machine with states for validation, LLM interaction, and error handling
194
+ * 4. Using XState features like `emit` bound with Arvo contracts for event emitting and event handling via transitions
195
+ */
196
+ function setupArvoMachine(param) {
197
+ var _a;
198
+ var _b, _c;
199
+ var createConfigErrorMessage = function (type) {
200
+ return (0, arvo_core_1.cleanString)("\n Configuration Error: '".concat(type, "' not supported in Arvo machines\n \n Arvo machines do not support XState ").concat(type === 'actor' ? 'actors' : 'delay transitions', " as they introduce asynchronous behavior.\n \n To fix:\n 1. Remove the '").concat(type, "' configuration\n 2. Use Arvo's event-driven patterns instead for asynchronous operations\n "));
201
+ };
202
+ if (param.actors) {
203
+ throw new Error(createConfigErrorMessage('actor'));
204
+ }
205
+ if (param.delays) {
206
+ throw new Error(createConfigErrorMessage('delays'));
207
+ }
208
+ if ((_b = param.actions) === null || _b === void 0 ? void 0 : _b.enqueueArvoEvent) {
209
+ throw new Error((0, arvo_core_1.cleanString)("\n Configuration Error: Reserved action name 'enqueueArvoEvent'\n \n 'enqueueArvoEvent' is an internal Arvo system action and cannot be overridden.\n \n To fix: Use a different name for your action, such as:\n - 'queueCustomEvent'\n - 'scheduleEvent'\n - 'dispatchEvent'\n "));
210
+ }
211
+ var __areServiceContractsUnique = (0, utils_1.areServiceContractsUnique)(param.contracts.services);
212
+ if (!__areServiceContractsUnique.result) {
213
+ throw new Error("The service contracts must have unique URIs. Multiple versions of the same contract are not allow. The contracts '".concat(__areServiceContractsUnique.keys[0], "' and '").concat(__areServiceContractsUnique.keys[1], "' have the same URI '").concat(__areServiceContractsUnique.contractUri, "'"));
214
+ }
215
+ var __checkIfSelfIsAService = (0, utils_1.areServiceContractsUnique)(__assign(__assign({}, param.contracts.services), (_a = {}, _a[(0, uuid_1.v4)()] = param.contracts.self, _a)));
216
+ if (!__checkIfSelfIsAService.result) {
217
+ throw new Error("Circular dependency detected: Machine with URI '".concat(param.contracts.self.uri, "' is registered as service '").concat(__checkIfSelfIsAService.keys[1], "'. Self-referential services create execution loops and are prohibited."));
218
+ }
219
+ var combinedActions = __assign(__assign({}, ((_c = param.actions) !== null && _c !== void 0 ? _c : {})), { enqueueArvoEvent: (0, xstate_1.assign)(function (_a, param) {
220
+ var _b, _c, _d, _e, _f;
221
+ var context = _a.context;
222
+ return (__assign(__assign({}, (context !== null && context !== void 0 ? context : {})), { arvo$$: __assign(__assign({}, ((_b = context === null || context === void 0 ? void 0 : context.arvo$$) !== null && _b !== void 0 ? _b : {})), { volatile$$: __assign(__assign({}, ((_d = (_c = context === null || context === void 0 ? void 0 : context.arvo$$) === null || _c === void 0 ? void 0 : _c.volatile$$) !== null && _d !== void 0 ? _d : {})), { eventQueue$$: __spreadArray(__spreadArray([], (((_f = (_e = context === null || context === void 0 ? void 0 : context.arvo$$) === null || _e === void 0 ? void 0 : _e.volatile$$) === null || _f === void 0 ? void 0 : _f.eventQueue$$) || []), true), [param], false) }) }) }));
223
+ }) });
224
+ // Call the original setup function with modified parameters
225
+ var systemSetup = (0, xstate_1.setup)({
226
+ schemas: param.schemas,
227
+ types: param.types,
228
+ guards: param.guards,
229
+ actions: combinedActions,
230
+ });
231
+ /**
232
+ * Creates an Arvo-compatible XState machine.
233
+ *
234
+ * @param config - The configuration object for the machine
235
+ * @returns An ArvoMachine instance
236
+ *
237
+ * @throws Error if 'invoke' or 'after' configurations are used
238
+ *
239
+ * @remarks
240
+ * This function creates a state machine based on the provided configuration.
241
+ * It performs additional checks to ensure the machine adheres to Arvo's constraints,
242
+ * such as disallowing 'invoke' and 'after' configurations which could introduce
243
+ * asynchronous behavior.
244
+ * ```
245
+ */
246
+ var createMachine = function (config) {
247
+ var _a, _b;
248
+ var machineVersion = (_a = config.version) !== null && _a !== void 0 ? _a : param.contracts.self.version;
249
+ if (machineVersion !== param.contracts.self.version) {
250
+ throw new Error("Version mismatch: Machine version must be '".concat(param.contracts.self.version, "' or undefined, received '").concat(config.version, "'"));
251
+ }
252
+ var createConfigErrorMessage = function (type, path) {
253
+ var location = path.join(' > ');
254
+ if (type === 'invoke') {
255
+ return (0, arvo_core_1.cleanString)("\n Configuration Error: 'invoke' not supported\n \n Location: ".concat(location, "\n \n Arvo machines do not support XState invocations as they introduce asynchronous behavior.\n \n To fix: Replace 'invoke' with Arvo event-driven patterns for asynchronous operations\n "));
256
+ }
257
+ if (type === 'after') {
258
+ return (0, arvo_core_1.cleanString)("\n Configuration Error: 'after' not supported\n \n Location: ".concat(location, "\n \n Arvo machines do not support delayed transitions as they introduce asynchronous behavior.\n \n To fix: Replace 'after' with Arvo event-driven patterns for time-based operations\n "));
259
+ }
260
+ if (type === 'enqueueArvoEvent') {
261
+ return (0, arvo_core_1.cleanString)("\n Configuration Error: Reserved action name 'enqueueArvoEvent'\n \n Location: ".concat(location, "\n \n 'enqueueArvoEvent' is an internal Arvo system action and cannot be used in machine configurations.\n \n To fix: Use a different name for your action\n "));
262
+ }
263
+ };
264
+ for (var _i = 0, _c = (0, object_1.getAllPaths)((_b = config.states) !== null && _b !== void 0 ? _b : {}); _i < _c.length; _i++) {
265
+ var item = _c[_i];
266
+ if (item.path.includes('invoke')) {
267
+ throw new Error(createConfigErrorMessage('invoke', item.path));
268
+ }
269
+ if (item.path.includes('after')) {
270
+ throw new Error(createConfigErrorMessage('after', item.path));
271
+ }
272
+ if (item.path.includes('enqueueArvoEvent')) {
273
+ throw new Error(createConfigErrorMessage('enqueueArvoEvent', item.path));
274
+ }
275
+ }
276
+ var machine = systemSetup.createMachine(__assign({}, config));
277
+ var hasParallelStates = (0, utils_1.detectParallelStates)(machine.config);
278
+ var hasMultipleNonSystemErrorEvents = Object.values(param.contracts.services).some(function (item) { return Object.keys(item.emits).length > 1; });
279
+ var requiresLocking = hasParallelStates || hasMultipleNonSystemErrorEvents;
280
+ return new _1.default(config.id, machineVersion, param.contracts, machine, requiresLocking);
281
+ };
282
+ return { createMachine: createMachine };
283
+ }
@@ -0,0 +1,93 @@
1
+ import { type ArvoContract, type ArvoEvent, type ArvoOrchestratorContract, type ArvoSemanticVersion, type VersionedArvoContract } from 'arvo-core';
2
+ import type { AnyActorLogic } from 'xstate';
3
+ import type { z } from 'zod';
4
+ /**
5
+ * Represents an ArvoMachine object that can be consumed by an Arvo orchestrator.
6
+ * ArvoMachine encapsulates the logic and metadata required for an Arvo-compatible
7
+ * state machine. It combines XState's actor logic with Arvo-specific contracts
8
+ * and versioning information.
9
+ *
10
+ * @remarks
11
+ * It is strongly recommended to use `setupArvoMachine(...).createMachine(...)`
12
+ * instead of creating this object directly. The setup function provides additional
13
+ * type safety and validation that helps prevent runtime errors.
14
+ */
15
+ export default class ArvoMachine<TId extends string, TVersion extends ArvoSemanticVersion, TSelfContract extends VersionedArvoContract<ArvoOrchestratorContract, TVersion>, TServiceContract extends Record<string, VersionedArvoContract<ArvoContract, ArvoSemanticVersion>>, TLogic extends AnyActorLogic> {
16
+ readonly id: TId;
17
+ readonly version: TVersion;
18
+ readonly contracts: {
19
+ self: TSelfContract;
20
+ services: TServiceContract;
21
+ };
22
+ readonly logic: TLogic;
23
+ readonly requiresResourceLocking: boolean;
24
+ /**
25
+ * Creates a new ArvoMachine instance.
26
+ *
27
+ * @param id - A unique identifier for the machine. This ID must be unique within
28
+ * the scope of an orchestrator and is used for routing and logging.
29
+ *
30
+ * @param version - The semantic version of the machine. Must follow semver format
31
+ * and match the version specified in the contract.
32
+ *
33
+ * @param contracts - Configuration object containing contract definitions
34
+ * @param contracts.self - The contract defining this machine's interface and capabilities
35
+ * @param contracts.services - Record of contracts for services this machine can interact with
36
+ *
37
+ * @param logic - The XState actor logic that defines the machine's behavior,
38
+ * including states, transitions, and actions.
39
+ * @param [requiresResourceLocking] - Optional flag indicating if the machine needs distributed locks.
40
+ * False when machine has no parallel states and executes sequentially.
41
+ * Defaults to true.
42
+ *
43
+ * @throws {Error} When contracts are invalid or incompatible with the specified version
44
+ */
45
+ constructor(id: TId, version: TVersion, contracts: {
46
+ self: TSelfContract;
47
+ services: TServiceContract;
48
+ }, logic: TLogic, requiresResourceLocking?: boolean);
49
+ /**
50
+ * Gets the event type that this machine accepts, as defined in its contract.
51
+ */
52
+ get source(): TSelfContract['accepts']['type'];
53
+ /**
54
+ * Validates an event against the machine's contracts and data schemas.
55
+ * Performs validation for both self-contract events and service contract events.
56
+ *
57
+ * @param event - The event to validate
58
+ * @returns A validation result object:
59
+ * - "VALID" - Event is valid and can be processed
60
+ * - "CONTRACT_UNRESOLVED" - No matching contract found for the event
61
+ * - "INVALID" - Event dataschema conflict with contract
62
+ * - "INVALID_DATA" - Event data conflicts with contract
63
+ *
64
+ * @example
65
+ * ```typescript
66
+ * const result = machine.validateInput(event);
67
+ * if (result.type === "VALID") {
68
+ * // Process the event
69
+ * } else if (result.type === "INVALID") {
70
+ * console.error(result.error);
71
+ * } else {
72
+ * // Handle unresolved contract
73
+ * }
74
+ * ```
75
+ *
76
+ * @remarks
77
+ * The validation process includes:
78
+ * - Finding a matching contract (self or service)
79
+ * - Validating dataschema URI and version if present
80
+ * - Validating event data against the contract schema
81
+ */
82
+ validateInput(event: ArvoEvent): {
83
+ type: 'VALID';
84
+ } | {
85
+ type: 'CONTRACT_UNRESOLVED';
86
+ } | {
87
+ type: 'INVALID';
88
+ error: Error;
89
+ } | {
90
+ type: 'INVALID_DATA';
91
+ error: z.ZodError;
92
+ };
93
+ }