reneco-advanced-input-module 0.0.25 → 0.0.26

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 (35) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/voice-input-module.cjs.entry.js +65 -28
  3. package/dist/cjs/voice-input-module.cjs.entry.js.map +1 -1
  4. package/dist/cjs/voice-input-module.cjs.js +1 -1
  5. package/dist/cjs/voice-input-module.entry.cjs.js.map +1 -1
  6. package/dist/collection/components/voice-input-module/voice-input-module.css +26 -3
  7. package/dist/collection/components/voice-input-module/voice-input-module.js +57 -23
  8. package/dist/collection/components/voice-input-module/voice-input-module.js.map +1 -1
  9. package/dist/collection/services/llm.service.js +8 -4
  10. package/dist/collection/services/llm.service.js.map +1 -1
  11. package/dist/collection/types/form-schema.types.js.map +1 -1
  12. package/dist/components/voice-input-module.js +66 -28
  13. package/dist/components/voice-input-module.js.map +1 -1
  14. package/dist/esm/loader.js +1 -1
  15. package/dist/esm/voice-input-module.entry.js +65 -28
  16. package/dist/esm/voice-input-module.entry.js.map +1 -1
  17. package/dist/esm/voice-input-module.js +1 -1
  18. package/dist/types/components/voice-input-module/voice-input-module.d.ts +4 -0
  19. package/dist/types/types/form-schema.types.d.ts +1 -0
  20. package/dist/voice-input-module/p-f14c05d0.entry.js +3 -0
  21. package/dist/voice-input-module/p-f14c05d0.entry.js.map +1 -0
  22. package/dist/voice-input-module/voice-input-module.entry.esm.js.map +1 -1
  23. package/dist/voice-input-module/voice-input-module.esm.js +1 -1
  24. package/package.json +1 -1
  25. package/www/build/p-4e26fbbb.js +2 -0
  26. package/www/build/p-f14c05d0.entry.js +3 -0
  27. package/www/build/p-f14c05d0.entry.js.map +1 -0
  28. package/www/build/voice-input-module.entry.esm.js.map +1 -1
  29. package/www/build/voice-input-module.esm.js +1 -1
  30. package/www/index.html +9 -9
  31. package/dist/voice-input-module/p-334644ec.entry.js +0 -3
  32. package/dist/voice-input-module/p-334644ec.entry.js.map +0 -1
  33. package/www/build/p-334644ec.entry.js +0 -3
  34. package/www/build/p-334644ec.entry.js.map +0 -1
  35. package/www/build/p-dfdcd9a6.js +0 -2
@@ -59,9 +59,6 @@
59
59
  transform: scale(1.05);
60
60
  }
61
61
 
62
- .upload-record-button svg path {
63
- /* Color applied via inline style from theme */
64
- }
65
62
 
