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
@@ -5,7 +5,7 @@ var index = require('./index-BtdDZbi5.js');
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await index.globalScripts();
8
- return index.bootstrapLazy([["ocr-file-uploader.cjs",[[257,"ocr-file-uploader",{"batch":[4],"callback":[16],"jsonSchema":[1,"json-schema"],"theme":[1],"parsedTheme":[32]},null,{"theme":["parseTheme"]}]]],["voice-input-module.cjs",[[257,"voice-input-module",{"formJson":[1,"form-json"],"serviceConfig":[1,"service-config"],"apiKey":[1,"api-key"],"apiProxyUrl":[1,"api-proxy-url"],"transcriptionModel":[1,"transcription-model"],"completionModel":[1,"completion-model"],"transcriptionProvider":[1,"transcription-provider"],"completionProvider":[1,"completion-provider"],"context":[1],"classificationRootUrl":[1,"classification-root-url"],"language":[1],"inputTypes":[1,"input-types"],"theme":[1],"debug":[4],"renderForm":[4,"render-form"],"displayStatus":[4,"display-status"],"isRecording":[32],"isProcessing":[32],"statusMessage":[32],"hasError":[32],"hasTransientError":[32],"transcription":[32],"filledData":[32],"debugInfo":[32],"isReadonlyMode":[32],"isInitializing":[32],"convertXmlToJson":[64],"convertJsonToXml":[64],"convertXmlToJsonLegacy":[64],"convertJsonToXmlLegacy":[64]},null,{"formJson":["initializeServices"],"serviceConfig":["initializeServices"],"theme":["initializeServices"],"transcriptionProvider":["initializeServices"],"completionProvider":["initializeServices"],"transcriptionModel":["initializeServices"],"completionModel":["initializeServices"]}]]]], options);
8
+ return index.bootstrapLazy([["ocr-file-uploader.cjs",[[257,"ocr-file-uploader",{"batch":[4],"callback":[16],"jsonSchema":[1,"json-schema"],"theme":[1],"parsedTheme":[32]},null,{"theme":["parseTheme"]}]]],["voice-input-module.cjs",[[257,"voice-input-module",{"formJson":[1,"form-json"],"serviceConfig":[1,"service-config"],"apiKey":[1,"api-key"],"apiProxyUrl":[1,"api-proxy-url"],"transcriptionModel":[1,"transcription-model"],"completionModel":[1,"completion-model"],"transcriptionProvider":[1,"transcription-provider"],"completionProvider":[1,"completion-provider"],"context":[1],"classificationRootUrl":[1,"classification-root-url"],"language":[1],"inputTypes":[1,"input-types"],"theme":[1],"debug":[4],"renderForm":[4,"render-form"],"displayStatus":[4,"display-status"],"isRecording":[32],"isProcessing":[32],"statusMessage":[32],"hasError":[32],"hasTransientError":[32],"transcription":[32],"filledData":[32],"confidenceScores":[32],"debugInfo":[32],"isReadonlyMode":[32],"isInitializing":[32],"convertXmlToJson":[64],"convertJsonToXml":[64],"convertXmlToJsonLegacy":[64],"convertJsonToXmlLegacy":[64]},null,{"formJson":["initializeServices"],"serviceConfig":["initializeServices"],"theme":["initializeServices"],"transcriptionProvider":["initializeServices"],"completionProvider":["initializeServices"],"transcriptionModel":["initializeServices"],"completionModel":["initializeServices"]}]]]], options);
9
9
  };
10
10
 
11
11
  exports.setNonce = index.setNonce;
