jsfe 1.7.1 → 1.7.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 (40) hide show
  1. package/README.md +5 -0
  2. package/dist/forms/contracts.d.ts.map +1 -1
  3. package/dist/forms/contracts.js +15 -5
  4. package/dist/forms/flows.d.ts +3 -155
  5. package/dist/forms/flows.d.ts.map +1 -1
  6. package/dist/forms/flows.js +98 -32
  7. package/dist/forms/proposal-runtime.d.ts +5 -0
  8. package/dist/forms/proposal-runtime.d.ts.map +1 -0
  9. package/dist/forms/proposal-runtime.js +9 -0
  10. package/dist/helpers/form-conversation.d.ts +28 -0
  11. package/dist/helpers/form-conversation.d.ts.map +1 -0
  12. package/dist/helpers/form-conversation.js +57 -0
  13. package/dist/helpers/form-proposals.d.ts +17 -0
  14. package/dist/helpers/form-proposals.d.ts.map +1 -0
  15. package/dist/helpers/form-proposals.js +292 -0
  16. package/dist/helpers/form-state.d.ts +1 -0
  17. package/dist/helpers/form-state.d.ts.map +1 -1
  18. package/dist/helpers/form-state.js +10 -2
  19. package/dist/helpers/index.d.ts +35 -1
  20. package/dist/helpers/index.d.ts.map +1 -1
  21. package/dist/helpers/index.js +6 -1
  22. package/dist/helpers/match-inputs.js +1 -1
  23. package/dist/helpers/proposal-contract.d.ts +7 -0
  24. package/dist/helpers/proposal-contract.d.ts.map +1 -0
  25. package/dist/helpers/proposal-contract.js +95 -0
  26. package/dist/host/capabilities.d.ts.map +1 -1
  27. package/dist/host/capabilities.js +6 -0
  28. package/dist/host/flow-recovery.d.ts +19 -0
  29. package/dist/host/flow-recovery.d.ts.map +1 -0
  30. package/dist/host/flow-recovery.js +43 -0
  31. package/dist/host/index.d.ts +2 -0
  32. package/dist/host/index.d.ts.map +1 -1
  33. package/dist/host/index.js +1 -0
  34. package/dist/index.d.ts +13 -1
  35. package/dist/index.d.ts.map +1 -1
  36. package/dist/index.js +31 -2
  37. package/dist/runtime-identity.js +1 -1
  38. package/docs/development-release.md +12 -0
  39. package/docs/forms.md +40 -1
  40. package/package.json +1 -1
package/README.md CHANGED
@@ -769,6 +769,11 @@ return aiResponse;
769
769
  is already repaired: the next turn starts with fresh intent detection. Log or record the error;
770
770
  no rollback is needed. A deliberate `RETURN ''` (which ends every flow) is not flagged.
771
771
 
