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
@@ -1 +1 @@
1
- {"version":3,"file":"llm.service.js","sourceRoot":"","sources":["../../src/services/llm.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { LLMProvider, SpeechToTextProvider, ServiceProviderConfig, TranscriptionProvider, CompletionProvider } from '../types/service-providers.types';\r\nimport { FormSchema } from '../types/form-schema.types';\r\nimport { fuzzyMatchOption } from '../utils/fuzzy-match';\r\n\r\nexport class OpenAILLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private baseUrl: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n \r\n if (this.useProxy) {\r\n // Mode proxy: pas besoin d'API key\r\n this.apiKey = '';\r\n this.baseUrl = this.proxyUrl;\r\n } else {\r\n // Mode direct: API key requise\r\n this.apiKey = config?.apiKey || this.getEnvironmentVariable('OPENAI_API_KEY') || '';\r\n this.baseUrl = config?.baseUrl || 'https://api.openai.com/v1';\r\n \r\n if (!this.apiKey) {\r\n throw new Error('OpenAI API key is required for LLM service');\r\n }\r\n }\r\n \r\n this.model = config?.model || 'gpt-5-mini';\r\n }\r\n\r\n private getEnvironmentVariable(name: string): string | undefined {\r\n // In browser environment, we might get env vars through other means\r\n if (typeof process !== 'undefined' && process.env) {\r\n return process.env[name];\r\n }\r\n // Check if it's available as a global variable or through other means\r\n return (window as any)[name] || undefined;\r\n }\r\n\r\n private getOptimizeFieldsDescription(schema: any){\r\n if (Array.isArray(schema)) {\r\n return schema.map((field: any) => {\r\n let description = `- ID:${field.id || field.name} | ${field.name || field.title} ` +\r\n `(${field.type}` +\r\n `${field.required ? ', required' : ''}` +\r\n `${field.readonly ? ', readonly' : ''}` +\r\n `${field.default !== undefined && field.default !== null && field.default !== '' ? ', default='+field.default : ''}` +\r\n `${field.min && field.min !== \"\" ? ', min='+field.min : ''}` +\r\n `${field.max && field.max !== \"\" ? ', max='+field.max : ''}` +\r\n `${field.pattern && field.pattern !== \"\" ? ', pattern='+field.pattern : ''}`;\r\n \r\n if (field.options && field.options.length > 0) {\r\n if (field.options.length < 50) {\r\n description += `) - options: ${field.options.join(', ')}`;\r\n } else {\r\n description += `, many options: ${field.options.length} total) - extract raw value, will be matched locally`;\r\n }\r\n } else {\r\n description += ')';\r\n }\r\n \r\n return description;\r\n }).join('\\n');\r\n }\r\n \r\n return Object.entries(schema).map(([fieldName, field]: [string, any]) => {\r\n let description = `- ID:${field.id || fieldName} | ${field.title || fieldName} ` +\r\n `(${field.type}` +\r\n `${field.required ? ', required' : ''}` +\r\n `${field.readonly ? ', readonly' : ''}` +\r\n `${field.default !== undefined && field.default !== null && field.default !== '' ? ', default='+field.default : ''}` +\r\n `${field.min && field.min !== \"\" ? ', min='+field.min : ''}` +\r\n `${field.max && field.max !== \"\" ? ', max='+field.max : ''}` +\r\n `${field.pattern && field.pattern !== \"\" ? ', pattern='+field.pattern : ''}`;\r\n \r\n if (field.options && field.options.length > 0) {\r\n if (field.options.length < 50) {\r\n description += `) - options: ${field.options.join(', ')}`;\r\n } else {\r\n description += `, many options: ${field.options.length} total) - extract raw value, will be matched locally`;\r\n }\r\n } else {\r\n description += ')';\r\n }\r\n \r\n return description;\r\n }).join('\\n');\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema, true);\r\n }\r\n\r\n private applyFuzzyMatching(llmResponse: any, schema: any): any {\r\n // Handle complex schema format with fields array\r\n if (schema?.fields || schema?.schema) {\r\n const finalSchema = schema?.fields || schema?.schema;\r\n const fieldsWithErrors: string[] = [];\r\n \r\n if (llmResponse.fields && Array.isArray(llmResponse.fields)) {\r\n llmResponse.fields = llmResponse.fields.map((field: any) => {\r\n // Find corresponding schema field\r\n const schemaField = Object.values(finalSchema).find((sf: any) => \r\n (sf.name === field.name || sf.title === field.name)\r\n ) as any;\r\n \r\n if (schemaField && schemaField.options && schemaField.options.length >= 50 && field.value) {\r\n const isMultiselect = schemaField.type === 'multiselect';\r\n \r\n // Handle multiselect (array of values)\r\n if (isMultiselect && Array.isArray(field.value)) {\r\n const matchedValues: string[] = [];\r\n const failedValues: string[] = [];\r\n \r\n field.value.forEach((val: string) => {\r\n const matchResult = fuzzyMatchOption(val, schemaField.options);\r\n if (matchResult) {\r\n matchedValues.push(matchResult.match);\r\n } else {\r\n failedValues.push(val);\r\n }\r\n });\r\n \r\n if (failedValues.length > 0) {\r\n fieldsWithErrors.push(field.name);\r\n field.error = `Could not match values: ${failedValues.join(', ')}`;\r\n }\r\n \r\n field.value = matchedValues.length > 0 ? matchedValues : null;\r\n field.fuzzyMatchConfidence = matchedValues.length / (matchedValues.length + failedValues.length);\r\n } else if (!isMultiselect) {\r\n // Handle single value (select, classification, thesaurus, position)\r\n const singleValue = Array.isArray(field.value) ? field.value[0] : field.value;\r\n const matchResult = fuzzyMatchOption(singleValue, schemaField.options);\r\n \r\n if (matchResult) {\r\n field.value = matchResult.match;\r\n field.fuzzyMatchConfidence = matchResult.confidence;\r\n } else {\r\n fieldsWithErrors.push(field.name);\r\n field.value = null;\r\n field.error = `Could not match \"${singleValue}\" to available options`;\r\n }\r\n }\r\n }\r\n \r\n return field;\r\n });\r\n }\r\n \r\n if (fieldsWithErrors.length > 0) {\r\n llmResponse.matchingErrors = fieldsWithErrors;\r\n }\r\n \r\n return llmResponse;\r\n }\r\n \r\n // Handle simple schema format\r\n if (schema?.schema) {\r\n const fieldsWithErrors: string[] = [];\r\n \r\n Object.entries(schema.schema).forEach(([fieldName, fieldDef]: [string, any]) => {\r\n if (fieldDef.options && fieldDef.options.length >= 50) {\r\n const fieldValue = llmResponse.schema?.[fieldName]?.default;\r\n \r\n if (fieldValue) {\r\n const isMultiselect = fieldDef.type === 'multiselect';\r\n \r\n // Handle multiselect (array of values)\r\n if (isMultiselect && Array.isArray(fieldValue)) {\r\n const matchedValues: string[] = [];\r\n const failedValues: string[] = [];\r\n \r\n fieldValue.forEach((val: string) => {\r\n const matchResult = fuzzyMatchOption(val, fieldDef.options);\r\n if (matchResult) {\r\n matchedValues.push(matchResult.match);\r\n } else {\r\n failedValues.push(val);\r\n }\r\n });\r\n \r\n if (failedValues.length > 0) {\r\n fieldsWithErrors.push(fieldName);\r\n llmResponse.schema[fieldName].error = `Could not match values: ${failedValues.join(', ')}`;\r\n }\r\n \r\n llmResponse.schema[fieldName].default = matchedValues.length > 0 ? matchedValues : null;\r\n llmResponse.schema[fieldName].fuzzyMatchConfidence = matchedValues.length / (matchedValues.length + failedValues.length);\r\n } else if (!isMultiselect) {\r\n // Handle single value (select, classification, thesaurus, position)\r\n const singleValue = Array.isArray(fieldValue) ? fieldValue[0] : fieldValue;\r\n const matchResult = fuzzyMatchOption(singleValue, fieldDef.options);\r\n \r\n if (matchResult) {\r\n llmResponse.schema[fieldName].default = matchResult.match;\r\n llmResponse.schema[fieldName].fuzzyMatchConfidence = matchResult.confidence;\r\n } else {\r\n fieldsWithErrors.push(fieldName);\r\n llmResponse.schema[fieldName].default = null;\r\n llmResponse.schema[fieldName].error = `Could not match \"${singleValue}\" to available options`;\r\n }\r\n }\r\n }\r\n }\r\n });\r\n \r\n if (fieldsWithErrors.length > 0) {\r\n llmResponse.matchingErrors = fieldsWithErrors;\r\n }\r\n }\r\n \r\n return llmResponse;\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema, false);\r\n }\r\n\r\n private async fillForm(data: string, schema: any, dataIsTranscription: boolean = true): Promise<any> {\r\n try {\r\n // Handle complex schema format with fields array\r\n if (schema?.fields || schema?.schema) {\r\n const finalSchema = schema?.fields || schema?.schema;\r\n const systemPrompt = `You are an expert form-filling assistant. You will receive a voice transcription and form field definitions. Your task is to extract values from the spoken content.\r\n Rules:\r\n 1. Only extract values that can be confidently determined from the transcription\r\n 2. Respect field types (string, number, datetime, boolean, select)\r\n 3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n 4. For date fields, use the following format: DD/MM/YYYY\r\n 5. For boolean fields, interpret yes/no, true/false, positive/negative responses\r\n 6. For select fields, use exact option values from the provided choices\r\n 7. Only include fields where relevant information is found\r\n 8. The current GMT datetime is ${(new Date() as any).toGMTString()}\r\n 9. Respect the constraints written between parenthesis for readonly status (readonly fields MUST NOT be filled with values), min and max values, whatever the transcription says\r\n 9b. CRITICAL - DATE/DATETIME OUT OF RANGE: For date and datetime fields with min and/or max constraints, if the value from the transcription falls outside the allowed range, leave the field EMPTY. NEVER clamp, adjust, or substitute a boundary date - either the date is valid and within range, or the field is left empty\r\n 10. IMPORTANT: Fields marked as \"readonly\" are presentation elements (headers, labels) that provide context but MUST NOT receive values\r\n 11. CRITICAL - DUPLICATE FIELDS: When you see multiple fields with the same name but different IDs (e.g., \"ID:field1 | Event date\" and \"ID:field2 | Event date\"), these are DIFFERENT fields in DIFFERENT sections. The user may explicitly say which section they are filling (e.g., \"for the first/second sub-form\"). Listen VERY CAREFULLY to these contextual clues. Use the readonly headers to understand which section each field belongs to. If the user says \"for the clinical sign, the event date is X\", you must fill the Event date field that comes AFTER the \"MC Clinical sign\" header, NOT the first Event date you see\r\n 12. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them\r\n 13. 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\r\n 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\r\n 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\r\n 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\r\n\r\n Respond with JSON in this exact format: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\"}]}`;\r\n\r\n let userPrompt = `\r\n Voice transcription: \"${data}\"\r\n\r\n Form fields:\r\n ${this.getOptimizeFieldsDescription(finalSchema)}\r\n\r\n Please extract values from the Transcription for these fields.\r\n `;\r\n\r\n //TODO\r\n\r\n // const userPrompt = (\r\n // dataIsTranscription \r\n // ?\r\n // `Voice transcription: \"${data}\"`\r\n // : \r\n // `Json datas: \"${JSON.stringify(data)}\"`\r\n // )+`\r\n\r\n // Form fields:\r\n // ${this.getOptimizeFieldsDescription(finalSchema)}\r\n\r\n // Please extract values from the ` + \r\n // (\r\n // dataIsTranscription \r\n // ?\r\n // `Transcription`\r\n // : \r\n // `Json generated file`\r\n // )+` for these fields.`;\r\n\r\n const endpoint = this.useProxy ? `${this.baseUrl}/complete` : `${this.baseUrl}/chat/completions`;\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n \r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers: headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: userPrompt }\r\n ],\r\n response_format: { type: 'json_object' },\r\n temperature: 1,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`LLM API failed: ${errorData.error?.message || response.statusText}`);\r\n }\r\n\r\n const result = await response.json();\r\n const llmResponse = JSON.parse(result.choices[0].message.content);\r\n \r\n // Apply fuzzy matching for fields with many options\r\n return this.applyFuzzyMatching(llmResponse, schema);\r\n }\r\n\r\n // Handle simple schema format (backward compatibility)\r\n const systemPrompt = `You are an expert form-filling assistant. You will receive a voice transcription and a JSON form schema. Your task is to intelligently fill the form fields based on the spoken content.\r\n Rules:\r\n 1. Only fill fields that can be confidently determined from the transcription\r\n 2. Respect field types (string, number, date, boolean, select)\r\n 3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n 4. For date fields, use the following format: DD/MM/YYYY\r\n 5. For boolean fields, interpret yes/no, true/false, positive/negative responses\r\n 6. For select fields, match the closest option from the provided choices\r\n 7. Leave fields empty if no relevant information is found\r\n 8. Return the same schema structure with 'default' values filled\r\n 9. The current GMT datetime is ${(new Date() as any).toGMTString()}\r\n 10. Respect the constraints written between parenthesis for readonly status (readonly fields MUST NOT be filled with values), min and max values, whatever the transcription says\r\n 10b. CRITICAL - DATE/DATETIME OUT OF RANGE: For date and datetime fields with min and/or max constraints, if the value from the transcription falls outside the allowed range, leave the field EMPTY. NEVER clamp, adjust, or substitute a boundary date - either the date is valid and within range, or the field is left empty\r\n 11. IMPORTANT: Fields marked as \"readonly\" are presentation elements (headers, labels) that provide context but MUST NOT receive values\r\n 12. CRITICAL - DUPLICATE FIELDS: When you see multiple fields with the same name but different IDs (e.g., \"ID:field1 | Event date\" and \"ID:field2 | Event date\"), these are DIFFERENT fields in DIFFERENT sections. The user will explicitly say which section they are filling (e.g., \"for the first/second sub-form\", \"in the anamnesis section\", \"for the clinical sign\"). Listen VERY CAREFULLY to these contextual clues. Use the readonly headers to understand which section each field belongs to. If the user says \"for the clinical sign, the event date is X\", you must fill the Event date field that comes AFTER the \"MC Clinical sign\" header, NOT the first Event date you see\r\n 13. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them\r\n 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\r\n 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\r\n\r\n Respond with JSON in this exact format: {\"schema\": {...}}`;\r\n\r\n let userPrompt = `\r\n Voice transcription: \"${data}\"\r\n\r\n Form schema to fill:\r\n ${JSON.stringify(schema, null, 2)}\r\n\r\n Please fill the form fields based on the Transcription and return the schema with default values populated.\r\n `;\r\n\r\n // const userPrompt = (\r\n // dataIsTranscription \r\n // ?\r\n // `Voice transcription: \"${data}\"`\r\n // : \r\n // `Json datas: \"${JSON.stringify(data)}\"`\r\n // )+`\r\n\r\n // Form schema to fill:\r\n // ${JSON.stringify(schema, null, 2)}\r\n\r\n // Please fill the form fields based on the ` + \r\n // (\r\n // dataIsTranscription \r\n // ?\r\n // `Transcription`\r\n // : \r\n // `Json generated file`\r\n // )+` nd return the schema with default values populated.`;\r\n\r\n const endpoint = this.useProxy ? `${this.baseUrl}/complete` : `${this.baseUrl}/chat/completions`;\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n \r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers: headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: userPrompt }\r\n ],\r\n response_format: { type: 'json_object' },\r\n temperature: 1, // Low temperature for consistency\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`LLM API failed: ${errorData.error?.message || response.statusText}`);\r\n }\r\n\r\n const result = await response.json();\r\n const filledSchema = JSON.parse(result.choices[0].message.content);\r\n \r\n // Validate that the response has the correct structure\r\n if (!filledSchema.schema) {\r\n throw new Error('Invalid response format from LLM service');\r\n }\r\n\r\n // Apply fuzzy matching for fields with many options\r\n return this.applyFuzzyMatching(filledSchema, schema);\r\n } catch (error) {\r\n throw new Error(`Form filling failed: ${error.message}`);\r\n }\r\n }\r\n}\r\n\r\nexport class AnthropicLLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n this.model = config?.model || 'claude-sonnet-4.5';\r\n this.apiKey = this.useProxy ? '' : (config?.apiKey || '');\r\n if (!this.useProxy && !this.apiKey) {\r\n throw new Error('Anthropic API key is required');\r\n }\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema);\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema);\r\n }\r\n\r\n private async fillForm(data: string, schema: any): Promise<any> {\r\n const endpoint = this.useProxy ? `${this.proxyUrl}/complete-anthropic` : 'https://api.anthropic.com/v1/messages';\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n if (!this.useProxy) {\r\n headers['x-api-key'] = this.apiKey;\r\n headers['anthropic-version'] = '2023-06-01';\r\n }\r\n\r\n const finalSchema = schema?.fields || schema?.schema || schema;\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = `Data: \"${data}\"\r\n\r\nForm fields:\r\n${JSON.stringify(finalSchema, null, 2)}\r\n\r\nRespond with JSON: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\"}]}`;\r\n\r\n const body = this.useProxy\r\n ? { model: this.model, messages: [{ role: 'user', content: userPrompt }], system: systemPrompt }\r\n : { model: this.model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userPrompt }] };\r\n\r\n const response = await fetch(endpoint, { method: 'POST', headers, body: JSON.stringify(body) });\r\n if (!response.ok) {\r\n const err = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`Anthropic API failed: ${err.error?.message || response.statusText}`);\r\n }\r\n const result = await response.json();\r\n const content = this.useProxy ? result.choices[0].message.content : result.content[0].text;\r\n return JSON.parse(content);\r\n }\r\n\r\n private buildSystemPrompt(): string {\r\n return `You are an expert form-filling assistant. Extract values from the input data and fill form fields.\r\nRules:\r\n1. Only extract values that can be confidently determined\r\n2. Respect field types (string, number, datetime, boolean, select)\r\n3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n4. For date fields, use DD/MM/YYYY format\r\n5. For select fields, use exact option values from the provided choices\r\n6. Leave fields empty if no relevant information is found\r\n7. Fields marked readonly MUST NOT receive values\r\n8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY\r\n9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty\r\n10. UNKNOWN VALUES: if the user says \"Unknown\" and it exists as an option, select it; otherwise leave empty\r\nRespond ONLY with valid JSON.`;\r\n }\r\n}\r\n\r\nexport class MistralLLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n this.model = config?.model || 'mistral-medium-latest';\r\n this.apiKey = this.useProxy ? '' : (config?.apiKey || '');\r\n if (!this.useProxy && !this.apiKey) {\r\n throw new Error('Mistral API key is required');\r\n }\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema);\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema);\r\n }\r\n\r\n private async fillForm(data: string, schema: any): Promise<any> {\r\n const endpoint = this.useProxy ? `${this.proxyUrl}/complete-mistral` : 'https://api.mistral.ai/v1/chat/completions';\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const finalSchema = schema?.fields || schema?.schema || schema;\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = `Data: \"${data}\"\r\n\r\nForm fields:\r\n${JSON.stringify(finalSchema, null, 2)}\r\n\r\nRespond with JSON: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\"}]}`;\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }],\r\n response_format: { type: 'json_object' },\r\n }),\r\n });\r\n if (!response.ok) {\r\n const err = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`Mistral API failed: ${err.error?.message || response.statusText}`);\r\n }\r\n const result = await response.json();\r\n return JSON.parse(result.choices[0].message.content);\r\n }\r\n\r\n private buildSystemPrompt(): string {\r\n return `You are an expert form-filling assistant. Extract values from the input data and fill form fields.\r\nRules:\r\n1. Only extract values that can be confidently determined\r\n2. Respect field types (string, number, datetime, boolean, select)\r\n3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n4. For date fields, use DD/MM/YYYY format\r\n5. For select fields, use exact option values from the provided choices\r\n6. Leave fields empty if no relevant information is found\r\n7. Fields marked readonly MUST NOT receive values\r\n8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY\r\n9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty\r\n10. UNKNOWN VALUES: if the user says \"Unknown\" and it exists as an option, select it; otherwise leave empty\r\nRespond ONLY with valid JSON.`;\r\n }\r\n}\r\n\r\nexport class LLMServiceFactory {\r\n static create(config: ServiceProviderConfig): LLMProvider {\r\n const provider = config.llm?.provider || 'openai';\r\n switch (provider) {\r\n case 'openai': return new OpenAILLMService(config.llm);\r\n case 'anthropic': return new AnthropicLLMService(config.llm);\r\n case 'mistral': return new MistralLLMService(config.llm);\r\n default: throw new Error(`Unsupported LLM provider: ${provider}`);\r\n }\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"llm.service.js","sourceRoot":"","sources":["../../src/services/llm.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { LLMProvider, SpeechToTextProvider, ServiceProviderConfig, TranscriptionProvider, CompletionProvider } from '../types/service-providers.types';\r\nimport { FormSchema } from '../types/form-schema.types';\r\nimport { fuzzyMatchOption } from '../utils/fuzzy-match';\r\n\r\nexport class OpenAILLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private baseUrl: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n \r\n if (this.useProxy) {\r\n // Mode proxy: pas besoin d'API key\r\n this.apiKey = '';\r\n this.baseUrl = this.proxyUrl;\r\n } else {\r\n // Mode direct: API key requise\r\n this.apiKey = config?.apiKey || this.getEnvironmentVariable('OPENAI_API_KEY') || '';\r\n this.baseUrl = config?.baseUrl || 'https://api.openai.com/v1';\r\n \r\n if (!this.apiKey) {\r\n throw new Error('OpenAI API key is required for LLM service');\r\n }\r\n }\r\n \r\n this.model = config?.model || 'gpt-5-mini';\r\n }\r\n\r\n private getEnvironmentVariable(name: string): string | undefined {\r\n // In browser environment, we might get env vars through other means\r\n if (typeof process !== 'undefined' && process.env) {\r\n return process.env[name];\r\n }\r\n // Check if it's available as a global variable or through other means\r\n return (window as any)[name] || undefined;\r\n }\r\n\r\n private getOptimizeFieldsDescription(schema: any){\r\n if (Array.isArray(schema)) {\r\n return schema.map((field: any) => {\r\n let description = `- ID:${field.id || field.name} | ${field.name || field.title} ` +\r\n `(${field.type}` +\r\n `${field.required ? ', required' : ''}` +\r\n `${field.readonly ? ', readonly' : ''}` +\r\n `${field.default !== undefined && field.default !== null && field.default !== '' ? ', default='+field.default : ''}` +\r\n `${field.min && field.min !== \"\" ? ', min='+field.min : ''}` +\r\n `${field.max && field.max !== \"\" ? ', max='+field.max : ''}` +\r\n `${field.pattern && field.pattern !== \"\" ? ', pattern='+field.pattern : ''}`;\r\n \r\n if (field.options && field.options.length > 0) {\r\n if (field.options.length < 50) {\r\n description += `) - options: ${field.options.join(', ')}`;\r\n } else {\r\n description += `, many options: ${field.options.length} total) - extract raw value, will be matched locally`;\r\n }\r\n } else {\r\n description += ')';\r\n }\r\n \r\n return description;\r\n }).join('\\n');\r\n }\r\n \r\n return Object.entries(schema).map(([fieldName, field]: [string, any]) => {\r\n let description = `- ID:${field.id || fieldName} | ${field.title || fieldName} ` +\r\n `(${field.type}` +\r\n `${field.required ? ', required' : ''}` +\r\n `${field.readonly ? ', readonly' : ''}` +\r\n `${field.default !== undefined && field.default !== null && field.default !== '' ? ', default='+field.default : ''}` +\r\n `${field.min && field.min !== \"\" ? ', min='+field.min : ''}` +\r\n `${field.max && field.max !== \"\" ? ', max='+field.max : ''}` +\r\n `${field.pattern && field.pattern !== \"\" ? ', pattern='+field.pattern : ''}`;\r\n \r\n if (field.options && field.options.length > 0) {\r\n if (field.options.length < 50) {\r\n description += `) - options: ${field.options.join(', ')}`;\r\n } else {\r\n description += `, many options: ${field.options.length} total) - extract raw value, will be matched locally`;\r\n }\r\n } else {\r\n description += ')';\r\n }\r\n \r\n return description;\r\n }).join('\\n');\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema, true);\r\n }\r\n\r\n private applyFuzzyMatching(llmResponse: any, schema: any): any {\r\n // Handle complex schema format with fields array\r\n if (schema?.fields || schema?.schema) {\r\n const finalSchema = schema?.fields || schema?.schema;\r\n const fieldsWithErrors: string[] = [];\r\n \r\n if (llmResponse.fields && Array.isArray(llmResponse.fields)) {\r\n llmResponse.fields = llmResponse.fields.map((field: any) => {\r\n // Find corresponding schema field\r\n const schemaField = Object.values(finalSchema).find((sf: any) => \r\n (sf.name === field.name || sf.title === field.name)\r\n ) as any;\r\n \r\n if (schemaField && schemaField.options && schemaField.options.length >= 50 && field.value) {\r\n const isMultiselect = schemaField.type === 'multiselect';\r\n \r\n // Handle multiselect (array of values)\r\n if (isMultiselect && Array.isArray(field.value)) {\r\n const matchedValues: string[] = [];\r\n const failedValues: string[] = [];\r\n \r\n field.value.forEach((val: string) => {\r\n const matchResult = fuzzyMatchOption(val, schemaField.options);\r\n if (matchResult) {\r\n matchedValues.push(matchResult.match);\r\n } else {\r\n failedValues.push(val);\r\n }\r\n });\r\n \r\n if (failedValues.length > 0) {\r\n fieldsWithErrors.push(field.name);\r\n field.error = `Could not match values: ${failedValues.join(', ')}`;\r\n }\r\n \r\n field.value = matchedValues.length > 0 ? matchedValues : null;\r\n field.fuzzyMatchConfidence = matchedValues.length / (matchedValues.length + failedValues.length);\r\n } else if (!isMultiselect) {\r\n // Handle single value (select, classification, thesaurus, position)\r\n const singleValue = Array.isArray(field.value) ? field.value[0] : field.value;\r\n const matchResult = fuzzyMatchOption(singleValue, schemaField.options);\r\n \r\n if (matchResult) {\r\n field.value = matchResult.match;\r\n field.fuzzyMatchConfidence = matchResult.confidence;\r\n } else {\r\n fieldsWithErrors.push(field.name);\r\n field.value = null;\r\n field.error = `Could not match \"${singleValue}\" to available options`;\r\n }\r\n }\r\n }\r\n \r\n return field;\r\n });\r\n }\r\n \r\n if (fieldsWithErrors.length > 0) {\r\n llmResponse.matchingErrors = fieldsWithErrors;\r\n }\r\n \r\n return llmResponse;\r\n }\r\n \r\n // Handle simple schema format\r\n if (schema?.schema) {\r\n const fieldsWithErrors: string[] = [];\r\n \r\n Object.entries(schema.schema).forEach(([fieldName, fieldDef]: [string, any]) => {\r\n if (fieldDef.options && fieldDef.options.length >= 50) {\r\n const fieldValue = llmResponse.schema?.[fieldName]?.default;\r\n \r\n if (fieldValue) {\r\n const isMultiselect = fieldDef.type === 'multiselect';\r\n \r\n // Handle multiselect (array of values)\r\n if (isMultiselect && Array.isArray(fieldValue)) {\r\n const matchedValues: string[] = [];\r\n const failedValues: string[] = [];\r\n \r\n fieldValue.forEach((val: string) => {\r\n const matchResult = fuzzyMatchOption(val, fieldDef.options);\r\n if (matchResult) {\r\n matchedValues.push(matchResult.match);\r\n } else {\r\n failedValues.push(val);\r\n }\r\n });\r\n \r\n if (failedValues.length > 0) {\r\n fieldsWithErrors.push(fieldName);\r\n llmResponse.schema[fieldName].error = `Could not match values: ${failedValues.join(', ')}`;\r\n }\r\n \r\n llmResponse.schema[fieldName].default = matchedValues.length > 0 ? matchedValues : null;\r\n llmResponse.schema[fieldName].fuzzyMatchConfidence = matchedValues.length / (matchedValues.length + failedValues.length);\r\n } else if (!isMultiselect) {\r\n // Handle single value (select, classification, thesaurus, position)\r\n const singleValue = Array.isArray(fieldValue) ? fieldValue[0] : fieldValue;\r\n const matchResult = fuzzyMatchOption(singleValue, fieldDef.options);\r\n \r\n if (matchResult) {\r\n llmResponse.schema[fieldName].default = matchResult.match;\r\n llmResponse.schema[fieldName].fuzzyMatchConfidence = matchResult.confidence;\r\n } else {\r\n fieldsWithErrors.push(fieldName);\r\n llmResponse.schema[fieldName].default = null;\r\n llmResponse.schema[fieldName].error = `Could not match \"${singleValue}\" to available options`;\r\n }\r\n }\r\n }\r\n }\r\n });\r\n \r\n if (fieldsWithErrors.length > 0) {\r\n llmResponse.matchingErrors = fieldsWithErrors;\r\n }\r\n }\r\n \r\n return llmResponse;\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema, false);\r\n }\r\n\r\n private async fillForm(data: string, schema: any, dataIsTranscription: boolean = true): Promise<any> {\r\n try {\r\n // Handle complex schema format with fields array\r\n if (schema?.fields || schema?.schema) {\r\n const finalSchema = schema?.fields || schema?.schema;\r\n const systemPrompt = `You are an expert form-filling assistant. You will receive a voice transcription and form field definitions. Your task is to extract values from the spoken content.\r\n Rules:\r\n 1. Only extract values that can be confidently determined from the transcription\r\n 2. Respect field types (string, number, datetime, boolean, select)\r\n 3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n 4. For date fields, use the following format: DD/MM/YYYY\r\n 5. For boolean fields, interpret yes/no, true/false, positive/negative responses\r\n 6. For select fields, use exact option values from the provided choices\r\n 7. Only include fields where relevant information is found\r\n 8. The current GMT datetime is ${(new Date() as any).toGMTString()}\r\n 9. Respect the constraints written between parenthesis for readonly status (readonly fields MUST NOT be filled with values), min and max values, whatever the transcription says\r\n 9b. CRITICAL - DATE/DATETIME OUT OF RANGE: For date and datetime fields with min and/or max constraints, if the value from the transcription falls outside the allowed range, leave the field EMPTY. NEVER clamp, adjust, or substitute a boundary date - either the date is valid and within range, or the field is left empty\r\n 10. IMPORTANT: Fields marked as \"readonly\" are presentation elements (headers, labels) that provide context but MUST NOT receive values\r\n 11. CRITICAL - DUPLICATE FIELDS: When you see multiple fields with the same name but different IDs (e.g., \"ID:field1 | Event date\" and \"ID:field2 | Event date\"), these are DIFFERENT fields in DIFFERENT sections. The user may explicitly say which section they are filling (e.g., \"for the first/second sub-form\"). Listen VERY CAREFULLY to these contextual clues. Use the readonly headers to understand which section each field belongs to. If the user says \"for the clinical sign, the event date is X\", you must fill the Event date field that comes AFTER the \"MC Clinical sign\" header, NOT the first Event date you see\r\n 12. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them\r\n 13. 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\r\n 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\r\n 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\r\n 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\r\n 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.\r\n\r\n Respond with JSON in this exact format: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\", \"confidence\": 0.87}]}`;\r\n\r\n let userPrompt = `\r\n Voice transcription: \"${data}\"\r\n\r\n Form fields:\r\n ${this.getOptimizeFieldsDescription(finalSchema)}\r\n\r\n Please extract values from the Transcription for these fields.\r\n `;\r\n\r\n //TODO\r\n\r\n // const userPrompt = (\r\n // dataIsTranscription \r\n // ?\r\n // `Voice transcription: \"${data}\"`\r\n // : \r\n // `Json datas: \"${JSON.stringify(data)}\"`\r\n // )+`\r\n\r\n // Form fields:\r\n // ${this.getOptimizeFieldsDescription(finalSchema)}\r\n\r\n // Please extract values from the ` + \r\n // (\r\n // dataIsTranscription \r\n // ?\r\n // `Transcription`\r\n // : \r\n // `Json generated file`\r\n // )+` for these fields.`;\r\n\r\n const endpoint = this.useProxy ? `${this.baseUrl}/complete` : `${this.baseUrl}/chat/completions`;\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n \r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers: headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: userPrompt }\r\n ],\r\n response_format: { type: 'json_object' },\r\n temperature: 1,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`LLM API failed: ${errorData.error?.message || response.statusText}`);\r\n }\r\n\r\n const result = await response.json();\r\n const llmResponse = JSON.parse(result.choices[0].message.content);\r\n \r\n // Apply fuzzy matching for fields with many options\r\n return this.applyFuzzyMatching(llmResponse, schema);\r\n }\r\n\r\n // Handle simple schema format (backward compatibility)\r\n const systemPrompt = `You are an expert form-filling assistant. You will receive a voice transcription and a JSON form schema. Your task is to intelligently fill the form fields based on the spoken content.\r\n Rules:\r\n 1. Only fill fields that can be confidently determined from the transcription\r\n 2. Respect field types (string, number, date, boolean, select)\r\n 3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n 4. For date fields, use the following format: DD/MM/YYYY\r\n 5. For boolean fields, interpret yes/no, true/false, positive/negative responses\r\n 6. For select fields, match the closest option from the provided choices\r\n 7. Leave fields empty if no relevant information is found\r\n 8. Return the same schema structure with 'default' values filled\r\n 9. The current GMT datetime is ${(new Date() as any).toGMTString()}\r\n 10. Respect the constraints written between parenthesis for readonly status (readonly fields MUST NOT be filled with values), min and max values, whatever the transcription says\r\n 10b. CRITICAL - DATE/DATETIME OUT OF RANGE: For date and datetime fields with min and/or max constraints, if the value from the transcription falls outside the allowed range, leave the field EMPTY. NEVER clamp, adjust, or substitute a boundary date - either the date is valid and within range, or the field is left empty\r\n 11. IMPORTANT: Fields marked as \"readonly\" are presentation elements (headers, labels) that provide context but MUST NOT receive values\r\n 12. CRITICAL - DUPLICATE FIELDS: When you see multiple fields with the same name but different IDs (e.g., \"ID:field1 | Event date\" and \"ID:field2 | Event date\"), these are DIFFERENT fields in DIFFERENT sections. The user will explicitly say which section they are filling (e.g., \"for the first/second sub-form\", \"in the anamnesis section\", \"for the clinical sign\"). Listen VERY CAREFULLY to these contextual clues. Use the readonly headers to understand which section each field belongs to. If the user says \"for the clinical sign, the event date is X\", you must fill the Event date field that comes AFTER the \"MC Clinical sign\" header, NOT the first Event date you see\r\n 13. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them\r\n 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\r\n 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\r\n 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.\r\n\r\n Respond with JSON in this exact format: {\"schema\": {...}, \"confidence\": {\"field_name\": 0.87}}`;\r\n\r\n let userPrompt = `\r\n Voice transcription: \"${data}\"\r\n\r\n Form schema to fill:\r\n ${JSON.stringify(schema, null, 2)}\r\n\r\n Please fill the form fields based on the Transcription and return the schema with default values populated.\r\n `;\r\n\r\n // const userPrompt = (\r\n // dataIsTranscription \r\n // ?\r\n // `Voice transcription: \"${data}\"`\r\n // : \r\n // `Json datas: \"${JSON.stringify(data)}\"`\r\n // )+`\r\n\r\n // Form schema to fill:\r\n // ${JSON.stringify(schema, null, 2)}\r\n\r\n // Please fill the form fields based on the ` + \r\n // (\r\n // dataIsTranscription \r\n // ?\r\n // `Transcription`\r\n // : \r\n // `Json generated file`\r\n // )+` nd return the schema with default values populated.`;\r\n\r\n const endpoint = this.useProxy ? `${this.baseUrl}/complete` : `${this.baseUrl}/chat/completions`;\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n \r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers: headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [\r\n { role: 'system', content: systemPrompt },\r\n { role: 'user', content: userPrompt }\r\n ],\r\n response_format: { type: 'json_object' },\r\n temperature: 1, // Low temperature for consistency\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n const errorData = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`LLM API failed: ${errorData.error?.message || response.statusText}`);\r\n }\r\n\r\n const result = await response.json();\r\n const filledSchema = JSON.parse(result.choices[0].message.content);\r\n \r\n // Validate that the response has the correct structure\r\n if (!filledSchema.schema) {\r\n throw new Error('Invalid response format from LLM service');\r\n }\r\n\r\n // Apply fuzzy matching for fields with many options\r\n return this.applyFuzzyMatching(filledSchema, schema);\r\n } catch (error) {\r\n throw new Error(`Form filling failed: ${error.message}`);\r\n }\r\n }\r\n}\r\n\r\nexport class AnthropicLLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n this.model = config?.model || 'claude-sonnet-4.5';\r\n this.apiKey = this.useProxy ? '' : (config?.apiKey || '');\r\n if (!this.useProxy && !this.apiKey) {\r\n throw new Error('Anthropic API key is required');\r\n }\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema);\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema);\r\n }\r\n\r\n private async fillForm(data: string, schema: any): Promise<any> {\r\n const endpoint = this.useProxy ? `${this.proxyUrl}/complete-anthropic` : 'https://api.anthropic.com/v1/messages';\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n if (!this.useProxy) {\r\n headers['x-api-key'] = this.apiKey;\r\n headers['anthropic-version'] = '2023-06-01';\r\n }\r\n\r\n const finalSchema = schema?.fields || schema?.schema || schema;\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = `Data: \"${data}\"\r\n\r\nForm fields:\r\n${JSON.stringify(finalSchema, null, 2)}\r\n\r\nRespond with JSON: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\", \"confidence\": 0.87}]}`;\r\n\r\n const body = this.useProxy\r\n ? { model: this.model, messages: [{ role: 'user', content: userPrompt }], system: systemPrompt }\r\n : { model: this.model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userPrompt }] };\r\n\r\n const response = await fetch(endpoint, { method: 'POST', headers, body: JSON.stringify(body) });\r\n if (!response.ok) {\r\n const err = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`Anthropic API failed: ${err.error?.message || response.statusText}`);\r\n }\r\n const result = await response.json();\r\n const content = this.useProxy ? result.choices[0].message.content : result.content[0].text;\r\n return JSON.parse(content);\r\n }\r\n\r\n private buildSystemPrompt(): string {\r\n return `You are an expert form-filling assistant. Extract values from the input data and fill form fields.\r\nRules:\r\n1. Only extract values that can be confidently determined\r\n2. Respect field types (string, number, datetime, boolean, select)\r\n3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n4. For date fields, use DD/MM/YYYY format\r\n5. For select fields, use exact option values from the provided choices\r\n6. Leave fields empty if no relevant information is found\r\n7. Fields marked readonly MUST NOT receive values\r\n8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY\r\n9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty\r\n10. UNKNOWN VALUES: if the user says \"Unknown\" and it exists as an option, select it; otherwise leave empty\r\n11. 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.\r\nRespond ONLY with valid JSON.`;\r\n }\r\n}\r\n\r\nexport class MistralLLMService implements LLMProvider {\r\n private apiKey: string;\r\n private model: string;\r\n private useProxy: boolean;\r\n private proxyUrl: string;\r\n\r\n constructor(config: ServiceProviderConfig['llm']) {\r\n this.useProxy = config?.useProxy || false;\r\n this.proxyUrl = config?.proxyUrl || 'http://localhost:8492';\r\n this.model = config?.model || 'mistral-medium-latest';\r\n this.apiKey = this.useProxy ? '' : (config?.apiKey || '');\r\n if (!this.useProxy && !this.apiKey) {\r\n throw new Error('Mistral API key is required');\r\n }\r\n }\r\n\r\n async fillFormFromTranscription(transcription: string, schema: any): Promise<any> {\r\n return this.fillForm(transcription, schema);\r\n }\r\n\r\n async fillFormFromJson(json: string, schema: any): Promise<any> {\r\n return this.fillForm(json, schema);\r\n }\r\n\r\n private async fillForm(data: string, schema: any): Promise<any> {\r\n const endpoint = this.useProxy ? `${this.proxyUrl}/complete-mistral` : 'https://api.mistral.ai/v1/chat/completions';\r\n const headers: any = { 'Content-Type': 'application/json' };\r\n if (!this.useProxy) {\r\n headers['Authorization'] = `Bearer ${this.apiKey}`;\r\n }\r\n\r\n const finalSchema = schema?.fields || schema?.schema || schema;\r\n const systemPrompt = this.buildSystemPrompt();\r\n const userPrompt = `Data: \"${data}\"\r\n\r\nForm fields:\r\n${JSON.stringify(finalSchema, null, 2)}\r\n\r\nRespond with JSON: {\"fields\": [{\"id\": \"field_id\", \"name\": \"field_name\", \"value\": \"extracted_value\", \"confidence\": 0.87}]}`;\r\n\r\n const response = await fetch(endpoint, {\r\n method: 'POST',\r\n headers,\r\n body: JSON.stringify({\r\n model: this.model,\r\n messages: [{ role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }],\r\n response_format: { type: 'json_object' },\r\n }),\r\n });\r\n if (!response.ok) {\r\n const err = await response.json().catch(() => ({ error: 'Unknown error' }));\r\n throw new Error(`Mistral API failed: ${err.error?.message || response.statusText}`);\r\n }\r\n const result = await response.json();\r\n return JSON.parse(result.choices[0].message.content);\r\n }\r\n\r\n private buildSystemPrompt(): string {\r\n return `You are an expert form-filling assistant. Extract values from the input data and fill form fields.\r\nRules:\r\n1. Only extract values that can be confidently determined\r\n2. Respect field types (string, number, datetime, boolean, select)\r\n3. For datetime fields, use ISO format (YYYY-MM-DDTHH:MM)\r\n4. For date fields, use DD/MM/YYYY format\r\n5. For select fields, use exact option values from the provided choices\r\n6. Leave fields empty if no relevant information is found\r\n7. Fields marked readonly MUST NOT receive values\r\n8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY\r\n9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty\r\n10. UNKNOWN VALUES: if the user says \"Unknown\" and it exists as an option, select it; otherwise leave empty\r\n11. 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.\r\nRespond ONLY with valid JSON.`;\r\n }\r\n}\r\n\r\nexport class LLMServiceFactory {\r\n static create(config: ServiceProviderConfig): LLMProvider {\r\n const provider = config.llm?.provider || 'openai';\r\n switch (provider) {\r\n case 'openai': return new OpenAILLMService(config.llm);\r\n case 'anthropic': return new AnthropicLLMService(config.llm);\r\n case 'mistral': return new MistralLLMService(config.llm);\r\n default: throw new Error(`Unsupported LLM provider: ${provider}`);\r\n }\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"form-schema.types.js","sourceRoot":"","sources":["../../src/types/form-schema.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FormField {\r\n id?: string;\r\n type: 'string' | 'number' | 'date' | 'boolean' | 'select' | 'header' | 'dbpicker';\r\n title: string;\r\n description?: string;\r\n required?: boolean;\r\n default?: any;\r\n options?: string[]; // For select fields\r\n pattern?: string; // For validation\r\n readonly?: boolean;\r\n min?: number;\r\n max?: number;\r\n}\r\nexport interface FormFieldExtended extends FormField {\r\n realType?: string;\r\n pickerOptions?: any[];\r\n\r\n ID?: string;\r\n TFie_PK_ID?: string;\r\n TVal_PK_ID?: string;\r\n TFIn_PK_ID?: string;\r\n Enabled?: boolean;\r\n isForm?: string;\r\n LabelText?: string;\r\n LabelTextFr?: string;\r\n SystemName?: string;\r\n HelpText?: string;\r\n CssStyle?: string;\r\n ControlType?: string;\r\n ValidationRequired?: string;\r\n ValidationMin?: string;\r\n ValidationMax?: string;\r\n Mask?: string;\r\n TypeId?: string;\r\n Unit?: string;\r\n TFie_Fullpath?: string;\r\n TVal_FK_Parent_ID?: string;\r\n value?: any;\r\n}\r\n\r\nexport interface FormSchema {\r\n schema: {\r\n [fieldName: string]: FormField;\r\n };\r\n title?: string;\r\n description?: string;\r\n}\r\n\r\nexport interface FormSchemaFieldsOnly {\r\n fields: {\r\n [fieldName: string]: FormField;\r\n };\r\n}\r\n\r\nexport interface FormSchemaExtended {\r\n schema: {\r\n [fieldName: string]: FormFieldExtended;\r\n };\r\n title?: string;\r\n description?: string;\r\n}\r\n\r\n\r\nexport interface FormSchemaFieldsOnlyExtended {\r\n fields: {\r\n [fieldName: string]: FormFieldExtended;\r\n };\r\n}\r\n\r\nexport interface FilledFormData {\r\n [fieldName: string]: any;\r\n}\r\n\r\nexport interface VoiceFormRecorderResult {\r\n success: boolean;\r\n data?: FilledFormData;\r\n error?: string;\r\n transcription?: string;\r\n jsonForm?: string;\r\n}\r\n"]}
1
+ {"version":3,"file":"form-schema.types.js","sourceRoot":"","sources":["../../src/types/form-schema.types.ts"],"names":[],"mappings":"","sourcesContent":["export interface FormField {\r\n id?: string;\r\n type: 'string' | 'number' | 'date' | 'boolean' | 'select' | 'header' | 'dbpicker';\r\n title: string;\r\n description?: string;\r\n required?: boolean;\r\n default?: any;\r\n options?: string[]; // For select fields\r\n pattern?: string; // For validation\r\n readonly?: boolean;\r\n min?: number;\r\n max?: number;\r\n}\r\nexport interface FormFieldExtended extends FormField {\r\n realType?: string;\r\n pickerOptions?: any[];\r\n\r\n ID?: string;\r\n TFie_PK_ID?: string;\r\n TVal_PK_ID?: string;\r\n TFIn_PK_ID?: string;\r\n Enabled?: boolean;\r\n isForm?: string;\r\n LabelText?: string;\r\n LabelTextFr?: string;\r\n SystemName?: string;\r\n HelpText?: string;\r\n CssStyle?: string;\r\n ControlType?: string;\r\n ValidationRequired?: string;\r\n ValidationMin?: string;\r\n ValidationMax?: string;\r\n Mask?: string;\r\n TypeId?: string;\r\n Unit?: string;\r\n TFie_Fullpath?: string;\r\n TVal_FK_Parent_ID?: string;\r\n value?: any;\r\n}\r\n\r\nexport interface FormSchema {\r\n schema: {\r\n [fieldName: string]: FormField;\r\n };\r\n title?: string;\r\n description?: string;\r\n}\r\n\r\nexport interface FormSchemaFieldsOnly {\r\n fields: {\r\n [fieldName: string]: FormField;\r\n };\r\n}\r\n\r\nexport interface FormSchemaExtended {\r\n schema: {\r\n [fieldName: string]: FormFieldExtended;\r\n };\r\n title?: string;\r\n description?: string;\r\n}\r\n\r\n\r\nexport interface FormSchemaFieldsOnlyExtended {\r\n fields: {\r\n [fieldName: string]: FormFieldExtended;\r\n };\r\n}\r\n\r\nexport interface FilledFormData {\r\n [fieldName: string]: any;\r\n}\r\n\r\nexport interface VoiceFormRecorderResult {\r\n success: boolean;\r\n data?: FilledFormData;\r\n confidence?: Record<string, number>;\r\n error?: string;\r\n transcription?: string;\r\n jsonForm?: string;\r\n}\r\n"]}
@@ -562,8 +562,9 @@ class OpenAILLMService {
562
562
  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
563
563
  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
564
564
  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
565
+ 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.
565
566
 
566
- Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
567
+ Respond with JSON in this exact format: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
567
568
  let userPrompt = `
568
569
  Voice transcription: "${data}"
569
570
 
@@ -636,8 +637,9 @@ class OpenAILLMService {
636
637
  13. Use readonly fields as contextual hints to understand form structure and field grouping, but never fill them
637
638
  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
638
639
  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
640
+ 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.
639
641
 
640
- Respond with JSON in this exact format: {"schema": {...}}`;
642
+ Respond with JSON in this exact format: {"schema": {...}, "confidence": {"field_name": 0.87}}`;
641
643
  let userPrompt = `
642
644
  Voice transcription: "${data}"
643
645
 
@@ -730,7 +732,7 @@ class AnthropicLLMService {
730
732
  Form fields:
731
733
  ${JSON.stringify(finalSchema, null, 2)}
732
734
 
733
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
735
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
734
736
  const body = this.useProxy
735
737
  ? { model: this.model, messages: [{ role: 'user', content: userPrompt }], system: systemPrompt }
736
738
  : { model: this.model, max_tokens: 4096, system: systemPrompt, messages: [{ role: 'user', content: userPrompt }] };
@@ -756,6 +758,7 @@ Rules:
756
758
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
757
759
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
758
760
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
761
+ 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.
759
762
  Respond ONLY with valid JSON.`;
760
763
  }
761
764
  }
@@ -789,7 +792,7 @@ class MistralLLMService {
789
792
  Form fields:
790
793
  ${JSON.stringify(finalSchema, null, 2)}
791
794
 
792
- Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value"}]}`;
795
+ Respond with JSON: {"fields": [{"id": "field_id", "name": "field_name", "value": "extracted_value", "confidence": 0.87}]}`;
793
796
  const response = await fetch(endpoint, {
794
797
  method: 'POST',
795
798
  headers,
@@ -819,6 +822,7 @@ Rules:
819
822
  8. DATE/DATETIME OUT OF RANGE: if a date falls outside min/max constraints, leave the field EMPTY
820
823
  9. PATTERN VALIDATION: if a field has a pattern, the value MUST match it exactly, otherwise leave empty
821
824
  10. UNKNOWN VALUES: if the user says "Unknown" and it exists as an option, select it; otherwise leave empty
825
+ 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.
822
826
  Respond ONLY with valid JSON.`;
823
827
  }
824
828
  }
@@ -4326,7 +4330,7 @@ const defineCustomElements = async (win, options) => {
4326
4330
 
4327
4331
  (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);}})();
4328
4332
 
4329
- 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}";
4333
+ 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}";
4330
4334
 