@@ -563,8 +563,9 @@ class OpenAILLMService {
563
563
  14. CRITICAL: Each field has a unique ID shown as "ID:xxx" at the start of its description. You MUST include this exact ID in your response for each field you fill. The ID is the ONLY way to distinguish between fields with the same name
564
564
  15. CRITICAL - DEFAULT VALUES: Some fields have default values shown as "default=xxx". If the user does NOT mention a specific value for that field in the transcription, you MUST return the default value. Default values should be preserved unless explicitly overridden by the user
565
565
  16. CRITICAL - PATTERN VALIDATION: Some fields have a regex pattern shown as "pattern=xxx". The value you extract MUST match this pattern exactly. If the transcription is too ambiguous to produce a value that matches the pattern, leave the field EMPTY
566
+ 17. CONFIDENCE SCORE: For each field you fill, add a "confidence" property (number between 0.01 and 0.99, maximum 2 decimal places) reflecting how certain you are about the extracted value. Use values close to 0.99 for values that are explicitly and unambiguously stated, lower values when you had to infer, interpret, paraphrase, or when the match was approximate.
566
567
 
567
- Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
568
+ Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
568
569
  let userPrompt = `
569
570
  Voice transcription: "${data}"
570
571
 
@@ -637,8 +638,9 @@ class OpenAILLMService {
637
638
  13. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them
638
639
  14. CRITICAL - UNKNOWN/NO/N-A VALUES: The interpretation of words like "Unknown", "Inconnu", "No", "Non", "N/A", "Non applicable" depends ENTIRELY on whether the field has those words as explicit options. Rule: if the user says "field X is Unknown" (or any similar phrasing) AND "Unknown" (or a close variant) exists in the options list for that field, then SELECT that option - it is a valid value. If the user says such words for a field that does NOT have them as options (string, number, date, etc.), then it means the user has no value to provide - leave the field empty, do NOT fill it with the literal text
639
640
  15. CRITICAL - PATTERN VALIDATION: Some fields have a regex pattern shown as "pattern=xxx". The value you extract MUST match this pattern exactly. If the transcription is too ambiguous to produce a value that matches the pattern, leave the field EMPTY
641
+ 16. CONFIDENCE SCORE: For each field you fill, add its name as a key in a top-level "confidence" object with a score from 0.01 to 0.99 (max 2 decimal places). Use values close to 0.99 for clearly stated values, lower when you had to infer, interpret, or approximate.
640
642
 
641
- Respond with JSON in this exact format: {"schema": {...}}`;
643
+ Respond with JSON in this exact format: {"schema": {...}, "confidence": {"field_name": 0.87}}`;
642
644
  let userPrompt = `
643
645
  Voice transcription: "${data}"
644
646
 
@@ -731,7 +733,7 @@ class AnthropicLLMService {
731
733
  Form fields:
732
734
  ${JSON.stringify(finalSchema, null, 2)}
733
735
 
734
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
736
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
735
737
  const body = this.useProxy
736
738
  ? { model: this.model, messages: [{ role: 'user', content: userPrompt }], system: systemPrompt }
737
739
  : { model: this.model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userPrompt }] };
@@ -757,6 +759,7 @@ Rules:
757
759
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
758
760
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
759
761
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
762
+ 11. CONFIDENCE SCORE: For each field you fill, add a "confidence" property (number between 0.01 and 0.99, max 2 decimal places) reflecting how certain you are about the extracted value. Use values close to 0.99 for clearly stated values, lower when you had to infer or approximate.
760
763
  Respond ONLY with valid JSON.`;
761
764
  }
762
765
  }
@@ -790,7 +793,7 @@ class MistralLLMService {
790
793
  Form fields:
791
794
  ${JSON.stringify(finalSchema, null, 2)}
792
795
 
793
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
796
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
794
797
  const response = await fetch(endpoint, {
795
798
  method: 'POST',
796
799
  headers,
@@ -820,6 +823,7 @@ Rules:
820
823
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
821
824
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
822
825
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
826
+ 11. CONFIDENCE SCORE: For each field you fill, add a "confidence" property (number between 0.01 and 0.99, max 2 decimal places) reflecting how certain you are about the extracted value. Use values close to 0.99 for clearly stated values, lower when you had to infer or approximate.
823
827
  Respond ONLY with valid JSON.`;
824
828
  }
825
829
  }
