jsfe 1.13.0 → 1.13.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":"identity-flows.d.ts","sourceRoot":"","sources":["../../src/forms/identity-flows.js"],"names":[],"mappings":"AA2BA,+GAA+G;AAC/G,oFAOC;AAQD,wFAAwF;AACxF,iDAGC;AACD,6CAMC;AACD,qHAQC;AAMD,4EAKC;AAoFD,4DAKC;
|
|
1
|
+
{"version":3,"file":"identity-flows.d.ts","sourceRoot":"","sources":["../../src/forms/identity-flows.js"],"names":[],"mappings":"AA2BA,+GAA+G;AAC/G,oFAOC;AAQD,wFAAwF;AACxF,iDAGC;AACD,6CAMC;AACD,qHAQC;AAMD,4EAKC;AAoFD,4DAKC;AAqFD,8EAGC;AA4BD,4FAA4F;AAC5F;;;;EAOC;AAQD,0BAAmI"}
|
|
@@ -191,6 +191,7 @@ const OTP_WORDS = {
|
|
|
191
191
|
other: ['otra cuenta', 'otro número', 'otro numero', 'cuenta diferente', 'another account', 'different account', 'other account', 'another number', 'different number', 'not my account', 'no es mi cuenta', 'número de cuenta', 'numero de cuenta', 'account number'],
|
|
192
192
|
// the offered OTRA CUENTA / ANOTHER ACCOUNT said by its first word, as the whole answer (prod 2026-10-25 00:19: "Otra")
|
|
193
193
|
other_alone: ['otra', 'otro', 'another', 'other'],
|
|
194
|
+
email: ['email', 'e-mail', 'e mail', 'emails', 'correo', 'correos', 'correo electrónico', 'correo electronico', 'imeil'],
|
|
194
195
|
resend: ['resend', 'send again', 'send it again', 'not received', 'never received', 'did not receive', 'didn t receive', 'didn t get', 'haven t received', 'nothing came', 'no code', 'no text', 'no llegó', 'no llego', 'no llega', 'no ha llegado', 'no me llegó', 'no me llego', 'no le llegó', 'no le llego', 'no me ha llegado', 'no recibí', 'no recibi', 'no lo recibí', 'no lo recibi', 'no tengo el código', 'no tengo el codigo', 'no lo tengo', 'no alcancé', 'no alcance', 'mándame el código', 'mandame el codigo', 'envíame el código', 'enviame el codigo', 'reenviar', 'reenvíe', 'reenvie'],
|
|
195
196
|
later: ['driving', 'i am driving', 'i m busy', 'im busy', 'not now', 'later', 'call me later', 'call back', 'cant right now', 'can t right now', 'can t now', 'cannot right now', 'manejando', 'conduciendo', 'estoy manejando', 'voy manejando', 'ahora no', 'ahora no puedo', 'no puedo ahora', 'más tarde', 'mas tarde', 'estoy ocupado', 'estoy ocupada'],
|
|
196
197
|
noPhone: ['don t have that phone', 'don t have that number', 'don t have that phone anymore', 'don t have the phone', 'not my number anymore', 'not my phone anymore', 'that s an old number', 'old number', 'changed my number', 'changed my phone', 'lost my phone', 'no tengo ese teléfono', 'no tengo ese telefono', 'no tengo ese número', 'no tengo ese numero', 'ya no tengo ese', 'ya no tengo el teléfono', 'ya no tengo el telefono', 'ya no es mi número', 'ya no es mi numero', 'número viejo', 'numero viejo', 'cambié de número', 'cambie de numero', 'cambié mi número', 'perdí mi teléfono', 'perdi mi telefono', 'don t have a phone', 'don t have phone', 'don t have my phone', 'don t have a cell', 'don t have the cell', 'don t have my cell', 'don t have a cell phone', 'don t have access to that phone', 'don t have access to the phone', 'no tengo teléfono', 'no tengo telefono', 'no tengo celular', 'no tengo el celular', 'no tengo mi teléfono', 'no tengo mi telefono', 'no tengo mi celular', 'no tengo un teléfono', 'no tengo un telefono', 'no tengo acceso a ese teléfono', 'no tengo acceso a ese telefono']
|
|
@@ -212,6 +213,9 @@ const validateCode = worker('validate-otp-code', 'ValidateOtpCode', 'Validate a
|
|
|
212
213
|
cases('otp_response', {
|
|
213
214
|
'condition: normalized_otp_code.length === 6': { id: 'otp_check_tool', type: 'CALL-TOOL', tool: 'validate-otp', variable: 'otp_validation_result', args: { otp: '{{normalized_otp_code}}', container: '{{cargo}}' }, onFail: call('otp_check_failed', 'get-and-validate-otp-code', undefined, 'replace') },
|
|
214
215
|
'condition: wants_other_account': call('otp_change_account', 'authenticate-user', { cell_number: '', email: '', retrying: true, declined_caller: true }, 'replace'),
|
|
216
|
+
// Email asked for at a code sent by text: authentication is an input step, so the contact question is asked again
|
|
217
|
+
// (without the caller-ID offer) and the caller gives the email; a code sent by email keeps "no me llegó el correo" a resend.
|
|
218
|
+
'condition: !!cargo.otp_cell_number && normalized_otp_code.length !== 6 && matchesChoice(user_choice,otp_phrases.email)': call('otp_use_email', 'authenticate-user', { cell_number: '', email: '', retrying: true, declined_caller: true }, 'replace'),
|
|
215
219
|
"condition: isExitRequest(user_choice)": call('otp_exit', '{{otp_cancel}}', undefined, 'reboot'),
|
|
216
220
|
"condition: isAnswer(user_choice,'agent')": call('otp_agent', 'live-agent-requested', undefined, 'reboot'),
|
|
217
221
|
"condition: isAnswer(user_choice,'text')": call('otp_text', 'switch-to-text', undefined, 'reboot'),
|
|
@@ -248,7 +252,7 @@ for (const flow of [auth, validateCode]) {
|
|
|
248
252
|
flow.steps.unshift(...otpMenuMessages.map(([name, value]) => set(name, name, value.includes('{{') ? value : JSON.stringify(value))));
|
|
249
253
|
}
|
|
250
254
|
const retryParams = [param('error_message', 'Failure sentence'), param('error_message_es', 'Spanish failure sentence'), param('retry_flow', 'Retry destination'), param('cancel_flow', 'Exit destination'), param('capture_patterns', 'Declared contact capture readers', 'array'), param('retry_call_type', 'reboot or replace'), param('allow_code_entry', 'Accept the active six-digit challenge', 'boolean'), param('question', 'Retry question'), param('question_es', 'Spanish retry question'), param('caller_outcome', 'Unresolved outcome'), param('caller_reason', 'Unresolved reason'), param('parent_form', 'Owning task FORM instance'), param('contact_options', 'Contact field protocol declaration', 'object')];
|
|
251
|
-
const retry = worker('generic-retry-with-options', 'GenericRetryWithOptions', 'Collect a retry, alternate contact, code or exit through the shared FORM adapter.', { scope: 'isolated', parameters: retryParams, variables: vars({ error_message: '', error_message_es: '', retry_flow: 'authenticate-user', cancel_flow: 'contact-support', capture_patterns: [], retry_call_type: 'reboot', allow_code_entry: false, question: '', question_es: '', caller_outcome: '', caller_reason: '', parent_form: '', contact_options: null, user_choice: '', smart_capture_result: null, normalized_otp_code: '', retry_question: '', retry_question_es: '', retry_profiles: [{ name: 'phone', label: 'phone number', label_es: 'número de teléfono', profile: { kind: 'phone' } }, { name: 'email_address', label: 'email address', label_es: 'correo electrónico', profile: { kind: 'email' } }, ...OTP_PROFILES] }), contract: { role: 'collector', summary: 'Common bounded service retry menu' }, steps: [
|
|
255
|
+
const retry = worker('generic-retry-with-options', 'GenericRetryWithOptions', 'Collect a retry, alternate contact, code or exit through the shared FORM adapter.', { scope: 'isolated', parameters: retryParams, variables: vars({ error_message: '', error_message_es: '', retry_flow: 'authenticate-user', cancel_flow: 'contact-support', capture_patterns: [], retry_call_type: 'reboot', allow_code_entry: false, question: '', question_es: '', caller_outcome: '', caller_reason: '', parent_form: '', contact_options: null, user_choice: '', smart_capture_result: null, normalized_otp_code: '', retry_question: '', retry_question_es: '', retry_yes_words: ['phone', 'email', 'cell', 'mobile', 'teléfono', 'telefono', 'celular', 'móvil', 'movil', 'correo electrónico', 'correo', 'try again', 'try it again', 'retry', 'intentar', 'intentarlo', 'intentar de nuevo', 'intentar nuevamente', 'intentarlo de nuevo', 'intentarlo otra vez', 'de nuevo', 'nuevamente', 'otra vez', 'reintentar', 'volver a intentar', 'volver a intentarlo'], retry_profiles: [{ name: 'phone', label: 'phone number', label_es: 'número de teléfono', profile: { kind: 'phone' } }, { name: 'email_address', label: 'email address', label_es: 'correo electrónico', profile: { kind: 'email' } }, ...OTP_PROFILES] }), contract: { role: 'collector', summary: 'Common bounded service retry menu' }, steps: [
|
|
252
256
|
set('retry_parent', 'parent_form', "parent_form || cargo.authOptions && cargo.authOptions.parent_form || cargo.contactOptions && cargo.contactOptions.parent_form || ''"),
|
|
253
257
|
set('retry_question', 'retry_question', "error_message+' '+(question || 'Would you like to try again?')+' To retry '+(cargo.voice?'Press 1 or ':'')+cargo.verb+' YES. '+(callerTextNumber(cargo)?'To switch to text press 9 or '+cargo.verb+' TEXT. ':'')+'To abort '+(cargo.voice?'press the asterisk key or ':'')+cargo.verb+' EXIT.'"),
|
|
254
258
|
set('retry_question_es', 'retry_question_es', "error_message_es+' '+(question_es || '¿Le gustaría intentar nuevamente?')+' Para reintentar '+(cargo.voice?'Presione 1 o ':'')+cargo.verb_es+' SÍ. '+(callerTextNumber(cargo)?'Para cambiar a texto presione 9 o '+cargo.verb_es+' TEXTO. ':'')+'Para salir '+(cargo.voice?'presione la tecla de asterisco o ':'')+cargo.verb_es+' SALIR.'"),
|
|
@@ -261,7 +265,7 @@ const retry = worker('generic-retry-with-options', 'GenericRetryWithOptions', 'C
|
|
|
261
265
|
set('retry_latest_answer', 'user_choice', 'String(cargo.serviceAnswer.raw || "")'), set('retry_capture', 'smart_capture_result', 'capture_patterns && capture_patterns.length ? normalizeAndFindCapture(user_choice,capture_patterns) : null'),
|
|
262
266
|
cases('retry_capture_route', { 'condition: smart_capture_result && retry_call_type === "replace"': call('retry_captured_replace', '{{retry_flow}}', { cell_number: '', email: '', '{{smart_capture_result.variable}}': '{{smart_capture_result.value}}', retry_flow: '{{retry_flow}}', cancel_flow: '{{cancel_flow}}', retrying: true, contact_options: null, parent_form: '{{parent_form}}' }, 'replace'), 'condition: smart_capture_result': call('retry_captured_reboot', '{{retry_flow}}', { '{{smart_capture_result.variable}}': '{{smart_capture_result.value}}', retry_flow: '{{retry_flow}}', cancel_flow: '{{cancel_flow}}', retrying: true, contact_options: null, parent_form: '{{parent_form}}' }, 'reboot'), default: effect('retry_no_capture', 'true') }),
|
|
263
267
|
set('retry_typed_code', 'normalized_otp_code', "allow_code_entry && user_choice.replace(/\\D/g,'').length === 6 ? user_choice.replace(/\\D/g,'') : ''"), when('retry_validate_code', '!!normalized_otp_code', call('retry_code_validate', 'validate-otp-code')),
|
|
264
|
-
cases('retry_decision', { 'condition: normalized_otp_code && cargo.otpVerified === true': end('retry_verified'), "condition: (user_choice.trim() === '1' || isAnswer(user_choice,'yes',
|
|
268
|
+
cases('retry_decision', { 'condition: normalized_otp_code && cargo.otpVerified === true': end('retry_verified'), "condition: (user_choice.trim() === '1' || isAnswer(user_choice,'yes',retry_yes_words)) && retry_call_type === 'replace'": call('retry_yes_replace', '{{retry_flow}}', { retrying: true, cell_number: '', email: '', contact_options: null, parent_form: '{{parent_form}}' }, 'replace'), "condition: user_choice.trim() === '1' || isAnswer(user_choice,'yes',retry_yes_words)": call('retry_yes_reboot', '{{retry_flow}}', { retrying: true, contact_options: null, parent_form: '{{parent_form}}' }, 'reboot'), "condition: user_choice.trim() === '9' || isAnswer(user_choice,'text')": call('retry_text', 'switch-to-text', undefined, 'reboot'), "condition: isAgentRequest(user_choice)": call('retry_agent', 'live-agent-requested', undefined, 'reboot'), "condition: !user_choice.trim() || /^\\d$/.test(user_choice.trim()) || isExitRequest(user_choice)": call('retry_cancel', '{{cancel_flow}}', undefined, 'reboot'), default: { id: 'retry_dispatch', type: 'DISPATCH', outcome: '{{caller_outcome}}', reason: '{{caller_reason}}' } })
|
|
265
269
|
] });
|
|
266
270
|
const EMAIL_CHOICES = { ok: ['1', 'ok', 'okay', 'yes', 'send', 'send it', 'si', 'sí', 'enviar', 'envíalo', 'correcto'], another: ['otro correo', 'otro correo electrónico', 'otro correo electronico', 'otro email', 'otra dirección', 'otra direccion', 'a otro correo', 'another email', 'a different email', 'different email', 'other email', 'another address', 'a different address'] };
|
|
267
271
|
export function emailReadback(address, voice, es = false) {
|
package/dist/helpers/answer.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export function isAnswer(input: any, kind: any, extra?: any[]): boolean;
|
|
|
6
6
|
/**
|
|
7
7
|
* Whether the WHOLE answer is an exit word ("exit", "Cancelar.", "salir por favor", "*"), never a sentence that contains
|
|
8
8
|
* one: "Cancelar el pedido" asks for something; it does not withdraw (prod 2026-10-26, at a verification-code prompt).
|
|
9
|
+
* The word may be repeated ("Salir salir."), echo the prompt ("Salir para cancelar") or end in "now" (prod 2026-10-28).
|
|
9
10
|
*/
|
|
10
11
|
export function isExitRequest(input: any): boolean;
|
|
11
12
|
/** Whether the WHOLE answer asks for a person ("agent", "I want to talk to a representative", "0") — for free-text prompts. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/helpers/answer.js"],"names":[],"mappings":"AAsNA;;;GAGG;AACH,wEAkBC;AAED
|
|
1
|
+
{"version":3,"file":"answer.d.ts","sourceRoot":"","sources":["../../src/helpers/answer.js"],"names":[],"mappings":"AAsNA;;;GAGG;AACH,wEAkBC;AAED;;;;GAIG;AACH,mDAIC;AAED,+HAA+H;AAC/H,oDAIC;AAcD,2GAA2G;AAC3G,uDAGC;AAOD;;;;;GAKG;AACH,+DAUC;AAKD;;;;GAIG;AACH,oDAEC;AAiBD;;;;;;GAMG;AACH,mDAAmF;AAEnF,kGAAkG;AAClG;;;EAmCC;AAUD;;;;;;;;;GASG;AACH,6EA4GC;;;;;;;;AAncD,qCAKwE"}
|
package/dist/helpers/answer.js
CHANGED
|
@@ -253,10 +253,12 @@ export function isAnswer(input, kind, extra = []) {
|
|
|
253
253
|
/**
|
|
254
254
|
* Whether the WHOLE answer is an exit word ("exit", "Cancelar.", "salir por favor", "*"), never a sentence that contains
|
|
255
255
|
* one: "Cancelar el pedido" asks for something; it does not withdraw (prod 2026-10-26, at a verification-code prompt).
|
|
256
|
+
* The word may be repeated ("Salir salir."), echo the prompt ("Salir para cancelar") or end in "now" (prod 2026-10-28).
|
|
256
257
|
*/
|
|
257
258
|
export function isExitRequest(input) {
|
|
258
259
|
const b = normalize(input).replace(/^[.\s]+|[.\s]+$/g, '');
|
|
259
|
-
|
|
260
|
+
const word = '(?:exit|quit|salir|abort|cancel|cancelar)';
|
|
261
|
+
return b === '*' || new RegExp(`^${word}(?:[ .]+${word})*(?: para cancelar| to cancel)?(?: please| por favor| ahora| now)?$`).test(b);
|
|
260
262
|
}
|
|
261
263
|
/** Whether the WHOLE answer asks for a person ("agent", "I want to talk to a representative", "0") — for free-text prompts. */
|
|
262
264
|
export function isAgentRequest(input) {
|
package/dist/runtime-identity.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const JSFE_RUNTIME_FINGERPRINT = "sha256:
|
|
1
|
+
export const JSFE_RUNTIME_FINGERPRINT = "sha256:32c2bede7bd93be3b95aaa402b64aaf747b89e7827f81566e9bba9876f044823";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jsfe",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.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",
|