4331
4335
  // Initialize OCR
4332
4336
  defineCustomElements();
@@ -4368,6 +4372,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4368
4372
  this.hasTransientError = false;
4369
4373
  this.transcription = '';
4370
4374
  this.filledData = null;
4375
+ this.confidenceScores = null;
4371
4376
  this.debugInfo = {};
4372
4377
  this.isReadonlyMode = true; // Start in readonly preview mode
4373
4378
  this.isInitializing = true;
@@ -4615,6 +4620,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4615
4620
  return;
4616
4621
  this.isProcessing = true;
4617
4622
  this.hasTransientError = false;
4623
+ this.confidenceScores = null;
4618
4624
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.processing) || (this.language == 'en' ? 'Processing document...' : 'Traitement du document ...');
4619
4625
  try {
4620
4626
  const extractedData = (ocrData === null || ocrData === void 0 ? void 0 : ocrData.content) || ocrData;
@@ -4632,10 +4638,11 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4632
4638
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4633
4639
  }
4634
4640
  this.filledData = this.extractFilledData(filledSchema);
4635
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4641
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4642
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4636
4643
  this.parsedSchema = this.filledData;
4637
4644
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4638
- this.formFilled.emit({ success: true, data: this.filledData, jsonForm });
4645
+ this.formFilled.emit({ success: true, data: this.filledData, jsonForm, confidence: this.confidenceScores });
4639
4646
  }