772
+ Native FORM collection in 1.7.2 acknowledges an unreadable answer once, then yields the current
773
+ utterance while retaining its draft. Explicit recovery metadata distinguishes resumption, required
774
+ restart, unknown-action hold and no promised recovery; business completion remains independent.
775
+ See the [retry/yield/recovery contract](docs/forms.md#retry-yield-and-recovery-contract-172).
776
+
772
777
  ### Host Responsibilities: Tool Calls, Cancellation and Concurrency
773
778
 
774
779
  A flow can take actions in the outside world through `CALL-TOOL` — charge a card, send an SMS,
@@ -1 +1 @@
1
- {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/forms/contracts.js"],"names":[],"mappings":"AAaA;;;IAGC;AACD;;;;;EAGC;AACD,qGAAqG;AACrG;;QAmCC;AAeD;;;QAEC;AACD;;;;;;;QAMC;AACD;;;QAGC;AACD;;;;;;;QA8BC;AAED,mHAAmH;AACnH,kDAgBC;AAED,+GAA+G;AAC/G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAsEC"}
1
+ {"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/forms/contracts.js"],"names":[],"mappings":"AAcA;;;IAGC;AACD;;;;;EAGC;AACD,qGAAqG;AACrG;;QAqCC;AAgBD;;;QAEC;AACD;;;;;;;QAMC;AACD;;;QAGC;AACD;;;;;;;QA8BC;AAED,mHAAmH;AACnH,kDAgBC;AAED,+GAA+G;AAC/G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAwEC"}
@@ -1,4 +1,5 @@
1
1
  /** Build-time contracts for conversational flows. Transport operations remain registered tools. */
2
+ import { INPUT_PROPOSALS_REQUIREMENT, hasInputProposals, proposalRuntimeSteps } from './proposal-runtime.js';
2
3
  import { ACTION_TOOLS } from './action-tools.js';
3
4
  import { normalizeHostRequirements } from '../host/capabilities.js';
4
5
  import { validateActionProjection, actionProjectionExpression } from './action-projection.js';
@@ -66,7 +67,9 @@ export function linkFormSchemas(flows, { externalFlows = [] } = {}) {
66
67
  parameters.push(input.schema ? { name: input.name, type: 'object', jsonSchema: objectSchema(input.schema.inputs), description: input.description || input.label || input.name }
67
68
  : { name: input.name, type: 'string', ...(input.profile.kind === 'choice' && !input.profile.accept_other ? { enum: input.profile.choices.map(c => c.key) } : {}), description: input.description || input.label || input.name });
68
69
  }
69
- return { ...flow, parameters, variables: { ...flow.variables, inputs: { ...flow.variables.inputs, value: inputs } } };
70
+ const linked = { ...flow, parameters, variables: { ...flow.variables, inputs: { ...flow.variables.inputs, value: inputs } } };
71
+ // Descendant schemas are linked after declaration; propagate their runtime requirement to the root entry.
72
+ return flow.variables?.contract ? declared(linked, flow.variables.contract.value) : { ...linked, steps: proposalRuntimeSteps(flow.id, linked.steps, hasInputProposals(inputs) ? [INPUT_PROPOSALS_REQUIREMENT] : []) };
70
73
  });
71
74
  }
72
75
  function declared(flow, contract) {
@@ -79,12 +82,13 @@ function declared(flow, contract) {
79
82
  ...(step.type === 'FLOW' && step.callType === 'replace' ? { initializeDefaults: step.initializeDefaults ?? true } : {}),
80
83
  ...(step.branches ? { branches: Object.fromEntries(Object.entries(step.branches).map(([key, branch]) => [key, replacementDefaults(branch)])) } : {}),
81
84
  ...(step.onFail ? { onFail: replacementDefaults(step.onFail) } : {}) });
85
+ const requirements = [...normalizeHostRequirements(contract.requires, flow.id), ...(hasInputProposals(flow.variables?.inputs?.value) ? [INPUT_PROPOSALS_REQUIREMENT] : [])];
82
86
  const metadata = { version: 1, ...contract, parametersFrom: 'parameters' };
83
- if (contract.requires !== undefined)
87
+ if (requirements.length || contract.requires !== undefined)
84
88
  Object.defineProperty(metadata, 'requires', {
85
- value: normalizeHostRequirements(contract.requires, flow.id), enumerable: true, writable: false, configurable: false,
89
+ value: normalizeHostRequirements(requirements, flow.id), enumerable: true, writable: false, configurable: false,
86
90
  });
87
- return { ...flow, steps: flow.steps.map(replacementDefaults), variables: { ...flow.variables, contract: value(metadata) } };
91
+ return { ...flow, steps: proposalRuntimeSteps(flow.id, flow.steps.map(replacementDefaults), requirements), variables: { ...flow.variables, contract: value(metadata) } };
88
92
  }