@@ -4327,7 +4331,7 @@ const defineCustomElements = async (win, options) => {
4327
4331
 
4328
4332
  (function(){if("undefined"!==typeof window&&void 0!==window.Reflect&&void 0!==window.customElements){var a=HTMLElement;window.HTMLElement=function(){return Reflect.construct(a,[],this.constructor)};HTMLElement.prototype=a.prototype;HTMLElement.prototype.constructor=HTMLElement;Object.setPrototypeOf(HTMLElement,a);}})();
4329
4333
 
4330
- const voiceInputModuleCss = ":host{display:block;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif}.row-audio-area{display:flex;flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap;justify-content:center}.voice-recorder-container{display:flex;flex-direction:column;align-items:center;gap:1rem;padding:1rem;border:1px solid #e5e7eb;border-radius:0.5rem;background:#ffffff;margin:0 auto}.voice-recorder-container-debug{display:flex;flex-direction:column;align-items:center;gap:1rem;padding:1rem;border:1px solid #e5e7eb;border-radius:0.5rem;background:#ffffff;margin:0 auto}.upload-record-container{display:inline-flex;cursor:pointer}.upload-record-button{display:flex;align-items:center;justify-content:center;transition:transform 0.2s ease, box-shadow 0.2s ease;user-select:none}.upload-record-button svg{width:100%;height:100%;transition:transform 0.2s ease}.upload-record-container:hover .upload-record-button svg{transform:scale(1.05)}.upload-record-button svg path{}.record-button{display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:#ee4444;color:white;cursor:pointer;transition:all 0.2s ease;position:relative;overflow:hidden;flex-shrink:0}.record-button:hover:not(:disabled){background:#dd3333;transform:scale(1.05)}.record-button:disabled{opacity:0.6;cursor:not-allowed}.record-button.recording{background:#dd3333;animation:pulse 1.5s infinite}.record-button.processing{background:#3b82f6}@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(239, 68, 68, 0.7)}70%{box-shadow:0 0 0 10px rgba(239, 68, 68, 0)}100%{box-shadow:0 0 0 0 rgba(239, 68, 68, 0)}}.record-icon{width:24px;height:24px;fill:currentColor}.status-text{font-size:0.875rem;color:#6b7280;text-align:center;min-height:1.25rem}.status-text.error{color:#ee4444}.status-text.success{color:#10b981}.debug-panel{width:100%;margin-top:1rem;padding:1rem;background:#f9fafb;border:1px solid #e5e7eb;border-radius:0.375rem;font-family:'Monaco', 'Menlo', 'Ubuntu Mono', monospace;font-size:0.75rem}.debug-title{font-weight:600;margin-bottom:0.5rem;color:#374151}.debug-content{white-space:pre-wrap;word-break:break-word;color:#6b7280;max-height:200px;overflow-y:auto}.permissions-warning{padding:0.75rem;background:#fef3c7;border:1px solid #f59e0b;border-radius:0.375rem;color:#92400e;font-size:0.875rem;text-align:center}.form-preview{width:100%;margin-top:1rem;padding:1rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:0.375rem}.form-preview-title{font-weight:600;margin-bottom:0.5rem;color:#1e293b}.form-field{margin-bottom:0.5rem;font-size:0.875rem}.field-name{font-weight:500;color:#475569}.field-value{color:#64748b;margin-left:0.5rem}.field-value.filled{color:#059669;font-weight:500}.voice-filled-form{display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));gap:0.5rem;margin-top:1rem}.form-group{display:flex;flex-direction:column;gap:0.15rem}.form-group.full-width{grid-column:1 / -1}.form-header{grid-column:1 / -1;font-weight:600;font-size:1rem;color:#1e293b;margin-top:0.75rem;margin-bottom:0.25rem;padding-bottom:0.25rem;border-bottom:2px solid #e2e8f0}.form-label{font-weight:500;color:#374151;font-size:0.8rem}.required{color:#ee4444;margin-left:0.125rem}.form-input{padding:0.4rem;border:1px solid #d1d5db;border-radius:0.375rem;font-size:0.8rem;transition:border-color 0.2s ease}.form-input:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59, 130, 246, 0.1)}.form-checkbox{width:auto;padding:0;margin:0}select.form-input{background-color:white;cursor:pointer}input[type=\"date\"].form-input{cursor:pointer}.readonly-select{background:#f9fafb;border:1px solid #d1d5db;border-radius:0.375rem;padding:0.5rem}.select-placeholder{font-size:0.875rem;color:#6b7280;margin-bottom:0.5rem}.select-options-list{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:0.25rem;max-height:150px;overflow-y:auto}.select-option{background:#e5e7eb;padding:0.25rem 0.5rem;border-radius:0.25rem;font-size:0.875rem;color:#374151}.multiselect-container{display:grid;grid-template-columns:repeat(2, 1fr);gap:0.25rem;padding:0.5rem;border:1px solid #d1d5db;border-radius:0.375rem;background:white}.multiselect-option{display:flex;align-items:center;gap:0.5rem;padding:0.5rem;border-radius:0.25rem;cursor:pointer;transition:background 0.2s ease}.multiselect-option:hover{background:#f3f4f6}.multiselect-option input[type=\"checkbox\"]{width:18px;height:18px;cursor:pointer}.multiselect-option input[type=\"checkbox\"]:checked+.multiselect-label{font-weight:600;color:#059669}.multiselect-label{font-size:0.875rem;color:#374151;user-select:none}@keyframes skeleton-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}.skeleton-circle{border-radius:50%;flex-shrink:0;background:linear-gradient(\r\n 90deg,\r\n #e2e8f0 25%,\r\n #f8fafc 50%,\r\n #e2e8f0 75%\r\n );background-size:200% 100%;animation:skeleton-shimmer 1.5s ease-in-out infinite}.skeleton-status{height:14px;border-radius:7px;width:140px;background:linear-gradient(\r\n 90deg,\r\n #e2e8f0 25%,\r\n #f8fafc 50%,\r\n #e2e8f0 75%\r\n );background-size:200% 100%;animation:skeleton-shimmer 1.5s ease-in-out infinite;animation-delay:0.15s}ocr-file-uploader{display:block;width:100% !important;height:100% !important;max-width:100% !important;max-height:100% !important}ocr-file-uploader *{max-width:100% !important;max-height:100% !important}";
4334
+ const voiceInputModuleCss = ":host{display:block;font-family:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif}.row-audio-area{display:flex;flex-direction:row;align-items:center;gap:8px;flex-wrap:wrap;justify-content:center}.voice-recorder-container{display:flex;flex-direction:column;align-items:center;gap:1rem;padding:1rem;border:1px solid #e5e7eb;border-radius:0.5rem;background:#ffffff;margin:0 auto}.voice-recorder-container-debug{display:flex;flex-direction:column;align-items:center;gap:1rem;padding:1rem;border:1px solid #e5e7eb;border-radius:0.5rem;background:#ffffff;margin:0 auto}.upload-record-container{display:inline-flex;cursor:pointer}.upload-record-button{display:flex;align-items:center;justify-content:center;transition:transform 0.2s ease, box-shadow 0.2s ease;user-select:none}.upload-record-button svg{width:100%;height:100%;transition:transform 0.2s ease}.upload-record-container:hover .upload-record-button svg{transform:scale(1.05)}.record-button{display:flex;align-items:center;justify-content:center;border:none;border-radius:50%;background:#ee4444;color:white;cursor:pointer;transition:all 0.2s ease;position:relative;overflow:hidden;flex-shrink:0}.record-button:hover:not(:disabled){background:#dd3333;transform:scale(1.05)}.record-button:disabled{opacity:0.6;cursor:not-allowed}.record-button.recording{background:#dd3333;animation:pulse 1.5s infinite}.record-button.processing{background:#3b82f6}@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(239, 68, 68, 0.7)}70%{box-shadow:0 0 0 10px rgba(239, 68, 68, 0)}100%{box-shadow:0 0 0 0 rgba(239, 68, 68, 0)}}.record-icon{width:24px;height:24px;fill:currentColor}.status-text{font-size:0.875rem;color:#6b7280;text-align:center;min-height:1.25rem}.status-text.error{color:#ee4444}.status-text.success{color:#10b981}.debug-panel{width:100%;margin-top:1rem;padding:1rem;background:#f9fafb;border:1px solid #e5e7eb;border-radius:0.375rem;font-family:'Monaco', 'Menlo', 'Ubuntu Mono', monospace;font-size:0.75rem}.debug-title{font-weight:600;margin-bottom:0.5rem;color:#374151}.debug-content{white-space:pre-wrap;word-break:break-word;color:#6b7280;max-height:200px;overflow-y:auto}.permissions-warning{padding:0.75rem;background:#fef3c7;border:1px solid #f59e0b;border-radius:0.375rem;color:#92400e;font-size:0.875rem;text-align:center}.form-preview{width:100%;margin-top:1rem;padding:1rem;background:#f8fafc;border:1px solid #e2e8f0;border-radius:0.375rem}.form-preview-title{font-weight:600;margin-bottom:0.5rem;color:#1e293b}.form-field{margin-bottom:0.5rem;font-size:0.875rem}.field-name{font-weight:500;color:#475569}.field-value{color:#64748b;margin-left:0.5rem}.field-value.filled{color:#059669;font-weight:500}.voice-filled-form{display:grid;grid-template-columns:repeat(auto-fit, minmax(250px, 1fr));gap:0.5rem;margin-top:1rem}.form-group{display:flex;flex-direction:column;gap:0.15rem}.form-group.full-width{grid-column:1 / -1}.form-header{grid-column:1 / -1;font-weight:600;font-size:1rem;color:#1e293b;margin-top:0.75rem;margin-bottom:0.25rem;padding-bottom:0.25rem;border-bottom:2px solid #e2e8f0}.form-label{font-weight:500;color:#374151;font-size:0.8rem}.required{color:#ee4444;margin-left:0.125rem}.form-input{padding:0.4rem;border:1px solid #d1d5db;border-radius:0.375rem;font-size:0.8rem;transition:border-color 0.2s ease}.form-input:focus{outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59, 130, 246, 0.1)}.form-checkbox{width:auto;padding:0;margin:0}select.form-input{background-color:white;cursor:pointer}input[type=\"date\"].form-input{cursor:pointer}.readonly-select{background:#f9fafb;border:1px solid #d1d5db;border-radius:0.375rem;padding:0.5rem}.select-placeholder{font-size:0.875rem;color:#6b7280;margin-bottom:0.5rem}.select-options-list{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:0.25rem;max-height:150px;overflow-y:auto}.select-option{background:#e5e7eb;padding:0.25rem 0.5rem;border-radius:0.25rem;font-size:0.875rem;color:#374151}.multiselect-container{display:grid;grid-template-columns:repeat(2, 1fr);gap:0.25rem;padding:0.5rem;border:1px solid #d1d5db;border-radius:0.375rem;background:white}.multiselect-option{display:flex;align-items:center;gap:0.5rem;padding:0.5rem;border-radius:0.25rem;cursor:pointer;transition:background 0.2s ease}.multiselect-option:hover{background:#f3f4f6}.multiselect-option input[type=\"checkbox\"]{width:18px;height:18px;cursor:pointer}.multiselect-option input[type=\"checkbox\"]:checked+.multiselect-label{font-weight:600;color:#059669}.multiselect-label{font-size:0.875rem;color:#374151;user-select:none}.confidence-badge{display:inline-flex;align-items:center;margin-left:4px;padding:1px 5px;border-radius:3px;font-size:0.65rem;font-weight:700;vertical-align:middle;line-height:1.4;cursor:help}.confidence-medium{background:#fef3c7;color:#92400e;border:1px solid #fde68a}.confidence-low{background:#fee2e2;color:#991b1b;border:1px solid #fca5a5}@keyframes skeleton-shimmer{0%{background-position:-200% 0}100%{background-position:200% 0}}.skeleton-circle{border-radius:50%;flex-shrink:0;background:linear-gradient(\r\n 90deg,\r\n #e2e8f0 25%,\r\n #f8fafc 50%,\r\n #e2e8f0 75%\r\n );background-size:200% 100%;animation:skeleton-shimmer 1.5s ease-in-out infinite}.skeleton-status{height:14px;border-radius:7px;width:140px;background:linear-gradient(\r\n 90deg,\r\n #e2e8f0 25%,\r\n #f8fafc 50%,\r\n #e2e8f0 75%\r\n );background-size:200% 100%;animation:skeleton-shimmer 1.5s ease-in-out infinite;animation-delay:0.15s}ocr-file-uploader{display:block;width:100% !important;height:100% !important;max-width:100% !important;max-height:100% !important}ocr-file-uploader *{max-width:100% !important;max-height:100% !important}";
4331
4335
 
4332
4336
  // Initialize OCR
4333
4337
  defineCustomElements();
@@ -4367,6 +4371,7 @@ const VoiceFormRecorder = class {
4367
4371
  this.hasTransientError = false;
4368
4372
  this.transcription = '';
4369
4373
  this.filledData = null;
4374
+ this.confidenceScores = null;
4370
4375
  this.debugInfo = {};
4371
4376
  this.isReadonlyMode = true; // Start in readonly preview mode
4372
4377
  this.isInitializing = true;
@@ -4614,6 +4619,7 @@ const VoiceFormRecorder = class {
4614
4619
  return;
4615
4620
  this.isProcessing = true;
4616
4621
  this.hasTransientError = false;
4622
+ this.confidenceScores = null;
4617
4623
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
4618
4624
  try {
4619
4625
  const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
@@ -4631,10 +4637,11 @@ const VoiceFormRecorder = class {
4631
4637
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4632
4638
  }
4633
4639
  this.filledData = this.extractFilledData(filledSchema);
4634
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4640
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4641
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4635
4642
  this.parsedSchema = this.filledData;
4636
4643
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4637
- this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
4644
+ this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
4638
4645
  }
4639
4646
  catch (error) {
4640
4647
  console.error('OCR processing error:', error);
@@ -4653,6 +4660,7 @@ const VoiceFormRecorder = class {
4653
4660
  return;
4654
4661
  this.isProcessing = true;
4655
4662
  this.hasTransientError = false;
4663
+ this.confidenceScores = null;
4656
4664
  this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
4657
4665
  try {
4658
4666
  // Validate audio file before sending to API
@@ -4673,7 +4681,6 @@ const VoiceFormRecorder = class {
4673
4681
  this.formFilled.emit({ success: false, error: 'Audio file too large' });
4674
4682
  return;
4675
4683
  }
4676
- // Step 1: Transcription
4677
4684
  let transcription;
4678
4685
  try {
4679
4686
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
@@ -4692,7 +4699,6 @@ const VoiceFormRecorder = class {
4692
4699
  this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
4693
4700
  return;
4694
4701
  }
4695
- // Step 2: LLM form filling
4696
4702
  let filledSchema;
4697
4703
  try {
4698
4704
  this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
@@ -4703,10 +4709,11 @@ const VoiceFormRecorder = class {
4703
4709
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4704
4710
  }
4705
4711
  this.filledData = this.extractFilledData(filledSchema);
4706
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4712
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4713
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4707
4714
  this.parsedSchema = this.filledData;
4708
4715
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4709
- this.formFilled.emit({ success: true, data: this.filledData, transcription });
4716
+ this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
4710
4717
  }
4711
4718
  catch (error) {
4712
4719
  console.error('Audio processing error:', error);
@@ -4730,7 +4737,8 @@ const VoiceFormRecorder = class {
4730
4737
  try {
4731
4738
  const audioBlob = await this.audioRecorder.stopRecording();
4732
4739
  const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
4733
- // processAudioContent manages isProcessing itself; await ensures we don't return early
4740
+ // Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
4741
+ this.isProcessing = false;
4734
4742
  await this.processAudioContent(audioContent);
4735
4743
  }
4736
4744
  catch (error) {
@@ -4747,12 +4755,52 @@ const VoiceFormRecorder = class {
4747
4755
  this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
4748
4756
  }
4749
4757
  }
4758
+ extractConfidenceScores(filledData) {
4759
+ const scores = {};
4760
+ if (!filledData)
4761
+ return scores;
4762
+ // Fields array format: [{"id": "...", "name": "...", "value": "...", "confidence": 0.87}]
4763
+ if (filledData.fields && Array.isArray(filledData.fields)) {
4764
+ filledData.fields.forEach((field) => {
4765
+ const raw = typeof field.confidence === 'number' ? field.confidence : parseFloat(field.confidence);
4766
+ if (!isNaN(raw)) {
4767
+ const clamped = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4768
+ // Store under both id and name so label-based lookups always work
4769
+ if (field.id)
4770
+ scores[field.id] = clamped;
4771
+ if (field.name)
4772
+ scores[field.name] = clamped;
4773
+ }
4774
+ });
4775
+ }
4776
+ // Simple schema format: {"schema": {...}, "confidence": {"field_name": 0.87}}
4777
+ if (filledData.confidence && typeof filledData.confidence === 'object') {
4778
+ Object.entries(filledData.confidence).forEach(([k, v]) => {
4779
+ const raw = typeof v === 'number' ? v : parseFloat(v);
4780
+ if (!isNaN(raw)) {
4781
+ scores[k] = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4782
+ }
4783
+ });
4784
+ }
4785
+ return scores;
4786
+ }
4787
+ getFieldConfidence(primary, fallback) {
4788
+ var _a, _b;
4789
+ if (!this.confidenceScores)
4790
+ return null;
4791
+ return (_a = this.confidenceScores[primary]) !== null && _a !== void 0 ? _a : (fallback ? ((_b = this.confidenceScores[fallback]) !== null && _b !== void 0 ? _b : null) : null);
4792
+ }
4793
+ renderConfidenceIndicator(confidence) {
4794
+ if (confidence === null || confidence >= 0.95)
4795
+ return null;
4796
+ const pct = Math.round(confidence * 100);
4797
+ const isApproximate = confidence >= 0.85;
4798
+ return (index.h("span", { class: `confidence-badge ${isApproximate ? 'confidence-medium' : 'confidence-low'}`, title: this.language === 'en' ? `Confidence: ${pct}%` : `Confiance : ${pct}%` }, pct, "%"));
4799
+ }
4750
4800
  extractFilledData(filledData) {
4751
- // console.log("extractFilledData", filledData);
4752
4801
  const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
4753
4802
  switch (this.context) {
4754
4803
  case "ecoteka":
4755
- // console.log("TODO extractFilledData", filledData);
4756
4804
  case "ng":
4757
4805
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4758
4806
  // Map AI response back to original schema structure
@@ -4767,7 +4815,6 @@ const VoiceFormRecorder = class {
4767
4815
  }
4768
4816
  break;
4769
4817
  case "ecoll-veto":
4770
- // console.log("TODO extractFilledData", filledData, updatedSchema);
4771
4818
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4772
4819
  // Map AI response back to original schema structure
4773
4820
  filledData.fields.forEach((field) => {
@@ -4808,15 +4855,12 @@ const VoiceFormRecorder = class {
4808
4855
  }
4809
4856
  break;
4810
4857
  }
4811
- // console.log("extractFilledData result", updatedSchema);
4812
4858
  return updatedSchema;
4813
4859
  }
4814
4860
  async trimSchemaForAI(schema) {
4815
4861
  var _a, _b;
4816
- // console.log("trimSchemaForAI", schema);
4817
4862
  switch (this.context) {
4818
4863
  case "ecoteka":
4819
- // console.log("TODO trimSchemaForAI", schema)
4820
4864
  case "ng":
4821
4865
  const trimmed = { fields: [] };
4822
4866
  schema.Children.forEach((child) => {
@@ -4835,10 +4879,8 @@ const VoiceFormRecorder = class {
4835
4879
  }
4836
4880
  trimmed.fields.push(fieldData);
4837
4881
  });
4838
- // console.log("Schema apres transformation, contexte NG:", trimmed);
4839
4882
  return trimmed;
4840
4883
  case "ecoll-veto":
4841
- // console.log("TODO trimSchemaForAI", schema)
4842
4884
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
4843
4885
  if (mergedItemsSchema) {
4844
4886
  const trimmedSchema = {
@@ -4883,7 +4925,6 @@ const VoiceFormRecorder = class {
4883
4925
  default: '',
4884
4926
  };
4885
4927
  });
4886
- // console.log("Schema apres transformation, contexte Track:", trimmedSchema);
4887
4928
  return trimmedSchema;
4888
4929
  }
4889
4930
  case "track":
@@ -5080,13 +5121,11 @@ const VoiceFormRecorder = class {
5080
5121
  return (index.h("div", { class: "form-preview" }, index.h("div", { class: "form-preview-title" }, title), index.h("form", { class: "voice-filled-form" }, this.renderFormFields())));
5081
5122
  }
5082
5123
  renderFormFields() {
5083
- // console.log("renderFormFields", this.parsedSchema);
5084
5124
  if (!this.parsedSchema)
5085
5125
  return null;
5086
5126
  const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
5087
5127
  switch (this.context) {
5088
5128
  case "ecoteka":
5089
- // console.log("TODO renderFormFields", this.parsedSchema);
5090
5129
  case "ng":
5091
5130
  return this.parsedSchema.Children.map((child) => {
5092
5131
  var _a, _b, _c;
@@ -5098,7 +5137,7 @@ const VoiceFormRecorder = class {
5098
5137
  const isRequired = child.Required || false;
5099
5138
  const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
5100
5139
  const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
5101
- return (index.h("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && index.h("span", { class: "required" }, "*")), this.renderFormField(fieldName, {
5140
+ return (index.h("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && index.h("span", { class: "required" }, "*"), this.renderConfidenceIndicator(this.getFieldConfidence(fieldLabel, fieldName))), this.renderFormField(fieldName, {
5102
5141
  type: fieldType,
5103
5142
  title: fieldLabel,
5104
5143
  required: isRequired,
@@ -5106,8 +5145,6 @@ const VoiceFormRecorder = class {
5106
5145
  }, fieldValue)));
5107
5146
  }).filter(Boolean);
5108
5147
  case "ecoll-veto":
5109
- // NOTE STEP 2
5110
- // console.log("TODO renderFormFields", this.parsedSchema);
5111
5148
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
5112
5149
  return Object.entries(mergedItemsSchema).map(([key, field]) => {
5113
5150
  var _a, _b;
@@ -5138,7 +5175,7 @@ const VoiceFormRecorder = class {
5138
5175
  // console.error("Error fetching classification data:", error);
5139
5176
  // }
5140
5177
  // }
5141
- return (index.h("div", { class: "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && index.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))));
5178
+ return (index.h("div", { class: "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && index.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))));
5142
5179
  });
5143
5180
  case "track":
5144
5181
  default:
@@ -5147,7 +5184,7 @@ const VoiceFormRecorder = class {
5147
5184
  if (field.type === 'header') {
5148
5185
  return (index.h("div", { class: "form-header", key: fieldName }, field.title || fieldName));
5149
5186
  }
5150
- return (index.h("div", { class: "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && index.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))));
5187
+ return (index.h("div", { class: "form-group", key: fieldName }, index.h("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && index.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))));
5151
5188
  });
5152
5189
  }
5153
5190
  }