4640
4647
  catch (error) {
4641
4648
  console.error('OCR processing error:', error);
@@ -4654,6 +4661,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4654
4661
  return;
4655
4662
  this.isProcessing = true;
4656
4663
  this.hasTransientError = false;
4664
+ this.confidenceScores = null;
4657
4665
  this.updateDebugInfo('Audio Captured', { size: audioFile.size, type: audioFile.type });
4658
4666
  try {
4659
4667
  // Validate audio file before sending to API
@@ -4674,7 +4682,6 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4674
4682
  this.formFilled.emit({ success: false, error: 'Audio file too large' });
4675
4683
  return;
4676
4684
  }
4677
- // Step 1: Transcription
4678
4685
  let transcription;
4679
4686
  try {
4680
4687
  this.statusMessage = ((_a = this.parsedTheme.texts) === null || _a === void 0 ? void 0 : _a.transcribing) || (this.language == 'en' ? 'Transcribing speech...' : 'Transcription du texte ...');
@@ -4693,7 +4700,6 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4693
4700
  this.formFilled.emit({ success: false, error: 'No speech detected', transcription: '' });
4694
4701
  return;
4695
4702
  }
4696
- // Step 2: LLM form filling
4697
4703
  let filledSchema;
4698
4704
  try {
4699
4705
  this.statusMessage = ((_b = this.parsedTheme.texts) === null || _b === void 0 ? void 0 : _b.filling) || (this.language == 'en' ? 'Filling form fields...' : 'Remplissage du formulaire ...');
@@ -4704,10 +4710,11 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4704
4710
  throw Object.assign(new Error(llmError.message), { phase: 'llm' });
4705
4711
  }
4706
4712
  this.filledData = this.extractFilledData(filledSchema);
4707
- this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData });
4713
+ this.confidenceScores = this.extractConfidenceScores(filledSchema);
4714
+ this.updateDebugInfo('Form Filled', { filledSchema, extractedData: this.filledData, confidence: this.confidenceScores });
4708
4715
  this.parsedSchema = this.filledData;