89
93
  export function defineWorker({ contract, ...flow }) {
90
94
  return declared({ scope: 'isolated', version: '1.0.0', ...flow }, contract);
@@ -114,7 +118,7 @@ export function definePerformer({ performs, contract, prepare, present, project
114
118
  call('prepare', prepare, { form: '{{form_instance}}' }),
115
119
  set('request', 'pf_request', 'cargo.actionRequest'),
116
120
  set('select', 'pf_action', 'selectFormAction(cargo, form_instance, performs)'),
117
- when('bad_request', "!(pf_action === null || pf_action && typeof pf_action === 'object' && pf_action.action) || pf_action !== null && (!pf_request || typeof pf_request !== 'object')", { id: `${spec.id}_prepare_failed`, type: 'FLOW', value: 'give-up', callType: 'reboot', parameters: { context: '{{exit_context}}', context_es: '{{exit_context_es}}' } }),
121
+ when('bad_request', "!(pf_action === null || pf_action && typeof pf_action === 'object' && pf_action.action) || pf_action !== null && (!pf_request || typeof pf_request !== 'object')", { id: `${spec.id}_prepare_failed`, type: 'FLOW', value: 'give-up', callType: 'reboot', recovery: { version: 1, mode: 'none', reason: 'performer_request_invalid' }, parameters: { context: '{{exit_context}}', context_es: '{{exit_context_es}}' } }),
118
122
  set('proposal', 'pf_record', "pf_action ? prepareFormAction(cargo, form_instance, pf_action, pf_request) : null"),
119
123
  ];
120
124
  const flow = formFlow({ ...spec, confirm, confirmation_condition: "pf_action !== null && pf_action && typeof pf_action === 'object'",
@@ -187,10 +191,16 @@ export function validateFlowContracts(flows, tools = [], { externalFlows = [], r
187
191
  for (const name of deps)
188
192
  if (!name.startsWith('cargo.') && !name.startsWith('form.') && !fieldNames.has(name))
189
193
  fail(flow.id, `unknown dependency ${name}`);
194
+ for (const name of [...Object.keys(spec.proposal?.when || {}), ...(spec.proposal?.unless || [])])
195
+ if (!name.startsWith('cargo.') && !name.startsWith('form.') && !fieldNames.has(name))
196
+ fail(flow.id, `unknown proposal condition ${name}`);
190
197
  graph.set(spec.name, deps);
191
198
  for (const key of ['form', 'validator', 'prepare', 'refresh', 'after', 'answer_precheck', 'answer_validator', 'on_exhausted'])
192
199
  if (spec[key] && !ids.has(spec[key]))
193
200
  fail(flow.id, `unknown ${key} worker ${spec[key]}`);
201
+ for (const reference of [spec.proposal?.prepare, spec.proposal?.on_declined, ...(spec.proposal?.interrupts || []).map(event => event.flow)])
202
+ if (reference && !ids.has(reference))
203
+ fail(flow.id, `unknown proposal worker ${reference}`);
194
204
  }
195
205
  const visited = new Set(), active = new Set();
196
206
  const visit = name => { if (active.has(name))
@@ -417,8 +417,8 @@ export const FLOWS: ({
417
417
  };
418
418
  })[];
419
419
  } | {
420
+ steps: any;
420
421
  variables: any;
421
- steps: any[];
422
422
  prompt?: undefined;
423
423
  prompt_es?: undefined;
424
424
  primary?: boolean | undefined;
@@ -432,6 +432,7 @@ export const FLOWS: ({
432
432
  };
433
433
  parameters: any[];
434
434
  } | {
435
+ steps: any;
435
436
  variables: any;
436
437
  id: string;
437
438
  name: string;
@@ -442,136 +443,8 @@ export const FLOWS: ({
442
443
  type: string;
443
444
  description: string;
444
445
  }[];
445
- steps: ({
446
- id: any;
447
- type: string;
448
- variable: any;
449
- value: any;
450
- } | {
451
- parameters?: any;
452
- initializeDefaults?: boolean | undefined;
453
- id: any;
454
- type: string;
455
- value: any;
456
- callType: string;
457
- } | {
458
- id: any;
459
- type: string;
460
- branches: {
461
- [x: string]: any;
462
- default: {
463
- id: any;
464
- type: string;
465
- variable: any;
466
- value: any;
467
- };
468
- };
469
- } | {
470
- id: string;
471
- type: string;
472
- branches: {
473
- 'condition: rf_next_form': {
474
- parameters?: any;
475
- initializeDefaults?: boolean | undefined;
476
- id: any;
477
- type: string;
478
- value: any;
479
- callType: string;
480
- };
481
- default: {
482
- parameters?: any;
483
- initializeDefaults?: boolean | undefined;
484
- id: any;
485
- type: string;
486
- value: any;
487
- callType: string;
488
- };
489
- };
490
- })[];
491
- } | {
492
- variables: any;
493
- id: string;
494
- name: string;
495
- version: string;
496
- scope: string;
497
- description: string;
498
- parameters: {
499
- name: string;
500
- type: string;
501
- description: string;
502
- }[];
503
- steps: ({
504
- id: any;
505
- type: string;
506
- variable: any;
507
- value: any;
508
- } | {
509
- parameters?: any;
510
- initializeDefaults?: boolean | undefined;
511
- id: any;
512
- type: string;
513
- value: any;
514
- callType: string;
515
- } | {
516
- id: any;
517
- type: string;
518
- branches: {
519
- [x: string]: any;
520
- default: {
521
- id: any;
522
- type: string;
523
- variable: any;
524
- value: any;
525
- };
526
- };
527
- } | {
528
- id: string;
529
- type: string;
530
- branches: {
531
- 'condition: pm_keys.length > 0': {
532
- parameters?: any;
533
- initializeDefaults?: boolean | undefined;
534
- id: any;
535
- type: string;
536
- value: any;
537
- callType: string;
538
- };
539
- 'condition: pm_flow': {
540
- parameters?: any;
541
- initializeDefaults?: boolean | undefined;
542
- id: any;
543
- type: string;
544
- value: any;
545
- callType: string;
546
- };
547
- "condition: pm_key === 'done'": {
548
- id: string;
549
- type: string;
550
- value: string;
551
- value_es: string;
552
- outcome: string;
553
- };
554
- "condition: /[a-z\u00E1\u00E9\u00ED\u00F3\u00FA\u00FC\u00F1]/i.test(String(cargo.choiceText || ''))": {
555
- id: string;
556
- type: string;
557
- };
558
- "condition: retry !== '1'": {
559
- parameters?: any;
560
- initializeDefaults?: boolean | undefined;
561
- id: any;
562
- type: string;
563
- value: any;
564
- callType: string;
565
- };
566
- default: {
567
- id: string;
568
- type: string;
569
- value: string;
570
- value_es: string;
571
- };
572
- };
573
- })[];
574
446
  } | {
447
+ steps: any;
575
448
  variables: any;
576
449
  id: string;
577
450
  name: string;
@@ -582,30 +455,5 @@ export const FLOWS: ({
582
455
  name: string;
583
456
  type: string;
584
457
  }[];
585
- steps: ({
586
- id: any;
587
- type: string;
588
- variable: any;
589
- value: any;
590
- } | {
591
- parameters?: any;
592
- initializeDefaults?: boolean | undefined;
593
- id: any;
594
- type: string;
595
- value: any;
596
- callType: string;
597
- } | {
598
- id: any;
599
- type: string;
600
- branches: {
601
- [x: string]: any;
602
- default: {
603
- id: any;
604
- type: string;
605
- variable: any;
606
- value: any;
607
- };
608
- };
609
- })[];
610
458
  })[];
611
459
  //# sourceMappingURL=flows.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../src/forms/flows.js"],"names":[],"mappings":"AAsFA;;;;;;GAMG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2DC;AACD;;;GAGG;AACH;;;;;;EAGC;AAiSD,wHAAwH;AACxH,wEAaC;AACD,4FAA4F;AAC5F;;;EAYC;AACD,sGAAsG;AACtG;;;EAOC;AAlcM,6CAAuG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAknB9G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOG"}
1
+ {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../src/forms/flows.js"],"names":[],"mappings":"AA0FA;;;;;;GAMG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6DC;AACD;;;GAGG;AACH;;;;;;EAGC;AA8VD,wHAAwH;AACxH,wEAaC;AACD,4FAA4F;AAC5F;;;EAYC;AACD,sGAAsG;AACtG;;;EAOC;AAjgBM,6CAAuG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkrB9G;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAOG"}