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
@@ -4,7 +4,7 @@ export { s as setNonce } from './index-a7QWC-5I.js';
4
4
  const defineCustomElements = async (win, options) => {
5
5
  if (typeof window === 'undefined') return undefined;
6
6
  await globalScripts();
7
- return bootstrapLazy([["ocr-file-uploader",[[257,"ocr-file-uploader",{"batch":[4],"callback":[16],"jsonSchema":[1,"json-schema"],"theme":[1],"parsedTheme":[32]},null,{"theme":["parseTheme"]}]]],["voice-input-module",[[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);
7
+ return bootstrapLazy([["ocr-file-uploader",[[257,"ocr-file-uploader",{"batch":[4],"callback":[16],"jsonSchema":[1,"json-schema"],"theme":[1],"parsedTheme":[32]},null,{"theme":["parseTheme"]}]]],["voice-input-module",[[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);
8
8
  };
9
9
 
10
10
  export { defineCustomElements };
@@ -561,8 +561,9 @@ class OpenAILLMService {
561
561
  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
562
562
  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
563
563
  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
564
+ 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.
564
565
 
565
- Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
566
+ Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
566
567
  let userPrompt = `
567
568
  Voice transcription: "${data}"
568
569
 
@@ -635,8 +636,9 @@ class OpenAILLMService {
635
636
  13. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them
636
637
  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
637
638
  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
639
+ 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.
638
640
 
639
- Respond with JSON in this exact format: {"schema": {...}}`;
641
+ Respond with JSON in this exact format: {"schema": {...}, "confidence": {"field_name": 0.87}}`;
640
642
  let userPrompt = `
641
643
  Voice transcription: "${data}"
642
644
 
@@ -729,7 +731,7 @@ class AnthropicLLMService {
729
731
  Form fields:
730
732
  ${JSON.stringify(finalSchema, null, 2)}
731
733
 
732
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
734
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
733
735
  const body = this.useProxy
734
736
  ? { model: this.model, messages: [{ role: 'user', content: userPrompt }], system: systemPrompt }
735
737
  : { model: this.model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userPrompt }] };
@@ -755,6 +757,7 @@ Rules:
755
757
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
756
758
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
757
759
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
760
+ 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.
758
761
  Respond ONLY with valid JSON.`;
759
762
  }
760
763
  }
@@ -788,7 +791,7 @@ class MistralLLMService {
788
791
  Form fields:
789
792
  ${JSON.stringify(finalSchema, null, 2)}
790
793
 
791
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
794
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
792
795
  const response = await fetch(endpoint, {
793
796
  method: 'POST',
794
797
  headers,
@@ -818,6 +821,7 @@ Rules:
818
821
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
819
822
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
820
823
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
824
+ 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.
821
825
  Respond ONLY with valid JSON.`;
822
826
  }
823
827
  }
@@ -4325,7 +4329,7 @@ const defineCustomElements = async (win, options) => {
4325
4329
 
4326
4330
  (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);}})();
4327
4331
 
4328
- 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}";
4332
+ 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}";
4329
4333
 
4330
4334
  // Initialize OCR
4331
4335
  defineCustomElements();
@@ -4365,6 +4369,7 @@ const VoiceFormRecorder = class {
4365
4369
  this.hasTransientError = false;
4366
4370
  this.transcription = '';
4367
4371
  this.filledData = null;
4372
+ this.confidenceScores = null;
4368
4373
  this.debugInfo = {};
4369
4374
  this.isReadonlyMode = true; // Start in readonly preview mode
4370
4375
  this.isInitializing = true;
@@ -4612,6 +4617,7 @@ const VoiceFormRecorder = class {
4612
4617
  return;
4613
4618
  this.isProcessing = true;
4614
4619
  this.hasTransientError = false;
4620
+ this.confidenceScores = null;
4615
4621
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
4616
4622
  try {
4617
4623
  const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
@@ -4629,10 +4635,11 @@ const VoiceFormRecorder = class {
4629
4635
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4630
4636
  }
4631
4637
  this.filledData = this.extractFilledData(filledSchema);
4632
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4638
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4639
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4633
4640
  this.parsedSchema = this.filledData;
4634
4641
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4635
- this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
4642
+ this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
4636
4643
  }
4637
4644
  catch (error) {
4638
4645
  console.error('OCR processing error:', error);
@@ -4651,6 +4658,7 @@ const VoiceFormRecorder = class {
4651
4658
  return;
4652
4659
  this.isProcessing = true;
4653
4660
  this.hasTransientError = false;
4661
+ this.confidenceScores = null;
4654
4662
  this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
4655
4663
  try {
4656
4664
  // Validate audio file before sending to API
@@ -4671,7 +4679,6 @@ const VoiceFormRecorder = class {
4671
4679
  this.formFilled.emit({ success: false, error: 'Audio file too large' });
4672
4680
  return;
4673
4681
  }
4674
- // Step 1: Transcription
4675
4682
  let transcription;
4676
4683
  try {
4677
4684
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
@@ -4690,7 +4697,6 @@ const VoiceFormRecorder = class {
4690
4697
  this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
4691
4698
  return;
4692
4699
  }
4693
- // Step 2: LLM form filling
4694
4700
  let filledSchema;
4695
4701
  try {
4696
4702
  this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
@@ -4701,10 +4707,11 @@ const VoiceFormRecorder = class {
4701
4707
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4702
4708
  }
4703
4709
  this.filledData = this.extractFilledData(filledSchema);
4704
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4710
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4711
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4705
4712
  this.parsedSchema = this.filledData;
4706
4713
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4707
- this.formFilled.emit({ success: true, data: this.filledData, transcription });
4714
+ this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
4708
4715
  }
4709
4716
  catch (error) {
4710
4717
  console.error('Audio processing error:', error);
@@ -4728,7 +4735,8 @@ const VoiceFormRecorder = class {
4728
4735
  try {
4729
4736
  const audioBlob = await this.audioRecorder.stopRecording();
4730
4737
  const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
4731
- // processAudioContent manages isProcessing itself; await ensures we don't return early
4738
+ // Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
4739
+ this.isProcessing = false;
4732
4740
  await this.processAudioContent(audioContent);
4733
4741
  }
4734
4742
  catch (error) {
@@ -4745,12 +4753,52 @@ const VoiceFormRecorder = class {
4745
4753
  this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
4746
4754
  }
4747
4755
  }
4756
+ extractConfidenceScores(filledData) {
4757
+ const scores = {};
4758
+ if (!filledData)
4759
+ return scores;
4760
+ // Fields array format: [{"id": "...", "name": "...", "value": "...", "confidence": 0.87}]
4761
+ if (filledData.fields && Array.isArray(filledData.fields)) {
4762
+ filledData.fields.forEach((field) => {
4763
+ const raw = typeof field.confidence === 'number' ? field.confidence : parseFloat(field.confidence);
4764
+ if (!isNaN(raw)) {
4765
+ const clamped = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4766
+ // Store under both id and name so label-based lookups always work
4767
+ if (field.id)
4768
+ scores[field.id] = clamped;
4769
+ if (field.name)
4770
+ scores[field.name] = clamped;
4771
+ }
4772
+ });
4773
+ }
4774
+ // Simple schema format: {"schema": {...}, "confidence": {"field_name": 0.87}}
4775
+ if (filledData.confidence && typeof filledData.confidence === 'object') {
4776
+ Object.entries(filledData.confidence).forEach(([k, v]) => {
4777
+ const raw = typeof v === 'number' ? v : parseFloat(v);
4778
+ if (!isNaN(raw)) {
4779
+ scores[k] = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4780
+ }
4781
+ });
4782
+ }
4783
+ return scores;
4784
+ }
4785
+ getFieldConfidence(primary, fallback) {
4786
+ var _a, _b;
4787
+ if (!this.confidenceScores)
4788
+ return null;
4789
+ return (_a = this.confidenceScores[primary]) !== null && _a !== void 0 ? _a : (fallback ? ((_b = this.confidenceScores[fallback]) !== null && _b !== void 0 ? _b : null) : null);
4790
+ }
4791
+ renderConfidenceIndicator(confidence) {
4792
+ if (confidence === null || confidence >= 0.95)
4793
+ return null;
4794
+ const pct = Math.round(confidence * 100);
4795
+ const isApproximate = confidence >= 0.85;
4796
+ return (h$1("span", { class: `confidence-badge ${isApproximate ? 'confidence-medium' : 'confidence-low'}`, title: this.language === 'en' ? `Confidence: ${pct}%` : `Confiance : ${pct}%` }, pct, "%"));
4797
+ }
4748
4798
  extractFilledData(filledData) {
4749
- // console.log("extractFilledData", filledData);
4750
4799
  const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
4751
4800
  switch (this.context) {
4752
4801
  case "ecoteka":
4753
- // console.log("TODO extractFilledData", filledData);
4754
4802
  case "ng":
4755
4803
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4756
4804
  // Map AI response back to original schema structure
@@ -4765,7 +4813,6 @@ const VoiceFormRecorder = class {
4765
4813
  }
4766
4814
  break;
4767
4815
  case "ecoll-veto":
4768
- // console.log("TODO extractFilledData", filledData, updatedSchema);
4769
4816
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4770
4817
  // Map AI response back to original schema structure
4771
4818
  filledData.fields.forEach((field) => {
@@ -4806,15 +4853,12 @@ const VoiceFormRecorder = class {
4806
4853
  }
4807
4854
  break;
4808
4855
  }
4809
- // console.log("extractFilledData result", updatedSchema);
4810
4856
  return updatedSchema;
4811
4857
  }
4812
4858
  async trimSchemaForAI(schema) {
4813
4859
  var _a, _b;
4814
- // console.log("trimSchemaForAI", schema);
4815
4860
  switch (this.context) {
4816
4861
  case "ecoteka":
4817
- // console.log("TODO trimSchemaForAI", schema)
4818
4862
  case "ng":
4819
4863
  const trimmed = { fields: [] };
4820
4864
  schema.Children.forEach((child) => {
@@ -4833,10 +4877,8 @@ const VoiceFormRecorder = class {
4833
4877
  }
4834
4878
  trimmed.fields.push(fieldData);
4835
4879
  });
4836
- // console.log("Schema apres transformation, contexte NG:", trimmed);
4837
4880
  return trimmed;
4838
4881
  case "ecoll-veto":
4839
- // console.log("TODO trimSchemaForAI", schema)
4840
4882
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
4841
4883
  if (mergedItemsSchema) {
4842
4884
  const trimmedSchema = {
@@ -4881,7 +4923,6 @@ const VoiceFormRecorder = class {
4881
4923
  default: '',
4882
4924
  };
4883
4925
  });
4884
- // console.log("Schema apres transformation, contexte Track:", trimmedSchema);
4885
4926
  return trimmedSchema;
4886
4927
  }
4887
4928
  case "track":
@@ -5078,13 +5119,11 @@ const VoiceFormRecorder = class {
5078
5119
  return (h$1("div", { class: "form-preview" }, h$1("div", { class: "form-preview-title" }, title), h$1("form", { class: "voice-filled-form" }, this.renderFormFields())));
5079
5120
  }
5080
5121
  renderFormFields() {
5081
- // console.log("renderFormFields", this.parsedSchema);
5082
5122
  if (!this.parsedSchema)
5083
5123
  return null;
5084
5124
  const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
5085
5125
  switch (this.context) {
5086
5126
  case "ecoteka":
5087
- // console.log("TODO renderFormFields", this.parsedSchema);
5088
5127
  case "ng":
5089
5128
  return this.parsedSchema.Children.map((child) => {
5090
5129
  var _a, _b, _c;
@@ -5096,7 +5135,7 @@ const VoiceFormRecorder = class {
5096
5135
  const isRequired = child.Required || false;
5097
5136
  const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
5098
5137
  const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
5099
- return (h$1("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h$1("span", { class: "required" }, "*")), this.renderFormField(fieldName, {
5138
+ return (h$1("div", { class: isLargeField ? "form-group full-width" : "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h$1("span", { class: "required" }, "*"), this.renderConfidenceIndicator(this.getFieldConfidence(fieldLabel, fieldName))), this.renderFormField(fieldName, {
5100
5139
  type: fieldType,
5101
5140
  title: fieldLabel,
5102
5141
  required: isRequired,
@@ -5104,8 +5143,6 @@ const VoiceFormRecorder = class {
5104
5143
  }, fieldValue)));
5105
5144
  }).filter(Boolean);
5106
5145
  case "ecoll-veto":
5107
- // NOTE STEP 2
5108
- // console.log("TODO renderFormFields", this.parsedSchema);
5109
5146
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
5110
5147
  return Object.entries(mergedItemsSchema).map(([key, field]) => {
5111
5148
  var _a, _b;
@@ -5136,7 +5173,7 @@ const VoiceFormRecorder = class {
5136
5173
  // console.error("Error fetching classification data:", error);
5137
5174
  // }
5138
5175
  // }
5139
- return (h$1("div", { class: "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h$1("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))));
5176
+ return (h$1("div", { class: "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, fieldLabel, isRequired && h$1("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))));
5140
5177
  });
5141
5178
  case "track":
5142
5179
  default:
@@ -5145,7 +5182,7 @@ const VoiceFormRecorder = class {
5145
5182
  if (field.type === 'header') {
5146
5183
  return (h$1("div", { class: "form-header", key: fieldName }, field.title || fieldName));
5147
5184
  }
5148
- return (h$1("div", { class: "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && h$1("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))));
5185
+ return (h$1("div", { class: "form-group", key: fieldName }, h$1("label", { htmlFor: fieldName, class: "form-label" }, field.title || fieldName, field.required && h$1("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))));
5149
5186
  });
5150
5187
  }
5151
5188
  }