4709
4716
  this.statusMessage = ((_c = this.parsedTheme.texts) === null || _c === void 0 ? void 0 : _c.completed) || (this.language == 'en' ? 'Form completed!' : 'Formulaire rempli !');
4710
- this.formFilled.emit({ success: true, data: this.filledData, transcription });
4717
+ this.formFilled.emit({ success: true, data: this.filledData, transcription, confidence: this.confidenceScores });
4711
4718
  }
4712
4719
  catch (error) {
4713
4720
  console.error('Audio processing error:', error);
@@ -4731,7 +4738,8 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4731
4738
  try {
4732
4739
  const audioBlob = await this.audioRecorder.stopRecording();
4733
4740
  const audioContent = new File([audioBlob], 'audio.wav', { type: 'audio/wav' });
4734
- // processAudioContent manages isProcessing itself; await ensures we don't return early
4741
+ // Reset isProcessing so the guard inside processAudioContent doesn't block this internal call
4742
+ this.isProcessing = false;
4735
4743
  await this.processAudioContent(audioContent);
4736
4744
  }
4737
4745
  catch (error) {
@@ -4748,12 +4756,52 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4748
4756
  this.recordingStateChanged.emit({ isRecording: false, state: 'idle' });
4749
4757
  }
4750
4758
  }
