@getrheo/flow-runtime 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/agentPrompt/index.d.ts +72 -0
  2. package/dist/agentPrompt/index.js +739 -0
  3. package/dist/agentPrompt/index.js.map +1 -0
  4. package/dist/aiFlowGenerationMerge.d.ts +32 -0
  5. package/dist/aiFlowGenerationMerge.js +120 -0
  6. package/dist/aiFlowGenerationMerge.js.map +1 -0
  7. package/dist/animations.d.ts +110 -0
  8. package/dist/animations.js +312 -0
  9. package/dist/animations.js.map +1 -0
  10. package/dist/assignment.d.ts +7 -0
  11. package/dist/assignment.js +25 -0
  12. package/dist/assignment.js.map +1 -0
  13. package/dist/brandGradient.d.ts +57 -0
  14. package/dist/brandGradient.js +137 -0
  15. package/dist/brandGradient.js.map +1 -0
  16. package/dist/brandGradientManifestIssues.d.ts +11 -0
  17. package/dist/brandGradientManifestIssues.js +302 -0
  18. package/dist/brandGradientManifestIssues.js.map +1 -0
  19. package/dist/buildFlowPreview.d.ts +7 -0
  20. package/dist/buildFlowPreview.js +81 -0
  21. package/dist/buildFlowPreview.js.map +1 -0
  22. package/dist/buttonVariantChrome.d.ts +26 -0
  23. package/dist/buttonVariantChrome.js +59 -0
  24. package/dist/buttonVariantChrome.js.map +1 -0
  25. package/dist/checkboxGlyphStyle.d.ts +31 -0
  26. package/dist/checkboxGlyphStyle.js +241 -0
  27. package/dist/checkboxGlyphStyle.js.map +1 -0
  28. package/dist/choiceOptionSelection.d.ts +11 -0
  29. package/dist/choiceOptionSelection.js +120 -0
  30. package/dist/choiceOptionSelection.js.map +1 -0
  31. package/dist/colorAlpha.d.ts +8 -0
  32. package/dist/colorAlpha.js +48 -0
  33. package/dist/colorAlpha.js.map +1 -0
  34. package/dist/counterLayer.d.ts +42 -0
  35. package/dist/counterLayer.js +95 -0
  36. package/dist/counterLayer.js.map +1 -0
  37. package/dist/decisionEval.d.ts +27 -0
  38. package/dist/decisionEval.js +197 -0
  39. package/dist/decisionEval.js.map +1 -0
  40. package/dist/dropShadow.d.ts +26 -0
  41. package/dist/dropShadow.js +76 -0
  42. package/dist/dropShadow.js.map +1 -0
  43. package/dist/emailPasswordAuthValidation.d.ts +16 -0
  44. package/dist/emailPasswordAuthValidation.js +25 -0
  45. package/dist/emailPasswordAuthValidation.js.map +1 -0
  46. package/dist/flowBuilderRules.d.ts +15 -0
  47. package/dist/flowBuilderRules.js +368 -0
  48. package/dist/flowBuilderRules.js.map +1 -0
  49. package/dist/flowGraph.d.ts +19 -0
  50. package/dist/flowGraph.js +373 -0
  51. package/dist/flowGraph.js.map +1 -0
  52. package/dist/hyperlinkLabel.d.ts +19 -0
  53. package/dist/hyperlinkLabel.js +232 -0
  54. package/dist/hyperlinkLabel.js.map +1 -0
  55. package/dist/index.d.ts +48 -0
  56. package/dist/index.js +4200 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/interpolateTemplate.d.ts +44 -0
  59. package/dist/interpolateTemplate.js +188 -0
  60. package/dist/interpolateTemplate.js.map +1 -0
  61. package/dist/layerRotate.d.ts +10 -0
  62. package/dist/layerRotate.js +9 -0
  63. package/dist/layerRotate.js.map +1 -0
  64. package/dist/layerTypography.d.ts +36 -0
  65. package/dist/layerTypography.js +68 -0
  66. package/dist/layerTypography.js.map +1 -0
  67. package/dist/layers.d.ts +69 -0
  68. package/dist/layers.js +257 -0
  69. package/dist/layers.js.map +1 -0
  70. package/dist/layout/index.d.ts +57 -0
  71. package/dist/layout/index.js +151 -0
  72. package/dist/layout/index.js.map +1 -0
  73. package/dist/manifestBillingSlice.d.ts +17 -0
  74. package/dist/manifestBillingSlice.js +102 -0
  75. package/dist/manifestBillingSlice.js.map +1 -0
  76. package/dist/prepareAiGeneratedScreen.d.ts +17 -0
  77. package/dist/prepareAiGeneratedScreen.js +99 -0
  78. package/dist/prepareAiGeneratedScreen.js.map +1 -0
  79. package/dist/publish-exports.json +166 -0
  80. package/dist/responsive/breakpoints.d.ts +34 -0
  81. package/dist/responsive/breakpoints.js +52 -0
  82. package/dist/responsive/breakpoints.js.map +1 -0
  83. package/dist/responsive/index.d.ts +8 -0
  84. package/dist/responsive/index.js +307 -0
  85. package/dist/responsive/index.js.map +1 -0
  86. package/dist/responsive/layerResolve.d.ts +43 -0
  87. package/dist/responsive/layerResolve.js +168 -0
  88. package/dist/responsive/layerResolve.js.map +1 -0
  89. package/dist/responsive/merge.d.ts +19 -0
  90. package/dist/responsive/merge.js +74 -0
  91. package/dist/responsive/merge.js.map +1 -0
  92. package/dist/responsive/previewSafeAreaInsets.d.ts +14 -0
  93. package/dist/responsive/previewSafeAreaInsets.js +24 -0
  94. package/dist/responsive/previewSafeAreaInsets.js.map +1 -0
  95. package/dist/responsive/screenContainerResolve.d.ts +11 -0
  96. package/dist/responsive/screenContainerResolve.js +122 -0
  97. package/dist/responsive/screenContainerResolve.js.map +1 -0
  98. package/dist/responsive/screenShellInsets.d.ts +11 -0
  99. package/dist/responsive/screenShellInsets.js +26 -0
  100. package/dist/responsive/screenShellInsets.js.map +1 -0
  101. package/dist/restingMotion.d.ts +167 -0
  102. package/dist/restingMotion.js +484 -0
  103. package/dist/restingMotion.js.map +1 -0
  104. package/dist/rheoAgentManifestMerge.d.ts +33 -0
  105. package/dist/rheoAgentManifestMerge.js +55 -0
  106. package/dist/rheoAgentManifestMerge.js.map +1 -0
  107. package/dist/scaleInputStyle.d.ts +35 -0
  108. package/dist/scaleInputStyle.js +77 -0
  109. package/dist/scaleInputStyle.js.map +1 -0
  110. package/dist/scaleValidation.d.ts +9 -0
  111. package/dist/scaleValidation.js +21 -0
  112. package/dist/scaleValidation.js.map +1 -0
  113. package/dist/stateMachine.d.ts +105 -0
  114. package/dist/stateMachine.js +674 -0
  115. package/dist/stateMachine.js.map +1 -0
  116. package/dist/stepResponse-BXgoZ7o-.d.ts +112 -0
  117. package/dist/textInputValidation.d.ts +14 -0
  118. package/dist/textInputValidation.js +46 -0
  119. package/dist/textInputValidation.js.map +1 -0
  120. package/dist/translationPlaceholders.d.ts +9 -0
  121. package/dist/translationPlaceholders.js +52 -0
  122. package/dist/translationPlaceholders.js.map +1 -0
  123. package/dist/validation.d.ts +31 -0
  124. package/dist/validation.js +233 -0
  125. package/dist/validation.js.map +1 -0
  126. package/package.json +242 -0