66
63
  .record-button {
67
64
  display: flex;
@@ -341,6 +338,32 @@ input[type="date"].form-input {
341
338
  user-select: none;
342
339
  }
343
340
 
341
+ /* Confidence score badges */
342
+ .confidence-badge {
343
+ display: inline-flex;
344
+ align-items: center;
345
+ margin-left: 4px;
346
+ padding: 1px 5px;
347
+ border-radius: 3px;
348
+ font-size: 0.65rem;
349
+ font-weight: 700;
350
+ vertical-align: middle;
351
+ line-height: 1.4;
352
+ cursor: help;
353
+ }
354
+
355
+ .confidence-medium {
356
+ background: #fef3c7;
357
+ color: #92400e;
358
+ border: 1px solid #fde68a;
359
+ }
360
+
361
+ .confidence-low {
362
+ background: #fee2e2;
363
+ color: #991b1b;
364
+ border: 1px solid #fca5a5;
365
+ }
366
+
344
367
  /* Skeleton loading state */
345
368
  @keyframes skeleton-shimmer {
346
369
  0% { background-position: -200% 0; }
@@ -40,6 +40,7 @@ export class VoiceFormRecorder {
40
40
  this.hasTransientError = false;
41
41
  this.transcription = '';
42
42
  this.filledData = null;
43
+ this.confidenceScores = null;
43
44
  this.debugInfo = {};
44
45
  this.isReadonlyMode = true; // Start in readonly preview mode
45
46
  this.isInitializing = true;
@@ -287,6 +288,7 @@ export class VoiceFormRecorder {
287
288
  return;
288
289
  this.isProcessing = true;
289
290
  this.hasTransientError = false;
291
+ this.confidenceScores = null;
290
292
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
291
293
  try {
292
294
  const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
@@ -304,10 +306,11 @@ export class VoiceFormRecorder {
304
306
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
305
307
  }
306
308
  this.filledData = this.extractFilledData(filledSchema);
307
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
309
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
310
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
308
311
  this.parsedSchema = this.filledData;
309
312
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
310
- this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
313
+ this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
311
314
  }
312
315
  catch (error) {
313
316
  console.error('OCR processing error:', error);
@@ -326,6 +329,7 @@ export class VoiceFormRecorder {
326
329
  return;
327
330
  this.isProcessing = true;
328
331
  this.hasTransientError = false;
332
+ this.confidenceScores = null;
329
333
  this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
330
334
  try {
331
335
  // Validate audio file before sending to API
@@ -346,7 +350,6 @@ export class VoiceFormRecorder {
346
350
  this.formFilled.emit({ success: false, error: 'Audio file too large' });
347
351
  return;
348
352
  }
349
- // Step 1: Transcription
350
353
  let transcription;
351
354
  try {
352
355
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
@@ -365,7 +368,6 @@ export class VoiceFormRecorder {
365
368
  this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
366
369
  return;
367
370
  }
368
- // Step 2: LLM form filling
369
371
  let filledSchema;
370
372
  try {
371
373
  this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
@@ -376,10 +378,11 @@ export class VoiceFormRecorder {
376
378
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
377
379
  }
378
380
  this.filledData = this.extractFilledData(filledSchema);
379
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
381
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
382
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
380
383
  this.parsedSchema = this.filledData;
381
384
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
382
- this.formFilled.emit({ success: true, data: this.filledData, transcription });
385
+ this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
383
386
  }
384
387
  catch (error) {
385
388
  console.error('Audio processing error:', error);
@@ -403,7 +406,8 @@ export class VoiceFormRecorder {
403
406
  try {
404
407
  const audioBlob = await this.audioRecorder.stopRecording();
405
408
  const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
406
- // processAudioContent manages isProcessing itself; await ensures we don't return early
409
+ // Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
410
+ this.isProcessing = false;
407
411
  await this.processAudioContent(audioContent);
408
412
  }
409
413
  catch (error) {
@@ -420,12 +424,52 @@ export class VoiceFormRecorder {
420
424
  this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
421
425
  }
422
426
  }
427
+ extractConfidenceScores(filledData) {
428
+ const scores = {};
429
+ if (!filledData)
430
+ return scores;
431
+ // Fields array format: [{"id": "...", "name": "...", "value": "...", "confidence": 0.87}]
432
+ if (filledData.fields && Array.isArray(filledData.fields)) {
433
+ filledData.fields.forEach((field) => {
434
+ const raw = typeof field.confidence === 'number' ? field.confidence : parseFloat(field.confidence);
435
+ if (!isNaN(raw)) {
436
+ const clamped = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
437
+ // Store under both id and name so label-based lookups always work
438
+ if (field.id)
439
+ scores[field.id] = clamped;
440
+ if (field.name)
441
+ scores[field.name] = clamped;
442
+ }
443
+ });
444
+ }
445
+ // Simple schema format: {"schema": {...}, "confidence": {"field_name": 0.87}}
446
+ if (filledData.confidence && typeof filledData.confidence === 'object') {
447
+ Object.entries(filledData.confidence).forEach(([k, v]) => {
448
+ const raw = typeof v === 'number' ? v : parseFloat(v);
449
+ if (!isNaN(raw)) {
450
+ scores[k] = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
451
+ }
452
+ });
453
+ }
454
+ return scores;
455
+ }
456
+ getFieldConfidence(primary, fallback) {
457
+ var _a, _b;
458
+ if (!this.confidenceScores)
459
+ return null;
460
+ return (_a = this.confidenceScores[primary]) !== null && _a !== void 0 ? _a : (fallback ? ((_b = this.confidenceScores[fallback]) !== null && _b !== void 0 ? _b : null) : null);
461
+ }
462
+ renderConfidenceIndicator(confidence) {
463
+ if (confidence === null || confidence >= 0.95)
464
+ return null;
465
+ const pct = Math.round(confidence * 100);
466
+ const isApproximate = confidence >= 0.85;
467
+ return (h("span", { class: `confidence-badge ${isApproximate ? 'confidence-medium' : 'confidence-low'}`, title: this.language === 'en' ? `Confidence: ${pct}%` : `Confiance : ${pct}%` }, pct, "%"));
468
+ }
423
469
  extractFilledData(filledData) {
424
- // console.log("extractFilledData", filledData);
425
470
  const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
426
471
  switch (this.context) {
427
472
  case "ecoteka":
428
- // console.log("TODO extractFilledData", filledData);
429
473
  case "ng":
430
474
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
431
475
  // Map AI response back to original schema structure
@@ -440,7 +484,6 @@ export class VoiceFormRecorder {
440
484
  }
441
485
  break;
442
486
  case "ecoll-veto":
443
- // console.log("TODO extractFilledData", filledData, updatedSchema);
444
487
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
445
488
  // Map AI response back to original schema structure
446
489
  filledData.fields.forEach((field) => {
@@ -481,15 +524,12 @@ export class VoiceFormRecorder {
481
524
  }
482
525
  break;
483
526
  }
484
- // console.log("extractFilledData result", updatedSchema);
485
527
  return updatedSchema;
486
528
  }
487
529
  async trimSchemaForAI(schema) {
488
530
  var _a, _b;
489
- // console.log("trimSchemaForAI", schema);
490
531
  switch (this.context) {
491
532
  case "ecoteka":
492
- // console.log("TODO trimSchemaForAI", schema)
493
533
  case "ng":
494
534
  const trimmed = { fields: [] };
495
535
  schema.Children.forEach((child) => {
@@ -508,10 +548,8 @@ export class VoiceFormRecorder {
508
548
  }
509
549
  trimmed.fields.push(fieldData);
510
550
  });
511
- // console.log("Schema apres transformation, contexte NG:", trimmed);
512
551
  return trimmed;
513
552
  case "ecoll-veto":
514
- // console.log("TODO trimSchemaForAI", schema)
515
553
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
516
554
  if (mergedItemsSchema) {
517
555
  const trimmedSchema = {
@@ -558,7 +596,6 @@ export class VoiceFormRecorder {
558
596
  default: '',
559
597
  };
560
598
  });
561
- // console.log("Schema apres transformation, contexte Track:", trimmedSchema);
562
599
  return trimmedSchema;
563
600
  }
564
601
  case "track":
@@ -755,13 +792,11 @@ export class VoiceFormRecorder {
755
792
  return (h("div", { class: "form-preview" }, h("div", { class: "form-preview-title" }, title), h("form", { class: "voice-filled-form" }, this.renderFormFields())));
756
793
  }
757
794
  renderFormFields() {
758
- // console.log("renderFormFields", this.parsedSchema);
759
795
  if (!this.parsedSchema)
760
796
  return null;
761
797
  const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
762
798
  switch (this.context) {
763
799
  case "ecoteka":
764
- // console.log("TODO renderFormFields", this.parsedSchema);
765
800
  case "ng":
766
801
  return this.parsedSchema.Children.map((child) => {
767
802
  var _a, _b, _c;
@@ -773,7 +808,7 @@ export class VoiceFormRecorder {
773
808
  const isRequired = child.Required || false;
774
809
  const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
775
810
  const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
776
- return (h("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h("span", { class: "required" }, "*")), this.renderFormField(fieldName, {
811
+ return (h("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h("span", { class: "required" }, "*"), this.renderConfidenceIndicator(this.getFieldConfidence(fieldLabel, fieldName))), this.renderFormField(fieldName, {
777
812
  type: fieldType,
778
813
  title: fieldLabel,
779
814
  required: isRequired,
@@ -781,8 +816,6 @@ export class VoiceFormRecorder {
781
816
  }, fieldValue)));
782
817
  }).filter(Boolean);
783
818
  case "ecoll-veto":
784
- // NOTE STEP 2
785
- // console.log("TODO renderFormFields", this.parsedSchema);
786
819
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
787
820
  return Object.entries(mergedItemsSchema).map(([key, field]) => {
788
821
  var _a, _b;
@@ -813,7 +846,7 @@ export class VoiceFormRecorder {
813
846
  // console.error("Error fetching classification data:", error);
814
847
  // }
815
848
  // }
816
- return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h("span", { class: "required" }, "*")), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : fieldValue))));
849
+ return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h("span", { class: "required" }, "*"), this.renderConfidenceIndicator(this.getFieldConfidence(fieldLabel, fieldName))), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : fieldValue))));
817
850
  });
818
851
  case "track":
819
852
  default:
@@ -822,7 +855,7 @@ export class VoiceFormRecorder {
822
855
  if (field.type === 'header') {
823
856
  return (h("div", { class: "form-header", key: fieldName }, field.title || fieldName));
824
857
  }
825
- return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && h("span", { class: "required" }, "*")), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : field.value))));
858
+ return (h("div", { class: "form-group", key: fieldName }, h("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && h("span", { class: "required" }, "*"), this.renderConfidenceIndicator(this.getFieldConfidence(fieldName))), this.renderFormField(fieldName, field, ((_b = (_a = this.filledData) === null || _a === void 0 ? void 0 : _a[fieldName]) !== null && _b !== void 0 ? _b : field.value))));
826
859
  });
827
860
  }
828
861
  }
@@ -1281,6 +1314,7 @@ export class VoiceFormRecorder {
1281
1314
  "hasTransientError": {},
1282
1315
  "transcription": {},
1283
1316
  "filledData": {},
1317
+ "confidenceScores": {},
1284
1318
  "debugInfo": {},
1285
1319
  "isReadonlyMode": {},
1286
1320
  "isInitializing": {}