@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.
Files changed (94) hide show
  1. package/README.md +112 -0
  2. package/dist/index.d.mts +27 -2
  3. package/dist/index.d.ts +27 -2
  4. package/dist/index.js +70 -3
  5. package/dist/index.mjs +74 -12
  6. package/package.json +4 -3
  7. package/package.json.backup +0 -41
  8. package/src/Blueprint.ts +0 -216
  9. package/src/__tests__/Blueprint.test.ts +0 -106
  10. package/src/__tests__/action-context.test.ts +0 -166
  11. package/src/__tests__/actionCreators.test.ts +0 -179
  12. package/src/__tests__/builders.test.ts +0 -336
  13. package/src/__tests__/defineBlueprint-composition.test.ts +0 -106
  14. package/src/__tests__/factories.test.ts +0 -229
  15. package/src/__tests__/loader.test.ts +0 -159
  16. package/src/__tests__/logger.test.ts +0 -70
  17. package/src/__tests__/type-inference.test.ts +0 -160
  18. package/src/__tests__/typed-transitions.test.ts +0 -126
  19. package/src/__tests__/useModuleConfig.test.ts +0 -61
  20. package/src/actionCreators.ts +0 -132
  21. package/src/actions.ts +0 -547
  22. package/src/atoms/index.ts +0 -600
  23. package/src/authoring.ts +0 -92
  24. package/src/browser-player.ts +0 -783
  25. package/src/builders.ts +0 -1342
  26. package/src/components/ExperienceWorkflowBridge.tsx +0 -123
  27. package/src/components/PlayerProvider.tsx +0 -43
  28. package/src/components/atoms/index.tsx +0 -269
  29. package/src/components/index.ts +0 -36
  30. package/src/conditions.ts +0 -692
  31. package/src/config/defineBlueprint.ts +0 -329
  32. package/src/config/defineModel.ts +0 -753
  33. package/src/config/defineWorkspace.ts +0 -24
  34. package/src/core/WorkflowRuntime.ts +0 -153
  35. package/src/factories.ts +0 -425
  36. package/src/grammar/index.ts +0 -173
  37. package/src/hooks/index.ts +0 -106
  38. package/src/hooks/useAuth.ts +0 -288
  39. package/src/hooks/useChannel.ts +0 -304
  40. package/src/hooks/useComputed.ts +0 -154
  41. package/src/hooks/useDomainSubscription.ts +0 -110
  42. package/src/hooks/useDuringAction.ts +0 -99
  43. package/src/hooks/useExperienceState.ts +0 -59
  44. package/src/hooks/useExpressionLibrary.ts +0 -129
  45. package/src/hooks/useForm.ts +0 -352
  46. package/src/hooks/useGeolocation.ts +0 -207
  47. package/src/hooks/useMapView.ts +0 -259
  48. package/src/hooks/useMiddleware.ts +0 -291
  49. package/src/hooks/useModel.ts +0 -363
  50. package/src/hooks/useModule.ts +0 -59
  51. package/src/hooks/useModuleConfig.ts +0 -61
  52. package/src/hooks/useMutation.ts +0 -237
  53. package/src/hooks/useNotification.ts +0 -151
  54. package/src/hooks/useOnChange.ts +0 -30
  55. package/src/hooks/useOnEnter.ts +0 -59
  56. package/src/hooks/useOnEvent.ts +0 -37
  57. package/src/hooks/useOnExit.ts +0 -27
  58. package/src/hooks/useOnTransition.ts +0 -30
  59. package/src/hooks/usePackage.ts +0 -128
  60. package/src/hooks/useParams.ts +0 -33
  61. package/src/hooks/usePlayer.ts +0 -308
  62. package/src/hooks/useQuery.ts +0 -184
  63. package/src/hooks/useRealtimeQuery.ts +0 -222
  64. package/src/hooks/useRole.ts +0 -191
  65. package/src/hooks/useRouteParams.ts +0 -100
  66. package/src/hooks/useRouter.ts +0 -347
  67. package/src/hooks/useServerAction.ts +0 -178
  68. package/src/hooks/useServerState.ts +0 -284
  69. package/src/hooks/useToast.ts +0 -164
  70. package/src/hooks/useTransition.ts +0 -39
  71. package/src/hooks/useView.ts +0 -102
  72. package/src/hooks/useWhileIn.ts +0 -48
  73. package/src/hooks/useWorkflow.ts +0 -63
  74. package/src/index.ts +0 -465
  75. package/src/loader/experience-workflow-loader.ts +0 -192
  76. package/src/loader/index.ts +0 -6
  77. package/src/local/LocalEngine.ts +0 -388
  78. package/src/local/LocalEngineAdapter.ts +0 -175
  79. package/src/local/LocalEngineContext.ts +0 -30
  80. package/src/logger.ts +0 -37
  81. package/src/mixins.ts +0 -1160
  82. package/src/providers/RuntimeContext.ts +0 -20
  83. package/src/providers/WorkflowProvider.tsx +0 -28
  84. package/src/routing/instance-key.ts +0 -107
  85. package/src/server/transition-context.ts +0 -172
  86. package/src/testing/index.ts +0 -9
  87. package/src/testing/useBlueprintTestRunner.ts +0 -91
  88. package/src/testing/useGraphAnalysis.ts +0 -18
  89. package/src/testing/useTestRunner.ts +0 -77
  90. package/src/testing.ts +0 -995
  91. package/src/types/workflow-inference.ts +0 -158
  92. package/src/types.ts +0 -114
  93. package/tsconfig.json +0 -27
  94. package/vitest.config.ts +0 -8
@@ -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
- }