4759
+ extractConfidenceScores(filledData) {
4760
+ const scores = {};
4761
+ if (!filledData)
4762
+ return scores;
4763
+ // Fields array format: [{"id": "...", "name": "...", "value": "...", "confidence": 0.87}]
4764
+ if (filledData.fields && Array.isArray(filledData.fields)) {
4765
+ filledData.fields.forEach((field) => {
4766
+ const raw = typeof field.confidence === 'number' ? field.confidence : parseFloat(field.confidence);
4767
+ if (!isNaN(raw)) {
4768
+ const clamped = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4769
+ // Store under both id and name so label-based lookups always work
4770
+ if (field.id)
4771
+ scores[field.id] = clamped;
4772
+ if (field.name)
4773
+ scores[field.name] = clamped;
4774
+ }
4775
+ });
4776
+ }
4777
+ // Simple schema format: {"schema": {...}, "confidence": {"field_name": 0.87}}
4778
+ if (filledData.confidence && typeof filledData.confidence === 'object') {
4779
+ Object.entries(filledData.confidence).forEach(([k, v]) => {
4780
+ const raw = typeof v === 'number' ? v : parseFloat(v);
4781
+ if (!isNaN(raw)) {
4782
+ scores[k] = Math.min(0.99, Math.max(0.01, Math.round(raw * 100) / 100));
4783
+ }
4784
+ });
4785
+ }
4786
+ return scores;
4787
+ }
4788
+ getFieldConfidence(primary, fallback) {
4789
+ var _a, _b;
4790
+ if (!this.confidenceScores)
4791
+ return null;
4792
+ return (_a = this.confidenceScores[primary]) !== null && _a !== void 0 ? _a : (fallback ? ((_b = this.confidenceScores[fallback]) !== null && _b !== void 0 ? _b : null) : null);
4793
+ }
4794
+ renderConfidenceIndicator(confidence) {
4795
+ if (confidence === null || confidence >= 0.95)
4796
+ return null;
4797
+ const pct = Math.round(confidence * 100);
4798
+ const isApproximate = confidence >= 0.85;
4799
+ return (h$1("span", { class: `confidence-badge ${isApproximate ? 'confidence-medium' : 'confidence-low'}`, title: this.language === 'en' ? `Confidence: ${pct}%` : `Confiance : ${pct}%` }, pct, "%"));
4800
+ }
4751
4801
  extractFilledData(filledData) {
4752
- // console.log("extractFilledData", filledData);
4753
4802
  const updatedSchema = JSON.parse(JSON.stringify(this.parsedSchema));
4754
4803
  switch (this.context) {
4755
4804
  case "ecoteka":
4756
- // console.log("TODO extractFilledData", filledData);
4757
4805
  case "ng":
4758
4806
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4759
4807
  // Map AI response back to original schema structure
@@ -4768,7 +4816,6 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4768
4816
  }
4769
4817
  break;
4770
4818
  case "ecoll-veto":
4771
- // console.log("TODO extractFilledData", filledData, updatedSchema);
4772
4819
  if (filledData === null || filledData === void 0 ? void 0 : filledData.fields) {
4773
4820
  // Map AI response back to original schema structure
4774
4821
  filledData.fields.forEach((field) => {
@@ -4809,15 +4856,12 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4809
4856
  }
4810
4857
  break;
4811
4858
  }
4812
- // console.log("extractFilledData result", updatedSchema);
4813
4859
  return updatedSchema;
4814
4860
  }
4815
4861
  async trimSchemaForAI(schema) {
4816
4862
  var _a, _b;
4817
- // console.log("trimSchemaForAI", schema);
4818
4863
  switch (this.context) {
4819
4864
  case "ecoteka":
4820
- // console.log("TODO trimSchemaForAI", schema)
4821
4865
  case "ng":
4822
4866
  const trimmed = { fields: [] };
4823
4867
  schema.Children.forEach((child) => {
@@ -4836,10 +4880,8 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4836
4880
  }
4837
4881
  trimmed.fields.push(fieldData);
4838
4882
  });
4839
- // console.log("Schema apres transformation, contexte NG:", trimmed);
4840
4883
  return trimmed;
4841
4884
  case "ecoll-veto":
4842
- // console.log("TODO trimSchemaForAI", schema)
4843
4885
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
4844
4886
  if (mergedItemsSchema) {
4845
4887
  const trimmedSchema = {
@@ -4884,7 +4926,6 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
4884
4926
  default: '',
4885
4927
  };
4886
4928
  });
4887
- // console.log("Schema apres transformation, contexte Track:", trimmedSchema);
4888
4929
  return trimmedSchema;
4889
4930
  }
