@mmapp/react 0.1.0-alpha.1 → 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +112 -0
- package/dist/index.d.mts +27 -2
- package/dist/index.d.ts +27 -2
- package/dist/index.js +70 -3
- package/dist/index.mjs +74 -12
- package/package.json +4 -3
- package/package.json.backup +0 -41
- package/src/Blueprint.ts +0 -216
- package/src/__tests__/Blueprint.test.ts +0 -106
- package/src/__tests__/action-context.test.ts +0 -166
- package/src/__tests__/actionCreators.test.ts +0 -179
- package/src/__tests__/builders.test.ts +0 -336
- package/src/__tests__/defineBlueprint-composition.test.ts +0 -106
- package/src/__tests__/factories.test.ts +0 -229
- package/src/__tests__/loader.test.ts +0 -159
- package/src/__tests__/logger.test.ts +0 -70
- package/src/__tests__/type-inference.test.ts +0 -160
- package/src/__tests__/typed-transitions.test.ts +0 -126
- package/src/__tests__/useModuleConfig.test.ts +0 -61
- package/src/actionCreators.ts +0 -132
- package/src/actions.ts +0 -547
- package/src/atoms/index.ts +0 -600
- package/src/authoring.ts +0 -92
- package/src/browser-player.ts +0 -783
- package/src/builders.ts +0 -1342
- package/src/components/ExperienceWorkflowBridge.tsx +0 -123
- package/src/components/PlayerProvider.tsx +0 -43
- package/src/components/atoms/index.tsx +0 -269
- package/src/components/index.ts +0 -36
- package/src/conditions.ts +0 -692
- package/src/config/defineBlueprint.ts +0 -329
- package/src/config/defineModel.ts +0 -753
- package/src/config/defineWorkspace.ts +0 -24
- package/src/core/WorkflowRuntime.ts +0 -153
- package/src/factories.ts +0 -425
- package/src/grammar/index.ts +0 -173
- package/src/hooks/index.ts +0 -106
- package/src/hooks/useAuth.ts +0 -288
- package/src/hooks/useChannel.ts +0 -304
- package/src/hooks/useComputed.ts +0 -154
- package/src/hooks/useDomainSubscription.ts +0 -110
- package/src/hooks/useDuringAction.ts +0 -99
- package/src/hooks/useExperienceState.ts +0 -59
- package/src/hooks/useExpressionLibrary.ts +0 -129
- package/src/hooks/useForm.ts +0 -352
- package/src/hooks/useGeolocation.ts +0 -207
- package/src/hooks/useMapView.ts +0 -259
- package/src/hooks/useMiddleware.ts +0 -291
- package/src/hooks/useModel.ts +0 -363
- package/src/hooks/useModule.ts +0 -59
- package/src/hooks/useModuleConfig.ts +0 -61
- package/src/hooks/useMutation.ts +0 -237
- package/src/hooks/useNotification.ts +0 -151
- package/src/hooks/useOnChange.ts +0 -30
- package/src/hooks/useOnEnter.ts +0 -59
- package/src/hooks/useOnEvent.ts +0 -37
- package/src/hooks/useOnExit.ts +0 -27
- package/src/hooks/useOnTransition.ts +0 -30
- package/src/hooks/usePackage.ts +0 -128
- package/src/hooks/useParams.ts +0 -33
- package/src/hooks/usePlayer.ts +0 -308
- package/src/hooks/useQuery.ts +0 -184
- package/src/hooks/useRealtimeQuery.ts +0 -222
- package/src/hooks/useRole.ts +0 -191
- package/src/hooks/useRouteParams.ts +0 -100
- package/src/hooks/useRouter.ts +0 -347
- package/src/hooks/useServerAction.ts +0 -178
- package/src/hooks/useServerState.ts +0 -284
- package/src/hooks/useToast.ts +0 -164
- package/src/hooks/useTransition.ts +0 -39
- package/src/hooks/useView.ts +0 -102
- package/src/hooks/useWhileIn.ts +0 -48
- package/src/hooks/useWorkflow.ts +0 -63
- package/src/index.ts +0 -465
- package/src/loader/experience-workflow-loader.ts +0 -192
- package/src/loader/index.ts +0 -6
- package/src/local/LocalEngine.ts +0 -388
- package/src/local/LocalEngineAdapter.ts +0 -175
- package/src/local/LocalEngineContext.ts +0 -30
- package/src/logger.ts +0 -37
- package/src/mixins.ts +0 -1160
- package/src/providers/RuntimeContext.ts +0 -20
- package/src/providers/WorkflowProvider.tsx +0 -28
- package/src/routing/instance-key.ts +0 -107
- package/src/server/transition-context.ts +0 -172
- package/src/testing/index.ts +0 -9
- package/src/testing/useBlueprintTestRunner.ts +0 -91
- package/src/testing/useGraphAnalysis.ts +0 -18
- package/src/testing/useTestRunner.ts +0 -77
- package/src/testing.ts +0 -995
- package/src/types/workflow-inference.ts +0 -158
- package/src/types.ts +0 -114
- package/tsconfig.json +0 -27
- package/vitest.config.ts +0 -8
package/src/actionCreators.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @mindmatrix/react/actionCreators — Type-safe action reference factories.
|
|
3
|
-
*
|
|
4
|
-
* Replaces stringly-typed `serverAction("authenticate", {...})` calls with
|
|
5
|
-
* typed action creators that catch typos at compile time.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { createActions } from '@mindmatrix/react';
|
|
10
|
-
*
|
|
11
|
-
* const actions = createActions({
|
|
12
|
-
* authenticate: { handler: 'actions/auth.server.ts' },
|
|
13
|
-
* destroySession: { handler: 'actions/auth.server.ts' },
|
|
14
|
-
* resetPassword: { handler: 'actions/auth.server.ts' },
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* // Usage in models — fully typed, autocomplete on action names:
|
|
18
|
-
* .do(actions.authenticate({ method: 'login' }))
|
|
19
|
-
* .do(actions.destroySession())
|
|
20
|
-
*
|
|
21
|
-
* // Typo = TypeScript compile error:
|
|
22
|
-
* .do(actions.autenticate({}))
|
|
23
|
-
* // ~~~~~~~~~~~~ Property 'autenticate' does not exist
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* @module
|
|
27
|
-
*/
|
|
28
|
-
|
|
29
|
-
import type { ActionDefinition } from './config/defineModel';
|
|
30
|
-
|
|
31
|
-
// =============================================================================
|
|
32
|
-
// Action Manifest & Creators
|
|
33
|
-
// =============================================================================
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Configuration for a single action in the manifest.
|
|
37
|
-
*/
|
|
38
|
-
export interface ActionManifestEntry {
|
|
39
|
-
/** The handler file path (e.g., 'actions/auth.server.ts'). */
|
|
40
|
-
handler: string;
|
|
41
|
-
/** Optional function name within the handler file. */
|
|
42
|
-
functionName?: string;
|
|
43
|
-
/** Optional description for documentation. */
|
|
44
|
-
description?: string;
|
|
45
|
-
/** Action execution mode. Default: 'auto'. */
|
|
46
|
-
mode?: 'auto' | 'manual';
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* A manifest mapping action names to their configuration.
|
|
51
|
-
*/
|
|
52
|
-
export type ActionManifest = Record<string, ActionManifestEntry>;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* A typed action creator function returned for each manifest entry.
|
|
56
|
-
* Accepts optional config and returns an ActionDefinition.
|
|
57
|
-
*/
|
|
58
|
-
export type ActionCreator = (config?: Record<string, unknown>) => ActionDefinition;
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Maps an ActionManifest to an object of typed action creators.
|
|
62
|
-
* Each key from the manifest becomes a callable action creator.
|
|
63
|
-
*/
|
|
64
|
-
export type ActionCreators<M extends ActionManifest> = {
|
|
65
|
-
readonly [K in keyof M]: ActionCreator;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Convert a camelCase or PascalCase string to kebab-case.
|
|
70
|
-
* @internal
|
|
71
|
-
*/
|
|
72
|
-
function toKebab(str: string): string {
|
|
73
|
-
return str
|
|
74
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
75
|
-
.replace(/[_.:\s]+/g, '-')
|
|
76
|
-
.toLowerCase();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Create typed action creators from an actions manifest.
|
|
81
|
-
*
|
|
82
|
-
* Each key in the manifest becomes a function that returns an {@link ActionDefinition}
|
|
83
|
-
* compatible with `.do()`, `onEnter`, `onExit`, and other action slots.
|
|
84
|
-
*
|
|
85
|
-
* The action type is `server:{kebab-case-name}` and the handler path is stored
|
|
86
|
-
* in the config for the build pipeline to resolve.
|
|
87
|
-
*
|
|
88
|
-
* @param manifest - Object mapping action names to their configuration.
|
|
89
|
-
* @returns An object with the same keys, where each value is a typed action creator.
|
|
90
|
-
*
|
|
91
|
-
* @example
|
|
92
|
-
* ```typescript
|
|
93
|
-
* const actions = createActions({
|
|
94
|
-
* authenticate: { handler: 'actions/auth.server.ts' },
|
|
95
|
-
* destroySession: { handler: 'actions/auth.server.ts' },
|
|
96
|
-
* sendWelcomeEmail: { handler: 'actions/email.server.ts', mode: 'manual' },
|
|
97
|
-
* });
|
|
98
|
-
*
|
|
99
|
-
* // Returns ActionDefinition:
|
|
100
|
-
* actions.authenticate({ method: 'login' })
|
|
101
|
-
* // => { id: 'server-authenticate', type: 'server:authenticate',
|
|
102
|
-
* // mode: 'auto', config: { method: 'login', __handler: 'actions/auth.server.ts' } }
|
|
103
|
-
*
|
|
104
|
-
* actions.destroySession()
|
|
105
|
-
* // => { id: 'server-destroy-session', type: 'server:destroySession',
|
|
106
|
-
* // mode: 'auto', config: { __handler: 'actions/auth.server.ts' } }
|
|
107
|
-
* ```
|
|
108
|
-
*/
|
|
109
|
-
export function createActions<const M extends ActionManifest>(manifest: M): ActionCreators<M> {
|
|
110
|
-
const creators = {} as Record<string, ActionCreator>;
|
|
111
|
-
|
|
112
|
-
for (const [name, entry] of Object.entries(manifest)) {
|
|
113
|
-
creators[name] = (config?: Record<string, unknown>): ActionDefinition => {
|
|
114
|
-
const actionConfig: Record<string, unknown> = {
|
|
115
|
-
...config,
|
|
116
|
-
__handler: entry.handler,
|
|
117
|
-
};
|
|
118
|
-
if (entry.functionName) {
|
|
119
|
-
actionConfig.__functionName = entry.functionName;
|
|
120
|
-
}
|
|
121
|
-
return {
|
|
122
|
-
id: `server-${toKebab(name)}`,
|
|
123
|
-
type: `server:${name}`,
|
|
124
|
-
mode: entry.mode ?? 'auto',
|
|
125
|
-
config: actionConfig,
|
|
126
|
-
};
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return creators as ActionCreators<M>;
|
|
131
|
-
}
|
|
132
|
-
|
package/src/actions.ts
DELETED
|
@@ -1,547 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @mindmatrix/react/actions — Typed action factory functions.
|
|
3
|
-
*
|
|
4
|
-
* Provides ergonomic helpers that produce {@link ActionDefinition} objects
|
|
5
|
-
* for use in model definitions (states and transitions). Every function
|
|
6
|
-
* returns a valid `ActionDefinition` that works with `defineModel()`.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```typescript
|
|
10
|
-
* import { defineModel } from '@mindmatrix/react';
|
|
11
|
-
* import { setField, logEvent, notify, spawn } from '@mindmatrix/react/actions';
|
|
12
|
-
*
|
|
13
|
-
* export default defineModel({
|
|
14
|
-
* slug: 'order',
|
|
15
|
-
* fields: { status: { type: 'string', default: 'draft' } },
|
|
16
|
-
* states: {
|
|
17
|
-
* draft: { type: 'initial' },
|
|
18
|
-
* submitted: {
|
|
19
|
-
* onEnter: [
|
|
20
|
-
* setField('status', '"submitted"'),
|
|
21
|
-
* logEvent('order.submitted', { orderId: '{{ state_data.id }}' }),
|
|
22
|
-
* ],
|
|
23
|
-
* },
|
|
24
|
-
* fulfilled: { type: 'end' },
|
|
25
|
-
* },
|
|
26
|
-
* transitions: {
|
|
27
|
-
* submit: { from: 'draft', to: 'submitted' },
|
|
28
|
-
* fulfill: { from: 'submitted', to: 'fulfilled' },
|
|
29
|
-
* },
|
|
30
|
-
* });
|
|
31
|
-
* ```
|
|
32
|
-
*
|
|
33
|
-
* @module
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
import type { ActionDefinition } from './config/defineModel';
|
|
37
|
-
|
|
38
|
-
// =============================================================================
|
|
39
|
-
// Helpers
|
|
40
|
-
// =============================================================================
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Convert a string to kebab-case for auto-generated action IDs.
|
|
44
|
-
*
|
|
45
|
-
* @internal
|
|
46
|
-
*/
|
|
47
|
-
function toKebab(str: string): string {
|
|
48
|
-
return str
|
|
49
|
-
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
50
|
-
.replace(/[_.:\s]+/g, '-')
|
|
51
|
-
.toLowerCase();
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Generate a deterministic action ID from a type and an optional qualifier.
|
|
56
|
-
*
|
|
57
|
-
* @internal
|
|
58
|
-
*/
|
|
59
|
-
function makeId(type: string, qualifier?: string): string {
|
|
60
|
-
const base = toKebab(type);
|
|
61
|
-
if (qualifier) {
|
|
62
|
-
return `${base}-${toKebab(qualifier)}`;
|
|
63
|
-
}
|
|
64
|
-
return base;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// =============================================================================
|
|
68
|
-
// Core Field Mutations
|
|
69
|
-
// =============================================================================
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Set a single field via an expression.
|
|
73
|
-
*
|
|
74
|
-
* Produces a `set_field` action with auto-generated ID based on the field name.
|
|
75
|
-
*
|
|
76
|
-
* @param field - The field name to set.
|
|
77
|
-
* @param expression - An expression string evaluated at runtime.
|
|
78
|
-
* @returns An `ActionDefinition` of type `set_field`.
|
|
79
|
-
*
|
|
80
|
-
* @example
|
|
81
|
-
* ```typescript
|
|
82
|
-
* // Clear an error message
|
|
83
|
-
* setField('errorMessage', '""')
|
|
84
|
-
* // => { id: 'set-field-error-message', type: 'set_field', mode: 'auto',
|
|
85
|
-
* // config: { field: 'errorMessage', expression: '""' } }
|
|
86
|
-
*
|
|
87
|
-
* // Set timestamp to current time
|
|
88
|
-
* setField('lastMessageAt', 'NOW()')
|
|
89
|
-
*
|
|
90
|
-
* // Set from input
|
|
91
|
-
* setField('name', 'input.name')
|
|
92
|
-
* ```
|
|
93
|
-
*/
|
|
94
|
-
export function setField(field: string, expression: string): ActionDefinition {
|
|
95
|
-
return {
|
|
96
|
-
id: makeId('set-field', field),
|
|
97
|
-
type: 'set_field',
|
|
98
|
-
mode: 'auto',
|
|
99
|
-
config: { field, expression },
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Set multiple fields at once via expressions.
|
|
105
|
-
*
|
|
106
|
-
* Produces a `set_fields` action. Each value in the record is an expression
|
|
107
|
-
* string that will be evaluated at runtime.
|
|
108
|
-
*
|
|
109
|
-
* @param fields - A record mapping field names to expression strings.
|
|
110
|
-
* @returns An `ActionDefinition` of type `set_fields`.
|
|
111
|
-
*
|
|
112
|
-
* @example
|
|
113
|
-
* ```typescript
|
|
114
|
-
* // Populate message fields on send
|
|
115
|
-
* setFields({
|
|
116
|
-
* senderId: 'context.actor_id',
|
|
117
|
-
* senderName: 'context.actor_name',
|
|
118
|
-
* timestamp: 'NOW()',
|
|
119
|
-
* content: 'input.content',
|
|
120
|
-
* })
|
|
121
|
-
* // => { id: 'set-fields', type: 'set_fields', mode: 'auto',
|
|
122
|
-
* // config: { fields: { senderId: { expression: 'context.actor_id' }, ... } } }
|
|
123
|
-
*
|
|
124
|
-
* // Clear multiple fields on retry
|
|
125
|
-
* setFields({
|
|
126
|
-
* errorMessage: '""',
|
|
127
|
-
* artifact: 'null',
|
|
128
|
-
* summary: '""',
|
|
129
|
-
* })
|
|
130
|
-
* ```
|
|
131
|
-
*/
|
|
132
|
-
export function setFields(fields: Record<string, string>): ActionDefinition {
|
|
133
|
-
const mapped: Record<string, { expression: string }> = {};
|
|
134
|
-
for (const [key, expr] of Object.entries(fields)) {
|
|
135
|
-
mapped[key] = { expression: expr };
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
id: 'set-fields',
|
|
139
|
-
type: 'set_fields',
|
|
140
|
-
mode: 'auto',
|
|
141
|
-
config: { fields: mapped },
|
|
142
|
-
};
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// =============================================================================
|
|
146
|
-
// Logging
|
|
147
|
-
// =============================================================================
|
|
148
|
-
|
|
149
|
-
/**
|
|
150
|
-
* Emit an event to the workflow audit log.
|
|
151
|
-
*
|
|
152
|
-
* Produces a `log_event` action. The event name is typically dot-delimited
|
|
153
|
-
* (e.g., `'auth.success'`, `'message.sent'`).
|
|
154
|
-
*
|
|
155
|
-
* @param event - The event name to log.
|
|
156
|
-
* @param data - Optional key-value data to include in the log entry.
|
|
157
|
-
* Values are template strings evaluated at runtime (e.g., `'{{ state_data.id }}'`).
|
|
158
|
-
* @returns An `ActionDefinition` of type `log_event`.
|
|
159
|
-
*
|
|
160
|
-
* @example
|
|
161
|
-
* ```typescript
|
|
162
|
-
* // Simple event
|
|
163
|
-
* logEvent('auth.logout')
|
|
164
|
-
* // => { id: 'log-event-auth-logout', type: 'log_event', mode: 'auto',
|
|
165
|
-
* // config: { event: 'auth.logout' } }
|
|
166
|
-
*
|
|
167
|
-
* // Event with data
|
|
168
|
-
* logEvent('message.sent', {
|
|
169
|
-
* channelId: '{{ state_data.channelId }}',
|
|
170
|
-
* senderId: '{{ state_data.senderId }}',
|
|
171
|
-
* })
|
|
172
|
-
* ```
|
|
173
|
-
*/
|
|
174
|
-
export function logEvent(event: string, data?: Record<string, string>): ActionDefinition {
|
|
175
|
-
const config: Record<string, unknown> = { event };
|
|
176
|
-
if (data) {
|
|
177
|
-
config.data = data;
|
|
178
|
-
}
|
|
179
|
-
return {
|
|
180
|
-
id: makeId('log-event', event),
|
|
181
|
-
type: 'log_event',
|
|
182
|
-
mode: 'auto',
|
|
183
|
-
config,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// =============================================================================
|
|
188
|
-
// Notifications
|
|
189
|
-
// =============================================================================
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Options for the {@link notify} action factory.
|
|
193
|
-
*/
|
|
194
|
-
export interface ActionNotifyOptions {
|
|
195
|
-
/**
|
|
196
|
-
* Template expression for notification recipients.
|
|
197
|
-
* Use `recipients` for multi-recipient expressions (e.g., `'{{ state_data.members }}'`).
|
|
198
|
-
*/
|
|
199
|
-
recipients?: string;
|
|
200
|
-
/**
|
|
201
|
-
* Shorthand for a single recipient expression.
|
|
202
|
-
* Alias for `recipients` when sending to one target.
|
|
203
|
-
*/
|
|
204
|
-
to?: string;
|
|
205
|
-
/**
|
|
206
|
-
* Key-value data interpolated into the notification template.
|
|
207
|
-
* Values are template strings evaluated at runtime.
|
|
208
|
-
*/
|
|
209
|
-
data?: Record<string, string>;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Send a notification to one or more recipients.
|
|
214
|
-
*
|
|
215
|
-
* Produces a `send_notification` action. Uses either `recipients` or `to`
|
|
216
|
-
* (whichever is provided) as the recipient expression.
|
|
217
|
-
*
|
|
218
|
-
* @param template - The notification template name.
|
|
219
|
-
* @param options - Recipient and data options.
|
|
220
|
-
* @returns An `ActionDefinition` of type `send_notification`.
|
|
221
|
-
*
|
|
222
|
-
* @example
|
|
223
|
-
* ```typescript
|
|
224
|
-
* // Notify channel members about archival
|
|
225
|
-
* notify('channel_archived', {
|
|
226
|
-
* recipients: '{{ state_data.members }}',
|
|
227
|
-
* data: { channel: '{{ state_data.name }}' },
|
|
228
|
-
* })
|
|
229
|
-
*
|
|
230
|
-
* // Notify a single user about a mention
|
|
231
|
-
* notify('message_mention', {
|
|
232
|
-
* to: '{{ state_data.senderId }}',
|
|
233
|
-
* data: { content: '{{ SUBSTR(state_data.content, 0, 100) }}' },
|
|
234
|
-
* })
|
|
235
|
-
* ```
|
|
236
|
-
*/
|
|
237
|
-
export function notify(template: string, options: ActionNotifyOptions = {}): ActionDefinition {
|
|
238
|
-
const config: Record<string, unknown> = { template };
|
|
239
|
-
const recipient = options.recipients ?? options.to;
|
|
240
|
-
if (recipient) {
|
|
241
|
-
config.recipients = recipient;
|
|
242
|
-
}
|
|
243
|
-
if (options.data) {
|
|
244
|
-
config.data = options.data;
|
|
245
|
-
}
|
|
246
|
-
return {
|
|
247
|
-
id: makeId('notify', template),
|
|
248
|
-
type: 'send_notification',
|
|
249
|
-
mode: 'auto',
|
|
250
|
-
config,
|
|
251
|
-
};
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// =============================================================================
|
|
255
|
-
// Sub-workflow Spawning
|
|
256
|
-
// =============================================================================
|
|
257
|
-
|
|
258
|
-
/**
|
|
259
|
-
* Options for the {@link spawn} action factory.
|
|
260
|
-
*/
|
|
261
|
-
export interface SpawnActionOptions {
|
|
262
|
-
/**
|
|
263
|
-
* Whether the parent workflow waits for the child to complete.
|
|
264
|
-
* Default: `false`.
|
|
265
|
-
*/
|
|
266
|
-
blocking?: boolean;
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Spawn a child workflow instance.
|
|
271
|
-
*
|
|
272
|
-
* Produces a `spawn_subworkflow` action. The child workflow is created
|
|
273
|
-
* from the given definition slug, with optional input field mapping.
|
|
274
|
-
*
|
|
275
|
-
* @param definitionSlug - The slug of the workflow definition to spawn.
|
|
276
|
-
* @param inputMapping - Optional mapping of child input fields to parent expressions.
|
|
277
|
-
* Keys are child field names, values are expression strings evaluated in the parent context.
|
|
278
|
-
* @param options - Optional spawn configuration.
|
|
279
|
-
* @returns An `ActionDefinition` of type `spawn_subworkflow`.
|
|
280
|
-
*
|
|
281
|
-
* @example
|
|
282
|
-
* ```typescript
|
|
283
|
-
* // Spawn a non-blocking reaction workflow
|
|
284
|
-
* spawn('chat-reaction', {
|
|
285
|
-
* messageId: 'state_data.id',
|
|
286
|
-
* channelId: 'state_data.channelId',
|
|
287
|
-
* userId: 'context.actor_id',
|
|
288
|
-
* emoji: 'input.emoji',
|
|
289
|
-
* })
|
|
290
|
-
*
|
|
291
|
-
* // Spawn a blocking payment processor
|
|
292
|
-
* spawn('payment-process', {
|
|
293
|
-
* amount: 'state_data.totalAmount',
|
|
294
|
-
* currency: 'state_data.currency',
|
|
295
|
-
* }, { blocking: true })
|
|
296
|
-
* ```
|
|
297
|
-
*/
|
|
298
|
-
export function spawn(
|
|
299
|
-
definitionSlug: string,
|
|
300
|
-
inputMapping?: Record<string, string>,
|
|
301
|
-
options?: SpawnActionOptions,
|
|
302
|
-
): ActionDefinition {
|
|
303
|
-
const config: Record<string, unknown> = {
|
|
304
|
-
definition_slug: definitionSlug,
|
|
305
|
-
blocking: options?.blocking ?? false,
|
|
306
|
-
};
|
|
307
|
-
if (inputMapping) {
|
|
308
|
-
config.input_mapping = inputMapping;
|
|
309
|
-
}
|
|
310
|
-
return {
|
|
311
|
-
id: makeId('spawn', definitionSlug),
|
|
312
|
-
type: 'spawn_subworkflow',
|
|
313
|
-
mode: 'auto',
|
|
314
|
-
config,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// =============================================================================
|
|
319
|
-
// Server / Device Actions
|
|
320
|
-
// =============================================================================
|
|
321
|
-
|
|
322
|
-
/**
|
|
323
|
-
* Execute an opaque server-side action.
|
|
324
|
-
*
|
|
325
|
-
* Produces a `server:{type}` action. Server actions are implemented in
|
|
326
|
-
* `actions.server.ts` files and run on the backend.
|
|
327
|
-
*
|
|
328
|
-
* @param type - The server action type (appended to `server:` prefix).
|
|
329
|
-
* @param config - Optional action configuration passed to the server handler.
|
|
330
|
-
* @returns An `ActionDefinition` of type `server:{type}`.
|
|
331
|
-
*
|
|
332
|
-
* @example
|
|
333
|
-
* ```typescript
|
|
334
|
-
* // Authenticate via server
|
|
335
|
-
* serverAction('authenticate', {
|
|
336
|
-
* method: 'login',
|
|
337
|
-
* email: '{{ input.email }}',
|
|
338
|
-
* password: '{{ input.password }}',
|
|
339
|
-
* })
|
|
340
|
-
* // => { id: 'server-authenticate', type: 'server:authenticate', mode: 'auto',
|
|
341
|
-
* // config: { method: 'login', ... } }
|
|
342
|
-
*
|
|
343
|
-
* // Destroy a session
|
|
344
|
-
* serverAction('destroy_session')
|
|
345
|
-
* // => { id: 'server-destroy-session', type: 'server:destroy_session', mode: 'auto', config: {} }
|
|
346
|
-
* ```
|
|
347
|
-
*/
|
|
348
|
-
export function serverAction(type: string, config?: Record<string, unknown>): ActionDefinition {
|
|
349
|
-
return {
|
|
350
|
-
id: makeId('server', type),
|
|
351
|
-
type: `server:${type}`,
|
|
352
|
-
mode: 'auto',
|
|
353
|
-
config: config ?? {},
|
|
354
|
-
};
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/**
|
|
358
|
-
* Execute an opaque device-side action.
|
|
359
|
-
*
|
|
360
|
-
* Produces a `device:{type}` action. Device actions run on the client
|
|
361
|
-
* (browser, mobile, etc.) and are implemented in `actions.device.ts` files.
|
|
362
|
-
*
|
|
363
|
-
* @param type - The device action type (appended to `device:` prefix).
|
|
364
|
-
* @param config - Optional action configuration passed to the device handler.
|
|
365
|
-
* @returns An `ActionDefinition` of type `device:{type}`.
|
|
366
|
-
*
|
|
367
|
-
* @example
|
|
368
|
-
* ```typescript
|
|
369
|
-
* // Trigger haptic feedback on mobile
|
|
370
|
-
* deviceAction('haptic', { pattern: 'success' })
|
|
371
|
-
* // => { id: 'device-haptic', type: 'device:haptic', mode: 'auto',
|
|
372
|
-
* // config: { pattern: 'success' } }
|
|
373
|
-
*
|
|
374
|
-
* // Open native share dialog
|
|
375
|
-
* deviceAction('share', {
|
|
376
|
-
* title: '{{ state_data.name }}',
|
|
377
|
-
* url: '{{ state_data.shareUrl }}',
|
|
378
|
-
* })
|
|
379
|
-
* ```
|
|
380
|
-
*/
|
|
381
|
-
export function deviceAction(type: string, config?: Record<string, unknown>): ActionDefinition {
|
|
382
|
-
return {
|
|
383
|
-
id: makeId('device', type),
|
|
384
|
-
type: `device:${type}`,
|
|
385
|
-
mode: 'auto',
|
|
386
|
-
config: config ?? {},
|
|
387
|
-
};
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// =============================================================================
|
|
391
|
-
// Connector Actions
|
|
392
|
-
// =============================================================================
|
|
393
|
-
|
|
394
|
-
/**
|
|
395
|
-
* Execute an external service connector action.
|
|
396
|
-
*
|
|
397
|
-
* Produces a `connector.{provider}.{operation}` action. Connector actions
|
|
398
|
-
* integrate with third-party services like Xero, Stripe, Slack, etc.
|
|
399
|
-
*
|
|
400
|
-
* @param provider - The connector provider name (e.g., `'xero'`, `'stripe'`).
|
|
401
|
-
* @param operation - The operation to perform (e.g., `'query'`, `'create'`).
|
|
402
|
-
* @param config - Optional configuration passed to the connector handler.
|
|
403
|
-
* @returns An `ActionDefinition` of type `connector.{provider}.{operation}`.
|
|
404
|
-
*
|
|
405
|
-
* @example
|
|
406
|
-
* ```typescript
|
|
407
|
-
* // Query Xero invoices
|
|
408
|
-
* connector('xero', 'query', {
|
|
409
|
-
* tenant_id: '{{ state_data.tenantId }}',
|
|
410
|
-
* entity: 'invoices',
|
|
411
|
-
* })
|
|
412
|
-
* // => { id: 'connector-xero-query', type: 'connector.xero.query', mode: 'auto',
|
|
413
|
-
* // config: { tenant_id: '...', entity: 'invoices' } }
|
|
414
|
-
*
|
|
415
|
-
* // Create a Stripe charge
|
|
416
|
-
* connector('stripe', 'create_charge', {
|
|
417
|
-
* amount: '{{ state_data.amount }}',
|
|
418
|
-
* currency: '{{ state_data.currency }}',
|
|
419
|
-
* customer: '{{ state_data.stripeCustomerId }}',
|
|
420
|
-
* })
|
|
421
|
-
* ```
|
|
422
|
-
*/
|
|
423
|
-
export function connector(
|
|
424
|
-
provider: string,
|
|
425
|
-
operation: string,
|
|
426
|
-
config?: Record<string, unknown>,
|
|
427
|
-
): ActionDefinition {
|
|
428
|
-
return {
|
|
429
|
-
id: makeId('connector', `${provider}-${operation}`),
|
|
430
|
-
type: `connector.${provider}.${operation}`,
|
|
431
|
-
mode: 'auto',
|
|
432
|
-
config: config ?? {},
|
|
433
|
-
};
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// =============================================================================
|
|
437
|
-
// LLM Actions
|
|
438
|
-
// =============================================================================
|
|
439
|
-
|
|
440
|
-
/**
|
|
441
|
-
* Execute an LLM / AI action.
|
|
442
|
-
*
|
|
443
|
-
* Produces an `llm.{operation}` action. LLM actions are registered globally
|
|
444
|
-
* as custom action handlers and support operations like chat completions,
|
|
445
|
-
* embeddings, classification, etc.
|
|
446
|
-
*
|
|
447
|
-
* @param operation - The LLM operation (e.g., `'chat'`, `'embed'`, `'classify'`).
|
|
448
|
-
* @param config - Optional configuration for the LLM call.
|
|
449
|
-
* @returns An `ActionDefinition` of type `llm.{operation}`.
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* ```typescript
|
|
453
|
-
* // Call LLM for chat completion
|
|
454
|
-
* llm('chat', {
|
|
455
|
-
* system_prompt: 'DATA_AGENT_SYSTEM_PROMPT',
|
|
456
|
-
* user_message: '{{ state_data.dataContext }}\n\nUser intent: {{ state_data.intentText }}',
|
|
457
|
-
* max_tokens: 8192,
|
|
458
|
-
* temperature: 0.3,
|
|
459
|
-
* })
|
|
460
|
-
* // => { id: 'llm-chat', type: 'llm.chat', mode: 'auto',
|
|
461
|
-
* // config: { system_prompt: '...', ... } }
|
|
462
|
-
*
|
|
463
|
-
* // Generate embeddings
|
|
464
|
-
* llm('embed', {
|
|
465
|
-
* input: '{{ state_data.content }}',
|
|
466
|
-
* model: 'text-embedding-3-small',
|
|
467
|
-
* })
|
|
468
|
-
* ```
|
|
469
|
-
*/
|
|
470
|
-
export function llm(operation: string, config?: Record<string, unknown>): ActionDefinition {
|
|
471
|
-
return {
|
|
472
|
-
id: makeId('llm', operation),
|
|
473
|
-
type: `llm.${operation}`,
|
|
474
|
-
mode: 'auto',
|
|
475
|
-
config: config ?? {},
|
|
476
|
-
};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// =============================================================================
|
|
480
|
-
// Generic Custom Action
|
|
481
|
-
// =============================================================================
|
|
482
|
-
|
|
483
|
-
/**
|
|
484
|
-
* Options for the generic {@link action} factory.
|
|
485
|
-
*/
|
|
486
|
-
export interface ActionOptions {
|
|
487
|
-
/**
|
|
488
|
-
* Whether this action runs automatically or requires manual trigger.
|
|
489
|
-
* Default: `'auto'`.
|
|
490
|
-
*/
|
|
491
|
-
mode?: 'auto' | 'manual';
|
|
492
|
-
/**
|
|
493
|
-
* Expression that must be truthy for this action to execute.
|
|
494
|
-
*/
|
|
495
|
-
condition?: string;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
/**
|
|
499
|
-
* Create a generic custom action with explicit ID and type.
|
|
500
|
-
*
|
|
501
|
-
* Use this when none of the specialized factories (`setField`, `logEvent`,
|
|
502
|
-
* `notify`, `spawn`, etc.) fit your use case. Provides full control over
|
|
503
|
-
* the action ID, type, config, and options.
|
|
504
|
-
*
|
|
505
|
-
* @param id - Unique identifier for the action within its state/transition.
|
|
506
|
-
* @param type - The action type string.
|
|
507
|
-
* @param config - Optional action configuration.
|
|
508
|
-
* @param options - Optional mode and condition.
|
|
509
|
-
* @returns An `ActionDefinition` with the specified parameters.
|
|
510
|
-
*
|
|
511
|
-
* @example
|
|
512
|
-
* ```typescript
|
|
513
|
-
* // Custom webhook action
|
|
514
|
-
* action('post-webhook', 'server:webhook', {
|
|
515
|
-
* url: 'https://hooks.example.com/orders',
|
|
516
|
-
* method: 'POST',
|
|
517
|
-
* body: '{{ state_data }}',
|
|
518
|
-
* })
|
|
519
|
-
*
|
|
520
|
-
* // Conditional manual action
|
|
521
|
-
* action('approve-order', 'server:approve', {
|
|
522
|
-
* orderId: '{{ state_data.id }}',
|
|
523
|
-
* }, {
|
|
524
|
-
* mode: 'manual',
|
|
525
|
-
* condition: 'state_data.amount > 1000',
|
|
526
|
-
* })
|
|
527
|
-
* ```
|
|
528
|
-
*/
|
|
529
|
-
export function action(
|
|
530
|
-
id: string,
|
|
531
|
-
type: string,
|
|
532
|
-
config?: Record<string, unknown>,
|
|
533
|
-
options?: ActionOptions,
|
|
534
|
-
): ActionDefinition {
|
|
535
|
-
const def: ActionDefinition = {
|
|
536
|
-
id,
|
|
537
|
-
type,
|
|
538
|
-
mode: options?.mode ?? 'auto',
|
|
539
|
-
};
|
|
540
|
-
if (config) {
|
|
541
|
-
def.config = config;
|
|
542
|
-
}
|
|
543
|
-
if (options?.condition) {
|
|
544
|
-
def.condition = options.condition;
|
|
545
|
-
}
|
|
546
|
-
return def;
|
|
547
|
-
}
|