@lokascript/domain-flow 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +120 -0
- package/dist/index.cjs +2251 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +643 -0
- package/dist/index.d.ts +643 -0
- package/dist/index.js +2169 -0
- package/dist/index.js.map +1 -0
- package/package.json +66 -0
- package/src/__test__/flow-domain.test.ts +696 -0
- package/src/__test__/hateoas-commands.test.ts +520 -0
- package/src/__test__/htmx-generator.test.ts +100 -0
- package/src/__test__/mcp-workflow-server.test.ts +317 -0
- package/src/__test__/pipeline-parser.test.ts +188 -0
- package/src/__test__/route-extractor.test.ts +94 -0
- package/src/generators/flow-generator.ts +338 -0
- package/src/generators/flow-renderer.ts +262 -0
- package/src/generators/htmx-generator.ts +129 -0
- package/src/generators/route-extractor.ts +105 -0
- package/src/generators/workflow-generator.ts +129 -0
- package/src/index.ts +210 -0
- package/src/parser/pipeline-parser.ts +151 -0
- package/src/profiles/index.ts +186 -0
- package/src/runtime/mcp-workflow-server.ts +409 -0
- package/src/runtime/workflow-executor.ts +171 -0
- package/src/schemas/hateoas-schemas.ts +152 -0
- package/src/schemas/index.ts +320 -0
- package/src/siren-agent.d.ts +14 -0
- package/src/tokenizers/index.ts +592 -0
- package/src/types.ts +108 -0
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HATEOAS Command Schemas
|
|
3
|
+
*
|
|
4
|
+
* Defines 4 HATEOAS-aware FlowScript commands: enter, follow, perform, capture.
|
|
5
|
+
* These compile to siren-grail workflow steps instead of vanilla JS.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { defineCommand, defineRole } from '@lokascript/framework';
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// ENTER — Establish HATEOAS entry point
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
export const enterSchema = defineCommand({
|
|
15
|
+
action: 'enter',
|
|
16
|
+
description: 'Connect to a HATEOAS API entry point',
|
|
17
|
+
category: 'source',
|
|
18
|
+
primaryRole: 'source',
|
|
19
|
+
roles: [
|
|
20
|
+
defineRole({
|
|
21
|
+
role: 'source',
|
|
22
|
+
description: 'API entry point URL',
|
|
23
|
+
required: true,
|
|
24
|
+
expectedTypes: ['expression'],
|
|
25
|
+
svoPosition: 1,
|
|
26
|
+
sovPosition: 1,
|
|
27
|
+
}),
|
|
28
|
+
],
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// =============================================================================
|
|
32
|
+
// FOLLOW — Navigate by link relation
|
|
33
|
+
// =============================================================================
|
|
34
|
+
|
|
35
|
+
export const followSchema = defineCommand({
|
|
36
|
+
action: 'follow',
|
|
37
|
+
description: 'Navigate to a resource by following a link relation',
|
|
38
|
+
category: 'action',
|
|
39
|
+
primaryRole: 'patient',
|
|
40
|
+
roles: [
|
|
41
|
+
defineRole({
|
|
42
|
+
role: 'patient',
|
|
43
|
+
description: 'Link relation name to follow (e.g., "orders", "next")',
|
|
44
|
+
required: true,
|
|
45
|
+
expectedTypes: ['expression'],
|
|
46
|
+
svoPosition: 2,
|
|
47
|
+
sovPosition: 2,
|
|
48
|
+
}),
|
|
49
|
+
defineRole({
|
|
50
|
+
role: 'instrument',
|
|
51
|
+
description: 'Parameter or sub-resource identifier (e.g., item {id})',
|
|
52
|
+
required: false,
|
|
53
|
+
expectedTypes: ['expression'],
|
|
54
|
+
svoPosition: 1,
|
|
55
|
+
sovPosition: 1,
|
|
56
|
+
markerOverride: {
|
|
57
|
+
en: 'item',
|
|
58
|
+
es: 'elemento',
|
|
59
|
+
ja: 'の',
|
|
60
|
+
ar: 'عنصر',
|
|
61
|
+
ko: '항목',
|
|
62
|
+
zh: '项',
|
|
63
|
+
tr: 'öğe',
|
|
64
|
+
fr: 'élément',
|
|
65
|
+
},
|
|
66
|
+
}),
|
|
67
|
+
],
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// =============================================================================
|
|
71
|
+
// PERFORM — Execute a server-defined action
|
|
72
|
+
// =============================================================================
|
|
73
|
+
|
|
74
|
+
export const performSchema = defineCommand({
|
|
75
|
+
action: 'perform',
|
|
76
|
+
description: 'Execute a server-defined action (Siren affordance)',
|
|
77
|
+
category: 'action',
|
|
78
|
+
primaryRole: 'patient',
|
|
79
|
+
roles: [
|
|
80
|
+
defineRole({
|
|
81
|
+
role: 'patient',
|
|
82
|
+
description: 'Action name to execute (e.g., "create-order", "ship-order")',
|
|
83
|
+
required: true,
|
|
84
|
+
expectedTypes: ['expression'],
|
|
85
|
+
svoPosition: 2,
|
|
86
|
+
sovPosition: 1,
|
|
87
|
+
}),
|
|
88
|
+
defineRole({
|
|
89
|
+
role: 'source',
|
|
90
|
+
description: 'Data source — form selector or inline data',
|
|
91
|
+
required: false,
|
|
92
|
+
expectedTypes: ['selector', 'expression'],
|
|
93
|
+
svoPosition: 1,
|
|
94
|
+
sovPosition: 2,
|
|
95
|
+
markerOverride: {
|
|
96
|
+
en: 'with',
|
|
97
|
+
es: 'con',
|
|
98
|
+
ja: 'で',
|
|
99
|
+
ar: 'ب',
|
|
100
|
+
ko: '로',
|
|
101
|
+
zh: '用',
|
|
102
|
+
tr: 'ile',
|
|
103
|
+
fr: 'avec',
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
106
|
+
],
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// =============================================================================
|
|
110
|
+
// CAPTURE — Bind response data to a variable
|
|
111
|
+
// =============================================================================
|
|
112
|
+
|
|
113
|
+
export const captureSchema = defineCommand({
|
|
114
|
+
action: 'capture',
|
|
115
|
+
description: 'Bind response data to a named variable for later use',
|
|
116
|
+
category: 'action',
|
|
117
|
+
primaryRole: 'destination',
|
|
118
|
+
roles: [
|
|
119
|
+
defineRole({
|
|
120
|
+
role: 'patient',
|
|
121
|
+
description: 'Property path to capture (optional — captures entire entity if omitted)',
|
|
122
|
+
required: false,
|
|
123
|
+
expectedTypes: ['expression'],
|
|
124
|
+
svoPosition: 2,
|
|
125
|
+
sovPosition: 2,
|
|
126
|
+
}),
|
|
127
|
+
defineRole({
|
|
128
|
+
role: 'destination',
|
|
129
|
+
description: 'Variable name to bind the captured value to',
|
|
130
|
+
required: true,
|
|
131
|
+
expectedTypes: ['expression'],
|
|
132
|
+
svoPosition: 1,
|
|
133
|
+
sovPosition: 1,
|
|
134
|
+
markerOverride: {
|
|
135
|
+
en: 'as',
|
|
136
|
+
es: 'como',
|
|
137
|
+
ja: 'として',
|
|
138
|
+
ar: 'ك',
|
|
139
|
+
ko: '로',
|
|
140
|
+
zh: '为',
|
|
141
|
+
tr: 'olarak',
|
|
142
|
+
fr: 'comme',
|
|
143
|
+
},
|
|
144
|
+
}),
|
|
145
|
+
],
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// =============================================================================
|
|
149
|
+
// All HATEOAS Schemas
|
|
150
|
+
// =============================================================================
|
|
151
|
+
|
|
152
|
+
export const hateoasSchemas = [enterSchema, followSchema, performSchema, captureSchema];
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FlowScript Command Schemas
|
|
3
|
+
*
|
|
4
|
+
* Defines the semantic structure of data flow commands using the framework's
|
|
5
|
+
* defineCommand/defineRole helpers. Each schema specifies roles (source, destination,
|
|
6
|
+
* style, duration, etc.) and per-language marker overrides for 8 languages.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { defineCommand, defineRole } from '@lokascript/framework';
|
|
10
|
+
|
|
11
|
+
// =============================================================================
|
|
12
|
+
// FETCH — Single HTTP request with target
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
export const fetchSchema = defineCommand({
|
|
16
|
+
action: 'fetch',
|
|
17
|
+
description: 'Fetch data from a URL and deliver to a target element',
|
|
18
|
+
category: 'source',
|
|
19
|
+
primaryRole: 'source',
|
|
20
|
+
roles: [
|
|
21
|
+
defineRole({
|
|
22
|
+
role: 'source',
|
|
23
|
+
description: 'URL to fetch from',
|
|
24
|
+
required: true,
|
|
25
|
+
expectedTypes: ['expression'],
|
|
26
|
+
svoPosition: 2,
|
|
27
|
+
sovPosition: 2,
|
|
28
|
+
}),
|
|
29
|
+
defineRole({
|
|
30
|
+
role: 'style',
|
|
31
|
+
description: 'Response format (json, html, text)',
|
|
32
|
+
required: false,
|
|
33
|
+
expectedTypes: ['expression'],
|
|
34
|
+
svoPosition: 1,
|
|
35
|
+
sovPosition: 1,
|
|
36
|
+
markerOverride: {
|
|
37
|
+
en: 'as',
|
|
38
|
+
es: 'como',
|
|
39
|
+
ja: 'で',
|
|
40
|
+
ar: 'ك',
|
|
41
|
+
ko: '로',
|
|
42
|
+
zh: '以',
|
|
43
|
+
tr: 'olarak',
|
|
44
|
+
fr: 'comme',
|
|
45
|
+
},
|
|
46
|
+
}),
|
|
47
|
+
defineRole({
|
|
48
|
+
role: 'destination',
|
|
49
|
+
description: 'Target element to deliver data to',
|
|
50
|
+
required: false,
|
|
51
|
+
expectedTypes: ['selector', 'expression'],
|
|
52
|
+
svoPosition: 0,
|
|
53
|
+
sovPosition: 0,
|
|
54
|
+
markerOverride: {
|
|
55
|
+
en: 'into',
|
|
56
|
+
es: 'en',
|
|
57
|
+
ja: 'に',
|
|
58
|
+
ar: 'في',
|
|
59
|
+
ko: '에',
|
|
60
|
+
zh: '到',
|
|
61
|
+
tr: 'e',
|
|
62
|
+
fr: 'dans',
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// =============================================================================
|
|
69
|
+
// POLL — Repeated fetch with interval
|
|
70
|
+
// =============================================================================
|
|
71
|
+
|
|
72
|
+
export const pollSchema = defineCommand({
|
|
73
|
+
action: 'poll',
|
|
74
|
+
description: 'Repeatedly fetch data at a specified interval',
|
|
75
|
+
category: 'source',
|
|
76
|
+
primaryRole: 'source',
|
|
77
|
+
roles: [
|
|
78
|
+
defineRole({
|
|
79
|
+
role: 'source',
|
|
80
|
+
description: 'URL to poll',
|
|
81
|
+
required: true,
|
|
82
|
+
expectedTypes: ['expression'],
|
|
83
|
+
svoPosition: 4,
|
|
84
|
+
sovPosition: 4,
|
|
85
|
+
}),
|
|
86
|
+
defineRole({
|
|
87
|
+
role: 'duration',
|
|
88
|
+
description: 'Polling interval (e.g., 5s, 30s, 1m)',
|
|
89
|
+
required: true,
|
|
90
|
+
expectedTypes: ['expression', 'literal'],
|
|
91
|
+
svoPosition: 3,
|
|
92
|
+
sovPosition: 3,
|
|
93
|
+
markerOverride: {
|
|
94
|
+
en: 'every',
|
|
95
|
+
es: 'cada',
|
|
96
|
+
ja: 'ごとに',
|
|
97
|
+
ar: 'كل',
|
|
98
|
+
ko: '마다',
|
|
99
|
+
zh: '每',
|
|
100
|
+
tr: 'her',
|
|
101
|
+
fr: 'chaque',
|
|
102
|
+
},
|
|
103
|
+
}),
|
|
104
|
+
defineRole({
|
|
105
|
+
role: 'style',
|
|
106
|
+
description: 'Response format (json, html, text)',
|
|
107
|
+
required: false,
|
|
108
|
+
expectedTypes: ['expression'],
|
|
109
|
+
svoPosition: 2,
|
|
110
|
+
sovPosition: 2,
|
|
111
|
+
markerOverride: {
|
|
112
|
+
en: 'as',
|
|
113
|
+
es: 'como',
|
|
114
|
+
ja: 'で',
|
|
115
|
+
ar: 'ك',
|
|
116
|
+
ko: '로',
|
|
117
|
+
zh: '以',
|
|
118
|
+
tr: 'olarak',
|
|
119
|
+
fr: 'comme',
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
defineRole({
|
|
123
|
+
role: 'destination',
|
|
124
|
+
description: 'Target element for poll results',
|
|
125
|
+
required: false,
|
|
126
|
+
expectedTypes: ['selector', 'expression'],
|
|
127
|
+
svoPosition: 1,
|
|
128
|
+
sovPosition: 1,
|
|
129
|
+
markerOverride: {
|
|
130
|
+
en: 'into',
|
|
131
|
+
es: 'en',
|
|
132
|
+
ja: 'に',
|
|
133
|
+
ar: 'في',
|
|
134
|
+
ko: '에',
|
|
135
|
+
zh: '到',
|
|
136
|
+
tr: 'e',
|
|
137
|
+
fr: 'dans',
|
|
138
|
+
},
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// =============================================================================
|
|
144
|
+
// STREAM — Server-Sent Events connection
|
|
145
|
+
// =============================================================================
|
|
146
|
+
|
|
147
|
+
export const streamSchema = defineCommand({
|
|
148
|
+
action: 'stream',
|
|
149
|
+
description: 'Open a streaming connection (SSE) to a URL',
|
|
150
|
+
category: 'source',
|
|
151
|
+
primaryRole: 'source',
|
|
152
|
+
roles: [
|
|
153
|
+
defineRole({
|
|
154
|
+
role: 'source',
|
|
155
|
+
description: 'URL for SSE stream',
|
|
156
|
+
required: true,
|
|
157
|
+
expectedTypes: ['expression'],
|
|
158
|
+
svoPosition: 2,
|
|
159
|
+
sovPosition: 2,
|
|
160
|
+
}),
|
|
161
|
+
defineRole({
|
|
162
|
+
role: 'style',
|
|
163
|
+
description: 'Stream type (sse)',
|
|
164
|
+
required: false,
|
|
165
|
+
expectedTypes: ['expression'],
|
|
166
|
+
svoPosition: 1,
|
|
167
|
+
sovPosition: 1,
|
|
168
|
+
markerOverride: {
|
|
169
|
+
en: 'as',
|
|
170
|
+
es: 'como',
|
|
171
|
+
ja: 'で',
|
|
172
|
+
ar: 'ك',
|
|
173
|
+
ko: '로',
|
|
174
|
+
zh: '以',
|
|
175
|
+
tr: 'olarak',
|
|
176
|
+
fr: 'comme',
|
|
177
|
+
},
|
|
178
|
+
}),
|
|
179
|
+
defineRole({
|
|
180
|
+
role: 'destination',
|
|
181
|
+
description: 'Target element for streamed data',
|
|
182
|
+
required: false,
|
|
183
|
+
expectedTypes: ['selector', 'expression'],
|
|
184
|
+
svoPosition: 0,
|
|
185
|
+
sovPosition: 0,
|
|
186
|
+
markerOverride: {
|
|
187
|
+
en: 'into',
|
|
188
|
+
es: 'en',
|
|
189
|
+
ja: 'に',
|
|
190
|
+
ar: 'في',
|
|
191
|
+
ko: '에',
|
|
192
|
+
zh: '到',
|
|
193
|
+
tr: 'e',
|
|
194
|
+
fr: 'dans',
|
|
195
|
+
},
|
|
196
|
+
}),
|
|
197
|
+
],
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// =============================================================================
|
|
201
|
+
// SUBMIT — Form submission
|
|
202
|
+
// =============================================================================
|
|
203
|
+
|
|
204
|
+
export const submitSchema = defineCommand({
|
|
205
|
+
action: 'submit',
|
|
206
|
+
description: 'Submit form data to a URL',
|
|
207
|
+
category: 'action',
|
|
208
|
+
primaryRole: 'patient',
|
|
209
|
+
roles: [
|
|
210
|
+
defineRole({
|
|
211
|
+
role: 'patient',
|
|
212
|
+
description: 'Form element to submit',
|
|
213
|
+
required: true,
|
|
214
|
+
expectedTypes: ['selector', 'expression'],
|
|
215
|
+
svoPosition: 2,
|
|
216
|
+
sovPosition: 1,
|
|
217
|
+
}),
|
|
218
|
+
defineRole({
|
|
219
|
+
role: 'destination',
|
|
220
|
+
description: 'URL to submit to',
|
|
221
|
+
required: true,
|
|
222
|
+
expectedTypes: ['expression'],
|
|
223
|
+
svoPosition: 1,
|
|
224
|
+
sovPosition: 2,
|
|
225
|
+
markerOverride: {
|
|
226
|
+
en: 'to',
|
|
227
|
+
es: 'a',
|
|
228
|
+
ja: 'に',
|
|
229
|
+
ar: 'إلى',
|
|
230
|
+
ko: '로',
|
|
231
|
+
zh: '到',
|
|
232
|
+
tr: 'e',
|
|
233
|
+
fr: 'vers',
|
|
234
|
+
},
|
|
235
|
+
}),
|
|
236
|
+
defineRole({
|
|
237
|
+
role: 'style',
|
|
238
|
+
description: 'Request encoding (json, form, multipart)',
|
|
239
|
+
required: false,
|
|
240
|
+
expectedTypes: ['expression'],
|
|
241
|
+
svoPosition: 0,
|
|
242
|
+
sovPosition: 0,
|
|
243
|
+
markerOverride: {
|
|
244
|
+
en: 'as',
|
|
245
|
+
es: 'como',
|
|
246
|
+
ja: 'で',
|
|
247
|
+
ar: 'ك',
|
|
248
|
+
ko: '로',
|
|
249
|
+
zh: '以',
|
|
250
|
+
tr: 'olarak',
|
|
251
|
+
fr: 'comme',
|
|
252
|
+
},
|
|
253
|
+
}),
|
|
254
|
+
],
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// =============================================================================
|
|
258
|
+
// TRANSFORM — Data transformation step
|
|
259
|
+
// =============================================================================
|
|
260
|
+
|
|
261
|
+
export const transformSchema = defineCommand({
|
|
262
|
+
action: 'transform',
|
|
263
|
+
description: 'Transform data using a function or format string',
|
|
264
|
+
category: 'transform',
|
|
265
|
+
primaryRole: 'patient',
|
|
266
|
+
roles: [
|
|
267
|
+
defineRole({
|
|
268
|
+
role: 'patient',
|
|
269
|
+
description: 'Data to transform',
|
|
270
|
+
required: true,
|
|
271
|
+
expectedTypes: ['expression'],
|
|
272
|
+
svoPosition: 2,
|
|
273
|
+
sovPosition: 1,
|
|
274
|
+
}),
|
|
275
|
+
defineRole({
|
|
276
|
+
role: 'instrument',
|
|
277
|
+
description: 'Transform function, format string, or mapping',
|
|
278
|
+
required: true,
|
|
279
|
+
expectedTypes: ['expression', 'literal'],
|
|
280
|
+
svoPosition: 1,
|
|
281
|
+
sovPosition: 2,
|
|
282
|
+
markerOverride: {
|
|
283
|
+
en: 'with',
|
|
284
|
+
es: 'con',
|
|
285
|
+
ja: 'で',
|
|
286
|
+
ar: 'ب',
|
|
287
|
+
ko: '로',
|
|
288
|
+
zh: '用',
|
|
289
|
+
tr: 'ile',
|
|
290
|
+
fr: 'avec',
|
|
291
|
+
},
|
|
292
|
+
}),
|
|
293
|
+
],
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// =============================================================================
|
|
297
|
+
// HATEOAS Schemas (re-exported from dedicated file)
|
|
298
|
+
// =============================================================================
|
|
299
|
+
|
|
300
|
+
export {
|
|
301
|
+
enterSchema,
|
|
302
|
+
followSchema,
|
|
303
|
+
performSchema,
|
|
304
|
+
captureSchema,
|
|
305
|
+
hateoasSchemas,
|
|
306
|
+
} from './hateoas-schemas.js';
|
|
307
|
+
import { hateoasSchemas } from './hateoas-schemas.js';
|
|
308
|
+
|
|
309
|
+
// =============================================================================
|
|
310
|
+
// All Schemas
|
|
311
|
+
// =============================================================================
|
|
312
|
+
|
|
313
|
+
export const allSchemas = [
|
|
314
|
+
fetchSchema,
|
|
315
|
+
pollSchema,
|
|
316
|
+
streamSchema,
|
|
317
|
+
submitSchema,
|
|
318
|
+
transformSchema,
|
|
319
|
+
...hateoasSchemas,
|
|
320
|
+
];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Type stub for optional peer dependency siren-agent */
|
|
2
|
+
declare module 'siren-agent' {
|
|
3
|
+
export class OODAAgent {
|
|
4
|
+
constructor(url: string, opts: Record<string, unknown>);
|
|
5
|
+
run(): Promise<{
|
|
6
|
+
status: 'stopped' | 'error' | 'maxSteps';
|
|
7
|
+
reason: string;
|
|
8
|
+
result?: unknown;
|
|
9
|
+
steps: number;
|
|
10
|
+
history: Array<Record<string, unknown>>;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
export function compileWorkflow(steps: Array<Record<string, unknown>>): unknown;
|
|
14
|
+
}
|