4890
4931
  case "track":
@@ -5081,13 +5122,11 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5081
5122
  return (h$1("div", { class: "form-preview" }, h$1("div", { class: "form-preview-title" }, title), h$1("form", { class: "voice-filled-form" }, this.renderFormFields())));
5082
5123
  }
5083
5124
  renderFormFields() {
5084
- // console.log("renderFormFields", this.parsedSchema);
5085
5125
  if (!this.parsedSchema)
5086
5126
  return null;
5087
5127
  const largeFieldTypes = ['select', 'multiselect', 'classification', 'thesaurus', 'position'];
5088
5128
  switch (this.context) {
5089
5129
  case "ecoteka":
5090
- // console.log("TODO renderFormFields", this.parsedSchema);
5091
5130
  case "ng":
5092
5131
  return this.parsedSchema.Children.map((child) => {
5093
5132
  var _a, _b, _c;
@@ -5099,7 +5138,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5099
5138
  const isRequired = child.Required || false;
5100
5139
  const fieldValue = (_b = child.Settings) === null || _b === void 0 ? void 0 : _b.Default_Value;
5101
5140
  const isLargeField = largeFieldTypes.includes(fieldType) || (child.Children && child.Children.length > 5);
5102
- 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, {
5141
+ 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, {
5103
5142
  type: fieldType,
5104
5143
  title: fieldLabel,
5105
5144
  required: isRequired,
@@ -5107,8 +5146,6 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5107
5146
  }, fieldValue)));
5108
5147
  }).filter(Boolean);
