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,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-BtdDZbi5.js');
|
|
4
4
|
|
|
5
5
|
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)}";
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var index = require('./index-
|
|
3
|
+
var index = require('./index-BtdDZbi5.js');
|
|
4
4
|
|
|
5
5
|
const TRANSCRIPTION_MODELS = {
|
|
6
6
|
openai: ['gpt-4o-transcribe', 'gpt-4o-mini-transcribe', 'whisper-1'],
|
|
@@ -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)}.
|
|
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;
|
|
@@ -4401,9 +4406,17 @@ const VoiceFormRecorder = class {
|
|
|
4401
4406
|
this.audioRecorder = new AudioRecorderService();
|
|
4402
4407
|
}
|
|
4403
4408
|
componentWillLoad() {
|
|
4404
|
-
|
|
4409
|
+
// Parse theme only so the skeleton can be styled correctly on first render.
|
|
4410
|
+
// Full initialization runs in componentDidLoad() to give the skeleton time to paint.
|
|
4411
|
+
try {
|
|
4412
|
+
this.parsedTheme = this.theme ? JSON.parse(this.theme) : this.getDefaultTheme();
|
|
4413
|
+
}
|
|
4414
|
+
catch (_a) {
|
|
4415
|
+
this.parsedTheme = this.getDefaultTheme();
|
|
4416
|
+
}
|
|
4405
4417
|
}
|
|
4406
4418
|
componentDidLoad() {
|
|
4419
|
+
this.initializeServices();
|
|
4407
4420
|
this.isInitializing = false;
|
|
4408
4421
|
}
|
|
4409
4422
|
initializeServices() {
|
|
@@ -4606,6 +4619,7 @@ const VoiceFormRecorder = class {
|
|
|
4606
4619
|
return;
|
|
4607
4620
|
this.isProcessing = true;
|
|
4608
4621
|
this.hasTransientError = false;
|
|
4622
|
+
this.confidenceScores = null;
|
|
4609
4623
|
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
|
|
4610
4624
|
try {
|
|
4611
4625
|
const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
|
|
@@ -4623,10 +4637,11 @@ const VoiceFormRecorder = class {
|
|
|
4623
4637
|
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4624
4638
|
}
|
|
4625
4639
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4626
|
-
this.
|
|
4640
|
+
this.confidenceScores = this.extractConfidenceScores(filledSchema);
|
|
4641
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
|
|
4627
4642
|
this.parsedSchema = this.filledData;
|
|
4628
4643
|
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4629
|
-
this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
|
|
4644
|
+
this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
|
|
4630
4645
|
}
|
|
4631
4646
|
catch (error) {
|
|
4632
4647
|
console.error('OCR processing error:', error);
|
|
@@ -4645,6 +4660,7 @@ const VoiceFormRecorder = class {
|
|
|
4645
4660
|
return;
|
|
4646
4661
|
this.isProcessing = true;
|
|
4647
4662
|
this.hasTransientError = false;
|
|
4663
|
+
this.confidenceScores = null;
|
|
4648
4664
|
this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
|
|
4649
4665
|
try {
|
|
4650
4666
|
// Validate audio file before sending to API
|
|
@@ -4665,7 +4681,6 @@ const VoiceFormRecorder = class {
|
|
|
4665
4681
|
this.formFilled.emit({ success: false, error: 'Audio file too large' });
|
|
4666
4682
|
return;
|
|
4667
4683
|
}
|
|
4668
|
-
// Step 1: Transcription
|
|
4669
4684
|
let transcription;
|
|
4670
4685
|
try {
|
|
4671
4686
|
this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
|
|
@@ -4684,7 +4699,6 @@ const VoiceFormRecorder = class {
|
|
|
4684
4699
|
this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
|
|
4685
4700
|
return;
|
|
4686
4701
|
}
|
|
4687
|
-
// Step 2: LLM form filling
|
|
4688
4702
|
let filledSchema;
|
|
4689
4703
|
try {
|
|
4690
4704
|
this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
|
|
@@ -4695,10 +4709,11 @@ const VoiceFormRecorder = class {
|
|
|
4695
4709
|
throw Object.assign(new Error(llmError.message), { phase: 'llm' });
|
|
4696
4710
|
}
|
|
4697
4711
|
this.filledData = this.extractFilledData(filledSchema);
|
|
4698
|
-
this.
|
|
4712
|
+
this.confidenceScores = this.extractConfidenceScores(filledSchema);
|
|
4713
|
+
this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
|
|
4699
4714
|
this.parsedSchema = this.filledData;
|
|
4700
4715
|
this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
|
|
4701
|
-
this.formFilled.emit({ success: true, data: this.filledData, transcription });
|
|
4716
|
+
this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
|
|
4702
4717
|
}
|
|
4703
4718
|
catch (error) {
|
|
4704
4719
|
console.error('Audio processing error:', error);
|
|
@@ -4722,7 +4737,8 @@ const VoiceFormRecorder = class {
|
|
|
4722
4737
|
try {
|
|
4723
4738
|
const audioBlob = await this.audioRecorder.stopRecording();
|
|
4724
4739
|
const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
|
|
4725
|
-
//
|
|
4740
|
+
// Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
|
|
4741
|
+
this.isProcessing = false;
|
|
4726
4742
|
await this.processAudioContent(audioContent);
|
|
4727
4743
|
}
|
|
4728
4744
|
catch (error) {
|
|
@@ -4739,12 +4755,52 @@ const VoiceFormRecorder = class {
|
|
|
4739
4755
|
this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
|
|
4740
4756
|
}
|
|
4741
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
|
+
}
|
|
4742
4800
|
extractFilledData(filledData) {
|
|
4743
|
-
// console.log("extractFilledData", filledData);
|
|
4744
4801
|
const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
|
|
4745
4802
|
switch (this.context) {
|
|
4746
4803
|
case "ecoteka":
|
|
4747
|
-
// console.log("TODO extractFilledData", filledData);
|
|
4748
4804
|
case "ng":
|
|
4749
4805
|
if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
|
|
4750
4806
|
// Map AI response back to original schema structure
|
|
@@ -4759,7 +4815,6 @@ const VoiceFormRecorder = class {
|
|
|
4759
4815
|
}
|
|
4760
4816
|
break;
|
|
4761
4817
|
case "ecoll-veto":
|
|
4762
|
-
// console.log("TODO extractFilledData", filledData, updatedSchema);
|
|
4763
4818
|
if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
|
|
4764
4819
|
// Map AI response back to original schema structure
|
|
4765
4820
|
filledData.fields.forEach((field) => {
|
|
@@ -4800,15 +4855,12 @@ const VoiceFormRecorder = class {
|
|
|
4800
4855
|
}
|
|
4801
4856
|
break;
|
|
4802
4857
|
}
|
|
4803
|
-
// console.log("extractFilledData result", updatedSchema);
|
|
4804
4858
|
return updatedSchema;
|
|
4805
4859
|
}
|
|
4806
4860
|
async trimSchemaForAI(schema) {
|
|
4807
4861
|
var _a, _b;
|
|
4808
|
-
// console.log("trimSchemaForAI", schema);
|
|
4809
4862
|
switch (this.context) {
|
|
4810
4863
|
case "ecoteka":
|
|
4811
|
-
// console.log("TODO trimSchemaForAI", schema)
|
|
4812
4864
|
case "ng":
|
|
4813
4865
|
const trimmed = { fields: [] };
|
|
4814
4866
|
schema.Children.forEach((child) => {
|
|
@@ -4827,10 +4879,8 @@ const VoiceFormRecorder = class {
|
|
|
4827
4879
|
}
|
|
4828
4880
|
trimmed.fields.push(fieldData);
|
|
4829
4881
|
});
|
|
4830
|
-
// console.log("Schema apres transformation, contexte NG:", trimmed);
|
|
4831
4882
|
return trimmed;
|
|
4832
4883
|
case "ecoll-veto":
|
|
4833
|
-
// console.log("TODO trimSchemaForAI", schema)
|
|
4834
4884
|
const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
|
|
4835
4885
|
if (mergedItemsSchema) {
|
|
4836
4886
|
const trimmedSchema = {
|
|
@@ -4875,7 +4925,6 @@ const VoiceFormRecorder = class {
|
|
|
4875
4925
|
default: '',
|
|
4876
4926
|
};
|
|
4877
4927
|
});
|
|
4878
|
-
// console.log("Schema apres transformation, contexte Track:", trimmedSchema);
|
|
4879
4928
|
return trimmedSchema;
|
|
4880
4929
|
}
|
|
4881
4930
|
case "track":
|
|
@@ -5072,13 +5121,11 @@ const VoiceFormRecorder = class {
|
|
|
5072
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())));
|
|
5073
5122
|
}
|
|
5074
5123
|
renderFormFields() {
|
|
5075
|
-
// console.log("renderFormFields", this.parsedSchema);
|
|
5076
5124
|
if (!this.parsedSchema)
|
|
5077
5125
|
return null;
|
|
5078
5126
|
const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
|
|
5079
5127
|
switch (this.context) {
|
|
5080
5128
|
case "ecoteka":
|
|
5081
|
-
// console.log("TODO renderFormFields", this.parsedSchema);
|
|
5082
5129
|
case "ng":
|
|
5083
5130
|
return this.parsedSchema.Children.map((child) => {
|
|
5084
5131
|
var _a, _b, _c;
|
|
@@ -5090,7 +5137,7 @@ const VoiceFormRecorder = class {
|
|
|
5090
5137
|
const isRequired = child.Required || false;
|
|
5091
5138
|
const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
|
|
5092
5139
|
const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
|
|
5093
|
-
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, {
|
|
5094
5141
|
type: fieldType,
|
|
5095
5142
|
title: fieldLabel,
|
|
5096
5143
|
required: isRequired,
|
|
@@ -5098,8 +5145,6 @@ const VoiceFormRecorder = class {
|
|
|
5098
5145
|
}, fieldValue)));
|
|
5099
5146
|
}).filter(Boolean);
|
|
5100
5147
|
case "ecoll-veto":
|
|
5101
|
-
// NOTE STEP 2
|
|
5102
|
-
// console.log("TODO renderFormFields", this.parsedSchema);
|
|
5103
5148
|
const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
|
|
5104
5149
|
return Object.entries(mergedItemsSchema).map(([key, field]) => {
|
|
5105
5150
|
var _a, _b;
|
|
@@ -5130,7 +5175,7 @@ const VoiceFormRecorder = class {
|
|
|
5130
5175
|
// console.error("Error fetching classification data:", error);
|
|
5131
5176
|
// }
|
|
5132
5177
|
// }
|
|
5133
|
-
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))));
|
|
5134
5179
|
});
|
|
5135
5180
|
case "track":
|
|
5136
5181
|
default:
|
|
@@ -5139,7 +5184,7 @@ const VoiceFormRecorder = class {
|
|
|
5139
5184
|
if (field.type === 'header') {
|
|
5140
5185
|
return (index.h("div", { class: "form-header", key: fieldName }, field.title || fieldName));
|
|
5141
5186
|
}
|
|
5142
|
-
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))));
|
|
5143
5188
|
});
|
|
5144
5189
|
}
|
|
5145
5190
|
}
|
|
@@ -5215,7 +5260,8 @@ const VoiceFormRecorder = class {
|
|
|
5215
5260
|
};
|
|
5216
5261
|
}
|
|
5217
5262
|
getContainerStyle() {
|
|
5218
|
-
|
|
5263
|
+
var _a;
|
|
5264
|
+
const c = ((_a = this.parsedTheme) === null || _a === void 0 ? void 0 : _a.container) || {};
|
|
5219
5265
|
return {
|
|
5220
5266
|
width: c.width || 'auto',
|
|
5221
5267
|
height: c.height || 'auto',
|
|
@@ -5227,7 +5273,8 @@ const VoiceFormRecorder = class {
|
|
|
5227
5273
|
};
|
|
5228
5274
|
}
|
|
5229
5275
|
getStatusStyle() {
|
|
5230
|
-
|
|
5276
|
+
var _a;
|
|
5277
|
+
const s = ((_a = this.parsedTheme) === null || _a === void 0 ? void 0 : _a.statusText) || {};
|
|
5231
5278
|
return {
|
|
5232
5279
|
color: s.color || '#1e293b',
|
|
5233
5280
|
fontSize: s.fontSize || '14px'
|