reneco-advanced-input-module 0.0.24 → 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.
- package/dist/cjs/{index-BTSzTkSZ.js → index-BtdDZbi5.js} +11 -4
- package/dist/cjs/index-BtdDZbi5.js.map +1 -0
- package/dist/cjs/loader.cjs.js +3 -4
- package/dist/cjs/loader.cjs.js.map +1 -1
- package/dist/cjs/ocr-file-uploader.cjs.entry.js +1 -1
- package/dist/cjs/voice-input-module.cjs.entry.js +79 -32
- package/dist/cjs/voice-input-module.cjs.entry.js.map +1 -1
- package/dist/cjs/voice-input-module.cjs.js +3 -4
- package/dist/cjs/voice-input-module.cjs.js.map +1 -1
- package/dist/cjs/voice-input-module.entry.cjs.js.map +1 -1
- package/dist/collection/components/voice-input-module/voice-input-module.css +26 -3
- package/dist/collection/components/voice-input-module/voice-input-module.js +70 -26
- package/dist/collection/components/voice-input-module/voice-input-module.js.map +1 -1
- package/dist/collection/services/llm.service.js +8 -4
- package/dist/collection/services/llm.service.js.map +1 -1
- package/dist/collection/types/form-schema.types.js.map +1 -1
- package/dist/components/voice-input-module.js +79 -31
- package/dist/components/voice-input-module.js.map +1 -1
- package/dist/esm/{index-jmc2yzBp.js → index-a7QWC-5I.js} +11 -5
- package/dist/esm/index-a7QWC-5I.js.map +1 -0
- package/dist/esm/loader.js +3 -4
- package/dist/esm/loader.js.map +1 -1
- package/dist/esm/ocr-file-uploader.entry.js +1 -1
- package/dist/esm/voice-input-module.entry.js +79 -32
- package/dist/esm/voice-input-module.entry.js.map +1 -1
- package/dist/esm/voice-input-module.js +3 -4
- package/dist/esm/voice-input-module.js.map +1 -1
- package/dist/types/components/voice-input-module/voice-input-module.d.ts +4 -0
- package/dist/types/types/form-schema.types.d.ts +1 -0
- package/dist/voice-input-module/loader.esm.js.map +1 -1
- package/dist/voice-input-module/p-a7QWC-5I.js +3 -0
- package/dist/voice-input-module/p-a7QWC-5I.js.map +1 -0
- package/dist/voice-input-module/{p-a5eeaf1c.entry.js → p-ba3d83d1.entry.js} +2 -2
- package/dist/voice-input-module/p-f14c05d0.entry.js +3 -0
- package/dist/voice-input-module/p-f14c05d0.entry.js.map +1 -0
- package/dist/voice-input-module/voice-input-module.css +6 -0
- package/dist/voice-input-module/voice-input-module.entry.esm.js.map +1 -1
- package/dist/voice-input-module/voice-input-module.esm.js +1 -1
- package/dist/voice-input-module/voice-input-module.esm.js.map +1 -1
- package/package.json +1 -1
- package/www/build/loader.esm.js.map +1 -1
- package/www/build/p-4e26fbbb.js +2 -0
- package/www/build/p-6cd2a3a1.css +6 -0
- package/www/build/p-a7QWC-5I.js +3 -0
- package/www/build/p-a7QWC-5I.js.map +1 -0
- package/www/build/{p-a5eeaf1c.entry.js → p-ba3d83d1.entry.js} +2 -2
- package/www/build/p-f14c05d0.entry.js +3 -0
- package/www/build/p-f14c05d0.entry.js.map +1 -0
- package/www/build/voice-input-module.css +6 -0
- package/www/build/voice-input-module.entry.esm.js.map +1 -1
- package/www/build/voice-input-module.esm.js +1 -1
- package/www/build/voice-input-module.esm.js.map +1 -1
- package/www/index.html +9 -9
- package/dist/cjs/app-globals-V2Kpy_OQ.js +0 -8
- package/dist/cjs/app-globals-V2Kpy_OQ.js.map +0 -1
- package/dist/cjs/index-BTSzTkSZ.js.map +0 -1
- package/dist/esm/app-globals-DQuL1Twl.js +0 -6
- package/dist/esm/app-globals-DQuL1Twl.js.map +0 -1
- package/dist/esm/index-jmc2yzBp.js.map +0 -1
- package/dist/voice-input-module/p-DQuL1Twl.js +0 -2
- package/dist/voice-input-module/p-DQuL1Twl.js.map +0 -1
- package/dist/voice-input-module/p-b3bf4feb.entry.js +0 -3
- package/dist/voice-input-module/p-b3bf4feb.entry.js.map +0 -1
- package/dist/voice-input-module/p-jmc2yzBp.js +0 -3
- package/dist/voice-input-module/p-jmc2yzBp.js.map +0 -1
- package/www/build/p-3aeb495d.js +0 -2
- package/www/build/p-DQuL1Twl.js +0 -2
- package/www/build/p-DQuL1Twl.js.map +0 -1
- package/www/build/p-b3bf4feb.entry.js +0 -3
- package/www/build/p-b3bf4feb.entry.js.map +0 -1
- package/www/build/p-jmc2yzBp.js +0 -3
- package/www/build/p-jmc2yzBp.js.map +0 -1
- /package/dist/voice-input-module/{p-a5eeaf1c.entry.js.map → p-ba3d83d1.entry.js.map} +0 -0
- /package/www/build/{p-a5eeaf1c.entry.js.map → p-ba3d83d1.entry.js.map} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as registerInstance, h } from './index-
|
|
1
|
+
import { r as registerInstance, h } from './index-a7QWC-5I.js';
|
|
2
2
|
|
|
3
3
|
const ocrFileUploaderCss = ".upload-container{display:inline-block;cursor:pointer}.upload-button{display:flex;align-items:center;justify-content:center;transition:transform 0.2s ease;user-select:none;width:var(--button-size, 50px);height:var(--button-size, 50px)}.upload-button svg{width:100%;height:100%;stroke:var(--button-bg, #10b981);transition:stroke 0.2s ease, transform 0.2s ease}.upload-button:hover svg{transform:scale(1.05);stroke:var(--button-hover, #059669)}";
|
|
4
4
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as registerInstance, c as createEvent, h as h$1 } from './index-
|
|
1
|
+
import { r as registerInstance, c as createEvent, h as h$1 } from './index-a7QWC-5I.js';
|
|
2
2
|
|
|
3
3
|
const TRANSCRIPTION_MODELS = {
|
|
4
4
|
openai: ['gpt-4o-transcribe', 'gpt-4o-mini-transcribe', 'whisper-1'],
|
|
@@ -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)}.
|
|
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;
|
|
@@ -4399,9 +4404,17 @@ const VoiceFormRecorder = class {
|
|
|
4399
4404
|
this.audioRecorder = new AudioRecorderService();
|
|
4400
4405
|
}
|
|
4401
4406
|
componentWillLoad() {
|
|
4402
|
-
|
|
4407
|
+
// Parse theme only so the skeleton can be styled correctly on first render.
|
|
4408
|
+
// Full initialization runs in componentDidLoad() to give the skeleton time to paint.
|
|
4409
|
+
try {
|
|
4410
|
+
this.parsedTheme = this.theme ? JSON.parse(this.theme) : this.getDefaultTheme();
|
|
4411
|
+
}
|
|
4412
|
+
catch (_a) {
|
|
4413
|
+
this.parsedTheme = this.getDefaultTheme();
|
|
4414
|
+
}
|
|
4403
4415
|
}
|
|
4404
4416
|
componentDidLoad() {
|
|
4417
|
+
this.initializeServices();
|
|
4405
4418
|
this.isInitializing = false;
|
|
4406
4419
|
}
|
|
4407
4420
|
initializeServices() {
|
|
@@ -4604,6 +4617,7 @@ const VoiceFormRecorder = class {
|
|
|
4604
4617
|
return;
|
|
4605
4618
|
this.isProcessing = true;
|
|
4606
4619
|
this.hasTransientError = false;
|
|
4620
|
+
this.confidenceScores = null;
|
|
4607
4621
|
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
|
|
4608
4622
|
try {
|
|
4609
4623
|
const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
|
|
@@ -4621,10 +4635,11 @@ const VoiceFormRecorder = class {
|
|
|
4621
4635
|
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4622
4636
|
}
|
|
4623
4637
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4624
|
-
this.
|
|
4638
|
+
this.confidenceScores = this.extractConfidenceScores(filledSchema);
|
|
4639
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
|
|
4625
4640
|
this.parsedSchema = this.filledData;
|
|
4626
4641
|
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4627
|
-
this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
|
|
4642
|
+
this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
|
|
4628
4643
|
}
|
|
4629
4644
|
catch (error) {
|
|
4630
4645
|
console.error('OCR processing error:', error);
|
|
@@ -4643,6 +4658,7 @@ const VoiceFormRecorder = class {
|
|
|
4643
4658
|
return;
|
|
4644
4659
|
this.isProcessing = true;
|
|
4645
4660
|
this.hasTransientError = false;
|
|
4661
|
+
this.confidenceScores = null;
|
|
4646
4662
|
this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
|
|
4647
4663
|
try {
|
|
4648
4664
|
// Validate audio file before sending to API
|
|
@@ -4663,7 +4679,6 @@ const VoiceFormRecorder = class {
|
|
|
4663
4679
|
this.formFilled.emit({ success: false, error: 'Audio file too large' });
|
|
4664
4680
|
return;
|
|
4665
4681
|
}
|
|
4666
|
-
// Step 1: Transcription
|
|
4667
4682
|
let transcription;
|
|
4668
4683
|
try {
|
|
4669
4684
|
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
|
|
@@ -4682,7 +4697,6 @@ const VoiceFormRecorder = class {
|
|
|
4682
4697
|
this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
|
|
4683
4698
|
return;
|
|
4684
4699
|
}
|
|
4685
|
-
// Step 2: LLM form filling
|
|
4686
4700
|
let filledSchema;
|
|
4687
4701
|
try {
|
|
4688
4702
|
this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
|
|
@@ -4693,10 +4707,11 @@ const VoiceFormRecorder = class {
|
|
|
4693
4707
|
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4694
4708
|
}
|
|
4695
4709
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4696
|
-
this.
|
|
4710
|
+
this.confidenceScores = this.extractConfidenceScores(filledSchema);
|
|
4711
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
|
|
4697
4712
|
this.parsedSchema = this.filledData;
|
|
4698
4713
|
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4699
|
-
this.formFilled.emit({ success: true, data: this.filledData, transcription });
|
|
4714
|
+
this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
|
|
4700
4715
|
}
|
|
4701
4716
|
catch (error) {
|
|
4702
4717
|
console.error('Audio processing error:', error);
|
|
@@ -4720,7 +4735,8 @@ const VoiceFormRecorder = class {
|
|
|
4720
4735
|
try {
|
|
4721
4736
|
const audioBlob = await this.audioRecorder.stopRecording();
|
|
4722
4737
|
const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
|
|
4723
|
-
//
|
|
4738
|
+
// Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
|
|
4739
|
+
this.isProcessing = false;
|
|
4724
4740
|
await this.processAudioContent(audioContent);
|
|
4725
4741
|
}
|
|
4726
4742
|
catch (error) {
|
|
@@ -4737,12 +4753,52 @@ const VoiceFormRecorder = class {
|
|
|
4737
4753
|
this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
|
|
4738
4754
|
}
|
|
4739
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
|
+
}
|
|
4740
4798
|
extractFilledData(filledData) {
|
|
4741
|
-
// console.log("extractFilledData", filledData);
|
|
4742
4799
|
const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
|
|
4743
4800
|
switch (this.context) {
|
|
4744
4801
|
case "ecoteka":
|
|
4745
|
-
// console.log("TODO extractFilledData", filledData);
|
|
4746
4802
|
case "ng":
|
|
4747
4803
|
if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
|
|
4748
4804
|
// Map AI response back to original schema structure
|
|
@@ -4757,7 +4813,6 @@ const VoiceFormRecorder = class {
|
|
|
4757
4813
|
}
|
|
4758
4814
|
break;
|
|
4759
4815
|
case "ecoll-veto":
|
|
4760
|
-
// console.log("TODO extractFilledData", filledData, updatedSchema);
|
|
4761
4816
|
if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
|
|
4762
4817
|
// Map AI response back to original schema structure
|
|
4763
4818
|
filledData.fields.forEach((field) => {
|
|
@@ -4798,15 +4853,12 @@ const VoiceFormRecorder = class {
|
|
|
4798
4853
|
}
|
|
4799
4854
|
break;
|
|
4800
4855
|
}
|
|
4801
|
-
// console.log("extractFilledData result", updatedSchema);
|
|
4802
4856
|
return updatedSchema;
|
|
4803
4857
|
}
|
|
4804
4858
|
async trimSchemaForAI(schema) {
|
|
4805
4859
|
var _a, _b;
|
|
4806
|
-
// console.log("trimSchemaForAI", schema);
|
|
4807
4860
|
switch (this.context) {
|
|
4808
4861
|
case "ecoteka":
|
|
4809
|
-
// console.log("TODO trimSchemaForAI", schema)
|
|
4810
4862
|
case "ng":
|
|
4811
4863
|
const trimmed = { fields: [] };
|
|
4812
4864
|
schema.Children.forEach((child) => {
|
|
@@ -4825,10 +4877,8 @@ const VoiceFormRecorder = class {
|
|
|
4825
4877
|
}
|
|
4826
4878
|
trimmed.fields.push(fieldData);
|
|
4827
4879
|
});
|
|
4828
|
-
// console.log("Schema apres transformation, contexte NG:", trimmed);
|
|
4829
4880
|
return trimmed;
|
|
4830
4881
|
case "ecoll-veto":
|
|
4831
|
-
// console.log("TODO trimSchemaForAI", schema)
|
|
4832
4882
|
const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
|
|
4833
4883
|
if (mergedItemsSchema) {
|
|
4834
4884
|
const trimmedSchema = {
|
|
@@ -4873,7 +4923,6 @@ const VoiceFormRecorder = class {
|
|
|
4873
4923
|
default: '',
|
|
4874
4924
|
};
|
|
4875
4925
|
});
|
|
4876
|
-
// console.log("Schema apres transformation, contexte Track:", trimmedSchema);
|
|
4877
4926
|
return trimmedSchema;
|
|
4878
4927
|
}
|
|
4879
4928
|
case "track":
|
|
@@ -5070,13 +5119,11 @@ const VoiceFormRecorder = class {
|
|
|
5070
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())));
|
|
5071
5120
|
}
|
|
5072
5121
|
renderFormFields() {
|
|
5073
|
-
// console.log("renderFormFields", this.parsedSchema);
|
|
5074
5122
|
if (!this.parsedSchema)
|
|
5075
5123
|
return null;
|
|
5076
5124
|
const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
|
|
5077
5125
|
switch (this.context) {
|
|
5078
5126
|
case "ecoteka":
|
|
5079
|
-
// console.log("TODO renderFormFields", this.parsedSchema);
|
|
5080
5127
|
case "ng":
|
|
5081
5128
|
return this.parsedSchema.Children.map((child) => {
|
|
5082
5129
|
var _a, _b, _c;
|
|
@@ -5088,7 +5135,7 @@ const VoiceFormRecorder = class {
|
|
|
5088
5135
|
const isRequired = child.Required || false;
|
|
5089
5136
|
const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
|
|
5090
5137
|
const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
|
|
5091
|
-
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, {
|
|
5092
5139
|
type: fieldType,
|
|
5093
5140
|
title: fieldLabel,
|
|
5094
5141
|
required: isRequired,
|
|
@@ -5096,8 +5143,6 @@ const VoiceFormRecorder = class {
|
|
|
5096
5143
|
}, fieldValue)));
|
|
5097
5144
|
}).filter(Boolean);
|
|
5098
5145
|
case "ecoll-veto":
|
|
5099
|
-
// NOTE STEP 2
|
|
5100
|
-
// console.log("TODO renderFormFields", this.parsedSchema);
|
|
5101
5146
|
const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
|
|
5102
5147
|
return Object.entries(mergedItemsSchema).map(([key, field]) => {
|
|
5103
5148
|
var _a, _b;
|
|
@@ -5128,7 +5173,7 @@ const VoiceFormRecorder = class {
|
|
|
5128
5173
|
// console.error("Error fetching classification data:", error);
|
|
5129
5174
|
// }
|
|
5130
5175
|
// }
|
|
5131
|
-
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))));
|
|
5132
5177
|
});
|
|
5133
5178
|
case "track":
|
|
5134
5179
|
default:
|
|
@@ -5137,7 +5182,7 @@ const VoiceFormRecorder = class {
|
|
|
5137
5182
|
if (field.type === 'header') {
|
|
5138
5183
|
return (h$1("div", { class: "form-header", key: fieldName }, field.title || fieldName));
|
|
5139
5184
|
}
|
|
5140
|
-
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))));
|
|
5141
5186
|
});
|
|
5142
5187
|
}
|
|
5143
5188
|
}
|
|
@@ -5213,7 +5258,8 @@ const VoiceFormRecorder = class {
|
|
|
5213
5258
|
};
|
|
5214
5259
|
}
|
|
5215
5260
|
getContainerStyle() {
|
|
5216
|
-
|
|
5261
|
+
var _a;
|
|
5262
|
+
const c = ((_a = this.parsedTheme) === null || _a === void 0 ? void 0 : _a.container) || {};
|
|
5217
5263
|
return {
|
|
5218
5264
|
width: c.width || 'auto',
|
|
5219
5265
|
height: c.height || 'auto',
|
|
@@ -5225,7 +5271,8 @@ const VoiceFormRecorder = class {
|
|
|
5225
5271
|
};
|
|
5226
5272
|
}
|
|
5227
5273
|
getStatusStyle() {
|
|
5228
|
-
|
|
5274
|
+
var _a;
|
|
5275
|
+
const s = ((_a = this.parsedTheme) === null || _a === void 0 ? void 0 : _a.statusText) || {};
|
|
5229
5276
|
return {
|
|
5230
5277
|
color: s.color || '#1e293b',
|
|
5231
5278
|
fontSize: s.fontSize || '14px'
|