@@ -0,0 +1,674 @@
1
+ import { permissionCaptureFieldKey, appReviewCaptureFieldKey, oauthLoginResponseKey, emailPasswordAuthResponseKey, OS_PERMISSION_OUTCOME_END, OS_PERMISSION_OUTCOME_CONTINUE, isInputLayer } from '@getrheo/contracts/layers';
2
+ import '@getrheo/contracts/localized';
3
+ import { EXTERNAL_SURFACE_NO_NEXT } from '@getrheo/contracts/decisions';
4
+
5
+ // src/stateMachine/stepResponse.ts
6
+ var externalSurfaceResponseKey = (nodeId) => `surface_${nodeId}`;
7
+ var isEligibleConsumedDraft = (r) => {
8
+ switch (r.kind) {
9
+ case "text":
10
+ case "choice":
11
+ case "multiChoice":
12
+ case "scale":
13
+ case "cta":
14
+ case "carousel":
15
+ return true;
16
+ default:
17
+ return false;
18
+ }
19
+ };
20
+
21
+ // src/stateMachine/flowSession.ts
22
+ var findScreen = (manifest, screenId) => manifest.screens.find((s) => s.id === screenId);
23
+ var findExternalSurface = (manifest, nodeId) => (
24
+ // Older / hand-constructed manifests may omit `externalSurfaceNodes` entirely;
25
+ // treat that as "no surfaces" rather than crashing the state machine.
26
+ (manifest.externalSurfaceNodes ?? []).find((n) => n.id === nodeId)
27
+ );
28
+ var initFlowState = (manifest, sessionPartial) => ({
29
+ manifest,
30
+ currentScreenId: null,
31
+ pendingExternalSurface: null,
32
+ history: [],
33
+ responses: {},
34
+ session: {
35
+ locale: sessionPartial?.locale ?? manifest.defaultLocale,
36
+ platform: sessionPartial?.platform ?? "unknown",
37
+ sdkAttributes: sessionPartial?.sdkAttributes ?? {}
38
+ },
39
+ status: "idle",
40
+ startedAt: null,
41
+ completedAt: null
42
+ });
43
+ var walkLayers = (root, fn) => {
44
+ const visit = (l, depth) => {
45
+ fn(l, depth);
46
+ if (l.kind === "stack") l.children.forEach((c) => visit(c, depth + 1));
47
+ else if (l.kind === "carousel") l.slides.forEach((c) => visit(c, depth + 1));
48
+ else if (l.kind === "button") l.children.forEach((c) => visit(c, depth + 1));
49
+ else if (l.kind === "back_button") l.children.forEach((c) => visit(c, depth + 1));
50
+ else if (l.kind === "hyperlink") l.children.forEach((c) => visit(c, depth + 1));
51
+ else if (l.kind === "single_choice" || l.kind === "multiple_choice") {
52
+ l.children.forEach((c) => visit(c, depth + 1));
53
+ } else if (l.kind === "text_input" || l.kind === "scale_input") {
54
+ l.children?.forEach((c) => visit(c, depth + 1));
55
+ } else if (l.kind === "oauth_login") {
56
+ l.children.forEach((c) => visit(c, depth + 1));
57
+ } else if (l.kind === "oauth_provider" && l.variant === "custom") {
58
+ l.children.forEach((c) => visit(c, depth + 1));
59
+ } else if (l.kind === "email_password_auth") {
60
+ l.children.forEach((c) => visit(c, depth + 1));
61
+ } else if (l.kind === "email_password_field") {
62
+ l.children?.forEach((c) => visit(c, depth + 1));
63
+ } else if (l.kind === "email_password_submit") {
64
+ l.children.forEach((c) => visit(c, depth + 1));
65
+ }
66
+ };
67
+ visit(root, 0);
68
+ };
69
+ var walkScreen = (screen, fn) => {
70
+ if (screen.regions.header) walkLayers(screen.regions.header, fn);
71
+ walkLayers(screen.regions.body, fn);
72
+ if (screen.regions.footer) walkLayers(screen.regions.footer, fn);
73
+ };
74
+ var findInputLayer = (screen) => {
75
+ let found = null;
76
+ walkScreen(screen, (l) => {
77
+ if (!found && isInputLayer(l)) found = l;
78
+ });
79
+ return found;
80
+ };
81
+ var findManualSubmitInputLayer = (screen) => {
82
+ const input = findInputLayer(screen);
83
+ if (!input) return null;
84
+ if (input.kind === "multiple_choice" || input.kind === "text_input" || input.kind === "scale_input") {
85
+ return input;
86
+ }
87
+ return null;
88
+ };
89
+ var findLayerById = (screen, id) => {
90
+ let found = null;
91
+ walkScreen(screen, (l) => {
92
+ if (!found && l.id === id) found = l;
93
+ });
94
+ return found;
95
+ };
96
+
97
+ // src/decisionEval.ts
98
+ var findDecisionNode = (manifest, id) => (manifest.decisionNodes ?? []).find((d) => d.id === id);
99
+ var stableSerialize = (value) => {
100
+ if (value === null || typeof value !== "object") return JSON.stringify(value);
101
+ if (Array.isArray(value)) return `[${value.map(stableSerialize).join(",")}]`;
102
+ const keys = Object.keys(value).sort();
103
+ const parts = keys.map((k) => `${JSON.stringify(k)}:${stableSerialize(value[k])}`);
104
+ return `{${parts.join(",")}}`;
105
+ };
106
+ var digestDecisionExpression = (expr) => {
107
+ const s = stableSerialize(expr);
108
+ let h = 5381;
109
+ for (let i = 0; i < s.length; i += 1) {
110
+ h = h * 33 ^ s.charCodeAt(i);
111
+ }
112
+ return `d${(h >>> 0).toString(16)}`;
113
+ };
114
+ var responseForField = (fieldKey, responses) => responses[fieldKey];
115
+ var normalizeResponseValue = (r) => {
116
+ if (!r || typeof r !== "object") return void 0;
117
+ const o = r;
118
+ switch (o.kind) {
119
+ case "choice":
120
+ return typeof o.choiceId === "string" ? o.choiceId : void 0;
121
+ case "multiChoice":
122
+ return Array.isArray(o.choiceIds) ? o.choiceIds : void 0;
123
+ case "text":
124
+ return typeof o.value === "string" ? o.value : void 0;
125
+ case "scale":
126
+ return typeof o.value === "number" ? o.value : void 0;
127
+ case "checkbox":
128
+ return typeof o.value === "boolean" ? o.value : void 0;
129
+ default:
130
+ return void 0;
131
+ }
132
+ };
133
+ var normalizeScalarForStringPred = (raw) => {
134
+ if (raw === void 0 || raw === null) return void 0;
135
+ if (typeof raw === "string") return raw;
136
+ if (typeof raw === "number" && Number.isFinite(raw)) return String(raw);
137
+ return void 0;
138
+ };
139
+ var normalizeNumber = (raw) => {
140
+ if (typeof raw !== "number" || !Number.isFinite(raw)) return void 0;
141
+ return raw;
142
+ };
143
+ var normalizeChoiceId = (raw) => typeof raw === "string" && raw.length > 0 ? raw : void 0;
144
+ var normalizeChoiceIds = (raw) => {
145
+ if (!Array.isArray(raw)) return void 0;
146
+ const ids = raw.filter((x) => typeof x === "string" && x.length > 0);
147
+ return ids;
148
+ };
149
+ var normalizeBoolean = (raw) => {
150
+ if (typeof raw === "boolean") return raw;
151
+ if (typeof raw === "number" && Number.isFinite(raw)) return raw !== 0;
152
+ if (typeof raw === "string") {
153
+ const s = raw.trim().toLowerCase();
154
+ if (s === "true" || s === "1" || s === "yes") return true;
155
+ if (s === "false" || s === "0" || s === "no") return false;
156
+ }
157
+ return void 0;
158
+ };
159
+ var resolveVariableValue = (variable, ctx) => {
160
+ if (variable.kind === "builtin") {
161
+ if (variable.name === "locale") return ctx.locale;
162
+ return ctx.platform;
163
+ }
164
+ if (variable.kind === "sdk") return ctx.sdkAttributes[variable.key];
165
+ const r = responseForField(variable.fieldKey, ctx.responses);
166
+ return normalizeResponseValue(r);
167
+ };
168
+ var evalStringPred = (left, pred) => {
169
+ switch (pred.op) {
170
+ case "eq":
171
+ return left === pred.value;
172
+ case "neq":
173
+ return left !== pred.value;
174
+ case "contains":
175
+ return left.includes(pred.value);
176
+ default:
177
+ return false;
178
+ }
179
+ };
180
+ var evalNumberPred = (left, pred) => {
181
+ switch (pred.op) {
182
+ case "eq":
183
+ return left === pred.value;
184
+ case "neq":
185
+ return left !== pred.value;
186
+ case "lt":
187
+ return left < pred.value;
188
+ case "lte":
189
+ return left <= pred.value;
190
+ case "gt":
191
+ return left > pred.value;
192
+ case "gte":
193
+ return left >= pred.value;
194
+ default:
195
+ return false;
196
+ }
197
+ };
198
+ var evalChoicePred = (choiceId, pred) => {
199
+ if (pred.op === "eq") return choiceId === pred.optionId;
200
+ return pred.optionIds.includes(choiceId);
201
+ };
202
+ var setIntersect = (a, b) => {
203
+ const bs = new Set(b);
204
+ return a.filter((x) => bs.has(x));
205
+ };
206
+ var evalBooleanPred = (left, pred) => {
207
+ if (pred.op === "eq") return left === pred.value;
208
+ return left !== pred.value;
209
+ };
210
+ var evalMultiPred = (selected, pred) => {
211
+ const required = pred.optionIds;
212
+ switch (pred.op) {
213
+ case "intersects":
214
+ return setIntersect(selected, required).length > 0;
215
+ case "contains_all": {
216
+ const sel = new Set(selected);
217
+ return required.every((id) => sel.has(id));
218
+ }
219
+ case "subset_of": {
220
+ const allow = new Set(required);
221
+ return selected.every((id) => allow.has(id));
222
+ }
223
+ default:
224
+ return false;
225
+ }
226
+ };
227
+ var evaluateDecisionExpression = (expr, ctx) => {
228
+ if (expr.kind === "empty") return false;
229
+ if (expr.kind === "group") {
230
+ if (expr.op === "and") {
231
+ for (const c of expr.children) {
232
+ if (!evaluateDecisionExpression(c, ctx)) return false;
233
+ }
234
+ return true;
235
+ }
236
+ for (const c of expr.children) {
237
+ if (evaluateDecisionExpression(c, ctx)) return true;
238
+ }
239
+ return false;
240
+ }
241
+ const raw = resolveVariableValue(expr.variable, ctx);
242
+ const { predicate } = expr;
243
+ switch (predicate.type) {
244
+ case "string": {
245
+ const s = normalizeScalarForStringPred(raw);
246
+ if (s === void 0) return false;
247
+ return evalStringPred(s, predicate.pred);
248
+ }
249
+ case "number": {
250
+ const n = normalizeNumber(raw);
251
+ if (n === void 0) return false;
252
+ return evalNumberPred(n, predicate.pred);
253
+ }
254
+ case "choice": {
255
+ const id = normalizeChoiceId(raw);
256
+ if (!id) return false;
257
+ return evalChoicePred(id, predicate.pred);
258
+ }
259
+ case "multi": {
260
+ const ids = normalizeChoiceIds(raw);
261
+ if (!ids) return false;
262
+ return evalMultiPred(ids, predicate.pred);
263
+ }
264
+ case "boolean": {
265
+ const b = normalizeBoolean(raw);
266
+ if (b === void 0) return false;
267
+ return evalBooleanPred(b, predicate.pred);
268
+ }
269
+ default:
270
+ return false;
271
+ }
272
+ };
273
+ var evaluateDecisionNode = (node, ctx) => {
274
+ for (const c of node.cases) {
275
+ if (evaluateDecisionExpression(c.expression, ctx)) {
276
+ return {
277
+ matchedCaseId: c.id,
278
+ next: c.next,
279
+ clauseDigest: digestDecisionExpression(c.expression)
280
+ };
281
+ }
282
+ }
283
+ return {
284
+ matchedCaseId: null,
285
+ next: node.elseNext,
286
+ clauseDigest: "else"
287
+ };
288
+ };
289
+
290
+ // src/stateMachine/graphLanding.ts
291
+ var resolveOsPermissionDestination = (screen, response) => {
292
+ const layer = findLayerById(screen, response.layerId);
293
+ if (!layer || layer.kind !== "button" || layer.action.kind !== "request_os_permission")
294
+ return null;
295
+ if (layer.action.permissionKey !== response.permissionKey) return null;
296
+ const target = layer.action.outcomes[response.outcome];
297
+ if (target === OS_PERMISSION_OUTCOME_END) return null;
298
+ if (target === OS_PERMISSION_OUTCOME_CONTINUE) return screen.next.default ?? null;
299
+ return target;
300
+ };
301
+ var resolveNextScreenId = (screen, response) => {
302
+ if (response.kind === "screen_commit") {
303
+ return resolveNextScreenId(screen, response.primary);
304
+ }
305
+ if (response.kind === "go_to_screen") return response.screenId;
306
+ if (response.kind === "permission_outcome") {
307
+ const nextId = resolveOsPermissionDestination(screen, response);
308
+ return nextId ?? screen.next.default ?? null;
309
+ }
310
+ if (response.kind === "app_review_outcome") {
311
+ const layer = findLayerById(screen, response.layerId);
312
+ if (!layer || layer.kind !== "button" || layer.action.kind !== "request_app_review") {
313
+ return screen.next.default ?? null;
314
+ }
315
+ return screen.next.default ?? null;
316
+ }
317
+ if (response.kind === "oauth_login_resolve") {
318
+ return screen.next.default ?? null;
319
+ }
320
+ if (response.kind === "email_password_auth_resolve") {
321
+ return screen.next.default ?? null;
322
+ }
323
+ const input = findInputLayer(screen);
324
+ if (input && (input.kind === "single_choice" || input.kind === "multiple_choice") && input.branching.enabled) {
325
+ if (response.kind === "choice") {
326
+ const m = input.branching.conditions.find((c) => c.choiceId === response.choiceId);
327
+ if (m) return m.goTo;
328
+ } else if (response.kind === "multiChoice") {
329
+ const m = input.branching.conditions.find((c) => response.choiceIds.includes(c.choiceId));
330
+ if (m) return m.goTo;
331
+ }
332
+ }
333
+ return screen.next.default ?? null;
334
+ };
335
+ var resolveThroughGraph = (manifest, cursor, responses, session, onDecisionEvaluated) => {
336
+ let cur = cursor;
337
+ const evalCtx = {
338
+ locale: session.locale,
339
+ platform: session.platform,
340
+ sdkAttributes: session.sdkAttributes,
341
+ responses
342
+ };
343
+ while (cur) {
344
+ const dn = findDecisionNode(manifest, cur);
345
+ if (!dn) break;
346
+ const evalResult = evaluateDecisionNode(dn, evalCtx);
347
+ onDecisionEvaluated?.({
348
+ decisionNodeId: dn.id,
349
+ matchedCaseId: evalResult.matchedCaseId,
350
+ clauseDigest: evalResult.clauseDigest
351
+ });
352
+ cur = evalResult.next;
353
+ if (cur == null) break;
354
+ }
355
+ if (cur == null) return { kind: "end" };
356
+ if (findExternalSurface(manifest, cur)) return { kind: "surface", nodeId: cur };
357
+ return { kind: "screen", screenId: cur };
358
+ };
359
+ var responseKeyFor = (screen, response) => {
360
+ if (response.kind === "text" || response.kind === "choice" || response.kind === "multiChoice" || response.kind === "scale" || response.kind === "checkbox") {
361
+ const input = findInputLayer(screen);
362
+ if (input) return input.fieldKey;
363
+ }
364
+ if (response.kind === "permission_outcome") return permissionCaptureFieldKey(response.permissionKey);
365
+ if (response.kind === "app_review_outcome") return appReviewCaptureFieldKey(response.layerId);
366
+ if (response.kind === "checkbox") return response.fieldKey;
367
+ if (response.kind === "oauth_login_resolve") return oauthLoginResponseKey(response.layerId);
368
+ if (response.kind === "email_password_auth_resolve") {
369
+ return emailPasswordAuthResponseKey(response.layerId);
370
+ }
371
+ return screen.id;
372
+ };
373
+ var applyGraphLanding = (base, landing, nextResponses, now) => {
374
+ if (landing.kind === "end") {
375
+ return {
376
+ ...base,
377
+ responses: nextResponses,
378
+ currentScreenId: null,
379
+ pendingExternalSurface: null,
380
+ status: "completed",
381
+ completedAt: now
382
+ };
383
+ }
384
+ if (landing.kind === "surface") {
385
+ return {
386
+ ...base,
387
+ responses: nextResponses,
388
+ currentScreenId: null,
389
+ pendingExternalSurface: { nodeId: landing.nodeId },
390
+ history: [...base.history, landing.nodeId]
391
+ };
392
+ }
393
+ return {
394
+ ...base,
395
+ responses: nextResponses,
396
+ currentScreenId: landing.screenId,
397
+ pendingExternalSurface: null,
398
+ history: [...base.history, landing.screenId]
399
+ };
400
+ };
401
+ var startFlow = (state, second) => {
402
+ const opts = typeof second === "string" ? { now: second } : second ?? {};
403
+ const now = opts.now ?? (/* @__PURE__ */ new Date()).toISOString();
404
+ const entry = state.manifest.entryScreenId;
405
+ if (entry == null) {
406
+ return {
407
+ ...state,
408
+ status: "idle",
409
+ currentScreenId: null,
410
+ pendingExternalSurface: null,
411
+ history: [],
412
+ startedAt: null,
413
+ completedAt: null
414
+ };
415
+ }
416
+ const landing = resolveThroughGraph(
417
+ state.manifest,
418
+ entry,
419
+ {},
420
+ {
421
+ ...state.session
422
+ },
423
+ opts.onDecisionEvaluated
424
+ );
425
+ if (landing.kind === "end") {
426
+ return {
427
+ ...state,
428
+ status: "completed",
429
+ currentScreenId: null,
430
+ pendingExternalSurface: null,
431
+ history: [entry],
432
+ startedAt: now,
433
+ completedAt: now
434
+ };
435
+ }
436
+ if (landing.kind === "surface") {
437
+ return {
438
+ ...state,
439
+ status: "running",
440
+ currentScreenId: null,
441
+ pendingExternalSurface: { nodeId: landing.nodeId },
442
+ history: [landing.nodeId],
443
+ startedAt: now
444
+ };
445
+ }
446
+ return {
447
+ ...state,
448
+ status: "running",
449
+ currentScreenId: landing.screenId,
450
+ pendingExternalSurface: null,
451
+ history: [landing.screenId],
452
+ startedAt: now
453
+ };
454
+ };
455
+ var submitResponse = (state, response, third) => {
456
+ const opts = typeof third === "string" ? { now: third } : third ?? {};
457
+ const now = opts.now ?? (/* @__PURE__ */ new Date()).toISOString();
458
+ if (state.status !== "running") return state;
459
+ if (response.kind === "external_surface_outcome") {
460
+ const pending = state.pendingExternalSurface;
461
+ if (!pending || pending.nodeId !== response.nodeId) return state;
462
+ const surface = findExternalSurface(state.manifest, pending.nodeId);
463
+ if (!surface) return state;
464
+ const nextSession = response.sdkKeyPatch ? {
465
+ ...state.session,
466
+ sdkAttributes: { ...state.session.sdkAttributes, ...response.sdkKeyPatch }
467
+ } : state.session;
468
+ const target = surface.outcomes[response.outcome] ?? surface.fallback;
469
+ const nextResponses2 = {
470
+ ...state.responses,
471
+ [externalSurfaceResponseKey(pending.nodeId)]: response
472
+ };
473
+ if (target === EXTERNAL_SURFACE_NO_NEXT) {
474
+ return {
475
+ ...state,
476
+ session: nextSession,
477
+ responses: nextResponses2,
478
+ pendingExternalSurface: null,
479
+ currentScreenId: null,
480
+ status: "completed",
481
+ completedAt: now
482
+ };
483
+ }
484
+ const landing2 = resolveThroughGraph(
485
+ state.manifest,
486
+ target,
487
+ nextResponses2,
488
+ nextSession,
489
+ opts.onDecisionEvaluated
490
+ );
491
+ return applyGraphLanding(
492
+ { ...state, session: nextSession },
493
+ landing2,
494
+ nextResponses2,
495
+ now
496
+ );
497
+ }
498
+ if (!state.currentScreenId) return state;
499
+ const screen = findScreen(state.manifest, state.currentScreenId);
500
+ if (!screen) return state;
501
+ if (response.kind === "screen_commit") {
502
+ const mergedResponses = { ...state.responses };
503
+ for (const [fk, value] of Object.entries(response.checkboxValues)) {
504
+ mergedResponses[fk] = { kind: "checkbox", fieldKey: fk, value };
505
+ }
506
+ if (response.capturedDraft) {
507
+ mergedResponses[responseKeyFor(screen, response.capturedDraft)] = response.capturedDraft;
508
+ }
509
+ return submitResponse({ ...state, responses: mergedResponses }, response.primary, opts);
510
+ }
511
+ if (response.kind === "go_back") {
512
+ const fallback = response.fallbackScreenId;
513
+ if (state.history.length > 1) {
514
+ const nextHistory = state.history.slice(0, -1);
515
+ const prevId = nextHistory[nextHistory.length - 1];
516
+ if (!prevId) return state;
517
+ return {
518
+ ...state,
519
+ currentScreenId: prevId,
520
+ history: nextHistory
521
+ };
522
+ }
523
+ if (fallback && findScreen(state.manifest, fallback)) {
524
+ return {
525
+ ...state,
526
+ currentScreenId: fallback,
527
+ history: [fallback]
528
+ };
529
+ }
530
+ return state;
531
+ }
532
+ if (response.kind === "oauth_login_resolve" && !response.success) {
533
+ const key2 = oauthLoginResponseKey(response.layerId);
534
+ return {
535
+ ...state,
536
+ responses: { ...state.responses, [key2]: response }
537
+ };
538
+ }
539
+ if (response.kind === "email_password_auth_resolve" && !response.success) {
540
+ const key2 = emailPasswordAuthResponseKey(response.layerId);
541
+ return {
542
+ ...state,
543
+ responses: { ...state.responses, [key2]: response }
544
+ };
545
+ }
546
+ if (response.kind === "end_flow") {
547
+ const nextResponses2 = { ...state.responses };
548
+ if (response.consumedDraft) {
549
+ nextResponses2[responseKeyFor(screen, response.consumedDraft)] = response.consumedDraft;
550
+ }
551
+ nextResponses2[responseKeyFor(screen, { kind: "end_flow" })] = { kind: "end_flow" };
552
+ return {
553
+ ...state,
554
+ responses: nextResponses2,
555
+ currentScreenId: null,
556
+ status: "completed",
557
+ completedAt: now
558
+ };
559
+ }
560
+ if (response.kind === "skip") {
561
+ const nextResponses2 = { ...state.responses };
562
+ const manualInput = findManualSubmitInputLayer(screen);
563
+ if (manualInput) {
564
+ nextResponses2[manualInput.fieldKey] = { kind: "bypass_input", via: "skip" };
565
+ }
566
+ nextResponses2[responseKeyFor(screen, { kind: "skip" })] = { kind: "skip" };
567
+ const nextRaw2 = resolveNextScreenId(screen, { kind: "skip" });
568
+ const landing2 = resolveThroughGraph(
569
+ state.manifest,
570
+ nextRaw2,
571
+ nextResponses2,
572
+ state.session,
573
+ opts.onDecisionEvaluated
574
+ );
575
+ return applyGraphLanding(state, landing2, nextResponses2, now);
576
+ }
577
+ const key = responseKeyFor(screen, response);
578
+ const nextResponses = { ...state.responses, [key]: response };
579
+ if (response.kind === "go_to_screen") {
580
+ const manualInput = findManualSubmitInputLayer(screen);
581
+ if (manualInput) {
582
+ nextResponses[manualInput.fieldKey] = { kind: "bypass_input", via: "go_to_screen" };
583
+ }
584
+ }
585
+ const nextRaw = resolveNextScreenId(screen, response);
586
+ const landing = resolveThroughGraph(
587
+ state.manifest,
588
+ nextRaw,
589
+ nextResponses,
590
+ state.session,
591
+ opts.onDecisionEvaluated
592
+ );
593
+ return applyGraphLanding(state, landing, nextResponses, now);
594
+ };
595
+
596
+ // src/stateMachine/flowTerminal.ts
597
+ var TERMINAL_EXPORT_AUTH_RESPONSE_KEY_PREFIXES = ["oauth:", "email_pw:"];
598
+ var isAuthTerminalExportResponseKey = (key) => TERMINAL_EXPORT_AUTH_RESPONSE_KEY_PREFIXES.some((prefix) => key.startsWith(prefix));
599
+ var stripAuthResponsesForTerminalExport = (responses) => {
600
+ const out = {};
601
+ for (const [k, v] of Object.entries(responses)) {
602
+ if (isAuthTerminalExportResponseKey(k)) continue;
603
+ out[k] = v;
604
+ }
605
+ return out;
606
+ };
607
+ var stepResponseToCompletionValue = (r) => {
608
+ if (r.kind === "screen_commit") return void 0;
609
+ switch (r.kind) {
610
+ case "choice":
611
+ return r.choiceId;
612
+ case "multiChoice":
613
+ return r.choiceIds;
614
+ case "text":
615
+ return { value: r.value, classification: r.classification };
616
+ case "scale":
617
+ return r.value;
618
+ case "checkbox":
619
+ return r.value;
620
+ case "cta":
621
+ return r.action;
622
+ case "carousel":
623
+ return "carousel";
624
+ case "end_flow":
625
+ return "end_flow";
626
+ case "skip":
627
+ return "skip";
628
+ case "permission_outcome":
629
+ return r.outcome;
630
+ case "app_review_outcome":
631
+ return r.outcome;
632
+ case "oauth_login_resolve":
633
+ return {
634
+ success: r.success,
635
+ customerExternalId: r.customerExternalId,
636
+ provider: r.provider
637
+ };
638
+ case "email_password_auth_resolve":
639
+ return {
640
+ success: r.success,
641
+ mode: r.mode,
642
+ email: r.email
643
+ };
644
+ case "bypass_input":
645
+ return { bypassed: true, via: r.via };
646
+ case "external_surface_outcome":
647
+ return { outcome: r.outcome };
648
+ case "go_to_screen":
649
+ return { goToScreen: r.screenId };
650
+ case "go_back":
651
+ return void 0;
652
+ default: {
653
+ const _never = r;
654
+ return _never;
655
+ }
656
+ }
657
+ };
658
+ var buildCompletionResponses = (state) => {
659
+ const out = {};
660
+ for (const [key, r] of Object.entries(state.responses)) {
661
+ const v = stepResponseToCompletionValue(r);
662
+ if (v !== void 0) out[key] = v;
663
+ }
664
+ return out;
665
+ };
666
+ var abandonFlow = (state, now = (/* @__PURE__ */ new Date()).toISOString()) => ({
667
+ ...state,
668
+ status: "abandoned",
669
+ completedAt: now
670
+ });
671
+
672
+ export { abandonFlow, applyGraphLanding, buildCompletionResponses, externalSurfaceResponseKey, findExternalSurface, findScreen, initFlowState, isAuthTerminalExportResponseKey, isEligibleConsumedDraft, resolveNextScreenId, resolveThroughGraph, responseKeyFor, startFlow, stepResponseToCompletionValue, stripAuthResponsesForTerminalExport, submitResponse };
673
+ //# sourceMappingURL=stateMachine.js.map
674
+ //# sourceMappingURL=stateMachine.js.map