jsfe 1.39.1 → 1.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"form-client.d.ts","sourceRoot":"","sources":["../../src/forms/form-client.js"],"names":[],"mappings":"AA2BA,iGAAiG;AACjG;;;;;
|
|
1
|
+
{"version":3,"file":"form-client.d.ts","sourceRoot":"","sources":["../../src/forms/form-client.js"],"names":[],"mappings":"AA2BA,iGAAiG;AACjG;;;;;SA0EC;AAED,+GAA+G;AAC/G;;;;SAgCC;AAED;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BC;AArKD,qCAAsC,eAAe,CAAC"}
|
|
@@ -40,12 +40,13 @@ export function projectForm(session, flows) {
|
|
|
40
40
|
const { state: root, context } = pending, cargo = session.cargo, language = session.language || 'en';
|
|
41
41
|
// Both the code field and its free-text fallback can contain the one-time code.
|
|
42
42
|
const collectingOtp = session.flowStacks.flat().some(frame => frame.flowId === 'get-and-validate-otp-code');
|
|
43
|
+
let askedShown = false;
|
|
43
44
|
const fields = (specs, state, prefix = '', depth = 0) => {
|
|
44
45
|
if (depth > 16)
|
|
45
46
|
return [];
|
|
46
47
|
const out = [];
|
|
47
48
|
for (const input of specs || []) {
|
|
48
|
-
if (!safe(input.name) || input.form_client === false || input.
|
|
49
|
+
if (!safe(input.name) || input.form_client === false || input.bind || input.confirmation || !formInputApplies(input, state.values, cargo, state))
|
|
49
50
|
continue;
|
|
50
51
|
const path = prefix + input.name;
|
|
51
52
|
const required = input.required_when === undefined || formInputApplies({ when: input.required_when }, state.values, cargo, state);
|
|
@@ -57,8 +58,10 @@ export function projectForm(session, flows) {
|
|
|
57
58
|
// An alternative is a group constraint, not several individually required fields.
|
|
58
59
|
const members = fields(input.any_of, state, prefix, depth + 1).map(field => ({ ...field, required: false }));
|
|
59
60
|
const groupLabel = language === 'es' ? input.label_es || input.label : input.label;
|
|
61
|
+
if (members.length && isCurrent)
|
|
62
|
+
askedShown = true;
|
|
60
63
|
if (members.length)
|
|
61
|
-
out.push({ name: input.name, path, kind: 'alternatives', label: groupLabel || '', required, exclusive: input.exclusive === true, fields: members });
|
|
64
|
+
out.push({ name: input.name, path, kind: 'alternatives', label: groupLabel || '', required, exclusive: input.exclusive === true, ...(isCurrent ? { current: true } : {}), fields: members });
|
|
62
65
|
}
|
|
63
66
|
else if (input.form && input.schema) {
|
|
64
67
|
if (input.prepare && !state.prepared?.[input.name])
|
|
@@ -67,8 +70,10 @@ export function projectForm(session, flows) {
|
|
|
67
70
|
const snapshot = state.childResults?.[input.name];
|
|
68
71
|
const virtual = child || { values: state.values?.[input.name] || {}, data: snapshot?.data || {}, prepared: snapshot?.prepared || {}, errors: {} };
|
|
69
72
|
const nested = fields(child?.specs || input.schema.inputs, virtual, path + '.', depth + 1);
|
|
73
|
+
if (nested.length && isCurrent)
|
|
74
|
+
askedShown = true;
|
|
70
75
|
if (nested.length)
|
|
71
|
-
out.push({ name: input.name, path, kind: 'group', label: label(input, language), required, fields: nested });
|
|
76
|
+
out.push({ name: input.name, path, kind: 'group', label: label(input, language), required, ...(isCurrent ? { current: true } : {}), fields: nested });
|
|
72
77
|
}
|
|
73
78
|
else if (input.profile) {
|
|
74
79
|
const profile = input.profile;
|
|
@@ -103,12 +108,22 @@ export function projectForm(session, flows) {
|
|
|
103
108
|
field.value = state.values[input.name];
|
|
104
109
|
if (state.errors?.[input.name])
|
|
105
110
|
field.error = String(state.errors[input.name]);
|
|
111
|
+
// The field the conversation is asking for now, so a client can point at it on a redrawn form.
|
|
112
|
+
if (isCurrent) {
|
|
113
|
+
field.current = true;
|
|
114
|
+
askedShown = true;
|
|
115
|
+
}
|
|
106
116
|
out.push(field);
|
|
107
117
|
}
|
|
108
118
|
}
|
|
109
119
|
return out;
|
|
110
120
|
};
|
|
111
121
|
const projected = fields(root.specs, root);
|
|
122
|
+
// A card that cannot take the answer being asked for (a chat-only or not yet prepared field) is not drawn: the
|
|
123
|
+
// question is answered in chat, never beside a form that has no place for it.
|
|
124
|
+
const asked = context.names?.length || context.current;
|
|
125
|
+
if (asked && !askedShown)
|
|
126
|
+
return null;
|
|
112
127
|
return projected.length ? { version: 1, form: root.id, language, fields: projected } : null;
|
|
113
128
|
}
|
|
114
129
|
/** Host preflight: call before updateActivity. Unknown paths and malformed envelopes never enter execution. */
|
package/dist/runtime-identity.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const JSFE_RUNTIME_FINGERPRINT = "sha256:
|
|
1
|
+
export const JSFE_RUNTIME_FINGERPRINT = "sha256:16e28f7248d2a884103079326baaf8d4f9aaf65486e99a8b3611bd248d646439";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsfe",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.40.1",
|
|
4
4
|
"description": "TypeScript workflow engine for conversational/automation apps: multi-flow orchestration, interrupt/resume, stack-based control, robust errors, and flexible tool/REST integration.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Ron Pinkas",
|