5109
5148
  case "ecoll-veto":
5110
- // NOTE STEP 2
5111
- // console.log("TODO renderFormFields", this.parsedSchema);
5112
5149
  const mergedItemsSchema = (this.parsedSchema[0].items).concat(this.parsedSchema[1].items);
5113
5150
  return Object.entries(mergedItemsSchema).map(([key, field]) => {
5114
5151
  var _a, _b;
@@ -5139,7 +5176,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5139
5176
  // console.error("Error fetching classification data:", error);
5140
5177
  // }
5141
5178
  // }
5142
- 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))));
5179
+ 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))));
5143
5180
  });
5144
5181
  case "track":
5145
5182
  default:
@@ -5148,7 +5185,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5148
5185
  if (field.type === 'header') {
5149
5186
  return (h$1("div", { class: "form-header", key: fieldName }, field.title || fieldName));
5150
5187
  }
5151
- 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))));
5188
+ 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))));
5152
5189
  });
5153
5190
  }
5154
5191
  }
@@ -5285,6 +5322,7 @@ const VoiceFormRecorder = /*@__PURE__*/ proxyCustomElement(class VoiceFormRecord
5285
5322
  "hasTransientError": [32],
5286
5323
  "transcription": [32],
5287
5324
  "filledData": [32],
5325
+ "confidenceScores": [32],
5288
5326
  "debugInfo": [32],
5289
5327
  "isReadonlyMode": [32],
5290
5328
  "isInitializing": [32],